From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1CskcC-0001IN-Kc for qemu-devel@nongnu.org; Sun, 23 Jan 2005 11:29:28 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1CskcB-0001Hk-Ev for qemu-devel@nongnu.org; Sun, 23 Jan 2005 11:29:28 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Cskbb-0000pC-Mz for qemu-devel@nongnu.org; Sun, 23 Jan 2005 11:28:51 -0500 Received: from [64.233.184.204] (helo=wproxy.gmail.com) by monty-python.gnu.org with esmtp (Exim 4.34) id 1Csk1P-0007qM-Ld for qemu-devel@nongnu.org; Sun, 23 Jan 2005 10:51:27 -0500 Received: by wproxy.gmail.com with SMTP id 63so263321wri for ; Sun, 23 Jan 2005 07:51:26 -0800 (PST) Message-ID: Date: Sun, 23 Jan 2005 16:51:26 +0100 From: Magnus Damm Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="----=_Part_2526_6772424.1106495486702" Subject: [Qemu-devel] [PATCH] bios and win98 cd boot Reply-To: Magnus Damm , qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org ------=_Part_2526_6772424.1106495486702 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Disposition: inline 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 ------=_Part_2526_6772424.1106495486702 Content-Type: text/x-patch; name=rombios-eltorito.patch; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="rombios-eltorito.patch" --- 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 - ------=_Part_2526_6772424.1106495486702--