Autor Tema: GUIA: FAT al desnudo  (Leído 7335 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
GUIA: FAT al desnudo
« en: 27 de Enero de 2007, 08:48:24 »
Hola amigos!
Como parte de un proyecto que tengo en mente, me he tenido que poner a leer sobre el sistema de archivos FAT, que venimos utilizando desde principio de los 1980, de la mano de las diferentes versiones de los sistemas operativos de Microsoft (MS-DOS 1.x en adelante). A pesar de su antiguedad, no han perdido vigencia, y hoy se utiliza, por ejemplo, en las tarjetas de memoria SD.
Mi idea es exponer con ejemplos, y en forma clara, la extructura interna de los distintos tipos de FAT. He comenzado "traduciendo" un documento de Microsoft, pero voy a ir "vistiendolo" con mas datos, ya que ese documento por si solo se queda algo corto en muchas cosas.
Como siempre, el problema son los tiempos, y si espero a tener todo armado, no lo publico mas. Es por eso que voy a ir posteando las partes que haya ido desentrañando.

Una ultima aclaracion: el objetivo de este hilo no es llegar a un dispositivo practico, sino proveer, en forma clara y en español, los elementos necesarios para poder entender este sistema de archivos.

Tambien he abierto el hilo GUIA: FAT al desnudo (COMENTARIOS), donde puedes comentar, preguntar y criticar esta guia, de manera que este hilo quede mas ordenado y facil de leer.

Aquellos impacientes que quieran ver un poco mas alla de este hilo, en este link pueden encontrar la ultima version actualizada de este hilo.

Saludos.
« Última modificación: 27 de Enero de 2007, 11:47:14 por aitopes »
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
Re: GUIA: FAT al desnudo
« Respuesta #1 en: 27 de Enero de 2007, 09:00:55 »
Introducción
Este documento se basa en el documento titulado FAT: General Overview of On-Disk Format, un “withe paper” de la empresa Microsoft. El autor del presente documento no garantiza la fidelidad de lo expuesto aquí, aunque se ha tratado de ser lo mas riguroso posible.

FAT es el acrónimo de File Allocation Table (Tabla de  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 tamaño. Con el paso del tiempo, se fueron introduciendo cambios en la especificación para soportar medios de almacenamiento cada vez mayores. En la actualidad coexisten tres sistemas de archivos tipo FAT: FAT12, FAT16 y FAT32. Las diferencias básicas entre esos subtipos, y la razón de sus nombres, es el tamaño, 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 FAT. 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 indian”. Si observamos una entrada en una FAT de 32 bits, almacenada como cuatro bytes (de 8 bits cada uno), siendo el primero el byte 0 y el ultimo el byte 3, los bits se encuentran en el siguiente orden (donde el bit menos significativo es el 00):


Código: [Seleccionar]
byte[3] 3 3 2 2 2 2 2 2
1 0 9 8 7 6 5 4

byte[2] 2 2 2 2 1 1 1 1
3 2 1 0 9 8 7 6

byte[1] 1 1 1 1 1 1 0 0
5 4 3 2 1 0 9 8

byte[0] 0 0 0 0 0 0 0 0
                7 6 5 4 3 2 1 0


Esto es particularmente importante si su maquina es “big endian”, dado que debera realizar una “traduccion” entre ambos formatos antes de mover datos desde y hacia el disco.
Un disco con sistema de archivos FAT esta dividido en cuatro zonas basicas, 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. 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 confusión cuando hablamos del sistema de archivos FAT. En las versiones 1.x del MS-DOS no existía un BPB en el sector de arranque. Es estas primeras versiones de FAT solamente había 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 consistía 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 método 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 confusión al intentar determinar el tipo de FAT: ¿Cuál es la función 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 limitación proviene de que el campo que alberga el valor correspondiente al numero total de sectores tiene 16 bits de longitud (2^16 = 65536). Esta limitación 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 versión OEM Service Release 2 (OSR2) de Microsoft Windows 95, donde se introdujo la FAT32. FAT16 estaba limitada por el tamaño máximo de la propia FAT y por el tamaño máximo de cluster, que no permitían discos de más de 2 GB si se empleaban sectores de 512 bytes. FAT32 supero esa limitación, y los discos de más de 2 GB podían 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 máxima 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 descripción del post siguiente, todos los campos cuyos nombres comienzan con BPB_ son parte del BPB. Aquellos cuyo nombre comienza con BS_ son parte del sector de arranque (Boot Sector), 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 diskete de 3.5 formateado con Windows XP.
« Última modificación: 27 de Enero de 2007, 09:43:01 por aitopes »
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
Re: GUIA: FAT al desnudo
« Respuesta #2 en: 27 de Enero de 2007, 09:32:12 »
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:




Campo: BS_jmpBoot
Offset (Byte): 0
Tamaño (Bytes) : 3
Descripcion: Instrucción de salto al código 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 instrucción de salto incondicional Intel x86  (jump) que apunta al inicio del código de arranque del sistema operativo. Generalmente, este código ocupa el resto del espacio siguiente al BPB en el sector de arranque, posiblemente otros sectores. 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.


Campo: BS_OEMName
Offset (Byte): 3
Tamaño (Bytes) : 8
Descripcion: Generalmente se trata de la cadena “MSWIN4.1”. Existe todo un folclore acerca de la función de este campo, pero solo se trata de una cadena de texto. Los sistemas operativos de Microsoft no prestan ninguna atención 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 algún driver en particular no reconozca la unidad. Generalmente se toma como una indicación de que la unidad esta formateada.
El diskette formatedo con Windows XP contiene los bytes “4D 53 44 4F 53 35 2E 30”, que corresponden a los carcteres “MSDOS5.0”.


Campo: BPB_BytsPerSec
Offset (Byte): 11
Tamaño (Bytes) : 2
Descripcion: Número de bytes por sector. Puede tomar alguno de los valores siguientes: 512, 1024, 2048 o 4096. Si buscamos el máximo 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 número correcto de bytes de cada sector.  Todos los sistemas operativos de Microsoft aceptan 1024, 2048, y 4096.
Siguiendo con el analisis del diskette, nos encontramos con los bytes “00 02”. Como mencionamos antes, al estar en formato “little indian”, el byte mas significativo es el ultimo, por lo que debemos interpretarlo como “02 00” (hexadecima), que corresponde al binario 0000 0010 0000 0000 o al decimal 512. Nuestro diskette contiene 512 bytes por sector.


Campo: BPB_SecPerClus
Offset (Byte): 13
Tamaño (Bytes) : 1
Descripcion: Numero 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. Hay que destacar que nunca se debe utilizar un valor que multiplicado por BPB_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 muchis sistemas no funcionaran de forma correcta. Algunos sistemas permiten valores de 64K por cluster, pero no funcionan adecuadamente como volúmenes FAT.
En el ejemplo anterior, este byte es “01”, por lo que nuestro diskete 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).

« Última modificación: 29 de Enero de 2007, 14:37:51 por aitopes »
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
Re: GUIA: FAT al desnudo
« Respuesta #3 en: 29 de Enero de 2007, 14:35:15 »
Continuamos analizando los campos del BPB.....

Campo: BPB_RsvdSecCnt
Offset (Byte): 14
Tamaño (Bytes) : 2
Descripción: Número de sectores reservados en la Zona Reservada del volumen, comenzado en el primer 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.

Campo: BPB_NumFATs
Offset (Byte): 16
Tamaño (Bytes) : 1
Descripción: Número de FATs presentes en el volumen. Este campo debería 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 podrían 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.

Campo: BPB_RootEntCnt
Offset (Byte): 17
Tamaño (Bytes) : 2
Descripción: En volúmenes FAT12 y FAT16, estos dos bytes contienen en numero de entradas de 32 bits que hay en el directorio raíz del disco. Ese valor debe ser tal, que al multiplicarlo por 32 resulte en un múltiplo de BPB_BytsPerSec. En el caso de volúmenes con FAT32, este campo debe ser "00 00". Por motivos de compatibilidad, en sistemas FAT16, este valor debería 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 múltiplo de BPB_BytsPerSec: 7168 / 512 = 14

Campo: BPB_TotSec16
Offset (Byte): 19
Tamaño (Bytes) : 2
Descripción: Este campo contiene en 16 bits la cuenta total de sectores del volumen (FAT12 o FAT16). Están 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 "0B 40" que en binario es  0000 1011 0100 0000 o 2880 en decimal. 2880 * 512 = 1474560 es el tamaño total del diskette.

Campo: BPB_Media
Offset (Byte): 21
Tamaño (Bytes) : 1
Descripción: 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 cuestión importante es que este valor debe también ser colocado en byte bajo de la entrada FAT
  • . La lista de valores posibles es la siguiente:

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 genérico para un medio removible.


Campo: BPB_FATz16
Offset (Byte): 22
Tamaño (Bytes) : 2
Descripción: Tamaño 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 tamaño de la FAT almacenado en BPB_FATz32.
En el diskette que estamos analizando vemos los bytes “09 00”, que debemos interpretar como "00 49" que en binario es  0000 0000 0000 1001 o 9 en decimal. 9 * 512 = 4608 bytes ocupados cada copia de la FAT.


Campo: BPB_SecPerTrk
Offset (Byte): 24
Tamaño (Bytes) : 2
Descripción: En aquellos soportes que tienen una "geometría" 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 tamaño total de bytes del disco, 1474560.

Campo: BPB_NumHeads
Offset (Byte): 26
Tamaño (Bytes) : 2
Descripción: 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 leído en una unidad que tiene dos cabezas.

Campo: BPB_HiddSec
Offset (Byte): 28
Tamaño (Bytes) : 4
Descripción: Numero de sectores ocultos anteriores a la partición que contiene este volumen FAT. Generalmente, solo tiene importancia en sistemas que acceden al volumen a través de la int13 de MS-DOS. Este valor debería 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.

Campo: BPB_TotSec32
Offset (Byte): 32
Tamaño (Bytes) : 4
Descripción: Este campo contiene en 32 bits la cuenta total de sectores del volumen (FAT32). Están 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 volúmenes FAT32 no debe ser 0. En volúmenes 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 continuación son propios de los sistemas FAT12/FAT16 o de los FAT32.


> Campos específicos de FAT12/FAT16:
Los siguientes campos solo se encuentran en aquellos volumenes con FAT12/FAT16:

Campo: BS_DrvNum
Offset (Byte): 36
Tamaño (Bytes) : 1
Descripción: Numero de drive para la interrupción 13. Este campo le indica a MS-DOS si se trata de un diskette ("00") o de un disco duro ("80").
En nuestro ejemplo, al tratarse de un diskette tenemos “00”.

Campo: BS_Reserved1
Offset (Byte): 37
Tamaño (Bytes) : 1
Descripción: 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.

Campo: BS_BootSig
Offset (Byte): 38
Tamaño (Bytes) : 1
Descripción: Marca de boot extendido. Simplemente, indica si los siguientes tres campos están presentes ("29") o no "00".
En este diskette tenemos “29”,lo que indica que los tres siguientes campos (BS_VolID, BS_VolLab y BS_FilSysType) están presentes.

Campo: BS_VolID
Offset (Byte): 39
Tamaño (Bytes) : 4
Descripción: 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. (Más adelante intentar publicar aquí el algoritmo utilizado).
El diskette bajo análisis tiene los bytes "B9 90 1C 92".

Campo: BS_VolLab
Offset (Byte): 43
Tamaño (Bytes) : 11
Descripción: 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, deberian 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    "

Campo: BS_FilSysType
Offset (Byte): 54
Tamaño (Bytes) : 8
Descripción: 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.
Etiqueta electrónica 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, deberían figurar los bytes "4E 4F 20 4E 41 4D 45 20 20 20 20" ("NO NAME    ") .
En este diskette tenemos la cadena "FAT12   "
Aquí terminan los campos específicos para los volúmenes con FAT12/FAT16.


(Continuara en unos días. Mientras, en www.ucontrol.com.ar puedes ir viendo los avances antes de que los postee con este formato.)


Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
Re: GUIA: FAT al desnudo
« Respuesta #4 en: 04 de Febrero de 2007, 13:43:52 »
> Notas sobre los campos de la FAT:
Esta es una aclaración 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 documentación 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 tamaño en sectores de su disco o partición 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 dañado de alguna manera. Sin embargo, si BPB_Totsec16/32 es demasiado grande (porcentualmente hablando) para el medio (o la partición) puede redundar en una gran perdida de datos.



> Estructura de datos de la FAT:

La estructura de datos que analizaremos a continuación 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 característica especial de un directorio es que su contenido es una serie de "entradas de directorio" de 32 bytes (que analizaremos enseguida). En todo lo demás, es igual a un archivo. La FAT mapea la región 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 raíz:

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

El resultado debe ser redondeado hacia arriba. Volviendo a la estructura del diskette bajo análisis, 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)

