1 //---------------------------------------------------------------------------
2 //File name: fat_driver.c
3 //---------------------------------------------------------------------------
13 //#include <sys/stat.h>
17 #define malloc(a) AllocSysMemory(0,(a), NULL)
18 #define free(a) FreeSysMemory((a))
21 #include "usbhd_common.h"
23 #include "fat_driver.h"
25 //#include "fat_write.h"
26 #include "mass_stor.h"
28 //#define DEBUG //comment out this line when not debugging
30 #include "mass_debug.h"
32 //#define DISK_INIT(d,b) scache_init((d), (b))
33 //#define DISK_CLOSE scache_close
34 //#define DISK_KILL scache_kill //dlanor: added for disconnection events (no flush)
35 #define READ_SECTOR(d, a, b) scache_readSector((d)->cache, (a), (void **)&b)
36 //#define FLUSH_SECTORS scache_flushSectors
39 static fat_driver
* g_fatd
[NUM_DRIVES
];
41 //---------------------------------------------------------------------------
46 for (i
= 0; i
< NUM_DRIVES
; ++i
)
51 //---------------------------------------------------------------------------
52 int strEqual(const unsigned char *s1
, const unsigned char* s2
) {
57 if (u1
>64 && u1
< 91) u1
+=32;
58 if (u2
>64 && u2
< 91) u2
+=32;
80 //---------------------------------------------------------------------------
81 unsigned int fat_getClusterRecord12(unsigned char* buf
, int type
) {
83 return ((buf
[1]<< 4) + (buf
[0] >>4));
85 return (((buf
[1] & 0x0F) << 8) + buf
[0]);
89 //---------------------------------------------------------------------------
90 // Get Cluster chain into <buf> buffer
92 // 0 :if buf is full (bufSize entries) and more chain entries exist
93 // 1-n :number of filled entries of the buf
95 //---------------------------------------------------------------------------
97 /* fat12 cluster records can overlap the edge of the sector so we need to detect and maintain
100 int fat_getClusterChain12(fat_driver
* fatd
, unsigned int cluster
, unsigned int* buf
, int bufSize
, int start
) {
108 unsigned char xbuf
[4];
109 unsigned char* sbuf
= NULL
; //sector buffer
115 buf
[i
] = cluster
; //strore first cluster
118 while(i
< bufSize
&& cont
) {
119 recordOffset
= (cluster
* 3) / 2; //offset of the cluster record (in bytes) from the FAT start
120 fatSector
= recordOffset
/ fatd
->partBpb
.sectorSize
;
122 if ((recordOffset
% fatd
->partBpb
.sectorSize
) == (fatd
->partBpb
.sectorSize
- 1)) {
125 if (lastFatSector
!= fatSector
|| sectorSpan
) {
126 ret
= READ_SECTOR(fatd
->dev
, fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
, sbuf
);
128 printf("USBHDFSD: Read fat12 sector failed! sector=%i! \n", fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
);
131 lastFatSector
= fatSector
;
134 xbuf
[0] = sbuf
[fatd
->partBpb
.sectorSize
- 2];
135 xbuf
[1] = sbuf
[fatd
->partBpb
.sectorSize
- 1];
136 ret
= READ_SECTOR(fatd
->dev
, fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
+ 1, sbuf
);
138 printf("USBHDFSD: Read fat12 sector failed sector=%i! \n", fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
+ 1);
145 if (sectorSpan
) { // use xbuf as source buffer
146 cluster
= fat_getClusterRecord12(xbuf
+ (recordOffset
% fatd
->partBpb
.sectorSize
) - (fatd
->partBpb
.sectorSize
-2), cluster
% 2);
147 } else { // use sector buffer as source buffer
148 cluster
= fat_getClusterRecord12(sbuf
+ (recordOffset
% fatd
->partBpb
.sectorSize
), cluster
% 2);
151 if ((cluster
& 0xFFF) >= 0xFF8) {
152 cont
= 0; //continue = false
154 buf
[i
] = cluster
& 0xFFF;
162 //---------------------------------------------------------------------------
164 int fat_getClusterChain16(fat_driver
* fatd
, unsigned int cluster
, unsigned int* buf
, int bufSize
, int start
) {
171 unsigned char* sbuf
= NULL
; //sector buffer
174 indexCount
= fatd
->partBpb
.sectorSize
/ 2; //FAT16->2, FAT32->4
178 buf
[i
] = cluster
; //strore first cluster
181 while(i
< bufSize
&& cont
) {
182 fatSector
= cluster
/ indexCount
;
183 if (lastFatSector
!= fatSector
) {
184 ret
= READ_SECTOR(fatd
->dev
, fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
, sbuf
);
186 printf("USBHDFSD: Read fat16 sector failed! sector=%i! \n", fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
);
190 lastFatSector
= fatSector
;
192 cluster
= getI16(sbuf
+ ((cluster
% indexCount
) * 2));
193 if ((cluster
& 0xFFFF) >= 0xFFF8) {
194 cont
= 0; //continue = false
196 buf
[i
] = cluster
& 0xFFFF;
203 //---------------------------------------------------------------------------
205 int fat_getClusterChain32(fat_driver
* fatd
, unsigned int cluster
, unsigned int* buf
, int bufSize
, int start
) {
212 unsigned char* sbuf
= NULL
; //sector buffer
215 indexCount
= fatd
->partBpb
.sectorSize
/ 4; //FAT16->2, FAT32->4
219 buf
[i
] = cluster
; //store first cluster
222 while(i
< bufSize
&& cont
) {
223 fatSector
= cluster
/ indexCount
;
224 if (lastFatSector
!= fatSector
) {
225 ret
= READ_SECTOR(fatd
->dev
, fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
, sbuf
);
227 printf("USBHDFSD: Read fat32 sector failed sector=%i! \n", fatd
->partBpb
.partStart
+ fatd
->partBpb
.resSectors
+ fatSector
);
231 lastFatSector
= fatSector
;
233 cluster
= getI32(sbuf
+ ((cluster
% indexCount
) * 4));
234 if ((cluster
& 0xFFFFFFF) >= 0xFFFFFF8) {
235 cont
= 0; //continue = false
237 buf
[i
] = cluster
& 0xFFFFFFF;
244 //---------------------------------------------------------------------------
245 int fat_getClusterChain(fat_driver
* fatd
, unsigned int cluster
, unsigned int* buf
, int bufSize
, int start
) {
247 if (cluster
== fatd
->lastChainCluster
) {
248 return fatd
->lastChainResult
;
251 switch (fatd
->partBpb
.fatType
) {
252 case FAT12
: fatd
->lastChainResult
= fat_getClusterChain12(fatd
, cluster
, buf
, bufSize
, start
); break;
253 case FAT16
: fatd
->lastChainResult
= fat_getClusterChain16(fatd
, cluster
, buf
, bufSize
, start
); break;
254 case FAT32
: fatd
->lastChainResult
= fat_getClusterChain32(fatd
, cluster
, buf
, bufSize
, start
); break;
256 fatd
->lastChainCluster
= cluster
;
257 return fatd
->lastChainResult
;
260 //---------------------------------------------------------------------------
261 void fat_invalidateLastChainResult(fat_driver
* fatd
)
263 fatd
->lastChainCluster
= 0;
266 //---------------------------------------------------------------------------
267 void fat_determineFatType(fat_bpb
* partBpb
) {
271 //get sector of cluster 0
272 sector
= fat_cluster2sector(partBpb
, 0);
273 //remove partition start sector to get BR+FAT+ROOT_DIR sector count
274 sector
-= partBpb
->partStart
;
275 sector
= partBpb
->sectorCount
- sector
;
276 clusterCount
= sector
/ partBpb
->clusterSize
;
277 //printf("USBHDFSD: Data cluster count = %i \n", clusterCount);
279 if (clusterCount
< 4085) {
280 partBpb
->fatType
= FAT12
;
282 if (clusterCount
< 65525) {
283 partBpb
->fatType
= FAT16
;
285 partBpb
->fatType
= FAT32
;
289 //---------------------------------------------------------------------------
290 int fat_getPartitionBootSector(mass_dev
* dev
, unsigned int sector
, fat_bpb
* partBpb
) {
291 fat_raw_bpb
* bpb_raw
; //fat16, fat12
292 fat32_raw_bpb
* bpb32_raw
; //fat32
294 unsigned char* sbuf
= NULL
; //sector buffer
296 ret
= READ_SECTOR(dev
, sector
, sbuf
); //read partition boot sector (first sector on partition)
298 printf("USBHDFSD: Read partition boot sector failed sector=%i! \n", sector
);
302 bpb_raw
= (fat_raw_bpb
*) sbuf
;
303 bpb32_raw
= (fat32_raw_bpb
*) sbuf
;
305 //set fat common properties
306 partBpb
->sectorSize
= getI16(bpb_raw
->sectorSize
);
307 partBpb
->clusterSize
= bpb_raw
->clusterSize
;
308 partBpb
->resSectors
= getI16(bpb_raw
->resSectors
);
309 partBpb
->fatCount
= bpb_raw
->fatCount
;
310 partBpb
->rootSize
= getI16(bpb_raw
->rootSize
);
311 partBpb
->fatSize
= getI16(bpb_raw
->fatSize
);
312 partBpb
->trackSize
= getI16(bpb_raw
->trackSize
);
313 partBpb
->headCount
= getI16(bpb_raw
->headCount
);
314 partBpb
->sectorCount
= getI16(bpb_raw
->sectorCountO
);
315 if (partBpb
->sectorCount
== 0) {
316 partBpb
->sectorCount
= getI32(bpb_raw
->sectorCount
); // large partition
318 partBpb
->partStart
= sector
;
319 partBpb
->rootDirStart
= partBpb
->partStart
+ (partBpb
->fatCount
* partBpb
->fatSize
) + partBpb
->resSectors
;
320 for (ret
= 0; ret
< 8; ret
++) {
321 partBpb
->fatId
[ret
] = bpb_raw
->fatId
[ret
];
323 partBpb
->fatId
[ret
] = 0;
324 partBpb
->rootDirCluster
= 0;
325 partBpb
->dataStart
= partBpb
->rootDirStart
+ (partBpb
->rootSize
/ (partBpb
->sectorSize
>> 5));
327 fat_determineFatType(partBpb
);
329 //fat32 specific info
330 if (partBpb
->fatType
== FAT32
&& partBpb
->fatSize
== 0) {
331 partBpb
->fatSize
= getI32(bpb32_raw
->fatSize32
);
332 partBpb
->activeFat
= getI16(bpb32_raw
->fatStatus
);
333 if (partBpb
->activeFat
& 0x80) { //fat not synced
334 partBpb
->activeFat
= (partBpb
->activeFat
& 0xF);
336 partBpb
->activeFat
= 0;
338 partBpb
->rootDirStart
= partBpb
->partStart
+ (partBpb
->fatCount
* partBpb
->fatSize
) + partBpb
->resSectors
;
339 partBpb
->rootDirCluster
= getI32(bpb32_raw
->rootDirCluster
);
340 for (ret
= 0; ret
< 8; ret
++) {
341 partBpb
->fatId
[ret
] = bpb32_raw
->fatId
[ret
];
343 partBpb
->fatId
[ret
] = 0;
344 partBpb
->dataStart
= partBpb
->rootDirStart
;
346 printf("USBHDFSD: Fat type %i Id %s \n", partBpb
->fatType
, partBpb
->fatId
);
350 //---------------------------------------------------------------------------
353 0 - no more dir entries
354 1 - short name dir entry found
355 2 - long name dir entry found
356 3 - deleted dir entry found
358 int fat_getDirentry(unsigned char fatType
, fat_direntry
* dir_entry
, fat_direntry_summary
* dir
) {
363 //detect last entry - all zeros (slight modification by radad)
364 if (dir_entry
->sfn
.name
[0] == 0) {
367 //detect deleted entry - it will be ignored
368 if (dir_entry
->sfn
.name
[0] == 0xE5) {
372 //detect long filename
373 if (dir_entry
->lfn
.rshv
== 0x0F && dir_entry
->lfn
.reserved1
== 0x00 && dir_entry
->lfn
.reserved2
[0] == 0x00) {
374 //long filename - almost whole direntry is unicode string - extract it
375 offset
= dir_entry
->lfn
.entrySeq
& 0x3f;
377 offset
= offset
* 13;
380 for (i
= 0; i
< 10 && cont
; i
+=2) {
381 if (dir_entry
->lfn
.name1
[i
]==0 && dir_entry
->lfn
.name1
[i
+1] == 0) {
382 dir
->name
[offset
] = 0; //terminate
385 dir
->name
[offset
] = dir_entry
->lfn
.name1
[i
];
390 for (i
= 0; i
< 12 && cont
; i
+=2) {
391 if (dir_entry
->lfn
.name2
[i
]==0 && dir_entry
->lfn
.name2
[i
+1] == 0) {
392 dir
->name
[offset
] = 0; //terminate
395 dir
->name
[offset
] = dir_entry
->lfn
.name2
[i
];
400 for (i
= 0; i
< 4 && cont
; i
+=2) {
401 if (dir_entry
->lfn
.name3
[i
]==0 && dir_entry
->lfn
.name3
[i
+1] == 0) {
402 dir
->name
[offset
] = 0; //terminate
405 dir
->name
[offset
] = dir_entry
->lfn
.name3
[i
];
409 if ((dir_entry
->lfn
.entrySeq
& 0x40)) { //terminate string flag
410 dir
->name
[offset
] = 0;
416 for (i
= 0; i
< 8 && dir_entry
->sfn
.name
[i
]!= 32; i
++) {
417 dir
->sname
[i
] = dir_entry
->sfn
.name
[i
];
418 // NT—adaption for LaunchELF
419 if (dir_entry
->sfn
.reservedNT
& 0x08 &&
420 dir
->sname
[i
] >= 'A' && dir
->sname
[i
] <= 'Z') {
421 dir
->sname
[i
] += 0x20; //Force standard letters in name to lower case
424 for (j
=0; j
< 3 && dir_entry
->sfn
.ext
[j
] != 32; j
++) {
429 dir
->sname
[i
+j
] = dir_entry
->sfn
.ext
[j
];
430 // NT—adaption for LaunchELF
431 if (dir_entry
->sfn
.reservedNT
& 0x10 &&
432 dir
->sname
[i
+j
] >= 'A' && dir
->sname
[i
+j
] <= 'Z') {
433 dir
->sname
[i
+j
] += 0x20; //Force standard letters in ext to lower case
436 dir
->sname
[i
+j
] = 0; //terminate
437 if (dir
->name
[0] == 0) { //long name desn't exit
438 for (i
=0 ; dir
->sname
[i
] !=0; i
++) dir
->name
[i
] = dir
->sname
[i
];
441 dir
->attr
= dir_entry
->sfn
.attr
;
442 dir
->size
= getI32(dir_entry
->sfn
.size
);
443 if (fatType
== FAT32
)
444 dir
->cluster
= getI32_2(dir_entry
->sfn
.clusterL
, dir_entry
->sfn
.clusterH
);
446 dir
->cluster
= getI16(dir_entry
->sfn
.clusterL
);
451 //---------------------------------------------------------------------------
452 //Set chain info (cluster/offset) cache
453 void fat_setFatDirChain(fat_driver
* fatd
, fat_dir
* fatDir
) {
458 int clusterChainStart
;
459 unsigned int fileCluster
;
464 XPRINTF("USBHDFSD: reading cluster chain \n");
465 fileCluster
= fatDir
->chain
[0].cluster
;
467 if (fileCluster
< 2) {
468 XPRINTF("USBHDFSD: early exit... \n");
472 fileSize
= fatDir
->size
;
473 blockSize
= fileSize
/ DIR_CHAIN_SIZE
;
476 clusterChainStart
= 0;
482 chainSize
= fat_getClusterChain(fatd
, fileCluster
, fatd
->cbuf
, MAX_DIR_CLUSTER
, 1);
483 if (chainSize
>= MAX_DIR_CLUSTER
) { //the chain is full, but more chain parts exist
484 fileCluster
= fatd
->cbuf
[MAX_DIR_CLUSTER
- 1];
485 }else { //chain fits in the chain buffer completely - no next chain exist
488 //process the cluster chain (fatd->cbuf)
489 for (i
= clusterChainStart
; i
< chainSize
; i
++) {
490 fileSize
+= (fatd
->partBpb
.clusterSize
* fatd
->partBpb
.sectorSize
);
491 while (fileSize
>= (j
* blockSize
) && j
< DIR_CHAIN_SIZE
) {
492 fatDir
->chain
[j
].cluster
= fatd
->cbuf
[i
];
493 fatDir
->chain
[j
].index
= index
;
498 clusterChainStart
= 1;
500 fatDir
->lastCluster
= fatd
->cbuf
[i
-1];
502 #ifdef DEBUG_EXTREME //dlanor: I patched this because this bloat hid important stuff
504 printf("USBHDFSD: SEEK CLUSTER CHAIN CACHE fileSize=%i blockSize=%i \n", fatDir
->size
, blockSize
);
505 for (i
= 0; i
< DIR_CHAIN_SIZE
; i
++) {
506 printf("USBHDFSD: index=%i cluster=%i offset= %i - %i start=%i \n",
507 fatDir
->chain
[i
].index
, fatDir
->chain
[i
].cluster
,
508 fatDir
->chain
[i
].index
* fatd
->partBpb
.clusterSize
* fatd
->partBpb
.sectorSize
,
509 (fatDir
->chain
[i
].index
+1) * fatd
->partBpb
.clusterSize
* fatd
->partBpb
.sectorSize
,
513 XPRINTF("USBHDFSD: read cluster chain done!\n");
518 //---------------------------------------------------------------------------
519 /* Set base attributes of direntry */
520 void fat_setFatDir(fat_driver
* fatd
, fat_dir
* fatDir
, fat_direntry_sfn
* dsfn
, fat_direntry_summary
* dir
, int getClusterInfo
) {
522 unsigned char* srcName
;
524 XPRINTF("USBHDFSD: setting fat dir...\n");
525 srcName
= dir
->sname
;
526 if (dir
->name
[0] != 0) { //long filename not empty
530 for (i
= 0; srcName
[i
] != 0; i
++) fatDir
->name
[i
] = srcName
[i
];
531 fatDir
->name
[i
] = 0; //terminate
533 fatDir
->attr
= dir
->attr
;
534 fatDir
->size
= dir
->size
;
536 //created Date: Day, Month, Year-low, Year-high
537 fatDir
->cdate
[0] = (dsfn
->dateCreate
[0] & 0x1F);
538 fatDir
->cdate
[1] = (dsfn
->dateCreate
[0] >> 5) + ((dsfn
->dateCreate
[1] & 0x01) << 3 );
539 i
= 1980 + (dsfn
->dateCreate
[1] >> 1);
540 fatDir
->cdate
[2] = (i
& 0xFF);
541 fatDir
->cdate
[3] = ((i
& 0xFF00)>> 8);
543 //created Time: Hours, Minutes, Seconds
544 fatDir
->ctime
[0] = ((dsfn
->timeCreate
[1] & 0xF8) >> 3);
545 fatDir
->ctime
[1] = ((dsfn
->timeCreate
[1] & 0x07) << 3) + ((dsfn
->timeCreate
[0] & 0xE0) >> 5);
546 fatDir
->ctime
[6] = ((dsfn
->timeCreate
[0] & 0x1F) << 1);
548 //accessed Date: Day, Month, Year-low, Year-high
549 fatDir
->adate
[0] = (dsfn
->dateAccess
[0] & 0x1F);
550 fatDir
->adate
[1] = (dsfn
->dateAccess
[0] >> 5) + ((dsfn
->dateAccess
[1] & 0x01) << 3 );
551 i
= 1980 + (dsfn
->dateAccess
[1] >> 1);
552 fatDir
->adate
[2] = (i
& 0xFF);
553 fatDir
->adate
[3] = ((i
& 0xFF00)>> 8);
555 //modified Date: Day, Month, Year-low, Year-high
556 fatDir
->mdate
[0] = (dsfn
->dateWrite
[0] & 0x1F);
557 fatDir
->mdate
[1] = (dsfn
->dateWrite
[0] >> 5) + ((dsfn
->dateWrite
[1] & 0x01) << 3 );
558 i
= 1980 + (dsfn
->dateWrite
[1] >> 1);
559 fatDir
->mdate
[2] = (i
& 0xFF);
560 fatDir
->mdate
[3] = ((i
& 0xFF00)>> 8);
562 //modified Time: Hours, Minutes, Seconds
563 fatDir
->mtime
[0] = ((dsfn
->timeWrite
[1] & 0xF8) >> 3);
564 fatDir
->mtime
[1] = ((dsfn
->timeWrite
[1] & 0x07) << 3) + ((dsfn
->timeWrite
[0] & 0xE0) >> 5);
565 fatDir
->mtime
[2] = ((dsfn
->timeWrite
[0] & 0x1F) << 1);
567 fatDir
->chain
[0].cluster
= dir
->cluster
;
568 fatDir
->chain
[0].index
= 0;
569 if (getClusterInfo
) {
570 fat_setFatDirChain(fatd
, fatDir
);
574 //---------------------------------------------------------------------------
575 int fat_getDirentrySectorData(fat_driver
* fatd
, unsigned int* startCluster
, unsigned int* startSector
, int* dirSector
) {
578 if (*startCluster
== 0 && fatd
->partBpb
.fatType
< FAT32
) { //Root directory
579 *startSector
= fatd
->partBpb
.rootDirStart
;
580 *dirSector
= fatd
->partBpb
.rootSize
/ (fatd
->partBpb
.sectorSize
/ 32);
583 //other directory or fat 32
584 if (*startCluster
== 0 && fatd
->partBpb
.fatType
== FAT32
) {
585 *startCluster
= fatd
->partBpb
.rootDirCluster
;
587 *startSector
= fat_cluster2sector(&fatd
->partBpb
, *startCluster
);
588 chainSize
= fat_getClusterChain(fatd
, *startCluster
, fatd
->cbuf
, MAX_DIR_CLUSTER
, 1);
589 if (chainSize
>= MAX_DIR_CLUSTER
) {
590 printf("USBHDFSD: Chain too large\n");
592 } else if (chainSize
> 0) {
593 *dirSector
= chainSize
* fatd
->partBpb
.clusterSize
;
595 printf("USBHDFSD: Error getting cluster chain! startCluster=%i \n", *startCluster
);
602 //---------------------------------------------------------------------------
603 int fat_getDirentryStartCluster(fat_driver
* fatd
, unsigned char* dirName
, unsigned int* startCluster
, fat_dir
* fatDir
) {
604 fat_direntry_summary dir
;
607 unsigned int startSector
;
611 mass_dev
* mass_device
= fatd
->dev
;
614 XPRINTF("USBHDFSD: getting cluster for dir entry: %s \n", dirName
);
619 ret
= fat_getDirentrySectorData(fatd
, startCluster
, &startSector
, &dirSector
);
623 XPRINTF("USBHDFSD: dirCluster=%i startSector=%i (%i) dirSector=%i \n", *startCluster
, startSector
, startSector
* mass_device
->sectorSize
, dirSector
);
625 //go through first directory sector till the max number of directory sectors
626 //or stop when no more direntries detected
627 for (i
= 0; i
< dirSector
&& cont
; i
++) {
628 unsigned char* sbuf
= NULL
; //sector buffer
630 //At cluster borders, get correct sector from cluster chain buffer
631 if ((*startCluster
!= 0) && (i
% fatd
->partBpb
.clusterSize
== 0)) {
632 startSector
= fat_cluster2sector(&fatd
->partBpb
, fatd
->cbuf
[(i
/ fatd
->partBpb
.clusterSize
)]) -i
;
635 ret
= READ_SECTOR(fatd
->dev
, startSector
+ i
, sbuf
);
637 printf("USBHDFSD: read directory sector failed ! sector=%i\n", startSector
+ i
);
640 XPRINTF("USBHDFSD: read sector ok, scanning sector for direntries...\n");
643 // go through start of the sector till the end of sector
644 while (cont
&& dirPos
< fatd
->partBpb
.sectorSize
) {
645 fat_direntry
* dir_entry
= (fat_direntry
*) (sbuf
+ dirPos
);
646 cont
= fat_getDirentry(fatd
->partBpb
.fatType
, dir_entry
, &dir
); //get single directory entry from sector buffer
647 if (cont
== 1) { //when short file name entry detected
648 if (!(dir
.attr
& FAT_ATTR_VOLUME_LABEL
)) { //not volume label
649 if ((strEqual(dir
.sname
, dirName
) == 0) ||
650 (strEqual(dir
.name
, dirName
) == 0) ) {
651 XPRINTF("USBHDFSD: found! %s\n", dir
.name
);
652 if (fatDir
!= NULL
) { //fill the directory properties
653 fat_setFatDir(fatd
, fatDir
, &dir_entry
->sfn
, &dir
, 1);
655 *startCluster
= dir
.cluster
;
656 XPRINTF("USBHDFSD: direntry %s found at cluster: %i \n", dirName
, dir
.cluster
);
657 return dir
.attr
; //returns file or directory attr
659 }//ends "if(!(dir.attr & FAT_ATTR_VOLUME_LABEL))"
663 }//ends "if (cont == 1)"
664 dirPos
+= sizeof(fat_direntry
);
667 XPRINTF("USBHDFSD: direntry %s not found! \n", dirName
);
671 //---------------------------------------------------------------------------
672 // start cluster should be 0 - if we want to search from root directory
673 // otherwise the start cluster should be correct cluster of directory
674 // to search directory - set fatDir as NULL
675 int fat_getFileStartCluster(fat_driver
* fatd
, const unsigned char* fname
, unsigned int* startCluster
, fat_dir
* fatDir
) {
676 unsigned char tmpName
[257];
682 XPRINTF("USBHDFSD: Entering fat_getFileStartCluster\n");
689 if (fatDir
!= NULL
) {
690 memset(fatDir
, 0, sizeof(fat_dir
));
691 fatDir
->attr
= FAT_ATTR_DIRECTORY
;
693 if (fname
[i
] == '/') {
697 for ( ; fname
[i
] !=0; i
++) {
698 if (fname
[i
] == '/') { //directory separator
699 tmpName
[offset
] = 0; //terminate string
700 ret
= fat_getDirentryStartCluster(fatd
, tmpName
, startCluster
, fatDir
);
706 tmpName
[offset
] = fname
[i
];
711 tmpName
[offset
] = 0; //terminate string
712 XPRINTF("USBHDFSD: Ready to get cluster for file \"%s\"\n", tmpName
);
713 if (fatDir
!= NULL
) {
714 //if the last char of the name was slash - the name was already found -exit
716 XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with a folder\n");
719 ret
= fat_getDirentryStartCluster(fatd
, tmpName
, startCluster
, fatDir
);
721 XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with error %i\n", ret
);
724 XPRINTF("USBHDFSD: file's startCluster found. Name=%s, cluster=%i \n", fname
, *startCluster
);
726 XPRINTF("USBHDFSD: Exiting from fat_getFileStartCluster with a file\n");
730 //---------------------------------------------------------------------------
731 void fat_getClusterAtFilePos(fat_driver
* fatd
, fat_dir
* fatDir
, unsigned int filePos
, unsigned int* cluster
, unsigned int* clusterPos
) {
734 int j
= (DIR_CHAIN_SIZE
-1);
736 blockSize
= fatd
->partBpb
.clusterSize
* fatd
->partBpb
.sectorSize
;
738 for (i
= 0; i
< (DIR_CHAIN_SIZE
-1); i
++) {
739 if (fatDir
->chain
[i
].index
* blockSize
<= filePos
&&
740 fatDir
->chain
[i
+1].index
* blockSize
> filePos
) {
745 *cluster
= fatDir
->chain
[j
].cluster
;
746 *clusterPos
= (fatDir
->chain
[j
].index
* blockSize
);
749 //---------------------------------------------------------------------------
750 int fat_readFile(fat_driver
* fatd
, fat_dir
* fatDir
, unsigned int filePos
, unsigned char* buffer
, unsigned int size
) {
756 unsigned int bufSize
;
760 mass_dev
* mass_device
= fatd
->dev
;
762 unsigned int bufferPos
;
763 unsigned int fileCluster
;
764 unsigned int clusterPos
;
766 int clusterChainStart
;
768 fat_getClusterAtFilePos(fatd
, fatDir
, filePos
, &fileCluster
, &clusterPos
);
769 sectorSkip
= (filePos
- clusterPos
) / fatd
->partBpb
.sectorSize
;
770 clusterSkip
= sectorSkip
/ fatd
->partBpb
.clusterSize
;
771 sectorSkip
%= fatd
->partBpb
.clusterSize
;
772 dataSkip
= filePos
% fatd
->partBpb
.sectorSize
;
775 XPRINTF("USBHDFSD: fileCluster = %i, clusterPos= %i clusterSkip=%i, sectorSkip=%i dataSkip=%i \n",
776 fileCluster
, clusterPos
, clusterSkip
, sectorSkip
, dataSkip
);
778 if (fileCluster
< 2) {
782 bufSize
= mass_device
->sectorSize
;
784 clusterChainStart
= 1;
786 while (nextChain
&& size
> 0 ) {
787 chainSize
= fat_getClusterChain(fatd
, fileCluster
, fatd
->cbuf
, MAX_DIR_CLUSTER
, clusterChainStart
);
788 clusterChainStart
= 0;
789 if (chainSize
>= MAX_DIR_CLUSTER
) { //the chain is full, but more chain parts exist
790 fileCluster
= fatd
->cbuf
[MAX_DIR_CLUSTER
- 1];
791 }else { //chain fits in the chain buffer completely - no next chain needed
794 while (clusterSkip
>= MAX_DIR_CLUSTER
) {
795 chainSize
= fat_getClusterChain(fatd
, fileCluster
, fatd
->cbuf
, MAX_DIR_CLUSTER
, clusterChainStart
);
796 clusterChainStart
= 0;
797 if (chainSize
>= MAX_DIR_CLUSTER
) { //the chain is full, but more chain parts exist
798 fileCluster
= fatd
->cbuf
[MAX_DIR_CLUSTER
- 1];
799 }else { //chain fits in the chain buffer completely - no next chain needed
802 clusterSkip
-= MAX_DIR_CLUSTER
;
805 //process the cluster chain (fatd->cbuf) and skip leading clusters if needed
806 for (i
= 0 + clusterSkip
; i
< chainSize
&& size
> 0; i
++) {
807 //read cluster and save cluster content
808 startSector
= fat_cluster2sector(&fatd
->partBpb
, fatd
->cbuf
[i
]);
809 //process all sectors of the cluster (and skip leading sectors if needed)
810 for (j
= 0 + sectorSkip
; j
< fatd
->partBpb
.clusterSize
&& size
> 0; j
++) {
811 unsigned char* sbuf
= NULL
; //sector buffer
813 ret
= READ_SECTOR(fatd
->dev
, startSector
+ j
, sbuf
);
815 printf("USBHDFSD: Read sector failed ! sector=%i\n", startSector
+ j
);
819 //compute exact size of transfered bytes
820 if (size
< bufSize
) {
821 bufSize
= size
+ dataSkip
;
823 if (bufSize
> mass_device
->sectorSize
) {
824 bufSize
= mass_device
->sectorSize
;
826 XPRINTF("USBHDFSD: memcopy dst=%i, src=%i, size=%i bufSize=%i \n", bufferPos
, dataSkip
, bufSize
-dataSkip
, bufSize
);
827 memcpy(buffer
+bufferPos
, sbuf
+ dataSkip
, bufSize
- dataSkip
);
828 size
-= (bufSize
- dataSkip
);
829 bufferPos
+= (bufSize
- dataSkip
);
831 bufSize
= mass_device
->sectorSize
;
840 //---------------------------------------------------------------------------
841 int fat_getNextDirentry(fat_driver
* fatd
, fat_dir_list
* fatdlist
, fat_dir
* fatDir
) {
842 fat_direntry_summary dir
;
845 unsigned int startSector
;
849 unsigned int dirCluster
;
850 mass_dev
* mass_device
= fatd
->dev
;
852 //the getFirst function was not called
853 if (fatdlist
->direntryCluster
== 0xFFFFFFFF || fatDir
== NULL
) {
857 dirCluster
= fatdlist
->direntryCluster
;
863 ret
= fat_getDirentrySectorData(fatd
, &dirCluster
, &startSector
, &dirSector
);
867 XPRINTF("USBHDFSD: dirCluster=%i startSector=%i (%i) dirSector=%i \n", dirCluster
, startSector
, startSector
* mass_device
->sectorSize
, dirSector
);
869 //go through first directory sector till the max number of directory sectors
870 //or stop when no more direntries detected
871 //dlanor: but avoid rescanning same areas redundantly (if possible)
874 dirPos
= (fatdlist
->direntryIndex
*32) % fatd
->partBpb
.sectorSize
;
875 for (i
= ((fatdlist
->direntryIndex
*32) / fatd
->partBpb
.sectorSize
); (i
< dirSector
) && cont
; i
++) {
876 unsigned char* sbuf
= NULL
; //sector buffer
878 //At cluster borders, get correct sector from cluster chain buffer
879 if ((dirCluster
!= 0) && (new_entry
|| (i
% fatd
->partBpb
.clusterSize
== 0))) {
880 startSector
= fat_cluster2sector(&fatd
->partBpb
, fatd
->cbuf
[(i
/ fatd
->partBpb
.clusterSize
)])
881 -i
+ (i
% fatd
->partBpb
.clusterSize
);
884 ret
= READ_SECTOR(fatd
->dev
, startSector
+ i
, sbuf
);
886 printf("USBHDFSD: Read directory sector failed ! sector=%i\n", startSector
+ i
);
890 // go through sector from current pos till its end
891 while (cont
&& (dirPos
< fatd
->partBpb
.sectorSize
)) {
892 fat_direntry
* dir_entry
= (fat_direntry
*) (sbuf
+ dirPos
);
893 cont
= fat_getDirentry(fatd
->partBpb
.fatType
, dir_entry
, &dir
); //get a directory entry from sector
894 fatdlist
->direntryIndex
++; //Note current entry processed
895 if (cont
== 1) { //when short file name entry detected
896 fat_setFatDir(fatd
, fatDir
, &dir_entry
->sfn
, &dir
, 0);
898 printf("USBHDFSD: fat_getNextDirentry %c%c%c%c%c%c %x %s %s\n",
899 (dir
.attr
& FAT_ATTR_VOLUME_LABEL
) ? 'v' : '-',
900 (dir
.attr
& FAT_ATTR_DIRECTORY
) ? 'd' : '-',
901 (dir
.attr
& FAT_ATTR_READONLY
) ? 'r' : '-',
902 (dir
.attr
& FAT_ATTR_ARCHIVE
) ? 'a' : '-',
903 (dir
.attr
& FAT_ATTR_SYSTEM
) ? 's' : '-',
904 (dir
.attr
& FAT_ATTR_HIDDEN
) ? 'h' : '-',
911 dirPos
+= sizeof(fat_direntry
);
915 // when we get this far - reset the direntry cluster
916 fatdlist
->direntryCluster
= 0xFFFFFFFF; //no more files
917 return 0; //indicate that no direntry is avalable
920 //---------------------------------------------------------------------------
921 int fat_getFirstDirentry(fat_driver
* fatd
, const unsigned char* dirName
, fat_dir_list
* fatdlist
, fat_dir
* fatDir
) {
923 unsigned int startCluster
= 0;
925 ret
= fat_getFileStartCluster(fatd
, dirName
, &startCluster
, fatDir
);
926 if (ret
< 0) { //dir name not found
929 //check that direntry is directory
930 if (!(fatDir
->attr
& FAT_ATTR_DIRECTORY
)) {
931 return -ENOTDIR
; //it's a file - exit
933 fatdlist
->direntryCluster
= startCluster
;
934 fatdlist
->direntryIndex
= 0;
935 return fat_getNextDirentry(fatd
, fatdlist
, fatDir
);
938 //---------------------------------------------------------------------------
939 int fat_mount(mass_dev
* dev
, unsigned int start
, unsigned int count
)
941 fat_driver
* fatd
= NULL
;
943 for (i
= 0; i
< NUM_DRIVES
&& fatd
== NULL
; ++i
)
945 if (g_fatd
[i
] == NULL
)
947 XPRINTF("USBHDFSD: usb fat: allocate fat_driver %d!\n", sizeof(fat_driver
));
948 g_fatd
[i
] = malloc(sizeof(fat_driver
));
949 if (g_fatd
[i
] != NULL
)
951 g_fatd
[i
]->dev
= NULL
;
955 else if(g_fatd
[i
]->dev
== NULL
)
963 printf("USBHDFSD: usb fat: unable to allocate drive!\n");
967 if (fatd
->dev
!= NULL
)
969 printf("USBHDFSD: usb fat: mount ERROR: alread mounted\n");
970 fat_forceUnmount(fatd
->dev
);
973 if (fat_getPartitionBootSector(dev
, start
, &fatd
->partBpb
) < 0)
978 fatd
->clStackIndex
= 0;
979 fatd
->clStackLast
= 0;
980 fatd
->lastChainCluster
= 0xFFFFFFFF;
981 fatd
->lastChainResult
= -1;
985 //---------------------------------------------------------------------------
986 void fat_forceUnmount(mass_dev
* dev
)
989 XPRINTF("USBHDFSD: usb fat: forceUnmount devId %i \n", dev
->devId
);
991 for (i
= 0; i
< NUM_DRIVES
; ++i
)
993 if (g_fatd
[i
] != NULL
&& g_fatd
[i
]->dev
== dev
)
998 //---------------------------------------------------------------------------
999 fat_driver
* fat_getData(int device
)
1001 if (device
>= NUM_DRIVES
)
1004 while (g_fatd
[device
] == NULL
|| g_fatd
[device
]->dev
== NULL
)
1006 if (mass_stor_configureNextDevice() <= 0)
1010 if (g_fatd
[device
] == NULL
|| g_fatd
[device
]->dev
== NULL
)
1013 return g_fatd
[device
];
1016 //---------------------------------------------------------------------------
1017 //End of file: fat_driver.c
1018 //---------------------------------------------------------------------------