微软EFI白皮书 Microsoft Extensible Firmware Initiative FAT32 File System Specification

https://msdn.microsoft.com/zh-cn/windows/hardware/gg463080

微软EFI白皮书 Microsoft Extensible Firmware Initiative FAT32 File System Specification

HardwareWhite Paper             

Designing Hardware for Microsoft® Operating Systems

Microsoft Extensible Firmware Initiative FAT32 FileSystem Specification

FAT:General Overview of On-Disk Format

 

Version 1.03, December 6, 2000
Microsoft Corporation

 

 

The FAT (File Allocation Table) file system has its originsin the late 1970s and early1980s and was the file system supported by theMicrosoft® MS-DOS® operating system. It was originally developed as a simplefile system suitable for floppy disk drives less than 500K in size. Over timeit has been enhanced to support larger and larger media. Currently there arethree FAT file system types: FAT12, FAT16 and FAT32. The basic difference inthese FAT sub types, and the reason for the names, is the size, in bits, of theentries in the actual FAT structure on the disk. There are 12 bits in a FAT12FAT entry, 16 bits in a FAT16 FAT entry and 32 bits in a FAT32 FAT entry.

 


 

Contents

Notational Conventions in this Document7

General Comments (Applicable to FAT File System AllTypes)7

Boot Sector and BPB. 7

FAT Data Structure. 13

FAT Type Determination. 14

FAT Volume Initialization. 19

FAT32 FSInfo Sector Structure and Backup Boot Sector21

FAT Directory Structure. 22

FAT Long Directory Entries25

Name Limits and Character Sets29

Name Matching In Short & Long Names30

Naming Conventions and Long Names30

Effect of Long Directory Entries on Down Level Versionsof FAT. 32

Validating The Contents of a Directory. 32

Other Notes Relating to FAT Directories33

 

Microsoft, MS_DOS,Windows, and Windows NT are trademarks or registered trademarks ofMicrosoft Corporation in the United States and/or other countries. Other productand company names mentioned herein may be the trademarks of their respectiveowners.

© 2000 Microsoft Corporation.All rights reserved.

 

Document History

Date

Change

 

 

 

March 30, 2011

Updated the Legal Agreement

December 6, 2000

First publication

 


Microsoft Extensible Firmware InitiativeFAT32 File System Specification

IMPORTANT-READ CAREFULLY: This MicrosoftAgreement (“Agreement”) is a legal agreement between you (either an individualor a single entity) and Microsoft Corporation (“Microsoft”) for the version ofthe Microsoft specification identified above which you are about to download(“Specification”). BY DOWNLOADING, COPYING OR OTHERWISE USING THE SPECIFICATION,YOU AGREE TO BE BOUND BY THE TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TOTHE TERMS OF THIS AGREEMENT, DO NOT DOWNLOAD, COPY, OR USE THE SPECIFICATION.

The Specification is owned by Microsoftor its suppliers and is protected by copyright laws and international copyrighttreaties, as well as other intellectual property laws and treaties.

1. LIMITED LICENSE AND COVENANT NOT TOSUE.

(a) Provided that you comply with allterms and conditions of this Agreement and subject to the limitations inSections 1(c) - (f) below, Microsoft grants to you the following non-exclusive,worldwide, royalty-free, non-transferable, non-sublicenseable license under anycopyrights owned or licensable by Microsoft without payment of consideration tounaffiliated third parties, to reproduce the Specification solely for thepurposes of creating portions of products which comply with the Specificationin unmodified form.

(b) Provided that you comply with allterms and conditions of this Agreement and subject to the limitations inSections 1(c) - (f) below, Microsoft grants to you the following non-exclusive,worldwide, royalty-free, non-transferable, non-sublicenseable, reciprocallimited covenant not to sue under its Necessary Claims solely to make, havemade, use, import, and directly and indirectly, offer to sell, sell andotherwise distribute and dispose of portions of products which comply with theSpecification in unmodified form.
For purposes of sections (a) and (b) above, the Specification is “unmodified”if there are no changes, additions or extensions to the Specification, and“Necessary Claims” means claims of a patent or patent application which are (1)owned or licenseable by Microsoft without payment of consideration to anunaffiliated third party; and (2) have an effective filing date on or beforeDecember 31, 2010, that must be infringed in order to make a portion(s) of aproduct that complies with the Specification. Necessary Claims does not includeclaims relating to semiconductor manufacturing technology or microprocessorcircuits or claims not required to be infringed in complying with theSpecification (even if in the same patent as Necessary Claims).

(c) The foregoing covenant not to sueshall not extend to any part or function of a product which (i) is not requiredto comply with the Specification in unmodified form, or (ii) to which there wasa commercially reasonable alternative to infringing a Necessary Claim.

(d) Each of the license and the covenant not to sue described above shall beunavailable to you and shall terminate immediately if you or any of yourAffiliates (collectively “Covenantee Party”) “Initiates” any action for patentinfringement against: (x) Microsoft or any of its Affiliates (collectively“Granting Party”), (y) any customers or distributors of the Granting Party, orother recipients of a covenant not to sue with respect to the Specificationfrom the Granting Party (“Covenantees”); or (z) any customers or distributorsof Covenantees (all parties identified in (y) and (z) collectively referred toas “Customers”), which action is based on a conformant implementation of theSpecification. As used herein, “Affiliate” means any entity which directly orindirectly controls, is controlled by, or is under common control with a party;and control shall mean the power, whether direct or indirect, to direct orcause the direction of the management or policies of any entity whether throughthe ownership of voting securities, by contract or otherwise. “Initiates” meansthat a Covenantee Party is the first (as between the Granting Party and theCovenantee Party) to file or institute any legal or administrative claim oraction for patent infringement against the Granting Party or any of theCustomers. “Initiates” includes any situation in which a Covenantee Party filesor initiates a legal or administrative claim or action for patent infringementsolely as a counterclaim or equivalent in response to a Granting Party firstfiling or instituting a legal or administrative patent infringement claim againstsuch Covenantee Party.

(e) Each of the license and the covenantnot to sue described above shall be conditioned on and limited to the sale,distribution, or other disposition of such compliant portions of products thatare usable only by the firmware during the boot process and shall not extend toany purpose other than: (A) to create portions of an operating system (i) onlyas necessary to adapt such operating system so that it can directly interactwith a firmware implementation of: Intel’s Extensible Firmware Initiative (EFI)Specification v. 1.0 and later, and the Unified Extensible Firmware Interface (UEFI)Forum’s UEFI Specifications v.2.0 and later  (together the “UEFI Specifications”); (ii)only as necessary to emulate an implementation of the UEFI Specifications; and(B) to create firmware, applications, utilities and/or drivers that will beused and/or licensed for only the following purposes: (i) to install, repairand maintain hardware, firmware and portions of operating system software whichare utilized in the boot process; (ii) to provide to an operating systemruntime services that are specified in the UEFI Specifications; (iii) todiagnose and correct failures in the hardware, firmware or operating systemsoftware; (iv) to query for identification of a computer system (whether byserial numbers, asset tags, user or otherwise); (v) to perform inventory of acomputer system; and (vi) to manufacture, install and setup any hardware,firmware or operating system software.

(f) Microsoft reserves all other rightsit may have in the Specification and any intellectual property therein. Thefurnishing of this document does not give you any license or covenant not tosue with respect to any other Microsoft patents, trademarks, copyrights orother intellectual property rights.

2. ADDITIONAL LIMITATIONS ANDOBLIGATIONS.
(a)The foregoing license and covenant not to sue is applicable only to theversion of the Specification which you are about to download. It does not applyto any additional versions of or extensions to the Specification.
(b)Without prejudice to any other rights, Microsoft may terminate thisAgreement if you fail to comply with the terms and conditions of thisAgreement. In such event you must destroy all copies of the Specification.

3. INTELLECTUAL PROPERTY RIGHTS. Allownership, title and intellectual property rights in and to the Specificationare owned by Microsoft or its suppliers.

4. U.S. GOVERNMENT RIGHTS. AnySpecification provided to the U.S. Government pursuant to solicitations issuedon or after December 1, 1995 is provided with the commercial rights andrestrictions described elsewhere herein. Any Specification provided to the U.S.Government pursuant to solicitations issued prior to December 1, 1995 isprovided with RESTRICTED RIGHTS as provided for in FAR, 48 CFR 52.227-14 (JUNE1987) or DFAR, 48 CFR 252.227-7013 (OCT 1988), as applicable.

5. EXPORT RESTRICTIONS. Export of theSpecification, any part thereof, or any process or service that is the directproduct of the Specification (the foregoing collectively referred to as the“Restricted Components”) from the United States is regulated by theExport Administration Regulations (EAR, 15 CFR 730-744) of the U.S. CommerceDepartment, Bureau of Export Administration (“BXA”). You agree to comply withthe EAR in the export or re-export of the Restricted Components (i) to anycountry to which the U.S. has embargoed or restricted the export of goods orservices, which currently include, but are not necessarily limited to Cuba,Iran, Iraq, Libya, North Korea, Sudan, Syria and the Federal Republic ofYugoslavia (including Serbia, but not Montenegro), or to any national of anysuch country, wherever located, who intends to transmit or transport theRestricted Components back to such country; (ii) to any person or entity whoyou know or have reason to know will utilize the Restricted Components in thedesign, development or production of nuclear, chemical or biological weapons;or (iii) to any person or entity who has been prohibited from participating inU.S. export transactions by any federal agency of the U.S. government. Youwarrant and represent that neither the BXA nor any other U.S. federalagency has suspended, revoked or denied your export privileges. For additionalinformation see http://www.microsoft.com/exporting.

6. DISCLAIMER OF WARRANTIES. To themaximum extent permitted by applicable law, Microsoft and its suppliers providethe Specification (and all intellectual property therein) and any (if any)support services related to the Specification (“Support Services”) AS IS ANDWITH ALL FAULTS, and hereby disclaim all warranties and conditions, eitherexpress, implied or statutory, including, but not limited to, any (if any)implied warranties or conditions of merchantability, of fitness for aparticular purpose, of lack of viruses, of accuracy or completeness ofresponses, of results, and of lack of negligence or lack of workmanlike effort,all with regard to the Specification, any intellectual property therein and theprovision of or failure to provide Support Services. ALSO, THERE IS NO WARRANTYOR CONDITION OF TITLE, QUIET ENJOYMENT, QUIET POSSESSION, CORRESPONDENCE TODESCRIPTION OR NON-INFRINGEMENT, WITH REGARD TO THE SPECIFICATION AND ANYINTELLECTUAL PROPERTY THEREIN. THE ENTIRE RISK AS TO THE QUALITY OF OR ARISINGOUT OF USE OR PERFORMANCE OF THE SPECIFICATION, ANY INTELLECTUAL PROPERTYTHEREIN, AND SUPPORT SERVICES, IF ANY, REMAINS WITH YOU.

7. EXCLUSION OF INCIDENTAL,CONSEQUENTIAL AND CERTAIN OTHER DAMAGES. To the maximum extent permitted byapplicable law, in no event shall Microsoft or its suppliers be liable for anyspecial, incidental, indirect, or consequential damages whatsoever (including,but not limited to, damages for loss of profits or confidential or otherinformation, for business interruption, for personal injury, for loss ofprivacy, for failure to meet any duty including of good faith or of reasonablecare, for negligence, and for any other pecuniary or other loss whatsoever)arising out of or in any way related to the use of or inability to use theSPECIFICATION, ANY INTELLECTUAL PROPERTY THEREIN, the provision of or failureto provide Support Services, or otherwise under or in connection with anyprovision of this AGREEMENT, even in the event of the fault, tort (includingnegligence), strict liability, breach of contract or breach of warranty ofMicrosoft or any supplier, and even if Microsoft or any supplier has beenadvised of the possibility of such damages.