Es decir, en nuestro diskette el directorio raíz utilizar 15 sectores de 512 bytes cada uno, o sea, 7680 bytes. En los volúmenes con FAT32, BPB_RootEntCnt siempre es 0, por lo tanto RootDirSectors  también es 0.

El comienzo de la región 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 quedaría:

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 región 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 volúmenes que tengan particiones estas direcciones pueden no coincidir con sector 0 del disco.

> Determinación 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 párrafos siguientes. Cuando decimos "numero de clusters" nos referimos exactamente a eso y no al "numero de clusters máximo 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 raíz, 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 región de datos del volumen. Tenemos dos casos, según se trate o no de una FAT32:

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 números mencionados son CORRECTOS, es decir, donde dice 4085 efectivamente se trata de ese numero. Lo mismo que los signos: si dice "<", utilizar "<=" es incorrecto.

Si CountOfClusters < 4085, el volumen es FAT12.
Si CountOfClusters >4084 y CountOfClusters < 65525, el volumen es FAT16.
Si CountOfClusters > 65524, el volumen es FAT32.


En nuestro diskette, CountOfClusters  = 2846, por lo que se trata de una FAT12.

Esta es la única manera correcta de determinar el tipo de FAT. No existen cosas como FAT12 con mas de 4084 clusters, ni FAT32 con menos de 65.525 clusters. Es posible escribir en el BPB valores que arrojen esos resultados, pero esos volúmenes violaran las especificaciones del formato, por lo que ningún sistema operativo Microsoft los interpretara correctamente.

