FAT Por Dentro

download FAT Por Dentro

of 22

Transcript of FAT Por Dentro

  • 7/28/2019 FAT Por Dentro

    1/22

    FAT por dentro

    A continuacin todo lo que se necesita saber sobre este sistema de archivos del que aun no podemos

    prescindir.

    Que significa FAT?

    FAT es el acrnimo deFile Allocation Table (Tabla de alocacin de archivos). Tiene su origen al

    final de los 1970s y comienzo de los 1980s y fue el sistema de archivos soportado por el sistema

    operativo Microsoft MS-DOS.

    Fue pensado como un simple sistema de archivo para utilizar en unidades de disco removibles

    (diskettes) de menos de 500K de tamao. Con el paso del tiempo, se fueron introduciendo cambios

    en la especificacin para soportar medios de almacenamiento cada vez mayores.

    Tipos de FAT

    En la actualidad coexisten tres sistemas de archivos tipo FAT: FAT12, FAT16 y FAT32. Las

    diferencias bsicas entre esos subtipos, y la razn de sus nombres, es el tamao, en bits, de las

    entradas en la estructura FAT en el disco.

    Es decir, hay 12 bits en una FAT12, 16 bits en una FAT16 y 32 bits en una FAT32. Las siguientes

    generalidades son aplicables a todos los tipos de FAT existentes.

    Todos los sistemas de archivos FAT fueron pensados originalmente para la arquitectura del IBM PC.

    Este es un dato importante, debido a que este hardware hace uso de las estructuras de datos en

    formato little endian. Si observamos una entrada en una FAT de 32 bits, almacenada como cuatro

    bytes (de 8 bits cada uno), siendo el primero el byte 00 y el ultimo el byte 03, los bits se encuentranen el siguiente orden (donde el bit menos significativo es el 00):

    Byte 03 - Byte 02 - Byte 01 - Byte 00

    Esto es particularmente importante si su maquina es big endian, dado que deber realizar una

    traduccion entre ambos formatos antes de mover datos desde y hacia el disco.

    Discos con FAT

    Un disco con sistema de archivos FAT esta dividido en cuatro zonas bsicas, que se encuentran en el

    siguiente orden:

    0 Zona reservada (Reserved Region)

    1 Zona de la FAT (FAT Region)

    2 Zona del directorio raiz (no existe en los discos con FAT32)

    3 Zona de datos de directorios y archivos.

    Sector de arranque (Boot Sector) y BIOS Parameter Block (BPB)

    La primer estructura de datos importante en un disco con FAT es la llamada BIOS Parameter Block

    (en adelante BPB), que se encuentra en el primer sector del disco dentro de la zona reservada.

  • 7/28/2019 FAT Por Dentro

    2/22

    En diferentes documentos se refiere a este sector como boot sector o reserved sector o 0th

    sector, pero el hecho verdaderamente importante es que se trata del primer sector en el disco.

    Este es el primer elemento que suele causar confusin cuando hablamos del sistema de archivos

    FAT. En las versiones 1.x del MS-DOS no exista un BPB en el sector de arranque. Es estas primeras

    versiones de FAT solamente haba dos formatos de disco posibles: 5.25 pulgadas y 360K, en una o

    dos caras.

    La manera de determinar de qu tipo era un disco consista en ver el contenido del primer byte de su

    FAT (los 8 bits bajos de FAT[0]).

    Esta forma de determinar el tipo de disco fue superada en las versiones 2.x del MS-DOS, cuando se

    agrego en el sector de arranque el BPB, y dejo de ser soportado el primitivo mtodo basado en mirar

    el contenido del primer byte de la FAT. Todos los discos con sistema de archivos FAT deben tener

    un BPB en el sector de arranque.

    Esto nos lleva al segundo tema que produce confusin al intentar determinar el tipo de FAT: Cul

    es la funcin que cumple exactamente el PBP? Tal como esta definido en las versiones 2.x del MS-DOS permite discos con menos de 65,536 sectores (32 MB en sectores de 512 bytes).

    Esta limitacin proviene de que el campo que alberga el valor correspondiente al numero total de

    sectores tiene 16 bits de longitud (2^16 = 65536). Esta limitacin fue superada con el MS-DOS 3.x,

    en el que el BPB fue modificado y su longitud llevada 32 bits.

    El siguiente cambio importante en el BPB vino de la mano de la versin OEM Service Release 2

    (OSR2) deMicrosoft Windows 95, donde se introdujo la FAT32. FAT16 estaba limitada por el

    tamao mximo de la propia FAT y por el tamao mximo de cluster, que no permitan discos de

    ms de 2 GB si se empleaban sectores de 512 bytes. FAT32 supero esa limitacin, y los discos de

    ms de 2 GB podan utilizarse sin necesidad de particionarlos en varias partes.

    El BPB del sistema de archivos FAT32 coincide exactamente con el BPB de las FAT12 y FAT16,

    hasta el campo BPB_TotSec32 (ver mas adelante). Las diferencias comienzan en el offset 36,

    dependiendo si se trata de un sistema FAT32 o FAT12/FAT16. Mas adelante veremos como

    determinar esto. El punto importante de destacar es que los primeros 36 bytes coinciden,

    independientemente del tipo de FAT que estemos utilizando. Esto permite la mxima compatibilidad

    entre diferentes sistemas, y permite a los drivers entender y soportar cualquiera de los tipos, ya que

    siempre contienen los mismos campos.

    NOTA: En la descripcin siguiente, todos los campos cuyos nombres comienzan conBPB_' son parte del BPB.

    Aquellos cuyo nombre comienza con BS_ son parte del sector de arranque (BootSector),

    y no son, en realidad, parte del BPB.

    Veremos el comienzo del sector 0 de un sistema de archivos FAT, que contiene BPB.

    Concretamente, analizaremos la FAT de un diskette de 3.5 formateado con Windows

    XP.

    Estructura del sector de arranque (Boot Sector) y BPB

    La siguiente es la captura de los primeros 512 bytes de un diskette de 3.5 formateado con WinXP:

  • 7/28/2019 FAT Por Dentro

    3/22

    Utilizaremos esta imagen como ejemplo, y la analizaremos bit a bit a medida que vayamos

    conociendo de que se trata cada uno de ellos.

    Campos comunes a todas las FATs

    BS_jmpBoot

    Offset (Byte): 0 Tamao (Bytes): 3

    Descripcin: Instruccin de salto al cdigo de arranque. Este campo tiene una de las siguientes

    formas:

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

    o

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

    0x?? significa que esta permitido cualquier valor de 8 bits. Estos tres bytes componen una instruccin

    de salto incondicional Intel x86 (jump) que apunta al inicio del cdigo de arranque del sistema

    operativo. Generalmente, este cdigo ocupa el resto del espacio siguiente al BPB en el sector de

    arranque, posiblemente otros sectores.

  • 7/28/2019 FAT Por Dentro

    4/22

    Cualquiera de las dos formas son aceptadas, pero JmpBoot[0] = 0xEB es el formato mas

    frecuentemente utilizado.

    En nuestro ejemplo, encontramos los bytes EB 3C 90 , lo que significa que se trata de la primera

    de las alternativas.

    BS_OEMName

    Offset (Byte): 3 Tamao (Bytes): 8

    Descripcin: Generalmente se trata de la cadena MSWIN4.1. Existe todo un folclore acerca de la

    funcin de este campo, pero solo se trata de una cadena de texto.

    Los sistemas operativos de Microsoft no prestan ninguna atencin a su contenido. Algunos drivers si

    lo hacen, por ese motivo se recomienda el valor MSWIN4.1, de manera de evitar

    incompatibilidades.

    El implementador es libre de cambiar esta cadena por cualquier otra, pero puede ocurrir que algn

    driver en particular no reconozca la unidad. Generalmente se toma como una indicacin de que la

    unidad esta formateada.

    El diskette formateado con Windows XP contiene los bytes 4D 53 44 4F 53 35 2E 30, que

    corresponden a los caracteres MSDOS5.0.

    BPB_BytsPerSec

    Offset (Byte): 11 Tamao (Bytes): 2

    Descripcin: Nmero de bytes por sector. Puede tomar alguno de los valores siguientes: 512, 1024,

    2048 o 4096.

    Si buscamos el mximo de compatibilidad con sistemas antiguos, debemos utilizar el valor 512.

    Existen muchos equipos viejos que manejan FAT de 512 bytes por sector por hard (hard wired) y

    no chequean este campo para determinar el nmero correcto de bytes de cada sector. Todos los

    sistemas operativos de Microsoft aceptan 1024, 2048, y 4096.

    Siguiendo con el anlisis del diskette, nos encontramos con los bytes 00 02.

    Como mencionamos antes, al estar en formato little endian, el byte mas significativo es el ultimo,

    por lo que debemos interpretarlo como 02 00 (hexadecimal), que corresponde al binario 0000 0010

    0000 0000 o al decimal 512. Nuestro diskette contiene 512 bytes por sector.

    BPB_SecPerClus

    Offset (Byte): 13 Tamao (Bytes) : 1

    Descripcin: Nmero de sectores por cluster. Este valor debe ser una potencia de 2 mayor a 0. Los

    valores permitidos son 1, 2, 4, 8, 16, 32, 64, y 128.

  • 7/28/2019 FAT Por Dentro

    5/22

    Hay que destacar que nunca se debe utilizar un valor que multiplicado porBPB_BytsPerSec de un

    resultado mayor a 32K (BPB_BytsPerSec * BPB_SecPerClus 32 * 1024).

    Es un error pensar que valores mayores son correctos. Si se eligen valores cuyo resultado sea superior

    a 32K muchos sistemas no funcionaran de forma correcta. Algunos sistemas permiten valores de 64K

    por cluster, pero no funcionan adecuadamente como volmenes FAT.

    En el ejemplo anterior, este byte es 01, por lo que nuestro diskette contiene 1 sector por cluster.

    BPB_BytsPerSec * BPB_SecPerClus 32 * 1024 nos da un valor de 2 * 1 * 1024 = 2048, que es

    valido, por ser menor que 32K (32768).

    BPB_RsvdSecCnt

    Offset (Byte): 14 Tamao (Bytes) : 2

    Descripcin: Nmero de sectores reservados en laZona Reservada del volumen, comenzado en elprimer sector del volumen.

    Este campo no puede ser 0. Para sistemas de FAT12 y FAT16 siempre debe ser 1. Para sistemas de

    archivos FAT32 generalmente este valor es 32.

    Nuevamente, tenemos que saber que muchos sistemas antiguos asumen un 1 en este campo y no

    leen su valor real. Todos los sistemas operativos de Microsoft aceptan cualquier valor distinto de 0

    para este campo.

    El diskette formateado con Windows XP contiene los bytes 01 00, al estar en formato little

    endian, el byte mas significativo es el ltimo, por lo que debemos interpretarlo como 00 01(hexadecimal), que corresponde al binario 0000 0000 0000 0001 o al decimal 1.

    BPB_NumFATs

    Offset (Byte): 16 Tamao (Bytes) : 1

    Descripcin: Nmero de FATs presentes en el volumen. Este campo debera tener un valor de 2,

    independientemente del tipo de FAT implementada. Sin embargo, cualquier valor igual o mayor a 1

    es valido.

    Como en casos anteriores, existen sistemas antiguos que podran fallar si encuentran un valor distinto

    de 2, o incluso algunos no leen su valor real. Todos los sistemas operativos de Microsoft aceptan

    cualquier valor distinto de 0 para este campo.

    En el diskette que estamos analizando vemos el byte 02, es decir, se tienen dos copias de la FAT.

    BPB_RootEntCnt

    Offset (Byte): 17 Tamao (Bytes) : 2

    Descripcin: En volmenes FAT12 y FAT16, estos dos bytes contienen en numero de entradas de 32

    bits que hay en el directorio raz del disco.

  • 7/28/2019 FAT Por Dentro

    6/22

    Ese valor debe ser tal, que al multiplicarlo por 32 resulte en un mltiplo de BPB_BytsPerSec. En el

    caso de volmenes con FAT32, este campo debe ser "00 00". Por motivos de compatibilidad, en

    sistemas FAT16, este valor debera ser 512.

    Nuestro ejemplo muestra "E0 00" en estos bytes, por lo que el valor (de nuevo little endian) "00

    E0", que en binario es 0000 0000 1110 000 y en decimal es 224. Al multiplicar 224 * 32 obtenemos

    7168, que es un mltiplo de BPB_BytsPerSec: 7168 / 512 = 14

    BPB_TotSec16

    Offset (Byte): 19 Tamao (Bytes) : 2

    Descripcin: Este campo contiene en 16 bits la cuenta total de sectores del volumen (FAT12 o

    FAT16). Estn incluidas en la cuenta la totalidad de sectores de todas las zonas. Este campo puede

    ser 0, en cuyo caso BPB_TotSec32 (ver mas adelante) no debe ser 0.

    En el diskette que estamos analizando vemos los bytes 40 0B, que debemos interpretar como "0B40" que en binario es 0000 1011 0100 0000 o 2880 en decimal. 2880 * 512 = 1474560 es el tamao

    total del diskette.

    BPB_Media

    Offset (Byte): 21 Tamao (Bytes) : 1

    Descripcin: Especifica el tipo de medio. "F8" es el valor que identifica a los medios no removibles.

    Los medios removibles en general se especifican como "F0". Una cuestin importante es que este

    valor debe tambin ser colocado en byte bajo de la entrada FAT [0] . La lista de valores posibles es la

    siguiente:

    Valor Significado

    0xF8 un lado, 80 pistas por lado, 9 sectores por pista

    0xF9 dos lados, 80 pistas por lado, 9 sectores por pista

    0xFA un lado, 80 pistas por lado, 8 sectores por pista

    0xFB dos lados, 80 pistas por lado, 8 sectores por pista

    0xFC un lado, 40 pistas por lado, 9 sectores por pista

    0xFD dos lados, 40 pistas por lado, 9 sectores por pista

    0xFE un lado, 40 pistas por lado, 8 sectores por pista

    0xFF dos lados, 40 pistas por lado, 8 sectores por pista

    Nuestro diskette tiene el valor "F0" en este byte, que es el valor genrico para un medio removible.

  • 7/28/2019 FAT Por Dentro

    7/22

    BPB_FATz16

    Offset (Byte): 22 Tamao (Bytes) : 2

    Descripcin: Tamao de la FAT12/FAT16. Es el numero de sectores ocupados por UNA copia de la

    FAT. Si se trata de un volumen FAT32, este campo debe ser 0, y el tamao de la FAT almacenado en

    BPB_FATz32.

    En el diskette que estamos analizando vemos los bytes 09 00, que debemos interpretar como "00

    09" que en binario es 0000 0000 0000 1001 o 9 en decimal. 9 * 512 = 4608 bytes ocupados cada

    copia de la FAT.

    BPB_SecPerTrk

    Offset (Byte): 24 Tamao (Bytes) : 2

    Descripcin: En aquellos soportes que tienen una "geometra" compuesta por pistas, cabezas y

    cilindros, tales como los discos duros, este valor especifica el numero de sectores por pista. Es

    utilizado por ejemplo por la int13 de MS-DOS.

    Nuestro diskette tiene los bytes 12 00, que debemos interpretar como "00 12" y que en binario es

    0000 0000 0001 0020 o 18 en decimal. Este diskette tiene 18 sectores de 512 bytes por pista. Si

    multiplicamos 18 * 512 * 80 (pistas) * 2 (cabezas), volvemos al tamao total de bytes del disco,

    1474560.

    BPB_NumHeadsOffset (Byte): 26 Tamao (Bytes) : 2

    Descripcin: Similar al campo anterior, pero indica el numero de cabezas. Nuestro diskette tiene los

    bytes 02 00, que debemos interpretar como "00 02" y que en binario es 0000 0000 0000 0010 o 2

    en decimal. Este diskette es ledo en una unidad que tiene dos cabezas.

    BPB_HiddSec

    Offset (Byte): 28 Tamao (Bytes) : 4

    Descripcin: Numero de sectores ocultos anteriores a la particin que contiene este volumen FAT.

    Generalmente, solo tiene importancia en sistemas que acceden al volumen a travs de la int13 de

    MS-DOS.

    Este valor debera ser 0 en un medio que no ha sido particionado. El valor exacto de este campo

    depende del sistema operativo utilizado.

    En el diskette que estamos analizando vemos los bytes 00 00 00 00, lo que indica que no existen

    particiones en el volumen.

  • 7/28/2019 FAT Por Dentro

    8/22

    Campo: BPB_TotSec32

    Offset (Byte): 32 Tamao (Bytes) : 4

    Descripcin: Este campo contiene en 32 bits la cuenta total de sectores del volumen (FAT32). Estn

    incluidas en la cuenta la totalidad de sectores de todas las zonas.

    Este campo puede ser 0, en cuyo caso BPB_TotSec16 (ver mas arriba) no debe ser 0. En volmenes

    FAT32 no debe ser 0. En volmenes FAT12/FAT16 este campo contiene el numero de sectores

    solamente cuando BPB_TotSec16 es 0 y el numero de sectores es mayor a 65535.

    En este diskette tenemos 00 00 00 00, debido a que es un volumen con FAT12/FAT16 con menos

    de 65536 sectores.

    Todos los campos vistos hasta aqu son comunes a las implementaciones de FAT12/FAT16/FAT32.

    Los que vienen a continuacin son propios de los sistemas FAT12/FAT16 o de los FAT32.

    Campos especficos de FAT12/FAT16

    Los siguientes campos solo se encuentran en aquellos volumenes con FAT12/FAT16:

    BS_DrvNum

    Offset (Byte): 36 Tamao (Bytes) : 1

    Descripcin: Numero de drive para la interrupcin 13. Este campo le indica a MS-DOS si se trata deun diskette ("00") o de un disco duro ("80").

    En nuestro ejemplo, al tratarse de un diskette tenemos 00.

    BS_Reserved1

    Offset (Byte): 37 Tamao (Bytes) : 1

    Descripcin: Reservado para su uso en Windows NT. Cualquier programa que de formato a un

    diskette deberia escribir un "00" en este lugar.

    En nuestro ejemplo encontramos 00 en ese byte.

    BS_BootSig

    Offset (Byte): 38 Tamao (Bytes) : 1

    Descripcin: Marca de boot extendido. Simplemente, indica si los siguientes tres campos estn

    presentes ("29") o no "00".

  • 7/28/2019 FAT Por Dentro

    9/22

    En este diskette tenemos 29,lo que indica que los tres siguientes campos (BS_VolID, BS_VolLab

    y BS_FilSysType) estn presentes.

    BS_VolID

    Offset (Byte): 39 Tamao (Bytes) : 4

    Descripcin: Estos cuatro bytes conforman el numero de serie del soporte. Junto con BS_VolLab

    sirven para identificar un soporte en particular. Se obtiene a partir de la fecha y la hora en que se

    realizo el formato del disco. (Ms adelante puede verse el algoritmo utilizado).

    El diskette bajo anlisis tiene los bytes "B9 90 1C 92".

    BS_VolLab

    Offset (Byte): 43 Tamao (Bytes) : 11

    Descripcin: Etiqueta electronica del volumen. Es el nombre que uno puede ver cuando accede al

    volumen desde Windows, por ejemplo. En aquellos soportes que no se ha escrito o cambiado el

    nombre, deberan figurar los bytes "4E 4F 20 4E 41 4D 45 20 20 20 20" ("NO NAME ") .

    El diskette que estamos estudiando tiene la cadena "NO NAME "

    BS_FilSysType

    Offset (Byte): 54 Tamao (Bytes) : 8

    Descripcin: Una cadena de texto, con 8 caracteres de longitud. Debe ser "FAT12 ", "FAT16 " o

    "FAT ". Muchos programadores suponen que esta etiqueta sirve para identificar el tipo de volumen,

    pero sin embargo no es as, ya que este campo no es parte del BPB.

    En este diskette tenemos la cadena "FAT12 "

    Aqu terminan los campos especficos para los volmenes con FAT12/FAT16.

    Campos especficos de FAT32

    Los siguientes 13 campos solo se encuentran en aquellos volumenes con FAT32. En nuestro diskette

    bajo estudio no parecen ninguno de estos campos, ya que posee una FAT12.

    BPB_FATSz32

    Offset (Byte): 36 Tamao (Bytes) : 4

    Descripcin: Tamao de la FAT32. Es el numero de sectores ocupados por UNA copia de la FAT. Si

    se trata de un volumen FAT12/FAT16, este campo debe ser 0, y el tamao de la FAT almacenado en

    BPB_FATz16.

  • 7/28/2019 FAT Por Dentro

    10/22

    BPB_ExtFlags

    Offset (Byte): 40 Tamao (Bytes) : 2

    Descripcin: Campo especifico de FAT32. Son 16 bits, cuyo significado es el siguiente:

    Bits 0..3:

    Numero (comenzando en 0) de FAT activa. Solo es vlido si esta desactivado el espejado.

    Bits 4..6:

    Reservado

    Bit 7:

    0: FATs en espejo 1: Solo una FAT esta activa (ver bits 0..3)

    Bits 8..15:

    Reservados.

    BPB_FSVer

    Offset (Byte): 42 Tamao (Bytes) : 2

    Descripcin: Versin de la FAT32 del volumen. El byte alto contiene la versin, y el bajo la revisin.Es til para evitar de que un sistema operativo antiguo manipule volmenes creados con versiones

    mas nuevas.

    BPB_RootClus

    Offset (Byte): 44 Tamao (Bytes) : 4

    Descripcin: Este es el numero de cluster del primer cluster del directorio raz. Normalmente (pero

    no necesariamente) es 2.

    BPB_FSInfo

    Offset (Byte): 48 Tamao (Bytes) : 2

    Descripcin: Numero de sector de la estructura FSINFO dentro del rea reservada del volumen.

    Generalmente es 1.

    BPB_BkBootSec

    Offset (Byte): 50 Tamao (Bytes) : 2

  • 7/28/2019 FAT Por Dentro

    11/22

    Descripcin: Si es distinto de cero, indica el numero de sector en el rea reservada del volumen en

    que se encuentra la copia del Boot Record. Generalmente es 6, y no se recomienda otro valor.

  • 7/28/2019 FAT Por Dentro

    12/22

    BPB_Reserved

    Offset (Byte): 52 Tamao (Bytes) : 12

    Descripcin: Reservados para futuras expansiones. Estos bytes deberan ser dejados en 0.

    BS_DrvNum

    Offset (Byte): 64 Tamao (Bytes) : 1

    Descripcin: Numero de drive para la interrupcin 13. Este campo le indica a MS-DOS si se trata de

    un diskette ("00") o de un disco duro ("80").

    BS_Reserved1

    Offset (Byte): 65 Tamao (Bytes) : 1

    Descripcin: Reservado para su uso en Windows NT. Cualquier programa que de formato a un

    diskette deberia escribir un "00" en este lugar.

    BS_BootSig

    Offset (Byte): 66 Tamao (Bytes) : 1

    Descripcin: Descripcin: Marca de boot extendido. Simplemente, indica si los siguientes tres

    campos estn presentes ("29") o no "00".

    BS_VolID

    Offset (Byte): 67 Tamao (Bytes) : 4

    Descripcin: Estos cuatro bytes conforman el numero de serie del soporte. Junto con BS_VolLab

    sirven para identificar un soporte en particular. Se obtiene a partir de la fecha y la hora en que se

    realizo el formato del disco. (Ms adelante intentar publicar aqu el algoritmo utilizado).

    BS_VolLab

    Offset (Byte): 71 Tamao (Bytes) : 11

    Descripcin: Etiqueta electrnica del volumen. Es el nombre que uno puede ver cuando accede al

    volumen desde Windows, por ejemplo. En aquellos soportes que no se ha escrito o cambiado el

    nombre, deberan figurar los bytes "4E 4F 20 4E 41 4D 45 20 20 20 20" ("NO NAME ") .

    BS_FilSysType

    Offset (Byte): 82 Tamao (Bytes) : 8

  • 7/28/2019 FAT Por Dentro

    13/22

    Descripcin: Una cadena de texto, con 8 caracteres de longitud. Debe ser "FAT32 ". Esta etiqueta no

    sirve para identificar el tipo de volumen, ya que este campo no es parte del BPB.

    Notas sobre los campos de la FAT

    Esta es una aclaracin muy importante sobre el sector cero de un volumen FAT: si consideramos toda

    la estructura del sector de la FAT como un vector, el elemento sector[510] debe ser igual a " 55" y el

    sector[511] igual a "AA". Mucha documentacin sobre este tema contiene el frecuente error de decir

    algo como "la firma "AA55" ocupa los ltimos dos bytes del sector de arranque". Esto solo es

    correcto si y solo si BPB_BytesPerSec = 512. Si BPB_BytesPerSec es mayor a 512, el offset

    (distancia desde el elemento cero) de esa firma no cambia.

    Revise sus presunciones sobre el valor almacenado en BPB_TotSec16 / BPB_TotSec32. Siempre

    suponga que el tamao en sectores de su disco o particin es DskSz. Si el campo BPB_Totsec (el

    que corresponda, BPB_Totsec16 o BPB_Totsec32, es decir, el que sea distinto de cero) es menor o

    igual a DskSz, no hay nada equivocado en la FAT. Efectivamente, no es raro tener un valor en

    BPB_Totsec16/32 ligeramente menor que DskSz. Eso es perfectamente valido.

    Esto significa que una parte del espacio del disco esta siendo desperdiciado. No quiere decir que el

    volumen FAT esta daado de alguna manera. Sin embargo, si BPB_Totsec16/32 es demasiado

    grande (porcentualmente hablando) para el medio (o la particin) puede redundar en una gran perdida

    de datos.

    Estructura de datos de la FAT

    La estructura de datos que analizaremos a continuacin es tan importante como la FAT en si misma.

    Un directorio no es mas que un archivo regular que tiene atributos especiales que indican que se

    trata de un directorio.

    La otra caracterstica especial de un directorio es que su contenido es una serie de "entradas de

    directorio" de 32 bytes (que analizaremos enseguida). En todo lo dems, es igual a un archivo. La

    FAT mapea la regin de datos de un disco mediante el numero de cluster. El primer cluster de datos

    es el 2. El primer sector del cluster 2 se debe calcular utilizando los campos apropiados del BPB de la

    siguiente manera:

    Primero, determinamos el numero de sectores ocupados por el directorio raz:

    RootDirSectors = ( ( BPB_RootEntCnt * 32 ) + ( BPB_BytsPerSec - 1 ) ) / BPB_BytsPerSec

    El resultado debe ser redondeado hacia arriba. Volviendo a la estructura del diskette bajo anlisis,

    tenemos que BPB_RootEntCnt = 224 y BPB_BytsPerSec = 512, por lo que

    RootDirSectors = ( ( 224 * 32 ) + ( 512 - 1 ) ) / 512

    RootDirSectors = ( ( 7168 ) + ( 511 ) ) / 512

    RootDirSectors = 7679 / 512

    RootDirSectors = 14,998046875 (redondeamos a 15)

  • 7/28/2019 FAT Por Dentro

    14/22

    Es decir, en nuestro diskette el directorio raz utiliza 15 sectores de 512 bytes cada uno, o sea, 7680

    bytes. En los volmenes con FAT32, BPB_RootEntCnt siempre es 0, por lo tanto RootDirSectors

    tambin es 0.

    El comienzo de la regin de datos, es decir, el primer sector del segundo cluster, se calcula de la

    siguiente manera si se trata de un volumen FAT12/FAT16:

    FirstDataSector = BPB_ResvdSecCnt + ( BPB_NumFATs * BPB_FATs16 ) + RootDirSectors

    Con los datos del diskette de ejemplo, RootDirSectors = 15 , BPB_ResvdSecCnt = 1,

    BPB_NumFATs = 2 y BPB_FATs16 = 9, por lo que la formula quedara:

    FirstDataSector = 1 + ( 2 * 9 ) + 15

    FirstDataSector = 1 + 18 + 15

    FirstDataSector = 34

    Si se trata de un volumen con FAT32, la formula a utilizar para encontrar el comienzo de la regin de

    datos es:

    FirstDataSector = BPB_ResvdSecCnt + ( BPB_NumFATs * BPB_FATs32 )

    (Recordemos que en FAT32, RootDirSectors = 0). Tengamos en cuenta que todas estas direcciones

    que estamos calculando son referidas al primer sector del volumen que contiene el BPB (que seria el

    "0"). En aquellos volmenes que tengan particiones estas direcciones pueden no coincidir con sector

    0 del disco.

    Determinacin del tipo de FAT

    Existe todo un folclore sobre como debe determinarse el tipo de fat de un volumen. La realidad es

    que existe una sola forma de determinar el tipo de FAT, y se basa nicamente en el numero de

    clusters existentes en el volumen, y nada mas.

    Lea atentamente los prrafos siguientes. Cuando decimos "numero de clusters" nos referimos

    exactamente a eso y no al "numero de clusters mximo que es valido", ya que difieren, debido a que

    el primer cluster de datos es el 2 y no el 0 o el 1.

    Vamos a comenzar viendo la manera exacta de calcular el numero de clusters. Nos basaremos en el

    contenido del BPB. Primero, determinamos el numero de sectores ocupados por el directorio raz,

    como hicimos antes:

    RootDirSectors = ( ( BPB_RootEntCnt * 32 ) + ( BPB_BytsPerSec - 1 ) ) / BPB_BytsPerSec

    El segundo paso consiste en calcular, utilizando RootDirSectors, el numero de sectores en la regin

    de datos del volumen. Tenemos dos casos, segn se trate o no de una FAT32:

  • 7/28/2019 FAT Por Dentro

    15/22

    FAT12/16:

    DataSec = BPB_TotSec16 - (BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16 ) +

    RootDisrSectors)

    FAT32:

    DataSec = BPB_TotSec32 - (BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz32) )

    (Recordemos que en FAT32, RootDirSectors = 0)

    En nuestro diskette, DataSec = 2880 - ( 1 + ( 2 * 9 ) + 15) = 2880 - (1 +18 + 15) = 2880 - 34 = 2846

    Ahora determinamos el numero de clusters:

    CountOfClusters = DataSec / BPB_SecPerClus

    Este resultado, de no ser entero, debe redondearse hacia abajo.

    En nuestro diskette, CountOfClusters = 2846 / 1 = 2846

    Con estos datos, ya somos capaces de determinar el tipo de FAT del volumen. Importante: los

    nmeros mencionados son CORRECTOS, es decir, donde dice 4085 efectivamente se trata de ese

    numero. Lo mismo que los signos: si dice "

  • 7/28/2019 FAT Por Dentro

    16/22

    FAT16:

    ThisFATSecNum = BPB_ResvdSecCnt + ( ( N * 2 ) / BPB_BytsPerSec ) ThisFATEntOffset =

    RESTO ( ( N * 2 ) / BPBBytsPerSec )

    Donde ThisFATSecNum es el numero de sector de la FAT que contiene la entrada para el cluster"N" en la primer FAT. Si se desea calcular el numero de sector de la segunda FAT, se debe sumar a

    este valorBPB_FATz16. Para la tercer copia de la FAT sumamos 2 * BPB_FATz16, y as

    sucesivamente.

    FAT32:

    ThisFATSecNum = BPB_ResvdSecCnt + ( ( N * 4 ) / BPB_BytsPerSec ) ThisFATEntOffset =

    RESTO ( ( N * 4 ) / BPBBytsPerSec )

    Donde ThisFATSecNum es el numero de sector de la FAT que contiene la entrada para el cluster

    "N" en la primer FAT. Si se desea calcular el numero de sector de la segunda FAT, se debe sumar aeste valorBPB_FATz32. Para la tercer copia de la FAT sumamos 2 * BPB_FATz32 y as

    sucesivamente.

    FAT12:

    Este calculo, como dijimos, es mas complicado debido a que los 12 bits de la direccin son un byte y

    medio, lo que dificulta las cuentas.

    FATOffset = N + (N/2) (redondear hacia abajo)

    ThisFATSecNum = BPB_ResvdSecCnt + ( FATOffset / BPB_BytsPerSec )

    ThisFATEntOffset = RESTO ( FATOffset / BPBBytsPerSec )

    Estructura de directorios en la FAT

    Un directorio es simplemente un archivo compuesto por una lista de estructuras de 32 bits. El nico

    directorio "especial" es el directorio raz.

    En los volmenes FAT12 y FAT16, el directorio raz se encuentra localizado inmediatamente

    despus de la ultima copia de la FAT, y su tamao en sectores se puede calcular a partir deBPB_RootEntCnt, como ya vimos. Asumiremos nombres cortos de archivo, nicamente, y mas

    adelante veremos como se almacenan los nombres largos.

    En los volmenes FAT12 y FAT16, el primer sector del directorio raz se encuentra en

    FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16 )

    En nuestro diskette, FirstRootDirSecNum = 1 + ( 2 * 9 ) = 19

    En el caso de las FAT32, el directorio raz puede tener un tamao variable, y ser una cadena declusters, como cualquier otro directorio. El primer cluster del directorio raz de una FAT32 esta

    almacenado, por supuesto, en BPB_RootClus.

  • 7/28/2019 FAT Por Dentro

    17/22

    A diferencia de los dems directorios, el directorio raz no tiene datos en los campos

    correspondientes a la fecha, hora y nombre (salvo el "/"), y no contiene los archivos "." ni "..", que

    generalmente estn en las dos primeras entradas en cualquier directorio. Adems, es el nico archivo

    en que es valido tener activado el bit "ATTR_VOLUME_ID", como veremos mas abajo.

    Esta es la estructura de directorios de una FAT32, explicada campo por campo:

    DIR_Name

    Offset (Bytes): 0 Tamao (Bytes): 11

    Nombre corto del directorio. Se divide en dos partes, una de 8 caracteres para el nombre, y otra de 3

    para la extensin. Ambas deben rellenarse con espacios al final. DIR_Name[0] no pueden ser un

    espacio ("20" o 32 en decimal). El "." entre el nombre y la extensin es implcito, y no esta

    almacenado en la estructura. No se permiten caracteres en minsculas en DIR_Name debido a que

    pueden ser especficos de algn idioma.

    Si DIR_Name[0] = "E5", esta entrada esta libre, es decir, no hay archivo o directorio.

    Si DIR_Name[0] = "00", esta entrada esta libre (igual que si fuera "E5") y no hay entradas

    despus de esta. Por lo tanto, si estamos recorriendo la estructura del directorio y encontramos

    esta entrada, no tiene sentido seguir despus de este punto.

    Si DIR_Name[0] = "05", el nombre de este archivo es "E5". Esto es as por que "E5" es un

    carcter valido en nombres de archivos escritos con caracteres KANJI, y de esta manera se

    evita que sistemas basados en ese juego de caracteres interpreten la entrada del directorio

    como vaca.

    Los caracteres siguientes son considerados ilegales dentro de DIR_Name:

    Valores menores a "20", con la excepcin del "05" explicada arriba.

    "22", "2A", "2B","2C","2E","2F", "3A", "3B", "3C", "3D", "3E", "3F", "5B", "5C", "5D" y

    "7C".

    Por ultimo, veamos con un ejemplo como se almacena un nombre dentro de DIR_Name:

    Nombre: "pepe.ext" Almacenado como: "PEPE EXT" Bytes: "50 45 50 45 20 20 20 20 45 58 54"

    DIR_Attr

    Offset (Bytes): 11 Tamao (Bytes): 1

    Atributos especficos del archivo. Los dos bites altos de este byte se deben dejar en 0 y nunca

    modificarse.

    ATTR_READ_ONLY ("01"): Significa que el archivo es de solo lectura.

    ATTR_HIDDEN ("02"): No debe mostrarse este archivo en un listado normal del contenido

    de ese directorio.

  • 7/28/2019 FAT Por Dentro

    18/22

    ATTR_SYSTEM ("04"): Se trata de un archivo perteneciente al sistema operativo.

    ATTR_VOLUME_ID ("08"): Debera haber solo un archivo en el volumen con este atributo

    en 1, y es el directorio raz. DIR_FstClusHI y DIR_FstClusLO (ver mas abajo) deben ser cero

    para la etiqueta del volumen.

    ATTR_DIRECTORY ("10"): Indica que se trata de un directorio y no de un archivo.

    ATTR_ARCHIVE ("20"): Atributo pensado para las copias de seguridad. Debe ponerse a 1

    cuando el software manejador de la FAT crea, renombra o escribe en un archivo. Las

    utilidades de backup pueden basarse en este bit para realizar sus tareas de respaldo, y ponerlo

    en 0 para indicar que ya fueron resguardados.

    ATTR_LONG_NAME: ATTR_READ_ONLY , ATTR_HIDDEN , ATTR_SYSTEM y

    ATTR_VOLUME_ID en 1. Esta combinacin de bits indican que el "archivo" es en realidad

    parte del nombre largo de otro archivo. Volveremos sobre este tema mas adelante.

    DIR_NTRes

    Offset (Bytes): 12 Tamao (Bytes): 1

    Reservado para Windows NT. Debe ser dejado en cero.

    DIR_CrtTimeTenth

    Offset (Bytes): 13 Tamao (Bytes): 1

    Milisegundos de la hora en que se creo el archivo. Este campo en realidad contiene las dcimas de

    segundos. La granularidad de los segundos almacenados en DIR_CrtTime2 es de dos segundos, por

    lo que este campo puede contener valores entre 0-199 .

    DIR_CrtTime

    Offset (Bytes): 14 Tamao (Bytes): 2

    Hora a la que se creo el archivo.

    DIR_CrtDate

    Offset (Bytes): 16 Tamao (Bytes): 2

    Fecha en la que se creo el archivo.

    DIR_LstAcctDate

    Offset (Bytes): 18 Tamao (Bytes): 2

  • 7/28/2019 FAT Por Dentro

    19/22

    Fecha en la que se accedi por ultima vez el archivo, ya sea para escribir en el o para leerlo. En el

    caso de una escritura, este valor debe ser el mismo que el almacenado en DIR_WrtDate. No se

    guarda la hora del ultimo acceso.

    DIR_FstClusHI

    Offset (Bytes): 20 Tamao (Bytes): 2

    Parte alta de la palabra de 32 bits que contiene el primer cluster del archivo. Siempre es cero en las

    FAT12 o FAT16.

    DIR_WrtTime

    Offset (Bytes): 22 Tamao (Bytes): 2

    Hora de la ultima escritura. La creacin del archivo se considera una escritura.

    DIR_WrtDate

    Offset (Bytes): 24 Tamao (Bytes): 2

    Fecha de la ultima escritura. La creacin del archivo se considera una escritura.

    DIR_FstClusLO

    Offset (Bytes): 26 Tamao (Bytes): 2

    Parte baja de la palabra de 32 bits que contiene el primer cluster del archivo.

    DIR_FileSize

    Offset (Bytes): 28 Tamao (Bytes): 4

    Tamao del archivo, en bytes.

    Creando un directorioCuando se crea un directorio (un archivo con ATTR_DIRECTORY en 1), se debe poner

    DIR_FileSize en cero. El tamao de los directorios se calcula siguiendo su cadena de clusters hasta

    la marca EOC.

    Un cluster es asignado al directorio (a menos que se trate de una FAT12 o FAT16), y se deben

    apuntarDIR_FstClusLO y DIR_FstClusHI al numero del cluster, y poner EOC en la entrada

    correspondiente de la FAT. A continuacin, se ponen todos los bytes de ese cluster en cero. Si se

    trata del directorio raz, no se crean las entradas "." y "..".

  • 7/28/2019 FAT Por Dentro

    20/22

    En caso de no ser el directorio raz hay que crear dos entradas especiales en las primeras dos entradas

    de 32 bits del directorio, con DIR_Name = ". " y DIR_Name = ".. ". DIR_FileSize es cero en

    ambas entradas. Los campos de fecha y hora son iguales a los del directorio que acabamos de crear.

    Para terminar, debemos poner en la entrada "." el campo DIR_FstClusLO y DIR_FstClusHI

    valores iguales a los del directorio que acabamos de crear. Y en ".." ponemos en los campos

    DIR_FstClusLO y DIR_FstClusHI el valor del directorio "padre". Si se trata del directorio raz,ponemos cero.

    Resumiendo: La entrada "." es un directorio que se apunta a si misma, y la entrada ".." es un

    directorio que apunta al directorio padre (cero si su "padre" es el directorio raz)

    Formatos de fecha y hora

    Muchas implementaciones solo soportan los campos DIR_WrtTime y DIR_WrtDate. Por esta

    razn, los campos DIR_CrtTimeTenth, DIR_CrtTime, DIR_CrtDate y DIR_LstAcctDate se han

    transformado en campos opcionales. DIR_WrtTime y DIR_WrtDate deben ser empleados siempre.Todos los campos que no se empleen deben ser completados con "00" al momento de crear el

    archivo, y ser ignorados en las dems operaciones.

    Los campos que contienen fechas utilizan 16 bits (dos bytes) para codificar el da, mes y ao de la

    fecha en cuestin, pero referidas a 1980. Es decir, al ao expresado deber sumrsele 1980 para

    obtener la fecha correcta. De los 16 bits utilizados, llamaremos bit0 al menos significativo, y bit 16 al

    mas significativo. La fecha se guarda de la siguiente manera:

    Bits 0-4: Da del mes, valores en el rango 1..31

    Bits 5-8: Nmero de mes, valores en el rango 1..12

    Bits 9-15: Aos transcurridos desde 1980, valores en el rango 0..127

    Por ejemplo, la fecha "10 de febrero de 2007" se codificara como:

    01010 para el da del mes (10)

    0010 para el numero de mes (2)

    0011011 para el ao (27, por que 1980 + 27 = 2007)

    Los 16 bits serian 0011 0110 0100 0101, en hexadecimal "36 45". Como se colocan en notacin

    "Little Endian", en el soporte deben guardarse invertidos, es decir "45 36".

    El formato de el tiempo es similar. Tambin se utilizan 16 bits, donde llamaremos bit0 al menos

    significativo, y bit 16 al mas significativo. La fecha se guarda de la siguiente manera:

    Bits 0-4: Numero de 2 * segundos, en el rango 0..29 (0..58 segundos).

    Bits 5-10: Numero de minutos, en el rango 0..59.

    Bits 11-15: Numero de horas, en el rango 0..23.

    El rango valido de tiempo va desde 00:00:00 a 23:59:58.

    Por ejemplo, la hora "15:25:38" se codificara como:

    10011 para los segundos (19, por que 19 * 2 = 38).

  • 7/28/2019 FAT Por Dentro

    21/22

    011001 para los minutos (25).

    01111 para las horas (15).

    Los 16 bits serian 0111 1011 0011 0011, en hexadecimal "7B 33". Como se colocan en notacin

    "Little Endian", en el soporte deben guardarse invertidos, es decir "33 7B".

    Anlisis de una tarjeta Flash de 1Gb con FAT32 (WinXP)

    Haciendo uso de todo lo expuesto anteriormente, vamos a analizar el contenido de una tarjeta Flash

    SD previamente formateada con WinXP, FAT32. El contenido de la tarjeta es:

    En el directorio raz, una carpeta llamada "directorio1" y un archivo de texto llamado

    "archivo1.txt" con el texto "HOLA MUNDO" dentro.

    En la carpeta "directorio1" hay otro archivo de texto llamado "archivo2.txt" con el contenido

    "SEGUNDO ARCHIVO" en el primer rengln, y "DE TEXTO" en el segundo.

    Esta es la imagen de los primeros 512 bytes de la tarjeta:

    Analizando esta imagen podemos deducir:

    BS_jmpBoot: EB 58 90. BS_OEMName: "4D 53 44 4F 53 35 2E 30, que corresponden a los caracteres MSDOS5.0

  • 7/28/2019 FAT Por Dentro

    22/22

    BPB_BytsPerSec: "00 02", o sea, 512 bytes por sector.

    BPB_SecPerClus: "08", o sea, 8 sectores por cluster. 512 * 8 = 4096 bytes por cluster.

    BPB_RsvdSecCnt: "26 00", es decir, 38 sectores reservados. (26 hexadecimal es 38 en

    decimal)

    BPB_NumFATs: "02", es decir, dos copias de la FAT.

    BPB_RootEntCnt: "00 00", por tratarse de una FAT 32.

    BPB_TotSec16: "00 00", por tratarse de una FAT 32. BPB_Media: "F8", identificado como un medio NO REMOVIBLE. (?)

    BPB_FATz16: "00 00", por tratarse de una(26 hexadecimal es 38 decimal) FAT 32.

    BPB_SecPerTrk: "3F 00", o sea 63 sectores por pista (3F hexadecimal es 63 en decimal)

    BPB_NumHeads: "20 00", o 20 cabezas por pista.

    BPB_HiddSec: "F3 00 00 00", o sea 243 sectores ocultos (F3 hexadecimal es 243 en decimal)

    BPB_TotSec32: "0D B3 1E 00", o sea 2.011.917 de sectores. ("little endian" de 32 bits, "00

    1E B3 0D" es 2.011.917 en decimal).

    BPB_FATSz32: "A9 07 00 00", 1961 sectores ocupados por UNA copia de la FAT. ("little

    endian" de 32 bits, "00 00 07 A9" es 1961 en decimal).

    BPB_ExtFlags: "00 00".

    BPB_FSVer: "00 00". Versin de FAT32 0.0.

    BPB_RootClus: "02 00 00 00", el numero de cluster del primer cluster del directorio raz es 2.

    BPB_FSInfo: "01 00", el numero de sector de la estructura FSINFO dentro del rea reservada

    del volumen es 1.

    BPB_BkBootSec: "06 00", el sector en el rea reservada del volumen en que se encuentra la

    copia del Boot Record es el 6.

    BPB_Reserved: "00 00 00 00 00 00 00 00 00 00 00 00"

    BS_DrvNum: "00" . Indica a MS-DOS que se trata de un diskette.

    BS_Reserved1: "00"

    BS_BootSig: "29". Los siguientes tres campos estn presentes.

    BS_VolID: "EC D2 C0 78". Es el numero de serie del volumen. BS_VolLab: "4E 4F 20 4E 41 4D 45 20 20 20 20" ("NO NAME ")

    BS_FilSysType: "46 41 54 33 32 20 20 20", o sea, "FAT32 "

    Ahora, veamos los datos que se pueden calcular con esta informacin:

    RootDirSectors: Es el nmero de sectores ocupados por el directorio raz: siempre es 0 para

    FAT32.

    FirstDataSector = BPB_ResvdSecCnt + ( BPB_NumFATs * BPB_FATs32 ) = 38 + ( 2 *

    1961 ) = 3960

    DataSec = BPB_TotSec32 - (BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz32) ) =

    2011917 - ( 38 + ( 2 * 1961 = 2.007.957

    CountOfClusters = DataSec / BPB_SecPerClus = 2007957 / 8 = 250994. Si CountOfClusters

    > 65524, el volumen es FAT32, lo cual es correcto.