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 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 \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

Regresar al índice de documentos