Es una muy buena idea mantener el numero de clusters de los volumenes a los que demos formato "alejados" de las fronteras entre uno y otro tipo de FATs. Existe mucho software que esta escrito de manera erronea, y erra por 1, 2, 8, 10 o 16 al hacer el calculo del tipo de FAT. Mantener el numero de clusters a una "distancia" mayor a 16 unidades de los limites (4.085 o 65.525) es una buena idea para que nuestro volumen sea reconocido correctamente en la mayor cantidad de sistemas.

En breve, mas informacion sobre este tema. Recuerden que el articulo esta en www.ucontrol.com.ar con un formato un poco menos arido para su lectura.
Saludos!

Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
GUIA: FAT al desnudo
« Respuesta #5 en: 06 de Febrero de 2007, 11:50:00 »
> Análisis 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. Este es el volcado correspondiente:



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”

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". Versión de FAT32 0.0.

BPB_RootClus: "02 00 00 00", el numero de cluster del primer cluster del directorio raíz 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 están 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 información:

RootDirSectors: Es el numero de sectores ocupados por el directorio raíz: 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.


En la proxima entrega, por fin: carpetas y archivos!

Saludos!
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert

Desconectado aitopes

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5102
    • uControl
Re: GUIA: FAT al desnudo
« Respuesta #6 en: 09 de Febrero de 2007, 10:45:27 »
> Formatos de fecha y hora:
Muchas implementaciones solo soportan los campos DIR_WrtTime y DIR_WrtDate. Por esta razón, 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 demás operaciones.

