Introducción a FAT32
Jordi Bartolomé 10-1-2008
1-Introducción
2-FAT32
3-Región reservada
4-Región de las FATs
5-Región de datos de directorios y ficheros
6-Notas básicas sobre el MBR
7-Implementación en C de ejemplo
1-Introducción
Este es un resumen de como se organiza la información dentro de una partición FAT32. En este no se entra en detalles sobre temas relacionados con particionado de discos, ni tampoco sobre FAT12 ni FAT16. Aunque estos últimos sistemas son similares a FAT32, difieren en algunos puntos importantes. A quien desee profundizar más sobre FAT32 ( y también FAT12 y FAT16 ), le recomiendo el documento "FAT: General overview of On-Disk Format (Hardware White Paper)" de Microsoft. La mayor parte de la información aquí expuesta está extraída de este documento. Recomiendo también contrastar esta información con la del documento de Microsoft, puesto que puede haber alguna incoherencia o error accidental.
Al final de la página hay un ejemplo de implementación en C de FAT32 sobre una tarjeta SD.
2-FAT32
FAT32 es un sistema de ficheros ( método que permite organizar la información guardadada en un soporte de almacenamiento de datos) desarrollado por Microsoft en 1995 como ampliación del sistema anterior FAT16 (1987) que a su vez era otra ampliación del sistema de ficheros original de MS-DOS, FAT12 (1977). Estas sucesivas ampliaciones han ido apareciendo con la intención de solventar los problemas que presentaban las versiones previas a medida que iba aumentando la capacidad de almacenamiento de los soportes físicos.
En un sistema FAT32 el espacio físico de almacenamiento se organiza en 3 grandes partes:
- Región reservada:
- BPB Bios Parameter Block
- Estructura File System Info
- Copia de la BPB Bios Parameter Block ( opcional aunque casi siempre presente )
- Región de las FATs:
- FAT
- Copia de la FAT ( opcional aunque casi siempre presente )
- Región de datos de directorios y ficheros
 |
