Don't overwrite %dl with a (potentially) modified drive number if we
[people/sha0/gpxe.git] / src / arch / i386 / interface / pcbios / int13.c
index a4563a0..f7cb679 100644 (file)
@@ -317,38 +317,6 @@ static int int13_get_extended_parameters ( struct int13_drive *drive,
        return 0;
 }
 
-struct int13_cdrom_specification {
-       /** Size of packet in bytes */
-       uint8_t size;
-       /** Boot media type */
-       uint8_t media_type;
-       /** Drive number */
-       uint8_t drive;
-};
-
-/**
- * INT 13, 4b - Get CD-ROM status / terminate emulation
- *
- * @v drive            Emulated drive
- * @v ds:si            El Torito specification packet to fill in
- * @ret status         Status code
- */
-static int int13_cdrom_status_terminate ( struct int13_drive *drive,
-                                         struct i386_all_regs *ix86 ) {
-       struct int13_cdrom_specification specification;
-
-       DBG ( "Get CD-ROM emulation parameters to %04x:%04x\n",
-             ix86->segs.ds, ix86->regs.di );
-
-       memset ( &specification, 0, sizeof ( specification ) );
-       specification.size = sizeof ( specification );
-       specification.drive = drive->drive;
-
-       copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
-                      sizeof ( specification ) );
-       return 0;
-}
-
 /**
  * INT 13 handler
  *
@@ -401,9 +369,6 @@ static void int13 ( struct i386_all_regs *ix86 ) {
                case INT13_GET_EXTENDED_PARAMETERS:
                        status = int13_get_extended_parameters ( drive, ix86 );
                        break;
-               case INT13_CDROM_STATUS_TERMINATE:
-                       status = int13_cdrom_status_terminate ( drive, ix86 );
-                       break;
                default:
                        DBG ( "*** Unrecognised INT 13 ***\n" );
                        status = -INT13_STATUS_INVALID;
@@ -425,7 +390,7 @@ static void int13 ( struct i386_all_regs *ix86 ) {
                /* Set OF to indicate to wrapper not to chain this call */
                ix86->flags |= OF;
 
-               break;
+               return;
        }
 
        /* Remap BIOS drive */
@@ -466,23 +431,28 @@ static void hook_int13 ( void ) {
                             /* Overwrite flags for iret */
                             "pushfw\n\t"
                             "popw 6(%%bp)\n\t"
-                            /* Restore %dl (except for %ah=0x08 or 0x15) */
-                            "cmpb $0x08, -1(%%bp)\n\t"
-
-                            "jne 7f\n\t"
-                            "movb $2, %%dl\n\t"
-                            "jmp 2f\n\t"
-                            "\n7:\n\t"
-
-                            "je 2f\n\t"
+                            /* Fix up %dl:
+                             *
+                             * INT 13,15 : do nothing
+                             * INT 13,08 : load with number of drives
+                             * all others: restore original value
+                             */
                             "cmpb $0x15, -1(%%bp)\n\t"
                             "je 2f\n\t"
                             "movb -4(%%bp), %%dl\n\t"
-                            "\n2:\n\t"
+                            "cmpb $0x08, -1(%%bp)\n\t"
+                            "jne 2f\n\t"
+                            "pushw %%ds\n\t"
+                            "pushw %1\n\t"
+                            "popw %%ds\n\t"
+                            "movb %c2, %%dl\n\t"
+                            "popw %%ds\n\t"
                             /* Return */
+                            "\n2:\n\t"
                             "movw %%bp, %%sp\n\t"
                             "popw %%bp\n\t"
-                            "iret\n\t" ) : : "i" ( int13 ) );
+                            "iret\n\t" )
+              : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) );
 
        hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
                              &int13_vector );
@@ -575,11 +545,9 @@ void register_int13_drive ( struct int13_drive *drive ) {
        get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
        if ( ! drive->drive )
                drive->drive = ( num_drives | 0x80 );
+       num_drives++;
        if ( num_drives <= ( drive->drive & 0x7f ) )
                num_drives = ( ( drive->drive & 0x7f ) + 1 );
-
-       num_drives = 2;
-
        put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
 
        DBG ( "Registered INT13 drive %02x with C/H/S geometry %d/%d/%d\n",
@@ -607,6 +575,10 @@ void unregister_int13_drive ( struct int13_drive *drive ) {
        /* Remove from list of emulated drives */
        list_del ( &drive->list );
 
+       /* Should adjust BIOS drive count, but it's difficult to do so
+        * reliably.
+        */
+
        DBG ( "Unregistered INT13 drive %02x\n", drive->drive );
 
        /* Unhook INT 13 vector if no more drives */
@@ -639,6 +611,7 @@ int int13_boot ( unsigned int drive ) {
                                           "pushw $0\n\t"
                                           "popw %%es\n\t"
                                           "stc\n\t"
+                                          "sti\n\t"
                                           "int $0x13\n\t"
                                           "sti\n\t" /* BIOS bugs */
                                           "jc 1f\n\t"