summaryrefslogtreecommitdiffstats
path: root/src/arch/x86/interface/pcbios/int13.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/interface/pcbios/int13.c')
-rw-r--r--src/arch/x86/interface/pcbios/int13.c117
1 files changed, 65 insertions, 52 deletions
diff --git a/src/arch/x86/interface/pcbios/int13.c b/src/arch/x86/interface/pcbios/int13.c
index 0bc123d7..b793d730 100644
--- a/src/arch/x86/interface/pcbios/int13.c
+++ b/src/arch/x86/interface/pcbios/int13.c
@@ -1239,13 +1239,14 @@ static void int13_unhook_vector ( void ) {
* @v drive Drive number
* @v uris List of URIs
* @v count Number of URIs
+ * @v flags Flags
* @ret drive Drive number, or negative error
*
* Registers the drive with the INT 13 emulation subsystem, and hooks
* the INT 13 interrupt vector (if not already hooked).
*/
static int int13_hook ( unsigned int drive, struct uri **uris,
- unsigned int count ) {
+ unsigned int count, unsigned int flags ) {
struct san_device *sandev;
struct int13_data *int13;
unsigned int natural_drive;
@@ -1267,14 +1268,13 @@ static int int13_hook ( unsigned int drive, struct uri **uris,
rc = -ENOMEM;
goto err_alloc;
}
- sandev->drive = drive;
int13 = sandev->priv;
int13->natural_drive = natural_drive;
/* Register SAN device */
- if ( ( rc = register_sandev ( sandev ) ) != 0 ) {
+ if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) {
DBGC ( sandev, "INT13 drive %02x could not register: %s\n",
- sandev->drive, strerror ( rc ) );
+ drive, strerror ( rc ) );
goto err_register;
}
@@ -1544,70 +1544,83 @@ static int int13_boot ( unsigned int drive ) {
return -ECANCELED; /* -EIMPOSSIBLE */
}
-/** A boot firmware table generated by iPXE */
-union xbft_table {
- /** ACPI header */
- struct acpi_description_header acpi;
- /** Padding */
- char pad[768];
-};
+/** Maximum size of boot firmware table(s) */
+#define XBFTAB_SIZE 768
+
+/** Alignment of boot firmware table entries */
+#define XBFTAB_ALIGN 16
-/** The boot firmware table generated by iPXE */
-static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
+/** The boot firmware table(s) generated by iPXE */
+static uint8_t __bss16_array ( xbftab, [XBFTAB_SIZE] )
+ __attribute__ (( aligned ( XBFTAB_ALIGN ) ));
#define xbftab __use_data16 ( xbftab )
+/** Total used length of boot firmware tables */
+static size_t xbftab_used;
+
/**
- * Describe SAN device for SAN-booted operating system
+ * Install ACPI table
*
- * @v drive Drive number
+ * @v acpi ACPI description header
* @ret rc Return status code
*/
-static int int13_describe ( unsigned int drive ) {
- struct san_device *sandev;
- struct san_path *sanpath;
+static int int13_install ( struct acpi_header *acpi ) {
struct segoff xbft_address;
- int rc;
-
- /* Find drive */
- sandev = sandev_find ( drive );
- if ( ! sandev ) {
- DBG ( "INT13 cannot find drive %02x\n", drive );
- return -ENODEV;
+ struct acpi_header *installed;
+ size_t len;
+
+ /* Check length */
+ len = acpi->length;
+ if ( len > ( sizeof ( xbftab ) - xbftab_used ) ) {
+ DBGC ( acpi, "INT13 out of space for %s table\n",
+ acpi_name ( acpi->signature ) );
+ return -ENOSPC;
}
- /* Reopen block device if necessary */
- if ( sandev_needs_reopen ( sandev ) &&
- ( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
- return rc;
- sanpath = sandev->active;
- assert ( sanpath != NULL );
+ /* Install table */
+ installed = ( ( ( void * ) xbftab ) + xbftab_used );
+ memcpy ( installed, acpi, len );
+ xbft_address.segment = rm_ds;
+ xbft_address.offset = __from_data16 ( installed );
+
+ /* Fill in common parameters */
+ strncpy ( installed->oem_id, "FENSYS",
+ sizeof ( installed->oem_id ) );
+ strncpy ( installed->oem_table_id, "iPXE",
+ sizeof ( installed->oem_table_id ) );
+
+ /* Fix checksum */
+ acpi_fix_checksum ( installed );
+
+ /* Update used length */
+ xbftab_used = ( ( xbftab_used + len + XBFTAB_ALIGN - 1 ) &
+ ~( XBFTAB_ALIGN - 1 ) );
+
+ DBGC ( acpi, "INT13 installed %s:\n",
+ acpi_name ( installed->signature ) );
+ DBGC_HDA ( acpi, xbft_address, installed, len );
+ return 0;
+}
- /* Clear table */
+/**
+ * Describe SAN devices for SAN-booted operating system
+ *
+ * @ret rc Return status code
+ */
+static int int13_describe ( void ) {
+ int rc;
+
+ /* Clear tables */
memset ( &xbftab, 0, sizeof ( xbftab ) );
+ xbftab_used = 0;
- /* Fill in common parameters */
- strncpy ( xbftab.acpi.oem_id, "FENSYS",
- sizeof ( xbftab.acpi.oem_id ) );
- strncpy ( xbftab.acpi.oem_table_id, "iPXE",
- sizeof ( xbftab.acpi.oem_table_id ) );
-
- /* Fill in remaining parameters */
- if ( ( rc = acpi_describe ( &sanpath->block, &xbftab.acpi,
- sizeof ( xbftab ) ) ) != 0 ) {
- DBGC ( sandev, "INT13 drive %02x could not create ACPI "
- "description: %s\n", sandev->drive, strerror ( rc ) );
+ /* Install ACPI tables */
+ if ( ( rc = acpi_install ( int13_install ) ) != 0 ) {
+ DBG ( "INT13 could not install ACPI tables: %s\n",
+ strerror ( rc ) );
return rc;
}
- /* Fix up ACPI checksum */
- acpi_fix_checksum ( &xbftab.acpi );
- xbft_address.segment = rm_ds;
- xbft_address.offset = __from_data16 ( &xbftab );
- DBGC ( sandev, "INT13 drive %02x described using boot firmware "
- "table:\n", sandev->drive );
- DBGC_HDA ( sandev, xbft_address, &xbftab,
- le32_to_cpu ( xbftab.acpi.length ) );
-
return 0;
}