Browse Source

[int13] Automatically reopen underlying block device as needed

We currently use INT 13,00 as an opportunity to reopen the underlying
block device, which works well for callers such as DOS that will use
INT 13,00 in response to any disk errors.  However, some callers (such
as Windows Server 2008) do not attempt to reset the disk, and so any
failures become effectively permanent.

Fix this by automatically reopening the underlying block device
whenever we might want to access it.

This makes direct installation of Windows to an iSCSI target much more
reliable.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
560cc637f9
1 changed files with 50 additions and 34 deletions
  1. 50
    34
      src/arch/i386/interface/pcbios/int13.c

+ 50
- 34
src/arch/i386/interface/pcbios/int13.c View File

@@ -202,6 +202,32 @@ static struct interface_operation int13_command_op[] = {
202 202
 static struct interface_descriptor int13_command_desc =
203 203
 	INTF_DESC ( struct int13_command, block, int13_command_op );
204 204
 
205
+/**
206
+ * Open (or reopen) INT 13 emulated drive underlying block device
207
+ *
208
+ * @v int13		Emulated drive
209
+ * @ret rc		Return status code
210
+ */
211
+static int int13_reopen_block ( struct int13_drive *int13 ) {
212
+	int rc;
213
+
214
+	/* Close any existing block device */
215
+	intf_restart ( &int13->block, -ECONNRESET );
216
+
217
+	/* Open block device */
218
+	if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
219
+		DBGC ( int13, "INT13 drive %02x could not reopen block "
220
+		       "device: %s\n", int13->drive, strerror ( rc ) );
221
+		int13->block_rc = rc;
222
+		return rc;
223
+	}
224
+
225
+	/* Clear block device error status */
226
+	int13->block_rc = 0;
227
+
228
+	return 0;
229
+}
230
+
205 231
 /**
206 232
  * Prepare to issue INT 13 command
207 233
  *
@@ -211,11 +237,17 @@ static struct interface_descriptor int13_command_desc =
211 237
  */
212 238
 static int int13_command_start ( struct int13_command *command,
213 239
 				 struct int13_drive *int13 ) {
240
+	int rc;
214 241
 
215 242
 	/* Sanity check */
216 243
 	assert ( command->int13 == NULL );
217 244
 	assert ( ! timer_running ( &command->timer ) );
218 245
 
246
+	/* Reopen block device if necessary */
247
+	if ( ( int13->block_rc != 0 ) &&
248
+	     ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
249
+		return rc;
250
+
219 251
 	/* Initialise command */
220 252
 	command->rc = -EINPROGRESS;
221 253
 	command->int13 = int13;
@@ -406,36 +438,6 @@ static int int13_guess_geometry ( struct int13_drive *int13 ) {
406 438
 	return 0;
407 439
 }
408 440
 
409
-/**
410
- * Open (or reopen) INT 13 emulated drive underlying block device
411
- *
412
- * @v int13		Emulated drive
413
- * @ret rc		Return status code
414
- */
415
-static int int13_reopen_block ( struct int13_drive *int13 ) {
416
-	int rc;
417
-
418
-	/* Close any existing block device */
419
-	intf_restart ( &int13->block, -ECONNRESET );
420
-
421
-	/* Open block device */
422
-	if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
423
-		DBGC ( int13, "INT13 drive %02x could not reopen block "
424
-		       "device: %s\n", int13->drive, strerror ( rc ) );
425
-		int13->block_rc = rc;
426
-		return rc;
427
-	}
428
-
429
-	/* Clear block device error status */
430
-	int13->block_rc = 0;
431
-
432
-	/* Read device capacity */
433
-	if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
434
-		return rc;
435
-
436
-	return 0;
437
-}
438
-
439 441
 /**
440 442
  * Update BIOS drive count
441 443
  */
@@ -485,6 +487,10 @@ static int int13_reset ( struct int13_drive *int13,
485 487
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
486 488
 		return -INT13_STATUS_RESET_FAILED;
487 489
 
490
+	/* Check that block device is functional */
491
+	if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
492
+		return -INT13_STATUS_RESET_FAILED;
493
+
488 494
 	return 0;
489 495
 }
490 496
 
@@ -837,6 +843,11 @@ static int int13_device_path_info ( struct int13_drive *int13,
837 843
 	uint8_t sum = 0;
838 844
 	int rc;
839 845
 
846
+	/* Reopen block device if necessary */
847
+	if ( ( int13->block_rc != 0 ) &&
848
+	     ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
849
+		return rc;
850
+
840 851
 	/* Get underlying hardware device */
841 852
 	device = identify_device ( &int13->block );
842 853
 	if ( ! device ) {
@@ -1125,10 +1136,6 @@ static void int13_block_close ( struct int13_drive *int13, int rc ) {
1125 1136
 
1126 1137
 	/* Shut down interfaces */
1127 1138
 	intf_restart ( &int13->block, rc );
1128
-
1129
-	/* Further INT 13 calls will fail immediately.  The caller may
1130
-	 * use INT 13,00 to reset the drive.
1131
-	 */
1132 1139
 }
1133 1140
 
1134 1141
 /** INT 13 drive interface operations */
@@ -1200,6 +1207,10 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
1200 1207
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
1201 1208
 		goto err_reopen_block;
1202 1209
 
1210
+	/* Read device capacity */
1211
+	if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
1212
+		return rc;
1213
+
1203 1214
 	/* Give drive a default geometry */
1204 1215
 	if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
1205 1216
 		goto err_guess_geometry;
@@ -1383,6 +1394,11 @@ static int int13_describe ( unsigned int drive ) {
1383 1394
 		return -ENODEV;
1384 1395
 	}
1385 1396
 
1397
+	/* Reopen block device if necessary */
1398
+	if ( ( int13->block_rc != 0 ) &&
1399
+	     ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
1400
+		return rc;
1401
+
1386 1402
 	/* Clear table */
1387 1403
 	memset ( &xbftab, 0, sizeof ( xbftab ) );
1388 1404
 

Loading…
Cancel
Save