GRUB boot issue when USB is recognized as a floppy disk

Long story short, on some computers, GRUB cannot boot from USB drive if BIOS of the PC recognizes the USB as a floppy disk, instead of emulating a hard drive. This would cause problems in booting, because when GRUB is installed onto the USB drive under Linux, the USB is recognized as a block device, which would be partitioned and formatted as a hard drive. However, when the PC is booting up, the USB drive is driven by BIOS and it may be recognized as a floppy disk (with a large number of tracks/heads/sectors). When this happens, the bootloader, which uses BIOS disk I/O calls, won't be able to correctly load itself into RAM and boot up the system.

In this scenario, what really prevents booting are two factors:

  1. When the BIOS passed the boot device number to GRUB stage1 (on MBR or VBR) in the x86 register %dl. It passes 00h (fd0), instead of 80h (hd0). In this case, the original grub stage1 code will think that BIOS has messed up, and assign disk 80h to %dl, which will not be recognized by BIOS because now BIOS is expecting disk number 00h for the USB drive. This glitch can be easily patched in stage1 binary.
  2. When BIOS recognizes the USB as a floppy disk, what really happens, is that it emulates a disk device based on the 1st partition on the USB drive, and give it a device number 00h. The numbers of cylinders(tracks) / heads / sectors of the emulated device are based on the partition table entry for the 1st partition. After this mapping, the first logical sector accessible by GRUB is the first sector on the partition, instead of the first sector of the physical drive. When GRUB is using hard-coded sector numbers (akin to LBA, though it may be decomposed into CHS) to load itself from the hard drive, it can't find the right locations. Therefore, one way of fixing it is to subtract the number of sectors before the start of the partition from all hard-coded sector numbers in GRUB. This turns out to be quite manageable too.

Here is my script to patch GRUB on a USB device to make it bootable:
Download grub-usb-check.py (Tested on GNU GRUB 0.97)

An example of the using the script is the following. The "grub-install" command will copy the grub files to the USB disk mounted on /mnt/memstick. The grub commands "root (hd1,0)" and "setup (hd1,0)" will install grub on the boot sectors. Then, at last, the "grub-usb-check.py /dev/sdb" command will check the installation, and ask if you want to modify grub to make the disk bootable when the PC recognizes it as a floppy disk.

Note: it is probably safer to install grub on the volume (partition) instead of the MBR (master boot record) of the physical drive, since BIOS is going to emulate the drive entirely based on the volume.

# grub-install --recheck --root-directory=/mnt/memstick /dev/sdb1
# grub
grub> root (hd1,0)
grub> setup (hd1,0)
 Checking if "/boot/grub/stage1" exists... yes
 Checking if "/boot/grub/stage2" exists... yes
 Checking if "/boot/grub/e2fs_stage1_5" exists... yes
 Running "embed /boot/grub/e2fs_stage1_5 (hd1,0)"... failed (this is not fatal)
 Running "embed /boot/grub/e2fs_stage1_5 (hd1,0)"... failed (this is not fatal)
 Running "install /boot/grub/stage1 (hd1,0) /boot/grub/stage2 p /boot/grub/menu.lst "... succeeded
Done.

grub> quit

# ./grub-usb-check.py /dev/sdb
Partition 0: Cylinder: 0 Head: 1 Sector: 1 Starting sector: 61
GRUB stage1 ok!
Stage1 seeks stage2 at sector 36927
GRUB stage2 ok!
blk 1 (36928,17)
blk 2 (36947,6)
blk 3 (36955,214)
Now GRUB works on USB HD emulation. To make it work on FD emulation, we will need to 
adjust sector numbers by 61
Do you want to fix GRUB (Y/N)? y
Fix NOPs on VBR...
Change stage2 sector number to 36866
Writing VBR file...
Fixing stage2 sector 1 blklists...
Writing stage2 file...
Write the files back to the disk (root/sudo required), Y/N? y

Now the GRUB boot loader has been installed, you can reboot the PC and choose the boot device as the USB drive to test it out. Without the patch done by 'grub-usb-check.py', it may get stuck at the "GRUB" title in this case. But with the patch, GRUB may get past the GRUB title (stage1), shows the progress of loading stage2, and eventually run the whole stage2, and show the "grub> " prompt or the GRUB menu.

If you see any problems, you are welcome to send feedback and questions back to me at Danke Xie <moc.liamg|eix.eknad#moc.liamg|eix.eknad>.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License