8. LIMITATION OF LIABILITY AND REMEDIES.Notwithstanding any damages that you might incur for any reason whatsoever(including, without limitation, all damages referenced above and all direct orgeneral damages), the entire liability of Microsoft and any of its suppliersunder any provision of this Agreement and your exclusive remedy for all of theforegoing shall be limited to the greater of the amount actually paid by youfor the Specification or U.S.$5.00. The foregoing limitations, exclusions anddisclaimers shall apply to the maximum extent permitted by applicable law, evenif any remedy fails its essential purpose.

9. APPLICABLE LAW. If you acquired thisSpecification in the United States,this Agreement is governed by the laws of the State of Washington. If you acquired thisSpecification in Canada, unlessexpressly prohibited by local law, this Agreement is governed by the laws inforce in the Province of Ontario, Canada; and, in respect of any dispute whichmay arise hereunder, you consent to the jurisdiction of the federal andprovincial courts sitting in Toronto, Ontario. If this Specificationwas acquired outside the United States, then local law may apply.

10.QUESTIONS. Should you have anyquestions concerning this Agreement, or if you desire to contact Microsoft forany reason, please contact the Microsoft subsidiary serving your country, orwrite: Microsoft Sales Information Center/One Microsoft Way/Redmond, WA98052-6399.

11.ENTIRE AGREEMENT. This Agreement isthe entire agreement between you and Microsoft relating to the Specificationand the Support Services (if any) and they supersede all prior orcontemporaneous oral or written communications, proposals and representationswith respect to the Specification or any other subject matter covered by thisAgreement. To the extent the terms of any Microsoft policies or programs forSupport Services conflict with the terms of this Agreement, the terms of thisAgreement shall control.

Si vous avez acquis votre produitMicrosoft au CANADA,la garantie limitée suivante vous concerne :

RENONCIATION AUX GARANTIES. Dans toutela mesure permise par la législation en vigueur, Microsoft et ses fournisseursfournissent la Specification (et à toute propriété intellectuelle danscelle-ci) et tous (selon le cas) les services d’assistance liés à laSpecification (“Services d’assistance”) TELS QUELS ET AVEC TOUS LEURS DÉFAUTS,et par les présentes excluent toute garantie ou condition, expresse ouimplicite, légale ou conventionnelle, écrite ou verbale, y compris, mais sanslimitation, toute (selon le cas) garantie ou condition implicite ou légale dequalité marchande, de conformité à un usage particulier, d’absence de virus,d’exactitude et d’intégralité des réponses, de résultats, d’efforts techniqueset professionnels et d’absence de négligence, le tout relativement à laSpecification, à toute propriété intellectuelle dans celle-ci et à laprestation ou à la non-prestation des Services d’assistance. DE PLUS, IL N’Y AAUCUNE GARANTIE ET CONDITION DE TITRE, DE JOUISSANCE PAISIBLE, DE POSSESSIONPAISIBLE, DE SIMILARITÉ À LA DESCRIPTION ET D’ABSENCE DE CONTREFAÇONRELATIVEMENT À LA SPÉCIFICATION ET À TOUTE PROPRIÉTÉ INTELLECTUELLE DANSCELLE-CI. VOUS SUPPORTEZ TOUS LES RISQUES DÉCOULANT DE L’UTILISATION ET DE LAPERFORMANCE DE LA SPÉCIFICATION ET DE TOUTE PROPRIÉTÉ INTELLECTUELLE DANSCELLE-CI ET CEUX DÉCOULANT DES SERVICES D’ASSISTANCE (S’IL Y A LIEU).

EXCLUSION DES DOMMAGES INDIRECTS,ACCESSOIRES ET AUTRES. Dans toute la mesure permise par la législation envigueur, Microsoft et ses fournisseurs ne sont en aucun cas responsables detout dommage spécial, indirect, accessoire, moral ou exemplaire quel qu’il soit(y compris, mais sans limitation, les dommages entraînés par la perte debénéfices ou la perte d’information confidentielle ou autre, l’interruption desaffaires, les préjudices corporels, la perte de confidentialité, le défaut deremplir toute obligation y compris les obligations de bonne foi et de diligenceraisonnable, la négligence et toute autre perte pécuniaire ou autre perte dequelque nature que ce soit) découlant de, ou de toute autre manière lié à,l’utilisation ou l’impossibilité d’utiliser la Spécification, toute propriétéintellectuelle dans celle-ci, la prestation ou la non-prestation des Servicesd’assistance ou autrement en vertu de ou relativement à toute disposition decette convention, que ce soit en cas de faute, de délit (y compris lanégligence), de responsabilité stricte, de manquement à un contrat ou demanquement à une garantie de Microsoft ou de l’un de ses fournisseurs, et ce,même si Microsoft ou l’un de ses fournisseurs a été avisé de la possibilité detels dommages.

LIMITATION DE RESPONSABILITÉ ET RECOURS.Malgré tout dommage que vous pourriez encourir pour quelque raison que ce soit(y compris, mais sans limitation, tous les dommages mentionnés ci-dessus ettous les dommages directs et généraux), la seule responsabilité de Microsoft etde ses fournisseurs en vertu de toute disposition de cette convention et votreunique recours en regard de tout ce qui précède sont limités au plus élevé desmontants suivants: soit (a) le montant que vous avez payé pour laSpécification, soit (b) un montant équivalant à cinq dollars U.S. (5,00 $U.S.). Les limitations, exclusions et renonciations ci-dessus s’appliquent danstoute la mesure permise par la législation en vigueur, et ce même si leurapplication a pour effet de priver un recours de son essence.

DROITS LIMITÉS DU GOUVERNEMENT AMÉRICAIN
Tout Produit Logiciel fourni au gouvernement américain conformément à desdemandes émises le ou après le 1er décembre 1995 est offert avec lesrestrictions et droits commerciaux décrits ailleurs dans la présenteconvention. Tout Produit Logiciel fourni au gouvernement américain conformémentà des demandes émises avant le 1er décembre 1995 est offert avec des DROITS LIMITÉStels que prévus dans le FAR, 48CFR 52.227-14 (juin 1987) ou dans le FAR, 48CFR252.227-7013 (octobre 1988), tels qu’applicables.
Sauf lorsqu’expressément prohibé par la législation locale, la présenteconvention est régie par les lois en vigueur dans la province d’Ontario, Canada. Pourtout différend qui pourrait découler des présentes, vous acceptez la compétencedes tribunaux fédéraux et provinciaux siégeant à Toronto, Ontario.

Si vous avez des questions concernantcette convention ou si vous désirez communiquer avec Microsoft pour quelqueraison que ce soit, veuillez contacter la succursale Microsoft desservant votrepays, ou écrire à: Microsoft Sales Information Center, One Microsoft Way, Redmond, Washington 98052-6399.

 

 

Notational Conventions in thisDocument

 

Numbers that have the characters “0x” atthe beginning of them are hexadecimal (base 16) numbers.

 

Any numbers that do not have the characters“0x” at the beginning are decimal (base 10) numbers.

 

The code fragments in this document arewritten in the ‘C’ programming language. Strict typing and syntax are notadhered to.

 

There are several code fragments in thisdocument that freely mix 32-bit and 16-bit data elements. It is assumed thatyou are a programmer who understands how to properly type such operations sothat data is not lost due to truncation of 32-bit values to 16-bit values. Alsotake note that all data types are UNSIGNED. Do not do FAT computations withsigned integer types, because the computations will be wrong on some FAT volumes.

 

General Comments (Applicable toFAT File System All Types)

All of the FAT file systems were originallydeveloped for the IBM PC machine architecture. The importance of this is thatFAT file system on disk data structure is all “little endian.” If we look atone 32-bit FAT entry stored on disk as a series of four 8-bit bytes—the firstbeing byte[0] and the last being byte[4]—here is where the 32 bits numbered 00through 31 are (00 being the least significant bit):

 

byte[3]     33 2 2 2 2 2 2

        1 0 98 7 6 5 4

 

byte[2]     22 2 2 1 1 1 1

        3 2 10 9 8 7 6

 

byte[1]     11 1 1 1 1 0 0

        5 4 32 1 0 9 8

 

byte[0]     00 0 0 0 0 0 0

7 65 4 3 2 1 0

 

This is important if your machine is a “bigendian” machine, because you will have to translate between big and little endianas you move data to and from the disk.

 

A FAT file system volume is composed offour basic regions, which are laid out in this order on the volume:

       0– Reserved Region

       1– FAT Region

       2– Root Directory Region (doesn’t exist on FAT32 volumes)

       3– File and Directory Data Region

 

Boot Sector and BPB

The first important data structure on a FATvolume is called the BPB (BIOS Parameter Block), which is located in the firstsector of the volume in the Reserved Region. This sector is sometimes calledthe “boot sector” or the “reserved sector” or the “0th sector,” butthe important fact is simply that it is the first sector of the volume.

 

This is the first thing about the FAT filesystem that sometimes causes confusion. In MS-DOS version 1.x, there was not aBPB in the boot sector. In this first version of the FAT file system, therewere only two different formats, the one for single-sided and the one fordouble-sided 360K 5.25-inch floppy disks. The determination of which type wason the disk was done by looking at the first byte of the FAT (the low 8 bits ofFAT[0]).

 

This type of media determination wassuperseded in MS-DOS version 2.x by putting a BPB in the boot sector, and theold style of media determination (done by looking at the first byte of the FAT)was no longer supported. All FAT volumes must have a BPB in the boot sector.

 

This brings us to the second point ofconfusion relating to FAT volume determination: What exactly does a BPB looklike? The BPB in the boot sector defined for MS-DOS 2.x only allowed for a FATvolume with strictly less than 65,536 sectors (32 MB worth of 512-bytesectors). This limitation was due to the fact that the “total sectors” fieldwas only a 16-bit field. This limitation was addressed by MS-DOS 3.x, where theBPB was modified to include a new 32-bit field for the total sectors value.

 

The next BPB change occurred with theMicrosoft Windows 95 operating system, specifically OEM Service Release 2(OSR2), where the FAT32 type was introduced. FAT16 was limited by the maximumsize of the FAT and the maximum valid cluster size to no more than a 2 GBvolume if the disk had 512-byte sectors. FAT32 addressed this limitation on theamount of disk space that one FAT volume could occupy so that disks larger than2 GB only had to have one partition defined.

 

The FAT32 BPB exactly matches theFAT12/FAT16 BPB up to and including the BPB_TotSec32 field. They differstarting at offset 36, depending on whether the media type is FAT12/FAT16 orFAT32 (see discussion below for determining FAT type). The relevant point hereis that the BPB in the boot sector of a FAT volume should always be one thathas all of the new BPB fields for either the FAT12/FAT16 or FAT32 BPB type.Doing it this way ensures the maximum compatibility of the FAT volume andensures that all FAT file system drivers will understand and support the volumeproperly, because it always contains all of the currently defined fields.

 

NOTE:In the following description, all the fields whosenames start with BPB_ are part of the BPB. All the fields whose names startwith BS_ are part of the boot sector and not really part of the BPB. Thefollowing shows the start of sector 0 of a FAT volume, which contains the BPB:

 


 Boot Sector and BPB Structure

Name

Offset (byte)

Size (bytes)

Description

BS_jmpBoot

0

3

Jump instruction to boot code. This field has two allowed forms:

jmpBoot[0] = 0xEB, jmpBoot[1] = 0x??, jmpBoot[2] = 0x90

and

jmpBoot[0] = 0xE9, jmpBoot[1] = 0x??, jmpBoot[2] = 0x??

 

0x?? indicates that any 8-bit value is allowed in that byte. What this forms is a three-byte Intel x86 unconditional branch (jump) instruction that jumps to the start of the operating system bootstrap code. This code typically occupies the rest of sector 0 of the volume following the BPB and possibly other sectors. Either of these forms is acceptable. JmpBoot[0] = 0xEB is the more frequently used format.

BS_OEMName

3

8

“MSWIN4.1” There are many misconceptions about this field. It is only a name string. Microsoft operating systems don’t pay any attention to this field. Some FAT drivers do. This is the reason that the indicated string, “MSWIN4.1”, is the recommended setting, because it is the setting least likely to cause compatibility problems. If you want to put something else in here, that is your option, but the result may be that some FAT drivers might not recognize the volume. Typically this is some indication of what system formatted the volume.

BPB_BytsPerSec

11

2

Count of bytes per sector. This value may take on only the following values: 512, 1024, 2048 or 4096. If maximum compatibility with old implementations is desired, only the value 512 should be used. There is a lot of FAT code in the world that is basically “hard wired” to 512 bytes per sector and doesn’t bother to check this field to make sure it is 512. Microsoft operating systems will properly support 1024, 2048, and 4096.

 

Note: Do not misinterpret these statements about maximum compatibility. If the media being recorded has a physical sector size N, you must use N and this must still be less than or equal to 4096. Maximum compatibility is achieved by only using media with specific sector sizes.

BPB_SecPerClus

13

1

Number of sectors per allocation unit. This value must be a power of 2 that is greater than 0. The legal values are 1, 2, 4, 8, 16, 32, 64, and 128. Note however, that a value should never be used that results in a “bytes per cluster” value (BPB_BytsPerSec * BPB_SecPerClus) greater than 32K (32 * 1024). There is a misconception that values greater than this are OK. Values that cause a cluster size greater than 32K bytes do not work properly; do not try to define one. Some versions of some systems allow 64K bytes per cluster value. Many application setup programs will not work correctly on such a FAT volume.


BPB_RsvdSecCnt

14

2

Number of reserved sectors in the Reserved region of the volume starting at the first sector of the volume. This field must not be 0. For FAT12 and FAT16 volumes, this value should never be anything other than 1. For FAT32 volumes, this value is typically 32. There is a lot of FAT code in the world “hard wired” to 1 reserved sector for FAT12 and FAT16 volumes and that doesn’t bother to check this field to make sure it is 1. Microsoft operating systems will properly support any non-zero value in this field.

BPB_NumFATs

16

1

The count of FAT data structures on the volume. This field should always contain the value 2 for any FAT volume of any type. Although any value greater than or equal to 1 is perfectly valid, many software programs and a few operating systems’ FAT file system drivers may not function properly if the value is something other than 2. All Microsoft file system drivers will support a value other than 2, but it is still highly recommended that no value other than 2 be used in this field.

 

The reason the standard value for this field is 2 is to provide redun­dancy for the FAT data structure so that if a sector goes bad in one of the FATs, that data is not lost because it is duplicated in the other FAT. On non-disk-based media, such as FLASH memory cards, where such redundancy is a useless feature, a value of 1 may be used to save the space that a second copy of the FAT uses, but some FAT file system drivers might not recognize such a volume properly.

BPB_RootEntCnt

17

2

For FAT12 and FAT16 volumes, this field contains the count of 32-byte directory entries in the root directory. For FAT32 volumes, this field must be set to 0. For FAT12 and FAT16 volumes, this value should always specify a count that when multiplied by 32 results in an even multiple of BPB_BytsPerSec. For maximum compatibility, FAT16 volumes should use the value 512.

BPB_TotSec16

19

2

This field is the old 16-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec32 must be non-zero. For FAT32 volumes, this field must be 0. For FAT12 and FAT16 volumes, this field contains the sector count, and BPB_TotSec32 is 0 if the total sector count “fits” (is less than 0x10000).

BPB_Media

21

1

0xF8 is the standard value for “fixed” (non-removable) media. For removable media, 0xF0 is frequently used. The legal values for this field are 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, and 0xFF. The only other important point is that whatever value is put in here must also be put in the low byte of the FAT[0] entry. This dates back to the old MS-DOS 1.x media determination noted earlier and is no longer usually used for anything.

BPB_FATSz16

22

2

This field is the FAT12/FAT16 16-bit count of sectors occupied by ONE FAT. On FAT32 volumes this field must be 0, and BPB_FATSz32 contains the FAT size count.

BPB_SecPerTrk

24

2

Sectors per track for interrupt 0x13. This field is only relevant for media that have a geometry (volume is broken down into tracks by multiple heads and cylinders) and are visible on interrupt 0x13. This field contains the “sectors per track” geometry value.

BPB_NumHeads

26

2

Number of heads for interrupt 0x13. This field is relevant as discussed earlier for BPB_SecPerTrk. This field contains the one based “count of heads”. For example, on a 1.44 MB 3.5-inch floppy drive this value is 2.

BPB_HiddSec

28

4

Count of hidden sectors preceding the partition that contains this FAT volume. This field is generally only relevant for media visible on interrupt 0x13. This field should always be zero on media that are not partitioned. Exactly what value is appropriate is operating system specific.

BPB_TotSec32

32

4

This field is the new 32-bit total count of sectors on the volume. This count includes the count of all sectors in all four regions of the volume. This field can be 0; if it is 0, then BPB_TotSec16 must be non-zero. For FAT32 volumes, this field must be non-zero. For FAT12/FAT16 volumes, this field contains the sector count if BPB_TotSec16 is 0 (count is greater than or equal to 0x10000).

 

At this point, the BPB/boot sector forFAT12 and FAT16 differs from the BPB/boot sector for FAT32. The first tableshows the structure for FAT12 and FAT16 starting at offset 36 of the bootsector.

 

Fat12 and Fat16 Structure Starting at Offset 36

Name

Offset (byte)

Size (bytes)

Description

BS_DrvNum

36

1

Int 0x13 drive number (e.g. 0x80). This field supports MS-DOS bootstrap and is set to the INT 0x13 drive number of the media (0x00 for floppy disks, 0x80 for hard disks).
NOTE: This field is actually operating system specific.

BS_Reserved1

37

1

Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0.

BS_BootSig

38

1

Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present.

BS_VolID

39

4

Volume serial number. This field, together with BS_VolLab, supports volume tracking on removable media. These values allow FAT file system drivers to detect that the wrong disk is inserted in a removable drive. This ID is usually generated by simply combining the current date and time into a 32-bit value.

BS_VolLab

43

11

Volume label. This field matches the 11-byte volume label recorded in the root directory.
NOTE: FAT file system drivers should make sure that they update this field when the volume label file in the root directory has its name changed or created. The setting for this field when there is no volume label is the string “NO NAME    ”.

BS_FilSysType

54

8

One of the strings “FAT12   ”, “FAT16   ”, or “FAT     ”.  NOTE: Many people think that the string in this field has something to do with the determination of what type of FAT—FAT12, FAT16, or FAT32—that the volume has. This is not true. You will note from its name that this field is not actually part of the BPB. This string is informational only and is not used by Microsoft file system drivers to determine FAT typ,e because it is frequently not set correctly or is not present. See the FAT Type Determination section of this document. This string should be set based on the FAT type though, because some non-Microsoft FAT file system drivers do look at it.

 


Here is the structure for FAT32 starting atoffset 36 of the boot sector.

 

FAT32 Structure Starting at Offset 36

Name

Offset (byte)

Size (bytes)

Description

BPB_FATSz32

36

4

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0.

BPB_ExtFlags

40

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media.

Bits 0-3  -- Zero-based number of active FAT. Only valid if mirroring is disabled.

Bits 4-6  -- Reserved.

Bit      7         -- 0 means the FAT is mirrored at runtime into all FATs.

               -- 1 means only one FAT is active; it is the one referenced in bits 0-3.

Bits 8-15   -- Reserved.

BPB_FSVer

42

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. High byte is major revision number. Low byte is minor revision number. This is the version number of the FAT32 volume. This supports the ability to extend the FAT32 media type in the future without worrying about old FAT32 drivers mounting the volume. This document defines the version to 0:0.  If this field is non-zero, back-level Windows versions will not mount the volume.

NOTE:  Disk utilities should respect this field and not operate on volumes with a higher major or minor version number than that for which they were designed. FAT32 file system drivers must check this field and not mount the volume if it does not contain a version number that was defined at the time the driver was written.

BPB_RootClus

44

4

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. This is set to the cluster number of the first cluster of the root directory, usually 2 but not required to be 2.

NOTE:  Disk utilities that change the location of the root directory should make every effort to place the first cluster of the root directory in the first non-bad cluster on the drive (i.e., in cluster 2, unless it’s marked bad). This is specified so that disk repair utilities can easily find the root directory if this field accidentally gets zeroed.

BPB_FSInfo

48

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. 

NOTE: There will be a copy of the FSINFO structure in BackupBoot, but only the copy pointed to by this field will be kept up to date (i.e., both the primary and backup boot record will point to the same FSINFO sector).

BPB_BkBootSec

50

2

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. No value other than 6 is recommended.

BPB_Reserved

52

12

This field is only defined for FAT32 media and does not exist on FAT12 and FAT16 media. Reserved for future expansion. Code that formats FAT32 volumes should always set all of the bytes of this field to 0.

BS_DrvNum

64

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_Reserved1

65

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_BootSig

66

1

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_VolID

67

4

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_VolLab

71

11

This field has the same definition as it does for FAT12 and FAT16 media. The only difference for FAT32 media is that the field is at a different offset in the boot sector.

BS_FilSysType

82

8

Always set to the string ”FAT32   ”.  Please see the note for this field in the FAT12/FAT16 section earlier. This field has nothing to do with FAT type determination.

 

There is one other important note aboutSector 0 of a FAT volume. If we consider the contents of the sector as a bytearray, it must be true that sector[510] equals 0x55, and sector[511] equals0xAA.

 

NOTE: Many FAT documents mistakenly say that this 0xAA55 signatureoccupies the “last 2 bytes of the boot sector”. This statement is correct if —and only if — BPB_BytsPerSec is 512. If BPB_BytsPerSec is greater than 512, the offsetsof these signature bytes do not change (although it is perfectly OK for thelast two bytes at the end of the boot sector to also contain this signature).

 

Check your assumptions about the value inthe BPB_TotSec16/32 field. Assume we have a disk or partition of size insectors DskSz. If the BPB TotSec field (either BPB_TotSec16 or BPB_TotSec32— whichever is non-zero) is less than orequal to DskSz, there is nothingwhatsoever wrong with the FAT volume. In fact, it is not at all unusual to havea BPB_TotSec16/32 value that is slightly smaller than DskSz. It is also perfectly OK for the BPB_TotSec16/32 value to beconsiderably smaller than DskSz.

 

All this means is that disk space is beingwasted. It does not by itself mean that the FAT volume is damaged in some way.However, if BPB_TotSec16/32 is larger thanDskSz, the volume is seriously damaged ormalformed because it extends past the end of the media or overlaps data thatfollows it on the disk. Treating a volume for which the BPB_TotSec16/32 valueis “too large” for the media or partition as valid can lead to catastrophicdata loss.

 

FAT Data Structure

