Ver código fonte

[int13] Guard against BIOSes that "fix" the drive count

Some BIOSes (observed with an AMI BIOS on a SunFire X2200) seem to
reset the BIOS drive counter at 40:75 after a failed boot attempt.
This causes problems when attempting a Windows direct-to-iSCSI
installation: bootmgr.exe calls INT 13,0800 and gets told that there
are no hard disks, so never bothers to read the MBR in order to obtain
the boot disk signature.  The Windows iSCSI initiator will detect the
iBFT and connect to the target, and everything will appear to work
except for the error message "This computer's hardware may not support
booting to this disk.  Ensure that the disk's controller is enabled in
the computer's BIOS menu."

Fix by checking the BIOS drive counter on every INT 13 call, and
updating it whenever necessary.
tags/v1.0.0-rc1
Michael Brown 14 anos atrás
pai
commit
b515977955
1 arquivos alterados com 48 adições e 6 exclusões
  1. 48
    6
      src/arch/i386/interface/pcbios/int13.c

+ 48
- 6
src/arch/i386/interface/pcbios/int13.c Ver arquivo

51
 /** List of registered emulated drives */
51
 /** List of registered emulated drives */
52
 static LIST_HEAD ( drives );
52
 static LIST_HEAD ( drives );
53
 
53
 
54
+/**
55
+ * Number of BIOS drives
56
+ *
57
+ * Note that this is the number of drives in the system as a whole
58
+ * (i.e. a mirror of the counter at 40:75), rather than a count of the
59
+ * number of emulated drives.
60
+ */
61
+static uint8_t num_drives;
62
+
63
+/**
64
+ * Update BIOS drive count
65
+ */
66
+static void int13_set_num_drives ( void ) {
67
+	struct int13_drive *drive;
68
+
69
+	/* Get current drive count */
70
+	get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
71
+
72
+	/* Ensure count is large enough to cover all of our emulated drives */
73
+	list_for_each_entry ( drive, &drives, list ) {
74
+		if ( num_drives <= ( drive->drive & 0x7f ) )
75
+			num_drives = ( ( drive->drive & 0x7f ) + 1 );
76
+	}
77
+
78
+	/* Update current drive count */
79
+	put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
80
+}
81
+
82
+/**
83
+ * Check number of drives
84
+ */
85
+static void int13_check_num_drives ( void ) {
86
+	uint8_t check_num_drives;
87
+
88
+	get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
89
+	if ( check_num_drives != num_drives ) {
90
+		int13_set_num_drives();
91
+		DBG ( "INT13 fixing up number of drives from %d to %d\n",
92
+		      check_num_drives, num_drives );
93
+	}
94
+}
95
+
54
 /**
96
 /**
55
  * INT 13, 00 - Reset disk system
97
  * INT 13, 00 - Reset disk system
56
  *
98
  *
340
 	struct int13_drive *drive;
382
 	struct int13_drive *drive;
341
 	int status;
383
 	int status;
342
 
384
 
385
+	/* Check BIOS hasn't killed off our drive */
386
+	int13_check_num_drives();
387
+
343
 	list_for_each_entry ( drive, &drives, list ) {
388
 	list_for_each_entry ( drive, &drives, list ) {
344
 
389
 
345
 		if ( bios_drive != drive->drive ) {
390
 		if ( bios_drive != drive->drive ) {
555
 	/* Assign natural drive number */
600
 	/* Assign natural drive number */
556
 	get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
601
 	get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
557
 	drive->natural_drive = ( num_drives | 0x80 );
602
 	drive->natural_drive = ( num_drives | 0x80 );
558
-	num_drives++;
559
 
603
 
560
 	/* Assign drive number */
604
 	/* Assign drive number */
561
 	if ( ( drive->drive & 0xff ) == 0xff ) {
605
 	if ( ( drive->drive & 0xff ) == 0xff ) {
564
 	} else {
608
 	} else {
565
 		/* Use specified drive number (+0x80 if necessary) */
609
 		/* Use specified drive number (+0x80 if necessary) */
566
 		drive->drive |= 0x80;
610
 		drive->drive |= 0x80;
567
-		if ( num_drives <= ( drive->drive & 0x7f ) )
568
-			num_drives = ( ( drive->drive & 0x7f ) + 1 );
569
 	}
611
 	}
570
 
612
 
571
-	/* Update BIOS drive count */
572
-	put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
573
-
574
 	DBG ( "Registered INT13 drive %02x (naturally %02x) with C/H/S "
613
 	DBG ( "Registered INT13 drive %02x (naturally %02x) with C/H/S "
575
 	      "geometry %d/%d/%d\n", drive->drive, drive->natural_drive,
614
 	      "geometry %d/%d/%d\n", drive->drive, drive->natural_drive,
576
 	      drive->cylinders, drive->heads, drive->sectors_per_track );
615
 	      drive->cylinders, drive->heads, drive->sectors_per_track );
581
 
620
 
582
 	/* Add to list of emulated drives */
621
 	/* Add to list of emulated drives */
583
 	list_add ( &drive->list, &drives );
622
 	list_add ( &drive->list, &drives );
623
+
624
+	/* Update BIOS drive count */
625
+	int13_set_num_drives();
584
 }
626
 }
585
 
627
 
586
 /**
628
 /**

Carregando…
Cancelar
Salvar