Skip to content

Commit

Permalink
[int13] Automatically reopen underlying block device as needed
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mcb30 committed Mar 2, 2011
1 parent 90563f6 commit 560cc63
Showing 1 changed file with 50 additions and 34 deletions.
84 changes: 50 additions & 34 deletions src/arch/i386/interface/pcbios/int13.c
Expand Up @@ -202,6 +202,32 @@ static struct interface_operation int13_command_op[] = {
static struct interface_descriptor int13_command_desc =
INTF_DESC ( struct int13_command, block, int13_command_op );

/**
* Open (or reopen) INT 13 emulated drive underlying block device
*
* @v int13 Emulated drive
* @ret rc Return status code
*/
static int int13_reopen_block ( struct int13_drive *int13 ) {
int rc;

/* Close any existing block device */
intf_restart ( &int13->block, -ECONNRESET );

/* Open block device */
if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
DBGC ( int13, "INT13 drive %02x could not reopen block "
"device: %s\n", int13->drive, strerror ( rc ) );
int13->block_rc = rc;
return rc;
}

/* Clear block device error status */
int13->block_rc = 0;

return 0;
}

/**
* Prepare to issue INT 13 command
*
Expand All @@ -211,11 +237,17 @@ static struct interface_descriptor int13_command_desc =
*/
static int int13_command_start ( struct int13_command *command,
struct int13_drive *int13 ) {
int rc;

/* Sanity check */
assert ( command->int13 == NULL );
assert ( ! timer_running ( &command->timer ) );

/* Reopen block device if necessary */
if ( ( int13->block_rc != 0 ) &&
( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
return rc;

/* Initialise command */
command->rc = -EINPROGRESS;
command->int13 = int13;
Expand Down Expand Up @@ -406,36 +438,6 @@ static int int13_guess_geometry ( struct int13_drive *int13 ) {
return 0;
}

/**
* Open (or reopen) INT 13 emulated drive underlying block device
*
* @v int13 Emulated drive
* @ret rc Return status code
*/
static int int13_reopen_block ( struct int13_drive *int13 ) {
int rc;

/* Close any existing block device */
intf_restart ( &int13->block, -ECONNRESET );

/* Open block device */
if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
DBGC ( int13, "INT13 drive %02x could not reopen block "
"device: %s\n", int13->drive, strerror ( rc ) );
int13->block_rc = rc;
return rc;
}

/* Clear block device error status */
int13->block_rc = 0;

/* Read device capacity */
if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
return rc;

return 0;
}

/**
* Update BIOS drive count
*/
Expand Down Expand Up @@ -485,6 +487,10 @@ static int int13_reset ( struct int13_drive *int13,
if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
return -INT13_STATUS_RESET_FAILED;

/* Check that block device is functional */
if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
return -INT13_STATUS_RESET_FAILED;

return 0;
}

Expand Down Expand Up @@ -837,6 +843,11 @@ static int int13_device_path_info ( struct int13_drive *int13,
uint8_t sum = 0;
int rc;

/* Reopen block device if necessary */
if ( ( int13->block_rc != 0 ) &&
( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
return rc;

/* Get underlying hardware device */
device = identify_device ( &int13->block );
if ( ! device ) {
Expand Down Expand Up @@ -1125,10 +1136,6 @@ static void int13_block_close ( struct int13_drive *int13, int rc ) {

/* Shut down interfaces */
intf_restart ( &int13->block, rc );

/* Further INT 13 calls will fail immediately. The caller may
* use INT 13,00 to reset the drive.
*/
}

/** INT 13 drive interface operations */
Expand Down Expand Up @@ -1200,6 +1207,10 @@ static int int13_hook ( struct uri *uri, unsigned int drive ) {
if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
goto err_reopen_block;

/* Read device capacity */
if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
return rc;

/* Give drive a default geometry */
if ( ( rc = int13_guess_geometry ( int13 ) ) != 0 )
goto err_guess_geometry;
Expand Down Expand Up @@ -1383,6 +1394,11 @@ static int int13_describe ( unsigned int drive ) {
return -ENODEV;
}

/* Reopen block device if necessary */
if ( ( int13->block_rc != 0 ) &&
( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
return rc;

/* Clear table */
memset ( &xbftab, 0, sizeof ( xbftab ) );

Expand Down

0 comments on commit 560cc63

Please sign in to comment.