On Thu, Dec 31, 2020 at 07:08:26PM -0800, Bin Gao wrote:
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);
This is not valid. Once we start the boot phase (via INT19), it's not valid to change the hard drive mappings. Once we invoke INT19, it's possible for external code to alter memory - including any temporary storage that SeaBIOS allocated during the post phase. Indeed, on normal QEMU the memory holding the active drives is marked as read-only after the POST phase. Also, external code can invoke the SeaBIOS int19 handler multiple times.
In accordance with the "BIOS Boot Specification", SeaBIOS does all its setup in the POST phase, and then just starts the boot process in the "BOOT phase".
-Kevin