david/ipxe
david
/
ipxe
Archived
1
0
Fork 0
This repository has been archived on 2020-12-06. You can view files and clone it, but cannot push or open issues or pull requests.
ipxe/src/drivers/block/ata.c

680 lines
18 KiB
C
Raw Normal View History

/*
* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
#include <stddef.h>
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <byteswap.h>
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
#include <ipxe/list.h>
#include <ipxe/interface.h>
#include <ipxe/blockdev.h>
#include <ipxe/edd.h>
#include <ipxe/ata.h>
/** @file
*
* ATA block device
*
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/******************************************************************************
*
* Interface methods
*
******************************************************************************
*/
/**
* Issue ATA command
*
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v control ATA control interface
* @v data ATA data interface
* @v command ATA command
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @ret tag Command tag, or negative error
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
int ata_command ( struct interface *control, struct interface *data,
struct ata_cmd *command ) {
struct interface *dest;
ata_command_TYPE ( void * ) *op =
intf_get_dest_op ( control, ata_command, &dest );
void *object = intf_object ( dest );
int tag;
if ( op ) {
tag = op ( object, data, command );
} else {
/* Default is to fail to issue the command */
tag = -EOPNOTSUPP;
}
intf_put ( dest );
return tag;
}
/******************************************************************************
*
* ATA devices and commands
*
******************************************************************************
*/
/** List of all ATA commands */
static LIST_HEAD ( ata_commands );
/** An ATA device */
struct ata_device {
/** Reference count */
struct refcnt refcnt;
/** Block control interface */
struct interface block;
/** ATA control interface */
struct interface ata;
/** Device number
*
* Must be ATA_DEV_MASTER or ATA_DEV_SLAVE.
*/
unsigned int device;
/** Maximum number of blocks per single transfer */
unsigned int max_count;
/** Device uses LBA48 extended addressing */
int lba48;
};
/** An ATA command */
struct ata_command {
/** Reference count */
struct refcnt refcnt;
/** ATA device */
struct ata_device *atadev;
/** List of ATA commands */
struct list_head list;
/** Block data interface */
struct interface block;
/** ATA data interface */
struct interface ata;
/** Command type */
struct ata_command_type *type;
/** Command tag */
uint32_t tag;
/** Private data */
uint8_t priv[0];
};
/** An ATA command type */
struct ata_command_type {
/** Name */
const char *name;
/** Additional working space */
size_t priv_len;
/** Command for non-LBA48-capable devices */
uint8_t cmd_lba;
/** Command for LBA48-capable devices */
uint8_t cmd_lba48;
/**
* Calculate data-in buffer
*
* @v atacmd ATA command
* @v buffer Available buffer
* @v len Available buffer length
* @ret data_in Data-in buffer
* @ret data_in_len Data-in buffer length
*/
void ( * data_in ) ( struct ata_command *atacmd, userptr_t buffer,
size_t len, userptr_t *data_in,
size_t *data_in_len );
/**
* Calculate data-out buffer
*
*
* @v atacmd ATA command
* @v buffer Available buffer
* @v len Available buffer length
* @ret data_out Data-out buffer
* @ret data_out_len Data-out buffer length
*/
void ( * data_out ) ( struct ata_command *atacmd, userptr_t buffer,
size_t len, userptr_t *data_out,
size_t *data_out_len );
/**
* Handle ATA command completion
*
* @v atacmd ATA command
* @v rc Reason for completion
*/
void ( * done ) ( struct ata_command *atacmd, int rc );
};
/**
* Get reference to ATA device
*
* @v atadev ATA device
* @ret atadev ATA device
*/
static inline __attribute__ (( always_inline )) struct ata_device *
atadev_get ( struct ata_device *atadev ) {
ref_get ( &atadev->refcnt );
return atadev;
}
/**
* Drop reference to ATA device
*
* @v atadev ATA device
*/
static inline __attribute__ (( always_inline )) void
atadev_put ( struct ata_device *atadev ) {
ref_put ( &atadev->refcnt );
}
/**
* Get reference to ATA command
*
* @v atacmd ATA command
* @ret atacmd ATA command
*/
static inline __attribute__ (( always_inline )) struct ata_command *
atacmd_get ( struct ata_command *atacmd ) {
ref_get ( &atacmd->refcnt );
return atacmd;
}
/**
* Drop reference to ATA command
*
* @v atacmd ATA command
*/
static inline __attribute__ (( always_inline )) void
atacmd_put ( struct ata_command *atacmd ) {
ref_put ( &atacmd->refcnt );
}
/**
* Get ATA command private data
*
* @v atacmd ATA command
* @ret priv Private data
*/
static inline __attribute__ (( always_inline )) void *
atacmd_priv ( struct ata_command *atacmd ) {
return atacmd->priv;
}
/**
* Free ATA command
*
* @v refcnt Reference count
*/
static void atacmd_free ( struct refcnt *refcnt ) {
struct ata_command *atacmd =
container_of ( refcnt, struct ata_command, refcnt );
/* Remove from list of commands */
list_del ( &atacmd->list );
atadev_put ( atacmd->atadev );
/* Free command */
free ( atacmd );
}
/**
* Close ATA command
*
* @v atacmd ATA command
* @v rc Reason for close
*/
static void atacmd_close ( struct ata_command *atacmd, int rc ) {
struct ata_device *atadev = atacmd->atadev;
if ( rc != 0 ) {
DBGC ( atadev, "ATA %p tag %08x closed: %s\n",
atadev, atacmd->tag, strerror ( rc ) );
}
/* Shut down interfaces */
intf_shutdown ( &atacmd->ata, rc );
intf_shutdown ( &atacmd->block, rc );
}
/**
* Handle ATA command completion
*
* @v atacmd ATA command
* @v rc Reason for close
*/
static void atacmd_done ( struct ata_command *atacmd, int rc ) {
/* Hand over to the command completion handler */
atacmd->type->done ( atacmd, rc );
}
/**
* Use provided data buffer for ATA command
*
* @v atacmd ATA command
* @v buffer Available buffer
* @v len Available buffer length
* @ret data Data buffer
* @ret data_len Data buffer length
*/
static void atacmd_data_buffer ( struct ata_command *atacmd __unused,
userptr_t buffer, size_t len,
userptr_t *data, size_t *data_len ) {
*data = buffer;
*data_len = len;
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/**
* Use no data buffer for ATA command
*
* @v atacmd ATA command
* @v buffer Available buffer
* @v len Available buffer length
* @ret data Data buffer
* @ret data_len Data buffer length
*/
static void atacmd_data_none ( struct ata_command *atacmd __unused,
userptr_t buffer __unused, size_t len __unused,
userptr_t *data __unused,
size_t *data_len __unused ) {
/* Nothing to do */
}
/**
* Use private data buffer for ATA command
*
* @v atacmd ATA command
* @v buffer Available buffer
* @v len Available buffer length
* @ret data Data buffer
* @ret data_len Data buffer length
*/
static void atacmd_data_priv ( struct ata_command *atacmd,
userptr_t buffer __unused, size_t len __unused,
userptr_t *data, size_t *data_len ) {
*data = virt_to_user ( atacmd_priv ( atacmd ) );
*data_len = atacmd->type->priv_len;
}
/** ATA READ command type */
static struct ata_command_type atacmd_read = {
.name = "READ",
.cmd_lba = ATA_CMD_READ,
.cmd_lba48 = ATA_CMD_READ_EXT,
.data_in = atacmd_data_buffer,
.data_out = atacmd_data_none,
.done = atacmd_close,
};
/** ATA WRITE command type */
static struct ata_command_type atacmd_write = {
.name = "WRITE",
.cmd_lba = ATA_CMD_WRITE,
.cmd_lba48 = ATA_CMD_WRITE_EXT,
.data_in = atacmd_data_none,
.data_out = atacmd_data_buffer,
.done = atacmd_close,
};
/** ATA IDENTIFY private data */
struct ata_identify_private {
/** Identity data */
struct ata_identity identity;
};
/**
* Return ATA model string (for debugging)
*
* @v identify ATA identity data
* @ret model Model string
*/
static const char * ata_model ( struct ata_identity *identity ) {
static union {
uint16_t words[ sizeof ( identity->model ) / 2 ];
char text[ sizeof ( identity->model ) + 1 /* NUL */ ];
} buf;
unsigned int i;
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
for ( i = 0 ; i < ( sizeof ( identity->model ) / 2 ) ; i++ )
buf.words[i] = bswap_16 ( identity->model[i] );
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
return buf.text;
}
/**
* Handle ATA IDENTIFY command completion
*
* @v atacmd ATA command
* @v rc Reason for completion
*/
static void atacmd_identify_done ( struct ata_command *atacmd, int rc ) {
struct ata_device *atadev = atacmd->atadev;
struct ata_identify_private *priv = atacmd_priv ( atacmd );
struct ata_identity *identity = &priv->identity;
struct block_device_capacity capacity;
/* Close if command failed */
if ( rc != 0 ) {
atacmd_close ( atacmd, rc );
return;
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/* Extract capacity */
if ( identity->supports_lba48 & cpu_to_le16 ( ATA_SUPPORTS_LBA48 ) ) {
atadev->lba48 = 1;
capacity.blocks = le64_to_cpu ( identity->lba48_sectors );
} else {
capacity.blocks = le32_to_cpu ( identity->lba_sectors );
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
capacity.blksize = ATA_SECTOR_SIZE;
capacity.max_count = atadev->max_count;
DBGC ( atadev, "ATA %p is a %s\n", atadev, ata_model ( identity ) );
DBGC ( atadev, "ATA %p has %#llx blocks (%ld MB) and uses %s\n",
atadev, capacity.blocks,
( ( signed long ) ( capacity.blocks >> 11 ) ),
( atadev->lba48 ? "LBA48" : "LBA" ) );
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/* Return capacity to caller */
block_capacity ( &atacmd->block, &capacity );
/* Close command */
atacmd_close ( atacmd, 0 );
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/** ATA IDENTITY command type */
static struct ata_command_type atacmd_identify = {
.name = "IDENTIFY",
.priv_len = sizeof ( struct ata_identify_private ),
.cmd_lba = ATA_CMD_IDENTIFY,
.cmd_lba48 = ATA_CMD_IDENTIFY,
.data_in = atacmd_data_priv,
.data_out = atacmd_data_none,
.done = atacmd_identify_done,
};
/** ATA command block interface operations */
static struct interface_operation atacmd_block_op[] = {
INTF_OP ( intf_close, struct ata_command *, atacmd_close ),
};
/** ATA command block interface descriptor */
static struct interface_descriptor atacmd_block_desc =
INTF_DESC_PASSTHRU ( struct ata_command, block,
atacmd_block_op, ata );
/** ATA command ATA interface operations */
static struct interface_operation atacmd_ata_op[] = {
INTF_OP ( intf_close, struct ata_command *, atacmd_done ),
};
/** ATA command ATA interface descriptor */
static struct interface_descriptor atacmd_ata_desc =
INTF_DESC_PASSTHRU ( struct ata_command, ata,
atacmd_ata_op, block );
/**
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* Create ATA command
*
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v atadev ATA device
* @v block Block data interface
* @v type ATA command type
* @v lba Starting logical block address
* @v count Number of blocks to transfer
* @v buffer Data buffer
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v len Length of data buffer
* @ret rc Return status code
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
static int atadev_command ( struct ata_device *atadev,
struct interface *block,
struct ata_command_type *type,
uint64_t lba, unsigned int count,
userptr_t buffer, size_t len ) {
struct ata_command *atacmd;
struct ata_cmd command;
int tag;
int rc;
/* Allocate and initialise structure */
atacmd = zalloc ( sizeof ( *atacmd ) + type->priv_len );
if ( ! atacmd ) {
rc = -ENOMEM;
goto err_zalloc;
}
ref_init ( &atacmd->refcnt, atacmd_free );
intf_init ( &atacmd->block, &atacmd_block_desc, &atacmd->refcnt );
intf_init ( &atacmd->ata, &atacmd_ata_desc,
&atacmd->refcnt );
atacmd->atadev = atadev_get ( atadev );
list_add ( &atacmd->list, &ata_commands );
atacmd->type = type;
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/* Sanity check */
if ( len != ( count * ATA_SECTOR_SIZE ) ) {
DBGC ( atadev, "ATA %p tag %08x buffer length mismatch (count "
"%d len %zd)\n", atadev, atacmd->tag, count, len );
rc = -EINVAL;
goto err_len;
}
/* Construct command */
memset ( &command, 0, sizeof ( command ) );
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
command.cb.lba.native = lba;
command.cb.count.native = count;
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
command.cb.device = ( atadev->device | ATA_DEV_OBSOLETE | ATA_DEV_LBA );
command.cb.lba48 = atadev->lba48;
if ( ! atadev->lba48 )
command.cb.device |= command.cb.lba.bytes.low_prev;
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
command.cb.cmd_stat =
( atadev->lba48 ? type->cmd_lba48 : type->cmd_lba );
type->data_in ( atacmd, buffer, len,
&command.data_in, &command.data_in_len );
type->data_out ( atacmd, buffer, len,
&command.data_out, &command.data_out_len );
/* Issue command */
if ( ( tag = ata_command ( &atadev->ata, &atacmd->ata,
&command ) ) < 0 ) {
rc = tag;
DBGC ( atadev, "ATA %p tag %08x could not issue command: %s\n",
atadev, atacmd->tag, strerror ( rc ) );
goto err_command;
}
atacmd->tag = tag;
DBGC2 ( atadev, "ATA %p tag %08x %s cmd %02x dev %02x LBA%s %08llx "
"count %04x\n", atadev, atacmd->tag, atacmd->type->name,
command.cb.cmd_stat, command.cb.device,
( command.cb.lba48 ? "48" : "" ),
( unsigned long long ) command.cb.lba.native,
command.cb.count.native );
/* Attach to parent interface, mortalise self, and return */
intf_plug_plug ( &atacmd->block, block );
ref_put ( &atacmd->refcnt );
return 0;
err_command:
err_len:
atacmd_close ( atacmd, rc );
ref_put ( &atacmd->refcnt );
err_zalloc:
return rc;
}
/**
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* Issue ATA block read
*
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v atadev ATA device
* @v block Block data interface
* @v lba Starting logical block address
* @v count Number of blocks to transfer
* @v buffer Data buffer
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v len Length of data buffer
* @ret rc Return status code
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
static int atadev_read ( struct ata_device *atadev,
struct interface *block,
uint64_t lba, unsigned int count,
userptr_t buffer, size_t len ) {
return atadev_command ( atadev, block, &atacmd_read,
lba, count, buffer, len );
}
/**
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* Issue ATA block write
*
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v atadev ATA device
* @v block Block data interface
* @v lba Starting logical block address
* @v count Number of blocks to transfer
* @v buffer Data buffer
* @v len Length of data buffer
* @ret rc Return status code
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
static int atadev_write ( struct ata_device *atadev,
struct interface *block,
uint64_t lba, unsigned int count,
userptr_t buffer, size_t len ) {
return atadev_command ( atadev, block, &atacmd_write,
lba, count, buffer, len );
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/**
* Read ATA device capacity
*
* @v atadev ATA device
* @v block Block data interface
* @ret rc Return status code
*/
static int atadev_read_capacity ( struct ata_device *atadev,
struct interface *block ) {
struct ata_identity *identity;
assert ( atacmd_identify.priv_len == sizeof ( *identity ) );
assert ( atacmd_identify.priv_len == ATA_SECTOR_SIZE );
return atadev_command ( atadev, block, &atacmd_identify,
0, 1, UNULL, ATA_SECTOR_SIZE );
}
/**
* Close ATA device
*
* @v atadev ATA device
* @v rc Reason for close
*/
static void atadev_close ( struct ata_device *atadev, int rc ) {
struct ata_command *atacmd;
struct ata_command *tmp;
/* Shut down interfaces */
intf_shutdown ( &atadev->block, rc );
intf_shutdown ( &atadev->ata, rc );
/* Shut down any remaining commands */
list_for_each_entry_safe ( atacmd, tmp, &ata_commands, list ) {
if ( atacmd->atadev != atadev )
continue;
atacmd_get ( atacmd );
atacmd_close ( atacmd, rc );
atacmd_put ( atacmd );
}
}
/**
* Describe ATA device using EDD
*
* @v atadev ATA device
* @v type EDD interface type
* @v path EDD device path
* @ret rc Return status code
*/
static int atadev_edd_describe ( struct ata_device *atadev,
struct edd_interface_type *type,
union edd_device_path *path ) {
type->type = cpu_to_le64 ( EDD_INTF_TYPE_ATA );
path->ata.slave = ( ( atadev->device == ATA_DEV_SLAVE ) ? 0x01 : 0x00 );
return 0;
}
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/** ATA device block interface operations */
static struct interface_operation atadev_block_op[] = {
INTF_OP ( block_read, struct ata_device *, atadev_read ),
INTF_OP ( block_write, struct ata_device *, atadev_write ),
INTF_OP ( block_read_capacity, struct ata_device *,
atadev_read_capacity ),
INTF_OP ( intf_close, struct ata_device *, atadev_close ),
INTF_OP ( edd_describe, struct ata_device *, atadev_edd_describe ),
};
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
/** ATA device block interface descriptor */
static struct interface_descriptor atadev_block_desc =
INTF_DESC_PASSTHRU ( struct ata_device, block,
atadev_block_op, ata );
/** ATA device ATA interface operations */
static struct interface_operation atadev_ata_op[] = {
INTF_OP ( intf_close, struct ata_device *, atadev_close ),
};
/** ATA device ATA interface descriptor */
static struct interface_descriptor atadev_ata_desc =
INTF_DESC_PASSTHRU ( struct ata_device, ata,
atadev_ata_op, block );
/**
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* Open ATA device
*
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
* @v block Block control interface
* @v ata ATA control interface
* @v device ATA device number
* @v max_count Maximum number of blocks per single transfer
* @ret rc Return status code
*/
[block] Replace gPXE block-device API with an iPXE asynchronous interface The block device interface used in gPXE predates the invention of even the old gPXE data-transfer interface, let alone the current iPXE generic asynchronous interface mechanism. Bring this old code up to date, with the following benefits: o Block device commands can be cancelled by the requestor. The INT 13 layer uses this to provide a global timeout on all INT 13 calls, with the result that an unexpected passive failure mode (such as an iSCSI target ACKing the request but never sending a response) will lead to a timeout that gets reported back to the INT 13 user, rather than simply freezing the system. o INT 13,00 (reset drive) is now able to reset the underlying block device. INT 13 users, such as DOS, that use INT 13,00 as a method for error recovery now have a chance of recovering. o All block device commands are tagged, with a numerical tag that will show up in debugging output and in packet captures; this will allow easier interpretation of bug reports that include both sources of information. o The extremely ugly hacks used to generate the boot firmware tables have been eradicated and replaced with a generic acpi_describe() method (exploiting the ability of iPXE interfaces to pass through methods to an underlying interface). The ACPI tables are now built in a shared data block within .bss16, rather than each requiring dedicated space in .data16. o The architecture-independent concept of a SAN device has been exposed to the iPXE core through the sanboot API, which provides calls to hook, unhook, boot, and describe SAN devices. This allows for much more flexible usage patterns (such as hooking an empty SAN device and then running an OS installer via TFTP). Signed-off-by: Michael Brown <mcb30@ipxe.org>
2010-09-03 17:11:51 +02:00
int ata_open ( struct interface *block, struct interface *ata,
unsigned int device, unsigned int max_count ) {
struct ata_device *atadev;
/* Allocate and initialise structure */
atadev = zalloc ( sizeof ( *atadev ) );
if ( ! atadev )
return -ENOMEM;
ref_init ( &atadev->refcnt, NULL );
intf_init ( &atadev->block, &atadev_block_desc, &atadev->refcnt );
intf_init ( &atadev->ata, &atadev_ata_desc, &atadev->refcnt );
atadev->device = device;
atadev->max_count = max_count;
/* Attach to ATA and parent and interfaces, mortalise self,
* and return
*/
intf_plug_plug ( &atadev->ata, ata );
intf_plug_plug ( &atadev->block, block );
ref_put ( &atadev->refcnt );
return 0;
}