The next data structure that is importantis the FAT itself. What this data structure does is define a singly linked listof the “extents” (clusters) of a file. Note at this point that a FAT directoryor file container is nothing but a regular file that has a special attributeindicating it is a directory. The only other special thing about a directory isthat the data or contents of the “file” is a series of 32=byte FAT directoryentries (see discussion below). In all other respects, a directory is just likea file. The FAT maps the data region of the volume by cluster number. The firstdata cluster is cluster 2.

 

The first sector of cluster 2 (the dataregion of the disk) is computed using the BPB fields for the volume as follows.First, we determine the count of sectors occupied by the root directory:

 

RootDirSectors = ((BPB_RootEntCnt * 32) +(BPB_BytsPerSec – 1)) / BPB_BytsPerSec;

 

Note that on a FAT32 volume the BPB_RootEntCnt value is always 0, so on a FAT32volume RootDirSectors is always 0. The 32in the above is the size of one FAT directory entry in bytes. Note alsothat this computation rounds up.

 

The start of the data region, the firstsector of cluster 2, is computed as follows:

 

If(BPB_FATSz16 != 0)

    FATSz =BPB_FATSz16;

Else

    FATSz =BPB_FATSz32;

 

FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs *FATSz) + RootDirSectors;

 

NOTE:This sector number is relative to the first sectorof the volume that contains the BPB (the sector that contains the BPB is sectornumber 0). This does not necessarily map directly onto the drive, becausesector 0 of the volume is not necessarily sector 0 of the drive due topartitioning.

 

Given any valid data cluster number N, the sector number of the firstsector of that cluster (again relative to sector 0 of the FAT volume) iscomputed as follows:

 

FirstSectorofCluster = ((N – 2) * BPB_SecPerClus)+ FirstDataSector;

 

NOTE:Because BPB_SecPerClusis restricted to powers of 2 (1,2,4,8,16,32….), this means that division andmultiplication by BPB_SecPerClus canactually be performed via SHIFT operations on 2s complement architectures thatare usually faster instructions than MULT and DIV instructions. On currentIntel X86 processors, this is largely irrelevant though because the MULT andDIV machine instructions are heavily optimized for multiplication and divisionby powers of 2.

 

FAT Type Determination

There is considerable confusion overexactly how this works, which leads to many “off by 1”, “off by 2”, “off by10”, and “massively off” errors. It is really quite simple how this works. TheFAT type—one of FAT12, FAT16, or FAT32—is determined by the count of clusterson the volume and nothing else.

 

Please read everything in this sectioncarefully, all of the words are important. For example, note that the statementwas “count of clusters.” This is not the same thing as “maximum valid clusternumber,” because the first data cluster is 2 and not 0 or 1.

 

To begin, let’s discuss exactly how the“count of clusters” value is determined. This is all done using the BPB fieldsfor the volume. First, we determine the count of sectors occupied by the rootdirectory as noted earlier.

 

RootDirSectors = ((BPB_RootEntCnt * 32) +(BPB_BytsPerSec – 1)) / BPB_BytsPerSec;

 

Note that on a FAT32 volume, the BPB_RootEntCnt value is always 0; so on a FAT32volume, RootDirSectors is always 0.

 

Next, wedetermine the count of sectors in the data region of the volume:

 

If(BPB_FATSz16 != 0)

    FATSz =BPB_FATSz16;

Else

    FATSz =BPB_FATSz32; 

 

If(BPB_TotSec16 != 0)

    TotSec =BPB_TotSec16;

Else

    TotSec =BPB_TotSec32;

 

DataSec = TotSec – (BPB_ResvdSecCnt + (BPB_NumFATs* FATSz) + RootDirSectors);

 

Now wedetermine the count of clusters:

 

CountofClusters = DataSec / BPB_SecPerClus;

 

Please note that this computation rounds down.

 

Now we can determine the FAT type. Please note carefully or you will commit anoff-by-one error!

 

In the following example, when it says<, it does not mean <=. Note also that the numbers are correct. The firstnumber for FAT12 is 4085; the second number for FAT16 is 65525. These numbersand the ‘<’ signs are not wrong.

 

If(CountofClusters < 4085) {

/* Volume is FAT12 */

} else if(CountofClusters < 65525) {

    /*Volume is FAT16 */

} else {

    /*Volume is FAT32 */

}

 

This is the one and only way that FAT typeis determined. There is no such thing as a FAT12 volume that has more than 4084clusters. There is no such thing as a FAT16 volume that has less than 4085clusters or more than 65,524 clusters. There is no such thing as a FAT32 volumethat has less than 65,525 clusters. If you try to make a FAT volume thatviolates this rule, Microsoft operating systems will not handle them correctlybecause they will think the volume has a different type of FAT than what youthink it does.

 

NOTE:As is noted numerous times earlier, the world isfull of FAT code that is wrong. There is a lot of FAT type code that is off by1 or 2 or 8 or 10 or 16. For this reason, it is highly recommended that if youare formatting a FAT volume which has maximum compatibility with all existingFAT code, then you should you avoid making volumes of any type that have closeto 4,085 or 65,525 clusters. Stay at least 16 clusters on each side away fromthese cut-over cluster counts.

 

Note also that the CountofClusters value is exactly that—the count of data clusters starting at cluster 2. The maximum validcluster number for the volume is CountofClusters+ 1, and the “count of clusters including the two reserved clusters” is CountofClusters + 2.

 

There is one more important computationrelated to the FAT. Given any valid cluster number N, where in the FAT(s) is the entry for that cluster number? Theonly FAT type for which this is complex is FAT12. For FAT16 and FAT32, thecomputation is simple:

 

If(BPB_FATSz16 != 0)

     FATSz =BPB_FATSz16;

 Else

    FATSz =BPB_FATSz32; 

 

If(FATType == FAT16)

   FATOffset = N * 2;

Else if (FATType == FAT32)

   FATOffset = N * 4;

 

ThisFATSecNum = BPB_ResvdSecCnt + (FATOffset /BPB_BytsPerSec);

ThisFATEntOffset = REM(FATOffset / BPB_BytsPerSec);

 

REM(…) is the remainder operator. Thatmeans the remainder after division of FATOffsetby BPB_BytsPerSec. ThisFATSecNum is the sector number of the FATsector that contains the entry for cluster N in the first FAT. If you want thesector number in the second FAT, you add FATSzto ThisFATSecNum; for the third FAT, youadd 2*FATSz, and so on.

 

You now read sector number ThisFATSecNum (remember this is a sector numberrelative to sector 0 of the FAT volume). Assume this is read into an 8-bit bytearray named SecBuff. Also assume that thetype WORD is a 16-bit unsigned and that the type DWORD is a 32-bit unsigned.

 

If(FATType == FAT16)

   FAT16ClusEntryVal = *((WORD *) &SecBuff[ThisFATEntOffset]);

Else

   FAT32ClusEntryVal = (*((DWORD *) &SecBuff[ThisFATEntOffset])) &0x0FFFFFFF;

 

Fetches the contents of that cluster. Toset the contents of this same cluster you do the following:

 

If(FATType == FAT16)

    *((WORD*) &SecBuff[ThisFATEntOffset]) = FAT16ClusEntryVal;

Else {

    FAT32ClusEntryVal = FAT32ClusEntryVal & 0x0FFFFFFF;

    *((DWORD*) &SecBuff[ThisFATEntOffset]) =

       (*((DWORD *) &SecBuff[ThisFATEntOffset])) & 0xF0000000;

    *((DWORD*) &SecBuff[ThisFATEntOffset]) =

       (*((DWORD *) &SecBuff[ThisFATEntOffset])) | FAT32ClusEntryVal;

}

 

Note how the FAT32 code above works. AFAT32 FAT entry is actually only a 28-bit entry. The high 4 bits of a FAT32 FATentry are reserved. The only time that the high 4 bits of FAT32 FAT entriesshould ever be changed is when the volume is formatted, at which time the whole32-bit FAT entry should be zeroed, including the high 4 bits.

 

A bit more explanation is in order here,because this point about FAT32 FAT entries seems to cause a great deal ofconfusion. Basically 32-bit FAT entries are not really 32-bit values; they areonly 28-bit values. For example, all of these 32-bit cluster entry values:0x10000000, 0xF0000000, and 0x00000000 all indicate that the cluster is FREE,because you ignore the high 4 bits when you read the cluster entry value. Ifthe 32-bit free cluster value is currently 0x30000000 and you want to mark thiscluster as bad by storing the value 0x0FFFFFF7 in it. Then the 32-bit entrywill contain the value 0x3FFFFFF7 when you are done, because you must preservethe high 4 bits when you write in the 0x0FFFFFF7 bad cluster mark.

 

Take note that because the BPB_BytsPerSec value is always divisible by 2and 4, you never have to worry about a FAT16 or FAT32 FAT entry spanning over asector boundary (this is not true of FAT12).

 

The code for FAT12 is more complicatedbecause there are 1.5 bytes (12-bits) per FAT entry.

 

    if(FATType == FAT12)

       FATOffset = N + (N / 2);   

/* Multiply by 1.5 without using floating point,the divide by 2 rounds DOWN */

   

   ThisFATSecNum = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);

   ThisFATEntOffset = REM(FATOffset / BPB_BytsPerSec);

 

We now have to check for the sectorboundary case:

 

If(ThisFATEntOffset == (BPB_BytsPerSec – 1)) {

    /* Thiscluster access spans a sector boundary in the FAT      */

    /* Thereare a number of strategies to handling this. The      */

    /*easiest is to always load FAT sectors into memory           */

    /* inpairs if the volume is FAT12 (if you want to load        */

    /* FATsector N, you also load FAT sector N+1 immediately      */

    /*following it in memory unless sector N is the last FAT      */

    /*sector). It is assumed that this is the strategy used here  */

    /* whichmakes this if test for a sector boundary span         */

    /*unnecessary.                                               */

}

 

We now access the FAT entry as a WORD justas we do for FAT16, but if the cluster number is EVEN, we only want the low12-bits of the 16-bits we fetch; and if the cluster number is ODD, we only wantthe high 12-bits of the 16-bits we fetch.

 

 FAT12ClusEntryVal = *((WORD *)&SecBuff[ThisFATEntOffset]);

 If(N &0x0001)

    FAT12ClusEntryVal = FAT12ClusEntryVal >> 4; /* Cluster number is ODD */

 Else

    FAT12ClusEntryVal = FAT12ClusEntryVal & 0x0FFF; /* Cluster number is EVEN */

 

Fetches the contents of that cluster. Toset the contents of this same cluster you do the following:

 

If(N & 0x0001) {

   FAT12ClusEntryVal = FAT12ClusEntryVal << 4;  /* Cluster number is ODD */

    *((WORD*) &SecBuff[ThisFATEntOffset]) =

       (*((WORD *) &SecBuff[ThisFATEntOffset])) & 0x000F;

} Else {

   FAT12ClusEntryVal = FAT12ClusEntryVal & 0x0FFF;  /* Cluster number is EVEN */

    *((WORD*) &SecBuff[ThisFATEntOffset]) =

       (*((WORD *) &SecBuff[ThisFATEntOffset])) & 0xF000;

}

*((WORD *) &SecBuff[ThisFATEntOffset]) =

    (*((WORD*) &SecBuff[ThisFATEntOffset])) | FAT12ClusEntryVal;

 

NOTE:It is assumed that the >> operator shifts abit value of 0 into the high 4 bits and that the << operator shifts a bitvalue of 0 into the low 4 bits.

 