Esquema general de organización de los primeros sectores de un file system FAT32 |
3-Región reservada
La región reservada comienza en el sector 0 de la partición, que no en el sector 0 del soporte. Es importante hacer esta distinción, dado que normalmente (aunque no siempre ) el primer sector del soporte está destinado al MBR el cual contiene la información básica de organización de las particiones. Al final del documento hay un pequeño apendice dónde se dan 4 notas básicas sobre el MBR.
Así, la región reservada contiene diferentes subloques con información básica del dispositivo de almacenamiento:
- BPB Bios Parameter Block ( a veces llamado Boot Sector o Sector 0 ). Es el primer sector del soporte (sector 0) y contiene la información elemental del dispositivo. La primera parte de la BPB es común para los sistemas FAT32, FAT16 y FAT12, pero la segunda parte es diferente en cada una de ellos. Se especifica a continuación la estructura de cada una de las 2 partes del BPB en FAT32:
- Primera parte del BPB ( comineza en el byte 0 del sector 0 de la partición ):
BPB Structure or Boot
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
|
\93MSWIN4.1\94 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, \93MSWIN4.1\94, 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 \93hard wired\94 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 \93bytes per cluster\94 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 \93hard wired\94 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 redundancy 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 \93fits\94 (is less than 0x10000).
|
BPB_Media Type
|
21
|
1
|
0xF8 is the standard value for \93fixed\94 (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 \93sectors per track\94 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 \93count of heads\94. 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).
|
(extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
Como originariamente el sistema FAT se diseñó para máquinas PC de IBM, los bytes se organizan siguiendo el criterio "Little Endian". Así los bytes más bajos se corresponden con los bytes de menos peso (menos significativos), y los bytes más altos con los de más peso (más significativos). P.ej, si el parámetro "BPB_HiddSec" comienza en el offset 28 del sector 0, y es de 32 bits (4 bytes), el byte 28 contendrá los 8 bits más bajos, el 29, los siguientes 8 bits... y el byte 31 los 8 bits de más peso.
-Segunda parte del BPB ( comienza en el byte 36 del sector 0 de la partición) :
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
|
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. 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
|
Volume label. This field matches the 11-byte volume label recorded in the root directory. 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. 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 \93 NO NAME \94.
|
BS_FilSysType
|
82
|
8
|
Always set to the string \94 FAT32 \94. Please see the note for this field in the FAT12/FAT16 section earlier.
NOTE: Many people think that the string in this field has something to do with the determination of what type of FAT\97FAT12, FAT16, or FAT32\97that 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.This field has nothing to do with FAT type determination.
|
(extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
Algunos de estos campos, hacen referencia a "sectores" y a "clústers". Un sector es la unidad física de almacenamiento en el soporte, y suelen ser agrupaciones de 128, 256, 512 o 1024 bytes. Un clúster es la unidad de alamacenamiento de la "Región de datos de ficheros y directorios". El campo BPB_BytsPerSec de la BPB contiene el número de bytes de que dispone un sector. Por otro lado el campo BPB_SecPerClus de la BPB nos permite conocer el número de sectores que forman un clúster.
- Estructura File System Info:
Esta es una estructura auxiliar que contiene información actualizada del estado de la tarjeta, como por ejemplo cual es el último clúster de la tarjeta o cual es el primer clúster libre para poder escribir. Como la tabla FAT32 puede ser muy grande, disponer de esta información actualizada puede acelerar mucho la ejecución de las operaciones de lectura o escritura en el soporte. Si no se dispone de esta información actualizada, se deberá recalcular cada vez que se realicen determinadas operaciones. La File System Info structure se situa en el sector indicado por el campo BPB_FSInfo de la BPB ( suele ser el sector 1).
FAT32 FSInfo Sector Structure
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\97which go into the bytes at offsets 510 and 511\97match the signature bytes used at the same offsets in sector 0.
|
(extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
- Copia de la BPB Bios Parameter Block:
Es muy frecuente que por razones de seguridad la "Region reservada" contenga una segunda copia de la BPB que permita restaurar la copia original si exsiten problemas. Esta copia comienza en el sector indicado por el campo BPB_BkBootSec de la BPB ( normalmente el sector 6 ), y es una réplica exacta de lo contenido en el BPB en el sector 0.
Lógicamente, para operar correctamente sobre la tarjeta es necesario cerciorarse de que efectivamente esta está formateada en FAT32. Llegados a este punto ya tenemos toda la información necesaria para saber si la tarjeta se encuentra formateada en FAT32 o no. Lo haremos comprobando que el número de clústers es mayor o igual a 65525 mediante el siguiente código:
RootDirSectors=((BPB_RootEntCont*32) + (BPB_BytsPerSec-1)) / BPB_BytsPerSec;
TFATSz = BPB_FATSz32;
TotSec = BPB_TotSec32;
DataSec = TotSec – (BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors);
CountofClusters = DataSec / BPB_SecPerClus;
If(CountofClusters < 4085) {
/* Volume is FAT12 */
} else if(CountofClusters < 65525) {
/* Volume is FAT16 */
} else {
/* !!!Volume is FAT32!!! */
} |
En FAT32, BPB_RootEntCont = 0 y por tanto RootDirSectors = 0. Por ello en FAT32 el código anterior se puede simplificar a:
DataSec = BPB_TotSec32 – BPB_ResvdSecCnt - (BPB_NumFATs * BPB_FATSz32);
CountofClusters = DataSec / BPB_SecPerClus;
if(CountofClusters >= 65525){
/* !!!Volume is FAT32!!! */
} |
4-Región de las FATs
La region de las FATs es la zona del soporte donde se localiza la "File Alocation Table" propiamente dicha y sus copias ( más adelante se explica en que consiste una FAT) . Comienza en el sector que sigue al último sector reservado. Es decir que la primera FAT se localiza en el sector indicado por el campo BPB_Rsvd_SecCnt de la BPB, justo después de la "Región reservada". Las dimensiones de las FAT vienen indicadas por el campo BPB_FATSz32 de la BPB, por lo que el último sector de la FAT se calculará BPB_Rsvd_SecCnt + BPB_FATSz32. Si la región de FATs tiene copias de seguridad de la FAT, este sector no será el último de la región, puesto que le seguirá la siguiente copia ( BPB_Rsvd_SecCnt + BPB_FATSz32*BPB_NumFATs).
La FAT tiene forma de tabla organizada en entradas sucesivas de 32 bits. Una entrada para cada clúster del soporte. Estas entradas permiten conocer el estado de cada uno de estos clústers, es decir saber si son defectuosos o no, si contienen o no información y si así es, si se corresponden con el último clúster del fichero o si en cambio el fichero continúa en algún otro clúster. De los 32 bits de cada entrada solo los 28 primeros ( los más bajos ) se utilizan para almacenar la dirección de clústers, los cuatro superiores están reservados. Algunos valores para las entradas de la FAT son :
0x?0000000 : clúster libre
0x?0000001 : clúster reservado que no se debe utilizar
0x?0000002 hasta 0x?FFFFFEF : clúster usado ( en realidad no es 0x?0000002 sino BPB_RootCluster que casi siempre es 2 ). El valor aquí contenido representa el clúster donde continuaría el directorio o fichero contenido en este clúster.
0x?FFFFFF0 hasta 0x?FFFFFF6 : Valores reservados que no se deben utilizar
0x?FFFFFF7: marca de clúster defectuoso
0x?FFFFFF8: marca de primer clúster (reservado) de la data region el ultimo byte se corresponde con el BPB_Media que suele ser 0xF8
0x?FFFFFFF : Indica que es el ultimo clúster del fichero o directorio es decir que el fichero finaliza en este clúster.
(NOTA: el interrogante \91?' se corresponde con los 4 bits superiores que tampoco se utilizan para dirección) |
Las entradas de 32 bits se organizan secuencialmente, una detrás de otra, a lo largo los sectores de la FAT, por tanto para leer la entrada de la FAT asociada a un clúster N (donde N: BPB_RootClus <= N < FSI_FreeCount) basta con ejecutar la operacion:
FATSz = BPB_FATSz32;
FATOffset = N * 4;
ThisFATSecNum = BPB_ResvdSecCnt + (FATOffset / BPB_BytsPerSec);
ThisFATEntOffset = REM(FATOffset / BPB_BytsPerSec); // REM es el residuo de la división |
Tal como se ha comentado, es frecuente que la zona de FATs contenga una segunda copia de la FAT. Los drivers de acceso al soporte únicamente suelen usar la primera de las FATs, pero al realizar operaciones de escritura es importante que actualicen la/s copia/s de cara a que las aplicaciones de recuperación que puedan acceder a estas dispongan de información actualizada.
Las entradas de la FAT que contienen el valor 0 corresponden a los clústers libres, por tanto la lista de clústers libres no existe como tal, sino que se debe calcular a partir de la lista de entradas de la FAT con el valor 0. Los campos FSI_Free_Count o FSI_Nxt_Free de la File System Structure pueden ayudar en esta operación ya que en teoría deberían contener esta información actualizada.
Ejemplo de inicio de FAT:

1-
0xF8 0xFF 0xFF 0x0F = 0x0FFFFFF8 Corresponde al primer clúster, el cual está siempre reservado. La entrada FAT de este clúster contiene siempre el byte BPB_Media en su byte mas bajo, seguido todo de unos. Como en este caso el BPB_Media es 0xF8, la entrada FAT es 0x0FFFFFF8
2-
0xFF 0xFF 0xFF 0xFF = 0xFFFFFFFF Corresponde al siguiente clúster reservado de la FAT. Como BPB_RootClus generalmente es 2 la siguiente entrada corresponde ya a un clúster no reservado, con información de usuario válida. Si BPB_RootClus fuera mayor de 2, las entradas de los clústers anteriores a este tendrían el valor aquí indicado.
3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 -
0xFF 0xFF 0xFF 0x0F = 0x0FFFFFFF Marca EOC de FAT32, que indica que es el último clúster del fichero o directorio. Si el fichero o directorio continuara en otro clúster, esta entrada contendría el número de clúster donde continúa. Pero como no continua en otro clúster, contiene la marca EOC.
16 , 17, ... -
0x00 0x00 0x00 0x00 = 0x00000000 Indica que el clúster está libre
5-Región de datos de directorios y ficheros:
Esta es la región donde se guarda la información de usuario propiamente dicha, es decir donde se sitúa todo el contenido que el usuario almacena en el dispositivo ( la información tanto de los directorios como de los ficheros). Desde la perspectiva del sistema de ficheros, la información de la "Region de Datos de Directorios y Ficheros" se organiza en clústers. Un clúster es la unidad lógica de almacenamiento del sistema de ficheros, y suele estar formada por entre 4 y 64 sectores, por lo que suelen ir de 2kB a 32kB de capacidad. En otras palabras: un clúster no es más que una agrupación lógica de sectores consecutivos.
La "Región de Datos" comienza en el BPB_RootClus, ( generalmente el clúster 2 ). Los valores por debajo del BPB_RootClus ( el clúster 0 y clúster 1) son valores reservados que no se pueden utilizar ( en realidad se corresponden a las areas del soporte con la información de la Región Reservada y las FATs). Para FAT32, el sector donde comienza el BPB_Rootclúster ( o lo que es lo mismo la Región de datos ) se calcula:
FirstDataRegionSector = BPB_ResvdSecCnt + (BPB_NumFats x BPB_FatSz32) |
Para cualquier número válido de clúster, el número del primer sector de ese clúster se calcula:
// BPB_RootClus normalmente vale 2
FirstSectorOfClusterN = ( (N - BPB_RootClus)*BPB_SecPerClus) +FirstDataRegionSector |
En los clústers de la Data Region encontraremos 3 tipos de información:
- FAT 32 Byte Directory Entry Structure: grupos de 32 bytes que contienen la información básica del volumen, de fichero o directorio. La información básica se corresponde a fechas y horas de creación o modificación, clúster donde se encuentra la información etc.
- FAT Long Directory Entry Structure: son las entradas de nombre largo, añadidas en FAT32 para permitir el almacenamiento de nombres de directorio o de fichero mayores de 11 bytes.
- Bytes con el contenido de fichero
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.
|
(extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
Para leer el contenido de un fichero bastaría saltar al clúster indicado por los respectivos campos DIR_FstClusLO y DIR_FstClusHI de la entrada de fichero y comenzar a leer los bytes de este. Deberemos leer tantos bytes como indique DIR_FileSize. A través de este último campo o consultando la correspondiente entrada de la FAT podremos saber si el fichero termina en este clúster, o si al contrario continua en otro. En caso de que ocupe más de un clúster, bastará con consultar la entrada FAT del clúster donde estamos leyendo para conocer el número de clúster donde continua el fichero. Se puede comprobar que, efectivamente, un fichero no es más que una secuencia de clústers encadenados a través de las respectivas entradas de la FAT. Consultando la FAT y conociendo el clúster de inicio ( DIR_FstClusLO y DIR_FstClusHI ) y el tamaño ( DIR_FileSize ) podremos movernos por un fichero sin problemas.
En el caso de los clústers con información FAT Long Directory Entry Structure y FAT Directory Entry Structure la unica opción para saber si debemos continuar leyendo otros clúster o no, es consultar la correspondiente entrada de la FAT, y verificar si lo que se esta leyendo se corresponde con una entrada o en cambio no se corresponde con nada, por lo que ya habríamos leído todas las entradas del directorio.
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.
|
(extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
El primer sector del RootCluster, comenzará con la información de volumen (32 bytes y basta) seguido de las entradas de nombres de los diferentes ficheros y o directorios ( con sus fechas, horas direcciones de cluser etc.) de la raíz.
Si el primer byte ( offset 0 ) de una entrada vale 0xE5, significa que esta entrada había sido usada con anterioridad pero ahora se encuentra libre, sin contenido útil. Si vale 0x00 significa que la entrada está libre, nunca ha sido utilizada y lógicamente tampoco tiene contenido útil. El byte DIR_ATTR ( offset 11 ) de cada entrada nos permite saber el tipo de esta ( long entry, fichero, directorio, volumen ... ), y por tanto como debemos procesarla y que información podemos obtener de ella. Si se trata de una long entry el primer byte de la primera entrada de nombre largo también nos permitirá saber cuantas entradas de nombre largo componen el nombre. Las entradas de nombre largo que componen el nombre se encuentran ordenadas al revés, es decir que primero aparece la última entrada de nombre largo, y luego las antecesoras hasta llegar a la que realmente es la primera. A continuación de la primera Long Directory Entry Structure, aparece la Directory Entry Structure con la información de úbicacion, fecha y tamaño etc. El siguiente diagrama de la documentación de Microsoft lo muestra mejor:
Sequence Of Long Directory Entries
Entry
|
Ordinal
|
Nth Long entry
|
LAST_LONG_ENTRY (0x40) | N
|
\85 Additional Long Entries
|
\85
|
1 st Long entry
|
1
|
Short Entry Associated With Preceding Long Entries
|
(not applicable)
|
(Extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
|
Contenido de una Long Directory Entry:

(Extraido del documento "FAT: General overview of On-Disk Format" de Microsoft)
P.ej, imaginemos que tras leer los 32 bytes de volumen, nuestro driver lee un 0x42, esto indicaría que los 31 bytes que siguen se corresponden con una segunda y ultima entrada Long Directory entry structure ( 0x40:ultimo | 0x02:segunda ). Luego, tras esta, deberíamos encontrar los 32 bytes de la primera entrada Long Directory Entry Structure que comenzaría por 0x01 ( 0x01: primero ). A continuación deberían seguir los 32 bytes de la entrada Directory Entry Structure con la información general de clúster , fecha de fichero o directorio etc.
Ejemplo de inicio de Root Cluster y Root Directory:

1 \96
Primer Sector del RootCluster: contendrá información del volumen y ya está.
TARJETATEST = DirName
0x08 = DirAttr = ATTR_VOLUME_ID indica que DirName se corresponde con el ID de un volumen.
Todos los bytes tienen valores NULOs a excepcion del WrtTime y WrtDate. Se corresponde a la hora-fecha en que se creo el volumen.
2 \96
La siguiente tira de 32 bytes corresponden con una segunda y ultima entrada Long Directory Entry Structure ( 0x40:ultimo | 0x02:segunda ):
\91B': = 0x42 = LDIR_Ord = 0x04 | 0x02, el 0x04 indica que es la ultima entrada , y el 0x02 que es la entrada 2 de nombre largo (aun restará la 0x01 con la primera Long Directory entry structure y la Directory entry structure con la información del fichero o directorio )
0x73 0x00 = \93s.\94 = LdirName1[0..1] = Es el contenido de la entrada de nombre largo
\93..\94 = 0x00 0x00 = LdirName1[2..4] = No hay mas carácteres en la entrada de nombre largo, el resto es inválido
0xFF 0xFF = \93ÿÿ\94 = LdirName1[5..6] = 0xFF 0xFF inválido
0xFF 0xFF = \93ÿÿ\94 = LdirName1[7..8] = 0xFF 0xFF Invalido
0xFF 0xFF = \93ÿÿ\94 = 0xFF 0xFF = LdirName1[9..10] = 0xFF 0xFF Invalido
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que la entrada es un subcomponente de un LONG NAME
0x6F = Checksum
Como el texto ya acabó (\93..\94 = LdirName1[2..4] ) no hacemos caso de los siguientes bytes puesto que no contienen información útil.
3-
La siguiente tira de 32 bytes se corresponde con la primera entrada Long Directory Entry Structure ( 0x00 | 0x01:primera):
\91.' = 0x01 = LDIR_Ord = 0x00 | 0x01, el 0x00 indica que NO es la última entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 0x00 = \93D.\94 = LdirName1[0..1]
0x68 0x00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x65 0x00 = \93e.\94 = LdirName1[7..8]
0x63 0x00 = \93c.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que la entrada es un subcomponente de un LONG NAME
0x6F = Checksum
0x74 0x00 = \93t.\94 = LdirName2[0..1] segunda parte de la entra
0x6F 0x00 = \93o.\94 = LdirName2[2..4] = No hay mas caracteres en la entrada de nombres largo, el resto es invalido
0x72 0x00 = \93r.\94 = 0x72 0x00 = LdirName2[5..6]
0x69 0x00 = \93i.\94 = 0x69 0x00 = LdirName2[7..8]
0x6F 0x00 = \93o.\94 = 0x6F LdirName2[9..10]
0x54 0x00 = \93T.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x72 0x00 = \93r.\94 = LdirName3[0..1]
0x65 0x00 = \93e.\94 = LdirName3[2..4].
4-
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRECT~1 \94 = DIR_Name
0x10 = DIR_Attr = ATTR_DIRECTORY = toda la información leida se corresponde a un directorio
0x00 = DIR_NTRes = Reservado para windows NT
0x70 = DiRCrtTimeTenth
0xD2 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0xD3 0xAA = DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x03 0x00 = DIR_FstClusLO
0x00 0x00 0x00 0x00 = DIR_FileSize
Según la información contenida en esta Directory Entry Structure, el contenido del directorio \93DirectorioTres\94 comienza en el clúster 0x00 0x00 0x00 0x03. Para leer su contenido deberíamos saltar a ese clúster, y alli comezar a leer las entradas de 32 bytes de las correspondientes Directory Entry Structure, y Long Directory Entry Structure. Más adelante se encuentra un ejemplo de estructura de un subdirectorio que se corresponde con el subdirectorio apuntado por esta entrada.
5-
La siguiente tira de 32 bytes corresponden con la primera y ultima entrada Long Directory Entry Structure ( 0x04 ultima | 0x01:primera):
\91A' = 0x04|0x01 = LDIR_Ord = 0x04 | 0x01, el 0x04 indica que es la ultima entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 0x00 = \93D.\94 = LdirName1[0..1]
0x69 0x00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x65 0x00 = \93e.\94 = LdirName1[7..8]
0x63 0x00 = \93c.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que la entrada es un subcomponente de un LONG NAME
0x8F = Checksum
0x74 0x00 = \93t.\94 = LdirName2[0..1] segunda parte de la entra
0x6F 0x00 = \93o.\94 = LdirName2[2..4] = No hay mas caracteres en la entrada de nombres largo, el resto es invalido
0x72 0x00 = \93r.\94 = LdirName2[5..6]
0x69 00 = \93i.\94 = LdirName2[7..8]
0x6F 0x00 = \93o.\94 = LdirName2[9..10]
0x55 0x00 = \93U.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x6E 0x00 = \93n.\94 = LdirName3[0..1]
0x6F 0x00 = \93o.\94 = LdirName3[2..4]
6-
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRECT~2 \94=DIR_Name
0x10 = DIR_Attr = ATTR_DIRECTORY = toda la información leida se corresponde a un directorio
0x00 = DIR_NTRes = Reservado para windows NT
0xC5 = DiRCrtTimeTenth
0xD2 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0xD3 0xAA = DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x07 0x00 = DIR_FstClusLO
0x00 0x00 0x00 0x00 = DIR_FileSize
Según la información contenida en esta entrada Directory Entry Structure, el contenido del directorio \93DirectorioUno\94 comienza en el clúster 0x00 0x00 0x00 0x07. Para leer su contenido deberíamos saltar a ese clúster, y alli comezar a leer las entradas de 32 bytes de las correspondientes Directory Entry Structure, y Long Directory Entry Structure.
7-
La siguiente tira de 32 bytes corresponden con la primera y ultima entrada Long Directory Entry Structure ( 0x04 ultima | 0x01:primera):
\91A' = 0x04 | 0x01 = LDIR_Ord = 0x04 | 0x01, el 0x04 indica que es la ultima entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 0x00 = \93D.\94 = LdirName1[0..1]
0x69 0x00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x65 0x00 = \93e.\94 = LdirName1[7..8]
0x63 0x00 = \93c.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que la entrada es un subcomponente de un LONG NAME
0x2F = Checksum
0x74 0x00 = \93t.\94 = LdirName2[0..1] segunda parte de la entra
0x6F 0x00 = \93o.\94 = LdirName2[2..4] = No hay mas caracteres en la entrada de nombres largo, el resto es invalido
0x72 0x00 = \93r.\94 = LdirName2[5..6]
0x69 0x00 = \93i.\94 = LdirName2[7..8]
0x6F 0x00 = \93o.\94 = LdirName2[9..10]
0x44 0x00 = \93D.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x6F 0x00 = \93o.\94 = LdirName3[0..1]
0x73 0x00 = \93s.\94 = LdirName3[2..4]
8-
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRECT~3 \94=DIR_Name
0x10 = DIR_Attr = ATTR_DIRECTORY = toda la información leida se corresponde a un directorio
0x00 = DIR_NTRes = Reservado para windows NT
0x4F = DiRCrtTimeTenth
0xD3 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0xD4 0xAA = DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x0B 0x00 = DIR_FstClusLO
0x00 0x00 0x00 0x00 = DIR_FileSize
Según la información contenida en esta entrada Directory Entry Structure, el contenido del directorio \93DirectorioDos\94 comienza en el clúster 0x00 0x00 0x00 0x0B. Para leer su contenido deberíamos saltar a ese clúster, y allí comezar a leer las entradas de 32 bytes de las correspondientes Directory Entry Structure, y Long Directory Entry Structure.
Ejemplo de subdirectorio:
1-
Se corresponde con los 32 bytes de la entrada del directorio que apunta al propio directorio, es decir es la entrada \93 \. \94
\93. \93 = 0x2E 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 =DIR_Name
0x10 = DIR_Attr = ATTR_DIRECTORY
0x00 = DIR_NTRes = Reservado para windows NT
0x70 = DIR_CrtTimeTenth
0xD2 0xAA = DIR_CrtTime
0x83 0x37 = DIR_CrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0xD3 0xAA = DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x03 0x00 = DIR_FstClusLO
0x00 0x00 0x00 0x00 = DIR_FileSize
2-
Se corresponde con los 32 bytes de la entrada del directorio que apunta al directorio precendente en este caso a la raíz. Es decir es la entrada \93 \.. \94
\93.. \93 = 0x2E 0x2E 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 =DIR_Name
0x10 = DIR_Attr = ATTR_DIRECTORY
0x00 = DIR_NTRes = Reservado para windows NT
0x70 = DIR_CrtTimeTenth
0xD2 0xAA = DIR_CrtTime
0x83 0x37 = DIR_CrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0xD3 0xAA = DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x03 0x00 = DIR_FstClusLO
0x00 0x00 0x00 0x00 = DIR_FileSize
3 \96
La siguiente tira de 32 bytes corresponden con una segunda y ultima entrada Long Directory Entry Structure ( 0x04 ultima | 0x02:segunda):
\91B' = 0x04|0x02 = LDIR_Ord = 0x04 | 0x02, el 0x04 indica que es la ultima entrada , y el 0x02 que es el campo 2 de la entrada de nombre largo, es decir la segunda.
0x6F 0x00 = \93o.\94 = LdirName1[0..1]
0x44 0x00 = \93D.\94 = LdirName1[2..4]
0x6F 0x00 = \93o.\94 = LdirName1[5..6]
0x73 0x00 = \93s.\94 = LdirName1[7..8]
\93..\93 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0xB2 = Checksum
0x74 0x00 = \93t.\94 = LdirName2[0..1]
\93x.\94 = LdirName2[2..4]
0x74 0x00 = \93t.\94 = LdirName2[5..6]
\93..\94 = 0x00 0x00 = LdirName2[7..8] = indica final del texto del Long Directory Entry Structure
0xFF 0xFF = \93ÿÿ\94 = LdirName2[9..10]
0xFF 0xFF = \93ÿÿ\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0xFF 0xFF = \93ÿÿ\94 = LdirName3[0..1]
0xFF 0xFF = \93ÿÿ\94 = LdirName3[2..4]
4 \96
La siguiente tira de 32 bytes corresponden con una primera entrada Long Directory Entry Structure ( 0x00: no es la última | 0x01:primera ):
\91.' = 0x00 | 0x01 = LDIR_Ord = 0x00 | 0x01, el 0x00 indica que no es la ultima entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 00 = \93D.\94 = LdirName1[0..1]
0x69 00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x54 0x00 = \93T.\94 = LdirName1[7..8]
0x72 0x00 = \93r.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0xB2 = Checksum
0x65 0x00 = \93e.\94 = LdirName2[0..1]
0x73 0x00 = \93s.\94 = LdirName2[2..4]
0x46 0x00 = \93F.\94 = LdirName2[5..6]
0x69 0x00 = \93i.\94 = LdirName2[7..8]
0x63 0x00 = \93c.\94 = LdirName2[9..10]
0x68 0x00 = \93h.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x65 0x00 = \93e.\94 = LdirName3[0..1]
0x72 0x00 = \93r.\94 = LdirName3[2..4]
5 \96
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRTRE~1TXT\94=DIR_Name
0x20 = DIR_Attr = ATTR_ARCHIVE = toda la información leida se corresponde con un fichero
0x00 = DIR_NTRes = Reservado para windows NT
0x7E = DiRCrtTimeTenth
0xD2 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0x42 0xB5= DIR_WrtTime
0x83 0x37 = DIR_WrtDate
0x04 0x00= DIR_FstClusLO
0x89 0x05 0x00 0x00 = DIR_FileSize
6 \96
La siguiente tira de 32 bytes se corresponde con una segunda y ultima entrada Long Directory Entry Structure ( 0x04 ultima | 0x02:segunda):
\91B' = 0x04|0x02 = LDIR_Ord = 0x04 | 0x02, el 0x04 indica que es la ultima entrada , y el 0x02 que es el campo 2 de la entrada de nombre largo, es decir la segunda.
0x6F 0x00 = "o." = LdirName1[0..1]
0x54 0x00 = "T." = LdirName1[2..4]
0x72 0x00 = "r." = LdirName1[5..6]
0x65 0x00 = "e."= LdirName1[7..8]
0x73 0x00 = "s." = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0x92 = Checksum
0x2E 0x00 = " . ." = LdirName2 [0..1]
0x74 0x00 = "t." = LdirName2 [2..4]
0x78 0x00 = "x." = LdirName2 [5..6]
0x74 0x00 = "t." = LdirName2 [7..8]
0x00 0x00 = " . ." = LdirName2[9..10] = indica final del texto del Long Directory Entry Structure
0xFF 0xFF = \93ÿÿ\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0xFF 0xFF = \93ÿÿ\94 = LdirName3[0..1]
0xFF 0xFF = \93ÿÿ\94 = LdirName3[2..4]
7-
La siguiente tira de 32 bytes corresponden con una primera entrada Long Directory Entry Structure ( 0x00: no es la última | 0x01:primera ):
\91.' = 0x00 | 0x01 = LDIR_Ord = 0x00 | 0x01, el 0x00 indica que no es la ultima entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 00 = \93D.\94 = LdirName1[0..1]
0x69 00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x54 0x00 = \93T.\94 = LdirName1[7..8]
0x72 0x00 = \93r.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0xB2 = Checksum
0x65 0x00 = \93e.\94 = LdirName2[0..1]
0x73 0x00 = \93s.\94 = LdirName2[2..4]
0x46 0x00 = \93F.\94 = LdirName2[5..6]
0x69 0x00 = \93i.\94 = LdirName2[7..8]
0x63 0x00 = \93c.\94 = LdirName2[9..10]
0x68 0x00 = \93h.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x65 0x00 = \93e.\94 = LdirName3[0..1]
0x72 0x00 = \93r.\94 = LdirName3[2..4]
8 \96
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRTRE~2TXT\94=DIR_Name
0x20 = DIR_Attr = ATTR_ARCHIVE = toda la información leida se corresponde con un fichero
0x00 = DIR_NTRes = Reservado para windows NT
0x92 = DiRCrtTimeTenth
0xD2 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0x42 0xB5= DIR_WrtTime
0x82 0x37 = DIR_WrtDate
0x05 0x00= DIR_FstClusLO
0x89 0x05 0x00 0x00 = DIR_FileSize
9 \96
La siguiente tira de 32 bytes corresponden con una segunda y ultima entrada Long Directory Entry Structure ( 0x04 ultima | 0x02:segunda):
\91B' = 0x04|0x02 = LDIR_Ord = 0x04 | 0x02, el 0x04 indica que es la ultima entrada , y el 0x02 que es el campo 2 de la entrada de nombre largo, es decir la segunda.
0x6F 0x00 = "o." = LdirName1[0..1]
0x55 0x00 = "U."= LdirName1[2..4]
0x6E 0x00 = "n."= LdirName1[5..6]
0x6F 0x00 = "o." = LdirName1[7..8]
0x2E 0x00 = " . ." = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0x72 = Checksum
0x74 0x00 ="t." = LdirName2 [0..1]
0x78 0x00 ="x." = LdirName2 [2..4]
0x74 0x00 ="t." = LdirName2 [5..6]
0x74 0x00 = "t." = LdirName2 [7..8]
0x00 0x00 =" . ." = LdirName2[9..10] = indica final del texto del Long Directory Entry Structure
0x00 0x00 =".." = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0xFF 0xFF = \93ÿÿ\94 = LdirName3[0..1]
0xFF 0xFF = \93ÿÿ\94 = LdirName3[2..4]
10 \96
La siguiente tira de 32 bytes corresponden con una primera entrada Long Directory Entry Structure ( 0x00: no es la última | 0x01:primera ):
\91.' = 0x00 | 0x01 = LDIR_Ord = 0x00 | 0x01, el 0x00 indica que no es la ultima entrada , y el 0x01 que es el campo 1 de la entrada de nombre largo, es decir la primera.
0x44 00 = \93D.\94 = LdirName1[0..1]
0x69 00 = \93i.\94 = LdirName1[2..4]
0x72 0x00 = \93r.\94 = LdirName1[5..6]
0x54 0x00 = \93T.\94 = LdirName1[7..8]
0x72 0x00 = \93r.\94 = LdirName1[9..10]
0x0F = LDIR_Attr = son los atributos del directorio indicando que es un ATTR_LONG_NAME
0x00 = LDRI_Type = si es 0 es que es la entrada es un subcomponente de un LONG NAME
0xB2 = Checksum
0x65 0x00 = \93e.\94 = LdirName2[0..1]
0x73 0x00 = \93s.\94 = LdirName2[2..4]
0x46 0x00 = \93F.\94 = LdirName2[5..6]
0x69 0x00 = \93i.\94 = LdirName2[7..8]
0x63 0x00 = \93c.\94 = LdirName2[9..10]
0x68 0x00 = \93h.\94 = LdirName2[11..12]
0x00 0x00 = FirstClusterLO = debe ser siempre 0, en realidad no se usa
0x65 0x00 = \93e.\94 = LdirName3[0..1]
0x72 0x00 = \93r.\94 = LdirName3[2..4]
11 \96
La siguiente tira de 32 bytes se corresponde a la entrada Directory Entry Structure, y comienza directamente con el nombre:
\93DIRTRE~3TXT\94 \94=DIR_Name
0x20= DIR_Attr = ATTR_ARCHIVE = toda la información leida se corresponde con un fichero
0x00 = DIR_NTRes = Reservado para windows NT
0xB3 = DiRCrtTimeTenth
0xD2 0xAA = DiRCrtTime
0x83 0x37 = DORCrtDate
0x83 0x37 = DIR_LstAccDate
0x00 0x00 = DIR_FstClusHi
0x3C 0xB3 = DIR_WrtTime
0x82 0x37 = DIR_WrtDate
0x06 0x00 = DIR_FstClusLO
0x89 0x05 0x00 0x00 = DIR_FileSize
Otro ejemplo de la documentación de Microsoft ( se corresponde con un fichero denominado 2The quick brown fox\94 ) :
6-Notas básicas sobre el MBR
Como se cita al inicio del documento, un mismo soporte puede contener diferentes particiones, cada una con su sistema de ficheros. Las particiones pueden ser más o menos complejas, con particiones primarias, extendidas y lógicas. La organización básica de estas particiones se establece en MBR ( Master Boot Record ) que se encuentra en el sector 0 del soporte. Interpretando la información contenida en éste sector, el sistema puede saber donde comienza cada partición primaria, si tiene sistema de ficheros, de que tipo de sistema de ficheros se trata etc :
Offset |
Tamaño |
Descripción |
0x000 |
440 Bytes |
Bytes reservados para código de arranque (boot) |
0x1B8 |
4 bytes |
Firma de disco opcional |
0x1BC |
2 Bytes |
Generalmente a 0x00 |
0x1BE |
16 Bytes |
1a Entrada de partición |
0x1CE |
16 Bytes |
2a Entrada de partición |
0x1DE |
16 Bytes |
3a Entrada de partición |
0x1EE |
16 Bytes |
4a Entrada de partición |
0x1FE |
2 Bytes |
Marca de Boot Record (55hAAh) |
(Organización general de la información en sector 0 correspondiente al MBR)
Los primeros 440 bytes del MBR están reservados para código de boot, es decir para código que implementa la inicialización de los subsitemas básicos que permiten arrancar el equipo. Algunos gestores de arranque utilizan este espacio para instalar su código. El resto de espacio se divide en 4 grupos de 16 bytes destinados a alamacenar información básica de las 4 posibles particiones primarias, y a la marca "boot record" ( 0x55h 0xAAh ).
Offset |
Tamaño |
Descripción |
0x00 |
1 Byte |
Estado de la partición (0x80 = bootable, 0x00 = non-bootable,
other = invalid) |
0x01 |
1 Byte |
Inicio de la partición - Cabeza |
0x02 |
1 Word |
Inicio de la partición - Sector |
0x04 |
1 Byte |
Tipo de partición ( 0x01 DOS 12-bit, 0x06 DOS 3.31+ 16-bit FAT, 0x07 OS/2 IF, Windows NT NTFS, 0x08 Commodore DOS, 0x0B WIN95 OSR2 FAT32 0x0C WIN95 OSR2 FAT32, 0x52 CP/M ... ) |
0x05 |
1 Byte |
Final de la partición - Cabeza |
0x06 |
1 Word |
Final de la partición - Cylinder/Sector |
0x08 |
1 Double Word |
Número de sectores entre el MBR y el primer sector de la partición |
0x0C |
1 Double Word |
Número de sectores en la partición |
(Organización general de la información en cada una de las Entradas de partición del MBR)
En algunas ocasiones es posible que un soporte no presente MBR y se encuentre organizado enteramente como una única partición ( como si fuera un "big floppy" ). Esto sucede por ejemplo con algunos modelos de tarjetas de memoria que vienen de fábrica preformateadas. Por otro lado es frecuente que al formatear estas tarjetas en cámaras de fotos, reproductores mp3 etc. estos creen un MBR. Así que, dependiendo del fabricante, del modelo, del dispositivo en que lo hayamos formateado etc., el soporte presentará MBR o no. Pero sea como sea, si deseamos tener más de una partición en el soporte deberemos tener MBR.
Ejemplo de un sector 0 MBR:
Ejemplo de un sector 0 que no es MBR ( contiene la región reservada de una FAT32 ):
Una forma ( no muy correcta ) de diferenciar si un sector 0 se corresponde con el MBR o con el primer sector de una FAT32 es consultar el byte BPB Media Type ( offset 21 ), de manera que si el valor leido se corresponde con un valor válido para este campo, probablemente se trate de una FAT32. No obstante esto puede no funcionar siempre, e incluso ser una fuente de problemas si se utilizan soportes con formatos de ficheros distintos a FAT32.
7-Implementación en C de ejemplo
El siguiente archivo comprimido contiene varios ficheros que implementan FAT32 (sólo de lectura) sobre una tarjeta SD. Estos han sido desarrollados para un microcontrolador de 8 bits de la familia ATmega de ATmel, pero con alguna modificación deberian servir para cualqier otro micro. Junto a los ficheros de implementación del sistema de ficheros (FAT32.c y FAT32.h), se encuentra también el driver de acceso a la tarjeta (SD.c, SD.h) que permite al microcontrolador operar sobre esta a través de su SPI. Sustituyendo estos últimos ficheros o adaptándolos adecuadamente se podría implementar FAT32 sobre otros muchos dispositivos de memoria.
Descargar FAT32.zip
|