Where are bootloader reserved sectors located in FAT32?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Kaisogen
Posts: 10
Joined: Tue Apr 26, 2016 3:50 pm
Location: South Carolina

Where are bootloader reserved sectors located in FAT32?

Post by Kaisogen »

I'm rewriting my bootloader to support FAT32, with a few extra features, including ELF loading, and configuration options (enable protected mode, a20 on bootup, load bin instead of elf, sha verification, etc). Previously, my bootloader fit into a single sector, and loaded the next 12 sectors into memory, which was were my kernel was located. I find this rather inelegant, and as my project grows in size, I can't keep adjusting my bootloader to fit that.

Ideally, I would have a stub, that loaded a 32bit Protected Mode program, then loaded X raw sectors which contains the stage 2 I've written in C. Stage 2 loads the config file, and decides what to do, eventually loading, and handing execution over to the kernel. The default kernel being a file named "kernel.elf", or whatever was decided in the configuration file to load (or user selection).

My only problem is that I can't seem to tell where bootloader reserved sectors start, and end. I use mkdosfs to create my virtual image, and then used a hex editor to look at the contents. It seems that according to the specs, by default, sectors 2, and 6 are reserved, but this doesn't match up with what I've found. I thought that the reserved sectors would show up immediately after these two, but in my image there is data immediately after these spaces. I'm not sure if this is an issue with mkdosfs, but it is rather confusing. I defined a default reserved sector count of 32, which should equate to 0x4000 bytes, but there isn't a single reserved gap other than in the middle of the drive (which is where I assume the clusters are, with their associated data) that fits that length at minimum. I'm really at a loss for where these reserved sectors are supposed to be, and where I should place my stage 2.
KoiOS: https://github.com/GabrielRRussell/KoiOS

Code: Select all

#define CURRENT_YEAR 2014 // Change this each year!
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Where are bootloader reserved sectors located in FAT32?

Post by bzt »

Kaisogen wrote:My only problem is that I can't seem to tell where bootloader reserved sectors start, and end. I use mkdosfs to create my virtual image, and then used a hex editor to look at the contents. It seems that according to the specs, by default, sectors 2, and 6 are reserved, but this doesn't match up with what I've found.
In theory reserved sectors are recorded in BPB and could be used for a loader, however it is problematic to access and there's no guarantee it's not zerod out by some fsck tool. I'd not recommend using it.
Kaisogen wrote:I'm really at a loss for where these reserved sectors are supposed to be, and where I should place my stage 2.
Do what the old DOS did. Create a special file as first file in the file system. Make it as big as your 2nd stage needs to be. Since the allocation table is empty, therefore the file system is defragmented, which guarantees that the first file will be stored contiguously. I would also recommend to set the SYSTEM attribute in the fat directory entry to tell other fat tools not to relocate the contents of this file. A bonus with this approach that you can update the 2nd stage with standard FAT fs utilities, no need for special tools.

You could read the root directory and parse the first directory entry to get the starting cluster and size of the loader from 1st stage (like MSDOS boot sector did with "MSDOS.SYS"). Converting clusters into sectors in Assembly is not that hard. There are literally hundreds of examples and tutorials on the net. Take a look at BootProg for one. BootProg btw is capable of walking the cluster chain, so you don't even have to create a contiguous file, any file will do. I'd still recommend using a contiguous area for 2nd stage, because that can be loaded with a single BIOS INT call, meaning simpler, smaller, faster 1st stage.

Or instead of parsing the root directory, you could easily calculate the first sector for the first data cluster on file system creation time when you write the boot sector (since the size of the root directory won't change, the first file's first cluster won't change either). This latter is what I use in my boot loader, and works perfectly. Just a side note, my mkboot.c tool expects that the 2nd stage is contiguous and looks for its magic bytes. So with a pre-calculated starting sector my 1st stage can load the 2nd stage from the BPB reserved sectors area as well as from a SYSTEM file on the FAT partition (or from any other file system as a matter of fact). There's absolutely nothing FAT32 specific in my 1st stage, and I use this scheme with FAT32 mostly because UEFI needs an ESP and that's where I put my 2nd stage.

Cheers,
bzt
Octocontrabass
Member
Member
Posts: 5575
Joined: Mon Mar 25, 2013 7:01 pm

Re: Where are bootloader reserved sectors located in FAT32?

Post by Octocontrabass »

Kaisogen wrote:It seems that according to the specs, by default, sectors 2, and 6 are reserved, but this doesn't match up with what I've found.
I'm not sure what spec you're reading, but that's not correct. Sector 2 contains additional code used by the bootloader in sector 0, and sector 6 is a backup copy of sector 0.

Using sector 0 and sector 2 gives you around 930 bytes for your stage 1, which is more than enough to parse the filesystem and load your stage 2 from a file instead of from reserved sectors.

FAT32 volumes are typically located on partitioned disks, so sector 0 will probably not be LBA 0.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: Where are bootloader reserved sectors located in FAT32?

Post by BenLunt »

With Octocontrabass' statement, let me go into a little more detail.

The FAT32 filesystem actually allows, by default, twenty five (25) sectors for your boot code. If sectors are 512 bytes each (and for a FAT system, due to legacy systems, this is a requirement), that gives you 12,800 bytes for your boot code, not counting the BPB. In fact, there are 480 reserved bytes in the Info Sector, so this count goes to 13,280 bytes, again not taking into account the BPB.

Typical FAT32 System contains:
LSN 0: Boot Sector
LSN 1: Info Sector (but can be anywhere between and including LSN 1 through LSN 26)
LSN 2: Reserved Sectors (4 count)
LSN 6: Backup Sector (but can be anywhere between and including LSN 1 through LSN 26)
LSN 7: Reserved Sectors (20 count)
LSN 27: First FAT
LSN 27+n: Second FAT
(LSN = Logical Sector Number)

Again, this is a typical FAT32 system. The BPB allows you to modify it to allow more or less, though the above is a common formatted FAT32 partition.
How about a non-typical, but perfectly legal format?

LSN 0: Boot Sector
LSN 2: Reserved Sectors (24 count)
LSN 25: Info Sector
LSN 26: Backup Sector
LSN 27: First FAT
LSN 27+n: Second FAT

This gives you 24+ consecutive sectors to use for your boot code. However, don't rely upon the fact that all FAT drivers will allow this. Some--probably more than we would like--assume the Info sector is at LSN 1 and the Backup Sector is at LSN 6.

Ben
- http://www.fysnet.net/osdesign_book_series.htm
User avatar
Kaisogen
Posts: 10
Joined: Tue Apr 26, 2016 3:50 pm
Location: South Carolina

Re: Where are bootloader reserved sectors located in FAT32?

Post by Kaisogen »

I've gone with the method of loading the first file. It's a bit lazy, but I'll redesign it later so it can properly walk a cluster chain, and search for the file entry.
Among other things that have been changed, I also decided to use the extended read sectors interrupt, since it reduced the amount of code I had to write / gave me slightly more space. I don't really care too much for any lost support, as it works on my machine and the VM I use to test it (qemu).

Right now, it loads the first file entry, expecting the stage2 to be contiguous in memory. Then counts the number of bytes, converts that to sectors, and adds another cluster if necessary. Then, it loads the file into 0x0000:0x1000, and jumps to it.

I'm actually pretty proud of what I've designed, and I'd like to thank everyone in this thread for their suggestions. It certainly was a massive help in redesigning my Stage 1. Now I'm on my way to redesigning my Stage 2 bootloader.
KoiOS: https://github.com/GabrielRRussell/KoiOS

Code: Select all

#define CURRENT_YEAR 2014 // Change this each year!
Post Reply