The way the data of a file is associatedwith the file is as follows. In the directory entry, the cluster number of thefirst cluster of the file is recorded. The first cluster (extent) of the fileis the data associated with this first cluster number, and the location of thatdata on the volume is computed from the cluster number as described earlier(computation of FirstSectorofCluster).

 

Note that a zero-length file—a file thathas no data allocated to it—has a first cluster number of 0 placed in itsdirectory entry. This cluster location in the FAT (see earlier computation of ThisFATSecNum and ThisFATEntOffset) contains either an EOC mark (End Of Clusterchain) or the cluster number of the nextcluster of the file. The EOC value is FAT type dependant (assume FATContent is the contents of the cluster entryin the FAT being checked to see whether it is an EOC mark):

 

IsEOF = FALSE;

If(FATType == FAT12) {

   If(FATContent >= 0x0FF8)

       IsEOF = TRUE;

} else if(FATType == FAT16) {

   If(FATContent >= 0xFFF8)

       IsEOF = TRUE;

} else if (FATType == FAT32) {

   If(FATContent >= 0x0FFFFFF8)

       IsEOF = TRUE;

}

 

Note that the cluster number whose clusterentry in the FAT contains the EOC mark is allocated to the file and is also thelast cluster allocated to the file. Microsoft operating system FAT drivers usethe EOC value 0x0FFF for FAT12, 0xFFFF for FAT16, and 0x0FFFFFFF for FAT32 whenthey set the contents of a cluster to the EOC mark. There are various diskutilities for Microsoft operating systems that use a different value, however.

 

There is also a special “BAD CLUSTER” mark.Any cluster that contains the “BAD CLUSTER” value in its FAT entry is a clusterthat should not be placed on the free list because it is prone to disk errors.The “BAD CLUSTER” value is 0x0FF7 for FAT12, 0xFFF7 for FAT16, and 0x0FFFFFF7for FAT32. The other relevant note here is that these bad clusters are alsolost clusters—clusters that appear to be allocated because they contain anon-zero value but which are not part of any files allocation chain. Diskrepair utilities must recognize lost clusters that contain this special valueas bad clusters and not change the content of the cluster entry.

 

NOTE: It is not possible for the bad cluster mark to be an allocatablecluster number on FAT12 and FAT16 volumes, but it is feasible for 0x0FFFFFF7 tobe an allocatable cluster number on FAT32 volumes. To avoid possible confusionby disk utilities, no FAT32 volume should ever be configured such that 0x0FFFFFF7is an allocatable cluster number.

 

The list of free clusters in the FAT isnothing more than the list of all clusters that contain the value 0 in theirFAT cluster entry. Note that this value must be fetched as described earlier asfor any other FAT entry that is not free. This list of free clusters is notstored anywhere on the volume; it must be computed when the volume is mountedby scanning the FAT for entries that contain the value 0. On FAT32 volumes, theBPB_FSInfo sector may contain a valid count of free clusters on the volume. See thedocumentation of the FAT32 FSInfo sector.

 

What are the two reserved clusters at thestart of the FAT for? The first reserved cluster, FAT[0], contains the BPB_Media byte value in its low 8 bits, and allother bits are set to 1. For example, if the BPB_Mediavalue is 0xF8, for FAT12 FAT[0] = 0x0FF8, for FAT16 FAT[0] = 0xFFF8, and forFAT32 FAT[0] = 0x0FFFFFF8. The second reserved cluster, FAT[1], is set byFORMAT to the EOC mark. On FAT12 volumes, it is not used and is simply alwayscontains an EOC mark. For FAT16 and FAT32, the file system driver may use thehigh two bits of the FAT[1] entry for dirty volume flags (all other bits, arealways left set to 1). Note that the bit location is different for FAT16 and FAT32,because they are the high 2 bits of the entry.

 

For FAT16:

   ClnShutBitMask  = 0x8000;

   HrdErrBitMask   = 0x4000;

 

For FAT32:

   ClnShutBitMask  = 0x08000000;

   HrdErrBitMask   = 0x04000000;

 

Bit ClnShutBitMask–     If bit is 1, volume is “clean”.
If bit is 0, volume is “dirty”. This indicates that the file system driver didnot Dismount the volume properly the last time it had the volume mounted. Itwould be a good idea to run a Chkdsk/Scandiskdisk repair utility on it, because it may be damaged.

Bit HrdErrBitMask–      If this bit is 1, no diskread/write errors were encountered.
If this bit is 0, the file system driver encountered a disk I/O error on theVolume the last time it was mounted, which is an indicator that some sectorsmay have gone bad on the volume. It would be a good idea to run a Chkdsk/Scandisk disk repair utility that doessurface analysis on it to look for new bad sectors.

 

Here are two more important notes about theFAT region of a FAT volume:

  1. The last sector of the FAT is not necessarily all part of the FAT. The FAT stops at the cluster number in the last FAT sector that corresponds to the entry for cluster number CountofClusters + 1 (see the CountofClusters computation earlier), and this entry is not necessarily at the end of the last FAT sector. FAT code should not make any assumptions about what the contents of the last FAT sector are after the CountofClusters + 1 entry. FAT format code should zero the bytes after this entry though.
  2. The BPB_FATSz16 (BPB_FATSz32 for FAT32 volumes) value may be bigger than it needs to be. In other words, there may be totally unused FAT sectors at the end of each FAT in the FAT region of the volume. For this reason, the last sector of the FAT is always computed using the CountofClusters + 1 value, never from the BPB_FATSz16/32 value. FAT code should not make any assumptions about what the contents of these “extra” FAT sectors are. FAT format code should zero the contents of these extra FAT sectors though.

 

FAT Volume Initialization

At this point, the careful reader shouldhave one very interesting question. Given that the FAT type (FAT12, FAT16, orFAT32) is dependant on the number of clusters—and that the sectors available inthe data area of a FAT volume is dependant on the size of the FAT—when handedan unformatted volume that does not yet have a BPB, how do you determine allthis and compute the proper values to put in BPB_SecPerClusand either BPB_FATSz16 or BPB_FATSz32? The way Microsoft operating systems dothis is with a fixed value, several tables, and a clever piece of arithmetic.

 

Microsoft operating systems only do FAT12on floppy disks. Because there is a limited number of floppy formats that allhave a fixed size, this is done with a simple table:

 

 “If it is afloppy of this type, then the BPB looks like this.”

 

There is no dynamic computation for FAT12.For the FAT12 formats, all the computation for BPB_SecPerClusand BPB_FATSz16 was worked out by hand on a piece of paper and recorded in thetable (being careful of course that the resultant cluster count was always lessthan 4085). If your media is larger than 4 MB, do not bother with FAT12. Usesmaller BPB_SecPerClus values so that thevolume will be FAT16.

 

The rest of this section is totallyspecific to drives that have 512 bytes per sector. You cannot use these tables,or the clever arithmetic, with drives that have a different sector size. The“fixed value” is simply a volume size that is the “FAT16 to FAT32 cutovervalue”. Any volume size smaller than this is FAT16 and any volume of this sizeor larger is FAT32. For Windows, this value is 512 MB. Any FAT volume smallerthan 512 MB is FAT16, and any FAT volume of 512 MB or larger is FAT32.

 

Please don’t draw an incorrect conclusionhere.

 

There are many FAT16 volumes out there thatare larger than 512 MB. There are various ways to force the format to be FAT16rather than the default of FAT32, and there is a great deal of code thatimplements different limits. All we are talking about here is the default cutover value for MS-DOS and Windowson volumes that have not yet been formatted. There are two tables—one is forFAT16 and the other is for FAT32. An entry in these tables is selected based onthe size of the volume in 512 byte sectors (the value that will go inBPB_TotSec16 or BPB_TotSec32), and the value that this table sets is the BPB_SecPerClus value.

 

    structDSKSZTOSECPERCLUS {

    DWORD   DiskSize;

    BYTE    SecPerClusVal;

    };

 

 /*

*This is the table for FAT16 drives. NOTE thatthis table includes

* entries for disk sizes larger than 512 MB eventhough typically

* only the entries for disks < 512 MB in sizeare used.

* The way this table is accessed is to look forthe first entry

* in the table for which the disk size is lessthan or equal

* to the DiskSize field in that table entry.  For this table to

* work properly BPB_RsvdSecCnt must be 1,BPB_NumFATs

* must be 2, and BPB_RootEntCnt must be 512. Anyof these values

* being different may require the first tableentries DiskSize value

* to be changedotherwise the cluster count may be to low for FAT16.

   */

   DSKSZTOSECPERCLUS DskTableFAT16 [] = {

        {       8400,   0}, /* disks up to  4.1 MB, the 0 value for SecPerClusVal tripsan error */

       {      32680,   2}, /* disks up to   16 MB,  1k cluster */

       {    262144,   4},  /* disks up to 128 MB,  2k cluster*/

       {   524288,    8},  /* disks up to 256 MB,  4k cluster*/

        {1048576,  16},     /* disks up to 512 MB,  8k cluster */

        /*The entries after this point are not used unless FAT16 is forced */

        {2097152,  32},     /* disks up to     1 GB, 16k cluster */

        {4194304,  64},     /* disks up to     2 GB, 32k cluster */

        { 0xFFFFFFFF, 0} /* any disk greaterthan 2GB, 0 value for SecPerClusVal trips an error */

    };

 

/*

* This is the table for FAT32 drives. NOTE thatthis table includes

* entries for disk sizes smaller than 512 MB eventhough typically

* only the entries for disks >= 512 MB in sizeare used.

* The way this table is accessed is to look forthe first entry

* in the table for which the disk size is lessthan or equal

* to the DiskSize field in that table entry. Forthis table to

* work properly BPB_RsvdSecCnt must be 32, andBPB_NumFATs

* must be 2. Any of these values being differentmay require the first

* table entries DiskSize value to be changedotherwise the cluster count

* may be to low for FAT32.

*/

   DSKSZTOSECPERCLUS DskTableFAT32 [] = {

        {      66600,   0},  /* disks up to 32.5 MB, the 0 value forSecPerClusVal trips an error */

        {    532480,   1},   /* disks up to 260 MB,  .5k cluster */

        {16777216,   8},     /* disks up to     8 GB,   4k cluster */

        {33554432, 16},      /* disks up to   16 GB,   8k cluster */

        {67108864, 32},      /* disks up to   32 GB, 16k cluster */

        {0xFFFFFFFF, 64}/* disks greater than 32GB, 32k cluster */

    };

 

So given a disk size and a FAT type ofFAT16 or FAT32, we now have a BPB_SecPerClusvalue. The only thing we have left is do is to compute how many sectors the FATtakes up so that we can set BPB_FATSz16 or BPB_FATSz32. Note that at this pointwe assume that BPB_RootEntCnt, BPB_RsvdSecCnt, and BPB_NumFATs are appropriately set. We also assume that DskSize is the size of the volume that we areeither going to put in BPB_TotSec32 or BPB_TotSec16.

 

RootDirSectors = ((BPB_RootEntCnt * 32) +(BPB_BytsPerSec – 1)) / BPB_BytsPerSec;

TmpVal1 = DskSize – (BPB_ResvdSecCnt +RootDirSectors);

TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;

If(FATType == FAT32)

    TmpVal2= TmpVal2 / 2;

FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;

If(FATType == FAT32) {

   BPB_FATSz16 = 0;

   BPB_FATSz32 = FATSz;

} else {

   BPB_FATSz16 = LOWORD(FATSz);

    /* thereis no BPB_FATSz32 in a FAT16 BPB */

}

 

