Qualquer pessoa que utilize um computador, um Tablet, um telemóvel ou qualquer outro dispositivo do género acabo por ter de lidar com sistemas de armazenamento de ficheiros (discos, disquetes, cartões de memória, pens…). Seja qual for o sistema operativo utilizado, é quase inevitável que a informação fique armazenada em dispositivos físicos. Dada a importância dos sistemas de armazenamento de ficheiros, seria de esperar que as pessoas que os utilizam tivessem, pelo menos, um mínimo de conhecimento sobre a forma como eles funcionam, mas a verdade é que não tem!
O sistema de armazenamento FAT foi concebido por volta de 1977 e tem sido utilizado até ao presente, embora tenha sofrido algumas alterações estruturais e diversas evoluções. É comum considerar a existência de três sistemas de armazenamento de ficheiros, comummente designados por FAT 12, FAT 16 e FAT 32, largamente utilizados e difundidos pelo sistema operativo DOS da Microsoft e IBM e pelas versões dos sistemas operativos Windows anteriores ao Windows XP. Este artigo é dedicado ao sistema de armazenamento de ficheiros FAT 12.
Um pouco de história
A FAT 12 evoluiu a partir de um projecto de Bill Gates e Marc McDonald do final dos anos setenta do século passado, mas foi Tim Paterson, entre 1980 e 1981, que, a convite da Microsoft, lhe conferiu a estrutura que perdura até aos dias de hoje.
Partindo de uma estrutura com oito bits por cada entrada da FAT, três cópias da FAT e dezasseis bytes para cada entrada na directoria da root, Tim Paterson definiu um modelo, originalmente pensado apenas para disquetes, com doze bits por cada entrada da FAT, duas cópias da FAT e trinta e dois bytes para cada entrada da directoria da root que ficou conhecido como 12-bit File Allocation Table ou simplesmente FAT 12.
Anatomia de uma partição formatada como FAT 12
O sistema de armazenamento de ficheiros FAT 12 é constituído por quatro secções: Boot Sector, File Allocation Tables (FAT), Directoria da Root e Área de Dados.
Boot Sector |
FAT (cópia 1) |
FAT (cópia 2) |
Directoria da Root |
Área de Dados |
Boot Sector
É o primeiro sector de uma partição formatada como FAT 12. Basicamente, contém um conjunto de parâmetros que especificam as características da partição e um pequeno programa (bootstarp code) responsável pelo carregamento e arranque do sistema operativo (no caso de se tratar de uma partição com sistema operativo ou, pela exibição no ecrã de uma mensagem indicando que a partição não contém sistema operativo).
Estrutura típica do Boot Sector
Pode considerar-se que o Boot Sector é constituído por cinco secções independentes: uma instrução de salto, que ocupa os três primeiros bytes; um conjunto de oito bytes, designados OEM ID, que, normalmente, identificam o sistema operativo que formatou a partição; uma tabela com as características da partição, situada ao longo dos próximos 51 bytes, designada BIOS Parameter Block, normalmente abreviada para BPB; o programa responsável pelo início do carregamento do sistema operativo, ou pela exibição de uma mensagem no monitor informando que a partição não tem sistema operativo, conhecido, em inglês, por bootstrap code; finalmente, uma “assinatura” composta por dois bytes com os valores hexadecimal 0x55 e 0xAA.
Endereço | Descrição | Dimensão | |
Decimal | Hexa | ||
0 | 0x000 | Instrução de salto | 3 bytes |
3 | 0x003 | OEM ID | 8 bytes |
11 | 0x00B | BIOS Parameter Block (BPB) | 51 bytes |
62 | 0x03E | Código inicial (bootstrap code) | 448 bytes |
510 | 0x1FE | Assinatura | 2 bytes |
A instrução de salto destina-se a transferir o controlo, de um modo geral, para o código inicial, e é habitual ser uma das instruções de salto da família Intel 86, muitas vezes um JMP SHORT 0x3E (a que correspondem os bytes 0xEB e 0x3C), seguida por uma instrução NOP (0x90) para perfazer os três bytes requeridos.
O OEM ID é um simples conjunto de oito caracteres que identifica o sistema operativo que formatou a partição. Por exemplo, uma partição formatada pelo Windows XP tem como OEM ID MSDOS5.0, uma partição formatada em Linux tem como OEM ID mkfs.fat.
O BPB é uma tabela com diversa informação sobre as características da partição, como por exemplo, o número de bytes de cada sector, o número de sectores por pista, o número de cabeças do dispositivo, etc… Ao longo do tempo, diversas versões do MS-DOS foram introduzindo pequenas alterações no BPB, de forma a poderem contemplar partições com maiores dimensões, acabando por dar origem ao que ficou conhecido o Extended BIOS Parameter Block (EBPB).
O código inicial, em inglês bootstrap code, é um pequeno programa responsável pelo carregamento para memória e passagem de controlo para o sistema operativo. No caso da partição não conter sistema operativo, responsabiliza-se por enviar mensagens elucidativas para o monitor e bloqueia a máquina.
Finalmente, a assinatura é sempre constituída pelos valores 0x55 e 0xAA.
BIOS Parameter Block (BPB)
As tabelas que se seguem apresentam a composição típica do BPB e os novos campos acrescentados pelo EBPB. Os endereços indicados têm como base o início do Boot Sector.
Endereço | Descrição | Dimensão | |
Decimal | Hexa | ||
11 | 0x0B | Número de bytes por sector | 2 bytes |
13 | 0x0D | Número de sectores por cluster | 1 byte |
14 | 0x0E | Número de sectores reservados | 2 bytes |
16 | 0x10 | Número de cópias da FAT | 1 byte |
17 | 0x11 | Número máximo de entradas na directoria da root | 2 bytes |
19 | 0x13 | Número de sectores da partição | 2 bytes |
21 | 0x15 | Media Descriptor Byte | 1 byte |
22 | 0x16 | Número de sectores de cada cópia da FAT | 2 bytes |
24 | 0x18 | Número de sectores por pista | 2 bytes |
26 | 0x1A | Número de cabeças do dispositivo | 2 bytes |
28 | 0x1C | Número de sectores escondidos da partição | 4 bytes |
32 | 0x20 | Número grande de sectores da partição | 4 bytes |
Endereço | Descrição | Dimensão | |
Decimal | Hexa | ||
36 | 0x24 | Nome lógico da partição (Drive Name) | 1 byte |
37 | 0x25 | Reservado | 1 byte |
38 | 0x26 | Extended Boot Signature | 1 byte |
39 | 0x27 | Número de série da partição | 4 bytes |
43 | 0x2B | Nome da partição | 11 bytes |
54 | 0x36 | Nome da FAT | 8 bytes |
Antes de apresentar uma descrição mais detalhada de cada um destes campos, é de toda a conveniência referir que os valores utilizam a notação Little Endian, ou seja, o primeiro valor que aparece corresponde ao valor de menor peso.
Número de bytes por sector
Indica o número de bytes que cada sector da partição tem. Normalmente são 512 bytes, embora nada impeça um valor diferente.
Número de sectores por cluster
Indica o número de sectores que compõe cada cluster. Como se verá posteriormente, o número de clusters de uma partição é limitado pelo tamanho das suas FATs. Um subterfúgio usado para conseguir formatar partições de maior dimensão consiste em aumentar este valor.
Número de sectores reservados
Indica o número de sectores que se encontram entre o início da partição e o primeiro sector da primeira cópia da FAT. Este valor é, no mínimo, 1 (o próprio Boot Sector), mas é frequente encontrar o valor 2 (o que significa que depois do Boot Sector vai estar um sector que nunca será usado).
Número de cópias da FAT
Especifica quantas cópias da FAT existem. É muito pouco provável que este valor seja diferente de 2. Seja como for, terá de ser, pelo menos 1!
Número máximo de entradas na directoria da root
Este campo indica quantos ficheiros e directorias (as directorias, que não a da root, na verdade não passam de simples ficheiros) podem existir na directoria da root da partição.
Ao contrário das restantes directorias, que podem conter um número de ficheiros limitado apenas pela capacidade da partição, a directoria da root está limitada por este valor. Ao tenta colocar mais um ficheiro do que o permitido na directoria da root, mesmo que exista espaço disponível, o sistema operativo não o permite e informa-o por intermédio de uma mensagem de erro.
Número de sectores da partição e número grande de sectores da partição
Para partições com menos 65.535 sectores (32 Mega Bytes para partições com 512 bytes por sector), este campo indica o número de sectores que a partição tem. Se a partição tiver um número de sectores superior, o campo tem o valor 0 e o número de sectores da partição está no campo “Número grande de sectores da partição”.
Media Descriptor Byte
Identifica o tipo de dispositivo, isto é, indica se o dispositivo é uma disquete ou um disco rígido. As pen e cartões de memória são identificadas como discos rígidos.
Este byte é interpretado bit a bit, tendo os quatro bits de maior peso sempre o valor ‘1’ e os cinco bits de menor peso o significado que a Tabela 4 apresenta:
Bit | Significado | |
com o valor 1 | com o valor 0 | |
0 | Dispositivo com 2 lados | Dispositivo sem 2 lados |
1 | Tem 8 sectores por pista | Não tem 8 sectores por pista |
2 | Dispositivo é removível | Dispositivo não é removível |
A Tabela 5 apresenta os diversos valores que este campo pode ter:
MDB | Dsipositivo |
0xF0 | Disquete de 3,5” de alta densidade (1,44MB e 2,88 MB) |
0xF9 | Disquete de 3,5” (720 KB) e 5,25” de alta densidade (1,2 MB) |
0xFD | Disquete de 5,25” (360 KB) |
0xFF | Disquete de 5,25” (320 KB) |
0xFC | Disquete de 5,25” (180 KB) |
0xFE | Disquete de 5,25” (160 KB) |
0xF8 | Disco rígido |
Número de sectores de cada cópia da FAT
Como seria de esperar, este campo indica o número de sectores destinado a cada uma das cópias da FAT, ou seja, a dimensão de cada cópia da FAT.
O valor deste campo, juntamente com o valor dos campos “Número de cópias da FAT” e “Número de sectores reservados” permite determinar o sector onde começa a directoria da root.
Número de sectores por pista, número de cabeças do dispositivo
Os valores destes dois campos correspondem aos respectivos valores físicos do dispositivo.
Nome lógico da partição (Drive Name)
O valor deste campo é 0x00 para as disquetes, 0x80 para os discos rígidos.
Reservado
Inicialmente, este campo era usado para guardar o número do cilindro do dispositivo onde se encontrava o Boot Sector. Posteriormente, o Windows NT passou a usar este campo para guardar dois sinalizadores (flags) que indicavam que deveria ser executada uma análise do disco, em inglês scan disk (bit de menor peso), ou uma análise de superfície, em inglês surface analysis (segundo bit de menor peso), logo após o arranque do sistema operativo.
Exteded Boot Signature
Quando este campo tem o valor 0x29 indica que os três campos que seguem existem.
Número de série da partição
O valor guardado neste campo é um número aleatório que uma vez combinado com o valor do campo “Nome da partição” permite determinar se se trata de uma partição existente num dispositivo removível (disquete) e se o dispositivo correcto está introduzido no leitor (drive).
Nome da partição
Este campo contém uma cópia do nome atribuído à partição durante o processo de formatação, ou posteriormente alterado, com o comando adequado do sistema operativo.
Nome da FAT
Este campo contém o nome “FAT12 “; os últimos três caracteres são o carácter espaço, de forma a preencher um total de exactamente oito bytes.
File Allocation Table (FAT)
A FAT, palavra formada pelas três iniciais das palavras inglesas File Allocation Table, não é mais do que uma simples e uni-dimensional tabela onde, cada um dos seus elementos é um número de 12 b bits que representa um cluster da partição. O valor de cada elemento da FAT tem o significado que se indica na Tabela 6. Não é consensual se os valores 0xFF0 a 0xFF6 podem ser utilizados ou se são considerados reservados.
Valor | Significado |
0x000 | Cluster livre |
0x001 e 0x002 | Valores não utilizados |
0x003 a 0xFF6 | O cluster faz parte de um ficheiro; o valor é o endereço do cluster seguinte |
0xFF7 | Cluster danificado |
0xFF8 a 0xFFF | Último cluster de um ficheiro |
O sistema de armazenamento de ficheiros FAT 12 utiliza duas cópias da FAT, iniciando-se a primeira cópia no sector que segue ao último sector reservado e iniciando-se a segunda cópia no sector que segue ao último sector ocupado pela primeira cópia.
Por definição, o valor da FAT para o primeiro cluster (cluster 0) é 0xFxx, onde xx é o valor do Media Descriptor Byte do BPB. O valor do segundo cluster (cluster 1) é um final de ficheiro (0xFFF); no entanto, os dois bits de maior peso podem ser utilizados para indicar que a partição pode estar corrompida por não ter sido correctamente desmontada (bit de maior peso a ‘0’), ou que houve um erro de leitura / escrita da última vez que a partição foi montada (segundo bit de maior peso a ‘0’). O primeiro cluster de dados é o cluster 2.
Como cada entrada da FAT usa 12 bits (cada byte é constituído por 8 bits e 12 não é múltiplo de 8) foi preciso encontrar uma forma de organizar a informação contida na FAT que não acarretasse desperdício de espaço. A solução encontrada recorre ao menor múltiplo comum entre 12 e 8, que é 24. Assim, cada duas entradas da FAT ocupam 24 bits, ou seja, 3 bytes. Do ponto de vista humano, esta solução dificulta um pouco a análise de uma FAT 12. Matematicamente, podem escrever-se as duas equações que seguem para calcular o valor de duas entradas de uma FAT 12:
Entrada_1 = ((Byte_2 And 0x0F) * 0x100) + Byte_1
Entrada_2 = (Byte_3 * 0x10) + ((Byte_2 And 0xF0) / 0x10)
Onde, Byte_1 é o byte de menor peso (mais à esquerda) e Byte_3 o de maior peso (mais à direita); “And” é o operador lógico para uma operação de conjunção realizada bit a bit; “*” e “/” são os operadores aritméticos para as operações de multiplicação e divisão.
Vamos ver um exemplo; sejam 0xFF, 0x0F e 0x00 o valor de três bytes de uma FAT 12:
Entrada_1 | = ((0x0F And 0x0F) * 0x100) + 0xFF |
= (0x0F * 0x100) + 0xFF | |
= 0xFFF (último cluster de um ficheiro) | |
Entrada_2 | = (0x00 * 0x10) + ((0x0F And 0xF0) / 0x10) |
= 0x00 + (0x00 / 0x10) | |
= 0x000 (cluster livre) |
Para o olho humano, muitas vezes é mais fácil visualizar os assuntos de forma gráfica:
Directoria da root
A directoria da root é a directoria de topo, ou seja, é a directoria que contém todas as demais directorias e ficheiros. Ao contrário de todas as restantes directorias que venham a ser criadas, a directoria da root é criada automaticamente pelo sistema operativo e não pode ser destruída (excepto por uma operação de formatação, o que irá destruir todos os dados existentes).
No sistema de armazenamento de ficheiros FAT 12, a directoria da root tem capacidade para albergar um número fixo de outras directorias e ficheiros, que passaremos a designar por entradas. O número de entradas que a directoria da root pode conter encontra-se no campo “Número máximo de entradas da directoria da root” do BIOS Parameter Block (BPB).
Cada entrada da directoria da root é constituída por trinta e dois bytes, cujo significado se apresenta na Tabela 7.
Endereço | Descrição | Dimensão | |
Decimal | Hexa | ||
0 | 0x00 | Nome da entrada | 8 bytes |
8 | 0x08 | Extensão da entrada | 3 bytes |
11 | 0x0B | Atributos da entrada | 1 byte |
12 | 0x0C | Reservado | 1 byte |
13 | 0x0D | Criação (milissegundos vezes 10) | 1 byte |
14 | 0x0E | Hora de criação | 1 byte |
16 | 0x10 | Data de criação | 2 bytes |
18 | 0x12 | Data em que foi acedida pela última vez | 2 bytes |
20 | 0x14 | Reservado | 2 bytes |
22 | 0x16 | Hora em que foi gravada pela última vez | 2 bytes |
24 | 0x18 | Data em que foi gravada pela última vez | 2 bytes |
26 | 0x1A | Endereço do cluster inicial | 2 bytes |
28 | 0x1C | Dimensão (em bytes) | 4 bytes |
Tal acontece com o BPB, também aqui, os valores usam a notação little endian, ou seja, o valor que surge primeiro é o de menor peso.
Nome da entrada
Este campo contém o nome do ficheiro ou directoria e pode conter um máximo de oito caracteres. Se o nome utilizar menos de oito caracteres, o sistema preenche automaticamente os restantes com o carácter espaço.
Quando um ficheiro ou directoria são apagados, o sistema operativo substitui o primeiro carácter do ‘Nome’ pelo carácter 0xE5 (e preenche a 0x000 os elementos das duas FAT que a entrada utilizava).
Extensão da entrada
Três bytes destinados a guardarem a extensão do ficheiro ou directoria. Tal como se verifica com o “Nome”, também neste caso o sistema preenche com o carácter espaço, os bytes não utilizados.
Atributos da entrada
Este campo contém os atributos do ficheiro ou directoria. Cada bit deste valor representa um atributo. A Tabela 8 apresenta o significado de cada um dos seus bits.
Bit | Atributo | Significado |
7 | – | Reservado, normalmente ’0’ |
6 | – | Reservado, normalmente ’0’ |
5 | (A)rquivo | Utilizado por programas capazes de realizar cópias de segurança (Backup e Restore) |
4 | (D)irectoria | É uma directoria (e não um ficheiro) |
3 | (V)olume | A entrada contém o nome da partição, não é ficheiro nem directoria |
2 | (S)istema | Trata-se de um ficheiro do sistema operativo |
1 | (H)idden | Ficheiro ou directoria escondido |
0 | (R)ead Only | Ficheiro ou directoria apenas pode ser lido, não pode ser alterado nem apagado |
Criação (milissegundos vezes 10)
Este byte guarda o número de milissegundos vezes dez, ou seja, centésimos de segundo) da hora em que o ficheiro ou directoria foi criado.
Hora de criação
Contém a hora, minuto e segundo em que o ficheiro ou directoria foi criado. O formato usado para guardar os valores é o que se ilustra na Tabela 9.
Bits | Significado |
11 a 15 | Horas (0 a 23) |
5 a 10 | Minutos (0 a 59) |
0 a 4 | Segundos ÷ 2 (0 a 29) |
Data de criação
Data de criação do ficheiro ou directoria. A Tabela 10 apresenta o formato usado para guardar os valores.
Bits | Significado |
9 a 15 | Ano (1980 + valor) |
5 a 8 | Mês (1 a 12) |
0 a 4 | Dia (1 a 31) |
Data em que foi acedido pela última vez
Regista a data em que o ficheiro foi acedido (lido ou escrito pela última vez. Se o último acesso foi uma escrita, então este valor é igual ao valor do campo “Data em que foi alterado pela última vez”. Os valores são guardados no formato que a Tabela 10 ilustra.
Hora em que foi alterado pela última vez
Regista a hora em que o ficheiro foi alterado pela última vez. Os valores são guardados no formato que se ilustra na Tabela 9.
Data em que foi alterado pela última vez
Regista a data em que o ficheiro foi alterado pela última vez. Os valores são guardados no formato que se ilustra na Tabela 10.
Endereço do cluster inicíal
Contém o valor do cluster onde se encontra o início do ficheiro ou directoria.
Dimensão (em bytes)
Simplesmente o número de bytes do ficheiro. Se a entrada não é um ficheiro (pode ser uma directoria ou o nome da partição), o valor é 0x00000000.
Área de Dados
A área de dados é todo o resto da partição, isto é, todos os clusters que vão desde o cluster número 2 (recorde-se que os dois primeiros clusters estão reservados e têm significados especiais) até ao último cluster da partição.
Exemplo prático – Analise de uma partição FAT 12
Concluímos este documento com a análise de um cartão Memory Stick com 16 MB de capacidade formatado pelo Windows XP com uma única partição FAT 12 (o Windows usa simplesmente o nome FAT).
Figura 2. Directoria da root do dispositivo.
Como se pode observar na Figura 2, a directoria da root contém dois ficheiros e uma directoria.
A Figura 3 apresenta o Boot Sector, ou seja, o sector inicial, da única partição existente neste dispositivo. Podem identificar-se, a partir do endereço 0x00 (realçado a azul) os três bytes que formam a instrução de salto; entre os endereços 0x0B e 0x3D (realçado a amarelo) o BPB; nos dois últimos bytes a assinatura (realçado a azul claro).
Podem agora extrair-se do BPB as informações que interessam para que se possa navegar pela partição. A Tabela 11 resume os valores mais importantes.
Endereço | Significado | Valor |
0x0B e 0x0C | Número de bytes por sector | 0x0200 = 512 |
0x0D | Número de sectores por cluster | 0x08 = 8 |
0x0E e 0x0F | Número de sectores reservados | 0x0008 = 8 |
0x10 | Número de cópias da FAT | 0x02 = 2 |
0x11 e 0x12 | Número de entradas da directoria da root | 0x0200 = 512 |
0x16 e 0x17 | Número de sectores de cada cópia da FAT | 0x000C = 12 |
Com base neste valores pode determinar-se que:
- a primeira cópia da FAT começa no sector 8 (número de sectores reservados),
- a segunda cópia da FAT começa no sector 20 (sector inicial da primeira cópia da FAT + número de sectores de cada cópia da FAT),
- a directoria da root começa no sector 32 (sector inicial da segunda cópia da FAT + número de sectores de cada cópia da FAT),
- o primeiro cluster de dados (cluster 2) ocupa 8 sectores a partir do sector 64 (número de entradas da directoria da root * número de bytes de cada entrada da root / número de bytes por sector + sector inicial da root, ou seja, 512 * 32 / 512 + 32 = 64).
Figura 4. Os primeiros bytes da directoria da root.
A Tabela 12 apresenta os primeiros bytes do sector onde começa a directoria da root. Pode ver-se (realçado a amarelo) o nome e extensão dos dois ficheiros e da directoria; repare-se que os caracteres não usados estão preenchidos com espaços (valor 0x20). Realçado a vermelho está o byte com os atributos; as duas primeiras entradas tem simplesmente o atributo “Arquivo”, a directoria, como não podia deixar de ser tem o atributo “Directoria”. A azul realça-se o cluster inicial de cada entrada; o ficheiro “LINKS.TXT” começa no cluster 2, o ficheiro “PORTASER.JAR” no cluster 3 e a directoria no cluster 54 (0x36). Pode ainda ver-se que existiu uma quarta entrada, um ficheiro, que foi apagado (o nome começa pelo carácter 0xE5) e que teria como nome um primeiro carácter que desconhecemos seguido pelos caracteres ‘ITACOES.TXT’.
Para continuar a navegação, é necessário examinar uma das cópias da FAT. A Figura 4 apresenta os primeiros bytes da primeira cópia da FAT:
Os três bytes referentes aos dois primeiros clusters (realçados a amarelo), os clusters reservados têm os valores esperados: oxFF8 para o cluster 0 (F8 é o Media Descriptor Byte – o cartão é considerado um disco rígido) e 0xFFF para o cluster 1.
Os três bytes seguintes (realçados a azul) têm informação sobre o que se passa com os clusters 2 (0xFFF) e 3 (0x004); o cluster 2 (onde tinha início o ficheiro LINKS.TXT) é um cluster terminal, ou seja, o ficheiro LINKS.TXT ocupa apenas um cluster na partição; o cluster 3 (onde tem inicio o ficheiro PORTASER.JAR) aponta para o cluster 4, ou seja, o ficheiro estende-se pelo cluster 4; seguindo a FAT, ficamos a saber que o ficheiro PORTASER.JAR ocupa clusters consecutivos até ao cluster 0x35 (realçado a verde), onde encontramos um fim de ficheiro.
Bibliografia
- Dettmann, Terry, «DOS Programmer’s Reference», QUE, 1989
- Jamsa, Kris, »DOS The Complete Reference», McGraw-Hill, 1987
- Rector, Russel and Alexy, George, »The 8086 Book», McGraw-Hill, 1980