]>
Commit | Line | Data |
---|---|---|
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 - [email protected] - ported to ppcboot v1.1.6 | |
7 | * 2003-03-10 - [email protected] - 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 | |
71f95118 WD |
34 | /* |
35 | * Convert a string to lowercase. | |
36 | */ | |
37 | static void | |
38 | downcase(char *str) | |
39 | { | |
40 | while (*str != '\0') { | |
41 | TOLOWER(*str); | |
42 | str++; | |
43 | } | |
44 | } | |
45 | ||
7205e407 WD |
46 | static block_dev_desc_t *cur_dev = NULL; |
47 | static unsigned long part_offset = 0; | |
48 | static int cur_part = 1; | |
49 | ||
50 | #define DOS_PART_TBL_OFFSET 0x1be | |
51 | #define DOS_PART_MAGIC_OFFSET 0x1fe | |
52 | #define DOS_FS_TYPE_OFFSET 0x36 | |
71f95118 WD |
53 | |
54 | int disk_read (__u32 startblock, __u32 getsize, __u8 * bufptr) | |
55 | { | |
7205e407 WD |
56 | startblock += part_offset; |
57 | if (cur_dev == NULL) | |
58 | return -1; | |
59 | if (cur_dev->block_read) { | |
3e3b9569 PP |
60 | return cur_dev->block_read (cur_dev->dev |
61 | , startblock, getsize, (unsigned long *)bufptr); | |
71f95118 WD |
62 | } |
63 | return -1; | |
64 | } | |
65 | ||
66 | ||
67 | int | |
7205e407 | 68 | fat_register_device(block_dev_desc_t *dev_desc, int part_no) |
71f95118 | 69 | { |
7205e407 | 70 | unsigned char buffer[SECTOR_SIZE]; |
566a494f | 71 | disk_partition_t info; |
7205e407 WD |
72 | |
73 | if (!dev_desc->block_read) | |
74 | return -1; | |
566a494f | 75 | cur_dev = dev_desc; |
7205e407 WD |
76 | /* check if we have a MBR (on floppies we have only a PBR) */ |
77 | if (dev_desc->block_read (dev_desc->dev, 0, 1, (ulong *) buffer) != 1) { | |
78 | printf ("** Can't read from device %d **\n", dev_desc->dev); | |
79 | return -1; | |
80 | } | |
81 | if (buffer[DOS_PART_MAGIC_OFFSET] != 0x55 || | |
82 | buffer[DOS_PART_MAGIC_OFFSET + 1] != 0xaa) { | |
83 | /* no signature found */ | |
84 | return -1; | |
85 | } | |
dd60d122 JL |
86 | #if (defined(CONFIG_CMD_IDE) || \ |
87 | defined(CONFIG_CMD_SCSI) || \ | |
88 | defined(CONFIG_CMD_USB) || \ | |
02df4a27 AF |
89 | defined(CONFIG_MMC) || \ |
90 | defined(CONFIG_SYSTEMACE) ) | |
91 | /* First we assume, there is a MBR */ | |
92 | if (!get_partition_info (dev_desc, part_no, &info)) { | |
93 | part_offset = info.start; | |
94 | cur_part = part_no; | |
95 | } else if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET], "FAT", 3)) { | |
96 | /* ok, we assume we are on a PBR only */ | |
97 | cur_part = 1; | |
98 | part_offset = 0; | |
99 | } else { | |
100 | printf ("** Partition %d not valid on device %d **\n", | |
bf1060ea | 101 | part_no, dev_desc->dev); |
02df4a27 AF |
102 | return -1; |
103 | } | |
104 | ||
7205e407 | 105 | #else |
02df4a27 AF |
106 | if (!strncmp((char *)&buffer[DOS_FS_TYPE_OFFSET],"FAT",3)) { |
107 | /* ok, we assume we are on a PBR only */ | |
108 | cur_part = 1; | |
109 | part_offset = 0; | |
110 | info.start = part_offset; | |
111 | } else { | |
112 | /* FIXME we need to determine the start block of the | |
113 | * partition where the DOS FS resides. This can be done | |
114 | * by using the get_partition_info routine. For this | |
115 | * purpose the libpart must be included. | |
116 | */ | |
117 | part_offset = 32; | |
118 | cur_part = 1; | |
bf1060ea | 119 | } |
02df4a27 | 120 | #endif |
71f95118 WD |
121 | return 0; |
122 | } | |
123 | ||
124 | ||
125 | /* | |
126 | * Get the first occurence of a directory delimiter ('/' or '\') in a string. | |
127 | * Return index into string if found, -1 otherwise. | |
128 | */ | |
129 | static int | |
130 | dirdelim(char *str) | |
131 | { | |
132 | char *start = str; | |
133 | ||
134 | while (*str != '\0') { | |
135 | if (ISDIRDELIM(*str)) return str - start; | |
136 | str++; | |
137 | } | |
138 | return -1; | |
139 | } | |
140 | ||
141 | ||
142 | /* | |
143 | * Match volume_info fs_type strings. | |
144 | * Return 0 on match, -1 otherwise. | |
145 | */ | |
146 | static int | |
147 | compare_sign(char *str1, char *str2) | |
148 | { | |
149 | char *end = str1+SIGNLEN; | |
150 | ||
151 | while (str1 != end) { | |
152 | if (*str1 != *str2) { | |
153 | return -1; | |
154 | } | |
155 | str1++; | |
156 | str2++; | |
157 | } | |
158 | ||
159 | return 0; | |
160 | } | |
161 | ||
162 | ||
163 | /* | |
164 | * Extract zero terminated short name from a directory entry. | |
165 | */ | |
166 | static void get_name (dir_entry *dirent, char *s_name) | |
167 | { | |
168 | char *ptr; | |
169 | ||
170 | memcpy (s_name, dirent->name, 8); | |
171 | s_name[8] = '\0'; | |
172 | ptr = s_name; | |
173 | while (*ptr && *ptr != ' ') | |
174 | ptr++; | |
175 | if (dirent->ext[0] && dirent->ext[0] != ' ') { | |
176 | *ptr = '.'; | |
177 | ptr++; | |
178 | memcpy (ptr, dirent->ext, 3); | |
179 | ptr[3] = '\0'; | |
180 | while (*ptr && *ptr != ' ') | |
181 | ptr++; | |
182 | } | |
183 | *ptr = '\0'; | |
184 | if (*s_name == DELETED_FLAG) | |
185 | *s_name = '\0'; | |
186 | else if (*s_name == aRING) | |
187 |