📄 paul's 8051 code library understanding the fat32 filesystem.htm
字号:
<TD align=right>16 Bits</TD>
<TD>Always 0xAA55</TD></TR></TBODY></TABLE>
<P>After checking the three fields to make sure the filesystem is using 512 byte
sectors, 2 FATs, and has a correct signature, you may want to "boil down" these
variables read from the MBR and Volume ID into just four simple numbers that are
needed for accessing the FAT32 filesystem. Here are simple formulas in C syntax:
<P><PRE>(unsigned long)fat_begin_lba = Partition_LBA_Begin + Number_of_Reserved_Sectors;
(unsigned long)cluster_begin_lba = Partition_LBA_Begin + Number_of_Reserved_Sectors + (Number_of_FATs * Sectors_Per_FAT);
(unsigned char)sectors_per_cluster = BPB_SecPerClus;
(unsigned long)root_dir_first_cluster = BPB_RootClus;
</PRE>
<P>As you can see, most of the information is needed only to learn the location
of the first cluster and the FAT. You will need to remember the size of the
clusters and where the root directory is located, but the other information is
usually not needed (at least for simply reading files).
<P>If you compare these formulas to the ones in Microsoft's specification, you
should notice two differences. They lack "RootDirSectors", because FAT32 stores
the root directory the same was as files and subdirectories, so RootDirSectors
is always zero with FAT32. For FAT16 and FAT12, this extra step is needed to
compute the special space allocated for the root directory.
<P>Microsoft's formulas do not show the "Partition_LBA_Begin" term. Their
formulas are all relative to the beginning of the filesystem, which they don't
explicitly state very well. You must add the "Partition_LBA_Begin" term found
from the MBR to compute correct LBA addresses for the IDE interface, because to
the drive the MBR is at zero, not the Volume ID.
<P>The rest of this page will usually refer to "fat_begin_lba",
"cluster_begin_lba", "sectors_per_cluster", and "root_dir_first_cluster", rather
than the individual fields from the MBR and Volume ID, because it is easiest to
compute these numbers when starting up and then you no longer need all the
details from the MBR and Volume ID.
<TABLE cellSpacing=4 cellPadding=10 width="30%" align=right>
<TBODY>
<TR bgColor=#e8e8e8>
<TD>
<CENTER>
<H3>Bad Sectors</H3></CENTER>In the old days, disk drives had "bad"
sectors. Brand new drives would often have several bad sectors, and as the
drive was used (or abused), additional sectors would become unusable.
<P>The FAT filesystems are designed to handle bad sectors. This is done by
storing two identical copies of the File Allocation Table. The idea is
that if a sector within one FAT becomes bad, the corresponding sector in
the other FAT will (hopefully) still be good.
<P>Bad sectors within the clusters are handled by storing a special code
within the FAT entry that represents the cluster that contains the bad
sector. If a file happened to be using that cluster, well, you lost part
of the file's data, but at least that cluster would be marked as bad so
that it would never be used again. The initial formatting of the disk
would write and read every sector and mark the bad clusters before they
could be used, so data loss could only occur when a previously-good sector
became bad.
<P>Fortunately, bad sectors today are only a distant memory, at least on
hard drives. Modern drives still internally experience media errors, but
they store <A
href="javascript:if(confirm('http://www.siam.org/siamnews/mtc/mtc193.htm%20%20\n\nThis%20file%20was%20not%20retrieved%20by%20Teleport%20Pro,%20because%20it%20is%20addressed%20on%20a%20domain%20or%20path%20outside%20the%20boundaries%20set%20for%20its%20Starting%20Address.%20%20\n\nDo%20you%20want%20to%20open%20it%20from%20the%20server?'))window.location='http://www.siam.org/siamnews/mtc/mtc193.htm'"
tppabs="http://www.siam.org/siamnews/mtc/mtc193.htm">Reed-Solomon error
correcting codes</A> for every sector. Sector data can be interleaved and
distributed over a wide area, so a physical defect (localized to one
place) can damage only a small part of many sectors, rather than all of a
few sectors. The error correction can easily recover the few missing bits
of each sector. Error correction also dramatically increases storage
capacity (despite using space to store redundant data), because the bits
can be packed so close together that a small number of errors begin to
occur, and the error correction fixes them.
<P>All modern drives also include extra storage capacity that is used to
<A
href="javascript:if(confirm('http://www.pcguide.com/ref/hdd/geom/format_Defect.htm%20%20\n\nThis%20file%20was%20not%20retrieved%20by%20Teleport%20Pro,%20because%20it%20is%20addressed%20on%20a%20domain%20or%20path%20outside%20the%20boundaries%20set%20for%20its%20Starting%20Address.%20%20\n\nDo%20you%20want%20to%20open%20it%20from%20the%20server?'))window.location='http://www.pcguide.com/ref/hdd/geom/format_Defect.htm'"
tppabs="http://www.pcguide.com/ref/hdd/geom/format_Defect.htm">automatically
remap damaged sectors</A>. When a sector is read and too many of the bits
needed error correction, the controller in the drive will "move" that
sector to a fresh portion of the space set aside for remapping sectors.
Remapping also dramatically reduces the cost of disk drives, because small
but common defects in manufacturing don't impact overall product quality.
<P>Because all modern drives use sophisticated error correction to
automatically detect and (almost always) correct for media errors, bad
sectors are virtually never seen at the IDE interface level.
</P></TD></TR></TBODY></TABLE>
<TABLE>
<H2>How The FAT32 Filesystem Is Arranged</H2>The layout of a FAT32 filesystem
is simple. The first sector is always the Volume ID, which is followed by some
unused space called the reserved sectors. Following the reserved sectors are
two copies of the FAT (File Allocation Table). The remainder of the filesystem
is data arranged in "clusters", with perhaps a tiny bit of unused space after
the last cluster.
<P></P>
<TBODY></TBODY></TABLE>
<TABLE width=432 align=center>
<TBODY>
<TR>
<TD><IMG height=300 alt="Filesystem Layout Diagrag"
src="Paul's 8051 Code Library Understanding the FAT32 Filesystem.files/fat32_layout.gif"
width=420
tppabs="http://www.pjrc.com/tech/8051/ide/fat32_layout.gif"><BR><SMALL><B>Figure
5</B>: FAT32 Filesystem Overall Layout</SMALL></TD></TR></TBODY></TABLE>
<P>The vast majority of the disk space is the clusters section, which is used to
hold all the files and directories. The clusters begin their numbering at 2, so
there is no cluster #0 or cluster #1. To access any particular cluster, you need
to use this formula to turn the cluster number into the LBA address for the IDE
drive:
<P><CODE>lba_addr = cluster_begin_lba + (cluster_number - 2) *
sectors_per_cluster;</CODE>
<P>Normally clusters are at least 4k (8 sectors), and sizes of 8k, 16k and 32k
are also widely used. Some later versions of Microsoft Windows allow using even
larger cluster sizes, by effectively considering the sector size to be some
mulitple of 512 bytes. The FAT32 specification from Microsoft states that 32k is
the maximum cluster size.
<H2>Now If Only We Knew Where The Files Were....</H2>When you begin, you only
know the first cluster of the root directory. Reading the directory will reveal
the names and first cluster location of other files and subdirectories. A key
point is that <FONT color=#b00000><B>directories only tell you how to find the
first cluster number of their files and subdirectories</B></FONT>. You also
obtain a variety of other info from the directory such as the file's length,
modification time, attribute bits, etc, but a directory only tells you where the
files begin. To access more than the first cluster, you will need to use the
FAT. But first we need to be able to find where those files start.
<P>In this section, we'll only briefly look at directories as much as is
necessary to learn where the files are, then we'll look at how to access the
rest of a file using the FAT, and later we'll revisit directory structure in
more detail.
<P>Directory data is organized in 32 byte records. This is nice, because any
sector holds exactly 16 records, and no directory record will ever cross a
sector boundry. There are four types of 32-byte directory records.
<OL>
<LI><B>Normal record with short filename</B> - Attrib is normal
<LI><B>Long filename text</B> - Attrib has all four type bits set
<LI><B>Unused</B> - First byte is 0xE5
<LI><B>End of directory</B> - First byte is zero </LI></OL>Unused directory
records are a result of deleting files. The first byte is overwritten with 0xE5,
and later when a new file is created it can be reused. At the end of the
directory is a record that begins with zero. All other records will be non-zero
in their first byte, so this is an easy way to determine when you have reached
the end of the directory.
<P>Records that do not begin with 0xE5 or zero are actual directory data, and
the format can be determined by checking the Attrib byte. For now, we are only
going to be concerned with the normal directory records that have the old 8.3
short filename format. In FAT32, all files and subdirectories have short names,
even if the user gave the file a longer name, so you can access all files
without needing to decode the long filename records (as long as your code simply
ignores them). Here is the format of a normal directory record:
<P>
<TABLE width=592 align=center>
<TBODY>
<TR>
<TD><IMG height=52 alt="Short Directory Entry"
src="Paul's 8051 Code Library Understanding the FAT32 Filesystem.files/dir_entry_short.gif"
width=581
tppabs="http://www.pjrc.com/tech/8051/ide/dir_entry_short.gif"><BR><SMALL><B>Figure
6</B>: 32 Byte Directory Structure, Short Filename
Format</SMALL></TD></TR></TBODY></TABLE>
<P>
<TABLE cellSpacing=0 cellPadding=4 align=center border=1>
<TBODY>
<TR>
<TH>Field</TH>
<TH>Microsoft's Name</TH>
<TH>Offset</TH>
<TH>Size</TH></TR>
<TR>
<TD>Short Filename</TD>
<TD>DIR_Name</TD>
<TD>0x00</TD>
<TD align=right>11 Bytes</TH></TD>
<TR>
<TD>Attrib Byte</TD>
<TD>DIR_Attr</TD>
<TD>0x0B</TD>
<TD align=right>8 Bits</TD></TR>
<TR>
<TD>First Cluster High</TD>
<TD>DIR_FstClusHI</TD>
<TD>0x14</TD>
<TD align=right>16 Bits</TD></TR>
<TR>
<TD>First Cluster Low</TD>
<TD>DIR_FstClusLO</TD>
<TD>0x1A</TD>
<TD align=right>16 Bits</TD></TR>
<TR>
<TD>File Size</TD>
<TD>DIR_FileSize</TD>
<TD>0x1C</TD>
<TD align=right>32 Bits</TD></TR></TBODY></TABLE>
<P>The Attrib byte has six bits defined, as shown in the table below. Most
simple firmware will check the Attrib byte to determine if the 32 bytes are a
normal record or long filename data, and to determine if it is a normal file or
a subdirectory. Long filename records have all four of the least significant
bits set. Normal files rarely have any of these four bits set.
<P>
<TABLE cellSpacing=0 cellPadding=4 align=center border=1>
<TBODY>
<TR>
<TH>Attrib Bit</TH>
<TH>Function</TH>
<TH>LFN</TH>
<TH>Comment</TH></TR>
<TR>
<TD>0 (LSB)</TD>
<TD>Read Only</TD>
<TD>1</TD>
<TD>Should not allow writing</TD></TR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -