In accord with the El Torito specification[1], SeaBIOS now signals failure (AH=1 and CF) whenever attempts are made to terminate disk emulation (0x4B) for non-emulated drives. The prior behavior of always returning success caused the Solaris 9 Device Configuration Assistant (DCA) diskette (d1_image) to fail to boot as it was unable to access the non-existent underlying drive.
References:
[1]: "CF - Clear if system released CF - Set if system not in emulation mode"
C. E. Stevens and S. Merkin, '"El Torito" Bootable CD-ROM Format Specification', Phoenix Technologies and IBM, 1994, p. 17.
Signed-off-by: Lev Kujawski lkujaw@member.fsf.org --- src/disk.c | 82 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 36 deletions(-)
diff --git a/src/disk.c b/src/disk.c index 14a99db..6a25015 100644 --- a/src/disk.c +++ b/src/disk.c @@ -568,6 +568,33 @@ disk_1349(struct bregs *regs, struct drive_s *drive_fl) regs->ah = DISK_RET_ECHANGED; }
+// El Torito - Terminate disk emulation +static void +disk_134b(struct bregs *regs, struct drive_s *drive_fl) +{ + if (CONFIG_CDROM_BOOT && regs->dl == GET_LOW(CDEmu.emulated_drive)) { + if ((regs->dl >= EXTSTART_CD) || + (CONFIG_CDROM_EMU && GET_LOW(CDEmu.media))) + { + memcpy_far(regs->ds, (void*)(regs->si+0), + SEG_LOW, &CDEmu, sizeof(CDEmu)); + + // If we have to terminate emulation + if (regs->al == 0x00) { + // FIXME ElTorito Various. Should be handled accordingly to spec + SET_LOW(CDEmu.media, 0x00); // bye bye + + // XXX - update floppy/hd count. + } + + disk_ret(regs, DISK_RET_SUCCESS); + return; + } + } + + disk_ret(regs, DISK_RET_EPARAM); +} + static void disk_134e01(struct bregs *regs, struct drive_s *drive_fl) { @@ -650,6 +677,7 @@ disk_13(struct bregs *regs, struct drive_s *drive_fl) case 0x47: disk_1347(regs, drive_fl); break; case 0x48: disk_1348(regs, drive_fl); break; case 0x49: disk_1349(regs, drive_fl); break; + case 0x4b: disk_134b(regs, drive_fl); break; case 0x4e: disk_134e(regs, drive_fl); break; default: disk_13XX(regs, drive_fl); break; } @@ -675,23 +703,6 @@ floppy_13(struct bregs *regs, struct drive_s *drive_fl) } }
-// ElTorito - Terminate disk emu -static void -cdemu_134b(struct bregs *regs) -{ - memcpy_far(regs->ds, (void*)(regs->si+0), SEG_LOW, &CDEmu, sizeof(CDEmu)); - - // If we have to terminate emulation - if (regs->al == 0x00) { - // FIXME ElTorito Various. Should be handled accordingly to spec - SET_LOW(CDEmu.media, 0x00); // bye bye - - // XXX - update floppy/hd count. - } - - disk_ret(regs, DISK_RET_SUCCESS); -} -
/**************************************************************** * Entry points @@ -743,27 +754,26 @@ handle_13(struct bregs *regs) debug_enter(regs, DEBUG_HDL_13); u8 extdrive = regs->dl;
- if (CONFIG_CDROM_EMU) { - if (regs->ah == 0x4b) { - cdemu_134b(regs); - return; - } - if (GET_LOW(CDEmu.media)) { - u8 emudrive = GET_LOW(CDEmu.emulated_drive); - if (extdrive == emudrive) { - // Access to an emulated drive. - struct drive_s *cdemu_gf = GET_GLOBAL(cdemu_drive_gf); - if (regs->ah > 0x16) { - // Only old-style commands supported. - disk_13XX(regs, cdemu_gf); - return; - } + if (CONFIG_CDROM_EMU && GET_LOW(CDEmu.media)) { + const u8 emudrive = GET_LOW(CDEmu.emulated_drive); + + if (extdrive == emudrive) { + // Access to an emulated drive. + struct drive_s *cdemu_gf = GET_GLOBAL(cdemu_drive_gf); + + if (regs->ah <= 0x16 || regs->ah == 0x4b) { disk_13(regs, cdemu_gf); - return; + } else { + // Only old-style commands supported. + disk_13XX(regs, cdemu_gf); } - if (extdrive < EXTSTART_CD && ((emudrive ^ extdrive) & 0x80) == 0) - // Adjust id to make room for emulated drive. - extdrive--; + + return; + } + + if (extdrive < EXTSTART_CD && ((emudrive ^ extdrive) & 0x80) == 0) { + // Adjust id to make room for emulated drive. + extdrive--; } } handle_legacy_disk(regs, extdrive);