Do not spend too much time trying to figureout why this math works. The basis for the computation is complicated; theimportant point is that this is how Microsoft operating systems do it, and itworks. Note, however, that this math does not work perfectly. It willoccasionally set a FATSz that is up to2 sectors too large for FAT16, and occasionally up to 8 sectors too largefor FAT32. It will never compute a FATSzvalue that is too small, however. Because it is OK to have a FATSz that is too large, at the expense ofwasting a few sectors, the fact that this computation is surprisingly simplemore than makes up for it being off in a safe way in some cases.

 

FAT32 FSInfo Sector Structureand Backup Boot Sector

Ona FAT32 volume, the FAT can be a large data structure, unlike on FAT16 where itis limited to a maximum of 128K worth of sectors and FAT12 where it is limitedto a maximum of 6K worth of sectors. For this reason, a provision is made tostore the “last known” free cluster count on the FAT32 volume so that it doesnot have to be computed as soon as an API call is made to ask how much freespace there is on the volume (like at the end of a directory listing). The FSInfo sector number is the value in the BPB_FSInfo field; for Microsoft operatingsystems it is always set to 1. Here is the structure of the FSInfo sector:

 

FAT32 FSInfo Sector Structure and Backup Boot Sector

Name

Offset (byte)

Size (bytes)

Description

FSI_LeadSig

0

4

Value 0x41615252. This lead signature is used to validate that this is in fact an FSInfo sector.

FSI_Reserved1

4

480

This field is currently reserved for future expansion. FAT32 format code should always initialize all bytes of this field to 0. Bytes in this field must currently never be used.

FSI_StrucSig

484

4

Value 0x61417272. Another signature that is more localized in the sector to the location of the fields that are used.

FSI_Free_Count

488

4

Contains the last known free cluster count on the volume. If the value is 0xFFFFFFFF, then the free count is unknown and must be computed. Any other value can be used, but is not necessarily correct. It should be range checked at least to make sure it is <= volume cluster count.

FSI_Nxt_Free

492

4

This is a hint for the FAT driver. It indicates the cluster number at which the driver should start looking for free clusters. Because a FAT32 FAT is large, it can be rather time consuming if there are a lot of allocated clusters at the start of the FAT and the driver starts looking for a free cluster starting at cluster 2. Typically this value is set to the last cluster number that the driver allocated. If the value is 0xFFFFFFFF, then there is no hint and the driver should start looking at cluster 2. Any other value can be used, but should be checked first to make sure it is a valid cluster number for the volume.

FSI_Reserved2

496

12

This field is currently reserved for future expansion. FAT32 format code should always initialize all bytes of this field to 0. Bytes in this field must currently never be used.

FSI_TrailSig

508

4

Value 0xAA550000. This trail signature is used to validate that this is in fact an FSInfo sector. Note that the high 2 bytes of this value—which go into the bytes at offsets 510 and 511—match the signature bytes used at the same offsets in sector 0.

 

Anotherfeature on FAT32 volumes that is not present on FAT16/FAT12 is the BPB_BkBootSec field. FAT16/FAT12 volumes can betotally lost if the contents of sector 0 of the volume are overwritten orsector 0 goes bad and cannot be read. This is a “single point of failure” forFAT16 and FAT12 volumes. The BPB_BkBootSecfield reduces the severity of this problem for FAT32 volumes, because startingat that sector number on the volume—6—there is a backup copy of the boot sectorinformation including the volume’s BPB.

 

Inthe case where the sector 0 information has been accidentally overwritten, alla disk repair utility has to do is restore the boot sector(s) from the backupcopy. In the case where sector 0 goes bad, this allows the volume to be mountedso that the user can access data before replacing the disk.

 

Thissecond case—sector 0 goes bad—is the reason why no value other than 6 shouldever be placed in the BPB_BkBootSecfield. If sector 0 is unreadable, various operating systems are “hard wired” tocheck for backup boot sector(s) starting at sector 6 of the FAT32 volume. Notethat starting at the BPB_BkBootSec sectoris a complete boot record. TheMicrosoft FAT32 “boot sector” is actually three 512-byte sectors long. There isa copy of all three of these sectors starting at the BPB_BkBootSec sector. A copy of the FSInfosector is also there, even though the BPB_FSInfofield in this backup boot sector is set to the same value as is stored in thesector 0 BPB.

 

NOTE: All 3 of these sectors have the 0xAA55 signature in sector offsets510 and 511, just like the first boot sector does (see the earlier discussionat the end of the BPB structure description).

 

FAT Directory Structure

We will first talk about short directoryentries and ignore long directory entries for the moment.

 

A FAT directory is nothing but a “file”composed of a linear list of 32-byte structures. The only special directory,which must always be present, is the root directory. For FAT12 and FAT16 media,the root directory is located in a fixed location on the disk immediatelyfollowing the last FAT and is of a fixed size in sectors computed from the BPB_RootEntCnt value (see computations for RootDirSectors earlier in this document). ForFAT12 and FAT16 media, the first sector of the root directory is sector numberrelative to the first sector of the FAT volume:

 

FirstRootDirSecNum = BPB_ResvdSecCnt +(BPB_NumFATs * BPB_FATSz16);

 

For FAT32, the root directory can be ofvariable size and is a cluster chain, just like any other directory is. Thefirst cluster of the root directory on a FAT32 volume is stored in BPB_RootClus. Unlike other directories, theroot directory itself on any FAT type does not have any date or time stamps,does not have a file name (other than the implied file name “\”), and does notcontain “.” and “..” files as the first two directory entries in the directory.The only other special aspect of the root directory is that it is the onlydirectory on the FAT volume for which it is valid to have a file that has onlythe ATTR_VOLUME_ID attribute bit set (see below).

 


FAT 32 Byte Directory Entry Structure

Name

Offset (byte)

Size (bytes)

Description

DIR_Name

0

11

Short name.

DIR_Attr

11

1

File attributes:

ATTR_READ_ONLY                      0x01

ATTR_HIDDEN                                0x02

ATTR_SYSTEM                                0x04

ATTR_VOLUME_ID                        0x08

ATTR_DIRECTORY                          0x10

ATTR_ARCHIVE                             0x20

ATTR_LONG_NAME                       ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID

The upper two bits of the attribute byte are reserved and should always be set to 0 when a file is created and never modified or looked at after that.

DIR_NTRes

12

1

Reserved for use by Windows NT. Set value to 0 when a file is created and never modify or look at it after that.

DIR_CrtTimeTenth

13

1

Millisecond stamp at file creation time. This field actually contains a count of tenths of a second. The granularity of the seconds part of DIR_CrtTime is 2 seconds so this field is a count of tenths of a second and its valid value range is 0-199 inclusive.

 

DIR_CrtTime

14

2

Time file was created.

DIR_CrtDate

16

2

Date file was created.

DIR_LstAccDate

18

2

Last access date. Note that there is no last access time, only a date. This is the date of last read or write. In the case of a write, this should be set to the same date as DIR_WrtDate.

 

DIR_FstClusHI

20

2

High word of this entry’s first cluster number (always 0 for a FAT12 or FAT16 volume).

DIR_WrtTime

22

2

Time of last write. Note that file creation is considered a write.

DIR_WrtDate

24

2

Date of last write. Note that file creation is considered a write.

DIR_FstClusLO

26

2

Low word of this entry’s first cluster number.

DIR_FileSize

28

4

32-bit DWORD holding this file’s size in bytes.

 

 

DIR_Name[0]

Special notes about the first byte (DIR_Name[0]) of a FAT directory entry:

 

·     If DIR_Name[0] == 0xE5, then the directory entry is free (there is nofile or directory name in this entry).

 

·     If DIR_Name[0] == 0x00, then the directory entry is free (same as for0xE5), and there are no allocated directory entries after this one (all of the DIR_Name[0] bytes in all of the entries afterthis one are also set to 0).

 

The special 0value, rather than the 0xE5 value, indicates to FAT file system driver codethat the rest of the entries in this directory do not need to be examinedbecause they are all free.

 

·     If DIR_Name[0] == 0x05, then the actual file name character for thisbyte is 0xE5. 0xE5 is actually a valid KANJI lead byte value for the characterset used in Japan.The special 0x05 value is used so that this special file name case for Japan can behandled properly and not cause FAT file system code to think that the entry isfree.

 

The DIR_Namefield is actually broken into two parts+ the 8-character main part of the name,and the 3-character extension. These two parts are “trailing space padded” withbytes of 0x20.

 

DIR_Name[0] may not equal 0x20. There is an implied ‘.’ character betweenthe main part of the name and the extension part of the name that is notpresent in DIR_Name. Lower casecharacters are not allowed in DIR_Name(what these characters are is country specific).

 

The following characters are not legal inany bytes of DIR_Name:

·     Values less than 0x20 exceptfor the special case of 0x05 in DIR_Name[0]described above.

·     0x22, 0x2A, 0x2B, 0x2C, 0x2E,0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, and 0x7C.

 

Here are some examples of how auser-entered name maps into DIR_Name:

 

“foo.bar”            -> “FOO     BAR”

“FOO.BAR”            -> “FOO     BAR”

“Foo.Bar”            -> “FOO     BAR”

“foo”                -> “FOO        “

“foo.”               -> “FOO        “

“PICKLE.A”           -> “PICKLE  A  “

“prettybg.big”       -> “PRETTYBGBIG”

“.big”               -> illegal, DIR_Name[0]cannot be 0x20

 

In FAT directoriesall names are unique. Look at the first three examples earlier. Those differentnames all refer to the same file, and there can only be one file with DIR_Nameset to “FOO     BAR” in any directory.

 

DIR_Attr specifies attributes of the file:

 

ATTR_READ_ONLY        Indicatesthat writes to the file should fail.

ATTR_HIDDEN               Indicatesthat normal directory listings should not show this file.

ATTR_SYSTEM               Indicatesthat this is an operating system file.

ATTR_VOLUME_ID         Thereshould only be one “file” on the volume that has this attribute set, and thatfile must be in the root directory. This name of this file is actually thelabel for the volume. DIR_FstClusHI and DIR_FstClusLO must always be 0 for the volumelabel (no data clusters are allocated to the volume label file).

ATTR_DIRECTORY          Indicatesthat this file is actually a container for other files.

ATTR_ARCHIVE             This attribute supports backuputilities. This bit is set by the FAT file system driver when a file iscreated, renamed, or written to. Backup utilities may use this attribute toindicate which files on the volume have been modified since the last time thata backup was performed.

 

Note that the ATTR_LONG_NAME attribute bitcombination indicates that the “file” is actually part of the long name entryfor some other file. See the next section for more information on thisattribute combination.

 

When a directory is created, a file withthe ATTR_DIRECTORY bit set in its DIR_Attrfield, you set its DIR_FileSize to 0. DIR_FileSize is not used and is always 0 on afile with the ATTR_DIRECTORY attribute (directories are sized by simplyfollowing their cluster chains to the EOC mark). One cluster is allocated tothe directory (unless it is the root directory on a FAT16/FAT12 volume), andyou set DIR_FstClusLO and DIR_FstClusHI to that cluster number and placean EOC mark in that clusters entry in the FAT. Next, you initialize all bytesof that cluster to 0. If the directory is the root directory, you are done(there are no dot or dotdot entries in the root directory). Ifthe directory is not the root directory, you need to create two special entriesin the first two 32-byte directory entries of the directory (the first two 32byte entries in the data region of the cluster you just allocated).

 

The first directory entry has DIR_Name set to:

“.         ”

 

The second has DIR_Name set to:

“..        ”

 

These are called the dot and dotdot entries. The DIR_FileSize field on both entries is set to 0, and all of the dateand time fields in both of these entries are set to the same values as theywere in the directory entry for the directory that you just created. You nowset DIR_FstClusLO and DIR_FstClusHI for the dot entry (the first entry) to the same values you put in thosefields for the directories directory entry (the cluster number of the clusterthat contains the dot and dotdotentries).

 

Finally, you set DIR_FstClusLO and DIR_FstClusHIfor the dotdotentry (the second entry) to the first cluster number of the directory in whichyou just created the directory (value is 0 if this directory is the rootdirectory even for FAT32 volumes).

 

Here is the summary for the dot and dotdot entries:

·     The dot entry is a directory that points to itself.

·     The dotdot entry points to thestarting cluster of the parent of this directory (which is 0 if thisdirectories parent is the root directory).

 

Date and Time Formats

Many FAT file systems do not supportDate/Time other than DIR_WrtTime and DIR_WrtDate. For this reason, DIR_CrtTimeMil, DIR_CrtTime,DIR_CrtDate, and DIR_LstAccDate are actually optional fields. DIR_WrtTime andDIR_WrtDate must be supported,however. If the other date and time fields are not supported, they should beset to 0 on file create and ignored on other file operations.

 

DateFormat. A FAT directory entry date stamp is a16-bit field that is basically a date relative to the MS-DOS epoch of01/01/1980. Here is the format (bit 0 is the LSB of the 16-bit word, bit 15 isthe MSB of the 16-bit word):

 

Bits 0–4: Day ofmonth, valid value range 1-31 inclusive.

Bits 5–8: Monthof year, 1 = January, valid value range 1–12 inclusive.

Bits 9–15: Countof years from 1980, valid value range 0–127 inclusive (1980–2107).

 

TimeFormat. A FAT directory entry time stamp is a16-bit field that has a granularity of 2 seconds. Here is the format (bit 0 isthe LSB of the 16-bit word, bit 15 is the MSB of the 16-bit word).

 

Bits 0–4:2-second count, valid value range 0–29 inclusive (0 – 58 seconds).

Bits 5–10:Minutes, valid value range 0–59 inclusive.

Bits 11–15:Hours, valid value range 0–23 inclusive.

 

The valid time range is from Midnight00:00:00 to 23:59:58.

 

FAT Long Directory Entries

In adding long directory entries to the FATfile system it was crucial that their addition to the FAT file system'sexisting design:

 

     Be essentially transparenton earlier versions of MS-DOS.  Theprimary goal being that existing MS-DOS APIs on previous versions ofMS-DOS/Windows do not easily "find" long directory entries.  The only MS-DOS APIs that can"find" long directory entries are the FCB-based-find APIs when usedwith a full meta-character matching pattern (i.e. *.*) and full attributematching bits (i.e. matching attributes are FFh).  On post-Windows 95 versions ofMS-DOS/Windows, no MS-DOS API can accidentally "find" a single longdirectory entry.

     Be located in closephysical proximity, on the media, to the short directory entries they areassociated with.  As will be evident,long directory entries are immediately contiguous to the short directory entrythey are associated with and their existence imposes an unnoticeable performanceimpact on the file system.

     If detected by diskmaintenance utilities, they do not jeopardize the integrity of existing filedata.  Disk maintenance utilitiestypically do not use MS-DOS APIs to access on-media file-system-specific datastructures.  Rather they read physical orlogical sector information from the disk and judge for themselves what thedirectory entries contain.  Based on theheuristics employed in the utilities, the utility may take various steps to "repair"what it perceives to be "damaged" file-system-specific datastructures.  Long directory entries wereadded to the FAT file system in such a way as to not cause the loss of filedata if a disk containing long directory entries was "repaired" by apre-Windows 95-compatible disk utility on a previous version of MS-DOS/Windows.

 

In order to meet the goals oflocality-of-access and transparency, the long directory entry is defined as ashort directory entry with a special attribute. As described previously, a long directory entry is just a regulardirectory entry in which the attribute field has a value of:

 

ATTR_LONG_NAME                        ATTR_READ_ONLY |
ATTR_HIDDEN |
ATTR_SYSTEM |
ATTR_VOLUME_ID

 

A mask for determining whether an entry isa long-name sub-component should also be defined:

 

ATTR_LONG_NAME_MASK         ATTR_READ_ONLY |
ATTR_HIDDEN |
ATTR_SYSTEM |
ATTR_VOLUME_ID |
ATTR_DIRECTORY |
ATTR_ARCHIVE

When such a directory entry is encounteredit is given special treatment by the file system.  It is treated as part of a set of directoryentries that are associated with a single short directory entry. Each longdirectory entry has the following structure:

 

FAT Long Directory Entry Structure

Name

Offset

(byte)

Size

(bytes)

Description

LDIR_Ord

0

1

The order of this entry in the sequence of long dir entries associated with the short dir entry at the end of the long dir set.


If masked with 0x40 (LAST_LONG_ENTRY), this indicates the entry is the last long dir entry in a set of long dir entries. All valid sets of long dir entries must begin with an entry having this mask.

LDIR_Name1

1

10

Characters 1-5 of the long-name sub-component in this dir entry.

LDIR_Attr

11

1

Attributes - must be ATTR_LONG_NAME

LDIR_Type

12

1

If zero, indicates a directory entry that is a sub-component of a long name.  NOTE: Other values reserved for future extensions.

Non-zero implies other dirent types.

LDIR_Chksum

13

1

Checksum of name in the short dir entry at the end of the long dir set.

LDIR_Name2

14

12

Characters 6-11 of the long-name sub-component in this dir entry.

LDIR_FstClusLO

26

2

Must be ZERO. This is an artifact of the FAT "first cluster" and must be zero for compatibility with existing disk utilities.  It's meaningless in the context of a long dir entry.

LDIR_Name3

28

4

Characters 12-13 of the long-name sub-component in this dir entry.

 

Organization and Association of Short & Long DirectoryEntries

 

A set of long entries is always associatedwith a short entry that they always immediately precede.  Long entries are paired with short entriesfor one reason: only short directory entries are visible to previous versionsof MS-DOS/Windows.  Without a short entryto accompany it, a long directory entry would be completely invisible onprevious versions of MS-DOS/Windows.  Along entry never legally exists all by itself. If long entries are found without being paired with a valid short entry,they are termed orphans.  The following figure depicts a set of n longdirectory entries associated with it's single short entry.

 

Long entries always immediately precede andare physically contiguous with, the short entry they are associated with.  The file system makes a few other checks toensure that a set of long entries is actually associated with a short entry.

 

Sequence Of LongDirectory Entries

Entry

Ordinal

Nth Long entry

LAST_LONG_ENTRY (0x40) | N

… Additional Long Entries

1st Long entry

1

Short Entry Associated With Preceding Long Entries

(not applicable)

 

First, every member of a set of longentries is uniquely numbered and the last member of the set is or'd with a flagindicating that it is, in fact, the last member of the set.  The LDIR_Ord field is used to make thisdetermination.  The first member of a sethas an LDIR_Ord value of one.  The nthlong member of the set has a value of (n OR LAST_LONG_ENTRY).  Note that the LDIR_Ord field cannot havevalues of 0xE5 or 0x00.  These valueshave always been used by the file system to indicate a "free"directory entry, or the "last" directory entry in a cluster.  Values for LDIR_Ord do not take on these twovalues over their range.  Values forLDIR_Ord must run from 1 to (n OR LAST_LONG_ENTRY).  If they do not, the long entries are"damaged" and are treated as orphans by the file system.

 

Second, an 8-bit checksum is computed onthe name contained in the short directory entry at the time the short and longdirectory entries are created.  All 11characters of the name in the short entry are used in the checksumcalculation.  The check sum is placed inevery long entry.  If any of the checksums in the set of long entries do not agree with the computed checksum of thename contained in the short entry, then the long entries are treated asorphans.  This can occur if a diskcontaining long and short entries is taken to a previous version of MS-DOS/Windowsand only the short name of a file or directory with a long entries is renamed.

 

The algorithm,implemented in C, for computing the checksum is:


 

    //-----------------------------------------------------------------------------
    //  ChkSum()
    //  Returnsan unsigned byte checksum computed on an unsigned byte
    //  array.  The array must be 11 bytes long and isassumed to contain
    //  aname stored in the format of a MS-DOS directory entry.
    //  Passed: pFcbName    Pointer to an unsigned bytearray assumed to be

//                          11 bytes long.
    //  Returns: Sum         An 8-bit unsigned checksum of thearray pointed

//                           to by pFcbName.
    //------------------------------------------------------------------------------
    unsigned char ChkSum (unsigned char*pFcbName)
    {
        short FcbNameLen;
        unsigned char Sum;

        Sum = 0;
        for (FcbNameLen=11; FcbNameLen!=0;FcbNameLen--) {
            // NOTE: The operation is anunsigned char rotate right
            Sum = ((Sum & 1) ? 0x80 :0) + (Sum >> 1) + *pFcbName++;
        }
        return (Sum);
    }

 

As a consequence of this pairing, the shortdirectory entry serves as the structure that contains fields like: last accessdate, creation time, creation date, first cluster, and size.  It also holds a name that is visible onprevious versions of MS-DOS/Windows.  Thelong directory entries are free to contain new information and need notreplicate information already available in the short entry.  Principally, the long entries contain thelong name of a file.  The name containedin a short entry which is associated with a set of long entries is termed the alias name, or simply alias, of the file.

 

Storage of a Long-Name Within Long Directory Entries

 

A long name can consist of more charactersthan can fit in a single long directory entry. When this occurs the name is stored in more than one long entry.  In any event, the name fields themselveswithin the long entries are disjoint. The following example is provided to illustrate how a long name isstored across several long directory entries. Names are also NUL terminated and padded with 0xFFFF characters in orderto detect corruption of long name fields by errant disk utilities.  A name that fits exactly in a n longdirectory entries (i.e. is an integer multiple of 13) is not NUL terminated andnot padded with 0xFFFFs.

 

Suppose a file is created with the name:"The quick brown.fox".  Thefollowing example illustrates how the name is packed into long and shortdirectory entries.  Most fields in thedirectory entries are also filled in as well.

 

 

The heuristics used to"auto-generate" a short name from a long name are explained in alater section.

 

Name Limits and Character Sets

 

Short Directory Entries

 

Short names are limited to 8 charactersfollowed by an optional period (.) and extension of up to 3 characters.  The total path length of a short name cannotexceed 80 characters (64 char path + 3 drive letter + 12 for 8.3 name + NUL)including the trailing NUL.  Thecharacters may be any combination of letters, digits, or characters with codepoint values greater than 127.  Thefollowing special characters are also allowed:

 

$   %  '   -   _  @   ~    `  !   (    )  {   }  ^ #  &

 

Names are stored in a short directory entryin the OEM code page that the system is configured for at the time thedirectory entry is created.  Shortdirectory entries remain in OEM for compatibility with previous versions ofMS-DOS/Windows.  OEM characters aresingle 8-bit characters or can be DBCS character pairs for certain code pages.

 

Short names passed to the file system are alwaysconverted to upper case and their original case value is lost.  One problem that is generally true of mostOEM code pages is that they map lower to upper case extended characters in anon-unique fashion.  That is, they mapmultiple extended characters to a single upper case character.  This creates problems because it does notpreserve the information that the extended character provides.  This mapping also prevents the creation ofsome file names that would normally differ, but because of the mapping to uppercase they become the same file name.

 

Long Directory Entries

 

