Hi,

On some boards, like the AsRock K7S41GX, Grub fails to boot from superfloppy fat32 formated usb sticks.

The reason for the boot failure is that the bios of the mentioned board replaces byte 0x24 of the bpb with the value 0x00 when it's read through the bios function. In fat16 this byte contains the Disc unit number, so this causes no real harm there. In fat32 this byte is part of the sectors per FAT information, so by modifying this value the bios makes Grub unable to read the fat system.

The attached workaround reads the backup bpb information from the fat32 filesystem and uses the sectors per fat information stored there.


--- ../grub2-upstream/grub2-upstream/grub-core/fs/fat.c 2010-09-21 
12:13:17.154835710 +0200
+++ grub2-merge/grub-core/fs/fat.c      2010-09-22 10:23:27.935482451 +0200
@@ -214,6 +214,29 @@ grub_fat_mount (grub_disk_t disk)
                            ? grub_le_to_cpu16 (bpb.sectors_per_fat_16)
                            : grub_le_to_cpu32 
(bpb.version_specific.fat32.sectors_per_fat_32))
                           << data->logical_sector_bits);
+  if (bpb.sectors_per_fat_16)
+    data->sectors_per_fat = grub_le_to_cpu16 (bpb.sectors_per_fat_16) << 
data->logical_sector_bits;
+  else
+    {
+      /* Workaround for buggy BIOSes which replace offset 0x24 in the bpb 
+         with the drive number. This offset is part of sectors_per_fat_32 in
+         the fat32 structure. 
+         We read the backup bpb (if available) and use the value there */
+      struct grub_fat_bpb backup_bpb;
+      grub_uint32_t backup_bpb_address = grub_le_to_cpu16 
(bpb.version_specific.fat32.backup_boot_sector) << data->logical_sector_bits;
+      if (bpb.version_specific.fat32.backup_boot_sector && 
+         (! grub_disk_read (disk,
+                            backup_bpb_address,
+                            0,
+                            sizeof (backup_bpb),
+                            &backup_bpb)))
+       data->sectors_per_fat = grub_le_to_cpu32 
(backup_bpb.version_specific.fat32.sectors_per_fat_32) << 
data->logical_sector_bits;
+
+      if (data->sectors_per_fat == 0)
+       data->sectors_per_fat = grub_le_to_cpu32 
(bpb.version_specific.fat32.sectors_per_fat_32) << data->logical_sector_bits;
+    }
+
+
   if (data->sectors_per_fat == 0)
     goto fail;
 
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to