By default SeaBIOS can map up to 2 hard disks, and more hard disks beyond
2 will be rejected. This restriction is caused by limited BDA slots.
This patch added support for mapping more than 2 hard disks by dynamically
mapping the hard disk right before we're about to boot the hard disk.

Signed-off-by: Bin Gao <gao...@amazon.com>
---
 src/Kconfig |  8 ++++++++
 src/block.c | 17 ++++++++++++++++-
 src/boot.c  | 14 +++++++++++---
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 3a8ffa1..d6031e2 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -380,6 +380,14 @@ menu "BIOS interfaces"
         help
             Support int13 disk/floppy drive functions.
 
+    config DYNAMIC_MAP_HD
+        depends on DRIVES
+        bool "Dynamically map hard drives"
+        default n
+        help
+            Support dynamically map hard drives so that the boot logic can
+            support more than 2 hard drives.
+
     config CDROM_BOOT
         depends on DRIVES
         bool "DVD/CDROM booting"
diff --git a/src/block.c b/src/block.c
index 1f600b8..904e5f4 100644
--- a/src/block.c
+++ b/src/block.c
@@ -253,6 +253,10 @@ add_drive(struct drive_s **idmap, u8 *count, struct 
drive_s *drive)
 }
 
 // Map a hard drive
+//
+// By default SeaBIOS can map up to 2 hard disks, and more hard disks beyond
+// 2 will be rejected. This restriction is caused by limited BDA slots.
+// To support more than 2 hard drives, we need to enable CONFIG_DYNAMIC_MAP_HD.
 void
 map_hd_drive(struct drive_s *drive)
 {
@@ -260,7 +264,18 @@ map_hd_drive(struct drive_s *drive)
     struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
     int hdid = bda->hdcount;
     dprintf(3, "Mapping hd drive %p to %d\n", drive, hdid);
-    add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive);
+    // To implement dynamic hard drive maping, we constantly keep
+    // bda->hdcount = 1, and use hdid = 0 all the times.
+    // map_hd_drive() must be called each time before boot to a
+    // specific hard drive.
+    if (CONFIG_DYNAMIC_MAP_HD) {
+        hdid = 0; // 0 - always the first hard drive
+        u8 tmp = 0;
+        add_drive(IDMap[EXTTYPE_HD], &tmp, drive);
+        bda->hdcount = 1;
+    } else {
+        add_drive(IDMap[EXTTYPE_HD], &bda->hdcount, drive);
+    }
 
     // Setup disk geometry translation.
     setup_translation(drive);
diff --git a/src/boot.c b/src/boot.c
index 1effd80..2e6e356 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -802,7 +802,7 @@ static int HaveHDBoot, HaveFDBoot;
 static void
 add_bev(int type, u32 vector)
 {
-    if (type == IPL_TYPE_HARDDISK && HaveHDBoot++)
+    if (type == IPL_TYPE_HARDDISK && HaveHDBoot++ && !CONFIG_DYNAMIC_MAP_HD)
         return;
     if (type == IPL_TYPE_FLOPPY && HaveFDBoot++)
         return;
@@ -837,8 +837,14 @@ bcv_prepboot(void)
             add_bev(IPL_TYPE_FLOPPY, 0);
             break;
         case IPL_TYPE_HARDDISK:
-            map_hd_drive(pos->drive);
-            add_bev(IPL_TYPE_HARDDISK, 0);
+            if (CONFIG_DYNAMIC_MAP_HD) {
+                // Pass the drive_s pointer to bev_s struct so that
+                // we can do dynamic hard disk map in do_boot().
+                add_bev(IPL_TYPE_HARDDISK, (u32)pos->drive);
+            } else {
+                map_hd_drive(pos->drive);
+                add_bev(IPL_TYPE_HARDDISK, 0);
+            }
             break;
         case IPL_TYPE_CDROM:
             map_cd_drive(pos->drive);
@@ -998,6 +1004,8 @@ do_boot(int seq_nr)
         break;
     case IPL_TYPE_HARDDISK:
         printf("Booting from Hard Disk...\n");
+        if (CONFIG_DYNAMIC_MAP_HD)
+            map_hd_drive((struct drive_s *)ie->vector);
         boot_disk(0x80, 1);
         break;
     case IPL_TYPE_CDROM:
-- 
2.17.1
_______________________________________________
SeaBIOS mailing list -- seabios@seabios.org
To unsubscribe send an email to seabios-le...@seabios.org

Reply via email to