* [Qemu-devel] [PATCH] bios and win98 cd boot
@ 2005-01-23 15:51 Magnus Damm
0 siblings, 0 replies; only message in thread
From: Magnus Damm @ 2005-01-23 15:51 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1154 bytes --]
Hello,
This patch makes it possible to install win98 from cdrom. Without the
patch the installer would ask the user to insert the installation cd
even though that cd is present. The workaround has been booting from
floppy.
The actual bug that is fixed is the int 13h eltorito code that without
this patch decrements the DL register and returns the modified DL
value back to the caller, but with the patch the DL value is
incremented internally and never exposed to the caller. This fix
required some rearranging of the code and resulted in a small cleanup.
People interested in the win98 installer and this problem should
objdump D:\WIN98\OEMSETUP.EXE and search for int...
I have tested the patch on a x86 host by installing win98 from cdrom
and booting xp sp2 from cdrom, together with booting of two linux live
cd:s. It is also still possible to install win95 from floppy and
cdrom. I do not have access to bootable win98se/winme/win2k isos, feel
free to test and report back!
And yeah, with some fuzz the patch applies to both rombios.c version
1.125 and the qemu-patched 1.110. This patch should of course be
pushed upstream to bochs.
/ magnus
[-- Attachment #2: rombios-eltorito.patch --]
[-- Type: text/x-patch, Size: 13220 bytes --]
--- rombios.c.1.110-qemu 2005-01-22 17:36:35.000000000 +0100
+++ rombios.c 2005-01-23 16:07:51.347091872 +0100
@@ -1008,6 +1008,8 @@
#define GET_CH() ( CX >> 8 )
#define GET_DH() ( DX >> 8 )
+#define GET_ELDL() ( ELDX & 0x00ff )
+#define GET_ELDH() ( ELDX >> 8 )
#define SET_CF() FLAGS |= 0x0001
#define CLEAR_CF() FLAGS &= 0xfffe
@@ -4437,8 +4439,8 @@
#if BX_USE_ATADRV
void
-int13_harddisk(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS;
+int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit32u lba;
Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -4453,17 +4455,17 @@
write_byte(0x0040, 0x008e, 0); // clear completion flag
// basic check : device has to be defined
- if ( (GET_DL() < 0x80) || (GET_DL() >= 0x80 + BX_MAX_ATA_DEVICES) ) {
- BX_INFO("int13_harddisk: function %02x, DL out of range %02x\n", GET_AH(), GET_DL());
+ if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) {
+ BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
goto int13_fail;
}
// Get the ata channel
- device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_DL()-0x80]);
+ device=read_byte(ebda_seg,&EbdaData->ata.hdidmap[GET_ELDL()-0x80]);
// basic check : device has to be valid
if (device >= BX_MAX_ATA_DEVICES) {
- BX_INFO("int13_harddisk: function %02x, unmapped device for DL=%02x\n", GET_AH(), GET_DL());
+ BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
goto int13_fail;
}
@@ -4832,10 +4834,8 @@
// ---------------------------------------------------------------------------
void
-int13_cdrom(DI, DIH, SI, SIH, BP, BPH, SP, SPH, BX, BXH, DX, DXH, CX, CXH, AX, AXH,
- DS, ES, FLAGS)
- Bit16u DI, DIH, SI, SIH, BP, BPH, SP, SPH, BX, BXH, DX, DXH, CX, CXH, AX, AXH,
- DS, ES, FLAGS;
+int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit8u device, status, locks;
@@ -4849,17 +4849,17 @@
SET_DISK_RET_STATUS(0x00);
/* basic check : device should be 0xE0+ */
- if( (GET_DL() < 0xE0) || (GET_DL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
- BX_INFO("int13_cdrom: function %02x, DL out of range %02x\n", GET_AH(), GET_DL());
+ if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) {
+ BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL());
goto int13_fail;
}
// Get the ata channel
- device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_DL()-0xE0]);
+ device=read_byte(ebda_seg,&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]);
/* basic check : device has to be valid */
if (device >= BX_MAX_ATA_DEVICES) {
- BX_INFO("int13_cdrom: function %02x, unmapped device for DL=%02x\n", GET_AH(), GET_DL());
+ BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL());
goto int13_fail;
}
@@ -5189,8 +5189,8 @@
// ---------------------------------------------------------------------------
void
-int13_eltorito(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS;
+int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
@@ -5259,8 +5259,8 @@
// ---------------------------------------------------------------------------
void
-int13_cdemu(DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS;
+int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit16u ebda_seg=read_word(0x0040,0x000E);
Bit8u device, status;
@@ -5511,8 +5511,8 @@
}
void
-int13_harddisk(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS;
+int13_harddisk(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit8u drive, num_sectors, sector, head, status, mod;
Bit8u drive_map;
@@ -5545,7 +5545,7 @@
n_drives = (drive_map==0) ? 0 :
((drive_map==3) ? 2 : 1);
- if (!(drive_map & (1<<(GET_DL()&0x7f)))) { /* allow 0, 1, or 2 disks */
+ if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */
SET_AH(0x01);
SET_DISK_RET_STATUS(0x01);
SET_CF(); /* error occurred */
@@ -5579,7 +5579,7 @@
case 0x04: // verify disk sectors
case 0x02: // read disk sectors
- drive = GET_DL();
+ drive = GET_ELDL();
get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
num_sectors = GET_AL();
@@ -5725,7 +5725,7 @@
case 0x03: /* write disk sectors */
BX_DEBUG_INT13_HD("int13_f03\n");
- drive = GET_DL ();
+ drive = GET_ELDL ();
get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
num_sectors = GET_AL();
@@ -5779,13 +5779,13 @@
/* activate LBA? (tomv) */
if (hd_heads > 16) {
BX_DEBUG_INT13_HD("CHS (write): %x %x %x\n", cylinder, head, sector);
- outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_DL());
+ outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_ELDL());
}
else {
outb(0x01f3, sector);
outb(0x01f4, cylinder & 0x00ff);
outb(0x01f5, cylinder >> 8);
- outb(0x01f6, 0xa0 | ((GET_DL() & 0x01)<<4) | (head & 0x0f));
+ outb(0x01f6, 0xa0 | ((GET_ELDL() & 0x01)<<4) | (head & 0x0f));
}
outb(0x01f7, 0x30);
@@ -5875,7 +5875,7 @@
case 0x08: /* read disk drive parameters */
BX_DEBUG_INT13_HD("int13_f08\n");
- drive = GET_DL ();
+ drive = GET_ELDL ();
get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
// translate CHS
@@ -5989,7 +5989,7 @@
break;
case 0x15: /* read disk drive size */
- drive = GET_DL();
+ drive = GET_ELDL();
get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors);
ASM_START
push bp
@@ -6318,8 +6318,8 @@
#if BX_SUPPORT_FLOPPY
void
-int13_diskette_function(DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS;
+int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit8u drive, num_sectors, track, sector, head, status;
Bit16u base_address, base_count, base_es;
@@ -6336,7 +6336,7 @@
switch ( ah ) {
case 0x00: // diskette controller reset
BX_DEBUG_INT13_FL("floppy f00\n");
- drive = GET_DL();
+ drive = GET_ELDL();
if (drive > 1) {
SET_AH(1); // invalid param
set_diskette_ret_status(1);
@@ -6377,7 +6377,7 @@
track = GET_CH();
sector = GET_CL();
head = GET_DH();
- drive = GET_DL();
+ drive = GET_ELDL();
if ( (drive > 1) || (head > 1) ||
(num_sectors == 0) || (num_sectors > 72) ) {
@@ -6735,7 +6735,7 @@
num_sectors = GET_AL();
track = GET_CH();
head = GET_DH();
- drive = GET_DL();
+ drive = GET_ELDL();
if ((drive > 1) || (head > 1) || (track > 79) ||
(num_sectors == 0) || (num_sectors > 18)) {
@@ -6889,7 +6889,7 @@
case 0x08: // read diskette drive parameters
BX_DEBUG_INT13_FL("floppy f08\n");
- drive = GET_DL();
+ drive = GET_ELDL();
if (drive > 1) {
AX = 0;
@@ -6981,7 +6981,7 @@
case 0x15: // read diskette drive type
BX_DEBUG_INT13_FL("floppy f15\n");
- drive = GET_DL();
+ drive = GET_ELDL();
if (drive > 1) {
SET_AH(0); // only 2 drives supported
// set_diskette_ret_status here ???
@@ -7002,16 +7002,11 @@
SET_AH(1); // drive present, does not support change line
}
-#if BX_ELTORITO_BOOT
- // This is mandatory. Otherwise Win98 does not boot
- if ((cdemu_isactive() != 00) && (cdemu_emulated_drive() == drive))
- DX+=0x0001;
-#endif
return;
case 0x16: // get diskette change line status
BX_DEBUG_INT13_FL("floppy f16\n");
- drive = GET_DL();
+ drive = GET_ELDL();
if (drive > 1) {
SET_AH(0x01); // invalid drive
set_diskette_ret_status(0x01);
@@ -7052,8 +7047,8 @@
}
#else // #if BX_SUPPORT_FLOPPY
void
-int13_diskette_function(DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS)
- Bit16u DI, SI, BP, SP, BX, DX, CX, AX, ES, FLAGS;
+int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
+ Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
{
Bit8u val8;
@@ -7608,7 +7603,15 @@
jb int13_not_eltorito
cmp ah,#0x4d
ja int13_not_eltorito
- jmp int13_eltorito
+
+ pusha
+ push es
+ push ds
+ push ss
+ pop ds
+
+ push #int13_out
+ jmp _int13_eltorito ;; ELDX not used
int13_not_eltorito:
push ax
@@ -7626,125 +7629,111 @@
pop dx
push dx
cmp al,dl ;; int13 on emulated drive
- je int13_cdemu
+ jne int13_nocdemu
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+
+ pusha
+ push es
+ push ds
+ push ss
+ pop ds
- ;; otherwise
+ push #int13_out
+ jmp _int13_cdemu ;; ELDX not used
+
+int13_nocdemu:
and dl,#0xE0 ;; mask to get device class, including cdroms
cmp al,dl ;; al is 0x00 or 0x80
jne int13_cdemu_inactive ;; inactive for device class
-
-int13_cdemu_active:
+
pop dx
pop cx
pop bx
pop ax
+
+ push ax
+ push cx
+ push dx
+ push bx
+
dec dl ;; real drive is dl - 1
jmp int13_legacy
-
+
int13_cdemu_inactive:
pop dx
pop cx
pop bx
pop ax
-int13_legacy:
-
#endif // BX_ELTORITO_BOOT
- pushf
- test dl, #0x80
- jz int13_floppy
+int13_noeltorito:
-#if BX_USE_ATADRV
+ push ax
+ push cx
+ push dx
+ push bx
-int13_disk_or_cdrom:
- cmp dl, #0xE0
- jae int13_cdrom
+int13_legacy:
-#endif
+ push dx ;; push eltorito value of dx instead of sp
+
+ push bp
+ push si
+ push di
-int13_disk:
- ;; pushf already done
push es
push ds
push ss
pop ds
- pusha
- call _int13_harddisk
- popa
- pop ds
- pop es
- popf
- // JMPL(iret_modify_cf)
- jmp iret_modify_cf
-int13_floppy:
- popf
- // JMPL(int13_diskette)
- jmp int13_diskette
+ ;; now the 16-bit registers can be restored with:
+ ;; pop ds; pop es; popa; iret
+ ;; arguments passed to functions should be
+ ;; DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS
+
+ test dl, #0x80
+ jnz int13_notfloppy
+ push #int13_out
+ jmp _int13_diskette_function
+
+int13_notfloppy:
#if BX_USE_ATADRV
-int13_cdrom:
- ;; pushf already done
- ;; popf
- ;; pushf
- push es
- push ds
- push ss
- pop ds
- // ebx is modified: BSD 5.2.1 boot loader problem, so we save all
- // the 32 bit registers. It should be done in all the bios or no 32
- // bit register should be used without saving it first.
- pushad
+
+ cmp dl, #0xE0
+ jb int13_notcdrom
+
+ // ebx is modified: BSD 5.2.1 boot loader problem
+ // someone should figure out which 32 bit register that actually are used
+
+ shr ebx, #16
+ push bx
+
call _int13_cdrom
- popad
- pop ds
- pop es
- popf
-
- // JMPL(iret_modify_cf)
- jmp iret_modify_cf
-#endif
-#if BX_ELTORITO_BOOT
-int13_cdemu:
- pop dx
- pop cx
pop bx
- pop ax
+ shl ebx, #16
- push ds
- push ss
- pop ds
+ jmp int13_out
- pushf
- push es
- pusha
- call _int13_cdemu
- popa
- pop es
- popf
+int13_notcdrom:
- pop ds
- jmp iret_modify_cf
+#endif
-int13_eltorito:
+int13_disk:
+ call _int13_harddisk
- pushf
- push es
- push ds
- push ss
- pop ds
- pusha
- call _int13_eltorito
+int13_out:
+ pop ds
+ pop es
popa
- pop ds
- pop es
- popf
-
- jmp iret_modify_cf
-#endif
+ iret
;----------
@@ -9400,46 +9389,7 @@
;----------------------------------------
.org 0xec59
int13_diskette:
- pushf
- push es
- pusha
- call _int13_diskette_function
- popa
- pop es
- popf
- //JMPL(iret_modify_cf)
- jmp iret_modify_cf
-
-#if 0
- pushf
- cmp ah, #0x01
- je i13d_f01
-
- ;; pushf already done
- push es
- pusha
- call _int13_diskette_function
- popa
- pop es
- popf
- //JMPL(iret_modify_cf)
- jmp iret_modify_cf
-i13d_f01:
- popf
- push ds
- push bx
- mov bx, #0x0000
- mov ds, bx
- mov ah, 0x0441
- pop bx
- pop ds
- clc
- ;; ??? dont know if this service changes the return status
- //JMPL(iret_modify_cf)
- jmp iret_modify_cf
-#endif
-
-
+ jmp int13_noeltorito
;---------------------------------------------
;- INT 0Eh Diskette Hardware ISR Entry Point -
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2005-01-23 16:29 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-23 15:51 [Qemu-devel] [PATCH] bios and win98 cd boot Magnus Damm
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.