Los campos que contienen fechas utilizan 16 bits (dos bytes) para codificar el día, mes y año de la fecha en cuestión, pero referidas a 1980. Es decir, al año expresado deberá sumársele 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: Día del mes, valores en el rango 1..31
Bits 5-8: Número de mes, valores en el rango 1..12
Bits 9-15: Años transcurridos desde 1980, valores en el rango 0..127

Por ejemplo, la fecha "10 de febrero de 2007" se codificaría como:

01010 para el día del mes (10)
0010 para el numero de mes (2)
0011011 para el año (27, por que 1980 + 27 = 2007)

Los 16 bits serian 0011 0110 0100 0101, en hexadecimal "36 45". Como se colocan en notación "Little Endian", en el soporte deben guardarse invertidos, es decir "45 36".


El formato de el tiempo es similar. También 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 codificaría como:

10011 para los segundos (19, por que 19 * 2 = 38).
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 notación "Little Endian", en el soporte deben guardarse invertidos, es decir "33 7B".


¡Hasta la proxima!
Si cualquier habilidad que aprende un niño será obsoleta antes de que la use, entonces, ¿qué es lo que tiene que aprender? La respuesta es obvia:
La única habilidad competitiva a largo plazo es la habilidad para aprender
“. Seymour Papert


 

anything