Page 1 of 1

Reading a FAT root directory

Posted: Wed Mar 30, 2011 10:19 pm
by duran
Greetings,

I have a quick question regarding the root directory of a FAT file system (specifically, FAT12).

I'm writing myself a bootloader from scratch, it's not really gotten far beyond booting, as I realised that I'm very soon going to require a file system if I want to do much. With this in mind, I started to implement a FAT12 fs for my boot floppy.

Right now I've got the boot sector coded so that it reads a FAT off the disk into memory (I cheated a little for testing and used a windows-formatted floppy image and overwrote the first sector with my own). this works, but now i want to read the root directory. My question is, given that this is a floppy I'm using here, and there's 14 sectors allocated to the root directory, should a properly designed FAT12 fs try to keep all directory entries at the top of the root directory space? At the moment there's only one example text file on the image in question, and I'm wondering how I check for the last directory entry while reading the contents, and what should happen were i to add 2 more files, and then delete the second, does this result in a fragmentation, or should the rest of the directory entries be moved down one whenever this happens?

Re: Reading a FAT root directory

Posted: Thu Mar 31, 2011 7:59 am
by U238
Hi,
duran wrote:My question is, given that this is a floppy I'm using here, and there's 14 sectors allocated to the root directory, should a properly designed FAT12 fs try to keep all directory entries at the top of the root directory space?
Yes, a properly designed FAT12 file system driver should keep all directory entries at the top of the root directory space. If a file is deleted, it's root directory entry should be replaced with the next file that is written to the disk, instead of creating a new directory entry for the new file.
duran wrote: At the moment there's only one example text file on the image in question, and I'm wondering how I check for the last directory entry while reading the contents
Your driver should check for a 0x0 (0h) byte as the first byte in each root directory entry, this signifies that the directory entry is not being used, and therefore is the last file on the disk.
duran wrote:what should happen were i to add 2 more files, and then delete the second, does this result in a fragmentation, or should the rest of the directory entries be moved down one whenever this happens?
When a file on a fat12 file system is deleted, a 0xE5 (E5h) byte is set as the first byte in the root directory entry, nothing else. So your driver should just skip any entry that has the 0xE5 byte when reading or listing files.

For example:

Code: Select all

4B 45 52 4E 45 4C 20 20 53 59 53 20 18 18 A9 23 54 3E 54 3E 00 00 56 8E 54 3E 02 00 32 01 00 00 
53 4B 55 5A 20 20 20 20 54 58 54 20 18 18 AC 23 54 3E 54 3E 00 00 DA AB 46 3E 03 00 1C 00 00 00 
E5 45 45 44 20 20 20 20 54 58 54 20 18 B4 12 8D 54 3E 54 3E 00 00 FC 8C 54 3E 00 00 00 00 00 00 
4D 4F 50 20 20 20 20 20 54 58 54 20 18 A4 15 8D 54 3E 54 3E 00 00 05 8D 54 3E 00 00 00 00 00 00 
E5 41 4A 41 52 20 20 20 54 58 54 20 18 1F 1A 8D 54 3E 54 3E 00 00 09 8D 54 3E 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
Each line is a root directory entry that points to a file in the FAT.

The first line points to a file that hasn't been deleted.
The second line points to a file that hasn't been deleted.
The third line points to a file that has been deleted.
The forth line points to a file that hasn't been deleted.
The fifth line points to a file that has been deleted.
The Sixth line is a root directory entry that is not being used, and therefore there are no more files on the disk.

When your driver gets to the third file, it should see the 0xE5 byte and skip that root directory, and go on and print the forth file. It should then skip the fifth file because of the 0xE5, and then finally go on to sixth root directory entry and find the 0x00 byte, indicating no more files and should then finish. Any new file that is written should overwrite the third root directory entry, since that file is deleted.

The pseudocode for your driver when listing the files on the disk should be:

1.Set up a counter of 224 for the number of root directory entries.
2.Increment the counter and continue if the counter does not equal 224, otherwise go to step 9.
3.Read the first byte of the root directory entry.
4.Compare it to either 0x00 or 0xE5.
5.If the first byte is 0x00, go to step 9.
6.If the first byte is 0xE5, go to step 8.
7.If the first byte is neither 0x00 or 0xE5, then the file is good so you can do whatever you want.
8.Point your driver to the next root directory entry and go back to step 2.
9.Once your driver has found a 0x00 or the counter has reached 224, then there are no more files on the disk.

Of course, the above will not work for LFN, it is only what I used for my simple "dir" command.

Hope I helped.

-U238

Re: Reading a FAT root directory

Posted: Thu Mar 31, 2011 9:04 am
by turdus
Disassemble a FAT12 boot sector. Here's one that's well commented:
http://www.omninerd.com/articles/PC_Boo ... ial_in_ASM

Re: Reading a FAT root directory

Posted: Fri Apr 01, 2011 1:02 am
by qw

Re: Reading a FAT root directory

Posted: Fri Apr 01, 2011 3:50 am
by duran
turdus wrote:Disassemble a FAT12 boot sector. Here's one that's well commented:
http://www.omninerd.com/articles/PC_Boo ... ial_in_ASM

Forgive me if I'm wrong, but I wanted to check this:

Code: Select all

LBACHS:
     xor     dx, dx                              ; prepare dx:ax for operation
     div     WORD [SectorsPerTrack]              ; calculate
     inc     dl                                  ; adjust for sector 0
     mov     BYTE [absoluteSector], dl
     xor     dx, dx                              ; prepare dx:ax for operation
     div     WORD [NumHeads]                     ; calculate
     mov     BYTE [absoluteHead], dl
     mov     BYTE [absoluteTrack], al
     ret
The calculation of the cylinder value there appears to work out to something like ( LBASector / SectorsPerTrack ) / NumHeads. I thought the algorithm for computing cylinder values from LBA addresses was LBASector / ( NumHeads * SectorsPerTrack ) ?

Re: Reading a FAT root directory

Posted: Fri Apr 01, 2011 5:21 am
by turdus
duran wrote: The calculation of the cylinder value there appears to work out to something like ( LBASector / SectorsPerTrack ) / NumHeads. I thought the algorithm for computing cylinder values from LBA addresses was LBASector / ( NumHeads * SectorsPerTrack ) ?
I cannot garantee that the above code is perfect. I've just googled it, and it was the first result. That's why I suggested to disassemble a code that you saw working and compare.
(I've never implemented FAT12, that's too obsolete for me, I use FAT32 for EFI support. And yes, I did it the hard way, I saved a boot sector of an MSDOS partition and disassembled it, understand it, and wrote my own implementation. I've tested it with linux "mkfs.vfat -F 32" and it worked, then I forget the whole thing.)

Re: Reading a FAT root directory

Posted: Fri Apr 01, 2011 6:24 am
by duran
Took the suck it and see approach...kinda
the code looked incorrect, so i changed it to use the canonical CHS algorithm. Everything went better than expected :)

FAT reads out,root directory read out. I've gotten as far as dumping the listing of the root directory to the terminal so far.

next stop, loading a kernel image, as the boot sector is getting kinda crowded now.

Re: Reading a FAT root directory

Posted: Fri Apr 01, 2011 6:33 am
by turdus
Well done! I'm glad it was useful despite of wrong LBSCHS!