diff options
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 585 |
1 files changed, 361 insertions, 224 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 7bed896748..322ae76a2d 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -22,14 +22,11 @@ | |||
22 | #include <math.h> | 22 | #include <math.h> |
23 | #include <stdlib.h> | 23 | #include <stdlib.h> |
24 | #include <ctype.h> | 24 | #include <ctype.h> |
25 | #ifdef DISK_WRITE | ||
26 | #include <time.h> | ||
27 | #include <sys/timeb.h> | ||
28 | #endif | ||
29 | #include <stdbool.h> | 25 | #include <stdbool.h> |
30 | #include "fat.h" | 26 | #include "fat.h" |
31 | #include "ata.h" | 27 | #include "ata.h" |
32 | #include "debug.h" | 28 | #include "debug.h" |
29 | #include "panic.h" | ||
33 | #include "system.h" | 30 | #include "system.h" |
34 | 31 | ||
35 | #define BYTES2INT16(array,pos) \ | 32 | #define BYTES2INT16(array,pos) \ |
@@ -38,11 +35,6 @@ | |||
38 | (array[pos] | (array[pos+1] << 8 ) | \ | 35 | (array[pos] | (array[pos+1] << 8 ) | \ |
39 | (array[pos+2] << 16 ) | (array[pos+3] << 24 )) | 36 | (array[pos+2] << 16 ) | (array[pos+3] << 24 )) |
40 | 37 | ||
41 | #define NUM_ROOT_DIR_ENTRIES 512 | ||
42 | #define NUM_FATS 2 | ||
43 | #define NUM_RESERVED_SECTORS 1 | ||
44 | #define NUM_BLOCKS 10000 | ||
45 | |||
46 | #define FATTYPE_FAT12 0 | 38 | #define FATTYPE_FAT12 0 |
47 | #define FATTYPE_FAT16 1 | 39 | #define FATTYPE_FAT16 1 |
48 | #define FATTYPE_FAT32 2 | 40 | #define FATTYPE_FAT32 2 |
@@ -107,6 +99,12 @@ | |||
107 | #define FATDIR_FSTCLUSLO 26 | 99 | #define FATDIR_FSTCLUSLO 26 |
108 | #define FATDIR_FILESIZE 28 | 100 | #define FATDIR_FILESIZE 28 |
109 | 101 | ||
102 | #define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4) | ||
103 | #define DIR_ENTRIES_PER_SECTOR (SECTOR_SIZE / 32) | ||
104 | #define DIR_ENTRY_SIZE 32 | ||
105 | #define FAT_BAD_MARK 0x0ffffff7 | ||
106 | #define FAT_EOF_MARK 0x0ffffff8 | ||
107 | |||
110 | struct fsinfo { | 108 | struct fsinfo { |
111 | int freecount; /* last known free cluster count */ | 109 | int freecount; /* last known free cluster count */ |
112 | int nextfree; /* first cluster to start looking for free clusters, | 110 | int nextfree; /* first cluster to start looking for free clusters, |
@@ -155,6 +153,7 @@ struct bpb | |||
155 | int rootdirsector; | 153 | int rootdirsector; |
156 | int firstdatasector; | 154 | int firstdatasector; |
157 | int startsector; | 155 | int startsector; |
156 | struct fsinfo fsinfo; | ||
158 | }; | 157 | }; |
159 | 158 | ||
160 | static struct bpb fat_bpb; | 159 | static struct bpb fat_bpb; |
@@ -167,6 +166,7 @@ static unsigned int getcurrdostime(unsigned short *dosdate, | |||
167 | unsigned short *dostime, | 166 | unsigned short *dostime, |
168 | unsigned char *dostenth); | 167 | unsigned char *dostenth); |
169 | static int create_dos_name(unsigned char *name, unsigned char *newname); | 168 | static int create_dos_name(unsigned char *name, unsigned char *newname); |
169 | static int find_free_cluster(int start); | ||
170 | #endif | 170 | #endif |
171 | 171 | ||
172 | #define FAT_CACHE_SIZE 0x20 | 172 | #define FAT_CACHE_SIZE 0x20 |
@@ -256,7 +256,6 @@ int fat_mount(int startsector) | |||
256 | fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS]; | 256 | fat_bpb.bpb_secperclus = buf[BPB_SECPERCLUS]; |
257 | fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); | 257 | fat_bpb.bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); |
258 | fat_bpb.bpb_numfats = buf[BPB_NUMFATS]; | 258 | fat_bpb.bpb_numfats = buf[BPB_NUMFATS]; |
259 | fat_bpb.bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); | ||
260 | fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); | 259 | fat_bpb.bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); |
261 | fat_bpb.bpb_media = buf[BPB_MEDIA]; | 260 | fat_bpb.bpb_media = buf[BPB_MEDIA]; |
262 | fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); | 261 | fat_bpb.bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); |
@@ -295,7 +294,7 @@ int fat_mount(int startsector) | |||
295 | #endif | 294 | #endif |
296 | { | 295 | { |
297 | DEBUGF("This is not FAT32. Go away!\n"); | 296 | DEBUGF("This is not FAT32. Go away!\n"); |
298 | return -1; | 297 | return -2; |
299 | } | 298 | } |
300 | 299 | ||
301 | fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); | 300 | fat_bpb.bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); |
@@ -316,11 +315,23 @@ int fat_mount(int startsector) | |||
316 | if (bpb_is_sane() < 0) | 315 | if (bpb_is_sane() < 0) |
317 | { | 316 | { |
318 | DEBUGF( "fat_mount() - BPB is not sane\n"); | 317 | DEBUGF( "fat_mount() - BPB is not sane\n"); |
319 | return -1; | 318 | return -3; |
320 | } | 319 | } |
321 | 320 | ||
322 | fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); | 321 | fat_bpb.rootdirsector = cluster2sec(fat_bpb.bpb_rootclus); |
323 | 322 | ||
323 | /* Read the fsinfo sector */ | ||
324 | err = ata_read_sectors(startsector + fat_bpb.bpb_fsinfo, 1, buf); | ||
325 | if (err) | ||
326 | { | ||
327 | DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", err); | ||
328 | return -1; | ||
329 | } | ||
330 | fat_bpb.fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT); | ||
331 | fat_bpb.fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE); | ||
332 | LDEBUGF("Freecount: %x\n",fat_bpb.fsinfo.freecount); | ||
333 | LDEBUGF("Nextfree: %x\n",fat_bpb.fsinfo.nextfree); | ||
334 | |||
324 | return 0; | 335 | return 0; |
325 | } | 336 | } |
326 | 337 | ||
@@ -339,9 +350,9 @@ static int bpb_is_sane(void) | |||
339 | fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus, | 350 | fat_bpb.bpb_bytspersec, fat_bpb.bpb_secperclus, |
340 | fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus); | 351 | fat_bpb.bpb_bytspersec * fat_bpb.bpb_secperclus); |
341 | } | 352 | } |
342 | if(fat_bpb.bpb_rsvdseccnt != 1) | 353 | if (fat_bpb.bpb_rsvdseccnt != 32) |
343 | { | 354 | { |
344 | DEBUGF( "bpb_is_sane() - Warning: Reserved sectors is not 1 (%d)\n", | 355 | DEBUGF( "bpb_is_sane() - Warning: Reserved sectors is not 32 (%d)\n", |
345 | fat_bpb.bpb_rsvdseccnt); | 356 | fat_bpb.bpb_rsvdseccnt); |
346 | } | 357 | } |
347 | if(fat_bpb.bpb_numfats != 2) | 358 | if(fat_bpb.bpb_numfats != 2) |
@@ -349,11 +360,6 @@ static int bpb_is_sane(void) | |||
349 | DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", | 360 | DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n", |
350 | fat_bpb.bpb_numfats); | 361 | fat_bpb.bpb_numfats); |
351 | } | 362 | } |
352 | if(fat_bpb.bpb_rootentcnt != 512) | ||
353 | { | ||
354 | DEBUGF( "bpb_is_sane() - Warning: RootEntCnt is not 512 (%d)\n", | ||
355 | fat_bpb.bpb_rootentcnt); | ||
356 | } | ||
357 | if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8) | 363 | if(fat_bpb.bpb_media != 0xf0 && fat_bpb.bpb_media < 0xf8) |
358 | { | 364 | { |
359 | DEBUGF( "bpb_is_sane() - Warning: Non-standard " | 365 | DEBUGF( "bpb_is_sane() - Warning: Non-standard " |
@@ -364,33 +370,42 @@ static int bpb_is_sane(void) | |||
364 | { | 370 | { |
365 | DEBUGF( "bpb_is_sane() - Error: Last word is not " | 371 | DEBUGF( "bpb_is_sane() - Error: Last word is not " |
366 | "0xaa55 (0x%04x)\n", fat_bpb.last_word); | 372 | "0xaa55 (0x%04x)\n", fat_bpb.last_word); |
367 | return -1; | 373 | return -4; |
374 | } | ||
375 | |||
376 | if (fat_bpb.fsinfo.freecount > | ||
377 | (fat_bpb.totalsectors - fat_bpb.firstdatasector)/ | ||
378 | fat_bpb.bpb_secperclus) | ||
379 | { | ||
380 | DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size " | ||
381 | "(0x%04x)\n", fat_bpb.fsinfo.freecount); | ||
382 | return -5; | ||
368 | } | 383 | } |
384 | |||
369 | return 0; | 385 | return 0; |
370 | } | 386 | } |
371 | 387 | ||
372 | static void *cache_fat_sector(int secnum) | 388 | static void *cache_fat_sector(int fatsector) |
373 | { | 389 | { |
390 | int secnum = fatsector + fat_bpb.bpb_rsvdseccnt; | ||
374 | int cache_index = secnum & FAT_CACHE_MASK; | 391 | int cache_index = secnum & FAT_CACHE_MASK; |
375 | 392 | ||
376 | /* Delete the cache entry if it isn't the sector we want */ | 393 | /* Delete the cache entry if it isn't the sector we want */ |
377 | if(fat_cache[cache_index].inuse && | 394 | if(fat_cache[cache_index].inuse && |
378 | fat_cache[cache_index].secnum != secnum) | 395 | fat_cache[cache_index].secnum != secnum) |
379 | { | 396 | { |
380 | #ifdef WRITE | ||
381 | /* Write back if it is dirty */ | 397 | /* Write back if it is dirty */ |
382 | if(fat_cache[cache_index].dirty) | 398 | if(fat_cache[cache_index].dirty) |
383 | { | 399 | { |
384 | if(ata_write_sectors(secnum + fat_bpb.startsector, 1, sec)) | 400 | if(ata_write_sectors(secnum + fat_bpb.startsector, 1, |
401 | fat_cache_sectors[cache_index])) | ||
385 | { | 402 | { |
386 | panic("cache_fat_sector() - Could" | 403 | panicf("cache_fat_sector() - Could not write sector %d\n", |
387 | " not write sector %d\n", | 404 | secnum); |
388 | secnum); | ||
389 | } | 405 | } |
390 | } | 406 | } |
391 | fat_cache[cache_index].secnum = 8; /* Normally an unused sector */ | 407 | fat_cache[cache_index].secnum = 8; /* Normally an unused sector */ |
392 | fat_cache[cache_index].dirty = false; | 408 | fat_cache[cache_index].dirty = false; |
393 | #endif | ||
394 | fat_cache[cache_index].inuse = false; | 409 | fat_cache[cache_index].inuse = false; |
395 | } | 410 | } |
396 | 411 | ||
@@ -409,101 +424,107 @@ static void *cache_fat_sector(int secnum) | |||
409 | return fat_cache_sectors[cache_index]; | 424 | return fat_cache_sectors[cache_index]; |
410 | } | 425 | } |
411 | 426 | ||
412 | #ifdef DISK_WRITE | 427 | static int find_free_cluster(int startcluster) |
413 | static int update_entry(int entry, unsigned int val) | ||
414 | { | 428 | { |
415 | unsigned long *sec; | 429 | int sector = startcluster / CLUSTERS_PER_FAT_SECTOR; |
416 | int fatoffset; | 430 | int offset = startcluster % CLUSTERS_PER_FAT_SECTOR; |
417 | int thisfatsecnum; | 431 | int i; |
418 | int thisfatentoffset; | ||
419 | 432 | ||
420 | fatoffset = entry * 4; | 433 | LDEBUGF("find_free_cluster(%x)\n",startcluster); |
421 | thisfatsecnum = fatoffset / fat_bpb.bpb_bytspersec + fat_bpb.bpb_rsvdseccnt; | ||
422 | thisfatentoffset = fatoffset % fat_bpb.bpb_bytspersec; | ||
423 | 434 | ||
424 | /* Load the sector if it is not cached */ | 435 | for (i = sector; i<fat_bpb.fatsize; i++) { |
425 | sec = cache_fat_sector(thisfatsecnum); | 436 | int j; |
426 | if(!sec) | 437 | unsigned int* fat = cache_fat_sector(i); |
438 | if ( !fat ) | ||
439 | break; | ||
440 | for (j = offset; j < CLUSTERS_PER_FAT_SECTOR; j++) | ||
441 | if (!(SWAB32(fat[j]) & 0x0fffffff)) { | ||
442 | int c = i * CLUSTERS_PER_FAT_SECTOR + j; | ||
443 | LDEBUGF("Found free cluster %x\n",c); | ||
444 | fat_bpb.fsinfo.nextfree = c; | ||
445 | return c; | ||
446 | } | ||
447 | } | ||
448 | return 0; /* 0 is an illegal cluster number */ | ||
449 | } | ||
450 | |||
451 | static int update_fat_entry(int entry, unsigned int val) | ||
452 | { | ||
453 | int sector = entry / CLUSTERS_PER_FAT_SECTOR; | ||
454 | int offset = entry % CLUSTERS_PER_FAT_SECTOR; | ||
455 | unsigned int* sec; | ||
456 | |||
457 | LDEBUGF("update_fat_entry(%x,%x)\n",entry,val); | ||
458 | |||
459 | sec = cache_fat_sector(sector); | ||
460 | if (!sec) | ||
427 | { | 461 | { |
428 | DEBUGF( "update_entry() - Could not cache sector %d\n", | 462 | DEBUGF( "update_entry() - Could not cache sector %d\n", sector); |
429 | thisfatsecnum); | ||
430 | return -1; | 463 | return -1; |
431 | } | 464 | } |
465 | fat_cache[sector & FAT_CACHE_MASK].dirty = true; | ||
432 | 466 | ||
433 | /* We can safely assume that the correct sector is in the cache, | 467 | if ( val ) { |
434 | so we mark it dirty without checking the sector number */ | 468 | if (!(sec[offset] & 0x0fffffff)) |
435 | fat_cache[thisfatsecnum & FAT_CACHE_MASK].dirty = 1; | 469 | fat_bpb.fsinfo.freecount--; |
470 | } | ||
471 | else | ||
472 | fat_bpb.fsinfo.freecount++; | ||
436 | 473 | ||
437 | /* don't change top 4 bits */ | 474 | /* don't change top 4 bits */ |
438 | sec[thisfatentoffset/sizeof(int)] &= 0xf000000; | 475 | sec[offset] &= SWAB32(0xf000000); |
439 | sec[thisfatentoffset/sizeof(int)] |= val & 0x0fffffff; | 476 | sec[offset] |= SWAB32(val & 0x0fffffff); |
440 | 477 | ||
441 | return 0; | 478 | return 0; |
442 | } | 479 | } |
443 | #endif | ||
444 | 480 | ||
445 | static int read_entry(int entry) | 481 | static int read_fat_entry(int entry) |
446 | { | 482 | { |
447 | unsigned long *sec; | 483 | int sector = entry / CLUSTERS_PER_FAT_SECTOR; |
448 | int fatoffset; | 484 | int offset = entry % CLUSTERS_PER_FAT_SECTOR; |
449 | int thisfatsecnum; | 485 | unsigned int* sec; |
450 | int thisfatentoffset; | ||
451 | int val = -1; | ||
452 | |||
453 | fatoffset = entry * 4; | ||
454 | thisfatsecnum = fatoffset / fat_bpb.bpb_bytspersec + fat_bpb.bpb_rsvdseccnt; | ||
455 | thisfatentoffset = fatoffset % fat_bpb.bpb_bytspersec; | ||
456 | 486 | ||
457 | /* Load the sector if it is not cached */ | 487 | sec = cache_fat_sector(sector); |
458 | sec = cache_fat_sector(thisfatsecnum); | 488 | if (!sec) |
459 | if(!sec) | ||
460 | { | 489 | { |
461 | DEBUGF( "read_entry() - Could not cache sector %d\n", | 490 | DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector); |
462 | thisfatsecnum); | ||
463 | return -1; | 491 | return -1; |
464 | } | 492 | } |
465 | 493 | ||
466 | val = sec[thisfatentoffset/sizeof(int)]; | 494 | return SWAB32(sec[offset]); |
467 | |||
468 | val = SWAB32(val); | ||
469 | |||
470 | return val; | ||
471 | } | 495 | } |
472 | 496 | ||
473 | static int get_next_cluster(unsigned int cluster) | 497 | static int get_next_cluster(unsigned int cluster) |
474 | { | 498 | { |
475 | int next_cluster; | 499 | int next_cluster; |
476 | 500 | ||
477 | next_cluster = read_entry(cluster); | 501 | next_cluster = read_fat_entry(cluster); |
478 | 502 | ||
479 | /* is this last cluster in chain? */ | 503 | /* is this last cluster in chain? */ |
480 | if ( next_cluster >= 0x0ffffff8 ) | 504 | if ( next_cluster >= FAT_EOF_MARK ) |
481 | return 0; | 505 | return 0; |
482 | else | 506 | else |
483 | return next_cluster; | 507 | return next_cluster; |
484 | } | 508 | } |
485 | 509 | ||
486 | #ifdef DISK_WRITE | 510 | static int flush_fat(void) |
487 | static int flush_fat(struct bpb *bpb) | ||
488 | { | 511 | { |
489 | int i; | 512 | int i; |
490 | int err; | 513 | int err; |
491 | unsigned char *sec; | 514 | unsigned char *sec; |
492 | int secnum; | 515 | int secnum; |
493 | int fatsz; | 516 | unsigned char fsinfo[SECTOR_SIZE]; |
494 | unsigned short d, t; | 517 | unsigned int* intptr; |
495 | char m; | ||
496 | 518 | ||
497 | fatsz = fat_bpb.fatsize; | 519 | LDEBUGF("flush_fat()\n"); |
498 | 520 | ||
499 | for(i = 0;i < FAT_CACHE_SIZE;i++) | 521 | for(i = 0;i < FAT_CACHE_SIZE;i++) |
500 | { | 522 | { |
501 | if(fat_cache[i].ptr && fat_cache[i].dirty) | 523 | if(fat_cache[i].inuse && fat_cache[i].dirty) |
502 | { | 524 | { |
503 | secnum = fat_cache[i].secnum + fat_bpb.bpb_rsvdseccnt + | 525 | secnum = fat_cache[i].secnum + fat_bpb.startsector; |
504 | fat_bpb.startsector; | 526 | LDEBUGF("Flushing FAT sector %x\n", secnum); |
505 | DEBUGF("Flushing FAT sector %d\n", secnum); | 527 | sec = fat_cache_sectors[i]; |
506 | sec = fat_cache[i].ptr; | ||
507 | 528 | ||
508 | /* Write to the first FAT */ | 529 | /* Write to the first FAT */ |
509 | err = ata_write_sectors(secnum, 1, sec); | 530 | err = ata_write_sectors(secnum, 1, sec); |
@@ -514,19 +535,41 @@ static int flush_fat(struct bpb *bpb) | |||
514 | return -1; | 535 | return -1; |
515 | } | 536 | } |
516 | 537 | ||
517 | /* Write to the second FAT */ | 538 | if(fat_bpb.bpb_numfats > 1 ) |
518 | err = ata_write_sectors(secnum + fatsz, 1, sec); | ||
519 | if(err) | ||
520 | { | 539 | { |
521 | DEBUGF( "flush_fat() - Couldn't write" | 540 | /* Write to the second FAT */ |
522 | " sector (%d)\n", secnum + fatsz); | 541 | err = ata_write_sectors(secnum + fat_bpb.fatsize, 1, sec); |
523 | return -1; | 542 | if (err) |
543 | { | ||
544 | DEBUGF( "flush_fat() - Couldn't write" | ||
545 | " sector (%d)\n", secnum + fat_bpb.fatsize); | ||
546 | return -2; | ||
547 | } | ||
524 | } | 548 | } |
525 | fat_cache[i].dirty = 0; | 549 | fat_cache[i].dirty = false; |
526 | } | 550 | } |
527 | } | 551 | } |
528 | 552 | ||
529 | getcurrdostime(&d, &t, &m); | 553 | /* update fsinfo */ |
554 | err = ata_read_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo, 1,fsinfo); | ||
555 | if (err) | ||
556 | { | ||
557 | DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", err); | ||
558 | return -1; | ||
559 | } | ||
560 | intptr = (int*)&(fsinfo[FSINFO_FREECOUNT]); | ||
561 | *intptr = SWAB32(fat_bpb.fsinfo.freecount); | ||
562 | |||
563 | intptr = (int*)&(fsinfo[FSINFO_NEXTFREE]); | ||
564 | *intptr = SWAB32(fat_bpb.fsinfo.nextfree); | ||
565 | |||
566 | err = ata_write_sectors(fat_bpb.startsector + fat_bpb.bpb_fsinfo,1,fsinfo); | ||
567 | if (err) | ||
568 | { | ||
569 | DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", err); | ||
570 | return -1; | ||
571 | } | ||
572 | |||
530 | return 0; | 573 | return 0; |
531 | } | 574 | } |
532 | 575 | ||
@@ -534,10 +577,9 @@ static unsigned int getcurrdostime(unsigned short *dosdate, | |||
534 | unsigned short *dostime, | 577 | unsigned short *dostime, |
535 | unsigned char *dostenth) | 578 | unsigned char *dostenth) |
536 | { | 579 | { |
537 | struct timeb tb; | 580 | #if 0 |
538 | struct tm *tm; | 581 | struct tm *tm; |
539 | 582 | unsigned long now = time(); | |
540 | ftime(&tb); | ||
541 | tm = localtime(&tb.time); | 583 | tm = localtime(&tb.time); |
542 | 584 | ||
543 | *dosdate = ((tm->tm_year - 80) << 9) | | 585 | *dosdate = ((tm->tm_year - 80) << 9) | |
@@ -549,102 +591,92 @@ static unsigned int getcurrdostime(unsigned short *dosdate, | |||
549 | (tm->tm_sec >> 1); | 591 | (tm->tm_sec >> 1); |
550 | 592 | ||
551 | *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10; | 593 | *dostenth = (tm->tm_sec & 1) * 100 + tb.millitm / 10; |
594 | #else | ||
595 | *dosdate = 0; | ||
596 | *dostime = 0; | ||
597 | *dostenth = 0; | ||
598 | #endif | ||
552 | return 0; | 599 | return 0; |
553 | } | 600 | } |
554 | 601 | ||
555 | static int add_dir_entry(unsigned int currdir, struct fat_direntry *de) | 602 | static int add_dir_entry(struct fat_dir* dir, |
603 | struct fat_direntry* de, | ||
604 | struct fat_file* file) | ||
556 | { | 605 | { |
557 | unsigned char buf[SECTOR_SIZE]; | 606 | unsigned char buf[SECTOR_SIZE]; |
558 | unsigned char *eptr; | 607 | unsigned char *eptr; |
559 | int i; | 608 | int i; |
560 | int err; | 609 | int err; |
561 | unsigned int sec; | 610 | int sec; |
562 | unsigned int sec_cnt; | 611 | int sec_cnt; |
563 | int need_to_update_last_empty_marker = 0; | 612 | bool need_to_update_last_empty_marker = false; |
564 | int is_rootdir = (currdir == 0); | 613 | bool done = false; |
565 | int done = 0; | ||
566 | unsigned char firstbyte; | 614 | unsigned char firstbyte; |
615 | int currdir = dir->startcluster; | ||
616 | bool is_rootdir = (currdir == 0); | ||
567 | 617 | ||
568 | if(is_rootdir) | 618 | LDEBUGF( "add_dir_entry()\n"); |
569 | { | 619 | |
620 | if (is_rootdir) | ||
570 | sec = fat_bpb.rootdirsector; | 621 | sec = fat_bpb.rootdirsector; |
571 | } | ||
572 | else | 622 | else |
573 | { | ||
574 | sec = first_sector_of_cluster(currdir); | 623 | sec = first_sector_of_cluster(currdir); |
575 | } | ||
576 | 624 | ||
577 | sec_cnt = 0; | 625 | sec_cnt = 0; |
578 | 626 | ||
579 | while(!done) | 627 | while(!done) |
580 | { | 628 | { |
581 | /* The root dir has a fixed size */ | 629 | if (sec_cnt >= fat_bpb.bpb_secperclus) |
582 | if(is_rootdir) | ||
583 | { | ||
584 | if(sec_cnt >= fat_bpb.bpb_rootentcnt * 32 / fat_bpb.bpb_bytspersec) | ||
585 | { | ||
586 | /* We have reached the last sector of the root dir */ | ||
587 | if(need_to_update_last_empty_marker) | ||
588 | { | ||
589 | /* Since the directory is full, there is no room for | ||
590 | a marker, so we just exit */ | ||
591 | return 0; | ||
592 | } | ||
593 | else | ||
594 | { | ||
595 | DEBUGF( "add_dir_entry() -" | ||
596 | " Root dir is full\n"); | ||
597 | return -1; | ||
598 | } | ||
599 | } | ||
600 | } | ||
601 | else | ||
602 | { | 630 | { |
603 | if(sec_cnt >= fat_bpb.bpb_secperclus) | 631 | int oldcluster = currdir; |
632 | /* We have reached the end of this cluster */ | ||
633 | LDEBUGF("Moving to the next cluster..."); | ||
634 | currdir = get_next_cluster(currdir); | ||
635 | LDEBUGF("new cluster is %d\n", currdir); | ||
636 | |||
637 | if (!currdir) | ||
604 | { | 638 | { |
605 | /* We have reached the end of this cluster */ | 639 | currdir = find_free_cluster(fat_bpb.fsinfo.nextfree); |
606 | DEBUGF("Moving to the next cluster..."); | 640 | if (!currdir) { |
607 | currdir = get_next_cluster(currdir); | 641 | currdir = find_free_cluster(0); |
608 | DEBUGF("new cluster is %d\n", currdir); | 642 | if (!currdir) { |
609 | 643 | DEBUGF("add_dir_entry(): Disk full!\n"); | |
610 | if(!currdir) | 644 | return -1; |
611 | { | 645 | } |
612 | /* This was the last in the chain, | ||
613 | we have to allocate a new cluster */ | ||
614 | /* TODO */ | ||
615 | } | 646 | } |
647 | update_fat_entry(oldcluster, currdir); | ||
616 | } | 648 | } |
617 | } | 649 | } |
618 | 650 | ||
619 | DEBUGF("Reading sector %d...\n", sec); | 651 | LDEBUGF("Reading sector %d...\n", sec); |
620 | /* Read the next sector in the current dir */ | 652 | /* Read the next sector in the current dir */ |
621 | err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); | 653 | err = ata_read_sectors(sec + fat_bpb.startsector,1,buf); |
622 | if(err) | 654 | if (err) |
623 | { | 655 | { |
624 | DEBUGF( "add_dir_entry() - Couldn't read dir sector" | 656 | DEBUGF( "add_dir_entry() - Couldn't read dir sector" |
625 | " (error code %d)\n", err); | 657 | " (error code %d)\n", err); |
626 | return -1; | 658 | return -2; |
627 | } | 659 | } |
628 | 660 | ||
629 | if(need_to_update_last_empty_marker) | 661 | if (need_to_update_last_empty_marker) |
630 | { | 662 | { |
631 | /* All we need to do is to set the first entry to 0 */ | 663 | /* All we need to do is to set the first entry to 0 */ |
632 | DEBUGF("Clearing the first entry in sector %d\n", sec); | 664 | LDEBUGF("Clearing the first entry in sector %x\n", sec); |
633 | buf[0] = 0; | 665 | buf[0] = 0; |
634 | done = 1; | 666 | done = true; |
635 | } | 667 | } |
636 | else | 668 | else |
637 | { | 669 | { |
638 | /* Look for a free slot */ | 670 | /* Look for a free slot */ |
639 | for(i = 0;i < SECTOR_SIZE;i+=32) | 671 | for (i = 0; i < SECTOR_SIZE; i += DIR_ENTRY_SIZE) |
640 | { | 672 | { |
641 | firstbyte = buf[i]; | 673 | firstbyte = buf[i]; |
642 | if(firstbyte == 0xe5 || firstbyte == 0) | 674 | if (firstbyte == 0xe5 || firstbyte == 0) |
643 | { | 675 | { |
644 | DEBUGF("Found free slot at entry %d in sector %d\n", | 676 | LDEBUGF("Found free slot at entry %d in sector %x\n", |
645 | i/32, sec); | 677 | i/DIR_ENTRY_SIZE, sec); |
646 | eptr = &buf[i]; | 678 | eptr = &buf[i]; |
647 | memset(eptr, 0, 32); | 679 | memset(eptr, 0, DIR_ENTRY_SIZE); |
648 | strncpy(&eptr[FATDIR_NAME], de->name, 11); | 680 | strncpy(&eptr[FATDIR_NAME], de->name, 11); |
649 | eptr[FATDIR_ATTR] = de->attr; | 681 | eptr[FATDIR_ATTR] = de->attr; |
650 | eptr[FATDIR_NTRES] = 0; | 682 | eptr[FATDIR_NTRES] = 0; |
@@ -665,31 +697,37 @@ static int add_dir_entry(unsigned int currdir, struct fat_direntry *de) | |||
665 | eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; | 697 | eptr[FATDIR_FILESIZE+2] = (de->filesize >> 16) & 0xff; |
666 | eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; | 698 | eptr[FATDIR_FILESIZE+3] = (de->filesize >> 24) & 0xff; |
667 | 699 | ||
700 | /* remember where the dir entry is located */ | ||
701 | file->dirsector = sec; | ||
702 | file->direntry = i/DIR_ENTRY_SIZE; | ||
703 | |||
668 | /* Advance the last_empty_entry marker */ | 704 | /* Advance the last_empty_entry marker */ |
669 | if(firstbyte == 0) | 705 | if (firstbyte == 0) |
670 | { | 706 | { |
671 | i += 32; | 707 | i += DIR_ENTRY_SIZE; |
672 | if(i < SECTOR_SIZE) | 708 | if (i < SECTOR_SIZE) |
673 | { | 709 | { |
674 | buf[i] = 0; | 710 | buf[i] = 0; |
675 | /* We are done */ | 711 | /* We are done */ |
676 | done = 1; | 712 | done = true; |
677 | } | 713 | } |
678 | else | 714 | else |
679 | { | 715 | { |
680 | /* We must fill in the first entry | 716 | /* We must fill in the first entry |
681 | in the next sector */ | 717 | in the next sector */ |
682 | need_to_update_last_empty_marker = 1; | 718 | need_to_update_last_empty_marker = true; |
683 | } | 719 | } |
684 | } | 720 | } |
721 | else | ||
722 | done = true; | ||
685 | 723 | ||
686 | err = ata_write_sectors(sec + fat_bpb.startsector,1,buf); | 724 | err = ata_write_sectors(sec + fat_bpb.startsector,1,buf); |
687 | if(err) | 725 | if (err) |
688 | { | 726 | { |
689 | DEBUGF( "add_dir_entry() - " | 727 | DEBUGF( "add_dir_entry() - " |
690 | " Couldn't write dir" | 728 | " Couldn't write dir" |
691 | " sector (error code %d)\n", err); | 729 | " sector (error code %d)\n", err); |
692 | return -1; | 730 | return -3; |
693 | } | 731 | } |
694 | break; | 732 | break; |
695 | } | 733 | } |
@@ -746,11 +784,6 @@ static int create_dos_name(unsigned char *name, unsigned char *newname) | |||
746 | int i; | 784 | int i; |
747 | char *ext; | 785 | char *ext; |
748 | 786 | ||
749 | if(strlen(name) > 12) | ||
750 | { | ||
751 | return -1; | ||
752 | } | ||
753 | |||
754 | strcpy(n, name); | 787 | strcpy(n, name); |
755 | 788 | ||
756 | ext = strchr(n, '.'); | 789 | ext = strchr(n, '.'); |
@@ -763,7 +796,7 @@ static int create_dos_name(unsigned char *name, unsigned char *newname) | |||
763 | In either case it is illegal. */ | 796 | In either case it is illegal. */ |
764 | if(n[0] == 0) | 797 | if(n[0] == 0) |
765 | { | 798 | { |
766 | return -1; | 799 | return -2; |
767 | } | 800 | } |
768 | 801 | ||
769 | /* Name part */ | 802 | /* Name part */ |
@@ -781,10 +814,10 @@ static int create_dos_name(unsigned char *name, unsigned char *newname) | |||
781 | } | 814 | } |
782 | 815 | ||
783 | /* Extension part */ | 816 | /* Extension part */ |
784 | for(i = 0;ext && ext[i] && (i < 3);i++) | 817 | for (i = 0;ext && ext[i] && (i < 3);i++) |
785 | { | 818 | { |
786 | c = char2dos(ext[i]); | 819 | c = char2dos(ext[i]); |
787 | if(c) | 820 | if (c) |
788 | { | 821 | { |
789 | newname[8+i] = toupper(c); | 822 | newname[8+i] = toupper(c); |
790 | } | 823 | } |
@@ -796,50 +829,48 @@ static int create_dos_name(unsigned char *name, unsigned char *newname) | |||
796 | return 0; | 829 | return 0; |
797 | } | 830 | } |
798 | 831 | ||
799 | int fat_create_dir(unsigned int currdir, char *name) | 832 | static void update_dir_entry( struct fat_file* file, int size ) |
800 | { | 833 | { |
801 | struct fat_direntry de; | 834 | unsigned char buf[SECTOR_SIZE]; |
835 | int sector = file->dirsector + fat_bpb.startsector; | ||
836 | unsigned char* entry = buf + file->direntry * DIR_ENTRY_SIZE; | ||
837 | unsigned int* sizeptr; | ||
838 | unsigned short* clusptr; | ||
802 | int err; | 839 | int err; |
803 | 840 | ||
804 | DEBUGF("fat_create_file()\n"); | 841 | LDEBUGF("update_dir_entry(cluster:%x entry:%d size:%d)\n", |
805 | memset(&de, 0, sizeof(struct fat_direntry)); | 842 | file->firstcluster,file->direntry,size); |
806 | if(create_dos_name(name, de.name) < 0) | 843 | |
844 | if ( file->direntry >= (SECTOR_SIZE / DIR_ENTRY_SIZE) ) { | ||
845 | DEBUGF("update_dir_entry(): Illegal entry %d!\n",file->direntry); | ||
846 | return; | ||
847 | } | ||
848 | |||
849 | err = ata_read_sectors(sector, 1, buf); | ||
850 | if (err) | ||
807 | { | 851 | { |
808 | DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name); | 852 | DEBUGF( "update_dir_entry() - Couldn't read dir sector %d" |
809 | return -1; | 853 | " (error code %d)\n", sector, err); |
854 | return; | ||
810 | } | 855 | } |
856 | |||
857 | clusptr = (short*)(entry + FATDIR_FSTCLUSHI); | ||
858 | *clusptr = SWAB16(file->firstcluster >> 16); | ||
811 | 859 | ||
812 | getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); | 860 | clusptr = (short*)(entry + FATDIR_FSTCLUSLO); |
813 | de.wrtdate = de.crtdate; | 861 | *clusptr = SWAB16(file->firstcluster & 0xffff); |
814 | de.wrttime = de.crttime; | ||
815 | de.filesize = 0; | ||
816 | de.attr = FAT_ATTR_DIRECTORY; | ||
817 | |||
818 | err = add_dir_entry(currdir, &de); | ||
819 | return 0; | ||
820 | } | ||
821 | 862 | ||
822 | int fat_create_file(unsigned int currdir, char *name) | 863 | sizeptr = (int*)(entry + FATDIR_FILESIZE); |
823 | { | 864 | *sizeptr = SWAB32(size); |
824 | struct fat_direntry de; | ||
825 | int err; | ||
826 | 865 | ||
827 | DEBUGF("fat_create_file()\n"); | 866 | err = ata_write_sectors(sector, 1, buf); |
828 | memset(&de, 0, sizeof(struct fat_direntry)); | 867 | if (err) |
829 | if(create_dos_name(name, de.name) < 0) | ||
830 | { | 868 | { |
831 | DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name); | 869 | DEBUGF( "update_file_size() - Couldn't write dir sector %d" |
832 | return -1; | 870 | " (error code %d)\n", sector, err); |
871 | return; | ||
833 | } | 872 | } |
834 | getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); | ||
835 | de.wrtdate = de.crtdate; | ||
836 | de.wrttime = de.crttime; | ||
837 | de.filesize = 0; | ||
838 | |||
839 | err = add_dir_entry(currdir, &de); | ||
840 | return err; | ||
841 | } | 873 | } |
842 | #endif | ||
843 | 874 | ||
844 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) | 875 | static int parse_direntry(struct fat_direntry *de, unsigned char *buf) |
845 | { | 876 | { |
@@ -866,37 +897,138 @@ static int parse_direntry(struct fat_direntry *de, unsigned char *buf) | |||
866 | return 1; | 897 | return 1; |
867 | } | 898 | } |
868 | 899 | ||
869 | int fat_open( unsigned int startcluster, struct fat_file *file) | 900 | int fat_open(unsigned int startcluster, |
901 | struct fat_file *file, | ||
902 | struct fat_dir* dir) | ||
870 | { | 903 | { |
871 | file->firstcluster = startcluster; | 904 | file->firstcluster = startcluster; |
872 | file->nextcluster = startcluster; | 905 | file->nextcluster = startcluster; |
873 | file->nextsector = cluster2sec(startcluster); | 906 | file->nextsector = cluster2sec(startcluster); |
874 | file->sectornum = 0; | 907 | file->sectornum = 0; |
908 | |||
909 | /* remember where the file's dir entry is located */ | ||
910 | file->dirsector = dir->cached_sec; | ||
911 | file->direntry = (dir->entry % DIR_ENTRIES_PER_SECTOR) - 1; | ||
912 | LDEBUGF("fat_open: entry %d\n",file->direntry); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | int fat_create_file(char* name, | ||
917 | struct fat_file* file, | ||
918 | struct fat_dir* dir) | ||
919 | { | ||
920 | struct fat_direntry de; | ||
921 | int err; | ||
922 | |||
923 | LDEBUGF("fat_create_file(\"%s\",%x,%x)\n",name,file,dir); | ||
924 | memset(&de, 0, sizeof(struct fat_direntry)); | ||
925 | if (create_dos_name(name, de.name) < 0) | ||
926 | { | ||
927 | DEBUGF( "fat_create_file() - Illegal file name (%s)\n", name); | ||
928 | return -1; | ||
929 | } | ||
930 | getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); | ||
931 | de.wrtdate = de.crtdate; | ||
932 | de.wrttime = de.crttime; | ||
933 | de.filesize = 0; | ||
934 | |||
935 | err = add_dir_entry(dir, &de, file); | ||
936 | if (!err) { | ||
937 | file->firstcluster = 0; | ||
938 | file->nextcluster = 0; | ||
939 | file->nextsector = 0; | ||
940 | file->sectornum = 0; | ||
941 | } | ||
942 | |||
943 | return err; | ||
944 | } | ||
945 | |||
946 | int fat_closewrite(struct fat_file *file, int size) | ||
947 | { | ||
948 | int endcluster = file->nextcluster; | ||
949 | int next, last = endcluster; | ||
950 | |||
951 | /* free unused clusters, if any */ | ||
952 | for ( next = get_next_cluster(last); next; last = next ) { | ||
953 | LDEBUGF("Clearing cluster %x\n",last); | ||
954 | update_fat_entry(last,0); | ||
955 | } | ||
956 | |||
957 | /* mark last used cluster as last in chain */ | ||
958 | update_fat_entry(endcluster, FAT_EOF_MARK); | ||
959 | |||
960 | flush_fat(); | ||
961 | |||
962 | update_dir_entry(file, size); | ||
963 | |||
875 | return 0; | 964 | return 0; |
876 | } | 965 | } |
877 | 966 | ||
878 | int fat_read( struct fat_file *file, int sectorcount, void* buf ) | 967 | int fat_readwrite( struct fat_file *file, int sectorcount, |
968 | void* buf, bool write ) | ||
879 | { | 969 | { |
880 | int cluster = file->nextcluster; | 970 | int cluster = file->nextcluster; |
881 | int sector = file->nextsector; | 971 | int sector = file->nextsector; |
882 | int numsec = file->sectornum; | 972 | int numsec = file->sectornum; |
883 | int first = sector, last = sector; | 973 | int first, last; |
884 | int err, i; | 974 | int err, i; |
885 | 975 | ||
976 | LDEBUGF( "fat_readwrite(file:%x,count:%d,buf:%x,%s)\n", | ||
977 | cluster,sectorcount,buf,write?"write":"read"); | ||
978 | |||
886 | if ( sector == -1 ) | 979 | if ( sector == -1 ) |
887 | return 0; | 980 | return 0; |
888 | 981 | ||
889 | /* find sequential sectors and read them all at once */ | 982 | if ( write && !cluster) { |
983 | /* new file */ | ||
984 | cluster = find_free_cluster(fat_bpb.fsinfo.nextfree); | ||
985 | if (!cluster) { | ||
986 | cluster = find_free_cluster(0); | ||
987 | if (!cluster) { | ||
988 | DEBUGF("fat_readwrite(): Disk full!\n"); | ||
989 | return -3; | ||
990 | } | ||
991 | } | ||
992 | file->firstcluster = cluster; | ||
993 | sector = cluster2sec(cluster); | ||
994 | if (sector<0) | ||
995 | return -1; | ||
996 | } | ||
997 | |||
998 | first = sector; | ||
999 | last = sector; | ||
1000 | |||
1001 | /* find sequential sectors and read/write them all at once */ | ||
890 | for (i=0; i<sectorcount && sector>=0; i++ ) { | 1002 | for (i=0; i<sectorcount && sector>=0; i++ ) { |
891 | numsec++; | 1003 | numsec++; |
892 | if ( numsec >= fat_bpb.bpb_secperclus ) { | 1004 | if ( numsec >= fat_bpb.bpb_secperclus ) { |
1005 | int oldcluster = cluster; | ||
893 | cluster = get_next_cluster(cluster); | 1006 | cluster = get_next_cluster(cluster); |
894 | if (!cluster) { | 1007 | if (!cluster) { |
895 | /* end of file */ | 1008 | if ( write ) { |
896 | sector = -1; | 1009 | /* writing past end-of-file, |
1010 | find a new free cluster to use. */ | ||
1011 | cluster = find_free_cluster(cluster); | ||
1012 | if (!cluster) { | ||
1013 | /* no cluster found after last, | ||
1014 | search from beginning */ | ||
1015 | cluster = find_free_cluster(0); | ||
1016 | if (!cluster) { | ||
1017 | /* no free clusters. disk is full. */ | ||
1018 | sector = -1; | ||
1019 | DEBUGF("fat_readwrite(): Disk full!\n"); | ||
1020 | } | ||
1021 | } | ||
1022 | if ( cluster ) | ||
1023 | update_fat_entry(oldcluster, cluster); | ||
1024 | } | ||
1025 | else { | ||
1026 | /* reading past end-of-file */ | ||
1027 | sector = -1; | ||
1028 | } | ||
897 | } | 1029 | } |
898 | else | 1030 | |
899 | { | 1031 | if (cluster) { |
900 | sector = cluster2sec(cluster); | 1032 | sector = cluster2sec(cluster); |
901 | if (sector<0) | 1033 | if (sector<0) |
902 | return -1; | 1034 | return -1; |
@@ -910,11 +1042,14 @@ int fat_read( struct fat_file *file, int sectorcount, void* buf ) | |||
910 | (i == sectorcount-1) || /* last sector requested? */ | 1042 | (i == sectorcount-1) || /* last sector requested? */ |
911 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ | 1043 | (last-first+1 == 256) ) { /* max 256 sectors per ata request */ |
912 | int count = last-first+1; | 1044 | int count = last-first+1; |
913 | err = ata_read_sectors(first + fat_bpb.startsector, count, buf); | 1045 | if (write) |
914 | if(err) { | 1046 | err = ata_write_sectors(first + fat_bpb.startsector, count, buf); |
915 | DEBUGF( "fat_read() - Couldn't read sector %d" | 1047 | else |
1048 | err = ata_read_sectors(first + fat_bpb.startsector, count, buf); | ||
1049 | if (err) { | ||
1050 | DEBUGF( "fat_readwrite() - Couldn't read sector %d" | ||
916 | " (error code %d)\n", sector,err); | 1051 | " (error code %d)\n", sector,err); |
917 | return -1; | 1052 | return -2; |
918 | } | 1053 | } |
919 | ((char*)buf) += count * SECTOR_SIZE; | 1054 | ((char*)buf) += count * SECTOR_SIZE; |
920 | first = sector; | 1055 | first = sector; |
@@ -970,9 +1105,9 @@ int fat_seek(struct fat_file *file, int seeksector ) | |||
970 | return 0; | 1105 | return 0; |
971 | } | 1106 | } |
972 | 1107 | ||
973 | int fat_opendir(struct fat_dir *dir, unsigned int currdir) | 1108 | int fat_opendir(struct fat_dir *dir, unsigned int startcluster) |
974 | { | 1109 | { |
975 | int is_rootdir = (currdir == 0); | 1110 | int is_rootdir = (startcluster == 0); |
976 | unsigned int sec; | 1111 | unsigned int sec; |
977 | int err; | 1112 | int err; |
978 | 1113 | ||
@@ -982,7 +1117,7 @@ int fat_opendir(struct fat_dir *dir, unsigned int currdir) | |||
982 | } | 1117 | } |
983 | else | 1118 | else |
984 | { | 1119 | { |
985 | sec = first_sector_of_cluster(currdir); | 1120 | sec = first_sector_of_cluster(startcluster); |
986 | } | 1121 | } |
987 | 1122 | ||
988 | /* Read the first sector in the current dir */ | 1123 | /* Read the first sector in the current dir */ |
@@ -997,13 +1132,14 @@ int fat_opendir(struct fat_dir *dir, unsigned int currdir) | |||
997 | dir->entry = 0; | 1132 | dir->entry = 0; |
998 | dir->cached_sec = sec; | 1133 | dir->cached_sec = sec; |
999 | dir->num_sec = 0; | 1134 | dir->num_sec = 0; |
1135 | dir->startcluster = startcluster; | ||
1000 | 1136 | ||
1001 | return 0; | 1137 | return 0; |
1002 | } | 1138 | } |
1003 | 1139 | ||
1004 | int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | 1140 | int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) |
1005 | { | 1141 | { |
1006 | int done = 0; | 1142 | bool done = false; |
1007 | int i; | 1143 | int i; |
1008 | int err; | 1144 | int err; |
1009 | unsigned char firstbyte; | 1145 | unsigned char firstbyte; |
@@ -1013,29 +1149,30 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1013 | 1149 | ||
1014 | while(!done) | 1150 | while(!done) |
1015 | { | 1151 | { |
1016 | for(i = dir->entry;i < SECTOR_SIZE/32;i++) | 1152 | for (i = dir->entry; i < SECTOR_SIZE/DIR_ENTRY_SIZE; i++) |
1017 | { | 1153 | { |
1018 | firstbyte = dir->cached_buf[i*32]; | 1154 | firstbyte = dir->cached_buf[i*DIR_ENTRY_SIZE]; |
1019 | 1155 | ||
1020 | if(firstbyte == 0xe5) { | 1156 | if (firstbyte == 0xe5) { |
1021 | /* free entry */ | 1157 | /* free entry */ |
1022 | sectoridx = 0; | 1158 | sectoridx = 0; |
1023 | continue; | 1159 | continue; |
1024 | } | 1160 | } |
1025 | 1161 | ||
1026 | if(firstbyte == 0) { | 1162 | if (firstbyte == 0) { |
1027 | /* last entry */ | 1163 | /* last entry */ |
1028 | entry->name[0] = 0; | 1164 | entry->name[0] = 0; |
1029 | return 0; | 1165 | return 0; |
1030 | } | 1166 | } |
1031 | 1167 | ||
1032 | /* longname entry? */ | 1168 | /* longname entry? */ |
1033 | if ( ( dir->cached_buf[i*32 + FATDIR_ATTR] & | 1169 | if ( ( dir->cached_buf[i*DIR_ENTRY_SIZE + FATDIR_ATTR] & |
1034 | FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { | 1170 | FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) { |
1035 | longarray[longs++] = i*32 + sectoridx; | 1171 | longarray[longs++] = i*DIR_ENTRY_SIZE + sectoridx; |
1036 | } | 1172 | } |
1037 | else { | 1173 | else { |
1038 | if ( parse_direntry(entry, &dir->cached_buf[i*32]) ) { | 1174 | if ( parse_direntry(entry, |
1175 | &dir->cached_buf[i*DIR_ENTRY_SIZE]) ) { | ||
1039 | 1176 | ||
1040 | /* don't return volume id entry */ | 1177 | /* don't return volume id entry */ |
1041 | if ( entry->attr == FAT_ATTR_VOLUME_ID ) | 1178 | if ( entry->attr == FAT_ATTR_VOLUME_ID ) |
@@ -1076,7 +1213,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1076 | } | 1213 | } |
1077 | entry->name[l]=0; | 1214 | entry->name[l]=0; |
1078 | } | 1215 | } |
1079 | done = 1; | 1216 | done = true; |
1080 | sectoridx = 0; | 1217 | sectoridx = 0; |
1081 | break; | 1218 | break; |
1082 | } | 1219 | } |
@@ -1091,7 +1228,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1091 | sectoridx += SECTOR_SIZE; | 1228 | sectoridx += SECTOR_SIZE; |
1092 | 1229 | ||
1093 | /* Next sector? */ | 1230 | /* Next sector? */ |
1094 | if(i < SECTOR_SIZE/32) | 1231 | if (i < SECTOR_SIZE / DIR_ENTRY_SIZE) |
1095 | { | 1232 | { |
1096 | i++; | 1233 | i++; |
1097 | } | 1234 | } |
@@ -1100,7 +1237,7 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1100 | dir->num_sec++; | 1237 | dir->num_sec++; |
1101 | 1238 | ||
1102 | /* Do we need to advance one cluster? */ | 1239 | /* Do we need to advance one cluster? */ |
1103 | if(dir->num_sec < fat_bpb.bpb_secperclus) | 1240 | if (dir->num_sec < fat_bpb.bpb_secperclus) |
1104 | { | 1241 | { |
1105 | dir->cached_sec++; | 1242 | dir->cached_sec++; |
1106 | } | 1243 | } |
@@ -1113,16 +1250,16 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1113 | } | 1250 | } |
1114 | dir->num_sec = 0; | 1251 | dir->num_sec = 0; |
1115 | cluster = get_next_cluster( cluster ); | 1252 | cluster = get_next_cluster( cluster ); |
1116 | if(!cluster) | 1253 | if (!cluster) |
1117 | { | 1254 | { |
1118 | DEBUGF("End of cluster chain.\n"); | 1255 | DEBUGF("End of cluster chain.\n"); |
1119 | return -1; | 1256 | return -2; |
1120 | } | 1257 | } |
1121 | dir->cached_sec = cluster2sec(cluster); | 1258 | dir->cached_sec = cluster2sec(cluster); |
1122 | if ( dir->cached_sec < 0 ) | 1259 | if ( dir->cached_sec < 0 ) |
1123 | { | 1260 | { |
1124 | DEBUGF("Invalid cluster: %d\n",cluster); | 1261 | DEBUGF("Invalid cluster: %d\n",cluster); |
1125 | return -1; | 1262 | return -3; |
1126 | } | 1263 | } |
1127 | 1264 | ||
1128 | } | 1265 | } |
@@ -1130,11 +1267,11 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry) | |||
1130 | /* Read the next sector */ | 1267 | /* Read the next sector */ |
1131 | err = ata_read_sectors(dir->cached_sec + fat_bpb.startsector, 1, | 1268 | err = ata_read_sectors(dir->cached_sec + fat_bpb.startsector, 1, |
1132 | dir->cached_buf); | 1269 | dir->cached_buf); |
1133 | if(err) | 1270 | if (err) |
1134 | { | 1271 | { |
1135 | DEBUGF( "fat_getnext() - Couldn't read dir sector" | 1272 | DEBUGF( "fat_getnext() - Couldn't read dir sector" |
1136 | " (error code %d)\n", err); | 1273 | " (error code %d)\n", err); |
1137 | return -1; | 1274 | return -4; |
1138 | } | 1275 | } |
1139 | 1276 | ||
1140 | i = 0; | 1277 | i = 0; |