diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/interface/pcbios/int13.c | 117 |
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; } |