|
@@ -355,12 +355,18 @@ static int int13_cdrom_status_terminate ( struct int13_drive *drive,
|
355
|
355
|
*/
|
356
|
356
|
static void int13 ( struct i386_all_regs *ix86 ) {
|
357
|
357
|
int command = ix86->regs.ah;
|
|
358
|
+ unsigned int bios_drive = ix86->regs.dl;
|
|
359
|
+ unsigned int original_bios_drive = bios_drive;
|
358
|
360
|
struct int13_drive *drive;
|
359
|
361
|
int status;
|
360
|
362
|
|
361
|
363
|
list_for_each_entry ( drive, &drives, list ) {
|
362
|
|
- if ( drive->drive != ix86->regs.dl )
|
|
364
|
+ if ( drive->drive > bios_drive )
|
363
|
365
|
continue;
|
|
366
|
+ if ( drive->drive < bios_drive ) {
|
|
367
|
+ original_bios_drive--;
|
|
368
|
+ continue;
|
|
369
|
+ }
|
364
|
370
|
|
365
|
371
|
DBG ( "INT 13,%04x (%02x): ", ix86->regs.ax, drive->drive );
|
366
|
372
|
|
|
@@ -421,6 +427,13 @@ static void int13 ( struct i386_all_regs *ix86 ) {
|
421
|
427
|
|
422
|
428
|
break;
|
423
|
429
|
}
|
|
430
|
+
|
|
431
|
+ /* Remap BIOS drive */
|
|
432
|
+ if ( bios_drive != original_bios_drive ) {
|
|
433
|
+ DBG ( "INT 13,%04x (%02x) remapped to (%02x)\n",
|
|
434
|
+ ix86->regs.ax, bios_drive, original_bios_drive );
|
|
435
|
+ }
|
|
436
|
+ ix86->regs.dl = original_bios_drive;
|
424
|
437
|
}
|
425
|
438
|
|
426
|
439
|
/**
|
|
@@ -434,19 +447,42 @@ static void hook_int13 ( void ) {
|
434
|
447
|
*/
|
435
|
448
|
__asm__ __volatile__ (
|
436
|
449
|
TEXT16_CODE ( "\nint13_wrapper:\n\t"
|
437
|
|
- "orb $0, %%al\n\t" /* clear OF */
|
|
450
|
+ /* Preserve %ax and %dx for future reference */
|
|
451
|
+ "pushw %%bp\n\t"
|
|
452
|
+ "movw %%sp, %%bp\n\t"
|
|
453
|
+ "pushw %%ax\n\t"
|
|
454
|
+ "pushw %%dx\n\t"
|
|
455
|
+ /* Clear OF, set CF, call int13() */
|
|
456
|
+ "orb $0, %%al\n\t"
|
438
|
457
|
"stc\n\t"
|
439
|
|
- "pushl %0\n\t" /* call int13() */
|
|
458
|
+ "pushl %0\n\t"
|
440
|
459
|
"pushw %%cs\n\t"
|
441
|
460
|
"call prot_call\n\t"
|
442
|
|
- "jo 1f\n\t" /* chain if OF not set */
|
|
461
|
+ /* Chain if OF not set */
|
|
462
|
+ "jo 1f\n\t"
|
443
|
463
|
"pushfw\n\t"
|
444
|
464
|
"lcall *%%cs:int13_vector\n\t"
|
445
|
465
|
"\n1:\n\t"
|
446
|
|
- "call 2f\n\t" /* return with flags intact */
|
447
|
|
- "lret $2\n\t"
|
|
466
|
+ /* Overwrite flags for iret */
|
|
467
|
+ "pushfw\n\t"
|
|
468
|
+ "popw 6(%%bp)\n\t"
|
|
469
|
+ /* Restore %dl (except for %ah=0x08 or 0x15) */
|
|
470
|
+ "cmpb $0x08, -1(%%bp)\n\t"
|
|
471
|
+
|
|
472
|
+ "jne 7f\n\t"
|
|
473
|
+ "movb $2, %%dl\n\t"
|
|
474
|
+ "jmp 2f\n\t"
|
|
475
|
+ "\n7:\n\t"
|
|
476
|
+
|
|
477
|
+ "je 2f\n\t"
|
|
478
|
+ "cmpb $0x15, -1(%%bp)\n\t"
|
|
479
|
+ "je 2f\n\t"
|
|
480
|
+ "movb -4(%%bp), %%dl\n\t"
|
448
|
481
|
"\n2:\n\t"
|
449
|
|
- "ret $4\n\t" ) : : "i" ( int13 ) );
|
|
482
|
+ /* Return */
|
|
483
|
+ "movw %%bp, %%sp\n\t"
|
|
484
|
+ "popw %%bp\n\t"
|
|
485
|
+ "iret\n\t" ) : : "i" ( int13 ) );
|
450
|
486
|
|
451
|
487
|
hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
|
452
|
488
|
&int13_vector );
|
|
@@ -541,6 +577,9 @@ void register_int13_drive ( struct int13_drive *drive ) {
|
541
|
577
|
drive->drive = ( num_drives | 0x80 );
|
542
|
578
|
if ( num_drives <= ( drive->drive & 0x7f ) )
|
543
|
579
|
num_drives = ( ( drive->drive & 0x7f ) + 1 );
|
|
580
|
+
|
|
581
|
+ num_drives = 2;
|
|
582
|
+
|
544
|
583
|
put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
|
545
|
584
|
|
546
|
585
|
DBG ( "Registered INT13 drive %02x with C/H/S geometry %d/%d/%d\n",
|