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 gaobin@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: