1 /*****************************************************************************
2 * FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
3 * Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 3 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 * Alternative Licensing is available directly from the Copyright holder, *
21 * (James Walmsley). For more information consult LICENSING.TXT to obtain *
22 * a Commercial license. *
24 * See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
26 * Removing the above notice is illegal and will invalidate this license. *
27 *****************************************************************************
28 * See http://worm.me.uk/fullfat for more information. *
29 * Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
30 *****************************************************************************/
34 * @author James Walmsley
37 * @defgroup FAT Fat File-System
38 * @brief Handles FAT access and traversal.
40 * Provides file-system interfaces for the FAT file-system.
44 #include "ff_config.h"
47 void FF_lockFAT(FF_IOMAN
*pIoman
) {
48 FF_PendSemaphore(pIoman
->pSemaphore
); // Use Semaphore to protect FAT modifications.
50 while((pIoman
->Locks
& FF_FAT_LOCK
)) {
51 FF_ReleaseSemaphore(pIoman
->pSemaphore
);
52 FF_Yield(); // Keep Releasing and Yielding until we have the Fat protector.
53 FF_PendSemaphore(pIoman
->pSemaphore
);
55 pIoman
->Locks
|= FF_FAT_LOCK
;
57 FF_ReleaseSemaphore(pIoman
->pSemaphore
);
60 void FF_unlockFAT(FF_IOMAN
*pIoman
) {
61 FF_PendSemaphore(pIoman
->pSemaphore
);
63 pIoman
->Locks
&= ~FF_FAT_LOCK
;
65 FF_ReleaseSemaphore(pIoman
->pSemaphore
);
71 FF_T_UINT32
FF_getRealLBA(FF_IOMAN
*pIoman
, FF_T_UINT32 LBA
) {
72 return LBA
* pIoman
->pPartition
->BlkFactor
;
78 FF_T_UINT32
FF_Cluster2LBA(FF_IOMAN
*pIoman
, FF_T_UINT32 Cluster
) {
82 pPart
= pIoman
->pPartition
;
85 lba
= ((Cluster
- 2) * pPart
->SectorsPerCluster
) + pPart
->FirstDataSector
;
87 lba
= pPart
->ClusterBeginLBA
;
96 FF_T_UINT32
FF_LBA2Cluster(FF_IOMAN
*pIoman
, FF_T_UINT32 Address
) {
97 FF_T_UINT32 cluster
= 0;
100 pPart
= pIoman
->pPartition
;
101 if(pPart
->Type
== FF_T_FAT32
) {
102 cluster
= ((Address
- pPart
->ClusterBeginLBA
) / pPart
->SectorsPerCluster
) + 2;
104 cluster
= ((Address
- pPart
->ClusterBeginLBA
) / pPart
->SectorsPerCluster
);
113 FF_T_SINT32
FF_getFatEntry(FF_IOMAN
*pIoman
, FF_T_UINT32 nCluster
) {
116 FF_T_UINT32 FatOffset
;
117 FF_T_UINT32 FatSector
;
118 FF_T_UINT32 FatSectorEntry
;
119 FF_T_UINT32 FatEntry
;
120 FF_T_UINT8 LBAadjust
;
121 FF_T_UINT16 relClusterEntry
;
123 #ifdef FF_FAT12_SUPPORT
124 FF_T_UINT8 F12short
[2]; // For FAT12 FAT Table Across sector boundary traversal.
127 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
128 FatOffset
= nCluster
* 4;
129 } else if(pIoman
->pPartition
->Type
== FF_T_FAT16
) {
130 FatOffset
= nCluster
* 2;
132 FatOffset
= nCluster
+ (nCluster
/ 2);
135 FatSector
= pIoman
->pPartition
->FatBeginLBA
+ (FatOffset
/ pIoman
->pPartition
->BlkSize
);
136 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
138 LBAadjust
= (FF_T_UINT8
) (FatSectorEntry
/ pIoman
->BlkSize
);
139 relClusterEntry
= (FF_T_UINT16
) (FatSectorEntry
% pIoman
->BlkSize
);
141 FatSector
= FF_getRealLBA(pIoman
, FatSector
);
143 #ifdef FF_FAT12_SUPPORT
144 if(pIoman
->pPartition
->Type
== FF_T_FAT12
) {
145 if(relClusterEntry
== (pIoman
->BlkSize
- 1)) {
146 // Fat Entry SPANS a Sector!
147 // First Buffer get the last Byte in buffer (first byte of our address)!
148 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
, FF_MODE_READ
);
151 return FF_ERR_DEVICE_DRIVER_FAILED
;
153 F12short
[0] = FF_getChar(pBuffer
->pBuffer
, (FF_T_UINT16
)(pIoman
->BlkSize
- 1));
155 FF_ReleaseBuffer(pIoman
, pBuffer
);
156 // Second Buffer get the first Byte in buffer (second byte of out address)!
157 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
+ 1, FF_MODE_READ
);
160 return FF_ERR_DEVICE_DRIVER_FAILED
;
162 F12short
[1] = FF_getChar(pBuffer
->pBuffer
, 0);
164 FF_ReleaseBuffer(pIoman
, pBuffer
);
166 FatEntry
= (FF_T_UINT32
) FF_getShort((FF_T_UINT8
*)&F12short
, 0); // Guarantee correct Endianess!
168 if(nCluster
& 0x0001) {
169 FatEntry
= FatEntry
>> 4;
172 return (FF_T_SINT32
) FatEntry
;
176 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
, FF_MODE_READ
);
179 return FF_ERR_DEVICE_DRIVER_FAILED
;
182 switch(pIoman
->pPartition
->Type
) {
184 FatEntry
= FF_getLong(pBuffer
->pBuffer
, relClusterEntry
);
185 FatEntry
&= 0x0fffffff; // Clear the top 4 bits.
189 FatEntry
= (FF_T_UINT32
) FF_getShort(pBuffer
->pBuffer
, relClusterEntry
);
192 #ifdef FF_FAT12_SUPPORT
194 FatEntry
= (FF_T_UINT32
) FF_getShort(pBuffer
->pBuffer
, relClusterEntry
);
195 if(nCluster
& 0x0001) {
196 FatEntry
= FatEntry
>> 4;
206 FF_ReleaseBuffer(pIoman
, pBuffer
);
208 return (FF_T_SINT32
) FatEntry
;
211 FF_T_SINT8
FF_ClearCluster(FF_IOMAN
*pIoman
, FF_T_UINT32 nCluster
) {
215 FF_T_SINT8 RetVal
= 0;
217 BaseLBA
= FF_Cluster2LBA(pIoman
, nCluster
);
218 BaseLBA
= FF_getRealLBA(pIoman
, BaseLBA
);
220 for(i
= 0; i
< pIoman
->pPartition
->SectorsPerCluster
; i
++) {
221 pBuffer
= FF_GetBuffer(pIoman
, BaseLBA
++, FF_MODE_WRITE
);
224 memset(pBuffer
->pBuffer
, 0x00, 512);
226 RetVal
= FF_ERR_DEVICE_DRIVER_FAILED
;
229 FF_ReleaseBuffer(pIoman
, pBuffer
);
237 * @brief Returns the Cluster address of the Cluster number from the beginning of a chain.
239 * @param pIoman FF_IOMAN Object
240 * @param Start Cluster address of the first cluster in the chain.
241 * @param Count Number of Cluster in the chain,
243 * @return FF_TRUE if it is an end of chain, otherwise FF_FALSE.
246 FF_T_UINT32
FF_TraverseFAT(FF_IOMAN
*pIoman
, FF_T_UINT32 Start
, FF_T_UINT32 Count
) {
249 FF_T_UINT32 fatEntry
= Start
, currentCluster
= Start
;
251 for(i
= 0; i
< Count
; i
++) {
252 fatEntry
= FF_getFatEntry(pIoman
, currentCluster
);
253 if(fatEntry
== (FF_T_UINT32
) FF_ERR_DEVICE_DRIVER_FAILED
) {
257 if(FF_isEndOfChain(pIoman
, fatEntry
)) {
258 return currentCluster
;
260 currentCluster
= fatEntry
;
267 FF_T_UINT32
FF_FindEndOfChain(FF_IOMAN
*pIoman
, FF_T_UINT32 Start
) {
269 FF_T_UINT32 fatEntry
= Start
, currentCluster
= Start
;
271 while(!FF_isEndOfChain(pIoman
, fatEntry
)) {
272 fatEntry
= FF_getFatEntry(pIoman
, currentCluster
);
273 if(fatEntry
== (FF_T_UINT32
) FF_ERR_DEVICE_DRIVER_FAILED
) {
277 if(FF_isEndOfChain(pIoman
, fatEntry
)) {
278 return currentCluster
;
280 currentCluster
= fatEntry
;
290 * @brief Tests if the fatEntry is an End of Chain Marker.
292 * @param pIoman FF_IOMAN Object
293 * @param fatEntry The fat entry from the FAT table to be checked.
295 * @return FF_TRUE if it is an end of chain, otherwise FF_FALSE.
298 FF_T_BOOL
FF_isEndOfChain(FF_IOMAN
*pIoman
, FF_T_UINT32 fatEntry
) {
299 FF_T_BOOL result
= FF_FALSE
;
300 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
301 if((fatEntry
& 0x0fffffff) >= 0x0ffffff8) {
304 } else if(pIoman
->pPartition
->Type
== FF_T_FAT16
) {
305 if(fatEntry
>= 0x0000fff8) {
309 if(fatEntry
>= 0x00000ff8) {
313 if(fatEntry
== 0x00000000) {
314 result
= FF_TRUE
; //Perhaps trying to read a deleted file!
322 * @brief Writes a new Entry to the FAT Tables.
324 * @param pIoman IOMAN object.
325 * @param nCluster Cluster Number to be modified.
326 * @param Value The Value to store.
328 FF_T_SINT8
FF_putFatEntry(FF_IOMAN
*pIoman
, FF_T_UINT32 nCluster
, FF_T_UINT32 Value
) {
331 FF_T_UINT32 FatOffset
;
332 FF_T_UINT32 FatSector
;
333 FF_T_UINT32 FatSectorEntry
;
334 FF_T_UINT32 FatEntry
;
335 FF_T_UINT8 LBAadjust
;
336 FF_T_UINT16 relClusterEntry
;
337 #ifdef FF_FAT12_SUPPORT
338 FF_T_UINT8 F12short
[2]; // For FAT12 FAT Table Across sector boundary traversal.
341 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
342 FatOffset
= nCluster
* 4;
343 } else if(pIoman
->pPartition
->Type
== FF_T_FAT16
) {
344 FatOffset
= nCluster
* 2;
346 FatOffset
= nCluster
+ (nCluster
/ 2);
349 FatSector
= pIoman
->pPartition
->FatBeginLBA
+ (FatOffset
/ pIoman
->pPartition
->BlkSize
);
350 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
352 LBAadjust
= (FF_T_UINT8
) (FatSectorEntry
/ pIoman
->BlkSize
);
353 relClusterEntry
= (FF_T_UINT16
)(FatSectorEntry
% pIoman
->BlkSize
);
355 FatSector
= FF_getRealLBA(pIoman
, FatSector
);
357 #ifdef FF_FAT12_SUPPORT
358 if(pIoman
->pPartition
->Type
== FF_T_FAT12
) {
359 if(relClusterEntry
== (FF_T_UINT16
) (pIoman
->BlkSize
- 1)) {
360 // Fat Entry SPANS a Sector!
361 // First Buffer get the last Byte in buffer (first byte of our address)!
362 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
, FF_MODE_READ
);
365 return FF_ERR_DEVICE_DRIVER_FAILED
;
367 F12short
[0] = FF_getChar(pBuffer
->pBuffer
, (FF_T_UINT16
)(pIoman
->BlkSize
- 1));
369 FF_ReleaseBuffer(pIoman
, pBuffer
);
370 // Second Buffer get the first Byte in buffer (second byte of out address)!
371 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
+ 1, FF_MODE_READ
);
374 return FF_ERR_DEVICE_DRIVER_FAILED
;
376 F12short
[1] = FF_getChar(pBuffer
->pBuffer
, (FF_T_UINT16
) 0x0000);
378 FF_ReleaseBuffer(pIoman
, pBuffer
);
381 FatEntry
= FF_getShort((FF_T_UINT8
*)&F12short
, (FF_T_UINT16
) 0x0000); // Guarantee correct Endianess!
382 if(nCluster
& 0x0001) {
384 Value
= (Value
<< 4);
391 FF_putShort((FF_T_UINT8
*)F12short
, 0x0000, (FF_T_UINT16
) (FatEntry
| Value
));
393 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
, FF_MODE_WRITE
);
396 return FF_ERR_DEVICE_DRIVER_FAILED
;
398 FF_putChar(pBuffer
->pBuffer
, (FF_T_UINT16
)(pIoman
->BlkSize
- 1), F12short
[0]);
400 FF_ReleaseBuffer(pIoman
, pBuffer
);
401 // Second Buffer get the first Byte in buffer (second byte of out address)!
402 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
+ 1, FF_MODE_READ
);
405 return FF_ERR_DEVICE_DRIVER_FAILED
;
407 FF_putChar(pBuffer
->pBuffer
, 0x0000, F12short
[1]);
409 FF_ReleaseBuffer(pIoman
, pBuffer
);
416 pBuffer
= FF_GetBuffer(pIoman
, FatSector
+ LBAadjust
, FF_MODE_WRITE
);
419 return FF_ERR_DEVICE_DRIVER_FAILED
;
421 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
422 Value
&= 0x0fffffff; // Clear the top 4 bits.
423 FF_putLong(pBuffer
->pBuffer
, relClusterEntry
, Value
);
424 } else if(pIoman
->pPartition
->Type
== FF_T_FAT16
) {
425 FF_putShort(pBuffer
->pBuffer
, relClusterEntry
, (FF_T_UINT16
) Value
);
427 FatEntry
= (FF_T_UINT32
) FF_getShort(pBuffer
->pBuffer
, relClusterEntry
);
428 if(nCluster
& 0x0001) {
430 Value
= (Value
<< 4);
437 FF_putShort(pBuffer
->pBuffer
, relClusterEntry
, (FF_T_UINT16
) (FatEntry
| Value
));
440 FF_ReleaseBuffer(pIoman
, pBuffer
);
449 * @brief Finds a Free Cluster and returns its number.
451 * @param pIoman IOMAN Object.
453 * @return The number of the cluster found to be free.
454 * @return 0 on error.
456 #ifdef FF_FAT12_SUPPORT
457 FF_T_UINT32
FF_FindFreeClusterOLD(FF_IOMAN
*pIoman
) {
458 FF_T_UINT32 nCluster
;
459 FF_T_UINT32 fatEntry
;
461 for(nCluster
= pIoman
->pPartition
->LastFreeCluster
; nCluster
< pIoman
->pPartition
->NumClusters
; nCluster
++) {
462 fatEntry
= FF_getFatEntry(pIoman
, nCluster
);
463 if(fatEntry
== 0x00000000) {
464 pIoman
->pPartition
->LastFreeCluster
= nCluster
;
472 FF_T_UINT32
FF_FindFreeCluster(FF_IOMAN
*pIoman
) {
474 FF_T_UINT32 i
, x
, nCluster
= pIoman
->pPartition
->LastFreeCluster
;
475 FF_T_UINT32 FatOffset
;
476 FF_T_UINT32 FatSector
;
477 FF_T_UINT32 FatSectorEntry
;
478 FF_T_UINT32 EntriesPerSector
;
479 FF_T_UINT32 FatEntry
= 1;
481 #ifdef FF_FAT12_SUPPORT
482 if(pIoman
->pPartition
->Type
== FF_T_FAT12
) { // FAT12 tables are too small to optimise, and would make it very complicated!
483 return FF_FindFreeClusterOLD(pIoman
);
487 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
488 EntriesPerSector
= pIoman
->BlkSize
/ 4;
489 FatOffset
= nCluster
* 4;
491 EntriesPerSector
= pIoman
->BlkSize
/ 2;
492 FatOffset
= nCluster
* 2;
495 FatSector
= (FatOffset
/ pIoman
->pPartition
->BlkSize
);
497 for(i
= FatSector
; i
< pIoman
->pPartition
->SectorsPerFAT
; i
++) {
498 pBuffer
= FF_GetBuffer(pIoman
, pIoman
->pPartition
->FatBeginLBA
+ i
, FF_MODE_READ
);
500 for(x
= nCluster
% EntriesPerSector
; x
< EntriesPerSector
; x
++) {
501 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
503 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
504 FatEntry
= FF_getLong(pBuffer
->pBuffer
, (FF_T_UINT16
)FatSectorEntry
);
505 FatEntry
&= 0x0fffffff; // Clear the top 4 bits.
508 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
509 FatEntry
= (FF_T_UINT32
) FF_getShort(pBuffer
->pBuffer
, (FF_T_UINT16
)FatSectorEntry
);
511 if(FatEntry
== 0x00000000) {
512 FF_ReleaseBuffer(pIoman
, pBuffer
);
513 pIoman
->pPartition
->LastFreeCluster
= nCluster
;
521 FF_ReleaseBuffer(pIoman
, pBuffer
);
529 * @brief Create's a Cluster Chain
531 FF_T_UINT32
FF_CreateClusterChain(FF_IOMAN
*pIoman
) {
532 FF_T_UINT32 iStartCluster
;
535 iStartCluster
= FF_FindFreeCluster(pIoman
);
536 FF_putFatEntry(pIoman
, iStartCluster
, 0xFFFFFFFF); // Mark the cluster as EOC
538 FF_unlockFAT(pIoman
);
539 return iStartCluster
;
542 FF_T_UINT32
FF_GetChainLength(FF_IOMAN
*pIoman
, FF_T_UINT32 pa_nStartCluster
, FF_T_UINT32
*piEndOfChain
) {
543 FF_T_UINT32 iLength
= 0;
547 while(!FF_isEndOfChain(pIoman
, pa_nStartCluster
)) {
548 pa_nStartCluster
= FF_getFatEntry(pIoman
, pa_nStartCluster
);
552 *piEndOfChain
= pa_nStartCluster
;
555 FF_unlockFAT(pIoman
);
562 * @brief Extend a Cluster chain by Count number of Clusters
564 * @param pIoman IOMAN object.
565 * @param StartCluster Cluster Number that starts the chain.
566 * @param Count Number of clusters to extend the chain with.
570 FF_T_UINT32 FF_ExtendClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_T_UINT32 Count) {
572 FF_T_UINT32 currentCluster = StartCluster, nextCluster;
573 FF_T_UINT32 clusEndOfChain;
576 clusEndOfChain = FF_FindEndOfChain(pIoman, StartCluster);
578 nextCluster = FF_FindFreeCluster(pIoman); // Find Free clusters!
580 FF_putFatEntry(pIoman, clusEndOfChain, nextCluster);
582 for(i = 0; i <= Count; i++) {
583 currentCluster = nextCluster;
585 FF_putFatEntry(pIoman, currentCluster, 0xFFFFFFFF);
589 nextCluster = FF_FindFreeCluster(pIoman);
590 FF_putFatEntry(pIoman, currentCluster, ++nextCluster);
592 FF_FlushCache(pIoman);
593 return currentCluster;
599 * @brief Free's Disk space by freeing unused links on Cluster Chains
601 * @param pIoman, IOMAN object.
602 * @param StartCluster Cluster Number that starts the chain.
603 * @param Count Number of Clusters from the end of the chain to unlink.
604 * @param Count 0 Means Free the entire chain (delete file).
606 * @return 0 On Success.
607 * @return -1 If the device driver failed to provide access.
610 FF_T_SINT8
FF_UnlinkClusterChain(FF_IOMAN
*pIoman
, FF_T_UINT32 StartCluster
, FF_T_UINT16 Count
) {
612 FF_T_UINT32 fatEntry
;
613 FF_T_UINT32 currentCluster
, chainLength
= 0;
614 FF_T_UINT32 iLen
= 0;
616 fatEntry
= StartCluster
;
619 // Free all clusters in the chain!
620 currentCluster
= StartCluster
;
621 fatEntry
= currentCluster
;
623 fatEntry
= FF_getFatEntry(pIoman
, fatEntry
);
624 FF_putFatEntry(pIoman
, currentCluster
, 0x00000000);
625 currentCluster
= fatEntry
;
627 }while(!FF_isEndOfChain(pIoman
, fatEntry
));
628 FF_IncreaseFreeClusters(pIoman
, iLen
);
630 // Truncation - This is quite hard, because we can only do it backwards.
632 fatEntry
= FF_getFatEntry(pIoman
, fatEntry
);
634 }while(!FF_isEndOfChain(pIoman
, fatEntry
));
640 #ifdef FF_FAT12_SUPPORT
641 FF_T_UINT32
FF_CountFreeClustersOLD(FF_IOMAN
*pIoman
) {
643 FF_T_UINT32 TotalClusters
= pIoman
->pPartition
->DataSectors
/ pIoman
->pPartition
->SectorsPerCluster
;
644 FF_T_UINT32 FatEntry
;
645 FF_T_UINT32 FreeClusters
= 0;
647 for(i
= 0; i
< TotalClusters
; i
++) {
648 FatEntry
= FF_getFatEntry(pIoman
, i
);
659 FF_T_UINT32
FF_CountFreeClusters(FF_IOMAN
*pIoman
) {
661 FF_T_UINT32 i
, x
, nCluster
= 0;
662 FF_T_UINT32 FatOffset
;
663 FF_T_UINT32 FatSector
;
664 FF_T_UINT32 FatSectorEntry
;
665 FF_T_UINT32 EntriesPerSector
;
666 FF_T_UINT32 FatEntry
= 1;
667 FF_T_UINT32 FreeClusters
= 0;
669 #ifdef FF_FAT12_SUPPORT
670 if(pIoman
->pPartition
->Type
== FF_T_FAT12
) { // FAT12 tables are too small to optimise, and would make it very complicated!
671 return FF_CountFreeClustersOLD(pIoman
);
675 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
676 EntriesPerSector
= pIoman
->BlkSize
/ 4;
677 FatOffset
= nCluster
* 4;
679 EntriesPerSector
= pIoman
->BlkSize
/ 2;
680 FatOffset
= nCluster
* 2;
683 FatSector
= (FatOffset
/ pIoman
->pPartition
->BlkSize
);
685 for(i
= 0; i
< pIoman
->pPartition
->SectorsPerFAT
; i
++) {
686 pBuffer
= FF_GetBuffer(pIoman
, pIoman
->pPartition
->FatBeginLBA
+ i
, FF_MODE_READ
);
688 for(x
= nCluster
% EntriesPerSector
; x
< EntriesPerSector
; x
++) {
689 if(pIoman
->pPartition
->Type
== FF_T_FAT32
) {
691 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
692 FatEntry
= FF_getLong(pBuffer
->pBuffer
, (FF_T_UINT16
)FatSectorEntry
);
693 FatEntry
&= 0x0fffffff; // Clear the top 4 bits.
696 FatSectorEntry
= FatOffset
% pIoman
->pPartition
->BlkSize
;
697 FatEntry
= (FF_T_UINT32
) FF_getShort(pBuffer
->pBuffer
, (FF_T_UINT16
)FatSectorEntry
);
699 if(FatEntry
== 0x00000000) {
706 FF_ReleaseBuffer(pIoman
, pBuffer
);
712 #ifdef FF_64_NUM_SUPPORT
713 FF_T_UINT64
FF_GetFreeSize(FF_IOMAN
*pIoman
) {
714 FF_T_UINT32 FreeClusters
;
715 FF_T_UINT64 FreeSize
;
720 if(!pIoman
->pPartition
->FreeClusterCount
) {
721 pIoman
->pPartition
->FreeClusterCount
= FF_CountFreeClusters(pIoman
);
723 FreeClusters
= pIoman
->pPartition
->FreeClusterCount
;
725 FF_unlockFAT(pIoman
);
726 FreeSize
= (FF_T_UINT64
) ((FF_T_UINT64
)FreeClusters
* (FF_T_UINT64
)((FF_T_UINT64
)pIoman
->pPartition
->SectorsPerCluster
* (FF_T_UINT64
)pIoman
->pPartition
->BlkSize
));
732 FF_T_UINT32
FF_GetFreeSize(FF_IOMAN
*pIoman
) {
733 FF_T_UINT32 FreeClusters
;
734 FF_T_UINT32 FreeSize
;
739 if(!pIoman
->pPartition
->FreeClusterCount
) {
740 pIoman
->pPartition
->FreeClusterCount
= FF_CountFreeClusters(pIoman
);
742 FreeClusters
= pIoman
->pPartition
->FreeClusterCount
;
744 FF_unlockFAT(pIoman
);
745 FreeSize
= (FF_T_UINT32
) ((FF_T_UINT32
)FreeClusters
* (FF_T_UINT32
)((FF_T_UINT32
)pIoman
->pPartition
->SectorsPerCluster
* (FF_T_UINT32
)pIoman
->pPartition
->BlkSize
));