Commit 1ad0b98a067a133c0e8a182649a76a4afd739594

Authored by Suriyan Ramasami
Committed by Tom Rini
1 parent 64553717bb

fat: Prepare API change for files greater than 2GB

Change the internal FAT functions to use loff_t for offsets.

Signed-off-by: Suriyan Ramasami <suriyan.r@gmail.com>
Acked-by: Simon Glass <sjg@chromium.org>
[trini: Fix fs/fat/fat.c for min3 updates]
Signed-off-by: Tom Rini <trini@ti.com>

Showing 7 changed files with 128 additions and 100 deletions Inline Diff

board/esd/common/auto_update.c
1 /* 1 /*
2 * (C) Copyright 2003-2004 2 * (C) Copyright 2003-2004
3 * Gary Jennejohn, DENX Software Engineering, garyj@denx.de. 3 * Gary Jennejohn, DENX Software Engineering, garyj@denx.de.
4 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com 4 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
5 * 5 *
6 * SPDX-License-Identifier: GPL-2.0+ 6 * SPDX-License-Identifier: GPL-2.0+
7 */ 7 */
8 8
9 #include <common.h> 9 #include <common.h>
10 10
11 #include <command.h> 11 #include <command.h>
12 #include <image.h> 12 #include <image.h>
13 #include <asm/byteorder.h> 13 #include <asm/byteorder.h>
14 #include <fat.h> 14 #include <fat.h>
15 #include <flash.h> 15 #include <flash.h>
16 #include <part.h> 16 #include <part.h>
17 17
18 #include "auto_update.h" 18 #include "auto_update.h"
19 19
20 #ifdef CONFIG_AUTO_UPDATE 20 #ifdef CONFIG_AUTO_UPDATE
21 21
22 #if !defined(CONFIG_CMD_FAT) 22 #if !defined(CONFIG_CMD_FAT)
23 #error "must define CONFIG_CMD_FAT" 23 #error "must define CONFIG_CMD_FAT"
24 #endif 24 #endif
25 25
26 extern au_image_t au_image[]; 26 extern au_image_t au_image[];
27 extern int N_AU_IMAGES; 27 extern int N_AU_IMAGES;
28 28
29 /* where to load files into memory */ 29 /* where to load files into memory */
30 #define LOAD_ADDR ((unsigned char *)0x100000) 30 #define LOAD_ADDR ((unsigned char *)0x100000)
31 #define MAX_LOADSZ 0x1c00000 31 #define MAX_LOADSZ 0x1c00000
32 32
33 /* externals */ 33 /* externals */
34 extern int fat_register_device(block_dev_desc_t *, int);
35 extern int file_fat_detectfs(void);
36 extern long file_fat_read(const char *, void *, unsigned long);
37 long do_fat_read (const char *filename, void *buffer, 34 long do_fat_read (const char *filename, void *buffer,
38 unsigned long maxsize, int dols); 35 unsigned long maxsize, int dols);
39 36
40 extern block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; 37 extern block_dev_desc_t ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE];
41 38
42 int au_check_cksum_valid(int i, long nbytes) 39 int au_check_cksum_valid(int i, long nbytes)
43 { 40 {
44 image_header_t *hdr; 41 image_header_t *hdr;
45 42
46 hdr = (image_header_t *)LOAD_ADDR; 43 hdr = (image_header_t *)LOAD_ADDR;
47 #if defined(CONFIG_FIT) 44 #if defined(CONFIG_FIT)
48 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { 45 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
49 puts ("Non legacy image format not supported\n"); 46 puts ("Non legacy image format not supported\n");
50 return -1; 47 return -1;
51 } 48 }
52 #endif 49 #endif
53 50
54 if ((au_image[i].type == AU_FIRMWARE) && 51 if ((au_image[i].type == AU_FIRMWARE) &&
55 (au_image[i].size != image_get_data_size (hdr))) { 52 (au_image[i].size != image_get_data_size (hdr))) {
56 printf ("Image %s has wrong size\n", au_image[i].name); 53 printf ("Image %s has wrong size\n", au_image[i].name);
57 return -1; 54 return -1;
58 } 55 }
59 56
60 if (nbytes != (image_get_image_size (hdr))) { 57 if (nbytes != (image_get_image_size (hdr))) {
61 printf ("Image %s bad total SIZE\n", au_image[i].name); 58 printf ("Image %s bad total SIZE\n", au_image[i].name);
62 return -1; 59 return -1;
63 } 60 }
64 61
65 /* check the data CRC */ 62 /* check the data CRC */
66 if (!image_check_dcrc (hdr)) { 63 if (!image_check_dcrc (hdr)) {
67 printf ("Image %s bad data checksum\n", au_image[i].name); 64 printf ("Image %s bad data checksum\n", au_image[i].name);
68 return -1; 65 return -1;
69 } 66 }
70 return 0; 67 return 0;
71 } 68 }
72 69
73 int au_check_header_valid(int i, long nbytes) 70 int au_check_header_valid(int i, long nbytes)
74 { 71 {
75 image_header_t *hdr; 72 image_header_t *hdr;
76 73
77 hdr = (image_header_t *)LOAD_ADDR; 74 hdr = (image_header_t *)LOAD_ADDR;
78 #if defined(CONFIG_FIT) 75 #if defined(CONFIG_FIT)
79 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { 76 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
80 puts ("Non legacy image format not supported\n"); 77 puts ("Non legacy image format not supported\n");
81 return -1; 78 return -1;
82 } 79 }
83 #endif 80 #endif
84 81
85 /* check the easy ones first */ 82 /* check the easy ones first */
86 if (nbytes < image_get_header_size ()) { 83 if (nbytes < image_get_header_size ()) {
87 printf ("Image %s bad header SIZE\n", au_image[i].name); 84 printf ("Image %s bad header SIZE\n", au_image[i].name);
88 return -1; 85 return -1;
89 } 86 }
90 if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) { 87 if (!image_check_magic (hdr) || !image_check_arch (hdr, IH_ARCH_PPC)) {
91 printf ("Image %s bad MAGIC or ARCH\n", au_image[i].name); 88 printf ("Image %s bad MAGIC or ARCH\n", au_image[i].name);
92 return -1; 89 return -1;
93 } 90 }
94 if (!image_check_hcrc (hdr)) { 91 if (!image_check_hcrc (hdr)) {
95 printf ("Image %s bad header checksum\n", au_image[i].name); 92 printf ("Image %s bad header checksum\n", au_image[i].name);
96 return -1; 93 return -1;
97 } 94 }
98 95
99 /* check the type - could do this all in one gigantic if() */ 96 /* check the type - could do this all in one gigantic if() */
100 if (((au_image[i].type & AU_TYPEMASK) == AU_FIRMWARE) && 97 if (((au_image[i].type & AU_TYPEMASK) == AU_FIRMWARE) &&
101 !image_check_type (hdr, IH_TYPE_FIRMWARE)) { 98 !image_check_type (hdr, IH_TYPE_FIRMWARE)) {
102 printf ("Image %s wrong type\n", au_image[i].name); 99 printf ("Image %s wrong type\n", au_image[i].name);
103 return -1; 100 return -1;
104 } 101 }
105 if (((au_image[i].type & AU_TYPEMASK) == AU_SCRIPT) && 102 if (((au_image[i].type & AU_TYPEMASK) == AU_SCRIPT) &&
106 !image_check_type (hdr, IH_TYPE_SCRIPT)) { 103 !image_check_type (hdr, IH_TYPE_SCRIPT)) {
107 printf ("Image %s wrong type\n", au_image[i].name); 104 printf ("Image %s wrong type\n", au_image[i].name);
108 return -1; 105 return -1;
109 } 106 }
110 107
111 return 0; 108 return 0;
112 } 109 }
113 110
114 int au_do_update(int i, long sz) 111 int au_do_update(int i, long sz)
115 { 112 {
116 image_header_t *hdr; 113 image_header_t *hdr;
117 char *addr; 114 char *addr;
118 long start, end; 115 long start, end;
119 int off, rc; 116 int off, rc;
120 uint nbytes; 117 uint nbytes;
121 int k; 118 int k;
122 119
123 hdr = (image_header_t *)LOAD_ADDR; 120 hdr = (image_header_t *)LOAD_ADDR;
124 #if defined(CONFIG_FIT) 121 #if defined(CONFIG_FIT)
125 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) { 122 if (genimg_get_format ((void *)hdr) != IMAGE_FORMAT_LEGACY) {
126 puts ("Non legacy image format not supported\n"); 123 puts ("Non legacy image format not supported\n");
127 return -1; 124 return -1;
128 } 125 }
129 #endif 126 #endif
130 127
131 switch (au_image[i].type & AU_TYPEMASK) { 128 switch (au_image[i].type & AU_TYPEMASK) {
132 case AU_SCRIPT: 129 case AU_SCRIPT:
133 printf("Executing script %s\n", au_image[i].name); 130 printf("Executing script %s\n", au_image[i].name);
134 131
135 /* execute a script */ 132 /* execute a script */
136 if (image_check_type (hdr, IH_TYPE_SCRIPT)) { 133 if (image_check_type (hdr, IH_TYPE_SCRIPT)) {
137 addr = (char *)((char *)hdr + image_get_header_size ()); 134 addr = (char *)((char *)hdr + image_get_header_size ());
138 /* stick a NULL at the end of the script, otherwise */ 135 /* stick a NULL at the end of the script, otherwise */
139 /* parse_string_outer() runs off the end. */ 136 /* parse_string_outer() runs off the end. */
140 addr[image_get_data_size (hdr)] = 0; 137 addr[image_get_data_size (hdr)] = 0;
141 addr += 8; 138 addr += 8;
142 139
143 /* 140 /*
144 * Replace cr/lf with ; 141 * Replace cr/lf with ;
145 */ 142 */
146 k = 0; 143 k = 0;
147 while (addr[k] != 0) { 144 while (addr[k] != 0) {
148 if ((addr[k] == 10) || (addr[k] == 13)) { 145 if ((addr[k] == 10) || (addr[k] == 13)) {
149 addr[k] = ';'; 146 addr[k] = ';';
150 } 147 }
151 k++; 148 k++;
152 } 149 }
153 150
154 run_command(addr, 0); 151 run_command(addr, 0);
155 return 0; 152 return 0;
156 } 153 }
157 154
158 break; 155 break;
159 156
160 case AU_FIRMWARE: 157 case AU_FIRMWARE:
161 case AU_NOR: 158 case AU_NOR:
162 case AU_NAND: 159 case AU_NAND:
163 start = au_image[i].start; 160 start = au_image[i].start;
164 end = au_image[i].start + au_image[i].size - 1; 161 end = au_image[i].start + au_image[i].size - 1;
165 162
166 /* 163 /*
167 * do not update firmware when image is already in flash. 164 * do not update firmware when image is already in flash.
168 */ 165 */
169 if (au_image[i].type == AU_FIRMWARE) { 166 if (au_image[i].type == AU_FIRMWARE) {
170 char *orig = (char*)start; 167 char *orig = (char*)start;
171 char *new = (char *)((char *)hdr + 168 char *new = (char *)((char *)hdr +
172 image_get_header_size ()); 169 image_get_header_size ());
173 nbytes = image_get_data_size (hdr); 170 nbytes = image_get_data_size (hdr);
174 171
175 while (--nbytes) { 172 while (--nbytes) {
176 if (*orig++ != *new++) { 173 if (*orig++ != *new++) {
177 break; 174 break;
178 } 175 }
179 } 176 }
180 if (!nbytes) { 177 if (!nbytes) {
181 printf ("Skipping firmware update - " 178 printf ("Skipping firmware update - "
182 "images are identical\n"); 179 "images are identical\n");
183 break; 180 break;
184 } 181 }
185 } 182 }
186 183
187 /* unprotect the address range */ 184 /* unprotect the address range */
188 if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) || 185 if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) ||
189 (au_image[i].type == AU_FIRMWARE)) { 186 (au_image[i].type == AU_FIRMWARE)) {
190 flash_sect_protect (0, start, end); 187 flash_sect_protect (0, start, end);
191 } 188 }
192 189
193 /* 190 /*
194 * erase the address range. 191 * erase the address range.
195 */ 192 */
196 if (au_image[i].type != AU_NAND) { 193 if (au_image[i].type != AU_NAND) {
197 printf ("Updating NOR FLASH with image %s\n", 194 printf ("Updating NOR FLASH with image %s\n",
198 au_image[i].name); 195 au_image[i].name);
199 debug ("flash_sect_erase(%lx, %lx);\n", start, end); 196 debug ("flash_sect_erase(%lx, %lx);\n", start, end);
200 flash_sect_erase (start, end); 197 flash_sect_erase (start, end);
201 } 198 }
202 199
203 udelay(10000); 200 udelay(10000);
204 201
205 /* strip the header - except for the kernel and ramdisk */ 202 /* strip the header - except for the kernel and ramdisk */
206 if (au_image[i].type != AU_FIRMWARE) { 203 if (au_image[i].type != AU_FIRMWARE) {
207 addr = (char *)hdr; 204 addr = (char *)hdr;
208 off = image_get_header_size (); 205 off = image_get_header_size ();
209 nbytes = image_get_image_size (hdr); 206 nbytes = image_get_image_size (hdr);
210 } else { 207 } else {
211 addr = (char *)((char *)hdr + image_get_header_size ()); 208 addr = (char *)((char *)hdr + image_get_header_size ());
212 off = 0; 209 off = 0;
213 nbytes = image_get_data_size (hdr); 210 nbytes = image_get_data_size (hdr);
214 } 211 }
215 212
216 /* 213 /*
217 * copy the data from RAM to FLASH 214 * copy the data from RAM to FLASH
218 */ 215 */
219 if (au_image[i].type != AU_NAND) { 216 if (au_image[i].type != AU_NAND) {
220 debug ("flash_write(%p, %lx, %x)\n", 217 debug ("flash_write(%p, %lx, %x)\n",
221 addr, start, nbytes); 218 addr, start, nbytes);
222 rc = flash_write ((char *)addr, start, 219 rc = flash_write ((char *)addr, start,
223 (nbytes + 1) & ~1); 220 (nbytes + 1) & ~1);
224 } else { 221 } else {
225 rc = -1; 222 rc = -1;
226 } 223 }
227 if (rc != 0) { 224 if (rc != 0) {
228 printf ("Flashing failed due to error %d\n", rc); 225 printf ("Flashing failed due to error %d\n", rc);
229 return -1; 226 return -1;
230 } 227 }
231 228
232 /* 229 /*
233 * check the dcrc of the copy 230 * check the dcrc of the copy
234 */ 231 */
235 if (au_image[i].type != AU_NAND) { 232 if (au_image[i].type != AU_NAND) {
236 rc = crc32 (0, (uchar *)(start + off), 233 rc = crc32 (0, (uchar *)(start + off),
237 image_get_data_size (hdr)); 234 image_get_data_size (hdr));
238 } 235 }
239 if (rc != image_get_dcrc (hdr)) { 236 if (rc != image_get_dcrc (hdr)) {
240 printf ("Image %s Bad Data Checksum After COPY\n", 237 printf ("Image %s Bad Data Checksum After COPY\n",
241 au_image[i].name); 238 au_image[i].name);
242 return -1; 239 return -1;
243 } 240 }
244 241
245 /* protect the address range */ 242 /* protect the address range */
246 /* this assumes that ONLY the firmware is protected! */ 243 /* this assumes that ONLY the firmware is protected! */
247 if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) || 244 if (((au_image[i].type & AU_FLAGMASK) == AU_PROTECT) ||
248 (au_image[i].type == AU_FIRMWARE)) { 245 (au_image[i].type == AU_FIRMWARE)) {
249 flash_sect_protect (1, start, end); 246 flash_sect_protect (1, start, end);
250 } 247 }
251 248
252 break; 249 break;
253 250
254 default: 251 default:
255 printf("Wrong image type selected!\n"); 252 printf("Wrong image type selected!\n");
256 } 253 }
257 254
258 return 0; 255 return 0;
259 } 256 }
260 257
261 static void process_macros (const char *input, char *output) 258 static void process_macros (const char *input, char *output)
262 { 259 {
263 char c, prev; 260 char c, prev;
264 const char *varname_start = NULL; 261 const char *varname_start = NULL;
265 int inputcnt = strlen (input); 262 int inputcnt = strlen (input);
266 int outputcnt = CONFIG_SYS_CBSIZE; 263 int outputcnt = CONFIG_SYS_CBSIZE;
267 int state = 0; /* 0 = waiting for '$' */ 264 int state = 0; /* 0 = waiting for '$' */
268 /* 1 = waiting for '(' or '{' */ 265 /* 1 = waiting for '(' or '{' */
269 /* 2 = waiting for ')' or '}' */ 266 /* 2 = waiting for ')' or '}' */
270 /* 3 = waiting for ''' */ 267 /* 3 = waiting for ''' */
271 #ifdef DEBUG_PARSER 268 #ifdef DEBUG_PARSER
272 char *output_start = output; 269 char *output_start = output;
273 270
274 printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", 271 printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n",
275 strlen(input), input); 272 strlen(input), input);
276 #endif 273 #endif
277 274
278 prev = '\0'; /* previous character */ 275 prev = '\0'; /* previous character */
279 276
280 while (inputcnt && outputcnt) { 277 while (inputcnt && outputcnt) {
281 c = *input++; 278 c = *input++;
282 inputcnt--; 279 inputcnt--;
283 280
284 if (state != 3) { 281 if (state != 3) {
285 /* remove one level of escape characters */ 282 /* remove one level of escape characters */
286 if ((c == '\\') && (prev != '\\')) { 283 if ((c == '\\') && (prev != '\\')) {
287 if (inputcnt-- == 0) 284 if (inputcnt-- == 0)
288 break; 285 break;
289 prev = c; 286 prev = c;
290 c = *input++; 287 c = *input++;
291 } 288 }
292 } 289 }
293 290
294 switch (state) { 291 switch (state) {
295 case 0: /* Waiting for (unescaped) $ */ 292 case 0: /* Waiting for (unescaped) $ */
296 if ((c == '\'') && (prev != '\\')) { 293 if ((c == '\'') && (prev != '\\')) {
297 state = 3; 294 state = 3;
298 break; 295 break;
299 } 296 }
300 if ((c == '$') && (prev != '\\')) { 297 if ((c == '$') && (prev != '\\')) {
301 state++; 298 state++;
302 } else { 299 } else {
303 *(output++) = c; 300 *(output++) = c;
304 outputcnt--; 301 outputcnt--;
305 } 302 }
306 break; 303 break;
307 case 1: /* Waiting for ( */ 304 case 1: /* Waiting for ( */
308 if (c == '(' || c == '{') { 305 if (c == '(' || c == '{') {
309 state++; 306 state++;
310 varname_start = input; 307 varname_start = input;
311 } else { 308 } else {
312 state = 0; 309 state = 0;
313 *(output++) = '$'; 310 *(output++) = '$';
314 outputcnt--; 311 outputcnt--;
315 312
316 if (outputcnt) { 313 if (outputcnt) {
317 *(output++) = c; 314 *(output++) = c;
318 outputcnt--; 315 outputcnt--;
319 } 316 }
320 } 317 }
321 break; 318 break;
322 case 2: /* Waiting for ) */ 319 case 2: /* Waiting for ) */
323 if (c == ')' || c == '}') { 320 if (c == ')' || c == '}') {
324 int i; 321 int i;
325 char envname[CONFIG_SYS_CBSIZE], *envval; 322 char envname[CONFIG_SYS_CBSIZE], *envval;
326 /* Varname # of chars */ 323 /* Varname # of chars */
327 int envcnt = input - varname_start - 1; 324 int envcnt = input - varname_start - 1;
328 325
329 /* Get the varname */ 326 /* Get the varname */
330 for (i = 0; i < envcnt; i++) { 327 for (i = 0; i < envcnt; i++) {
331 envname[i] = varname_start[i]; 328 envname[i] = varname_start[i];
332 } 329 }
333 envname[i] = 0; 330 envname[i] = 0;
334 331
335 /* Get its value */ 332 /* Get its value */
336 envval = getenv (envname); 333 envval = getenv (envname);
337 334
338 /* Copy into the line if it exists */ 335 /* Copy into the line if it exists */
339 if (envval != NULL) 336 if (envval != NULL)
340 while ((*envval) && outputcnt) { 337 while ((*envval) && outputcnt) {
341 *(output++) = *(envval++); 338 *(output++) = *(envval++);
342 outputcnt--; 339 outputcnt--;
343 } 340 }
344 /* Look for another '$' */ 341 /* Look for another '$' */
345 state = 0; 342 state = 0;
346 } 343 }
347 break; 344 break;
348 case 3: /* Waiting for ' */ 345 case 3: /* Waiting for ' */
349 if ((c == '\'') && (prev != '\\')) { 346 if ((c == '\'') && (prev != '\\')) {
350 state = 0; 347 state = 0;
351 } else { 348 } else {
352 *(output++) = c; 349 *(output++) = c;
353 outputcnt--; 350 outputcnt--;
354 } 351 }
355 break; 352 break;
356 } 353 }
357 prev = c; 354 prev = c;
358 } 355 }
359 356
360 if (outputcnt) 357 if (outputcnt)
361 *output = 0; 358 *output = 0;
362 359
363 #ifdef DEBUG_PARSER 360 #ifdef DEBUG_PARSER
364 printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", 361 printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
365 strlen (output_start), output_start); 362 strlen (output_start), output_start);
366 #endif 363 #endif
367 } 364 }
368 365
369 /* 366 /*
370 * this is called from board_init() after the hardware has been set up 367 * this is called from board_init() after the hardware has been set up
371 * and is usable. That seems like a good time to do this. 368 * and is usable. That seems like a good time to do this.
372 * Right now the return value is ignored. 369 * Right now the return value is ignored.
373 */ 370 */
374 int do_auto_update(void) 371 int do_auto_update(void)
375 { 372 {
376 block_dev_desc_t *stor_dev = NULL; 373 block_dev_desc_t *stor_dev = NULL;
377 long sz; 374 long sz;
378 int i, res, old_ctrlc; 375 int i, res, old_ctrlc;
379 char buffer[32]; 376 char buffer[32];
380 char str[80]; 377 char str[80];
381 int n; 378 int n;
382 379
383 if (ide_dev_desc[0].type != DEV_TYPE_UNKNOWN) { 380 if (ide_dev_desc[0].type != DEV_TYPE_UNKNOWN) {
384 stor_dev = get_dev ("ide", 0); 381 stor_dev = get_dev ("ide", 0);
385 if (stor_dev == NULL) { 382 if (stor_dev == NULL) {
386 debug ("ide: unknown device\n"); 383 debug ("ide: unknown device\n");
387 return -1; 384 return -1;
388 } 385 }
389 } 386 }
390 387
391 if (fat_register_device (stor_dev, 1) != 0) { 388 if (fat_register_device (stor_dev, 1) != 0) {
392 debug ("Unable to register ide disk 0:1\n"); 389 debug ("Unable to register ide disk 0:1\n");
393 return -1; 390 return -1;
394 } 391 }
395 392
396 /* 393 /*
397 * Check if magic file is present 394 * Check if magic file is present
398 */ 395 */
399 if ((n = do_fat_read (AU_MAGIC_FILE, buffer, 396 if ((n = do_fat_read (AU_MAGIC_FILE, buffer,
400 sizeof(buffer), LS_NO)) <= 0) { 397 sizeof(buffer), LS_NO)) <= 0) {
401 debug ("No auto_update magic file (n=%d)\n", n); 398 debug ("No auto_update magic file (n=%d)\n", n);
402 return -1; 399 return -1;
403 } 400 }
404 401
405 #ifdef CONFIG_AUTO_UPDATE_SHOW 402 #ifdef CONFIG_AUTO_UPDATE_SHOW
406 board_auto_update_show (1); 403 board_auto_update_show (1);
407 #endif 404 #endif
408 puts("\nAutoUpdate Disk detected! Trying to update system...\n"); 405 puts("\nAutoUpdate Disk detected! Trying to update system...\n");
409 406
410 /* make sure that we see CTRL-C and save the old state */ 407 /* make sure that we see CTRL-C and save the old state */
411 old_ctrlc = disable_ctrlc (0); 408 old_ctrlc = disable_ctrlc (0);
412 409
413 /* just loop thru all the possible files */ 410 /* just loop thru all the possible files */
414 for (i = 0; i < N_AU_IMAGES; i++) { 411 for (i = 0; i < N_AU_IMAGES; i++) {
415 /* 412 /*
416 * Try to expand the environment var in the fname 413 * Try to expand the environment var in the fname
417 */ 414 */
418 process_macros (au_image[i].name, str); 415 process_macros (au_image[i].name, str);
419 strcpy (au_image[i].name, str); 416 strcpy (au_image[i].name, str);
420 417
421 printf("Reading %s ...", au_image[i].name); 418 printf("Reading %s ...", au_image[i].name);
422 /* just read the header */ 419 /* just read the header */
423 sz = do_fat_read (au_image[i].name, LOAD_ADDR, 420 sz = do_fat_read (au_image[i].name, LOAD_ADDR,
424 image_get_header_size (), LS_NO); 421 image_get_header_size (), LS_NO);
425 debug ("read %s sz %ld hdr %d\n", 422 debug ("read %s sz %ld hdr %d\n",
426 au_image[i].name, sz, image_get_header_size ()); 423 au_image[i].name, sz, image_get_header_size ());
427 if (sz <= 0 || sz < image_get_header_size ()) { 424 if (sz <= 0 || sz < image_get_header_size ()) {
428 puts(" not found\n"); 425 puts(" not found\n");
429 continue; 426 continue;
430 } 427 }
431 if (au_check_header_valid (i, sz) < 0) { 428 if (au_check_header_valid (i, sz) < 0) {
432 puts(" header not valid\n"); 429 puts(" header not valid\n");
433 continue; 430 continue;
434 } 431 }
435 sz = do_fat_read (au_image[i].name, LOAD_ADDR, 432 sz = do_fat_read (au_image[i].name, LOAD_ADDR,
436 MAX_LOADSZ, LS_NO); 433 MAX_LOADSZ, LS_NO);
437 debug ("read %s sz %ld hdr %d\n", 434 debug ("read %s sz %ld hdr %d\n",
438 au_image[i].name, sz, image_get_header_size ()); 435 au_image[i].name, sz, image_get_header_size ());
439 if (sz <= 0 || sz <= image_get_header_size ()) { 436 if (sz <= 0 || sz <= image_get_header_size ()) {
440 puts(" not found\n"); 437 puts(" not found\n");
441 continue; 438 continue;
442 } 439 }
443 if (au_check_cksum_valid (i, sz) < 0) { 440 if (au_check_cksum_valid (i, sz) < 0) {
444 puts(" checksum not valid\n"); 441 puts(" checksum not valid\n");
445 continue; 442 continue;
446 } 443 }
447 puts(" done\n"); 444 puts(" done\n");
448 445
449 do { 446 do {
450 res = au_do_update (i, sz); 447 res = au_do_update (i, sz);
451 /* let the user break out of the loop */ 448 /* let the user break out of the loop */
452 if (ctrlc() || had_ctrlc ()) { 449 if (ctrlc() || had_ctrlc ()) {
453 clear_ctrlc (); 450 clear_ctrlc ();
454 break; 451 break;
455 } 452 }
456 } while (res < 0); 453 } while (res < 0);
457 } 454 }
458 455
459 /* restore the old state */ 456 /* restore the old state */
460 disable_ctrlc (old_ctrlc); 457 disable_ctrlc (old_ctrlc);
461 458
462 puts("AutoUpdate finished\n\n"); 459 puts("AutoUpdate finished\n\n");
463 #ifdef CONFIG_AUTO_UPDATE_SHOW 460 #ifdef CONFIG_AUTO_UPDATE_SHOW
464 board_auto_update_show (0); 461 board_auto_update_show (0);
465 #endif 462 #endif
466 463
467 return 0; 464 return 0;
468 } 465 }
469 466
470 int auto_update(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 467 int auto_update(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
471 { 468 {
472 do_auto_update(); 469 do_auto_update();
473 470
474 return 0; 471 return 0;
475 } 472 }
476 U_BOOT_CMD( 473 U_BOOT_CMD(
477 autoupd, 1, 1, auto_update, 474 autoupd, 1, 1, auto_update,
478 "Automatically update images", 475 "Automatically update images",
479 "" 476 ""
480 ); 477 );
481 #endif /* CONFIG_AUTO_UPDATE */ 478 #endif /* CONFIG_AUTO_UPDATE */
482 479
1 /* 1 /*
2 * (C) Copyright 2002 2 * (C) Copyright 2002
3 * Richard Jones, rjones@nexus-tech.net 3 * Richard Jones, rjones@nexus-tech.net
4 * 4 *
5 * SPDX-License-Identifier: GPL-2.0+ 5 * SPDX-License-Identifier: GPL-2.0+
6 */ 6 */
7 7
8 /* 8 /*
9 * Boot support 9 * Boot support
10 */ 10 */
11 #include <common.h> 11 #include <common.h>
12 #include <command.h> 12 #include <command.h>
13 #include <s_record.h> 13 #include <s_record.h>
14 #include <net.h> 14 #include <net.h>
15 #include <ata.h> 15 #include <ata.h>
16 #include <asm/io.h> 16 #include <asm/io.h>
17 #include <part.h> 17 #include <part.h>
18 #include <fat.h> 18 #include <fat.h>
19 #include <fs.h> 19 #include <fs.h>
20 20
21 int do_fat_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 21 int do_fat_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
22 { 22 {
23 return do_size(cmdtp, flag, argc, argv, FS_TYPE_FAT); 23 return do_size(cmdtp, flag, argc, argv, FS_TYPE_FAT);
24 } 24 }
25 25
26 U_BOOT_CMD( 26 U_BOOT_CMD(
27 fatsize, 4, 0, do_fat_size, 27 fatsize, 4, 0, do_fat_size,
28 "determine a file's size", 28 "determine a file's size",
29 "<interface> <dev[:part]> <filename>\n" 29 "<interface> <dev[:part]> <filename>\n"
30 " - Find file 'filename' from 'dev' on 'interface'\n" 30 " - Find file 'filename' from 'dev' on 'interface'\n"
31 " and determine its size." 31 " and determine its size."
32 ); 32 );
33 33
34 int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 34 int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
35 { 35 {
36 return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT); 36 return do_load(cmdtp, flag, argc, argv, FS_TYPE_FAT);
37 } 37 }
38 38
39 39
40 U_BOOT_CMD( 40 U_BOOT_CMD(
41 fatload, 7, 0, do_fat_fsload, 41 fatload, 7, 0, do_fat_fsload,
42 "load binary file from a dos filesystem", 42 "load binary file from a dos filesystem",
43 "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n" 43 "<interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]\n"
44 " - Load binary file 'filename' from 'dev' on 'interface'\n" 44 " - Load binary file 'filename' from 'dev' on 'interface'\n"
45 " to address 'addr' from dos filesystem.\n" 45 " to address 'addr' from dos filesystem.\n"
46 " 'pos' gives the file position to start loading from.\n" 46 " 'pos' gives the file position to start loading from.\n"
47 " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n" 47 " If 'pos' is omitted, 0 is used. 'pos' requires 'bytes'.\n"
48 " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n" 48 " 'bytes' gives the size to load. If 'bytes' is 0 or omitted,\n"
49 " the load stops on end of file.\n" 49 " the load stops on end of file.\n"
50 " If either 'pos' or 'bytes' are not aligned to\n" 50 " If either 'pos' or 'bytes' are not aligned to\n"
51 " ARCH_DMA_MINALIGN then a misaligned buffer warning will\n" 51 " ARCH_DMA_MINALIGN then a misaligned buffer warning will\n"
52 " be printed and performance will suffer for the load." 52 " be printed and performance will suffer for the load."
53 ); 53 );
54 54
55 static int do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 55 static int do_fat_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
56 { 56 {
57 return do_ls(cmdtp, flag, argc, argv, FS_TYPE_FAT); 57 return do_ls(cmdtp, flag, argc, argv, FS_TYPE_FAT);
58 } 58 }
59 59
60 U_BOOT_CMD( 60 U_BOOT_CMD(
61 fatls, 4, 1, do_fat_ls, 61 fatls, 4, 1, do_fat_ls,
62 "list files in a directory (default /)", 62 "list files in a directory (default /)",
63 "<interface> [<dev[:part]>] [directory]\n" 63 "<interface> [<dev[:part]>] [directory]\n"
64 " - list files from 'dev' on 'interface' in a 'directory'" 64 " - list files from 'dev' on 'interface' in a 'directory'"
65 ); 65 );
66 66
67 static int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, 67 static int do_fat_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc,
68 char * const argv[]) 68 char * const argv[])
69 { 69 {
70 int dev, part; 70 int dev, part;
71 block_dev_desc_t *dev_desc; 71 block_dev_desc_t *dev_desc;
72 disk_partition_t info; 72 disk_partition_t info;
73 73
74 if (argc < 2) { 74 if (argc < 2) {
75 printf("usage: fatinfo <interface> [<dev[:part]>]\n"); 75 printf("usage: fatinfo <interface> [<dev[:part]>]\n");
76 return 0; 76 return 0;
77 } 77 }
78 78
79 part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); 79 part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
80 if (part < 0) 80 if (part < 0)
81 return 1; 81 return 1;
82 82
83 dev = dev_desc->dev; 83 dev = dev_desc->dev;
84 if (fat_set_blk_dev(dev_desc, &info) != 0) { 84 if (fat_set_blk_dev(dev_desc, &info) != 0) {
85 printf("\n** Unable to use %s %d:%d for fatinfo **\n", 85 printf("\n** Unable to use %s %d:%d for fatinfo **\n",
86 argv[1], dev, part); 86 argv[1], dev, part);
87 return 1; 87 return 1;
88 } 88 }
89 return file_fat_detectfs(); 89 return file_fat_detectfs();
90 } 90 }
91 91
92 U_BOOT_CMD( 92 U_BOOT_CMD(
93 fatinfo, 3, 1, do_fat_fsinfo, 93 fatinfo, 3, 1, do_fat_fsinfo,
94 "print information about filesystem", 94 "print information about filesystem",
95 "<interface> [<dev[:part]>]\n" 95 "<interface> [<dev[:part]>]\n"
96 " - print information about filesystem from 'dev' on 'interface'" 96 " - print information about filesystem from 'dev' on 'interface'"
97 ); 97 );
98 98
99 #ifdef CONFIG_FAT_WRITE 99 #ifdef CONFIG_FAT_WRITE
100 static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag, 100 static int do_fat_fswrite(cmd_tbl_t *cmdtp, int flag,
101 int argc, char * const argv[]) 101 int argc, char * const argv[])
102 { 102 {
103 long size; 103 loff_t size;
104 int ret;
104 unsigned long addr; 105 unsigned long addr;
105 unsigned long count; 106 unsigned long count;
106 block_dev_desc_t *dev_desc = NULL; 107 block_dev_desc_t *dev_desc = NULL;
107 disk_partition_t info; 108 disk_partition_t info;
108 int dev = 0; 109 int dev = 0;
109 int part = 1; 110 int part = 1;
110 void *buf; 111 void *buf;
111 112
112 if (argc < 5) 113 if (argc < 5)
113 return cmd_usage(cmdtp); 114 return cmd_usage(cmdtp);
114 115
115 part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1); 116 part = get_device_and_partition(argv[1], argv[2], &dev_desc, &info, 1);
116 if (part < 0) 117 if (part < 0)
117 return 1; 118 return 1;
118 119
119 dev = dev_desc->dev; 120 dev = dev_desc->dev;
120 121
121 if (fat_set_blk_dev(dev_desc, &info) != 0) { 122 if (fat_set_blk_dev(dev_desc, &info) != 0) {
122 printf("\n** Unable to use %s %d:%d for fatwrite **\n", 123 printf("\n** Unable to use %s %d:%d for fatwrite **\n",
123 argv[1], dev, part); 124 argv[1], dev, part);
124 return 1; 125 return 1;
125 } 126 }
126 addr = simple_strtoul(argv[3], NULL, 16); 127 addr = simple_strtoul(argv[3], NULL, 16);
127 count = simple_strtoul(argv[5], NULL, 16); 128 count = simple_strtoul(argv[5], NULL, 16);
128 129
129 buf = map_sysmem(addr, count); 130 buf = map_sysmem(addr, count);
130 size = file_fat_write(argv[4], buf, count); 131 ret = file_fat_write(argv[4], buf, 0, count, &size);
131 unmap_sysmem(buf); 132 unmap_sysmem(buf);
132 if (size == -1) { 133 if (ret < 0) {
133 printf("\n** Unable to write \"%s\" from %s %d:%d **\n", 134 printf("\n** Unable to write \"%s\" from %s %d:%d **\n",
134 argv[4], argv[1], dev, part); 135 argv[4], argv[1], dev, part);
135 return 1; 136 return 1;
136 } 137 }
137 138
138 printf("%ld bytes written\n", size); 139 printf("%llu bytes written\n", size);
139 140
140 return 0; 141 return 0;
141 } 142 }
142 143
143 U_BOOT_CMD( 144 U_BOOT_CMD(
144 fatwrite, 6, 0, do_fat_fswrite, 145 fatwrite, 6, 0, do_fat_fswrite,
145 "write file into a dos filesystem", 146 "write file into a dos filesystem",
146 "<interface> <dev[:part]> <addr> <filename> <bytes>\n" 147 "<interface> <dev[:part]> <addr> <filename> <bytes>\n"
147 " - write file 'filename' from the address 'addr' in RAM\n" 148 " - write file 'filename' from the address 'addr' in RAM\n"
148 " to 'dev' on 'interface'" 149 " to 'dev' on 'interface'"
149 ); 150 );
150 #endif 151 #endif
151 152
1 /* 1 /*
2 * (c) Copyright 2011 by Tigris Elektronik GmbH 2 * (c) Copyright 2011 by Tigris Elektronik GmbH
3 * 3 *
4 * Author: 4 * Author:
5 * Maximilian Schwerin <mvs@tigris.de> 5 * Maximilian Schwerin <mvs@tigris.de>
6 * 6 *
7 * SPDX-License-Identifier: GPL-2.0+ 7 * SPDX-License-Identifier: GPL-2.0+
8 */ 8 */
9 9
10 #include <common.h> 10 #include <common.h>
11 11
12 #include <command.h> 12 #include <command.h>
13 #include <environment.h> 13 #include <environment.h>
14 #include <linux/stddef.h> 14 #include <linux/stddef.h>
15 #include <malloc.h> 15 #include <malloc.h>
16 #include <search.h> 16 #include <search.h>
17 #include <errno.h> 17 #include <errno.h>
18 #include <fat.h> 18 #include <fat.h>
19 #include <mmc.h> 19 #include <mmc.h>
20 20
21 char *env_name_spec = "FAT"; 21 char *env_name_spec = "FAT";
22 22
23 env_t *env_ptr; 23 env_t *env_ptr;
24 24
25 DECLARE_GLOBAL_DATA_PTR; 25 DECLARE_GLOBAL_DATA_PTR;
26 26
27 int env_init(void) 27 int env_init(void)
28 { 28 {
29 /* use default */ 29 /* use default */
30 gd->env_addr = (ulong)&default_environment[0]; 30 gd->env_addr = (ulong)&default_environment[0];
31 gd->env_valid = 1; 31 gd->env_valid = 1;
32 32
33 return 0; 33 return 0;
34 } 34 }
35 35
36 #ifdef CONFIG_CMD_SAVEENV 36 #ifdef CONFIG_CMD_SAVEENV
37 int saveenv(void) 37 int saveenv(void)
38 { 38 {
39 env_t env_new; 39 env_t env_new;
40 block_dev_desc_t *dev_desc = NULL; 40 block_dev_desc_t *dev_desc = NULL;
41 disk_partition_t info; 41 disk_partition_t info;
42 int dev, part; 42 int dev, part;
43 int err; 43 int err;
44 loff_t size;
44 45
45 err = env_export(&env_new); 46 err = env_export(&env_new);
46 if (err) 47 if (err)
47 return err; 48 return err;
48 49
49 part = get_device_and_partition(FAT_ENV_INTERFACE, 50 part = get_device_and_partition(FAT_ENV_INTERFACE,
50 FAT_ENV_DEVICE_AND_PART, 51 FAT_ENV_DEVICE_AND_PART,
51 &dev_desc, &info, 1); 52 &dev_desc, &info, 1);
52 if (part < 0) 53 if (part < 0)
53 return 1; 54 return 1;
54 55
55 dev = dev_desc->dev; 56 dev = dev_desc->dev;
56 if (fat_set_blk_dev(dev_desc, &info) != 0) { 57 if (fat_set_blk_dev(dev_desc, &info) != 0) {
57 printf("\n** Unable to use %s %d:%d for saveenv **\n", 58 printf("\n** Unable to use %s %d:%d for saveenv **\n",
58 FAT_ENV_INTERFACE, dev, part); 59 FAT_ENV_INTERFACE, dev, part);
59 return 1; 60 return 1;
60 } 61 }
61 62
62 err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, sizeof(env_t)); 63 err = file_fat_write(FAT_ENV_FILE, (void *)&env_new, 0, sizeof(env_t),
64 &size);
63 if (err == -1) { 65 if (err == -1) {
64 printf("\n** Unable to write \"%s\" from %s%d:%d **\n", 66 printf("\n** Unable to write \"%s\" from %s%d:%d **\n",
65 FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part); 67 FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part);
66 return 1; 68 return 1;
67 } 69 }
68 70
69 puts("done\n"); 71 puts("done\n");
70 return 0; 72 return 0;
71 } 73 }
72 #endif /* CONFIG_CMD_SAVEENV */ 74 #endif /* CONFIG_CMD_SAVEENV */
73 75
74 void env_relocate_spec(void) 76 void env_relocate_spec(void)
75 { 77 {
76 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE); 78 ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
77 block_dev_desc_t *dev_desc = NULL; 79 block_dev_desc_t *dev_desc = NULL;
78 disk_partition_t info; 80 disk_partition_t info;
79 int dev, part; 81 int dev, part;
80 int err; 82 int err;
81 83
82 part = get_device_and_partition(FAT_ENV_INTERFACE, 84 part = get_device_and_partition(FAT_ENV_INTERFACE,
83 FAT_ENV_DEVICE_AND_PART, 85 FAT_ENV_DEVICE_AND_PART,
84 &dev_desc, &info, 1); 86 &dev_desc, &info, 1);
85 if (part < 0) 87 if (part < 0)
86 goto err_env_relocate; 88 goto err_env_relocate;
87 89
88 dev = dev_desc->dev; 90 dev = dev_desc->dev;
89 if (fat_set_blk_dev(dev_desc, &info) != 0) { 91 if (fat_set_blk_dev(dev_desc, &info) != 0) {
90 printf("\n** Unable to use %s %d:%d for loading the env **\n", 92 printf("\n** Unable to use %s %d:%d for loading the env **\n",
91 FAT_ENV_INTERFACE, dev, part); 93 FAT_ENV_INTERFACE, dev, part);
92 goto err_env_relocate; 94 goto err_env_relocate;
93 } 95 }
94 96
95 err = file_fat_read(FAT_ENV_FILE, buf, CONFIG_ENV_SIZE); 97 err = file_fat_read(FAT_ENV_FILE, buf, CONFIG_ENV_SIZE);
96 if (err == -1) { 98 if (err == -1) {
97 printf("\n** Unable to read \"%s\" from %s%d:%d **\n", 99 printf("\n** Unable to read \"%s\" from %s%d:%d **\n",
98 FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part); 100 FAT_ENV_FILE, FAT_ENV_INTERFACE, dev, part);
99 goto err_env_relocate; 101 goto err_env_relocate;
100 } 102 }
101 103
102 env_import(buf, 1); 104 env_import(buf, 1);
103 return; 105 return;
104 106
105 err_env_relocate: 107 err_env_relocate:
106 set_default_env(NULL); 108 set_default_env(NULL);
107 } 109 }
108 110
1 /* 1 /*
2 * fat.c 2 * fat.c
3 * 3 *
4 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg 4 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
5 * 5 *
6 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 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 7 * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
8 * 8 *
9 * SPDX-License-Identifier: GPL-2.0+ 9 * SPDX-License-Identifier: GPL-2.0+
10 */ 10 */
11 11
12 #include <common.h> 12 #include <common.h>
13 #include <config.h> 13 #include <config.h>
14 #include <exports.h> 14 #include <exports.h>
15 #include <fat.h> 15 #include <fat.h>
16 #include <asm/byteorder.h> 16 #include <asm/byteorder.h>
17 #include <part.h> 17 #include <part.h>
18 #include <malloc.h> 18 #include <malloc.h>
19 #include <linux/compiler.h> 19 #include <linux/compiler.h>
20 #include <linux/ctype.h> 20 #include <linux/ctype.h>
21 21
22 #ifdef CONFIG_SUPPORT_VFAT 22 #ifdef CONFIG_SUPPORT_VFAT
23 static const int vfat_enabled = 1; 23 static const int vfat_enabled = 1;
24 #else 24 #else
25 static const int vfat_enabled = 0; 25 static const int vfat_enabled = 0;
26 #endif 26 #endif
27 27
28 /* 28 /*
29 * Convert a string to lowercase. 29 * Convert a string to lowercase.
30 */ 30 */
31 static void downcase(char *str) 31 static void downcase(char *str)
32 { 32 {
33 while (*str != '\0') { 33 while (*str != '\0') {
34 *str = tolower(*str); 34 *str = tolower(*str);
35 str++; 35 str++;
36 } 36 }
37 } 37 }
38 38
39 static block_dev_desc_t *cur_dev; 39 static block_dev_desc_t *cur_dev;
40 static disk_partition_t cur_part_info; 40 static disk_partition_t cur_part_info;
41 41
42 #define DOS_BOOT_MAGIC_OFFSET 0x1fe 42 #define DOS_BOOT_MAGIC_OFFSET 0x1fe
43 #define DOS_FS_TYPE_OFFSET 0x36 43 #define DOS_FS_TYPE_OFFSET 0x36
44 #define DOS_FS32_TYPE_OFFSET 0x52 44 #define DOS_FS32_TYPE_OFFSET 0x52
45 45
46 static int disk_read(__u32 block, __u32 nr_blocks, void *buf) 46 static int disk_read(__u32 block, __u32 nr_blocks, void *buf)
47 { 47 {
48 if (!cur_dev || !cur_dev->block_read) 48 if (!cur_dev || !cur_dev->block_read)
49 return -1; 49 return -1;
50 50
51 return cur_dev->block_read(cur_dev->dev, 51 return cur_dev->block_read(cur_dev->dev,
52 cur_part_info.start + block, nr_blocks, buf); 52 cur_part_info.start + block, nr_blocks, buf);
53 } 53 }
54 54
55 int fat_set_blk_dev(block_dev_desc_t *dev_desc, disk_partition_t *info) 55 int fat_set_blk_dev(block_dev_desc_t *dev_desc, disk_partition_t *info)
56 { 56 {
57 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz); 57 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev_desc->blksz);
58 58
59 cur_dev = dev_desc; 59 cur_dev = dev_desc;
60 cur_part_info = *info; 60 cur_part_info = *info;
61 61
62 /* Make sure it has a valid FAT header */ 62 /* Make sure it has a valid FAT header */
63 if (disk_read(0, 1, buffer) != 1) { 63 if (disk_read(0, 1, buffer) != 1) {
64 cur_dev = NULL; 64 cur_dev = NULL;
65 return -1; 65 return -1;
66 } 66 }
67 67
68 /* Check if it's actually a DOS volume */ 68 /* Check if it's actually a DOS volume */
69 if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) { 69 if (memcmp(buffer + DOS_BOOT_MAGIC_OFFSET, "\x55\xAA", 2)) {
70 cur_dev = NULL; 70 cur_dev = NULL;
71 return -1; 71 return -1;
72 } 72 }
73 73
74 /* Check for FAT12/FAT16/FAT32 filesystem */ 74 /* Check for FAT12/FAT16/FAT32 filesystem */
75 if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3)) 75 if (!memcmp(buffer + DOS_FS_TYPE_OFFSET, "FAT", 3))
76 return 0; 76 return 0;
77 if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5)) 77 if (!memcmp(buffer + DOS_FS32_TYPE_OFFSET, "FAT32", 5))
78 return 0; 78 return 0;
79 79
80 cur_dev = NULL; 80 cur_dev = NULL;
81 return -1; 81 return -1;
82 } 82 }
83 83
84 int fat_register_device(block_dev_desc_t *dev_desc, int part_no) 84 int fat_register_device(block_dev_desc_t *dev_desc, int part_no)
85 { 85 {
86 disk_partition_t info; 86 disk_partition_t info;
87 87
88 /* First close any currently found FAT filesystem */ 88 /* First close any currently found FAT filesystem */
89 cur_dev = NULL; 89 cur_dev = NULL;
90 90
91 /* Read the partition table, if present */ 91 /* Read the partition table, if present */
92 if (get_partition_info(dev_desc, part_no, &info)) { 92 if (get_partition_info(dev_desc, part_no, &info)) {
93 if (part_no != 0) { 93 if (part_no != 0) {
94 printf("** Partition %d not valid on device %d **\n", 94 printf("** Partition %d not valid on device %d **\n",
95 part_no, dev_desc->dev); 95 part_no, dev_desc->dev);
96 return -1; 96 return -1;
97 } 97 }
98 98
99 info.start = 0; 99 info.start = 0;
100 info.size = dev_desc->lba; 100 info.size = dev_desc->lba;
101 info.blksz = dev_desc->blksz; 101 info.blksz = dev_desc->blksz;
102 info.name[0] = 0; 102 info.name[0] = 0;
103 info.type[0] = 0; 103 info.type[0] = 0;
104 info.bootable = 0; 104 info.bootable = 0;
105 #ifdef CONFIG_PARTITION_UUIDS 105 #ifdef CONFIG_PARTITION_UUIDS
106 info.uuid[0] = 0; 106 info.uuid[0] = 0;
107 #endif 107 #endif
108 } 108 }
109 109
110 return fat_set_blk_dev(dev_desc, &info); 110 return fat_set_blk_dev(dev_desc, &info);
111 } 111 }
112 112
113 /* 113 /*
114 * Get the first occurence of a directory delimiter ('/' or '\') in a string. 114 * Get the first occurence of a directory delimiter ('/' or '\') in a string.
115 * Return index into string if found, -1 otherwise. 115 * Return index into string if found, -1 otherwise.
116 */ 116 */
117 static int dirdelim(char *str) 117 static int dirdelim(char *str)
118 { 118 {
119 char *start = str; 119 char *start = str;
120 120
121 while (*str != '\0') { 121 while (*str != '\0') {
122 if (ISDIRDELIM(*str)) 122 if (ISDIRDELIM(*str))
123 return str - start; 123 return str - start;
124 str++; 124 str++;
125 } 125 }
126 return -1; 126 return -1;
127 } 127 }
128 128
129 /* 129 /*
130 * Extract zero terminated short name from a directory entry. 130 * Extract zero terminated short name from a directory entry.
131 */ 131 */
132 static void get_name(dir_entry *dirent, char *s_name) 132 static void get_name(dir_entry *dirent, char *s_name)
133 { 133 {
134 char *ptr; 134 char *ptr;
135 135
136 memcpy(s_name, dirent->name, 8); 136 memcpy(s_name, dirent->name, 8);
137 s_name[8] = '\0'; 137 s_name[8] = '\0';
138 ptr = s_name; 138 ptr = s_name;
139 while (*ptr && *ptr != ' ') 139 while (*ptr && *ptr != ' ')
140 ptr++; 140 ptr++;
141 if (dirent->ext[0] && dirent->ext[0] != ' ') { 141 if (dirent->ext[0] && dirent->ext[0] != ' ') {
142 *ptr = '.'; 142 *ptr = '.';
143 ptr++; 143 ptr++;
144 memcpy(ptr, dirent->ext, 3); 144 memcpy(ptr, dirent->ext, 3);
145 ptr[3] = '\0'; 145 ptr[3] = '\0';
146 while (*ptr && *ptr != ' ') 146 while (*ptr && *ptr != ' ')
147 ptr++; 147 ptr++;
148 } 148 }
149 *ptr = '\0'; 149 *ptr = '\0';
150 if (*s_name == DELETED_FLAG) 150 if (*s_name == DELETED_FLAG)
151 *s_name = '\0'; 151 *s_name = '\0';
152 else if (*s_name == aRING) 152 else if (*s_name == aRING)
153 *s_name = DELETED_FLAG; 153 *s_name = DELETED_FLAG;
154 downcase(s_name); 154 downcase(s_name);
155 } 155 }
156 156
157 /* 157 /*
158 * Get the entry at index 'entry' in a FAT (12/16/32) table. 158 * Get the entry at index 'entry' in a FAT (12/16/32) table.
159 * On failure 0x00 is returned. 159 * On failure 0x00 is returned.
160 */ 160 */
161 static __u32 get_fatent(fsdata *mydata, __u32 entry) 161 static __u32 get_fatent(fsdata *mydata, __u32 entry)
162 { 162 {
163 __u32 bufnum; 163 __u32 bufnum;
164 __u32 off16, offset; 164 __u32 off16, offset;
165 __u32 ret = 0x00; 165 __u32 ret = 0x00;
166 __u16 val1, val2; 166 __u16 val1, val2;
167 167
168 switch (mydata->fatsize) { 168 switch (mydata->fatsize) {
169 case 32: 169 case 32:
170 bufnum = entry / FAT32BUFSIZE; 170 bufnum = entry / FAT32BUFSIZE;
171 offset = entry - bufnum * FAT32BUFSIZE; 171 offset = entry - bufnum * FAT32BUFSIZE;
172 break; 172 break;
173 case 16: 173 case 16:
174 bufnum = entry / FAT16BUFSIZE; 174 bufnum = entry / FAT16BUFSIZE;
175 offset = entry - bufnum * FAT16BUFSIZE; 175 offset = entry - bufnum * FAT16BUFSIZE;
176 break; 176 break;
177 case 12: 177 case 12:
178 bufnum = entry / FAT12BUFSIZE; 178 bufnum = entry / FAT12BUFSIZE;
179 offset = entry - bufnum * FAT12BUFSIZE; 179 offset = entry - bufnum * FAT12BUFSIZE;
180 break; 180 break;
181 181
182 default: 182 default:
183 /* Unsupported FAT size */ 183 /* Unsupported FAT size */
184 return ret; 184 return ret;
185 } 185 }
186 186
187 debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n", 187 debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
188 mydata->fatsize, entry, entry, offset, offset); 188 mydata->fatsize, entry, entry, offset, offset);
189 189
190 /* Read a new block of FAT entries into the cache. */ 190 /* Read a new block of FAT entries into the cache. */
191 if (bufnum != mydata->fatbufnum) { 191 if (bufnum != mydata->fatbufnum) {
192 __u32 getsize = FATBUFBLOCKS; 192 __u32 getsize = FATBUFBLOCKS;
193 __u8 *bufptr = mydata->fatbuf; 193 __u8 *bufptr = mydata->fatbuf;
194 __u32 fatlength = mydata->fatlength; 194 __u32 fatlength = mydata->fatlength;
195 __u32 startblock = bufnum * FATBUFBLOCKS; 195 __u32 startblock = bufnum * FATBUFBLOCKS;
196 196
197 if (startblock + getsize > fatlength) 197 if (startblock + getsize > fatlength)
198 getsize = fatlength - startblock; 198 getsize = fatlength - startblock;
199 199
200 startblock += mydata->fat_sect; /* Offset from start of disk */ 200 startblock += mydata->fat_sect; /* Offset from start of disk */
201 201
202 if (disk_read(startblock, getsize, bufptr) < 0) { 202 if (disk_read(startblock, getsize, bufptr) < 0) {
203 debug("Error reading FAT blocks\n"); 203 debug("Error reading FAT blocks\n");
204 return ret; 204 return ret;
205 } 205 }
206 mydata->fatbufnum = bufnum; 206 mydata->fatbufnum = bufnum;
207 } 207 }
208 208
209 /* Get the actual entry from the table */ 209 /* Get the actual entry from the table */
210 switch (mydata->fatsize) { 210 switch (mydata->fatsize) {
211 case 32: 211 case 32:
212 ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]); 212 ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
213 break; 213 break;
214 case 16: 214 case 16:
215 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]); 215 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
216 break; 216 break;
217 case 12: 217 case 12:
218 off16 = (offset * 3) / 4; 218 off16 = (offset * 3) / 4;
219 219
220 switch (offset & 0x3) { 220 switch (offset & 0x3) {
221 case 0: 221 case 0:
222 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]); 222 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]);
223 ret &= 0xfff; 223 ret &= 0xfff;
224 break; 224 break;
225 case 1: 225 case 1:
226 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 226 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
227 val1 &= 0xf000; 227 val1 &= 0xf000;
228 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]); 228 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
229 val2 &= 0x00ff; 229 val2 &= 0x00ff;
230 ret = (val2 << 4) | (val1 >> 12); 230 ret = (val2 << 4) | (val1 >> 12);
231 break; 231 break;
232 case 2: 232 case 2:
233 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 233 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
234 val1 &= 0xff00; 234 val1 &= 0xff00;
235 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]); 235 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
236 val2 &= 0x000f; 236 val2 &= 0x000f;
237 ret = (val2 << 8) | (val1 >> 8); 237 ret = (val2 << 8) | (val1 >> 8);
238 break; 238 break;
239 case 3: 239 case 3:
240 ret = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 240 ret = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
241 ret = (ret & 0xfff0) >> 4; 241 ret = (ret & 0xfff0) >> 4;
242 break; 242 break;
243 default: 243 default:
244 break; 244 break;
245 } 245 }
246 break; 246 break;
247 } 247 }
248 debug("FAT%d: ret: %08x, offset: %04x\n", 248 debug("FAT%d: ret: %08x, offset: %04x\n",
249 mydata->fatsize, ret, offset); 249 mydata->fatsize, ret, offset);
250 250
251 return ret; 251 return ret;
252 } 252 }
253 253
254 /* 254 /*
255 * Read at most 'size' bytes from the specified cluster into 'buffer'. 255 * Read at most 'size' bytes from the specified cluster into 'buffer'.
256 * Return 0 on success, -1 otherwise. 256 * Return 0 on success, -1 otherwise.
257 */ 257 */
258 static int 258 static int
259 get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size) 259 get_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, unsigned long size)
260 { 260 {
261 __u32 idx = 0; 261 __u32 idx = 0;
262 __u32 startsect; 262 __u32 startsect;
263 int ret; 263 int ret;
264 264
265 if (clustnum > 0) { 265 if (clustnum > 0) {
266 startsect = mydata->data_begin + 266 startsect = mydata->data_begin +
267 clustnum * mydata->clust_size; 267 clustnum * mydata->clust_size;
268 } else { 268 } else {
269 startsect = mydata->rootdir_sect; 269 startsect = mydata->rootdir_sect;
270 } 270 }
271 271
272 debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect); 272 debug("gc - clustnum: %d, startsect: %d\n", clustnum, startsect);
273 273
274 if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) { 274 if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) {
275 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); 275 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
276 276
277 printf("FAT: Misaligned buffer address (%p)\n", buffer); 277 printf("FAT: Misaligned buffer address (%p)\n", buffer);
278 278
279 while (size >= mydata->sect_size) { 279 while (size >= mydata->sect_size) {
280 ret = disk_read(startsect++, 1, tmpbuf); 280 ret = disk_read(startsect++, 1, tmpbuf);
281 if (ret != 1) { 281 if (ret != 1) {
282 debug("Error reading data (got %d)\n", ret); 282 debug("Error reading data (got %d)\n", ret);
283 return -1; 283 return -1;
284 } 284 }
285 285
286 memcpy(buffer, tmpbuf, mydata->sect_size); 286 memcpy(buffer, tmpbuf, mydata->sect_size);
287 buffer += mydata->sect_size; 287 buffer += mydata->sect_size;
288 size -= mydata->sect_size; 288 size -= mydata->sect_size;
289 } 289 }
290 } else { 290 } else {
291 idx = size / mydata->sect_size; 291 idx = size / mydata->sect_size;
292 ret = disk_read(startsect, idx, buffer); 292 ret = disk_read(startsect, idx, buffer);
293 if (ret != idx) { 293 if (ret != idx) {
294 debug("Error reading data (got %d)\n", ret); 294 debug("Error reading data (got %d)\n", ret);
295 return -1; 295 return -1;
296 } 296 }
297 startsect += idx; 297 startsect += idx;
298 idx *= mydata->sect_size; 298 idx *= mydata->sect_size;
299 buffer += idx; 299 buffer += idx;
300 size -= idx; 300 size -= idx;
301 } 301 }
302 if (size) { 302 if (size) {
303 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size); 303 ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
304 304
305 ret = disk_read(startsect, 1, tmpbuf); 305 ret = disk_read(startsect, 1, tmpbuf);
306 if (ret != 1) { 306 if (ret != 1) {
307 debug("Error reading data (got %d)\n", ret); 307 debug("Error reading data (got %d)\n", ret);
308 return -1; 308 return -1;
309 } 309 }
310 310
311 memcpy(buffer, tmpbuf, size); 311 memcpy(buffer, tmpbuf, size);
312 } 312 }
313 313
314 return 0; 314 return 0;
315 } 315 }
316 316
317 /* 317 /*
318 * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr' 318 * Read at most 'maxsize' bytes from 'pos' in the file associated with 'dentptr'
319 * into 'buffer'. 319 * into 'buffer'.
320 * Return the number of bytes read or -1 on fatal errors. 320 * Update the number of bytes read in *gotsize or return -1 on fatal errors.
321 */ 321 */
322 __u8 get_contents_vfatname_block[MAX_CLUSTSIZE] 322 __u8 get_contents_vfatname_block[MAX_CLUSTSIZE]
323 __aligned(ARCH_DMA_MINALIGN); 323 __aligned(ARCH_DMA_MINALIGN);
324 324
325 static long 325 static int get_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos,
326 get_contents(fsdata *mydata, dir_entry *dentptr, unsigned long pos, 326 __u8 *buffer, loff_t maxsize, loff_t *gotsize)
327 __u8 *buffer, unsigned long maxsize)
328 { 327 {
329 unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; 328 loff_t filesize = FAT2CPU32(dentptr->size);
330 unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; 329 unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
331 __u32 curclust = START(dentptr); 330 __u32 curclust = START(dentptr);
332 __u32 endclust, newclust; 331 __u32 endclust, newclust;
333 unsigned long actsize; 332 loff_t actsize;
334 333
335 debug("Filesize: %ld bytes\n", filesize); 334 *gotsize = 0;
335 debug("Filesize: %llu bytes\n", filesize);
336 336
337 if (pos >= filesize) { 337 if (pos >= filesize) {
338 debug("Read position past EOF: %lu\n", pos); 338 debug("Read position past EOF: %llu\n", pos);
339 return gotsize; 339 return 0;
340 } 340 }
341 341
342 if (maxsize > 0 && filesize > pos + maxsize) 342 if (maxsize > 0 && filesize > pos + maxsize)
343 filesize = pos + maxsize; 343 filesize = pos + maxsize;
344 344
345 debug("%ld bytes\n", filesize); 345 debug("%llu bytes\n", filesize);
346 346
347 actsize = bytesperclust; 347 actsize = bytesperclust;
348 348
349 /* go to cluster at pos */ 349 /* go to cluster at pos */
350 while (actsize <= pos) { 350 while (actsize <= pos) {
351 curclust = get_fatent(mydata, curclust); 351 curclust = get_fatent(mydata, curclust);
352 if (CHECK_CLUST(curclust, mydata->fatsize)) { 352 if (CHECK_CLUST(curclust, mydata->fatsize)) {
353 debug("curclust: 0x%x\n", curclust); 353 debug("curclust: 0x%x\n", curclust);
354 debug("Invalid FAT entry\n"); 354 debug("Invalid FAT entry\n");
355 return gotsize; 355 return 0;
356 } 356 }
357 actsize += bytesperclust; 357 actsize += bytesperclust;
358 } 358 }
359 359
360 /* actsize > pos */ 360 /* actsize > pos */
361 actsize -= bytesperclust; 361 actsize -= bytesperclust;
362 filesize -= actsize; 362 filesize -= actsize;
363 pos -= actsize; 363 pos -= actsize;
364 364
365 /* align to beginning of next cluster if any */ 365 /* align to beginning of next cluster if any */
366 if (pos) { 366 if (pos) {
367 actsize = min(filesize, (unsigned long)bytesperclust); 367 actsize = min(filesize, (loff_t)bytesperclust);
368 if (get_cluster(mydata, curclust, get_contents_vfatname_block, 368 if (get_cluster(mydata, curclust, get_contents_vfatname_block,
369 (int)actsize) != 0) { 369 (int)actsize) != 0) {
370 printf("Error reading cluster\n"); 370 printf("Error reading cluster\n");
371 return -1; 371 return -1;
372 } 372 }
373 filesize -= actsize; 373 filesize -= actsize;
374 actsize -= pos; 374 actsize -= pos;
375 memcpy(buffer, get_contents_vfatname_block + pos, actsize); 375 memcpy(buffer, get_contents_vfatname_block + pos, actsize);
376 gotsize += actsize; 376 *gotsize += actsize;
377 if (!filesize) 377 if (!filesize)
378 return gotsize; 378 return 0;
379 buffer += actsize; 379 buffer += actsize;
380 380
381 curclust = get_fatent(mydata, curclust); 381 curclust = get_fatent(mydata, curclust);
382 if (CHECK_CLUST(curclust, mydata->fatsize)) { 382 if (CHECK_CLUST(curclust, mydata->fatsize)) {
383 debug("curclust: 0x%x\n", curclust); 383 debug("curclust: 0x%x\n", curclust);
384 debug("Invalid FAT entry\n"); 384 debug("Invalid FAT entry\n");
385 return gotsize; 385 return 0;
386 } 386 }
387 } 387 }
388 388
389 actsize = bytesperclust; 389 actsize = bytesperclust;
390 endclust = curclust; 390 endclust = curclust;
391 391
392 do { 392 do {
393 /* search for consecutive clusters */ 393 /* search for consecutive clusters */
394 while (actsize < filesize) { 394 while (actsize < filesize) {
395 newclust = get_fatent(mydata, endclust); 395 newclust = get_fatent(mydata, endclust);
396 if ((newclust - 1) != endclust) 396 if ((newclust - 1) != endclust)
397 goto getit; 397 goto getit;
398 if (CHECK_CLUST(newclust, mydata->fatsize)) { 398 if (CHECK_CLUST(newclust, mydata->fatsize)) {
399 debug("curclust: 0x%x\n", newclust); 399 debug("curclust: 0x%x\n", newclust);
400 debug("Invalid FAT entry\n"); 400 debug("Invalid FAT entry\n");
401 return gotsize; 401 return 0;
402 } 402 }
403 endclust = newclust; 403 endclust = newclust;
404 actsize += bytesperclust; 404 actsize += bytesperclust;
405 } 405 }
406 406
407 /* get remaining bytes */ 407 /* get remaining bytes */
408 actsize = filesize; 408 actsize = filesize;
409 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 409 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
410 printf("Error reading cluster\n"); 410 printf("Error reading cluster\n");
411 return -1; 411 return -1;
412 } 412 }
413 gotsize += actsize; 413 *gotsize += actsize;
414 return gotsize; 414 return 0;
415 getit: 415 getit:
416 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 416 if (get_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
417 printf("Error reading cluster\n"); 417 printf("Error reading cluster\n");
418 return -1; 418 return -1;
419 } 419 }
420 gotsize += (int)actsize; 420 *gotsize += (int)actsize;
421 filesize -= actsize; 421 filesize -= actsize;
422 buffer += actsize; 422 buffer += actsize;
423 423
424 curclust = get_fatent(mydata, endclust); 424 curclust = get_fatent(mydata, endclust);
425 if (CHECK_CLUST(curclust, mydata->fatsize)) { 425 if (CHECK_CLUST(curclust, mydata->fatsize)) {
426 debug("curclust: 0x%x\n", curclust); 426 debug("curclust: 0x%x\n", curclust);
427 printf("Invalid FAT entry\n"); 427 printf("Invalid FAT entry\n");
428 return gotsize; 428 return 0;
429 } 429 }
430 actsize = bytesperclust; 430 actsize = bytesperclust;
431 endclust = curclust; 431 endclust = curclust;
432 } while (1); 432 } while (1);
433 } 433 }
434 434
435 /* 435 /*
436 * Extract the file name information from 'slotptr' into 'l_name', 436 * Extract the file name information from 'slotptr' into 'l_name',
437 * starting at l_name[*idx]. 437 * starting at l_name[*idx].
438 * Return 1 if terminator (zero byte) is found, 0 otherwise. 438 * Return 1 if terminator (zero byte) is found, 0 otherwise.
439 */ 439 */
440 static int slot2str(dir_slot *slotptr, char *l_name, int *idx) 440 static int slot2str(dir_slot *slotptr, char *l_name, int *idx)
441 { 441 {
442 int j; 442 int j;
443 443
444 for (j = 0; j <= 8; j += 2) { 444 for (j = 0; j <= 8; j += 2) {
445 l_name[*idx] = slotptr->name0_4[j]; 445 l_name[*idx] = slotptr->name0_4[j];
446 if (l_name[*idx] == 0x00) 446 if (l_name[*idx] == 0x00)
447 return 1; 447 return 1;
448 (*idx)++; 448 (*idx)++;
449 } 449 }
450 for (j = 0; j <= 10; j += 2) { 450 for (j = 0; j <= 10; j += 2) {
451 l_name[*idx] = slotptr->name5_10[j]; 451 l_name[*idx] = slotptr->name5_10[j];
452 if (l_name[*idx] == 0x00) 452 if (l_name[*idx] == 0x00)
453 return 1; 453 return 1;
454 (*idx)++; 454 (*idx)++;
455 } 455 }
456 for (j = 0; j <= 2; j += 2) { 456 for (j = 0; j <= 2; j += 2) {
457 l_name[*idx] = slotptr->name11_12[j]; 457 l_name[*idx] = slotptr->name11_12[j];
458 if (l_name[*idx] == 0x00) 458 if (l_name[*idx] == 0x00)
459 return 1; 459 return 1;
460 (*idx)++; 460 (*idx)++;
461 } 461 }
462 462
463 return 0; 463 return 0;
464 } 464 }
465 465
466 /* 466 /*
467 * Extract the full long filename starting at 'retdent' (which is really 467 * Extract the full long filename starting at 'retdent' (which is really
468 * a slot) into 'l_name'. If successful also copy the real directory entry 468 * a slot) into 'l_name'. If successful also copy the real directory entry
469 * into 'retdent' 469 * into 'retdent'
470 * Return 0 on success, -1 otherwise. 470 * Return 0 on success, -1 otherwise.
471 */ 471 */
472 static int 472 static int
473 get_vfatname(fsdata *mydata, int curclust, __u8 *cluster, 473 get_vfatname(fsdata *mydata, int curclust, __u8 *cluster,
474 dir_entry *retdent, char *l_name) 474 dir_entry *retdent, char *l_name)
475 { 475 {
476 dir_entry *realdent; 476 dir_entry *realdent;
477 dir_slot *slotptr = (dir_slot *)retdent; 477 dir_slot *slotptr = (dir_slot *)retdent;
478 __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? 478 __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
479 PREFETCH_BLOCKS : 479 PREFETCH_BLOCKS :
480 mydata->clust_size); 480 mydata->clust_size);
481 __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff; 481 __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
482 int idx = 0; 482 int idx = 0;
483 483
484 if (counter > VFAT_MAXSEQ) { 484 if (counter > VFAT_MAXSEQ) {
485 debug("Error: VFAT name is too long\n"); 485 debug("Error: VFAT name is too long\n");
486 return -1; 486 return -1;
487 } 487 }
488 488
489 while ((__u8 *)slotptr < buflimit) { 489 while ((__u8 *)slotptr < buflimit) {
490 if (counter == 0) 490 if (counter == 0)
491 break; 491 break;
492 if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter) 492 if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
493 return -1; 493 return -1;
494 slotptr++; 494 slotptr++;
495 counter--; 495 counter--;
496 } 496 }
497 497
498 if ((__u8 *)slotptr >= buflimit) { 498 if ((__u8 *)slotptr >= buflimit) {
499 dir_slot *slotptr2; 499 dir_slot *slotptr2;
500 500
501 if (curclust == 0) 501 if (curclust == 0)
502 return -1; 502 return -1;
503 curclust = get_fatent(mydata, curclust); 503 curclust = get_fatent(mydata, curclust);
504 if (CHECK_CLUST(curclust, mydata->fatsize)) { 504 if (CHECK_CLUST(curclust, mydata->fatsize)) {
505 debug("curclust: 0x%x\n", curclust); 505 debug("curclust: 0x%x\n", curclust);
506 printf("Invalid FAT entry\n"); 506 printf("Invalid FAT entry\n");
507 return -1; 507 return -1;
508 } 508 }
509 509
510 if (get_cluster(mydata, curclust, get_contents_vfatname_block, 510 if (get_cluster(mydata, curclust, get_contents_vfatname_block,
511 mydata->clust_size * mydata->sect_size) != 0) { 511 mydata->clust_size * mydata->sect_size) != 0) {
512 debug("Error: reading directory block\n"); 512 debug("Error: reading directory block\n");
513 return -1; 513 return -1;
514 } 514 }
515 515
516 slotptr2 = (dir_slot *)get_contents_vfatname_block; 516 slotptr2 = (dir_slot *)get_contents_vfatname_block;
517 while (counter > 0) { 517 while (counter > 0) {
518 if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK) 518 if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
519 & 0xff) != counter) 519 & 0xff) != counter)
520 return -1; 520 return -1;
521 slotptr2++; 521 slotptr2++;
522 counter--; 522 counter--;
523 } 523 }
524 524
525 /* Save the real directory entry */ 525 /* Save the real directory entry */
526 realdent = (dir_entry *)slotptr2; 526 realdent = (dir_entry *)slotptr2;
527 while ((__u8 *)slotptr2 > get_contents_vfatname_block) { 527 while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
528 slotptr2--; 528 slotptr2--;
529 slot2str(slotptr2, l_name, &idx); 529 slot2str(slotptr2, l_name, &idx);
530 } 530 }
531 } else { 531 } else {
532 /* Save the real directory entry */ 532 /* Save the real directory entry */
533 realdent = (dir_entry *)slotptr; 533 realdent = (dir_entry *)slotptr;
534 } 534 }
535 535
536 do { 536 do {
537 slotptr--; 537 slotptr--;
538 if (slot2str(slotptr, l_name, &idx)) 538 if (slot2str(slotptr, l_name, &idx))
539 break; 539 break;
540 } while (!(slotptr->id & LAST_LONG_ENTRY_MASK)); 540 } while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
541 541
542 l_name[idx] = '\0'; 542 l_name[idx] = '\0';
543 if (*l_name == DELETED_FLAG) 543 if (*l_name == DELETED_FLAG)
544 *l_name = '\0'; 544 *l_name = '\0';
545 else if (*l_name == aRING) 545 else if (*l_name == aRING)
546 *l_name = DELETED_FLAG; 546 *l_name = DELETED_FLAG;
547 downcase(l_name); 547 downcase(l_name);
548 548
549 /* Return the real directory entry */ 549 /* Return the real directory entry */
550 memcpy(retdent, realdent, sizeof(dir_entry)); 550 memcpy(retdent, realdent, sizeof(dir_entry));
551 551
552 return 0; 552 return 0;
553 } 553 }
554 554
555 /* Calculate short name checksum */ 555 /* Calculate short name checksum */
556 static __u8 mkcksum(const char name[8], const char ext[3]) 556 static __u8 mkcksum(const char name[8], const char ext[3])
557 { 557 {
558 int i; 558 int i;
559 559
560 __u8 ret = 0; 560 __u8 ret = 0;
561 561
562 for (i = 0; i < 8; i++) 562 for (i = 0; i < 8; i++)
563 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i]; 563 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + name[i];
564 for (i = 0; i < 3; i++) 564 for (i = 0; i < 3; i++)
565 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i]; 565 ret = (((ret & 1) << 7) | ((ret & 0xfe) >> 1)) + ext[i];
566 566
567 return ret; 567 return ret;
568 } 568 }
569 569
570 /* 570 /*
571 * Get the directory entry associated with 'filename' from the directory 571 * Get the directory entry associated with 'filename' from the directory
572 * starting at 'startsect' 572 * starting at 'startsect'
573 */ 573 */
574 __u8 get_dentfromdir_block[MAX_CLUSTSIZE] 574 __u8 get_dentfromdir_block[MAX_CLUSTSIZE]
575 __aligned(ARCH_DMA_MINALIGN); 575 __aligned(ARCH_DMA_MINALIGN);
576 576
577 static dir_entry *get_dentfromdir(fsdata *mydata, int startsect, 577 static dir_entry *get_dentfromdir(fsdata *mydata, int startsect,
578 char *filename, dir_entry *retdent, 578 char *filename, dir_entry *retdent,
579 int dols) 579 int dols)
580 { 580 {
581 __u16 prevcksum = 0xffff; 581 __u16 prevcksum = 0xffff;
582 __u32 curclust = START(retdent); 582 __u32 curclust = START(retdent);
583 int files = 0, dirs = 0; 583 int files = 0, dirs = 0;
584 584
585 debug("get_dentfromdir: %s\n", filename); 585 debug("get_dentfromdir: %s\n", filename);
586 586
587 while (1) { 587 while (1) {
588 dir_entry *dentptr; 588 dir_entry *dentptr;
589 589
590 int i; 590 int i;
591 591
592 if (get_cluster(mydata, curclust, get_dentfromdir_block, 592 if (get_cluster(mydata, curclust, get_dentfromdir_block,
593 mydata->clust_size * mydata->sect_size) != 0) { 593 mydata->clust_size * mydata->sect_size) != 0) {
594 debug("Error: reading directory block\n"); 594 debug("Error: reading directory block\n");
595 return NULL; 595 return NULL;
596 } 596 }
597 597
598 dentptr = (dir_entry *)get_dentfromdir_block; 598 dentptr = (dir_entry *)get_dentfromdir_block;
599 599
600 for (i = 0; i < DIRENTSPERCLUST; i++) { 600 for (i = 0; i < DIRENTSPERCLUST; i++) {
601 char s_name[14], l_name[VFAT_MAXLEN_BYTES]; 601 char s_name[14], l_name[VFAT_MAXLEN_BYTES];
602 602
603 l_name[0] = '\0'; 603 l_name[0] = '\0';
604 if (dentptr->name[0] == DELETED_FLAG) { 604 if (dentptr->name[0] == DELETED_FLAG) {
605 dentptr++; 605 dentptr++;
606 continue; 606 continue;
607 } 607 }
608 if ((dentptr->attr & ATTR_VOLUME)) { 608 if ((dentptr->attr & ATTR_VOLUME)) {
609 if (vfat_enabled && 609 if (vfat_enabled &&
610 (dentptr->attr & ATTR_VFAT) == ATTR_VFAT && 610 (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
611 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) { 611 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
612 prevcksum = ((dir_slot *)dentptr)->alias_checksum; 612 prevcksum = ((dir_slot *)dentptr)->alias_checksum;
613 get_vfatname(mydata, curclust, 613 get_vfatname(mydata, curclust,
614 get_dentfromdir_block, 614 get_dentfromdir_block,
615 dentptr, l_name); 615 dentptr, l_name);
616 if (dols) { 616 if (dols) {
617 int isdir; 617 int isdir;
618 char dirc; 618 char dirc;
619 int doit = 0; 619 int doit = 0;
620 620
621 isdir = (dentptr->attr & ATTR_DIR); 621 isdir = (dentptr->attr & ATTR_DIR);
622 622
623 if (isdir) { 623 if (isdir) {
624 dirs++; 624 dirs++;
625 dirc = '/'; 625 dirc = '/';
626 doit = 1; 626 doit = 1;
627 } else { 627 } else {
628 dirc = ' '; 628 dirc = ' ';
629 if (l_name[0] != 0) { 629 if (l_name[0] != 0) {
630 files++; 630 files++;
631 doit = 1; 631 doit = 1;
632 } 632 }
633 } 633 }
634 if (doit) { 634 if (doit) {
635 if (dirc == ' ') { 635 if (dirc == ' ') {
636 printf(" %8ld %s%c\n", 636 printf(" %8u %s%c\n",
637 (long)FAT2CPU32(dentptr->size), 637 FAT2CPU32(dentptr->size),
638 l_name, 638 l_name,
639 dirc); 639 dirc);
640 } else { 640 } else {
641 printf(" %s%c\n", 641 printf(" %s%c\n",
642 l_name, 642 l_name,
643 dirc); 643 dirc);
644 } 644 }
645 } 645 }
646 dentptr++; 646 dentptr++;
647 continue; 647 continue;
648 } 648 }
649 debug("vfatname: |%s|\n", l_name); 649 debug("vfatname: |%s|\n", l_name);
650 } else { 650 } else {
651 /* Volume label or VFAT entry */ 651 /* Volume label or VFAT entry */
652 dentptr++; 652 dentptr++;
653 continue; 653 continue;
654 } 654 }
655 } 655 }
656 if (dentptr->name[0] == 0) { 656 if (dentptr->name[0] == 0) {
657 if (dols) { 657 if (dols) {
658 printf("\n%d file(s), %d dir(s)\n\n", 658 printf("\n%d file(s), %d dir(s)\n\n",
659 files, dirs); 659 files, dirs);
660 } 660 }
661 debug("Dentname == NULL - %d\n", i); 661 debug("Dentname == NULL - %d\n", i);
662 return NULL; 662 return NULL;
663 } 663 }
664 if (vfat_enabled) { 664 if (vfat_enabled) {
665 __u8 csum = mkcksum(dentptr->name, dentptr->ext); 665 __u8 csum = mkcksum(dentptr->name, dentptr->ext);
666 if (dols && csum == prevcksum) { 666 if (dols && csum == prevcksum) {
667 prevcksum = 0xffff; 667 prevcksum = 0xffff;
668 dentptr++; 668 dentptr++;
669 continue; 669 continue;
670 } 670 }
671 } 671 }
672 672
673 get_name(dentptr, s_name); 673 get_name(dentptr, s_name);
674 if (dols) { 674 if (dols) {
675 int isdir = (dentptr->attr & ATTR_DIR); 675 int isdir = (dentptr->attr & ATTR_DIR);
676 char dirc; 676 char dirc;
677 int doit = 0; 677 int doit = 0;
678 678
679 if (isdir) { 679 if (isdir) {
680 dirs++; 680 dirs++;
681 dirc = '/'; 681 dirc = '/';
682 doit = 1; 682 doit = 1;
683 } else { 683 } else {
684 dirc = ' '; 684 dirc = ' ';
685 if (s_name[0] != 0) { 685 if (s_name[0] != 0) {
686 files++; 686 files++;
687 doit = 1; 687 doit = 1;
688 } 688 }
689 } 689 }
690 690
691 if (doit) { 691 if (doit) {
692 if (dirc == ' ') { 692 if (dirc == ' ') {
693 printf(" %8ld %s%c\n", 693 printf(" %8u %s%c\n",
694 (long)FAT2CPU32(dentptr->size), 694 FAT2CPU32(dentptr->size),
695 s_name, dirc); 695 s_name, dirc);
696 } else { 696 } else {
697 printf(" %s%c\n", 697 printf(" %s%c\n",
698 s_name, dirc); 698 s_name, dirc);
699 } 699 }
700 } 700 }
701 701
702 dentptr++; 702 dentptr++;
703 continue; 703 continue;
704 } 704 }
705 705
706 if (strcmp(filename, s_name) 706 if (strcmp(filename, s_name)
707 && strcmp(filename, l_name)) { 707 && strcmp(filename, l_name)) {
708 debug("Mismatch: |%s|%s|\n", s_name, l_name); 708 debug("Mismatch: |%s|%s|\n", s_name, l_name);
709 dentptr++; 709 dentptr++;
710 continue; 710 continue;
711 } 711 }
712 712
713 memcpy(retdent, dentptr, sizeof(dir_entry)); 713 memcpy(retdent, dentptr, sizeof(dir_entry));
714 714
715 debug("DentName: %s", s_name); 715 debug("DentName: %s", s_name);
716 debug(", start: 0x%x", START(dentptr)); 716 debug(", start: 0x%x", START(dentptr));
717 debug(", size: 0x%x %s\n", 717 debug(", size: 0x%x %s\n",
718 FAT2CPU32(dentptr->size), 718 FAT2CPU32(dentptr->size),
719 (dentptr->attr & ATTR_DIR) ? "(DIR)" : ""); 719 (dentptr->attr & ATTR_DIR) ? "(DIR)" : "");
720 720
721 return retdent; 721 return retdent;
722 } 722 }
723 723
724 curclust = get_fatent(mydata, curclust); 724 curclust = get_fatent(mydata, curclust);
725 if (CHECK_CLUST(curclust, mydata->fatsize)) { 725 if (CHECK_CLUST(curclust, mydata->fatsize)) {
726 debug("curclust: 0x%x\n", curclust); 726 debug("curclust: 0x%x\n", curclust);
727 printf("Invalid FAT entry\n"); 727 printf("Invalid FAT entry\n");
728 return NULL; 728 return NULL;
729 } 729 }
730 } 730 }
731 731
732 return NULL; 732 return NULL;
733 } 733 }
734 734
735 /* 735 /*
736 * Read boot sector and volume info from a FAT filesystem 736 * Read boot sector and volume info from a FAT filesystem
737 */ 737 */
738 static int 738 static int
739 read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize) 739 read_bootsectandvi(boot_sector *bs, volume_info *volinfo, int *fatsize)
740 { 740 {
741 __u8 *block; 741 __u8 *block;
742 volume_info *vistart; 742 volume_info *vistart;
743 int ret = 0; 743 int ret = 0;
744 744
745 if (cur_dev == NULL) { 745 if (cur_dev == NULL) {
746 debug("Error: no device selected\n"); 746 debug("Error: no device selected\n");
747 return -1; 747 return -1;
748 } 748 }
749 749
750 block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz); 750 block = memalign(ARCH_DMA_MINALIGN, cur_dev->blksz);
751 if (block == NULL) { 751 if (block == NULL) {
752 debug("Error: allocating block\n"); 752 debug("Error: allocating block\n");
753 return -1; 753 return -1;
754 } 754 }
755 755
756 if (disk_read(0, 1, block) < 0) { 756 if (disk_read(0, 1, block) < 0) {
757 debug("Error: reading block\n"); 757 debug("Error: reading block\n");
758 goto fail; 758 goto fail;
759 } 759 }
760 760
761 memcpy(bs, block, sizeof(boot_sector)); 761 memcpy(bs, block, sizeof(boot_sector));
762 bs->reserved = FAT2CPU16(bs->reserved); 762 bs->reserved = FAT2CPU16(bs->reserved);
763 bs->fat_length = FAT2CPU16(bs->fat_length); 763 bs->fat_length = FAT2CPU16(bs->fat_length);
764 bs->secs_track = FAT2CPU16(bs->secs_track); 764 bs->secs_track = FAT2CPU16(bs->secs_track);
765 bs->heads = FAT2CPU16(bs->heads); 765 bs->heads = FAT2CPU16(bs->heads);
766 bs->total_sect = FAT2CPU32(bs->total_sect); 766 bs->total_sect = FAT2CPU32(bs->total_sect);
767 767
768 /* FAT32 entries */ 768 /* FAT32 entries */
769 if (bs->fat_length == 0) { 769 if (bs->fat_length == 0) {
770 /* Assume FAT32 */ 770 /* Assume FAT32 */
771 bs->fat32_length = FAT2CPU32(bs->fat32_length); 771 bs->fat32_length = FAT2CPU32(bs->fat32_length);
772 bs->flags = FAT2CPU16(bs->flags); 772 bs->flags = FAT2CPU16(bs->flags);
773 bs->root_cluster = FAT2CPU32(bs->root_cluster); 773 bs->root_cluster = FAT2CPU32(bs->root_cluster);
774 bs->info_sector = FAT2CPU16(bs->info_sector); 774 bs->info_sector = FAT2CPU16(bs->info_sector);
775 bs->backup_boot = FAT2CPU16(bs->backup_boot); 775 bs->backup_boot = FAT2CPU16(bs->backup_boot);
776 vistart = (volume_info *)(block + sizeof(boot_sector)); 776 vistart = (volume_info *)(block + sizeof(boot_sector));
777 *fatsize = 32; 777 *fatsize = 32;
778 } else { 778 } else {
779 vistart = (volume_info *)&(bs->fat32_length); 779 vistart = (volume_info *)&(bs->fat32_length);
780 *fatsize = 0; 780 *fatsize = 0;
781 } 781 }
782 memcpy(volinfo, vistart, sizeof(volume_info)); 782 memcpy(volinfo, vistart, sizeof(volume_info));
783 783
784 if (*fatsize == 32) { 784 if (*fatsize == 32) {
785 if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0) 785 if (strncmp(FAT32_SIGN, vistart->fs_type, SIGNLEN) == 0)
786 goto exit; 786 goto exit;
787 } else { 787 } else {
788 if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) { 788 if (strncmp(FAT12_SIGN, vistart->fs_type, SIGNLEN) == 0) {
789 *fatsize = 12; 789 *fatsize = 12;
790 goto exit; 790 goto exit;
791 } 791 }
792 if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) { 792 if (strncmp(FAT16_SIGN, vistart->fs_type, SIGNLEN) == 0) {
793 *fatsize = 16; 793 *fatsize = 16;
794 goto exit; 794 goto exit;
795 } 795 }
796 } 796 }
797 797
798 debug("Error: broken fs_type sign\n"); 798 debug("Error: broken fs_type sign\n");
799 fail: 799 fail:
800 ret = -1; 800 ret = -1;
801 exit: 801 exit:
802 free(block); 802 free(block);
803 return ret; 803 return ret;
804 } 804 }
805 805
806 __u8 do_fat_read_at_block[MAX_CLUSTSIZE] 806 __u8 do_fat_read_at_block[MAX_CLUSTSIZE]
807 __aligned(ARCH_DMA_MINALIGN); 807 __aligned(ARCH_DMA_MINALIGN);
808 808
809 long 809 int do_fat_read_at(const char *filename, loff_t pos, void *buffer,
810 do_fat_read_at(const char *filename, unsigned long pos, void *buffer, 810 loff_t maxsize, int dols, int dogetsize, loff_t *size)
811 unsigned long maxsize, int dols, int dogetsize)
812 { 811 {
813 char fnamecopy[2048]; 812 char fnamecopy[2048];
814 boot_sector bs; 813 boot_sector bs;
815 volume_info volinfo; 814 volume_info volinfo;
816 fsdata datablock; 815 fsdata datablock;
817 fsdata *mydata = &datablock; 816 fsdata *mydata = &datablock;
818 dir_entry *dentptr = NULL; 817 dir_entry *dentptr = NULL;
819 __u16 prevcksum = 0xffff; 818 __u16 prevcksum = 0xffff;
820 char *subname = ""; 819 char *subname = "";
821 __u32 cursect; 820 __u32 cursect;
822 int idx, isdir = 0; 821 int idx, isdir = 0;
823 int files = 0, dirs = 0; 822 int files = 0, dirs = 0;
824 long ret = -1; 823 int ret = -1;
825 int firsttime; 824 int firsttime;
826 __u32 root_cluster = 0; 825 __u32 root_cluster = 0;
827 int rootdir_size = 0; 826 int rootdir_size = 0;
828 int j; 827 int j;
829 828
830 if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { 829 if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
831 debug("Error: reading boot sector\n"); 830 debug("Error: reading boot sector\n");
832 return -1; 831 return -1;
833 } 832 }
834 833
835 if (mydata->fatsize == 32) { 834 if (mydata->fatsize == 32) {
836 root_cluster = bs.root_cluster; 835 root_cluster = bs.root_cluster;
837 mydata->fatlength = bs.fat32_length; 836 mydata->fatlength = bs.fat32_length;
838 } else { 837 } else {
839 mydata->fatlength = bs.fat_length; 838 mydata->fatlength = bs.fat_length;
840 } 839 }
841 840
842 mydata->fat_sect = bs.reserved; 841 mydata->fat_sect = bs.reserved;
843 842
844 cursect = mydata->rootdir_sect 843 cursect = mydata->rootdir_sect
845 = mydata->fat_sect + mydata->fatlength * bs.fats; 844 = mydata->fat_sect + mydata->fatlength * bs.fats;
846 845
847 mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0]; 846 mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
848 mydata->clust_size = bs.cluster_size; 847 mydata->clust_size = bs.cluster_size;
849 if (mydata->sect_size != cur_part_info.blksz) { 848 if (mydata->sect_size != cur_part_info.blksz) {
850 printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n", 849 printf("Error: FAT sector size mismatch (fs=%hu, dev=%lu)\n",
851 mydata->sect_size, cur_part_info.blksz); 850 mydata->sect_size, cur_part_info.blksz);
852 return -1; 851 return -1;
853 } 852 }
854 853
855 if (mydata->fatsize == 32) { 854 if (mydata->fatsize == 32) {
856 mydata->data_begin = mydata->rootdir_sect - 855 mydata->data_begin = mydata->rootdir_sect -
857 (mydata->clust_size * 2); 856 (mydata->clust_size * 2);
858 } else { 857 } else {
859 rootdir_size = ((bs.dir_entries[1] * (int)256 + 858 rootdir_size = ((bs.dir_entries[1] * (int)256 +
860 bs.dir_entries[0]) * 859 bs.dir_entries[0]) *
861 sizeof(dir_entry)) / 860 sizeof(dir_entry)) /
862 mydata->sect_size; 861 mydata->sect_size;
863 mydata->data_begin = mydata->rootdir_sect + 862 mydata->data_begin = mydata->rootdir_sect +
864 rootdir_size - 863 rootdir_size -
865 (mydata->clust_size * 2); 864 (mydata->clust_size * 2);
866 } 865 }
867 866
868 mydata->fatbufnum = -1; 867 mydata->fatbufnum = -1;
869 mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE); 868 mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
870 if (mydata->fatbuf == NULL) { 869 if (mydata->fatbuf == NULL) {
871 debug("Error: allocating memory\n"); 870 debug("Error: allocating memory\n");
872 return -1; 871 return -1;
873 } 872 }
874 873
875 if (vfat_enabled) 874 if (vfat_enabled)
876 debug("VFAT Support enabled\n"); 875 debug("VFAT Support enabled\n");
877 876
878 debug("FAT%d, fat_sect: %d, fatlength: %d\n", 877 debug("FAT%d, fat_sect: %d, fatlength: %d\n",
879 mydata->fatsize, mydata->fat_sect, mydata->fatlength); 878 mydata->fatsize, mydata->fat_sect, mydata->fatlength);
880 debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n" 879 debug("Rootdir begins at cluster: %d, sector: %d, offset: %x\n"
881 "Data begins at: %d\n", 880 "Data begins at: %d\n",
882 root_cluster, 881 root_cluster,
883 mydata->rootdir_sect, 882 mydata->rootdir_sect,
884 mydata->rootdir_sect * mydata->sect_size, mydata->data_begin); 883 mydata->rootdir_sect * mydata->sect_size, mydata->data_begin);
885 debug("Sector size: %d, cluster size: %d\n", mydata->sect_size, 884 debug("Sector size: %d, cluster size: %d\n", mydata->sect_size,
886 mydata->clust_size); 885 mydata->clust_size);
887 886
888 /* "cwd" is always the root... */ 887 /* "cwd" is always the root... */
889 while (ISDIRDELIM(*filename)) 888 while (ISDIRDELIM(*filename))
890 filename++; 889 filename++;
891 890
892 /* Make a copy of the filename and convert it to lowercase */ 891 /* Make a copy of the filename and convert it to lowercase */
893 strcpy(fnamecopy, filename); 892 strcpy(fnamecopy, filename);
894 downcase(fnamecopy); 893 downcase(fnamecopy);
895 894
896 if (*fnamecopy == '\0') { 895 if (*fnamecopy == '\0') {
897 if (!dols) 896 if (!dols)
898 goto exit; 897 goto exit;
899 898
900 dols = LS_ROOT; 899 dols = LS_ROOT;
901 } else if ((idx = dirdelim(fnamecopy)) >= 0) { 900 } else if ((idx = dirdelim(fnamecopy)) >= 0) {
902 isdir = 1; 901 isdir = 1;
903 fnamecopy[idx] = '\0'; 902 fnamecopy[idx] = '\0';
904 subname = fnamecopy + idx + 1; 903 subname = fnamecopy + idx + 1;
905 904
906 /* Handle multiple delimiters */ 905 /* Handle multiple delimiters */
907 while (ISDIRDELIM(*subname)) 906 while (ISDIRDELIM(*subname))
908 subname++; 907 subname++;
909 } else if (dols) { 908 } else if (dols) {
910 isdir = 1; 909 isdir = 1;
911 } 910 }
912 911
913 j = 0; 912 j = 0;
914 while (1) { 913 while (1) {
915 int i; 914 int i;
916 915
917 if (j == 0) { 916 if (j == 0) {
918 debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n", 917 debug("FAT read sect=%d, clust_size=%d, DIRENTSPERBLOCK=%zd\n",
919 cursect, mydata->clust_size, DIRENTSPERBLOCK); 918 cursect, mydata->clust_size, DIRENTSPERBLOCK);
920 919
921 if (disk_read(cursect, 920 if (disk_read(cursect,
922 (mydata->fatsize == 32) ? 921 (mydata->fatsize == 32) ?
923 (mydata->clust_size) : 922 (mydata->clust_size) :
924 PREFETCH_BLOCKS, 923 PREFETCH_BLOCKS,
925 do_fat_read_at_block) < 0) { 924 do_fat_read_at_block) < 0) {
926 debug("Error: reading rootdir block\n"); 925 debug("Error: reading rootdir block\n");
927 goto exit; 926 goto exit;
928 } 927 }
929 928
930 dentptr = (dir_entry *) do_fat_read_at_block; 929 dentptr = (dir_entry *) do_fat_read_at_block;
931 } 930 }
932 931
933 for (i = 0; i < DIRENTSPERBLOCK; i++) { 932 for (i = 0; i < DIRENTSPERBLOCK; i++) {
934 char s_name[14], l_name[VFAT_MAXLEN_BYTES]; 933 char s_name[14], l_name[VFAT_MAXLEN_BYTES];
935 __u8 csum; 934 __u8 csum;
936 935
937 l_name[0] = '\0'; 936 l_name[0] = '\0';
938 if (dentptr->name[0] == DELETED_FLAG) { 937 if (dentptr->name[0] == DELETED_FLAG) {
939 dentptr++; 938 dentptr++;
940 continue; 939 continue;
941 } 940 }
942 941
943 if (vfat_enabled) 942 if (vfat_enabled)
944 csum = mkcksum(dentptr->name, dentptr->ext); 943 csum = mkcksum(dentptr->name, dentptr->ext);
945 944
946 if (dentptr->attr & ATTR_VOLUME) { 945 if (dentptr->attr & ATTR_VOLUME) {
947 if (vfat_enabled && 946 if (vfat_enabled &&
948 (dentptr->attr & ATTR_VFAT) == ATTR_VFAT && 947 (dentptr->attr & ATTR_VFAT) == ATTR_VFAT &&
949 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) { 948 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
950 prevcksum = 949 prevcksum =
951 ((dir_slot *)dentptr)->alias_checksum; 950 ((dir_slot *)dentptr)->alias_checksum;
952 951
953 get_vfatname(mydata, 952 get_vfatname(mydata,
954 root_cluster, 953 root_cluster,
955 do_fat_read_at_block, 954 do_fat_read_at_block,
956 dentptr, l_name); 955 dentptr, l_name);
957 956
958 if (dols == LS_ROOT) { 957 if (dols == LS_ROOT) {
959 char dirc; 958 char dirc;
960 int doit = 0; 959 int doit = 0;
961 int isdir = 960 int isdir =
962 (dentptr->attr & ATTR_DIR); 961 (dentptr->attr & ATTR_DIR);
963 962
964 if (isdir) { 963 if (isdir) {
965 dirs++; 964 dirs++;
966 dirc = '/'; 965 dirc = '/';
967 doit = 1; 966 doit = 1;
968 } else { 967 } else {
969 dirc = ' '; 968 dirc = ' ';
970 if (l_name[0] != 0) { 969 if (l_name[0] != 0) {
971 files++; 970 files++;
972 doit = 1; 971 doit = 1;
973 } 972 }
974 } 973 }
975 if (doit) { 974 if (doit) {
976 if (dirc == ' ') { 975 if (dirc == ' ') {
977 printf(" %8ld %s%c\n", 976 printf(" %8u %s%c\n",
978 (long)FAT2CPU32(dentptr->size), 977 FAT2CPU32(dentptr->size),
979 l_name, 978 l_name,
980 dirc); 979 dirc);
981 } else { 980 } else {
982 printf(" %s%c\n", 981 printf(" %s%c\n",
983 l_name, 982 l_name,
984 dirc); 983 dirc);
985 } 984 }
986 } 985 }
987 dentptr++; 986 dentptr++;
988 continue; 987 continue;
989 } 988 }
990 debug("Rootvfatname: |%s|\n", 989 debug("Rootvfatname: |%s|\n",
991 l_name); 990 l_name);
992 } else { 991 } else {
993 /* Volume label or VFAT entry */ 992 /* Volume label or VFAT entry */
994 dentptr++; 993 dentptr++;
995 continue; 994 continue;
996 } 995 }
997 } else if (dentptr->name[0] == 0) { 996 } else if (dentptr->name[0] == 0) {
998 debug("RootDentname == NULL - %d\n", i); 997 debug("RootDentname == NULL - %d\n", i);
999 if (dols == LS_ROOT) { 998 if (dols == LS_ROOT) {
1000 printf("\n%d file(s), %d dir(s)\n\n", 999 printf("\n%d file(s), %d dir(s)\n\n",
1001 files, dirs); 1000 files, dirs);
1002 ret = 0; 1001 ret = 0;
1003 } 1002 }
1004 goto exit; 1003 goto exit;
1005 } 1004 }
1006 else if (vfat_enabled && 1005 else if (vfat_enabled &&
1007 dols == LS_ROOT && csum == prevcksum) { 1006 dols == LS_ROOT && csum == prevcksum) {
1008 prevcksum = 0xffff; 1007 prevcksum = 0xffff;
1009 dentptr++; 1008 dentptr++;
1010 continue; 1009 continue;
1011 } 1010 }
1012 1011
1013 get_name(dentptr, s_name); 1012 get_name(dentptr, s_name);
1014 1013
1015 if (dols == LS_ROOT) { 1014 if (dols == LS_ROOT) {
1016 int isdir = (dentptr->attr & ATTR_DIR); 1015 int isdir = (dentptr->attr & ATTR_DIR);
1017 char dirc; 1016 char dirc;
1018 int doit = 0; 1017 int doit = 0;
1019 1018
1020 if (isdir) { 1019 if (isdir) {
1021 dirc = '/'; 1020 dirc = '/';
1022 if (s_name[0] != 0) { 1021 if (s_name[0] != 0) {
1023 dirs++; 1022 dirs++;
1024 doit = 1; 1023 doit = 1;
1025 } 1024 }
1026 } else { 1025 } else {
1027 dirc = ' '; 1026 dirc = ' ';
1028 if (s_name[0] != 0) { 1027 if (s_name[0] != 0) {
1029 files++; 1028 files++;
1030 doit = 1; 1029 doit = 1;
1031 } 1030 }
1032 } 1031 }
1033 if (doit) { 1032 if (doit) {
1034 if (dirc == ' ') { 1033 if (dirc == ' ') {
1035 printf(" %8ld %s%c\n", 1034 printf(" %8u %s%c\n",
1036 (long)FAT2CPU32(dentptr->size), 1035 FAT2CPU32(dentptr->size),
1037 s_name, dirc); 1036 s_name, dirc);
1038 } else { 1037 } else {
1039 printf(" %s%c\n", 1038 printf(" %s%c\n",
1040 s_name, dirc); 1039 s_name, dirc);
1041 } 1040 }
1042 } 1041 }
1043 dentptr++; 1042 dentptr++;
1044 continue; 1043 continue;
1045 } 1044 }
1046 1045
1047 if (strcmp(fnamecopy, s_name) 1046 if (strcmp(fnamecopy, s_name)
1048 && strcmp(fnamecopy, l_name)) { 1047 && strcmp(fnamecopy, l_name)) {
1049 debug("RootMismatch: |%s|%s|\n", s_name, 1048 debug("RootMismatch: |%s|%s|\n", s_name,
1050 l_name); 1049 l_name);
1051 dentptr++; 1050 dentptr++;
1052 continue; 1051 continue;
1053 } 1052 }
1054 1053
1055 if (isdir && !(dentptr->attr & ATTR_DIR)) 1054 if (isdir && !(dentptr->attr & ATTR_DIR))
1056 goto exit; 1055 goto exit;
1057 1056
1058 debug("RootName: %s", s_name); 1057 debug("RootName: %s", s_name);
1059 debug(", start: 0x%x", START(dentptr)); 1058 debug(", start: 0x%x", START(dentptr));
1060 debug(", size: 0x%x %s\n", 1059 debug(", size: 0x%x %s\n",
1061 FAT2CPU32(dentptr->size), 1060 FAT2CPU32(dentptr->size),
1062 isdir ? "(DIR)" : ""); 1061 isdir ? "(DIR)" : "");
1063 1062
1064 goto rootdir_done; /* We got a match */ 1063 goto rootdir_done; /* We got a match */
1065 } 1064 }
1066 debug("END LOOP: j=%d clust_size=%d\n", j, 1065 debug("END LOOP: j=%d clust_size=%d\n", j,
1067 mydata->clust_size); 1066 mydata->clust_size);
1068 1067
1069 /* 1068 /*
1070 * On FAT32 we must fetch the FAT entries for the next 1069 * On FAT32 we must fetch the FAT entries for the next
1071 * root directory clusters when a cluster has been 1070 * root directory clusters when a cluster has been
1072 * completely processed. 1071 * completely processed.
1073 */ 1072 */
1074 ++j; 1073 ++j;
1075 int rootdir_end = 0; 1074 int rootdir_end = 0;
1076 if (mydata->fatsize == 32) { 1075 if (mydata->fatsize == 32) {
1077 if (j == mydata->clust_size) { 1076 if (j == mydata->clust_size) {
1078 int nxtsect = 0; 1077 int nxtsect = 0;
1079 int nxt_clust = 0; 1078 int nxt_clust = 0;
1080 1079
1081 nxt_clust = get_fatent(mydata, root_cluster); 1080 nxt_clust = get_fatent(mydata, root_cluster);
1082 rootdir_end = CHECK_CLUST(nxt_clust, 32); 1081 rootdir_end = CHECK_CLUST(nxt_clust, 32);
1083 1082
1084 nxtsect = mydata->data_begin + 1083 nxtsect = mydata->data_begin +
1085 (nxt_clust * mydata->clust_size); 1084 (nxt_clust * mydata->clust_size);
1086 1085
1087 root_cluster = nxt_clust; 1086 root_cluster = nxt_clust;
1088 1087
1089 cursect = nxtsect; 1088 cursect = nxtsect;
1090 j = 0; 1089 j = 0;
1091 } 1090 }
1092 } else { 1091 } else {
1093 if (j == PREFETCH_BLOCKS) 1092 if (j == PREFETCH_BLOCKS)
1094 j = 0; 1093 j = 0;
1095 1094
1096 rootdir_end = (++cursect - mydata->rootdir_sect >= 1095 rootdir_end = (++cursect - mydata->rootdir_sect >=
1097 rootdir_size); 1096 rootdir_size);
1098 } 1097 }
1099 1098
1100 /* If end of rootdir reached */ 1099 /* If end of rootdir reached */
1101 if (rootdir_end) { 1100 if (rootdir_end) {
1102 if (dols == LS_ROOT) { 1101 if (dols == LS_ROOT) {
1103 printf("\n%d file(s), %d dir(s)\n\n", 1102 printf("\n%d file(s), %d dir(s)\n\n",
1104 files, dirs); 1103 files, dirs);
1105 ret = 0; 1104 *size = 0;
1106 } 1105 }
1107 goto exit; 1106 goto exit;
1108 } 1107 }
1109 } 1108 }
1110 rootdir_done: 1109 rootdir_done:
1111 1110
1112 firsttime = 1; 1111 firsttime = 1;
1113 1112
1114 while (isdir) { 1113 while (isdir) {
1115 int startsect = mydata->data_begin 1114 int startsect = mydata->data_begin
1116 + START(dentptr) * mydata->clust_size; 1115 + START(dentptr) * mydata->clust_size;
1117 dir_entry dent; 1116 dir_entry dent;
1118 char *nextname = NULL; 1117 char *nextname = NULL;
1119 1118
1120 dent = *dentptr; 1119 dent = *dentptr;
1121 dentptr = &dent; 1120 dentptr = &dent;
1122 1121
1123 idx = dirdelim(subname); 1122 idx = dirdelim(subname);
1124 1123
1125 if (idx >= 0) { 1124 if (idx >= 0) {
1126 subname[idx] = '\0'; 1125 subname[idx] = '\0';
1127 nextname = subname + idx + 1; 1126 nextname = subname + idx + 1;
1128 /* Handle multiple delimiters */ 1127 /* Handle multiple delimiters */
1129 while (ISDIRDELIM(*nextname)) 1128 while (ISDIRDELIM(*nextname))
1130 nextname++; 1129 nextname++;
1131 if (dols && *nextname == '\0') 1130 if (dols && *nextname == '\0')
1132 firsttime = 0; 1131 firsttime = 0;
1133 } else { 1132 } else {
1134 if (dols && firsttime) { 1133 if (dols && firsttime) {
1135 firsttime = 0; 1134 firsttime = 0;
1136 } else { 1135 } else {
1137 isdir = 0; 1136 isdir = 0;
1138 } 1137 }
1139 } 1138 }
1140 1139
1141 if (get_dentfromdir(mydata, startsect, subname, dentptr, 1140 if (get_dentfromdir(mydata, startsect, subname, dentptr,
1142 isdir ? 0 : dols) == NULL) { 1141 isdir ? 0 : dols) == NULL) {
1143 if (dols && !isdir) 1142 if (dols && !isdir)
1144 ret = 0; 1143 *size = 0;
1145 goto exit; 1144 goto exit;
1146 } 1145 }
1147 1146
1148 if (isdir && !(dentptr->attr & ATTR_DIR)) 1147 if (isdir && !(dentptr->attr & ATTR_DIR))
1149 goto exit; 1148 goto exit;
1150 1149
1151 if (idx >= 0) 1150 if (idx >= 0)
1152 subname = nextname; 1151 subname = nextname;
1153 } 1152 }
1154 1153
1155 if (dogetsize) 1154 if (dogetsize) {
1156 ret = FAT2CPU32(dentptr->size); 1155 *size = FAT2CPU32(dentptr->size);
1157 else 1156 ret = 0;
1158 ret = get_contents(mydata, dentptr, pos, buffer, maxsize); 1157 } else {
1159 debug("Size: %d, got: %ld\n", FAT2CPU32(dentptr->size), ret); 1158 ret = get_contents(mydata, dentptr, pos, buffer, maxsize, size);
1159 }
1160 debug("Size: %u, got: %llu\n", FAT2CPU32(dentptr->size), *size);
1160 1161
1161 exit: 1162 exit:
1162 free(mydata->fatbuf); 1163 free(mydata->fatbuf);
1163 return ret; 1164 return ret;
1164 } 1165 }
1165 1166
1166 long 1167 int do_fat_read(const char *filename, void *buffer, loff_t maxsize, int dols,
1167 do_fat_read(const char *filename, void *buffer, unsigned long maxsize, int dols) 1168 loff_t *actread)
1168 { 1169 {
1169 return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0); 1170 return do_fat_read_at(filename, 0, buffer, maxsize, dols, 0, actread);
1170 } 1171 }
1171 1172
1172 int file_fat_detectfs(void) 1173 int file_fat_detectfs(void)
1173 { 1174 {
1174 boot_sector bs; 1175 boot_sector bs;
1175 volume_info volinfo; 1176 volume_info volinfo;
1176 int fatsize; 1177 int fatsize;
1177 char vol_label[12]; 1178 char vol_label[12];
1178 1179
1179 if (cur_dev == NULL) { 1180 if (cur_dev == NULL) {
1180 printf("No current device\n"); 1181 printf("No current device\n");
1181 return 1; 1182 return 1;
1182 } 1183 }
1183 1184
1184 #if defined(CONFIG_CMD_IDE) || \ 1185 #if defined(CONFIG_CMD_IDE) || \
1185 defined(CONFIG_CMD_SATA) || \ 1186 defined(CONFIG_CMD_SATA) || \
1186 defined(CONFIG_CMD_SCSI) || \ 1187 defined(CONFIG_CMD_SCSI) || \
1187 defined(CONFIG_CMD_USB) || \ 1188 defined(CONFIG_CMD_USB) || \
1188 defined(CONFIG_MMC) 1189 defined(CONFIG_MMC)
1189 printf("Interface: "); 1190 printf("Interface: ");
1190 switch (cur_dev->if_type) { 1191 switch (cur_dev->if_type) {
1191 case IF_TYPE_IDE: 1192 case IF_TYPE_IDE:
1192 printf("IDE"); 1193 printf("IDE");
1193 break; 1194 break;
1194 case IF_TYPE_SATA: 1195 case IF_TYPE_SATA:
1195 printf("SATA"); 1196 printf("SATA");
1196 break; 1197 break;
1197 case IF_TYPE_SCSI: 1198 case IF_TYPE_SCSI:
1198 printf("SCSI"); 1199 printf("SCSI");
1199 break; 1200 break;
1200 case IF_TYPE_ATAPI: 1201 case IF_TYPE_ATAPI:
1201 printf("ATAPI"); 1202 printf("ATAPI");
1202 break; 1203 break;
1203 case IF_TYPE_USB: 1204 case IF_TYPE_USB:
1204 printf("USB"); 1205 printf("USB");
1205 break; 1206 break;
1206 case IF_TYPE_DOC: 1207 case IF_TYPE_DOC:
1207 printf("DOC"); 1208 printf("DOC");
1208 break; 1209 break;
1209 case IF_TYPE_MMC: 1210 case IF_TYPE_MMC:
1210 printf("MMC"); 1211 printf("MMC");
1211 break; 1212 break;
1212 default: 1213 default:
1213 printf("Unknown"); 1214 printf("Unknown");
1214 } 1215 }
1215 1216
1216 printf("\n Device %d: ", cur_dev->dev); 1217 printf("\n Device %d: ", cur_dev->dev);
1217 dev_print(cur_dev); 1218 dev_print(cur_dev);
1218 #endif 1219 #endif
1219 1220
1220 if (read_bootsectandvi(&bs, &volinfo, &fatsize)) { 1221 if (read_bootsectandvi(&bs, &volinfo, &fatsize)) {
1221 printf("\nNo valid FAT fs found\n"); 1222 printf("\nNo valid FAT fs found\n");
1222 return 1; 1223 return 1;
1223 } 1224 }
1224 1225
1225 memcpy(vol_label, volinfo.volume_label, 11); 1226 memcpy(vol_label, volinfo.volume_label, 11);
1226 vol_label[11] = '\0'; 1227 vol_label[11] = '\0';
1227 volinfo.fs_type[5] = '\0'; 1228 volinfo.fs_type[5] = '\0';
1228 1229
1229 printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label); 1230 printf("Filesystem: %s \"%s\"\n", volinfo.fs_type, vol_label);
1230 1231
1231 return 0; 1232 return 0;
1232 } 1233 }
1233 1234
1234 int file_fat_ls(const char *dir) 1235 int file_fat_ls(const char *dir)
1235 { 1236 {
1236 return do_fat_read(dir, NULL, 0, LS_YES); 1237 loff_t size;
1238
1239 return do_fat_read(dir, NULL, 0, LS_YES, &size);
1237 } 1240 }
1238 1241
1239 int fat_exists(const char *filename) 1242 int fat_exists(const char *filename)
1240 { 1243 {
1241 int sz; 1244 int ret;
1242 sz = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1); 1245 loff_t size;
1243 return sz >= 0; 1246
1247 ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size);
1248 return ret == 0;
1244 } 1249 }
1245 1250
1246 int fat_size(const char *filename) 1251 int fat_size(const char *filename)
1247 { 1252 {
1248 return do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1); 1253 loff_t size;
1254 int ret;
1255
1256 ret = do_fat_read_at(filename, 0, NULL, 0, LS_NO, 1, &size);
1257 if (ret)
1258 return ret;
1259 else
1260 return size;
1249 } 1261 }
1250 1262
1251 long file_fat_read_at(const char *filename, unsigned long pos, void *buffer, 1263 int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
1252 unsigned long maxsize) 1264 loff_t maxsize, loff_t *actread)
1253 { 1265 {
1254 printf("reading %s\n", filename); 1266 printf("reading %s\n", filename);
1255 return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0); 1267 return do_fat_read_at(filename, pos, buffer, maxsize, LS_NO, 0,
1268 actread);
1256 } 1269 }
1257 1270
1258 long file_fat_read(const char *filename, void *buffer, unsigned long maxsize) 1271 int file_fat_read(const char *filename, void *buffer, int maxsize)
1259 { 1272 {
1260 return file_fat_read_at(filename, 0, buffer, maxsize); 1273 loff_t actread;
1274 int ret;
1275
1276 ret = file_fat_read_at(filename, 0, buffer, maxsize, &actread);
1277 if (ret)
1278 return ret;
1279 else
1280 return actread;
1261 } 1281 }
1262 1282
1263 int fat_read_file(const char *filename, void *buf, int offset, int len) 1283 int fat_read_file(const char *filename, void *buf, int offset, int len)
1264 { 1284 {
1265 int len_read; 1285 int ret;
1286 loff_t actread;
1266 1287
1267 len_read = file_fat_read_at(filename, offset, buf, len); 1288 ret = file_fat_read_at(filename, offset, buf, len, &actread);
1268 if (len_read == -1) { 1289 if (ret) {
1269 printf("** Unable to read file %s **\n", filename); 1290 printf("** Unable to read file %s **\n", filename);
1270 return -1; 1291 return ret;
1271 } 1292 }
1272 1293
1273 return len_read; 1294 return actread;
1274 } 1295 }
1275 1296
1276 void fat_close(void) 1297 void fat_close(void)
1277 { 1298 {
1 /* 1 /*
2 * fat_write.c 2 * fat_write.c
3 * 3 *
4 * R/W (V)FAT 12/16/32 filesystem implementation by Donggeun Kim 4 * R/W (V)FAT 12/16/32 filesystem implementation by Donggeun Kim
5 * 5 *
6 * SPDX-License-Identifier: GPL-2.0+ 6 * SPDX-License-Identifier: GPL-2.0+
7 */ 7 */
8 8
9 #include <common.h> 9 #include <common.h>
10 #include <command.h> 10 #include <command.h>
11 #include <config.h> 11 #include <config.h>
12 #include <fat.h> 12 #include <fat.h>
13 #include <asm/byteorder.h> 13 #include <asm/byteorder.h>
14 #include <part.h> 14 #include <part.h>
15 #include <linux/ctype.h> 15 #include <linux/ctype.h>
16 #include "fat.c" 16 #include "fat.c"
17 17
18 static void uppercase(char *str, int len) 18 static void uppercase(char *str, int len)
19 { 19 {
20 int i; 20 int i;
21 21
22 for (i = 0; i < len; i++) { 22 for (i = 0; i < len; i++) {
23 *str = toupper(*str); 23 *str = toupper(*str);
24 str++; 24 str++;
25 } 25 }
26 } 26 }
27 27
28 static int total_sector; 28 static int total_sector;
29 static int disk_write(__u32 block, __u32 nr_blocks, void *buf) 29 static int disk_write(__u32 block, __u32 nr_blocks, void *buf)
30 { 30 {
31 if (!cur_dev || !cur_dev->block_write) 31 if (!cur_dev || !cur_dev->block_write)
32 return -1; 32 return -1;
33 33
34 if (cur_part_info.start + block + nr_blocks > 34 if (cur_part_info.start + block + nr_blocks >
35 cur_part_info.start + total_sector) { 35 cur_part_info.start + total_sector) {
36 printf("error: overflow occurs\n"); 36 printf("error: overflow occurs\n");
37 return -1; 37 return -1;
38 } 38 }
39 39
40 return cur_dev->block_write(cur_dev->dev, 40 return cur_dev->block_write(cur_dev->dev,
41 cur_part_info.start + block, nr_blocks, buf); 41 cur_part_info.start + block, nr_blocks, buf);
42 } 42 }
43 43
44 /* 44 /*
45 * Set short name in directory entry 45 * Set short name in directory entry
46 */ 46 */
47 static void set_name(dir_entry *dirent, const char *filename) 47 static void set_name(dir_entry *dirent, const char *filename)
48 { 48 {
49 char s_name[VFAT_MAXLEN_BYTES]; 49 char s_name[VFAT_MAXLEN_BYTES];
50 char *period; 50 char *period;
51 int period_location, len, i, ext_num; 51 int period_location, len, i, ext_num;
52 52
53 if (filename == NULL) 53 if (filename == NULL)
54 return; 54 return;
55 55
56 len = strlen(filename); 56 len = strlen(filename);
57 if (len == 0) 57 if (len == 0)
58 return; 58 return;
59 59
60 strcpy(s_name, filename); 60 strcpy(s_name, filename);
61 uppercase(s_name, len); 61 uppercase(s_name, len);
62 62
63 period = strchr(s_name, '.'); 63 period = strchr(s_name, '.');
64 if (period == NULL) { 64 if (period == NULL) {
65 period_location = len; 65 period_location = len;
66 ext_num = 0; 66 ext_num = 0;
67 } else { 67 } else {
68 period_location = period - s_name; 68 period_location = period - s_name;
69 ext_num = len - period_location - 1; 69 ext_num = len - period_location - 1;
70 } 70 }
71 71
72 /* Pad spaces when the length of file name is shorter than eight */ 72 /* Pad spaces when the length of file name is shorter than eight */
73 if (period_location < 8) { 73 if (period_location < 8) {
74 memcpy(dirent->name, s_name, period_location); 74 memcpy(dirent->name, s_name, period_location);
75 for (i = period_location; i < 8; i++) 75 for (i = period_location; i < 8; i++)
76 dirent->name[i] = ' '; 76 dirent->name[i] = ' ';
77 } else if (period_location == 8) { 77 } else if (period_location == 8) {
78 memcpy(dirent->name, s_name, period_location); 78 memcpy(dirent->name, s_name, period_location);
79 } else { 79 } else {
80 memcpy(dirent->name, s_name, 6); 80 memcpy(dirent->name, s_name, 6);
81 dirent->name[6] = '~'; 81 dirent->name[6] = '~';
82 dirent->name[7] = '1'; 82 dirent->name[7] = '1';
83 } 83 }
84 84
85 if (ext_num < 3) { 85 if (ext_num < 3) {
86 memcpy(dirent->ext, s_name + period_location + 1, ext_num); 86 memcpy(dirent->ext, s_name + period_location + 1, ext_num);
87 for (i = ext_num; i < 3; i++) 87 for (i = ext_num; i < 3; i++)
88 dirent->ext[i] = ' '; 88 dirent->ext[i] = ' ';
89 } else 89 } else
90 memcpy(dirent->ext, s_name + period_location + 1, 3); 90 memcpy(dirent->ext, s_name + period_location + 1, 3);
91 91
92 debug("name : %s\n", dirent->name); 92 debug("name : %s\n", dirent->name);
93 debug("ext : %s\n", dirent->ext); 93 debug("ext : %s\n", dirent->ext);
94 } 94 }
95 95
96 static __u8 num_of_fats; 96 static __u8 num_of_fats;
97 /* 97 /*
98 * Write fat buffer into block device 98 * Write fat buffer into block device
99 */ 99 */
100 static int flush_fat_buffer(fsdata *mydata) 100 static int flush_fat_buffer(fsdata *mydata)
101 { 101 {
102 int getsize = FATBUFBLOCKS; 102 int getsize = FATBUFBLOCKS;
103 __u32 fatlength = mydata->fatlength; 103 __u32 fatlength = mydata->fatlength;
104 __u8 *bufptr = mydata->fatbuf; 104 __u8 *bufptr = mydata->fatbuf;
105 __u32 startblock = mydata->fatbufnum * FATBUFBLOCKS; 105 __u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
106 106
107 startblock += mydata->fat_sect; 107 startblock += mydata->fat_sect;
108 108
109 if (getsize > fatlength) 109 if (getsize > fatlength)
110 getsize = fatlength; 110 getsize = fatlength;
111 111
112 /* Write FAT buf */ 112 /* Write FAT buf */
113 if (disk_write(startblock, getsize, bufptr) < 0) { 113 if (disk_write(startblock, getsize, bufptr) < 0) {
114 debug("error: writing FAT blocks\n"); 114 debug("error: writing FAT blocks\n");
115 return -1; 115 return -1;
116 } 116 }
117 117
118 if (num_of_fats == 2) { 118 if (num_of_fats == 2) {
119 /* Update corresponding second FAT blocks */ 119 /* Update corresponding second FAT blocks */
120 startblock += mydata->fatlength; 120 startblock += mydata->fatlength;
121 if (disk_write(startblock, getsize, bufptr) < 0) { 121 if (disk_write(startblock, getsize, bufptr) < 0) {
122 debug("error: writing second FAT blocks\n"); 122 debug("error: writing second FAT blocks\n");
123 return -1; 123 return -1;
124 } 124 }
125 } 125 }
126 126
127 return 0; 127 return 0;
128 } 128 }
129 129
130 /* 130 /*
131 * Get the entry at index 'entry' in a FAT (12/16/32) table. 131 * Get the entry at index 'entry' in a FAT (12/16/32) table.
132 * On failure 0x00 is returned. 132 * On failure 0x00 is returned.
133 * When bufnum is changed, write back the previous fatbuf to the disk. 133 * When bufnum is changed, write back the previous fatbuf to the disk.
134 */ 134 */
135 static __u32 get_fatent_value(fsdata *mydata, __u32 entry) 135 static __u32 get_fatent_value(fsdata *mydata, __u32 entry)
136 { 136 {
137 __u32 bufnum; 137 __u32 bufnum;
138 __u32 off16, offset; 138 __u32 off16, offset;
139 __u32 ret = 0x00; 139 __u32 ret = 0x00;
140 __u16 val1, val2; 140 __u16 val1, val2;
141 141
142 if (CHECK_CLUST(entry, mydata->fatsize)) { 142 if (CHECK_CLUST(entry, mydata->fatsize)) {
143 printf("Error: Invalid FAT entry: 0x%08x\n", entry); 143 printf("Error: Invalid FAT entry: 0x%08x\n", entry);
144 return ret; 144 return ret;
145 } 145 }
146 146
147 switch (mydata->fatsize) { 147 switch (mydata->fatsize) {
148 case 32: 148 case 32:
149 bufnum = entry / FAT32BUFSIZE; 149 bufnum = entry / FAT32BUFSIZE;
150 offset = entry - bufnum * FAT32BUFSIZE; 150 offset = entry - bufnum * FAT32BUFSIZE;
151 break; 151 break;
152 case 16: 152 case 16:
153 bufnum = entry / FAT16BUFSIZE; 153 bufnum = entry / FAT16BUFSIZE;
154 offset = entry - bufnum * FAT16BUFSIZE; 154 offset = entry - bufnum * FAT16BUFSIZE;
155 break; 155 break;
156 case 12: 156 case 12:
157 bufnum = entry / FAT12BUFSIZE; 157 bufnum = entry / FAT12BUFSIZE;
158 offset = entry - bufnum * FAT12BUFSIZE; 158 offset = entry - bufnum * FAT12BUFSIZE;
159 break; 159 break;
160 160
161 default: 161 default:
162 /* Unsupported FAT size */ 162 /* Unsupported FAT size */
163 return ret; 163 return ret;
164 } 164 }
165 165
166 debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n", 166 debug("FAT%d: entry: 0x%04x = %d, offset: 0x%04x = %d\n",
167 mydata->fatsize, entry, entry, offset, offset); 167 mydata->fatsize, entry, entry, offset, offset);
168 168
169 /* Read a new block of FAT entries into the cache. */ 169 /* Read a new block of FAT entries into the cache. */
170 if (bufnum != mydata->fatbufnum) { 170 if (bufnum != mydata->fatbufnum) {
171 int getsize = FATBUFBLOCKS; 171 int getsize = FATBUFBLOCKS;
172 __u8 *bufptr = mydata->fatbuf; 172 __u8 *bufptr = mydata->fatbuf;
173 __u32 fatlength = mydata->fatlength; 173 __u32 fatlength = mydata->fatlength;
174 __u32 startblock = bufnum * FATBUFBLOCKS; 174 __u32 startblock = bufnum * FATBUFBLOCKS;
175 175
176 if (getsize > fatlength) 176 if (getsize > fatlength)
177 getsize = fatlength; 177 getsize = fatlength;
178 178
179 fatlength *= mydata->sect_size; /* We want it in bytes now */ 179 fatlength *= mydata->sect_size; /* We want it in bytes now */
180 startblock += mydata->fat_sect; /* Offset from start of disk */ 180 startblock += mydata->fat_sect; /* Offset from start of disk */
181 181
182 /* Write back the fatbuf to the disk */ 182 /* Write back the fatbuf to the disk */
183 if (mydata->fatbufnum != -1) { 183 if (mydata->fatbufnum != -1) {
184 if (flush_fat_buffer(mydata) < 0) 184 if (flush_fat_buffer(mydata) < 0)
185 return -1; 185 return -1;
186 } 186 }
187 187
188 if (disk_read(startblock, getsize, bufptr) < 0) { 188 if (disk_read(startblock, getsize, bufptr) < 0) {
189 debug("Error reading FAT blocks\n"); 189 debug("Error reading FAT blocks\n");
190 return ret; 190 return ret;
191 } 191 }
192 mydata->fatbufnum = bufnum; 192 mydata->fatbufnum = bufnum;
193 } 193 }
194 194
195 /* Get the actual entry from the table */ 195 /* Get the actual entry from the table */
196 switch (mydata->fatsize) { 196 switch (mydata->fatsize) {
197 case 32: 197 case 32:
198 ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]); 198 ret = FAT2CPU32(((__u32 *) mydata->fatbuf)[offset]);
199 break; 199 break;
200 case 16: 200 case 16:
201 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]); 201 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[offset]);
202 break; 202 break;
203 case 12: 203 case 12:
204 off16 = (offset * 3) / 4; 204 off16 = (offset * 3) / 4;
205 205
206 switch (offset & 0x3) { 206 switch (offset & 0x3) {
207 case 0: 207 case 0:
208 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]); 208 ret = FAT2CPU16(((__u16 *) mydata->fatbuf)[off16]);
209 ret &= 0xfff; 209 ret &= 0xfff;
210 break; 210 break;
211 case 1: 211 case 1:
212 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 212 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
213 val1 &= 0xf000; 213 val1 &= 0xf000;
214 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]); 214 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
215 val2 &= 0x00ff; 215 val2 &= 0x00ff;
216 ret = (val2 << 4) | (val1 >> 12); 216 ret = (val2 << 4) | (val1 >> 12);
217 break; 217 break;
218 case 2: 218 case 2:
219 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 219 val1 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
220 val1 &= 0xff00; 220 val1 &= 0xff00;
221 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]); 221 val2 = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16 + 1]);
222 val2 &= 0x000f; 222 val2 &= 0x000f;
223 ret = (val2 << 8) | (val1 >> 8); 223 ret = (val2 << 8) | (val1 >> 8);
224 break; 224 break;
225 case 3: 225 case 3:
226 ret = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]); 226 ret = FAT2CPU16(((__u16 *)mydata->fatbuf)[off16]);
227 ret = (ret & 0xfff0) >> 4; 227 ret = (ret & 0xfff0) >> 4;
228 break; 228 break;
229 default: 229 default:
230 break; 230 break;
231 } 231 }
232 break; 232 break;
233 } 233 }
234 debug("FAT%d: ret: %08x, entry: %08x, offset: %04x\n", 234 debug("FAT%d: ret: %08x, entry: %08x, offset: %04x\n",
235 mydata->fatsize, ret, entry, offset); 235 mydata->fatsize, ret, entry, offset);
236 236
237 return ret; 237 return ret;
238 } 238 }
239 239
240 /* 240 /*
241 * Set the file name information from 'name' into 'slotptr', 241 * Set the file name information from 'name' into 'slotptr',
242 */ 242 */
243 static int str2slot(dir_slot *slotptr, const char *name, int *idx) 243 static int str2slot(dir_slot *slotptr, const char *name, int *idx)
244 { 244 {
245 int j, end_idx = 0; 245 int j, end_idx = 0;
246 246
247 for (j = 0; j <= 8; j += 2) { 247 for (j = 0; j <= 8; j += 2) {
248 if (name[*idx] == 0x00) { 248 if (name[*idx] == 0x00) {
249 slotptr->name0_4[j] = 0; 249 slotptr->name0_4[j] = 0;
250 slotptr->name0_4[j + 1] = 0; 250 slotptr->name0_4[j + 1] = 0;
251 end_idx++; 251 end_idx++;
252 goto name0_4; 252 goto name0_4;
253 } 253 }
254 slotptr->name0_4[j] = name[*idx]; 254 slotptr->name0_4[j] = name[*idx];
255 (*idx)++; 255 (*idx)++;
256 end_idx++; 256 end_idx++;
257 } 257 }
258 for (j = 0; j <= 10; j += 2) { 258 for (j = 0; j <= 10; j += 2) {
259 if (name[*idx] == 0x00) { 259 if (name[*idx] == 0x00) {
260 slotptr->name5_10[j] = 0; 260 slotptr->name5_10[j] = 0;
261 slotptr->name5_10[j + 1] = 0; 261 slotptr->name5_10[j + 1] = 0;
262 end_idx++; 262 end_idx++;
263 goto name5_10; 263 goto name5_10;
264 } 264 }
265 slotptr->name5_10[j] = name[*idx]; 265 slotptr->name5_10[j] = name[*idx];
266 (*idx)++; 266 (*idx)++;
267 end_idx++; 267 end_idx++;
268 } 268 }
269 for (j = 0; j <= 2; j += 2) { 269 for (j = 0; j <= 2; j += 2) {
270 if (name[*idx] == 0x00) { 270 if (name[*idx] == 0x00) {
271 slotptr->name11_12[j] = 0; 271 slotptr->name11_12[j] = 0;
272 slotptr->name11_12[j + 1] = 0; 272 slotptr->name11_12[j + 1] = 0;
273 end_idx++; 273 end_idx++;
274 goto name11_12; 274 goto name11_12;
275 } 275 }
276 slotptr->name11_12[j] = name[*idx]; 276 slotptr->name11_12[j] = name[*idx];
277 (*idx)++; 277 (*idx)++;
278 end_idx++; 278 end_idx++;
279 } 279 }
280 280
281 if (name[*idx] == 0x00) 281 if (name[*idx] == 0x00)
282 return 1; 282 return 1;
283 283
284 return 0; 284 return 0;
285 /* Not used characters are filled with 0xff 0xff */ 285 /* Not used characters are filled with 0xff 0xff */
286 name0_4: 286 name0_4:
287 for (; end_idx < 5; end_idx++) { 287 for (; end_idx < 5; end_idx++) {
288 slotptr->name0_4[end_idx * 2] = 0xff; 288 slotptr->name0_4[end_idx * 2] = 0xff;
289 slotptr->name0_4[end_idx * 2 + 1] = 0xff; 289 slotptr->name0_4[end_idx * 2 + 1] = 0xff;
290 } 290 }
291 end_idx = 5; 291 end_idx = 5;
292 name5_10: 292 name5_10:
293 end_idx -= 5; 293 end_idx -= 5;
294 for (; end_idx < 6; end_idx++) { 294 for (; end_idx < 6; end_idx++) {
295 slotptr->name5_10[end_idx * 2] = 0xff; 295 slotptr->name5_10[end_idx * 2] = 0xff;
296 slotptr->name5_10[end_idx * 2 + 1] = 0xff; 296 slotptr->name5_10[end_idx * 2 + 1] = 0xff;
297 } 297 }
298 end_idx = 11; 298 end_idx = 11;
299 name11_12: 299 name11_12:
300 end_idx -= 11; 300 end_idx -= 11;
301 for (; end_idx < 2; end_idx++) { 301 for (; end_idx < 2; end_idx++) {
302 slotptr->name11_12[end_idx * 2] = 0xff; 302 slotptr->name11_12[end_idx * 2] = 0xff;
303 slotptr->name11_12[end_idx * 2 + 1] = 0xff; 303 slotptr->name11_12[end_idx * 2 + 1] = 0xff;
304 } 304 }
305 305
306 return 1; 306 return 1;
307 } 307 }
308 308
309 static int is_next_clust(fsdata *mydata, dir_entry *dentptr); 309 static int is_next_clust(fsdata *mydata, dir_entry *dentptr);
310 static void flush_dir_table(fsdata *mydata, dir_entry **dentptr); 310 static void flush_dir_table(fsdata *mydata, dir_entry **dentptr);
311 311
312 /* 312 /*
313 * Fill dir_slot entries with appropriate name, id, and attr 313 * Fill dir_slot entries with appropriate name, id, and attr
314 * The real directory entry is returned by 'dentptr' 314 * The real directory entry is returned by 'dentptr'
315 */ 315 */
316 static void 316 static void
317 fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name) 317 fill_dir_slot(fsdata *mydata, dir_entry **dentptr, const char *l_name)
318 { 318 {
319 dir_slot *slotptr = (dir_slot *)get_contents_vfatname_block; 319 dir_slot *slotptr = (dir_slot *)get_contents_vfatname_block;
320 __u8 counter = 0, checksum; 320 __u8 counter = 0, checksum;
321 int idx = 0, ret; 321 int idx = 0, ret;
322 char s_name[16]; 322 char s_name[16];
323 323
324 /* Get short file name and checksum value */ 324 /* Get short file name and checksum value */
325 strncpy(s_name, (*dentptr)->name, 16); 325 strncpy(s_name, (*dentptr)->name, 16);
326 checksum = mkcksum((*dentptr)->name, (*dentptr)->ext); 326 checksum = mkcksum((*dentptr)->name, (*dentptr)->ext);
327 327
328 do { 328 do {
329 memset(slotptr, 0x00, sizeof(dir_slot)); 329 memset(slotptr, 0x00, sizeof(dir_slot));
330 ret = str2slot(slotptr, l_name, &idx); 330 ret = str2slot(slotptr, l_name, &idx);
331 slotptr->id = ++counter; 331 slotptr->id = ++counter;
332 slotptr->attr = ATTR_VFAT; 332 slotptr->attr = ATTR_VFAT;
333 slotptr->alias_checksum = checksum; 333 slotptr->alias_checksum = checksum;
334 slotptr++; 334 slotptr++;
335 } while (ret == 0); 335 } while (ret == 0);
336 336
337 slotptr--; 337 slotptr--;
338 slotptr->id |= LAST_LONG_ENTRY_MASK; 338 slotptr->id |= LAST_LONG_ENTRY_MASK;
339 339
340 while (counter >= 1) { 340 while (counter >= 1) {
341 if (is_next_clust(mydata, *dentptr)) { 341 if (is_next_clust(mydata, *dentptr)) {
342 /* A new cluster is allocated for directory table */ 342 /* A new cluster is allocated for directory table */
343 flush_dir_table(mydata, dentptr); 343 flush_dir_table(mydata, dentptr);
344 } 344 }
345 memcpy(*dentptr, slotptr, sizeof(dir_slot)); 345 memcpy(*dentptr, slotptr, sizeof(dir_slot));
346 (*dentptr)++; 346 (*dentptr)++;
347 slotptr--; 347 slotptr--;
348 counter--; 348 counter--;
349 } 349 }
350 350
351 if (is_next_clust(mydata, *dentptr)) { 351 if (is_next_clust(mydata, *dentptr)) {
352 /* A new cluster is allocated for directory table */ 352 /* A new cluster is allocated for directory table */
353 flush_dir_table(mydata, dentptr); 353 flush_dir_table(mydata, dentptr);
354 } 354 }
355 } 355 }
356 356
357 static __u32 dir_curclust; 357 static __u32 dir_curclust;
358 358
359 /* 359 /*
360 * Extract the full long filename starting at 'retdent' (which is really 360 * Extract the full long filename starting at 'retdent' (which is really
361 * a slot) into 'l_name'. If successful also copy the real directory entry 361 * a slot) into 'l_name'. If successful also copy the real directory entry
362 * into 'retdent' 362 * into 'retdent'
363 * If additional adjacent cluster for directory entries is read into memory, 363 * If additional adjacent cluster for directory entries is read into memory,
364 * then 'get_contents_vfatname_block' is copied into 'get_dentfromdir_block' and 364 * then 'get_contents_vfatname_block' is copied into 'get_dentfromdir_block' and
365 * the location of the real directory entry is returned by 'retdent' 365 * the location of the real directory entry is returned by 'retdent'
366 * Return 0 on success, -1 otherwise. 366 * Return 0 on success, -1 otherwise.
367 */ 367 */
368 static int 368 static int
369 get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster, 369 get_long_file_name(fsdata *mydata, int curclust, __u8 *cluster,
370 dir_entry **retdent, char *l_name) 370 dir_entry **retdent, char *l_name)
371 { 371 {
372 dir_entry *realdent; 372 dir_entry *realdent;
373 dir_slot *slotptr = (dir_slot *)(*retdent); 373 dir_slot *slotptr = (dir_slot *)(*retdent);
374 dir_slot *slotptr2 = NULL; 374 dir_slot *slotptr2 = NULL;
375 __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ? 375 __u8 *buflimit = cluster + mydata->sect_size * ((curclust == 0) ?
376 PREFETCH_BLOCKS : 376 PREFETCH_BLOCKS :
377 mydata->clust_size); 377 mydata->clust_size);
378 __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff; 378 __u8 counter = (slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff;
379 int idx = 0, cur_position = 0; 379 int idx = 0, cur_position = 0;
380 380
381 if (counter > VFAT_MAXSEQ) { 381 if (counter > VFAT_MAXSEQ) {
382 debug("Error: VFAT name is too long\n"); 382 debug("Error: VFAT name is too long\n");
383 return -1; 383 return -1;
384 } 384 }
385 385
386 while ((__u8 *)slotptr < buflimit) { 386 while ((__u8 *)slotptr < buflimit) {
387 if (counter == 0) 387 if (counter == 0)
388 break; 388 break;
389 if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter) 389 if (((slotptr->id & ~LAST_LONG_ENTRY_MASK) & 0xff) != counter)
390 return -1; 390 return -1;
391 slotptr++; 391 slotptr++;
392 counter--; 392 counter--;
393 } 393 }
394 394
395 if ((__u8 *)slotptr >= buflimit) { 395 if ((__u8 *)slotptr >= buflimit) {
396 if (curclust == 0) 396 if (curclust == 0)
397 return -1; 397 return -1;
398 curclust = get_fatent_value(mydata, dir_curclust); 398 curclust = get_fatent_value(mydata, dir_curclust);
399 if (CHECK_CLUST(curclust, mydata->fatsize)) { 399 if (CHECK_CLUST(curclust, mydata->fatsize)) {
400 debug("curclust: 0x%x\n", curclust); 400 debug("curclust: 0x%x\n", curclust);
401 printf("Invalid FAT entry\n"); 401 printf("Invalid FAT entry\n");
402 return -1; 402 return -1;
403 } 403 }
404 404
405 dir_curclust = curclust; 405 dir_curclust = curclust;
406 406
407 if (get_cluster(mydata, curclust, get_contents_vfatname_block, 407 if (get_cluster(mydata, curclust, get_contents_vfatname_block,
408 mydata->clust_size * mydata->sect_size) != 0) { 408 mydata->clust_size * mydata->sect_size) != 0) {
409 debug("Error: reading directory block\n"); 409 debug("Error: reading directory block\n");
410 return -1; 410 return -1;
411 } 411 }
412 412
413 slotptr2 = (dir_slot *)get_contents_vfatname_block; 413 slotptr2 = (dir_slot *)get_contents_vfatname_block;
414 while (counter > 0) { 414 while (counter > 0) {
415 if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK) 415 if (((slotptr2->id & ~LAST_LONG_ENTRY_MASK)
416 & 0xff) != counter) 416 & 0xff) != counter)
417 return -1; 417 return -1;
418 slotptr2++; 418 slotptr2++;
419 counter--; 419 counter--;
420 } 420 }
421 421
422 /* Save the real directory entry */ 422 /* Save the real directory entry */
423 realdent = (dir_entry *)slotptr2; 423 realdent = (dir_entry *)slotptr2;
424 while ((__u8 *)slotptr2 > get_contents_vfatname_block) { 424 while ((__u8 *)slotptr2 > get_contents_vfatname_block) {
425 slotptr2--; 425 slotptr2--;
426 slot2str(slotptr2, l_name, &idx); 426 slot2str(slotptr2, l_name, &idx);
427 } 427 }
428 } else { 428 } else {
429 /* Save the real directory entry */ 429 /* Save the real directory entry */
430 realdent = (dir_entry *)slotptr; 430 realdent = (dir_entry *)slotptr;
431 } 431 }
432 432
433 do { 433 do {
434 slotptr--; 434 slotptr--;
435 if (slot2str(slotptr, l_name, &idx)) 435 if (slot2str(slotptr, l_name, &idx))
436 break; 436 break;
437 } while (!(slotptr->id & LAST_LONG_ENTRY_MASK)); 437 } while (!(slotptr->id & LAST_LONG_ENTRY_MASK));
438 438
439 l_name[idx] = '\0'; 439 l_name[idx] = '\0';
440 if (*l_name == DELETED_FLAG) 440 if (*l_name == DELETED_FLAG)
441 *l_name = '\0'; 441 *l_name = '\0';
442 else if (*l_name == aRING) 442 else if (*l_name == aRING)
443 *l_name = DELETED_FLAG; 443 *l_name = DELETED_FLAG;
444 downcase(l_name); 444 downcase(l_name);
445 445
446 /* Return the real directory entry */ 446 /* Return the real directory entry */
447 *retdent = realdent; 447 *retdent = realdent;
448 448
449 if (slotptr2) { 449 if (slotptr2) {
450 memcpy(get_dentfromdir_block, get_contents_vfatname_block, 450 memcpy(get_dentfromdir_block, get_contents_vfatname_block,
451 mydata->clust_size * mydata->sect_size); 451 mydata->clust_size * mydata->sect_size);
452 cur_position = (__u8 *)realdent - get_contents_vfatname_block; 452 cur_position = (__u8 *)realdent - get_contents_vfatname_block;
453 *retdent = (dir_entry *) &get_dentfromdir_block[cur_position]; 453 *retdent = (dir_entry *) &get_dentfromdir_block[cur_position];
454 } 454 }
455 455
456 return 0; 456 return 0;
457 } 457 }
458 458
459 /* 459 /*
460 * Set the entry at index 'entry' in a FAT (16/32) table. 460 * Set the entry at index 'entry' in a FAT (16/32) table.
461 */ 461 */
462 static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value) 462 static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
463 { 463 {
464 __u32 bufnum, offset; 464 __u32 bufnum, offset;
465 465
466 switch (mydata->fatsize) { 466 switch (mydata->fatsize) {
467 case 32: 467 case 32:
468 bufnum = entry / FAT32BUFSIZE; 468 bufnum = entry / FAT32BUFSIZE;
469 offset = entry - bufnum * FAT32BUFSIZE; 469 offset = entry - bufnum * FAT32BUFSIZE;
470 break; 470 break;
471 case 16: 471 case 16:
472 bufnum = entry / FAT16BUFSIZE; 472 bufnum = entry / FAT16BUFSIZE;
473 offset = entry - bufnum * FAT16BUFSIZE; 473 offset = entry - bufnum * FAT16BUFSIZE;
474 break; 474 break;
475 default: 475 default:
476 /* Unsupported FAT size */ 476 /* Unsupported FAT size */
477 return -1; 477 return -1;
478 } 478 }
479 479
480 /* Read a new block of FAT entries into the cache. */ 480 /* Read a new block of FAT entries into the cache. */
481 if (bufnum != mydata->fatbufnum) { 481 if (bufnum != mydata->fatbufnum) {
482 int getsize = FATBUFBLOCKS; 482 int getsize = FATBUFBLOCKS;
483 __u8 *bufptr = mydata->fatbuf; 483 __u8 *bufptr = mydata->fatbuf;
484 __u32 fatlength = mydata->fatlength; 484 __u32 fatlength = mydata->fatlength;
485 __u32 startblock = bufnum * FATBUFBLOCKS; 485 __u32 startblock = bufnum * FATBUFBLOCKS;
486 486
487 fatlength *= mydata->sect_size; 487 fatlength *= mydata->sect_size;
488 startblock += mydata->fat_sect; 488 startblock += mydata->fat_sect;
489 489
490 if (getsize > fatlength) 490 if (getsize > fatlength)
491 getsize = fatlength; 491 getsize = fatlength;
492 492
493 if (mydata->fatbufnum != -1) { 493 if (mydata->fatbufnum != -1) {
494 if (flush_fat_buffer(mydata) < 0) 494 if (flush_fat_buffer(mydata) < 0)
495 return -1; 495 return -1;
496 } 496 }
497 497
498 if (disk_read(startblock, getsize, bufptr) < 0) { 498 if (disk_read(startblock, getsize, bufptr) < 0) {
499 debug("Error reading FAT blocks\n"); 499 debug("Error reading FAT blocks\n");
500 return -1; 500 return -1;
501 } 501 }
502 mydata->fatbufnum = bufnum; 502 mydata->fatbufnum = bufnum;
503 } 503 }
504 504
505 /* Set the actual entry */ 505 /* Set the actual entry */
506 switch (mydata->fatsize) { 506 switch (mydata->fatsize) {
507 case 32: 507 case 32:
508 ((__u32 *) mydata->fatbuf)[offset] = cpu_to_le32(entry_value); 508 ((__u32 *) mydata->fatbuf)[offset] = cpu_to_le32(entry_value);
509 break; 509 break;
510 case 16: 510 case 16:
511 ((__u16 *) mydata->fatbuf)[offset] = cpu_to_le16(entry_value); 511 ((__u16 *) mydata->fatbuf)[offset] = cpu_to_le16(entry_value);
512 break; 512 break;
513 default: 513 default:
514 return -1; 514 return -1;
515 } 515 }
516 516
517 return 0; 517 return 0;
518 } 518 }
519 519
520 /* 520 /*
521 * Determine the entry value at index 'entry' in a FAT (16/32) table 521 * Determine the entry value at index 'entry' in a FAT (16/32) table
522 */ 522 */
523 static __u32 determine_fatent(fsdata *mydata, __u32 entry) 523 static __u32 determine_fatent(fsdata *mydata, __u32 entry)
524 { 524 {
525 __u32 next_fat, next_entry = entry + 1; 525 __u32 next_fat, next_entry = entry + 1;
526 526
527 while (1) { 527 while (1) {
528 next_fat = get_fatent_value(mydata, next_entry); 528 next_fat = get_fatent_value(mydata, next_entry);
529 if (next_fat == 0) { 529 if (next_fat == 0) {
530 set_fatent_value(mydata, entry, next_entry); 530 set_fatent_value(mydata, entry, next_entry);
531 break; 531 break;
532 } 532 }
533 next_entry++; 533 next_entry++;
534 } 534 }
535 debug("FAT%d: entry: %08x, entry_value: %04x\n", 535 debug("FAT%d: entry: %08x, entry_value: %04x\n",
536 mydata->fatsize, entry, next_entry); 536 mydata->fatsize, entry, next_entry);
537 537
538 return next_entry; 538 return next_entry;
539 } 539 }
540 540
541 /* 541 /*
542 * Write at most 'size' bytes from 'buffer' into the specified cluster. 542 * Write at most 'size' bytes from 'buffer' into the specified cluster.
543 * Return 0 on success, -1 otherwise. 543 * Return 0 on success, -1 otherwise.
544 */ 544 */
545 static int 545 static int
546 set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer, 546 set_cluster(fsdata *mydata, __u32 clustnum, __u8 *buffer,
547 unsigned long size) 547 unsigned long size)
548 { 548 {
549 int idx = 0; 549 int idx = 0;
550 __u32 startsect; 550 __u32 startsect;
551 551
552 if (clustnum > 0) 552 if (clustnum > 0)
553 startsect = mydata->data_begin + 553 startsect = mydata->data_begin +
554 clustnum * mydata->clust_size; 554 clustnum * mydata->clust_size;
555 else 555 else
556 startsect = mydata->rootdir_sect; 556 startsect = mydata->rootdir_sect;
557 557
558 debug("clustnum: %d, startsect: %d\n", clustnum, startsect); 558 debug("clustnum: %d, startsect: %d\n", clustnum, startsect);
559 559
560 if ((size / mydata->sect_size) > 0) { 560 if ((size / mydata->sect_size) > 0) {
561 if (disk_write(startsect, size / mydata->sect_size, buffer) < 0) { 561 if (disk_write(startsect, size / mydata->sect_size, buffer) < 0) {
562 debug("Error writing data\n"); 562 debug("Error writing data\n");
563 return -1; 563 return -1;
564 } 564 }
565 } 565 }
566 566
567 if (size % mydata->sect_size) { 567 if (size % mydata->sect_size) {
568 __u8 tmpbuf[mydata->sect_size]; 568 __u8 tmpbuf[mydata->sect_size];
569 569
570 idx = size / mydata->sect_size; 570 idx = size / mydata->sect_size;
571 buffer += idx * mydata->sect_size; 571 buffer += idx * mydata->sect_size;
572 memcpy(tmpbuf, buffer, size % mydata->sect_size); 572 memcpy(tmpbuf, buffer, size % mydata->sect_size);
573 573
574 if (disk_write(startsect + idx, 1, tmpbuf) < 0) { 574 if (disk_write(startsect + idx, 1, tmpbuf) < 0) {
575 debug("Error writing data\n"); 575 debug("Error writing data\n");
576 return -1; 576 return -1;
577 } 577 }
578 578
579 return 0; 579 return 0;
580 } 580 }
581 581
582 return 0; 582 return 0;
583 } 583 }
584 584
585 /* 585 /*
586 * Find the first empty cluster 586 * Find the first empty cluster
587 */ 587 */
588 static int find_empty_cluster(fsdata *mydata) 588 static int find_empty_cluster(fsdata *mydata)
589 { 589 {
590 __u32 fat_val, entry = 3; 590 __u32 fat_val, entry = 3;
591 591
592 while (1) { 592 while (1) {
593 fat_val = get_fatent_value(mydata, entry); 593 fat_val = get_fatent_value(mydata, entry);
594 if (fat_val == 0) 594 if (fat_val == 0)
595 break; 595 break;
596 entry++; 596 entry++;
597 } 597 }
598 598
599 return entry; 599 return entry;
600 } 600 }
601 601
602 /* 602 /*
603 * Write directory entries in 'get_dentfromdir_block' to block device 603 * Write directory entries in 'get_dentfromdir_block' to block device
604 */ 604 */
605 static void flush_dir_table(fsdata *mydata, dir_entry **dentptr) 605 static void flush_dir_table(fsdata *mydata, dir_entry **dentptr)
606 { 606 {
607 int dir_newclust = 0; 607 int dir_newclust = 0;
608 608
609 if (set_cluster(mydata, dir_curclust, 609 if (set_cluster(mydata, dir_curclust,
610 get_dentfromdir_block, 610 get_dentfromdir_block,
611 mydata->clust_size * mydata->sect_size) != 0) { 611 mydata->clust_size * mydata->sect_size) != 0) {
612 printf("error: wrinting directory entry\n"); 612 printf("error: wrinting directory entry\n");
613 return; 613 return;
614 } 614 }
615 dir_newclust = find_empty_cluster(mydata); 615 dir_newclust = find_empty_cluster(mydata);
616 set_fatent_value(mydata, dir_curclust, dir_newclust); 616 set_fatent_value(mydata, dir_curclust, dir_newclust);
617 if (mydata->fatsize == 32) 617 if (mydata->fatsize == 32)
618 set_fatent_value(mydata, dir_newclust, 0xffffff8); 618 set_fatent_value(mydata, dir_newclust, 0xffffff8);
619 else if (mydata->fatsize == 16) 619 else if (mydata->fatsize == 16)
620 set_fatent_value(mydata, dir_newclust, 0xfff8); 620 set_fatent_value(mydata, dir_newclust, 0xfff8);
621 621
622 dir_curclust = dir_newclust; 622 dir_curclust = dir_newclust;
623 623
624 if (flush_fat_buffer(mydata) < 0) 624 if (flush_fat_buffer(mydata) < 0)
625 return; 625 return;
626 626
627 memset(get_dentfromdir_block, 0x00, 627 memset(get_dentfromdir_block, 0x00,
628 mydata->clust_size * mydata->sect_size); 628 mydata->clust_size * mydata->sect_size);
629 629
630 *dentptr = (dir_entry *) get_dentfromdir_block; 630 *dentptr = (dir_entry *) get_dentfromdir_block;
631 } 631 }
632 632
633 /* 633 /*
634 * Set empty cluster from 'entry' to the end of a file 634 * Set empty cluster from 'entry' to the end of a file
635 */ 635 */
636 static int clear_fatent(fsdata *mydata, __u32 entry) 636 static int clear_fatent(fsdata *mydata, __u32 entry)
637 { 637 {
638 __u32 fat_val; 638 __u32 fat_val;
639 639
640 while (1) { 640 while (1) {
641 fat_val = get_fatent_value(mydata, entry); 641 fat_val = get_fatent_value(mydata, entry);
642 if (fat_val != 0) 642 if (fat_val != 0)
643 set_fatent_value(mydata, entry, 0); 643 set_fatent_value(mydata, entry, 0);
644 else 644 else
645 break; 645 break;
646 646
647 if (fat_val == 0xfffffff || fat_val == 0xffff) 647 if (fat_val == 0xfffffff || fat_val == 0xffff)
648 break; 648 break;
649 649
650 entry = fat_val; 650 entry = fat_val;
651 } 651 }
652 652
653 /* Flush fat buffer */ 653 /* Flush fat buffer */
654 if (flush_fat_buffer(mydata) < 0) 654 if (flush_fat_buffer(mydata) < 0)
655 return -1; 655 return -1;
656 656
657 return 0; 657 return 0;
658 } 658 }
659 659
660 /* 660 /*
661 * Write at most 'maxsize' bytes from 'buffer' into 661 * Write at most 'maxsize' bytes from 'buffer' into
662 * the file associated with 'dentptr' 662 * the file associated with 'dentptr'
663 * Return the number of bytes read or -1 on fatal errors. 663 * Update the number of bytes written in *gotsize and return 0
664 * or return -1 on fatal errors.
664 */ 665 */
665 static int 666 static int
666 set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer, 667 set_contents(fsdata *mydata, dir_entry *dentptr, __u8 *buffer,
667 unsigned long maxsize) 668 loff_t maxsize, loff_t *gotsize)
668 { 669 {
669 unsigned long filesize = FAT2CPU32(dentptr->size), gotsize = 0; 670 loff_t filesize = FAT2CPU32(dentptr->size);
670 unsigned int bytesperclust = mydata->clust_size * mydata->sect_size; 671 unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
671 __u32 curclust = START(dentptr); 672 __u32 curclust = START(dentptr);
672 __u32 endclust = 0, newclust = 0; 673 __u32 endclust = 0, newclust = 0;
673 unsigned long actsize; 674 loff_t actsize;
674 675
675 debug("Filesize: %ld bytes\n", filesize); 676 *gotsize = 0;
677 debug("Filesize: %llu bytes\n", filesize);
676 678
677 if (maxsize > 0 && filesize > maxsize) 679 if (maxsize > 0 && filesize > maxsize)
678 filesize = maxsize; 680 filesize = maxsize;
679 681
680 debug("%ld bytes\n", filesize); 682 debug("%llu bytes\n", filesize);
681 683
682 actsize = bytesperclust; 684 actsize = bytesperclust;
683 endclust = curclust; 685 endclust = curclust;
684 do { 686 do {
685 /* search for consecutive clusters */ 687 /* search for consecutive clusters */
686 while (actsize < filesize) { 688 while (actsize < filesize) {
687 newclust = determine_fatent(mydata, endclust); 689 newclust = determine_fatent(mydata, endclust);
688 690
689 if ((newclust - 1) != endclust) 691 if ((newclust - 1) != endclust)
690 goto getit; 692 goto getit;
691 693
692 if (CHECK_CLUST(newclust, mydata->fatsize)) { 694 if (CHECK_CLUST(newclust, mydata->fatsize)) {
693 debug("curclust: 0x%x\n", newclust); 695 debug("curclust: 0x%x\n", newclust);
694 debug("Invalid FAT entry\n"); 696 debug("Invalid FAT entry\n");
695 return gotsize; 697 return 0;
696 } 698 }
697 endclust = newclust; 699 endclust = newclust;
698 actsize += bytesperclust; 700 actsize += bytesperclust;
699 } 701 }
700 /* actsize >= file size */ 702 /* actsize >= file size */
701 actsize -= bytesperclust; 703 actsize -= bytesperclust;
702 /* set remaining clusters */ 704 /* set remaining clusters */
703 if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 705 if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
704 debug("error: writing cluster\n"); 706 debug("error: writing cluster\n");
705 return -1; 707 return -1;
706 } 708 }
707 709
708 /* set remaining bytes */ 710 /* set remaining bytes */
709 gotsize += (int)actsize; 711 *gotsize += actsize;
710 filesize -= actsize; 712 filesize -= actsize;
711 buffer += actsize; 713 buffer += actsize;
712 actsize = filesize; 714 actsize = filesize;
713 715
714 if (set_cluster(mydata, endclust, buffer, (int)actsize) != 0) { 716 if (set_cluster(mydata, endclust, buffer, (int)actsize) != 0) {
715 debug("error: writing cluster\n"); 717 debug("error: writing cluster\n");
716 return -1; 718 return -1;
717 } 719 }
718 gotsize += actsize; 720 *gotsize += actsize;
719 721
720 /* Mark end of file in FAT */ 722 /* Mark end of file in FAT */
721 if (mydata->fatsize == 16) 723 if (mydata->fatsize == 16)
722 newclust = 0xffff; 724 newclust = 0xffff;
723 else if (mydata->fatsize == 32) 725 else if (mydata->fatsize == 32)
724 newclust = 0xfffffff; 726 newclust = 0xfffffff;
725 set_fatent_value(mydata, endclust, newclust); 727 set_fatent_value(mydata, endclust, newclust);
726 728
727 return gotsize; 729 return 0;
728 getit: 730 getit:
729 if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) { 731 if (set_cluster(mydata, curclust, buffer, (int)actsize) != 0) {
730 debug("error: writing cluster\n"); 732 debug("error: writing cluster\n");
731 return -1; 733 return -1;
732 } 734 }
733 gotsize += (int)actsize; 735 *gotsize += actsize;
734 filesize -= actsize; 736 filesize -= actsize;
735 buffer += actsize; 737 buffer += actsize;
736 738
737 if (CHECK_CLUST(curclust, mydata->fatsize)) { 739 if (CHECK_CLUST(curclust, mydata->fatsize)) {
738 debug("curclust: 0x%x\n", curclust); 740 debug("curclust: 0x%x\n", curclust);
739 debug("Invalid FAT entry\n"); 741 debug("Invalid FAT entry\n");
740 return gotsize; 742 return 0;
741 } 743 }
742 actsize = bytesperclust; 744 actsize = bytesperclust;
743 curclust = endclust = newclust; 745 curclust = endclust = newclust;
744 } while (1); 746 } while (1);
745 } 747 }
746 748
747 /* 749 /*
748 * Fill dir_entry 750 * Fill dir_entry
749 */ 751 */
750 static void fill_dentry(fsdata *mydata, dir_entry *dentptr, 752 static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
751 const char *filename, __u32 start_cluster, __u32 size, __u8 attr) 753 const char *filename, __u32 start_cluster, __u32 size, __u8 attr)
752 { 754 {
753 if (mydata->fatsize == 32) 755 if (mydata->fatsize == 32)
754 dentptr->starthi = 756 dentptr->starthi =
755 cpu_to_le16((start_cluster & 0xffff0000) >> 16); 757 cpu_to_le16((start_cluster & 0xffff0000) >> 16);
756 dentptr->start = cpu_to_le16(start_cluster & 0xffff); 758 dentptr->start = cpu_to_le16(start_cluster & 0xffff);
757 dentptr->size = cpu_to_le32(size); 759 dentptr->size = cpu_to_le32(size);
758 760
759 dentptr->attr = attr; 761 dentptr->attr = attr;
760 762
761 set_name(dentptr, filename); 763 set_name(dentptr, filename);
762 } 764 }
763 765
764 /* 766 /*
765 * Check whether adding a file makes the file system to 767 * Check whether adding a file makes the file system to
766 * exceed the size of the block device 768 * exceed the size of the block device
767 * Return -1 when overflow occurs, otherwise return 0 769 * Return -1 when overflow occurs, otherwise return 0
768 */ 770 */
769 static int check_overflow(fsdata *mydata, __u32 clustnum, unsigned long size) 771 static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size)
770 { 772 {
771 __u32 startsect, sect_num; 773 __u32 startsect, sect_num;
772 774
773 if (clustnum > 0) { 775 if (clustnum > 0) {
774 startsect = mydata->data_begin + 776 startsect = mydata->data_begin +
775 clustnum * mydata->clust_size; 777 clustnum * mydata->clust_size;
776 } else { 778 } else {
777 startsect = mydata->rootdir_sect; 779 startsect = mydata->rootdir_sect;
778 } 780 }
779 781
780 sect_num = size / mydata->sect_size; 782 sect_num = size / mydata->sect_size;
781 if (size % mydata->sect_size) 783 if (size % mydata->sect_size)
782 sect_num++; 784 sect_num++;
783 785
784 if (startsect + sect_num > cur_part_info.start + total_sector) 786 if (startsect + sect_num > cur_part_info.start + total_sector)
785 return -1; 787 return -1;
786 788
787 return 0; 789 return 0;
788 } 790 }
789 791
790 /* 792 /*
791 * Check if adding several entries exceed one cluster boundary 793 * Check if adding several entries exceed one cluster boundary
792 */ 794 */
793 static int is_next_clust(fsdata *mydata, dir_entry *dentptr) 795 static int is_next_clust(fsdata *mydata, dir_entry *dentptr)
794 { 796 {
795 int cur_position; 797 int cur_position;
796 798
797 cur_position = (__u8 *)dentptr - get_dentfromdir_block; 799 cur_position = (__u8 *)dentptr - get_dentfromdir_block;
798 800
799 if (cur_position >= mydata->clust_size * mydata->sect_size) 801 if (cur_position >= mydata->clust_size * mydata->sect_size)
800 return 1; 802 return 1;
801 else 803 else
802 return 0; 804 return 0;
803 } 805 }
804 806
805 static dir_entry *empty_dentptr; 807 static dir_entry *empty_dentptr;
806 /* 808 /*
807 * Find a directory entry based on filename or start cluster number 809 * Find a directory entry based on filename or start cluster number
808 * If the directory entry is not found, 810 * If the directory entry is not found,
809 * the new position for writing a directory entry will be returned 811 * the new position for writing a directory entry will be returned
810 */ 812 */
811 static dir_entry *find_directory_entry(fsdata *mydata, int startsect, 813 static dir_entry *find_directory_entry(fsdata *mydata, int startsect,
812 char *filename, dir_entry *retdent, __u32 start) 814 char *filename, dir_entry *retdent, __u32 start)
813 { 815 {
814 __u32 curclust = (startsect - mydata->data_begin) / mydata->clust_size; 816 __u32 curclust = (startsect - mydata->data_begin) / mydata->clust_size;
815 817
816 debug("get_dentfromdir: %s\n", filename); 818 debug("get_dentfromdir: %s\n", filename);
817 819
818 while (1) { 820 while (1) {
819 dir_entry *dentptr; 821 dir_entry *dentptr;
820 822
821 int i; 823 int i;
822 824
823 if (get_cluster(mydata, curclust, get_dentfromdir_block, 825 if (get_cluster(mydata, curclust, get_dentfromdir_block,
824 mydata->clust_size * mydata->sect_size) != 0) { 826 mydata->clust_size * mydata->sect_size) != 0) {
825 printf("Error: reading directory block\n"); 827 printf("Error: reading directory block\n");
826 return NULL; 828 return NULL;
827 } 829 }
828 830
829 dentptr = (dir_entry *)get_dentfromdir_block; 831 dentptr = (dir_entry *)get_dentfromdir_block;
830 832
831 dir_curclust = curclust; 833 dir_curclust = curclust;
832 834
833 for (i = 0; i < DIRENTSPERCLUST; i++) { 835 for (i = 0; i < DIRENTSPERCLUST; i++) {
834 char s_name[14], l_name[VFAT_MAXLEN_BYTES]; 836 char s_name[14], l_name[VFAT_MAXLEN_BYTES];
835 837
836 l_name[0] = '\0'; 838 l_name[0] = '\0';
837 if (dentptr->name[0] == DELETED_FLAG) { 839 if (dentptr->name[0] == DELETED_FLAG) {
838 dentptr++; 840 dentptr++;
839 if (is_next_clust(mydata, dentptr)) 841 if (is_next_clust(mydata, dentptr))
840 break; 842 break;
841 continue; 843 continue;
842 } 844 }
843 if ((dentptr->attr & ATTR_VOLUME)) { 845 if ((dentptr->attr & ATTR_VOLUME)) {
844 if (vfat_enabled && 846 if (vfat_enabled &&
845 (dentptr->attr & ATTR_VFAT) && 847 (dentptr->attr & ATTR_VFAT) &&
846 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) { 848 (dentptr->name[0] & LAST_LONG_ENTRY_MASK)) {
847 get_long_file_name(mydata, curclust, 849 get_long_file_name(mydata, curclust,
848 get_dentfromdir_block, 850 get_dentfromdir_block,
849 &dentptr, l_name); 851 &dentptr, l_name);
850 debug("vfatname: |%s|\n", l_name); 852 debug("vfatname: |%s|\n", l_name);
851 } else { 853 } else {
852 /* Volume label or VFAT entry */ 854 /* Volume label or VFAT entry */
853 dentptr++; 855 dentptr++;
854 if (is_next_clust(mydata, dentptr)) 856 if (is_next_clust(mydata, dentptr))
855 break; 857 break;
856 continue; 858 continue;
857 } 859 }
858 } 860 }
859 if (dentptr->name[0] == 0) { 861 if (dentptr->name[0] == 0) {
860 debug("Dentname == NULL - %d\n", i); 862 debug("Dentname == NULL - %d\n", i);
861 empty_dentptr = dentptr; 863 empty_dentptr = dentptr;
862 return NULL; 864 return NULL;
863 } 865 }
864 866
865 get_name(dentptr, s_name); 867 get_name(dentptr, s_name);
866 868
867 if (strcmp(filename, s_name) 869 if (strcmp(filename, s_name)
868 && strcmp(filename, l_name)) { 870 && strcmp(filename, l_name)) {
869 debug("Mismatch: |%s|%s|\n", 871 debug("Mismatch: |%s|%s|\n",
870 s_name, l_name); 872 s_name, l_name);
871 dentptr++; 873 dentptr++;
872 if (is_next_clust(mydata, dentptr)) 874 if (is_next_clust(mydata, dentptr))
873 break; 875 break;
874 continue; 876 continue;
875 } 877 }
876 878
877 memcpy(retdent, dentptr, sizeof(dir_entry)); 879 memcpy(retdent, dentptr, sizeof(dir_entry));
878 880
879 debug("DentName: %s", s_name); 881 debug("DentName: %s", s_name);
880 debug(", start: 0x%x", START(dentptr)); 882 debug(", start: 0x%x", START(dentptr));
881 debug(", size: 0x%x %s\n", 883 debug(", size: 0x%x %s\n",
882 FAT2CPU32(dentptr->size), 884 FAT2CPU32(dentptr->size),
883 (dentptr->attr & ATTR_DIR) ? 885 (dentptr->attr & ATTR_DIR) ?
884 "(DIR)" : ""); 886 "(DIR)" : "");
885 887
886 return dentptr; 888 return dentptr;
887 } 889 }
888 890
889 /* 891 /*
890 * In FAT16/12, the root dir is locate before data area, shows 892 * In FAT16/12, the root dir is locate before data area, shows
891 * in following: 893 * in following:
892 * ------------------------------------------------------------- 894 * -------------------------------------------------------------
893 * | Boot | FAT1 & 2 | Root dir | Data (start from cluster #2) | 895 * | Boot | FAT1 & 2 | Root dir | Data (start from cluster #2) |
894 * ------------------------------------------------------------- 896 * -------------------------------------------------------------
895 * 897 *
896 * As a result if curclust is in Root dir, it is a negative 898 * As a result if curclust is in Root dir, it is a negative
897 * number or 0, 1. 899 * number or 0, 1.
898 * 900 *
899 */ 901 */
900 if (mydata->fatsize != 32 && (int)curclust <= 1) { 902 if (mydata->fatsize != 32 && (int)curclust <= 1) {
901 /* Current clust is in root dir, set to next clust */ 903 /* Current clust is in root dir, set to next clust */
902 curclust++; 904 curclust++;
903 if ((int)curclust <= 1) 905 if ((int)curclust <= 1)
904 continue; /* continue to find */ 906 continue; /* continue to find */
905 907
906 /* Reach the end of root dir */ 908 /* Reach the end of root dir */
907 empty_dentptr = dentptr; 909 empty_dentptr = dentptr;
908 return NULL; 910 return NULL;
909 } 911 }
910 912
911 curclust = get_fatent_value(mydata, dir_curclust); 913 curclust = get_fatent_value(mydata, dir_curclust);
912 if (IS_LAST_CLUST(curclust, mydata->fatsize)) { 914 if (IS_LAST_CLUST(curclust, mydata->fatsize)) {
913 empty_dentptr = dentptr; 915 empty_dentptr = dentptr;
914 return NULL; 916 return NULL;
915 } 917 }
916 if (CHECK_CLUST(curclust, mydata->fatsize)) { 918 if (CHECK_CLUST(curclust, mydata->fatsize)) {
917 debug("curclust: 0x%x\n", curclust); 919 debug("curclust: 0x%x\n", curclust);
918 debug("Invalid FAT entry\n"); 920 debug("Invalid FAT entry\n");
919 return NULL; 921 return NULL;
920 } 922 }
921 } 923 }
922 924
923 return NULL; 925 return NULL;
924 } 926 }
925 927
926 static int do_fat_write(const char *filename, void *buffer, 928 static int do_fat_write(const char *filename, void *buffer, loff_t size,
927 unsigned long size) 929 loff_t *actwrite)
928 { 930 {
929 dir_entry *dentptr, *retdent; 931 dir_entry *dentptr, *retdent;
930 __u32 startsect; 932 __u32 startsect;
931 __u32 start_cluster; 933 __u32 start_cluster;
932 boot_sector bs; 934 boot_sector bs;
933 volume_info volinfo; 935 volume_info volinfo;
934 fsdata datablock; 936 fsdata datablock;
935 fsdata *mydata = &datablock; 937 fsdata *mydata = &datablock;
936 int cursect; 938 int cursect;
937 int ret = -1, name_len; 939 int ret = -1, name_len;
938 char l_filename[VFAT_MAXLEN_BYTES]; 940 char l_filename[VFAT_MAXLEN_BYTES];
939 int write_size = size;
940 941
942 *actwrite = size;
941 dir_curclust = 0; 943 dir_curclust = 0;
942 944
943 if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) { 945 if (read_bootsectandvi(&bs, &volinfo, &mydata->fatsize)) {
944 debug("error: reading boot sector\n"); 946 debug("error: reading boot sector\n");
945 return -1; 947 return -1;
946 } 948 }
947 949
948 total_sector = bs.total_sect; 950 total_sector = bs.total_sect;
949 if (total_sector == 0) 951 if (total_sector == 0)
950 total_sector = (int)cur_part_info.size; /* cast of lbaint_t */ 952 total_sector = (int)cur_part_info.size; /* cast of lbaint_t */
951 953
952 if (mydata->fatsize == 32) 954 if (mydata->fatsize == 32)
953 mydata->fatlength = bs.fat32_length; 955 mydata->fatlength = bs.fat32_length;
954 else 956 else
955 mydata->fatlength = bs.fat_length; 957 mydata->fatlength = bs.fat_length;
956 958
957 mydata->fat_sect = bs.reserved; 959 mydata->fat_sect = bs.reserved;
958 960
959 cursect = mydata->rootdir_sect 961 cursect = mydata->rootdir_sect
960 = mydata->fat_sect + mydata->fatlength * bs.fats; 962 = mydata->fat_sect + mydata->fatlength * bs.fats;
961 num_of_fats = bs.fats; 963 num_of_fats = bs.fats;
962 964
963 mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0]; 965 mydata->sect_size = (bs.sector_size[1] << 8) + bs.sector_size[0];
964 mydata->clust_size = bs.cluster_size; 966 mydata->clust_size = bs.cluster_size;
965 967
966 if (mydata->fatsize == 32) { 968 if (mydata->fatsize == 32) {
967 mydata->data_begin = mydata->rootdir_sect - 969 mydata->data_begin = mydata->rootdir_sect -
968 (mydata->clust_size * 2); 970 (mydata->clust_size * 2);
969 } else { 971 } else {
970 int rootdir_size; 972 int rootdir_size;
971 973
972 rootdir_size = ((bs.dir_entries[1] * (int)256 + 974 rootdir_size = ((bs.dir_entries[1] * (int)256 +
973 bs.dir_entries[0]) * 975 bs.dir_entries[0]) *
974 sizeof(dir_entry)) / 976 sizeof(dir_entry)) /
975 mydata->sect_size; 977 mydata->sect_size;
976 mydata->data_begin = mydata->rootdir_sect + 978 mydata->data_begin = mydata->rootdir_sect +
977 rootdir_size - 979 rootdir_size -
978 (mydata->clust_size * 2); 980 (mydata->clust_size * 2);
979 } 981 }
980 982
981 mydata->fatbufnum = -1; 983 mydata->fatbufnum = -1;
982 mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE); 984 mydata->fatbuf = memalign(ARCH_DMA_MINALIGN, FATBUFSIZE);
983 if (mydata->fatbuf == NULL) { 985 if (mydata->fatbuf == NULL) {
984 debug("Error: allocating memory\n"); 986 debug("Error: allocating memory\n");
985 return -1; 987 return -1;
986 } 988 }
987 989
988 if (disk_read(cursect, 990 if (disk_read(cursect,
989 (mydata->fatsize == 32) ? 991 (mydata->fatsize == 32) ?
990 (mydata->clust_size) : 992 (mydata->clust_size) :
991 PREFETCH_BLOCKS, do_fat_read_at_block) < 0) { 993 PREFETCH_BLOCKS, do_fat_read_at_block) < 0) {
992 debug("Error: reading rootdir block\n"); 994 debug("Error: reading rootdir block\n");
993 goto exit; 995 goto exit;
994 } 996 }
995 dentptr = (dir_entry *) do_fat_read_at_block; 997 dentptr = (dir_entry *) do_fat_read_at_block;
996 998
997 name_len = strlen(filename); 999 name_len = strlen(filename);
998 if (name_len >= VFAT_MAXLEN_BYTES) 1000 if (name_len >= VFAT_MAXLEN_BYTES)
999 name_len = VFAT_MAXLEN_BYTES - 1; 1001 name_len = VFAT_MAXLEN_BYTES - 1;
1000 1002
1001 memcpy(l_filename, filename, name_len); 1003 memcpy(l_filename, filename, name_len);
1002 l_filename[name_len] = 0; /* terminate the string */ 1004 l_filename[name_len] = 0; /* terminate the string */
1003 downcase(l_filename); 1005 downcase(l_filename);
1004 1006
1005 startsect = mydata->rootdir_sect; 1007 startsect = mydata->rootdir_sect;
1006 retdent = find_directory_entry(mydata, startsect, 1008 retdent = find_directory_entry(mydata, startsect,
1007 l_filename, dentptr, 0); 1009 l_filename, dentptr, 0);
1008 if (retdent) { 1010 if (retdent) {
1009 /* Update file size and start_cluster in a directory entry */ 1011 /* Update file size and start_cluster in a directory entry */
1010 retdent->size = cpu_to_le32(size); 1012 retdent->size = cpu_to_le32(size);
1011 start_cluster = FAT2CPU16(retdent->start); 1013 start_cluster = FAT2CPU16(retdent->start);
1012 if (mydata->fatsize == 32) 1014 if (mydata->fatsize == 32)
1013 start_cluster |= 1015 start_cluster |=
1014 (FAT2CPU16(retdent->starthi) << 16); 1016 (FAT2CPU16(retdent->starthi) << 16);
1015 1017
1016 ret = check_overflow(mydata, start_cluster, size); 1018 ret = check_overflow(mydata, start_cluster, size);
1017 if (ret) { 1019 if (ret) {
1018 printf("Error: %ld overflow\n", size); 1020 printf("Error: %llu overflow\n", size);
1019 goto exit; 1021 goto exit;
1020 } 1022 }
1021 1023
1022 ret = clear_fatent(mydata, start_cluster); 1024 ret = clear_fatent(mydata, start_cluster);
1023 if (ret) { 1025 if (ret) {
1024 printf("Error: clearing FAT entries\n"); 1026 printf("Error: clearing FAT entries\n");
1025 goto exit; 1027 goto exit;
1026 } 1028 }
1027 1029
1028 ret = set_contents(mydata, retdent, buffer, size); 1030 ret = set_contents(mydata, retdent, buffer, size, actwrite);
1029 if (ret < 0) { 1031 if (ret < 0) {
1030 printf("Error: writing contents\n"); 1032 printf("Error: writing contents\n");
1031 goto exit; 1033 goto exit;
1032 } 1034 }
1033 write_size = ret; 1035 debug("attempt to write 0x%llx bytes\n", *actwrite);
1034 debug("attempt to write 0x%x bytes\n", write_size);
1035 1036
1036 /* Flush fat buffer */ 1037 /* Flush fat buffer */
1037 ret = flush_fat_buffer(mydata); 1038 ret = flush_fat_buffer(mydata);
1038 if (ret) { 1039 if (ret) {
1039 printf("Error: flush fat buffer\n"); 1040 printf("Error: flush fat buffer\n");
1040 goto exit; 1041 goto exit;
1041 } 1042 }
1042 1043
1043 /* Write directory table to device */ 1044 /* Write directory table to device */
1044 ret = set_cluster(mydata, dir_curclust, 1045 ret = set_cluster(mydata, dir_curclust,
1045 get_dentfromdir_block, 1046 get_dentfromdir_block,
1046 mydata->clust_size * mydata->sect_size); 1047 mydata->clust_size * mydata->sect_size);
1047 if (ret) { 1048 if (ret) {
1048 printf("Error: writing directory entry\n"); 1049 printf("Error: writing directory entry\n");
1049 goto exit; 1050 goto exit;
1050 } 1051 }
1051 } else { 1052 } else {
1052 /* Set short name to set alias checksum field in dir_slot */ 1053 /* Set short name to set alias checksum field in dir_slot */
1053 set_name(empty_dentptr, filename); 1054 set_name(empty_dentptr, filename);
1054 fill_dir_slot(mydata, &empty_dentptr, filename); 1055 fill_dir_slot(mydata, &empty_dentptr, filename);
1055 1056
1056 ret = start_cluster = find_empty_cluster(mydata); 1057 ret = start_cluster = find_empty_cluster(mydata);
1057 if (ret < 0) { 1058 if (ret < 0) {
1058 printf("Error: finding empty cluster\n"); 1059 printf("Error: finding empty cluster\n");
1059 goto exit; 1060 goto exit;
1060 } 1061 }
1061 1062
1062 ret = check_overflow(mydata, start_cluster, size); 1063 ret = check_overflow(mydata, start_cluster, size);
1063 if (ret) { 1064 if (ret) {
1064 printf("Error: %ld overflow\n", size); 1065 printf("Error: %llu overflow\n", size);
1065 goto exit; 1066 goto exit;
1066 } 1067 }
1067 1068
1068 /* Set attribute as archieve for regular file */ 1069 /* Set attribute as archieve for regular file */
1069 fill_dentry(mydata, empty_dentptr, filename, 1070 fill_dentry(mydata, empty_dentptr, filename,
1070 start_cluster, size, 0x20); 1071 start_cluster, size, 0x20);
1071 1072
1072 ret = set_contents(mydata, empty_dentptr, buffer, size); 1073 ret = set_contents(mydata, empty_dentptr, buffer, size,
1074 actwrite);
1073 if (ret < 0) { 1075 if (ret < 0) {
1074 printf("Error: writing contents\n"); 1076 printf("Error: writing contents\n");
1075 goto exit; 1077 goto exit;
1076 } 1078 }
1077 write_size = ret; 1079 debug("attempt to write 0x%llx bytes\n", *actwrite);
1078 debug("attempt to write 0x%x bytes\n", write_size);
1079 1080
1080 /* Flush fat buffer */ 1081 /* Flush fat buffer */
1081 ret = flush_fat_buffer(mydata); 1082 ret = flush_fat_buffer(mydata);
1082 if (ret) { 1083 if (ret) {
1083 printf("Error: flush fat buffer\n"); 1084 printf("Error: flush fat buffer\n");
1084 goto exit; 1085 goto exit;
1085 } 1086 }
1086 1087
1087 /* Write directory table to device */ 1088 /* Write directory table to device */
1088 ret = set_cluster(mydata, dir_curclust, 1089 ret = set_cluster(mydata, dir_curclust,
1089 get_dentfromdir_block, 1090 get_dentfromdir_block,
1090 mydata->clust_size * mydata->sect_size); 1091 mydata->clust_size * mydata->sect_size);
1091 if (ret) { 1092 if (ret) {
1092 printf("Error: writing directory entry\n"); 1093 printf("Error: writing directory entry\n");
1093 goto exit; 1094 goto exit;
1094 } 1095 }
1095 } 1096 }
1096 1097
1097 exit: 1098 exit:
1098 free(mydata->fatbuf); 1099 free(mydata->fatbuf);
1099 return ret < 0 ? ret : write_size; 1100 return ret;
1100 } 1101 }
1101 1102
1102 int file_fat_write(const char *filename, void *buffer, unsigned long maxsize) 1103 int file_fat_write(const char *filename, void *buffer, loff_t offset,
1104 loff_t maxsize, loff_t *actwrite)
1103 { 1105 {
1106 if (offset != 0) {
1107 printf("Error: non zero offset is currently not suported.\n");
1108 return -1;
1109 }
1110
1104 printf("writing %s\n", filename); 1111 printf("writing %s\n", filename);
1 /* 1 /*
2 * file.c 2 * file.c
3 * 3 *
4 * Mini "VFS" by Marcus Sundberg 4 * Mini "VFS" by Marcus Sundberg
5 * 5 *
6 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 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 7 * 2003-03-10 - kharris@nexus-tech.net - ported to uboot
8 * 8 *
9 * SPDX-License-Identifier: GPL-2.0+ 9 * SPDX-License-Identifier: GPL-2.0+
10 */ 10 */
11 11
12 #include <common.h> 12 #include <common.h>
13 #include <config.h> 13 #include <config.h>
14 #include <malloc.h> 14 #include <malloc.h>
15 #include <fat.h> 15 #include <fat.h>
16 #include <linux/stat.h> 16 #include <linux/stat.h>
17 #include <linux/time.h> 17 #include <linux/time.h>
18 18
19 /* Supported filesystems */ 19 /* Supported filesystems */
20 static const struct filesystem filesystems[] = { 20 static const struct filesystem filesystems[] = {
21 { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" }, 21 { file_fat_detectfs, file_fat_ls, file_fat_read, "FAT" },
22 }; 22 };
23 #define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem)) 23 #define NUM_FILESYS (sizeof(filesystems)/sizeof(struct filesystem))
24 24
25 /* The filesystem which was last detected */ 25 /* The filesystem which was last detected */
26 static int current_filesystem = FSTYPE_NONE; 26 static int current_filesystem = FSTYPE_NONE;
27 27
28 /* The current working directory */ 28 /* The current working directory */
29 #define CWD_LEN 511 29 #define CWD_LEN 511
30 char file_cwd[CWD_LEN+1] = "/"; 30 char file_cwd[CWD_LEN+1] = "/";
31 31
32 const char * 32 const char *
33 file_getfsname(int idx) 33 file_getfsname(int idx)
34 { 34 {
35 if (idx < 0 || idx >= NUM_FILESYS) 35 if (idx < 0 || idx >= NUM_FILESYS)
36 return NULL; 36 return NULL;
37 37
38 return filesystems[idx].name; 38 return filesystems[idx].name;
39 } 39 }
40 40
41 static void 41 static void
42 pathcpy(char *dest, const char *src) 42 pathcpy(char *dest, const char *src)
43 { 43 {
44 char *origdest = dest; 44 char *origdest = dest;
45 45
46 do { 46 do {
47 if (dest-file_cwd >= CWD_LEN) { 47 if (dest-file_cwd >= CWD_LEN) {
48 *dest = '\0'; 48 *dest = '\0';
49 return; 49 return;
50 } 50 }
51 *(dest) = *(src); 51 *(dest) = *(src);
52 if (*src == '\0') { 52 if (*src == '\0') {
53 if (dest-- != origdest && ISDIRDELIM(*dest)) { 53 if (dest-- != origdest && ISDIRDELIM(*dest)) {
54 *dest = '\0'; 54 *dest = '\0';
55 } 55 }
56 return; 56 return;
57 } 57 }
58 ++dest; 58 ++dest;
59 59
60 if (ISDIRDELIM(*src)) 60 if (ISDIRDELIM(*src))
61 while (ISDIRDELIM(*src)) src++; 61 while (ISDIRDELIM(*src)) src++;
62 else 62 else
63 src++; 63 src++;
64 } while (1); 64 } while (1);
65 } 65 }
66 66
67 int 67 int
68 file_cd(const char *path) 68 file_cd(const char *path)
69 { 69 {
70 if (ISDIRDELIM(*path)) { 70 if (ISDIRDELIM(*path)) {
71 while (ISDIRDELIM(*path)) path++; 71 while (ISDIRDELIM(*path)) path++;
72 strncpy(file_cwd+1, path, CWD_LEN-1); 72 strncpy(file_cwd+1, path, CWD_LEN-1);
73 } else { 73 } else {
74 const char *origpath = path; 74 const char *origpath = path;
75 char *tmpstr = file_cwd; 75 char *tmpstr = file_cwd;
76 int back = 0; 76 int back = 0;
77 77
78 while (*tmpstr != '\0') tmpstr++; 78 while (*tmpstr != '\0') tmpstr++;
79 do { 79 do {
80 tmpstr--; 80 tmpstr--;
81 } while (ISDIRDELIM(*tmpstr)); 81 } while (ISDIRDELIM(*tmpstr));
82 82
83 while (*path == '.') { 83 while (*path == '.') {
84 path++; 84 path++;
85 while (*path == '.') { 85 while (*path == '.') {
86 path++; 86 path++;
87 back++; 87 back++;
88 } 88 }
89 if (*path != '\0' && !ISDIRDELIM(*path)) { 89 if (*path != '\0' && !ISDIRDELIM(*path)) {
90 path = origpath; 90 path = origpath;
91 back = 0; 91 back = 0;
92 break; 92 break;
93 } 93 }
94 while (ISDIRDELIM(*path)) path++; 94 while (ISDIRDELIM(*path)) path++;
95 origpath = path; 95 origpath = path;
96 } 96 }
97 97
98 while (back--) { 98 while (back--) {
99 /* Strip off path component */ 99 /* Strip off path component */
100 while (!ISDIRDELIM(*tmpstr)) { 100 while (!ISDIRDELIM(*tmpstr)) {
101 tmpstr--; 101 tmpstr--;
102 } 102 }
103 if (tmpstr == file_cwd) { 103 if (tmpstr == file_cwd) {
104 /* Incremented again right after the loop. */ 104 /* Incremented again right after the loop. */
105 tmpstr--; 105 tmpstr--;
106 break; 106 break;
107 } 107 }
108 /* Skip delimiters */ 108 /* Skip delimiters */
109 while (ISDIRDELIM(*tmpstr)) tmpstr--; 109 while (ISDIRDELIM(*tmpstr)) tmpstr--;
110 } 110 }
111 tmpstr++; 111 tmpstr++;
112 if (*path == '\0') { 112 if (*path == '\0') {
113 if (tmpstr == file_cwd) { 113 if (tmpstr == file_cwd) {
114 *tmpstr = '/'; 114 *tmpstr = '/';
115 tmpstr++; 115 tmpstr++;
116 } 116 }
117 *tmpstr = '\0'; 117 *tmpstr = '\0';
118 return 0; 118 return 0;
119 } 119 }
120 *tmpstr = '/'; 120 *tmpstr = '/';
121 pathcpy(tmpstr+1, path); 121 pathcpy(tmpstr+1, path);
122 } 122 }
123 123
124 return 0; 124 return 0;
125 } 125 }
126 126
127 int 127 int
128 file_detectfs(void) 128 file_detectfs(void)
129 { 129 {
130 int i; 130 int i;
131 131
132 current_filesystem = FSTYPE_NONE; 132 current_filesystem = FSTYPE_NONE;
133 133
134 for (i = 0; i < NUM_FILESYS; i++) { 134 for (i = 0; i < NUM_FILESYS; i++) {
135 if (filesystems[i].detect() == 0) { 135 if (filesystems[i].detect() == 0) {
136 strcpy(file_cwd, "/"); 136 strcpy(file_cwd, "/");
137 current_filesystem = i; 137 current_filesystem = i;
138 break; 138 break;
139 } 139 }
140 } 140 }
141 141
142 return current_filesystem; 142 return current_filesystem;
143 } 143 }
144 144
145 int 145 int
146 file_ls(const char *dir) 146 file_ls(const char *dir)
147 { 147 {
148 char fullpath[1024]; 148 char fullpath[1024];
149 const char *arg; 149 const char *arg;
150 150
151 if (current_filesystem == FSTYPE_NONE) { 151 if (current_filesystem == FSTYPE_NONE) {
152 printf("Can't list files without a filesystem!\n"); 152 printf("Can't list files without a filesystem!\n");
153 return -1; 153 return -1;
154 } 154 }
155 155
156 if (ISDIRDELIM(*dir)) { 156 if (ISDIRDELIM(*dir)) {
157 arg = dir; 157 arg = dir;
158 } else { 158 } else {
159 sprintf(fullpath, "%s/%s", file_cwd, dir); 159 sprintf(fullpath, "%s/%s", file_cwd, dir);
160 arg = fullpath; 160 arg = fullpath;
161 } 161 }
162 return filesystems[current_filesystem].ls(arg); 162 return filesystems[current_filesystem].ls(arg);
163 } 163 }
164 164
165 long 165 int file_read(const char *filename, void *buffer, int maxsize)
166 file_read(const char *filename, void *buffer, unsigned long maxsize)
167 { 166 {
168 char fullpath[1024]; 167 char fullpath[1024];
169 const char *arg; 168 const char *arg;
170 169
171 if (current_filesystem == FSTYPE_NONE) { 170 if (current_filesystem == FSTYPE_NONE) {
172 printf("Can't load file without a filesystem!\n"); 171 printf("Can't load file without a filesystem!\n");
173 return -1; 172 return -1;
174 } 173 }
175 174
176 if (ISDIRDELIM(*filename)) { 175 if (ISDIRDELIM(*filename)) {
177 arg = filename; 176 arg = filename;
178 } else { 177 } else {
179 sprintf(fullpath, "%s/%s", file_cwd, filename); 178 sprintf(fullpath, "%s/%s", file_cwd, filename);
180 arg = fullpath; 179 arg = fullpath;
181 } 180 }
182 181
183 return filesystems[current_filesystem].read(arg, buffer, maxsize); 182 return filesystems[current_filesystem].read(arg, buffer, maxsize);
184 } 183 }
185 184
1 /* 1 /*
2 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg 2 * R/O (V)FAT 12/16/32 filesystem implementation by Marcus Sundberg
3 * 3 *
4 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6 4 * 2002-07-28 - rjones@nexus-tech.net - ported to ppcboot v1.1.6
5 * 2003-03-10 - kharris@nexus-tech.net - ported to u-boot 5 * 2003-03-10 - kharris@nexus-tech.net - ported to u-boot
6 * 6 *
7 * SPDX-License-Identifier: GPL-2.0+ 7 * SPDX-License-Identifier: GPL-2.0+
8 */ 8 */
9 9
10 #ifndef _FAT_H_ 10 #ifndef _FAT_H_
11 #define _FAT_H_ 11 #define _FAT_H_
12 12
13 #include <asm/byteorder.h> 13 #include <asm/byteorder.h>
14 14
15 #define CONFIG_SUPPORT_VFAT 15 #define CONFIG_SUPPORT_VFAT
16 /* Maximum Long File Name length supported here is 128 UTF-16 code units */ 16 /* Maximum Long File Name length supported here is 128 UTF-16 code units */
17 #define VFAT_MAXLEN_BYTES 256 /* Maximum LFN buffer in bytes */ 17 #define VFAT_MAXLEN_BYTES 256 /* Maximum LFN buffer in bytes */
18 #define VFAT_MAXSEQ 9 /* Up to 9 of 13 2-byte UTF-16 entries */ 18 #define VFAT_MAXSEQ 9 /* Up to 9 of 13 2-byte UTF-16 entries */
19 #define PREFETCH_BLOCKS 2 19 #define PREFETCH_BLOCKS 2
20 20
21 #ifndef CONFIG_FS_FAT_MAX_CLUSTSIZE 21 #ifndef CONFIG_FS_FAT_MAX_CLUSTSIZE
22 #define CONFIG_FS_FAT_MAX_CLUSTSIZE 65536 22 #define CONFIG_FS_FAT_MAX_CLUSTSIZE 65536
23 #endif 23 #endif
24 #define MAX_CLUSTSIZE CONFIG_FS_FAT_MAX_CLUSTSIZE 24 #define MAX_CLUSTSIZE CONFIG_FS_FAT_MAX_CLUSTSIZE
25 25
26 #define DIRENTSPERBLOCK (mydata->sect_size / sizeof(dir_entry)) 26 #define DIRENTSPERBLOCK (mydata->sect_size / sizeof(dir_entry))
27 #define DIRENTSPERCLUST ((mydata->clust_size * mydata->sect_size) / \ 27 #define DIRENTSPERCLUST ((mydata->clust_size * mydata->sect_size) / \
28 sizeof(dir_entry)) 28 sizeof(dir_entry))
29 29
30 #define FATBUFBLOCKS 6 30 #define FATBUFBLOCKS 6
31 #define FATBUFSIZE (mydata->sect_size * FATBUFBLOCKS) 31 #define FATBUFSIZE (mydata->sect_size * FATBUFBLOCKS)
32 #define FAT12BUFSIZE ((FATBUFSIZE*2)/3) 32 #define FAT12BUFSIZE ((FATBUFSIZE*2)/3)
33 #define FAT16BUFSIZE (FATBUFSIZE/2) 33 #define FAT16BUFSIZE (FATBUFSIZE/2)
34 #define FAT32BUFSIZE (FATBUFSIZE/4) 34 #define FAT32BUFSIZE (FATBUFSIZE/4)
35 35
36 36
37 /* Filesystem identifiers */ 37 /* Filesystem identifiers */
38 #define FAT12_SIGN "FAT12 " 38 #define FAT12_SIGN "FAT12 "
39 #define FAT16_SIGN "FAT16 " 39 #define FAT16_SIGN "FAT16 "
40 #define FAT32_SIGN "FAT32 " 40 #define FAT32_SIGN "FAT32 "
41 #define SIGNLEN 8 41 #define SIGNLEN 8
42 42
43 /* File attributes */ 43 /* File attributes */
44 #define ATTR_RO 1 44 #define ATTR_RO 1
45 #define ATTR_HIDDEN 2 45 #define ATTR_HIDDEN 2
46 #define ATTR_SYS 4 46 #define ATTR_SYS 4
47 #define ATTR_VOLUME 8 47 #define ATTR_VOLUME 8
48 #define ATTR_DIR 16 48 #define ATTR_DIR 16
49 #define ATTR_ARCH 32 49 #define ATTR_ARCH 32
50 50
51 #define ATTR_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME) 51 #define ATTR_VFAT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
52 52
53 #define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */ 53 #define DELETED_FLAG ((char)0xe5) /* Marks deleted files when in name[0] */
54 #define aRING 0x05 /* Used as special character in name[0] */ 54 #define aRING 0x05 /* Used as special character in name[0] */
55 55
56 /* 56 /*
57 * Indicates that the entry is the last long entry in a set of long 57 * Indicates that the entry is the last long entry in a set of long
58 * dir entries 58 * dir entries
59 */ 59 */
60 #define LAST_LONG_ENTRY_MASK 0x40 60 #define LAST_LONG_ENTRY_MASK 0x40
61 61
62 /* Flags telling whether we should read a file or list a directory */ 62 /* Flags telling whether we should read a file or list a directory */
63 #define LS_NO 0 63 #define LS_NO 0
64 #define LS_YES 1 64 #define LS_YES 1
65 #define LS_DIR 1 65 #define LS_DIR 1
66 #define LS_ROOT 2 66 #define LS_ROOT 2
67 67
68 #define ISDIRDELIM(c) ((c) == '/' || (c) == '\\') 68 #define ISDIRDELIM(c) ((c) == '/' || (c) == '\\')
69 69
70 #define FSTYPE_NONE (-1) 70 #define FSTYPE_NONE (-1)
71 71
72 #if defined(__linux__) && defined(__KERNEL__) 72 #if defined(__linux__) && defined(__KERNEL__)
73 #define FAT2CPU16 le16_to_cpu 73 #define FAT2CPU16 le16_to_cpu
74 #define FAT2CPU32 le32_to_cpu 74 #define FAT2CPU32 le32_to_cpu
75 #else 75 #else
76 #if __LITTLE_ENDIAN 76 #if __LITTLE_ENDIAN
77 #define FAT2CPU16(x) (x) 77 #define FAT2CPU16(x) (x)
78 #define FAT2CPU32(x) (x) 78 #define FAT2CPU32(x) (x)
79 #else 79 #else
80 #define FAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8)) 80 #define FAT2CPU16(x) ((((x) & 0x00ff) << 8) | (((x) & 0xff00) >> 8))
81 #define FAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \ 81 #define FAT2CPU32(x) ((((x) & 0x000000ff) << 24) | \
82 (((x) & 0x0000ff00) << 8) | \ 82 (((x) & 0x0000ff00) << 8) | \
83 (((x) & 0x00ff0000) >> 8) | \ 83 (((x) & 0x00ff0000) >> 8) | \
84 (((x) & 0xff000000) >> 24)) 84 (((x) & 0xff000000) >> 24))
85 #endif 85 #endif
86 #endif 86 #endif
87 87
88 #define START(dent) (FAT2CPU16((dent)->start) \ 88 #define START(dent) (FAT2CPU16((dent)->start) \
89 + (mydata->fatsize != 32 ? 0 : \ 89 + (mydata->fatsize != 32 ? 0 : \
90 (FAT2CPU16((dent)->starthi) << 16))) 90 (FAT2CPU16((dent)->starthi) << 16)))
91 #define IS_LAST_CLUST(x, fatsize) ((x) >= ((fatsize) != 32 ? \ 91 #define IS_LAST_CLUST(x, fatsize) ((x) >= ((fatsize) != 32 ? \
92 ((fatsize) != 16 ? 0xff8 : 0xfff8) : \ 92 ((fatsize) != 16 ? 0xff8 : 0xfff8) : \
93 0xffffff8)) 93 0xffffff8))
94 #define CHECK_CLUST(x, fatsize) ((x) <= 1 || \ 94 #define CHECK_CLUST(x, fatsize) ((x) <= 1 || \
95 (x) >= ((fatsize) != 32 ? \ 95 (x) >= ((fatsize) != 32 ? \
96 ((fatsize) != 16 ? 0xff0 : 0xfff0) : \ 96 ((fatsize) != 16 ? 0xff0 : 0xfff0) : \
97 0xffffff0)) 97 0xffffff0))
98 98
99 typedef struct boot_sector { 99 typedef struct boot_sector {
100 __u8 ignored[3]; /* Bootstrap code */ 100 __u8 ignored[3]; /* Bootstrap code */
101 char system_id[8]; /* Name of fs */ 101 char system_id[8]; /* Name of fs */
102 __u8 sector_size[2]; /* Bytes/sector */ 102 __u8 sector_size[2]; /* Bytes/sector */
103 __u8 cluster_size; /* Sectors/cluster */ 103 __u8 cluster_size; /* Sectors/cluster */
104 __u16 reserved; /* Number of reserved sectors */ 104 __u16 reserved; /* Number of reserved sectors */
105 __u8 fats; /* Number of FATs */ 105 __u8 fats; /* Number of FATs */
106 __u8 dir_entries[2]; /* Number of root directory entries */ 106 __u8 dir_entries[2]; /* Number of root directory entries */
107 __u8 sectors[2]; /* Number of sectors */ 107 __u8 sectors[2]; /* Number of sectors */
108 __u8 media; /* Media code */ 108 __u8 media; /* Media code */
109 __u16 fat_length; /* Sectors/FAT */ 109 __u16 fat_length; /* Sectors/FAT */
110 __u16 secs_track; /* Sectors/track */ 110 __u16 secs_track; /* Sectors/track */
111 __u16 heads; /* Number of heads */ 111 __u16 heads; /* Number of heads */
112 __u32 hidden; /* Number of hidden sectors */ 112 __u32 hidden; /* Number of hidden sectors */
113 __u32 total_sect; /* Number of sectors (if sectors == 0) */ 113 __u32 total_sect; /* Number of sectors (if sectors == 0) */
114 114
115 /* FAT32 only */ 115 /* FAT32 only */
116 __u32 fat32_length; /* Sectors/FAT */ 116 __u32 fat32_length; /* Sectors/FAT */
117 __u16 flags; /* Bit 8: fat mirroring, low 4: active fat */ 117 __u16 flags; /* Bit 8: fat mirroring, low 4: active fat */
118 __u8 version[2]; /* Filesystem version */ 118 __u8 version[2]; /* Filesystem version */
119 __u32 root_cluster; /* First cluster in root directory */ 119 __u32 root_cluster; /* First cluster in root directory */
120 __u16 info_sector; /* Filesystem info sector */ 120 __u16 info_sector; /* Filesystem info sector */
121 __u16 backup_boot; /* Backup boot sector */ 121 __u16 backup_boot; /* Backup boot sector */
122 __u16 reserved2[6]; /* Unused */ 122 __u16 reserved2[6]; /* Unused */
123 } boot_sector; 123 } boot_sector;
124 124
125 typedef struct volume_info 125 typedef struct volume_info
126 { 126 {
127 __u8 drive_number; /* BIOS drive number */ 127 __u8 drive_number; /* BIOS drive number */
128 __u8 reserved; /* Unused */ 128 __u8 reserved; /* Unused */
129 __u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */ 129 __u8 ext_boot_sign; /* 0x29 if fields below exist (DOS 3.3+) */
130 __u8 volume_id[4]; /* Volume ID number */ 130 __u8 volume_id[4]; /* Volume ID number */
131 char volume_label[11]; /* Volume label */ 131 char volume_label[11]; /* Volume label */
132 char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */ 132 char fs_type[8]; /* Typically FAT12, FAT16, or FAT32 */
133 /* Boot code comes next, all but 2 bytes to fill up sector */ 133 /* Boot code comes next, all but 2 bytes to fill up sector */
134 /* Boot sign comes last, 2 bytes */ 134 /* Boot sign comes last, 2 bytes */
135 } volume_info; 135 } volume_info;
136 136
137 typedef struct dir_entry { 137 typedef struct dir_entry {
138 char name[8],ext[3]; /* Name and extension */ 138 char name[8],ext[3]; /* Name and extension */
139 __u8 attr; /* Attribute bits */ 139 __u8 attr; /* Attribute bits */
140 __u8 lcase; /* Case for base and extension */ 140 __u8 lcase; /* Case for base and extension */
141 __u8 ctime_ms; /* Creation time, milliseconds */ 141 __u8 ctime_ms; /* Creation time, milliseconds */
142 __u16 ctime; /* Creation time */ 142 __u16 ctime; /* Creation time */
143 __u16 cdate; /* Creation date */ 143 __u16 cdate; /* Creation date */
144 __u16 adate; /* Last access date */ 144 __u16 adate; /* Last access date */
145 __u16 starthi; /* High 16 bits of cluster in FAT32 */ 145 __u16 starthi; /* High 16 bits of cluster in FAT32 */
146 __u16 time,date,start;/* Time, date and first cluster */ 146 __u16 time,date,start;/* Time, date and first cluster */
147 __u32 size; /* File size in bytes */ 147 __u32 size; /* File size in bytes */
148 } dir_entry; 148 } dir_entry;
149 149
150 typedef struct dir_slot { 150 typedef struct dir_slot {
151 __u8 id; /* Sequence number for slot */ 151 __u8 id; /* Sequence number for slot */
152 __u8 name0_4[10]; /* First 5 characters in name */ 152 __u8 name0_4[10]; /* First 5 characters in name */
153 __u8 attr; /* Attribute byte */ 153 __u8 attr; /* Attribute byte */
154 __u8 reserved; /* Unused */ 154 __u8 reserved; /* Unused */
155 __u8 alias_checksum;/* Checksum for 8.3 alias */ 155 __u8 alias_checksum;/* Checksum for 8.3 alias */
156 __u8 name5_10[12]; /* 6 more characters in name */ 156 __u8 name5_10[12]; /* 6 more characters in name */
157 __u16 start; /* Unused */ 157 __u16 start; /* Unused */
158 __u8 name11_12[4]; /* Last 2 characters in name */ 158 __u8 name11_12[4]; /* Last 2 characters in name */
159 } dir_slot; 159 } dir_slot;
160 160
161 /* 161 /*
162 * Private filesystem parameters 162 * Private filesystem parameters
163 * 163 *
164 * Note: FAT buffer has to be 32 bit aligned 164 * Note: FAT buffer has to be 32 bit aligned
165 * (see FAT32 accesses) 165 * (see FAT32 accesses)
166 */ 166 */
167 typedef struct { 167 typedef struct {
168 __u8 *fatbuf; /* Current FAT buffer */ 168 __u8 *fatbuf; /* Current FAT buffer */
169 int fatsize; /* Size of FAT in bits */ 169 int fatsize; /* Size of FAT in bits */
170 __u32 fatlength; /* Length of FAT in sectors */ 170 __u32 fatlength; /* Length of FAT in sectors */
171 __u16 fat_sect; /* Starting sector of the FAT */ 171 __u16 fat_sect; /* Starting sector of the FAT */
172 __u32 rootdir_sect; /* Start sector of root directory */ 172 __u32 rootdir_sect; /* Start sector of root directory */
173 __u16 sect_size; /* Size of sectors in bytes */ 173 __u16 sect_size; /* Size of sectors in bytes */
174 __u16 clust_size; /* Size of clusters in sectors */ 174 __u16 clust_size; /* Size of clusters in sectors */
175 int data_begin; /* The sector of the first cluster, can be negative */ 175 int data_begin; /* The sector of the first cluster, can be negative */
176 int fatbufnum; /* Used by get_fatent, init to -1 */ 176 int fatbufnum; /* Used by get_fatent, init to -1 */
177 } fsdata; 177 } fsdata;
178 178
179 typedef int (file_detectfs_func)(void); 179 typedef int (file_detectfs_func)(void);
180 typedef int (file_ls_func)(const char *dir); 180 typedef int (file_ls_func)(const char *dir);
181 typedef long (file_read_func)(const char *filename, void *buffer, 181 typedef int (file_read_func)(const char *filename, void *buffer,
182 unsigned long maxsize); 182 int maxsize);
183 183
184 struct filesystem { 184 struct filesystem {
185 file_detectfs_func *detect; 185 file_detectfs_func *detect;
186 file_ls_func *ls; 186 file_ls_func *ls;
187 file_read_func *read; 187 file_read_func *read;
188 const char name[12]; 188 const char name[12];
189 }; 189 };
190 190
191 /* FAT tables */ 191 /* FAT tables */
192 file_detectfs_func file_fat_detectfs; 192 file_detectfs_func file_fat_detectfs;
193 file_ls_func file_fat_ls; 193 file_ls_func file_fat_ls;
194 file_read_func file_fat_read; 194 file_read_func file_fat_read;
195 195
196 /* Currently this doesn't check if the dir exists or is valid... */ 196 /* Currently this doesn't check if the dir exists or is valid... */
197 int file_cd(const char *path); 197 int file_cd(const char *path);
198 int file_fat_detectfs(void); 198 int file_fat_detectfs(void);
199 int file_fat_ls(const char *dir); 199 int file_fat_ls(const char *dir);
200 int fat_exists(const char *filename); 200 int fat_exists(const char *filename);
201 int fat_size(const char *filename); 201 int fat_size(const char *filename);
202 long file_fat_read_at(const char *filename, unsigned long pos, void *buffer, 202 int file_fat_read_at(const char *filename, loff_t pos, void *buffer,
203 unsigned long maxsize); 203 loff_t maxsize, loff_t *actread);
204 long file_fat_read(const char *filename, void *buffer, unsigned long maxsize); 204 int file_fat_read(const char *filename, void *buffer, int maxsize);
205 const char *file_getfsname(int idx); 205 const char *file_getfsname(int idx);
206 int fat_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); 206 int fat_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info);
207 int fat_register_device(block_dev_desc_t *dev_desc, int part_no); 207 int fat_register_device(block_dev_desc_t *dev_desc, int part_no);
208 208
209 int file_fat_write(const char *filename, void *buffer, unsigned long maxsize); 209 int file_fat_write(const char *filename, void *buf, loff_t offset, loff_t len,
210 loff_t *actwrite);
210 int fat_read_file(const char *filename, void *buf, int offset, int len); 211 int fat_read_file(const char *filename, void *buf, int offset, int len);
211 void fat_close(void); 212 void fat_close(void);
212 #endif /* _FAT_H_ */ 213 #endif /* _FAT_H_ */
213 214