]> git.ipfire.org Git - people/ms/u-boot.git/blame - fs/fat/fat.c
Expose parse_line() globally.
[people/ms/u-boot.git] / fs / fat / fat.c
CommitLineData
71f95118
WD
1/*
2 * fat.c
3 *
4 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
5 *
6 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
7 * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <config.h>
30#include <fat.h>
31#include <asm/byteorder.h>
7205e407 32#include <part.h>
71f95118 33
dd60d122 34#if defined(CONFIG_CMD_FAT)
71f95118
WD
35
36/*
37 * Convert a string to lowercase.
38 */
39static void
40downcase(char *str)
41{
42 while (*str != '\0') {
43 TOLOWER(*str);
44 str++;
45 }
46}
47
7205e407
WD
48static block_dev_desc_t *cur_dev = NULL;
49static unsigned long part_offset = 0;
50static int cur_part = 1;
51
52#define DOS_PART_TBL_OFFSET 0x1be
53#define DOS_PART_MAGIC_OFFSET 0x1fe
54#define DOS_FS_TYPE_OFFSET 0x36
71f95118
WD
55
56int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr)
57{
7205e407
WD
58 startblock += part_offset;
59 if (cur_dev == NULL)
60 return -1;
61 if (cur_dev->block_read) {
3e3b9569
PP
62 return cur_dev->block_read (cur_dev->dev
63 , startblock, getsize, (unsigned long *)bufptr);
71f95118
WD
64 }
65 return -1;
66}
67
68
69int
7205e407 70fat_register_device(block_dev_desc_t *dev_desc, int part_no)
71f95118 71{
7205e407 72 unsigned char buffer[SECTOR_SIZE];
566a494f 73 disk_partition_t info;
7205e407
WD
74
75 if (!dev_desc->block_read)
76 return -1;
566a494f 77 cur_dev = dev_desc;
7205e407
WD
78 /* check if we have a MBR (on floppies we have only a PBR) */
79 if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) {
80 printf ("** Can't read from device %d **\n", dev_desc->dev);
81 return -1;
82 }
83 if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 ||
84 buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) {
85 /* no signature found */
86 return -1;
87 }
77ddac94 88 if(!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) {
7205e407
WD
89 /* ok, we assume we are on a PBR only */
90 cur_part = 1;
91 part_offset=0;
bf1060ea 92 } else {
dd60d122
JL
93#if (defined(CONFIG_CMD_IDE) || \
94 defined(CONFIG_CMD_SCSI) || \
95 defined(CONFIG_CMD_USB) || \
b0d8f5bf
PP
96 (defined(CONFIG_MMC) && defined(CONFIG_LPC2292)) || \
97 defined(CONFIG_SYSTEMACE) )
bf1060ea
WD
98 /* First we assume, there is a MBR */
99 if (!get_partition_info (dev_desc, part_no, &info)) {
100 part_offset = info.start;
101 cur_part = part_no;
102 } else if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3)) {
103 /* ok, we assume we are on a PBR only */
104 cur_part = 1;
105 part_offset = 0;
106 } else {
107 printf ("** Partition %d not valid on device %d **\n",
108 part_no, dev_desc->dev);
109 return -1;
110 }
7205e407 111#else
bf1060ea
WD
112 if(!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) {
113 /* ok, we assume we are on a PBR only */
114 cur_part = 1;
115 part_offset = 0;
116 info.start = part_offset;
117 } else {
118 /* FIXME we need to determine the start block of the
119 * partition where the DOS FS resides. This can be done
120 * by using the get_partition_info routine. For this
121 * purpose the libpart must be included.
122 */
123 part_offset = 32;
124 cur_part = 1;
125 }
566a494f 126#endif
bf1060ea 127 }
71f95118
WD
128 return 0;
129}
130
131
132/*
133 * Get the first occurence of a directory delimiter ('/' or '\') in a string.
134 * Return index into string if found, -1 otherwise.
135 */
136static int
137dirdelim(char *str)
138{
139 char *start = str;
140
141 while (*str != '\0') {
142 if (ISDIRDELIM(*str)) return str - start;
143 str++;
144 }
145 return -1;
146}
147
148
149/*
150 * Match volume_info fs_type strings.
151 * Return 0 on match, -1 otherwise.
152 */
153static int
154compare_sign(char *str1, char *str2)
155{
156 char *end = str1+SIGNLEN;
157
158 while (str1 != end) {
159 if (*str1 != *str2) {
160 return -1;
161 }
162 str1++;
163 str2++;
164 }
165
166 return 0;
167}
168
169
170/*
171 * Extract zero terminated short name from a directory entry.
172 */
173static void get_name (dir_entry *dirent, char *s_name)
174{
175 char *ptr;
176
177 memcpy (s_name, dirent->name, 8);
178 s_name[8] = '\0';
179 ptr = s_name;
180 while (*ptr && *ptr != ' ')
181 ptr++;
182 if (dirent->ext[0] && dirent->ext[0] != ' ') {
183 *ptr = '.';
184 ptr++;
185 memcpy (ptr, dirent->ext, 3);
186 ptr[3] = '\0';
187 while (*ptr && *ptr != ' ')
188 ptr++;
189 }
190 *ptr = '\0';
191 if (*s_name == DELETED_FLAG)
192 *s_name = '\0';
193 else if (*s_name == aRING)
194