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 14 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
 static struct interface_descriptor int13_command_desc =
202
 static struct interface_descriptor int13_command_desc =
203
 	INTF_DESC ( struct int13_command, block, int13_command_op );
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
  * Prepare to issue INT 13 command
232
  * Prepare to issue INT 13 command
207
  *
233
  *
211
  */
237
  */
212
 static int int13_command_start ( struct int13_command *command,
238
 static int int13_command_start ( struct int13_command *command,
213
 				 struct int13_drive *int13 ) {
239
 				 struct int13_drive *int13 ) {
240
+	int rc;
214
 
241
 
215
 	/* Sanity check */
242
 	/* Sanity check */
216
 	assert ( command->int13 == NULL );
243
 	assert ( command->int13 == NULL );
217
 	assert ( ! timer_running ( &command->timer ) );
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
 	/* Initialise command */
251
 	/* Initialise command */
220
 	command->rc = -EINPROGRESS;
252
 	command->rc = -EINPROGRESS;
221
 	command->int13 = int13;
253
 	command->int13 = int13;
406
 	return 0;
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
  * Update BIOS drive count
442
  * Update BIOS drive count
441
  */
443
  */
485
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
487
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
486
 		return -INT13_STATUS_RESET_FAILED;
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
 	return 0;
494
 	return 0;
489
 }
495
 }
490
 
496
 
837
 	uint8_t sum = 0;
843
 	uint8_t sum = 0;
838
 	int rc;
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
 	/* Get underlying hardware device */
851
 	/* Get underlying hardware device */
841
 	device = identify_device ( &int13->block );
852
 	device = identify_device ( &int13->block );
842
 	if ( ! device ) {
853
 	if ( ! device ) {
1125
 
1136
 
1126
 	/* Shut down interfaces */
1137
 	/* Shut down interfaces */
1127
 	intf_restart ( &int13->block, rc );
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
 /** INT 13 drive interface operations */
1141
 /** INT 13 drive interface operations */
1200
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
1207
 	if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
1201
 		goto err_reopen_block;
1208
 		goto err_reopen_block;
1202
 
1209
 
1210
+	/* Read device capacity */
1211
+	if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
1212
+		return rc;
1213
+
1203
 	/* Give drive a default geometry */
1214
 	/* Give drive a default geometry */
1204
 	if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
1215
 	if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
1205
 		goto err_guess_geometry;
1216
 		goto err_guess_geometry;
1383
 		return -ENODEV;
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
 	/* Clear table */
1402
 	/* Clear table */
1387
 	memset ( &xbftab, 0, sizeof ( xbftab ) );
1403
 	memset ( &xbftab, 0, sizeof ( xbftab ) );
1388
 
1404
 

Loading…
Cancel
Save