Long names are limited to 255 characters,not including the trailing NUL.  Thetotal path length of a long name cannot exceed 260 characters, including thetrailing NUL.  The characters may be anycombination of those defined for short names with the addition of the period(.) character used multiple times within the long name.  A space is also a valid character in a longname as it always has been for a short name. However, in short names it typically is not used.  The following six special characters are nowallowed in a long name.  They are notlegal in a short name.

 

+   ,  ;   =   [   ]

 

Embedded spaces within a long name areallowed.  Leading and trailing spaces ina long name are ignored.

 

Leading and embedded periods are allowed ina name and are stored in the long name. Trailing periods are ignored.

 

Long names are stored in long directoryentries in UNICODE.  UNICODE charactersare 16-bit characters.  It is not bepossible to store UNICODE in short directory entries since the names storedthere are 8-bit characters or DBCS characters.

 

Long names passed to the file system arenot converted to upper case and their original case value is preserved.  UNICODE solves the case mapping problemprevalent in some OEM code pages by always providing a translation for lowercase characters to a single, unique upper case character.

 

Name Matching In Short & LongNames

The names contained in the set of all shortdirectory entries are termed the "short name space".  The names contained in the set of all longdirectory entries are termed the "long name space".  Together, they form a single unified namespace in which no duplicate names can exist. That is: any name within a specific directory, whether it is a shortname or a long name, can occur only once in the name space.  Furthermore, although the case of a name ispreserved in a long name, no two names can have the same name although thenames on the media actually differ by case. That is names like "foobar" cannot be created if there isalready a short entry with a name of "FOOBAR" or a long name with aname of "FooBar".

 

All types of search operations within thefile system (i.e. find, open, create, delete, rename) are case-insensitive.  An open of "FOOBAR" will open either"FooBar" or "foobar" if one or the other exists.  A find using "FOOBAR" as a patternwill find the same files mentioned.  Thesame rules are also true for extended characters that are accented.

 

A short name search operation checks onlythe names of the short directory entries for a match.  A long name search operation checks both thelong and short directory entries.  As thefile system traverses a directory, it caches the long-name sub-componentscontained in long directory entries.  Assoon as a short directory entry is encountered that is associated with thecached long name, the long name search operation will check the cached longname first and then the short name for a match.

 

When a character on the media, whether itis stored in the OEM character set or in UNICODE, cannot be translated into theappropriate character in the OEM or ANSI code page, it is always"translated" to the "_" (underscore) character as it isreturned to the user – it is NOT modified on the disk.  This character is the same in all OEM codepages and ANSI.

 

Naming Conventions and Long Names

An API allows the caller to specify thelong name to be assigned to a file or directory.  They do notallow the caller to independently specify the short name.  The reason for this prohibition is that theshort and long names are considered to be a single unified name space.  As should be obvious the file system's namespace does not support duplicate names. In other words, a long name for a file may not contain the same name,ignoring case, as the short name in a different file.  This restriction is intended to preventconfusion among users, and applications, regarding the proper name of a file ordirectory.  To make this restrictiontransparent, whenever a long name is created and the no matching long nameexists, the short name is automatically generated from the long name in such away that it does not collide with an existing short name.

 

The technique chosen to auto-generate shortnames from long names is modeled after Windows NT.  Auto-generated short names are composed ofthe basis-name and an optional numeric-tail.

 

The Basis-Name Generation Algorithm

 

The basis-namegeneration algorithm is outlined below. This is asample algorithm and serves to illustrate how short names canbe auto-generated from long names. An implementation should followthis basic sequence of steps.

 

1.         TheUNICODE name passed to the file system is converted to upper case.

2.         Theupper cased UNICODE name is converted to OEM.
if          (theuppercased UNICODE glyph does not exist as an OEM glyph in the OEM code page)
       or   (theOEM glyph is invalid in an 8.3 name)
{
       Replace the glyph to an OEM '_'(underscore) character.
       Set a "lossy conversion"flag.
}

3.         Stripall leading and embedded spaces from the long name.

4.         Stripall leading periods from the long name.

5.         While         (not at end of the long name)
       and      (charis not a period)
       and      (totalchars copied < 8)
{
       Copy characters into primaryportion of the basis name
}

6.         Inserta dot at the end of the primary components of the basis-name iff the basis name has an extension after the lastperiod in the name.

7.         Scanfor the last embedded period in the long name.
If   (the last embedded period was found)
{
       While         (not at end of the long name)
             and      (total chars copied < 3)
       {
             Copy characters intoextension portion of the basis name
       }
}

Proceed to numeric-tail generation.

 

The Numeric-Tail Generation Algorithm

 

             If                (a "lossy conversion"was not flagged)
       and      (thelong name fits within the 8.3 naming conventions)
       and      (thebasis-name does not collide with any existing short name)
{
       The short name is only thebasis-name without the numeric tail.
}
else
{
       Insert a numeric-tail"~n" to the end of the primary name such that the value of the"~n" is chosen so that the
       name thus formed does not collidewith any existing short name and that the primary name does not exceed eight        characters in length.
}

The "~n" string can range from"~1" to "~999999". The number "n" is chosen so that it is the next number in asequence of files with similar basis-names. For example, assume the following short names existed: LETTER~1.DOC andLETTER~2.DOC.  As expected, the nextauto-generated name of name of this type would be LETTER~3.DOC.  Assume the following short names existed:LETTER~1.DOC, LETTER~3.DOC.  Again, thenext auto-generated name of name of this type would be LETTER~2.DOC.  However, one absolutely cannot count on this behavior.  In a directory with a very large mix of namesof this type, the selection algorithm is optimized for speed and may selectanother "n" based on the characteristics of short names that end in"~n" and have similarleading name patterns.

Effect of Long Directory Entrieson Down Level Versions of FAT

The support of long names is most importanton the hard disk, however it will be supported on removable media as well.  The implementation provides support for longnames without breaking compatibility with the existing FAT format.  A disk can be read by a down level systemwithout any compatibility problems.  Anexisting disk does not go through a conversion process before it can startusing long names.  All of the currentfiles remain unmodified.  The long namedirectory entries are added when a long name is created.  The addition of a long name to an existingfile may require the 8.3 directory entry to be moved if the required adjacentdirectory entries are not available.

 

The long name entries are as hidden ashidden or system files are on a down level system.  This is enough to keep the casual user fromcausing problems.  The user can copy thefiles off using the 8.3 name, and put new files on without any side effects

 

The interesting part of this is whathappens when the disk is taken to a down level FAT system and the directory ischanged.  This can affect the long nameentries since the down level system ignores these long names and will notensure they are properly associated with the 8.3 names.

 

A down level system will only see the longname entries when searching for a label. On a down level system, the volume label will be incorrectly reported ifthe true volume label does not come before all of the long name entries in theroot directory.  This is because the longname entries also have the volume label bit set.  This is unfortunate, but is not a criticalproblem.

 

If an attempt is made to remove the volumelabel, one of the long name directory entries may be deleted.  This would be a rare occurrence.  It is easily detected on an aware system.  The long name entry will no longer be a validfile entry, since one or more of the long entries is marked as deleted.  If the deleted entry is reused, then theattribute byte will not have the proper value for a long name entry. 

 

If a file is renamed on a down levelsystem, then only the short name will be renamed.  The long name will not be affected.  Since the long and short names must be keptconsistent across the name space, it is desirable to have the long name becomeinvalid as a result of this rename.  Thechecksum of the 8.3 name that is kept in the long name directory provides theability to detect this type of change. This checksum will be checked to validate the long name before it isused.  Rename will cause problems only ifthe renamed 8.3 file name happens to have the same checksum.  The checksum algorithm chosen has arelatively flat distribution across the short name space.

 

This rename of the 8.3 name must also notconflict with any of the long names. Otherwise a down level system could create a short name in one file thatmatches a long name, when case is ignored, in a different file.  To prevent this, the automatic creation of an8.3 name from a long name, that has an 8.3 format, will directly map the longname to the 8.3 name by converting the characters to upper case.

 

If the file is deleted, then the long nameis simply orphaned.  If a new file iscreated, the long name may be incorrectly associated with the new filename.  As in the case of a rename thechecksum of the 8.3 name will help prevent this incorrect association.

 

Validating The Contents of aDirectory

These guidelines are provided so that diskmaintenance utilities can verify individual directory entries for 'correctness'while maintaining compatibility with future enhancements to the directorystructure.

 

1.   DO NOT look at the content of directory entry fields marked'reserved' and assume that, if they are any value other than zero, that theyare 'bad'.

2.   DO NOT reset the content of directory entry fields marked reserved to zero when they contain non-zerovalues (under the assumption that they are "bad").  Directory entry fields are designated reserved, rather than must-be-zero.  They should be ignored by yourapplication..  These fields are intendedfor future extensions of the file system. By ignoring them an utility can continue to run on future versions ofthe operating system.

3.   DO use the A_LONG attribute firstwhen determining whether a directory entry is a long directory entry or a shortdirectory entry.  The following algorithmis the correct algorithm for making this determination:

 

        if (((LDIR_attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) &&(LDIR_Ord != 0xE5))
{
/*  Found an active long name sub-component.   */
}

 

4.   DO use bits 4 and 3 of a short entry together when determining what type of short directory entry isbeing inspected.    The followingalgorithm is the correct algorithm for making this determination:

 

        if  (((LDIR_attr & ATTR_LONG_NAME_MASK) !=ATTR_LONG_NAME) && (LDIR_Ord != 0xE5))
{
if       ((DIR_Attr & (ATTR_DIRECTORY | ATTR_VOLUME_ID)) == 0x00)
           /*   Found a file.   */
else if ((DIR_Attr & (ATTR_DIRECTORY| ATTR_VOLUME_ID)) == ATTR_DIRECTORY)
           /*   Found a directory.   */
else if ((DIR_Attr & (ATTR_DIRECTORY| ATTR_VOLUME_ID)) == ATTR_VOLUME_ID)
           /*   Found a volume label.   */
else
           /*   Found an invalid directory entry.   */
}

 

5.   DO NOT assume that a non-zero value in the "type" fieldindicates a bad directory entry.  Do notforce the "type" field to zero.

6.   Usethe "checksum" field as a value to validate the directory entry.  The "first cluster" field iscurrently being set to zero, though this might change in future.

 

Other Notes Relating to FATDirectories

·     Long File Name directoryentries are identical on all FAT types. See the preceeding sections for details.

 

·     DIR_FileSize is a 32-bit field. For FAT32 volumes, your FAT file system drivermust not allow a cluster chain to be created that is longer than 0x100000000bytes, and the last byte of the last cluster in a chain that long cannot beallocated to the file. This must be done so that no file has a file size >0xFFFFFFFF bytes. This is a fundamental limit of all FAT file systems. Themaximum allowed file size on a FAT volume is 0xFFFFFFFF (4,294,967,295) bytes.

 

·     Similarly, a FAT file systemdriver must not allow a directory (a file that is actually a container forother files) to be larger than 65,536 * 32 (2,097,152) bytes.

NOTE: This limit does not apply to the number of files in thedirectory. This limit is on the size of the directory itself and has nothing todo with the content of the directory. There are two reasons for this limit:

 

1.       Because FAT directories are not sorted or indexed, it is a bad ideato create huge directories; otherwise, operations like creating a new entry(which requires every allocated directory entry to be checked to verify thatthe name doesn’t already exist in the directory) become very slow.

2.       There are many FAT file system drivers and disk utilities, includingMicrosoft’s, that expect to be able to count the entries in a directory using a16-bit WORD variable. For this reason, directories cannot have more than16-bits worth of entries.

 

 


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值