Monday, June 2, 2014

Where is GRUB2 on my disk anyways?

Preparing our client PC system for imaging before Fall semester, we ran into another problem.  The imaging system we use, FOG, recently made some updates to support GRUB2.  This was welcome news, in years past we have had to downgrade to grub-legacy to get the dual boot system working after imaging.  Initial tests produced booting systems.  However, we started having boot problems very soon after that.  It looked like GRUB2 was using the disk differently in our production case than in our test case.

In order to understand and fix the problem, I spent a while with "the google", trying to understand how GRUB2 puts itself onto the disk.  After a lot of time reading several different websites, including GNU's GRUB page, the Wikipedia GRUB article, and ArchLinux's GRUB page, I was learning, but not enough.  I downloaded the source for GRUB2, got psyched up to read some detailed assembly, then found a great post by someone who already had done it.

Here is a summary of what I learned, regarding the placement of GRUB2 on MBR partitioned disks.  The assumption here is that GRUB is installed in the MBR of the disk.

Grub puts the "boot.img" into the MBR.  This is ~440 bytes of boot code that only know enough to load and jump to the first sector (512 bytes) of the "core.img".  So, in this code, there is stored the disk location of 1 sector.  This code is generic, so it can load from anywhere on the disk.  If you really want to know that location, you can reverse engineer but dumping the bytes of your MBR and finding it.  However, this is usually stored in the "embedding area".  This is the set of unused sectors after the MBR and before the first partition.

The first sector of the "core.img" is the "diskboot.img" file.  This code has the responsibility of loading the rest of "core.img" into memory and jumping to it.  Part of the "diskboot.img" sector is a list of sector collections to load, and the order to load them.  Each collection has a beginning sector and a number of sectors to load.  Again, if you want to reverse engineer, you can dump these data from the end of the block and see the location and size of each collection.  These collections are usually also in the "embedding area".

After "core.img" is loaded, it has enough information and code to use the linux file system, instead of using block access.  It loads the GRUB configuration file, and any other GRUB modules necessary to do its job.  These files are usually stored in "/boot/grub".  The beauty of this system, is that you can have rather large amounts of data for GRUB, and you don't have to re-write the bootloader if the files are moved within the file system's data blocks.  Again, the actual location is configurable and can be found from dumping the on-disk copy of "core.img", if you really need to.

OK, for our setup, the problem turned out to be the size of the "embedding area".  FOG assumed it to be 62 sectors in size, and always captured and restored those sectors.  BTW, the Wikipedia article, and most of the online documentation supports that idea.

After using dd and od to examine the contents of "diskboot.img" on my system, I saw that the total size of "core.img" was closer to 100 sectors, but it was stored in the "embedding area".  After wondering how that could work without wiping out the first partition's data, I used sfdisk -d to examine the actual location of the first partition.  It started at sector 2048, not sector 64.  There was plenty of room.

After making minor changes to FOG's scripts, it saves the entire "embedding area", and restores it again.  Presto!  GRUB2 is imaged just fine.

It turns out that Windows 7 puts the first partition 1MB=2048sectors into the disk, making for a larger "embedding area".  However, an Ubuntu only system will put the first partition at sector 64.  GRUB2 is smart enough to know how much space is available.  It puts enough into "core.img" to mount and load the rest.  But it might put more in "core.img" if there is more space.

The initial tests with FOG were Ubuntu only, so the 62 sector "core.img" assumption worked great.  Our production, dual-boot systems we install Windows 7, then Ubuntu, so Windows can be happily in the first 2 partitions.  These weren't working, because we were only copying the first 62 of ~100 sectors.

Thanks again to the FOG developers and support staff, the GNU project, especially the GRUB developers, and the producers of the website that finally gave the information I needed to understand my problem.



No comments:

Post a Comment