All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.