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 -/** The boot firmware table generated by iPXE */ -static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) )); +/** Alignment of boot firmware table entries */ +#define XBFTAB_ALIGN 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; + struct acpi_header *installed; + size_t len; - /* Find drive */ - sandev = sandev_find ( drive ); - if ( ! sandev ) { - DBG ( "INT13 cannot find drive %02x\n", drive ); - return -ENODEV; + /* 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 ); - - /* Clear table */ - memset ( &xbftab, 0, sizeof ( xbftab ) ); + /* 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 ( xbftab.acpi.oem_id, "FENSYS", - sizeof ( xbftab.acpi.oem_id ) ); - strncpy ( xbftab.acpi.oem_table_id, "iPXE", - sizeof ( xbftab.acpi.oem_table_id ) ); + strncpy ( installed->oem_id, "FENSYS", + sizeof ( installed->oem_id ) ); + strncpy ( installed->oem_table_id, "iPXE", + sizeof ( installed->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 ) ); + /* 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; +} + +/** + * 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; + + /* 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; } diff --git a/src/core/acpi.c b/src/core/acpi.c index 955637e0..8ebe4b19 100644 --- a/src/core/acpi.c +++ b/src/core/acpi.c @@ -42,28 +42,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); ****************************************************************************** */ -/** - * Transcribe ACPI table signature (for debugging) - * - * @v signature ACPI table signature - * @ret name ACPI table signature name - */ -static const char * acpi_name ( uint32_t signature ) { - static union { - uint32_t signature; - char name[5]; - } u; - - u.signature = cpu_to_le32 ( signature ); - return u.name; -} - /** * Fix up ACPI table checksum * * @v acpi ACPI table header */ -void acpi_fix_checksum ( struct acpi_description_header *acpi ) { +void acpi_fix_checksum ( struct acpi_header *acpi ) { unsigned int i = 0; uint8_t sum = 0; @@ -147,7 +131,7 @@ userptr_t acpi_find_rsdt ( userptr_t ebda ) { * @ret table Table, or UNULL if not found */ userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) { - struct acpi_description_header acpi; + struct acpi_header acpi; struct acpi_rsdt *rsdtab; typeof ( rsdtab->entry[0] ) entry; userptr_t table; @@ -227,7 +211,7 @@ userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ) { * the ACPI specification itself. */ static int acpi_sx_zsdt ( userptr_t zsdt, uint32_t signature ) { - struct acpi_description_header acpi; + struct acpi_header acpi; union { uint32_t dword; uint8_t byte[4]; @@ -331,34 +315,73 @@ int acpi_sx ( userptr_t rsdt, uint32_t signature ) { /****************************************************************************** * - * Interface methods + * Descriptors * ****************************************************************************** */ /** - * Describe object in an ACPI table + * Add ACPI descriptor + * + * @v desc ACPI descriptor + */ +void acpi_add ( struct acpi_descriptor *desc ) { + + /* Add to list of descriptors */ + ref_get ( desc->refcnt ); + list_add_tail ( &desc->list, &desc->model->descs ); +} + +/** + * Remove ACPI descriptor + * + * @v desc ACPI descriptor + */ +void acpi_del ( struct acpi_descriptor *desc ) { + + /* Remove from list of descriptors */ + list_check_contains_entry ( desc, &desc->model->descs, list ); + list_del ( &desc->list ); + ref_put ( desc->refcnt ); +} + +/** + * Get object's ACPI descriptor * * @v intf Interface - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code + * @ret desc ACPI descriptor, or NULL */ -int acpi_describe ( struct interface *intf, - struct acpi_description_header *acpi, size_t len ) { +struct acpi_descriptor * acpi_describe ( struct interface *intf ) { struct interface *dest; acpi_describe_TYPE ( void * ) *op = intf_get_dest_op ( intf, acpi_describe, &dest ); void *object = intf_object ( dest ); - int rc; + struct acpi_descriptor *desc; if ( op ) { - rc = op ( object, acpi, len ); + desc = op ( object ); } else { - /* Default is to fail to describe */ - rc = -EOPNOTSUPP; + desc = NULL; } intf_put ( dest ); - return rc; + return desc; +} + +/** + * Install ACPI tables + * + * @v install Table installation method + * @ret rc Return status code + */ +int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ){ + struct acpi_model *model; + int rc; + + for_each_table_entry ( model, ACPI_MODELS ) { + if ( ( rc = model->install ( install ) ) != 0 ) + return rc; + } + + return 0; } diff --git a/src/core/dummy_sanboot.c b/src/core/dummy_sanboot.c index 64d5206f..08180852 100644 --- a/src/core/dummy_sanboot.c +++ b/src/core/dummy_sanboot.c @@ -38,10 +38,11 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * @v drive Drive number * @v uris List of URIs * @v count Number of URIs + * @v flags Flags * @ret drive Drive number, or negative error */ static int dummy_san_hook ( unsigned int drive, struct uri **uris, - unsigned int count ) { + unsigned int count, unsigned int flags ) { struct san_device *sandev; int rc; @@ -51,10 +52,9 @@ static int dummy_san_hook ( unsigned int drive, struct uri **uris, rc = -ENOMEM; goto err_alloc; } - sandev->drive = drive; /* Register SAN device */ - if ( ( rc = register_sandev ( sandev ) ) != 0 ) { + if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) { DBGC ( sandev, "SAN %#02x could not register: %s\n", sandev->drive, strerror ( rc ) ); goto err_register; @@ -101,14 +101,27 @@ static int dummy_san_boot ( unsigned int drive __unused ) { return -EOPNOTSUPP; } +/** + * Install ACPI table + * + * @v acpi ACPI description header + * @ret rc Return status code + */ +static int dummy_install ( struct acpi_header *acpi ) { + + DBGC ( acpi, "ACPI table %s:\n", acpi_name ( acpi->signature ) ); + DBGC_HDA ( acpi, 0, acpi, le32_to_cpu ( acpi->length ) ); + return 0; +} + /** * Describe dummy SAN device * - * @v drive Drive number + * @ret rc Return status code */ -static int dummy_san_describe ( unsigned int drive __unused ) { +static int dummy_san_describe ( void ) { - return 0; + return acpi_install ( dummy_install ); } PROVIDE_SANBOOT ( dummy, san_hook, dummy_san_hook ); diff --git a/src/core/null_sanboot.c b/src/core/null_sanboot.c index 42fb0682..b09562e2 100644 --- a/src/core/null_sanboot.c +++ b/src/core/null_sanboot.c @@ -28,7 +28,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); static int null_san_hook ( unsigned int drive __unused, struct uri **uris __unused, - unsigned int count __unused ) { + unsigned int count __unused, + unsigned int flags __unused ) { return -EOPNOTSUPP; } @@ -40,7 +41,7 @@ static int null_san_boot ( unsigned int drive __unused ) { return -EOPNOTSUPP; } -static int null_san_describe ( unsigned int drive __unused ) { +static int null_san_describe ( void ) { return -EOPNOTSUPP; } diff --git a/src/core/sanboot.c b/src/core/sanboot.c index 03beae79..f134f76a 100644 --- a/src/core/sanboot.c +++ b/src/core/sanboot.c @@ -119,8 +119,10 @@ static void sandev_free ( struct refcnt *refcnt ) { assert ( ! timer_running ( &sandev->timer ) ); assert ( ! sandev->active ); assert ( list_empty ( &sandev->opened ) ); - for ( i = 0 ; i < sandev->paths ; i++ ) + for ( i = 0 ; i < sandev->paths ; i++ ) { uri_put ( sandev->path[i].uri ); + assert ( sandev->path[i].desc == NULL ); + } free ( sandev ); } @@ -199,6 +201,15 @@ static int sanpath_open ( struct san_path *sanpath ) { return rc; } + /* Update ACPI descriptor, if applicable */ + if ( ! ( sandev->flags & SAN_NO_DESCRIBE ) ) { + if ( sanpath->desc ) + acpi_del ( sanpath->desc ); + sanpath->desc = acpi_describe ( &sanpath->block ); + if ( sanpath->desc ) + acpi_add ( sanpath->desc ); + } + /* Start process */ process_add ( &sanpath->process ); @@ -606,6 +617,72 @@ int sandev_rw ( struct san_device *sandev, uint64_t lba, return 0; } +/** + * Describe SAN device + * + * @v sandev SAN device + * @ret rc Return status code + * + * Allow connections to progress until all existent path descriptors + * are complete. + */ +static int sandev_describe ( struct san_device *sandev ) { + struct san_path *sanpath; + struct acpi_descriptor *desc; + int rc; + + /* Wait for all paths to be either described or closed */ + while ( 1 ) { + + /* Allow connections to progress */ + step(); + + /* Fail if any closed path has an incomplete descriptor */ + list_for_each_entry ( sanpath, &sandev->closed, list ) { + desc = sanpath->desc; + if ( ! desc ) + continue; + if ( ( rc = desc->model->complete ( desc ) ) != 0 ) { + DBGC ( sandev, "SAN %#02x.%d could not be " + "described: %s\n", sandev->drive, + sanpath->index, strerror ( rc ) ); + return rc; + } + } + + /* Succeed if no paths have an incomplete descriptor */ + rc = 0; + list_for_each_entry ( sanpath, &sandev->opened, list ) { + desc = sanpath->desc; + if ( ! desc ) + continue; + if ( ( rc = desc->model->complete ( desc ) ) != 0 ) + break; + } + if ( rc == 0 ) + return 0; + } +} + +/** + * Remove SAN device descriptors + * + * @v sandev SAN device + */ +static void sandev_undescribe ( struct san_device *sandev ) { + struct san_path *sanpath; + unsigned int i; + + /* Remove all ACPI descriptors */ + for ( i = 0 ; i < sandev->paths ; i++ ) { + sanpath = &sandev->path[i]; + if ( sanpath->desc ) { + acpi_del ( sanpath->desc ); + sanpath->desc = NULL; + } + } +} + /** * Configure SAN device as a CD-ROM, if applicable * @@ -729,18 +806,25 @@ struct san_device * alloc_sandev ( struct uri **uris, unsigned int count, * Register SAN device * * @v sandev SAN device + * @v drive Drive number + * @v flags Flags * @ret rc Return status code */ -int register_sandev ( struct san_device *sandev ) { +int register_sandev ( struct san_device *sandev, unsigned int drive, + unsigned int flags ) { int rc; /* Check that drive number is not in use */ - if ( sandev_find ( sandev->drive ) != NULL ) { - DBGC ( sandev, "SAN %#02x is already in use\n", sandev->drive ); + if ( sandev_find ( drive ) != NULL ) { + DBGC ( sandev, "SAN %#02x is already in use\n", drive ); rc = -EADDRINUSE; goto err_in_use; } + /* Record drive number and flags */ + sandev->drive = drive; + sandev->flags = flags; + /* Check that device is capable of being opened (i.e. that all * URIs are well-formed and that at least one path is * working). @@ -748,6 +832,10 @@ int register_sandev ( struct san_device *sandev ) { if ( ( rc = sandev_reopen ( sandev ) ) != 0 ) goto err_reopen; + /* Describe device */ + if ( ( rc = sandev_describe ( sandev ) ) != 0 ) + goto err_describe; + /* Read device capacity */ if ( ( rc = sandev_command ( sandev, sandev_command_read_capacity, NULL ) ) != 0 ) @@ -766,8 +854,10 @@ int register_sandev ( struct san_device *sandev ) { list_del ( &sandev->list ); err_iso9660: err_capacity: + err_describe: err_reopen: sandev_restart ( sandev, rc ); + sandev_undescribe ( sandev ); err_in_use: return rc; } @@ -788,6 +878,9 @@ void unregister_sandev ( struct san_device *sandev ) { /* Shut down interfaces */ sandev_restart ( sandev, 0 ); + /* Remove ACPI descriptors */ + sandev_undescribe ( sandev ); + DBGC ( sandev, "SAN %#02x unregistered\n", sandev->drive ); } diff --git a/src/drivers/block/ibft.c b/src/drivers/block/ibft.c index 91a808d8..a9d21f9a 100644 --- a/src/drivers/block/ibft.c +++ b/src/drivers/block/ibft.c @@ -28,6 +28,7 @@ FILE_LICENCE ( BSD2 ); #include +#include #include #include #include @@ -38,6 +39,7 @@ FILE_LICENCE ( BSD2 ); #include #include #include +#include #include #include #include @@ -54,37 +56,31 @@ FILE_LICENCE ( BSD2 ); */ /** - * An iBFT created by iPXE - * - */ -struct ipxe_ibft { - /** The fixed section */ - struct ibft_table table; - /** The Initiator section */ - struct ibft_initiator initiator __attribute__ (( aligned ( 16 ) )); - /** The NIC section */ - struct ibft_nic nic __attribute__ (( aligned ( 16 ) )); - /** The Target section */ - struct ibft_target target __attribute__ (( aligned ( 16 ) )); - /** Strings block */ - char strings[0]; -} __attribute__ (( packed, aligned ( 16 ) )); - -/** - * iSCSI string block descriptor + * iSCSI string buffer * * This is an internal structure that we use to keep track of the * allocation of string data. */ struct ibft_strings { - /** The iBFT containing these strings */ - struct ibft_table *table; - /** Offset of first free byte within iBFT */ - size_t offset; - /** Total length of the iBFT */ + /** Strings data */ + char *data; + /** Starting offset of strings */ + size_t start; + /** Total length */ size_t len; }; +/** + * Align structure within iBFT + * + * @v len Unaligned length (or offset) + * @ret len Aligned length (or offset) + */ +static inline size_t ibft_align ( size_t len ) { + + return ( ( len + IBFT_ALIGN - 1 ) & ~( IBFT_ALIGN - 1 ) ); +} + /** * Fill in an IP address field within iBFT * @@ -141,15 +137,29 @@ static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) { */ static char * ibft_alloc_string ( struct ibft_strings *strings, struct ibft_string *string, size_t len ) { + size_t new_len; + char *new_data; + char *dest; - if ( ( strings->offset + len ) >= strings->len ) + /* Extend string data buffer */ + new_len = ( strings->len + len + 1 /* NUL */ ); + new_data = realloc ( strings->data, new_len ); + if ( ! new_data ) return NULL; + strings->data = new_data; - string->offset = cpu_to_le16 ( strings->offset ); + /* Fill in string field */ + string->offset = cpu_to_le16 ( strings->start + strings->len ); string->len = cpu_to_le16 ( len ); - strings->offset += ( len + 1 ); - return ( ( ( char * ) strings->table ) + string->offset ); + /* Zero string */ + dest = ( strings->data + strings->len ); + memset ( dest, 0, ( len + 1 /* NUL */ ) ); + + /* Update allocated length */ + strings->len = new_len; + + return dest; } /** @@ -217,8 +227,28 @@ static int ibft_set_string_setting ( struct settings *settings, */ static const char * ibft_string ( struct ibft_strings *strings, struct ibft_string *string ) { - return ( string->offset ? - ( ( ( char * ) strings->table ) + string->offset ) : NULL ); + size_t offset = le16_to_cpu ( string->offset ); + + return ( offset ? ( strings->data + offset - strings->start ) : NULL ); +} + +/** + * Check if network device is required for the iBFT + * + * @v netdev Network device + * @ret is_required Network device is required + */ +static int ibft_netdev_is_required ( struct net_device *netdev ) { + struct iscsi_session *iscsi; + struct sockaddr_tcpip *st_target; + + list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) { + st_target = ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr; + if ( tcpip_netdev ( st_target ) == netdev ) + return 1; + } + + return 0; } /** @@ -245,29 +275,33 @@ static int ibft_fill_nic ( struct ibft_nic *nic, nic->header.length = cpu_to_le16 ( sizeof ( *nic ) ); nic->header.flags = ( IBFT_FL_NIC_BLOCK_VALID | IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED ); + DBG ( "iBFT NIC %d is %s\n", nic->header.index, netdev->name ); /* Determine origin of IP address */ fetch_setting ( parent, &ip_setting, &origin, NULL, NULL, 0 ); nic->origin = ( ( origin == parent ) ? IBFT_NIC_ORIGIN_MANUAL : IBFT_NIC_ORIGIN_DHCP ); - DBG ( "iBFT NIC origin = %d\n", nic->origin ); + DBG ( "iBFT NIC %d origin = %d\n", nic->header.index, nic->origin ); /* Extract values from configuration settings */ ibft_set_ipaddr_setting ( parent, &nic->ip_address, &ip_setting, 1 ); - DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) ); + DBG ( "iBFT NIC %d IP = %s\n", + nic->header.index, ibft_ipaddr ( &nic->ip_address ) ); ibft_set_ipaddr_setting ( parent, &nic->gateway, &gateway_setting, 1 ); - DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) ); + DBG ( "iBFT NIC %d gateway = %s\n", + nic->header.index, ibft_ipaddr ( &nic->gateway ) ); ibft_set_ipaddr_setting ( NULL, &nic->dns[0], &dns_setting, ( sizeof ( nic->dns ) / sizeof ( nic->dns[0] ) ) ); ibft_set_ipaddr_setting ( parent, &nic->dhcp, &dhcp_server_setting, 1 ); - DBG ( "iBFT NIC DNS = %s", ibft_ipaddr ( &nic->dns[0] ) ); + DBG ( "iBFT NIC %d DNS = %s", + nic->header.index, ibft_ipaddr ( &nic->dns[0] ) ); DBG ( ", %s\n", ibft_ipaddr ( &nic->dns[1] ) ); if ( ( rc = ibft_set_string_setting ( NULL, strings, &nic->hostname, &hostname_setting ) ) != 0 ) return rc; - DBG ( "iBFT NIC hostname = %s\n", - ibft_string ( strings, &nic->hostname ) ); + DBG ( "iBFT NIC %d hostname = %s\n", + nic->header.index, ibft_string ( strings, &nic->hostname ) ); /* Derive subnet mask prefix from subnet mask */ fetch_ipv4_setting ( parent, &netmask_setting, &netmask_addr ); @@ -277,19 +311,24 @@ static int ibft_fill_nic ( struct ibft_nic *nic, netmask_addr.s_addr >>= 1; } nic->subnet_mask_prefix = netmask_count; - DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix ); + DBG ( "iBFT NIC %d subnet = /%d\n", + nic->header.index, nic->subnet_mask_prefix ); /* Extract values from net-device configuration */ nic->vlan = cpu_to_le16 ( vlan_tag ( netdev ) ); - DBG ( "iBFT NIC VLAN = %02x\n", le16_to_cpu ( nic->vlan ) ); + DBG ( "iBFT NIC %d VLAN = %02x\n", + nic->header.index, le16_to_cpu ( nic->vlan ) ); if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr, nic->mac_address ) ) != 0 ) { - DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) ); + DBG ( "Could not determine %s MAC: %s\n", + netdev->name, strerror ( rc ) ); return rc; } - DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) ); + DBG ( "iBFT NIC %d MAC = %s\n", + nic->header.index, eth_ntoa ( nic->mac_address ) ); nic->pci_bus_dev_func = cpu_to_le16 ( netdev->dev->desc.location ); - DBG ( "iBFT NIC PCI = %04x\n", le16_to_cpu ( nic->pci_bus_dev_func ) ); + DBG ( "iBFT NIC %d PCI = %04x\n", + nic->header.index, le16_to_cpu ( nic->pci_bus_dev_func ) ); return 0; } @@ -299,12 +338,10 @@ static int ibft_fill_nic ( struct ibft_nic *nic, * * @v initiator Initiator portion of iBFT * @v strings iBFT string block descriptor - * @v iscsi iSCSI session * @ret rc Return status code */ static int ibft_fill_initiator ( struct ibft_initiator *initiator, - struct ibft_strings *strings, - struct iscsi_session *iscsi ) { + struct ibft_strings *strings ) { int rc; /* Fill in common header */ @@ -314,16 +351,57 @@ static int ibft_fill_initiator ( struct ibft_initiator *initiator, initiator->header.flags = ( IBFT_FL_INITIATOR_BLOCK_VALID | IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED ); - /* Fill in hostname */ - if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name, - iscsi->initiator_iqn ) ) != 0 ) + /* Fill in initiator name */ + if ( ( rc = ibft_set_string_setting ( NULL, strings, + &initiator->initiator_name, + &initiator_iqn_setting ) ) != 0 ) return rc; - DBG ( "iBFT initiator hostname = %s\n", + DBG ( "iBFT initiator name = %s\n", ibft_string ( strings, &initiator->initiator_name ) ); return 0; } +/** + * Fill in Target NIC association + * + * @v target Target portion of iBFT + * @v iscsi iSCSI session + * @ret rc Return status code + */ +static int ibft_fill_target_nic_association ( struct ibft_target *target, + struct iscsi_session *iscsi ) { + struct sockaddr_tcpip *st_target = + ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr; + struct net_device *associated; + struct net_device *netdev; + + /* Find network device used to reach target */ + associated = tcpip_netdev ( st_target ); + if ( ! associated ) { + DBG ( "iBFT target %d has no net device\n", + target->header.index ); + return -EHOSTUNREACH; + } + + /* Calculate association */ + for_each_netdev ( netdev ) { + if ( netdev == associated ) { + DBG ( "iBFT target %d uses NIC %d (%s)\n", + target->header.index, target->nic_association, + netdev->name ); + return 0; + } + if ( ! ibft_netdev_is_required ( netdev ) ) + continue; + target->nic_association++; + } + + DBG ( "iBFT target %d has impossible NIC %s\n", + target->header.index, netdev->name ); + return -EINVAL; +} + /** * Fill in Target CHAP portion of iBFT * @@ -347,12 +425,12 @@ static int ibft_fill_target_chap ( struct ibft_target *target, if ( ( rc = ibft_set_string ( strings, &target->chap_name, iscsi->initiator_username ) ) != 0 ) return rc; - DBG ( "iBFT target username = %s\n", + DBG ( "iBFT target %d username = %s\n", target->header.index, ibft_string ( strings, &target->chap_name ) ); if ( ( rc = ibft_set_string ( strings, &target->chap_secret, iscsi->initiator_password ) ) != 0 ) return rc; - DBG ( "iBFT target password = \n" ); + DBG ( "iBFT target %d password = \n", target->header.index ); return 0; } @@ -382,12 +460,13 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target, if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name, iscsi->target_username ) ) != 0 ) return rc; - DBG ( "iBFT target reverse username = %s\n", + DBG ( "iBFT target %d reverse username = %s\n", target->header.index, ibft_string ( strings, &target->chap_name ) ); if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret, iscsi->target_password ) ) != 0 ) return rc; - DBG ( "iBFT target reverse password = \n" ); + DBG ( "iBFT target %d reverse password = \n", + target->header.index ); return 0; } @@ -403,6 +482,8 @@ static int ibft_fill_target_reverse_chap ( struct ibft_target *target, static int ibft_fill_target ( struct ibft_target *target, struct ibft_strings *strings, struct iscsi_session *iscsi ) { + struct sockaddr_tcpip *st_target = + ( struct sockaddr_tcpip * ) &iscsi->target_sockaddr; struct sockaddr_in *sin_target = ( struct sockaddr_in * ) &iscsi->target_sockaddr; int rc; @@ -416,17 +497,21 @@ static int ibft_fill_target ( struct ibft_target *target, /* Fill in Target values */ ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr ); - DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) ); - target->socket = cpu_to_le16 ( ntohs ( sin_target->sin_port ) ); - DBG ( "iBFT target port = %d\n", target->socket ); + DBG ( "iBFT target %d IP = %s\n", + target->header.index, ibft_ipaddr ( &target->ip_address ) ); + target->socket = cpu_to_le16 ( ntohs ( st_target->st_port ) ); + DBG ( "iBFT target %d port = %d\n", + target->header.index, target->socket ); memcpy ( &target->boot_lun, &iscsi->lun, sizeof ( target->boot_lun ) ); - DBG ( "iBFT target boot LUN = " SCSI_LUN_FORMAT "\n", - SCSI_LUN_DATA ( target->boot_lun ) ); + DBG ( "iBFT target %d boot LUN = " SCSI_LUN_FORMAT "\n", + target->header.index, SCSI_LUN_DATA ( target->boot_lun ) ); if ( ( rc = ibft_set_string ( strings, &target->target_name, iscsi->target_iqn ) ) != 0 ) return rc; - DBG ( "iBFT target name = %s\n", + DBG ( "iBFT target %d name = %s\n", target->header.index, ibft_string ( strings, &target->target_name ) ); + if ( ( rc = ibft_fill_target_nic_association ( target, iscsi ) ) != 0 ) + return rc; if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 ) return rc; if ( ( rc = ibft_fill_target_reverse_chap ( target, strings, @@ -437,62 +522,159 @@ static int ibft_fill_target ( struct ibft_target *target, } /** - * Fill in iBFT + * Check if iBFT descriptor is complete * - * @v iscsi iSCSI session - * @v acpi ACPI table - * @v len Length of ACPI table + * @v desc ACPI descriptor * @ret rc Return status code */ -int ibft_describe ( struct iscsi_session *iscsi, - struct acpi_description_header *acpi, - size_t len ) { - struct ipxe_ibft *ibft = - container_of ( acpi, struct ipxe_ibft, table.acpi ); - struct ibft_strings strings = { - .table = &ibft->table, - .offset = offsetof ( typeof ( *ibft ), strings ), - .len = len, - }; - struct net_device *netdev; - int rc; +static int ibft_complete ( struct acpi_descriptor *desc ) { + struct iscsi_session *iscsi = + container_of ( desc, struct iscsi_session, desc ); - /* Ugly hack. Now that we have a generic interface mechanism - * that can support ioctls, we can potentially eliminate this. - */ - netdev = last_opened_netdev(); - if ( ! netdev ) { - DBGC ( iscsi, "iSCSI %p cannot guess network device\n", - iscsi ); - return -ENODEV; - } - - /* Fill in ACPI header */ - ibft->table.acpi.signature = cpu_to_le32 ( IBFT_SIG ); - ibft->table.acpi.length = cpu_to_le32 ( len ); - ibft->table.acpi.revision = 1; - - /* Fill in Control block */ - ibft->table.control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL; - ibft->table.control.header.version = 1; - ibft->table.control.header.length = - cpu_to_le16 ( sizeof ( ibft->table.control ) ); - ibft->table.control.initiator = - cpu_to_le16 ( offsetof ( typeof ( *ibft ), initiator ) ); - ibft->table.control.nic_0 = - cpu_to_le16 ( offsetof ( typeof ( *ibft ), nic ) ); - ibft->table.control.target_0 = - cpu_to_le16 ( offsetof ( typeof ( *ibft ), target ) ); - - /* Fill in NIC, Initiator and Target blocks */ - if ( ( rc = ibft_fill_nic ( &ibft->nic, &strings, netdev ) ) != 0 ) - return rc; - if ( ( rc = ibft_fill_initiator ( &ibft->initiator, &strings, - iscsi ) ) != 0 ) - return rc; - if ( ( rc = ibft_fill_target ( &ibft->target, &strings, - iscsi ) ) != 0 ) - return rc; + /* Fail if we do not yet have the target address */ + if ( ! iscsi->target_sockaddr.sa_family ) + return -EAGAIN; return 0; } + +/** + * Install iBFT + * + * @v install Installation method + * @ret rc Return status code + */ +static int ibft_install ( int ( * install ) ( struct acpi_header *acpi ) ) { + struct net_device *netdev; + struct iscsi_session *iscsi; + struct ibft_table *table; + struct ibft_initiator *initiator; + struct ibft_nic *nic; + struct ibft_target *target; + struct ibft_strings strings; + struct acpi_header *acpi; + void *data; + unsigned int targets = 0; + unsigned int pairs = 0; + size_t offset = 0; + size_t table_len; + size_t control_len; + size_t initiator_offset; + size_t nic_offset; + size_t target_offset; + size_t strings_offset; + size_t len; + unsigned int i; + int rc; + + /* Calculate table sizes and offsets */ + list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) + targets++; + pairs = ( sizeof ( table->control.pair ) / + sizeof ( table->control.pair[0] ) ); + if ( pairs < targets ) + pairs = targets; + offset = offsetof ( typeof ( *table ), control.pair ); + offset += ( pairs * sizeof ( table->control.pair[0] ) ); + table_len = offset; + control_len = ( table_len - offsetof ( typeof ( *table ), control ) ); + offset = ibft_align ( offset ); + initiator_offset = offset; + offset += ibft_align ( sizeof ( *initiator ) ); + nic_offset = offset; + offset += ( pairs * ibft_align ( sizeof ( *nic ) ) ); + target_offset = offset; + offset += ( pairs * ibft_align ( sizeof ( *target ) ) ); + strings_offset = offset; + strings.data = NULL; + strings.start = strings_offset; + strings.len = 0; + len = offset; + + /* Allocate table */ + data = zalloc ( len ); + if ( ! data ) { + rc = -ENOMEM; + goto err_alloc; + } + + /* Fill in Control block */ + table = data; + table->control.header.structure_id = IBFT_STRUCTURE_ID_CONTROL; + table->control.header.version = 1; + table->control.header.length = cpu_to_le16 ( control_len ); + + /* Fill in Initiator block */ + initiator = ( data + initiator_offset ); + table->control.initiator = cpu_to_le16 ( initiator_offset ); + if ( ( rc = ibft_fill_initiator ( initiator, &strings ) ) != 0 ) + goto err_initiator; + + /* Fill in NIC blocks */ + i = 0; + for_each_netdev ( netdev ) { + if ( ! ibft_netdev_is_required ( netdev ) ) + continue; + assert ( i < pairs ); + table->control.pair[i].nic = nic_offset; + nic = ( data + nic_offset ); + nic->header.index = i; + if ( ( rc = ibft_fill_nic ( nic, &strings, netdev ) ) != 0 ) + goto err_nic; + i++; + nic_offset += ibft_align ( sizeof ( *nic ) ); + } + + /* Fill in Target blocks */ + i = 0; + list_for_each_entry ( iscsi, &ibft_model.descs, desc.list ) { + assert ( i < pairs ); + table->control.pair[i].target = target_offset; + target = ( data + target_offset ); + target->header.index = i; + if ( ( rc = ibft_fill_target ( target, &strings, iscsi ) ) != 0) + goto err_target; + i++; + target_offset += ibft_align ( sizeof ( *target ) ); + } + + /* Reallocate table to include space for strings */ + len += strings.len; + acpi = realloc ( data, len ); + if ( ! acpi ) + goto err_realloc; + data = NULL; + + /* Fill in ACPI header */ + acpi->signature = cpu_to_le32 ( IBFT_SIG ); + acpi->length = cpu_to_le32 ( len ); + acpi->revision = 1; + + /* Append strings */ + memcpy ( ( ( ( void * ) acpi ) + strings_offset ), strings.data, + strings.len ); + + /* Install ACPI table */ + if ( ( rc = install ( acpi ) ) != 0 ) { + DBG ( "iBFT could not install: %s\n", strerror ( rc ) ); + goto err_install; + } + + err_install: + free ( acpi ); + err_realloc: + err_target: + err_nic: + err_initiator: + free ( data ); + err_alloc: + free ( strings.data ); + return rc; +} + +/** iBFT model */ +struct acpi_model ibft_model __acpi_model = { + .descs = LIST_HEAD_INIT ( ibft_model.descs ), + .complete = ibft_complete, + .install = ibft_install, +}; diff --git a/src/drivers/block/srp.c b/src/drivers/block/srp.c index 7edf69ac..ab481251 100644 --- a/src/drivers/block/srp.c +++ b/src/drivers/block/srp.c @@ -113,13 +113,6 @@ struct srp_device { /** Login completed successfully */ int logged_in; - /** Initiator port ID (for boot firmware table) */ - union srp_port_id initiator; - /** Target port ID (for boot firmware table) */ - union srp_port_id target; - /** SCSI LUN (for boot firmware table) */ - struct scsi_lun lun; - /** List of active commands */ struct list_head commands; }; @@ -684,61 +677,6 @@ static size_t srpdev_window ( struct srp_device *srpdev ) { return ( srpdev->logged_in ? ~( ( size_t ) 0 ) : 0 ); } -/** - * A (transport-independent) sBFT created by iPXE - */ -struct ipxe_sbft { - /** The table header */ - struct sbft_table table; - /** The SCSI subtable */ - struct sbft_scsi_subtable scsi; - /** The SRP subtable */ - struct sbft_srp_subtable srp; -} __attribute__ (( packed, aligned ( 16 ) )); - -/** - * Describe SRP device in an ACPI table - * - * @v srpdev SRP device - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code - */ -static int srpdev_describe ( struct srp_device *srpdev, - struct acpi_description_header *acpi, - size_t len ) { - struct ipxe_sbft *sbft = - container_of ( acpi, struct ipxe_sbft, table.acpi ); - int rc; - - /* Sanity check */ - if ( len < sizeof ( *sbft ) ) - return -ENOBUFS; - - /* Populate table */ - sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG ); - sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) ); - sbft->table.acpi.revision = 1; - sbft->table.scsi_offset = - cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) ); - memcpy ( &sbft->scsi.lun, &srpdev->lun, sizeof ( sbft->scsi.lun ) ); - sbft->table.srp_offset = - cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) ); - memcpy ( &sbft->srp.initiator, &srpdev->initiator, - sizeof ( sbft->srp.initiator ) ); - memcpy ( &sbft->srp.target, &srpdev->target, - sizeof ( sbft->srp.target ) ); - - /* Ask transport layer to describe transport-specific portions */ - if ( ( rc = acpi_describe ( &srpdev->socket, acpi, len ) ) != 0 ) { - DBGC ( srpdev, "SRP %p cannot describe transport layer: %s\n", - srpdev, strerror ( rc ) ); - return rc; - } - - return 0; -} - /** SRP device socket interface operations */ static struct interface_operation srpdev_socket_op[] = { INTF_OP ( xfer_deliver, struct srp_device *, srpdev_deliver ), @@ -755,7 +693,6 @@ static struct interface_operation srpdev_scsi_op[] = { INTF_OP ( scsi_command, struct srp_device *, srpdev_scsi_command ), INTF_OP ( xfer_window, struct srp_device *, srpdev_window ), INTF_OP ( intf_close, struct srp_device *, srpdev_close ), - INTF_OP ( acpi_describe, struct srp_device *, srpdev_describe ), }; /** SRP device SCSI interface descriptor */ @@ -797,11 +734,6 @@ int srp_open ( struct interface *block, struct interface *socket, ntohl ( target->dwords[0] ), ntohl ( target->dwords[1] ), ntohl ( target->dwords[2] ), ntohl ( target->dwords[3] ) ); - /* Preserve parameters required for boot firmware table */ - memcpy ( &srpdev->initiator, initiator, sizeof ( srpdev->initiator ) ); - memcpy ( &srpdev->target, target, sizeof ( srpdev->target ) ); - memcpy ( &srpdev->lun, lun, sizeof ( srpdev->lun ) ); - /* Attach to socket interface and initiate login */ intf_plug_plug ( &srpdev->socket, socket ); tag = srp_new_tag ( srpdev ); diff --git a/src/include/ipxe/acpi.h b/src/include/ipxe/acpi.h index 17d29b9d..f87b8ae9 100644 --- a/src/include/ipxe/acpi.h +++ b/src/include/ipxe/acpi.h @@ -10,8 +10,12 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include +#include +#include +#include #include #include +#include /** * An ACPI description header @@ -19,7 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * This is the structure common to the start of all ACPI system * description tables. */ -struct acpi_description_header { +struct acpi_header { /** ACPI signature (4 ASCII characters) */ uint32_t signature; /** Length of table, in bytes, including header */ @@ -40,6 +44,22 @@ struct acpi_description_header { uint32_t asl_compiler_revision; } __attribute__ (( packed )); +/** + * Transcribe ACPI table signature (for debugging) + * + * @v signature ACPI table signature + * @ret name ACPI table signature name + */ +static inline const char * acpi_name ( uint32_t signature ) { + static union { + uint32_t signature; + char name[5]; + } u; + + u.signature = cpu_to_le32 ( signature ); + return u.name; +} + /** * Build ACPI signature * @@ -87,7 +107,7 @@ struct acpi_rsdp { /** ACPI Root System Description Table (RSDT) */ struct acpi_rsdt { /** ACPI header */ - struct acpi_description_header acpi; + struct acpi_header acpi; /** ACPI table entries */ uint32_t entry[0]; } __attribute__ (( packed )); @@ -98,7 +118,7 @@ struct acpi_rsdt { /** Fixed ACPI Description Table (FADT) */ struct acpi_fadt { /** ACPI header */ - struct acpi_description_header acpi; + struct acpi_header acpi; /** Physical address of FACS */ uint32_t facs; /** Physical address of DSDT */ @@ -122,17 +142,70 @@ struct acpi_fadt { /** Secondary System Description Table (SSDT) signature */ #define SSDT_SIGNATURE ACPI_SIGNATURE ( 'S', 'S', 'D', 'T' ) -extern int acpi_describe ( struct interface *interface, - struct acpi_description_header *acpi, size_t len ); -#define acpi_describe_TYPE( object_type ) \ - typeof ( int ( object_type, \ - struct acpi_description_header *acpi, \ - size_t len ) ) +/** An ACPI descriptor (used to construct ACPI tables) */ +struct acpi_descriptor { + /** Reference count of containing object */ + struct refcnt *refcnt; + /** Table model */ + struct acpi_model *model; + /** List of ACPI descriptors for this model */ + struct list_head list; +}; -extern void acpi_fix_checksum ( struct acpi_description_header *acpi ); +/** + * Initialise ACPI descriptor + * + * @v desc ACPI descriptor + * @v model Table model + * @v refcnt Reference count + */ +static inline __attribute__ (( always_inline )) void +acpi_init ( struct acpi_descriptor *desc, struct acpi_model *model, + struct refcnt *refcnt ) { + + desc->refcnt = refcnt; + desc->model = model; + INIT_LIST_HEAD ( &desc->list ); +} + +/** An ACPI table model */ +struct acpi_model { + /** List of descriptors */ + struct list_head descs; + /** + * Check if ACPI descriptor is complete + * + * @v desc ACPI descriptor + * @ret rc Return status code + */ + int ( * complete ) ( struct acpi_descriptor *desc ); + /** + * Install ACPI tables + * + * @v install Installation method + * @ret rc Return status code + */ + int ( * install ) ( int ( * install ) ( struct acpi_header *acpi ) ); +}; + +/** ACPI models */ +#define ACPI_MODELS __table ( struct acpi_model, "acpi_models" ) + +/** Declare an ACPI model */ +#define __acpi_model __table_entry ( ACPI_MODELS, 01 ) + +extern struct acpi_descriptor * +acpi_describe ( struct interface *interface ); +#define acpi_describe_TYPE( object_type ) \ + typeof ( struct acpi_descriptor * ( object_type ) ) + +extern void acpi_fix_checksum ( struct acpi_header *acpi ); extern userptr_t acpi_find_rsdt ( userptr_t ebda ); extern userptr_t acpi_find ( userptr_t rsdt, uint32_t signature, unsigned int index ); extern int acpi_sx ( userptr_t rsdt, uint32_t signature ); +extern void acpi_add ( struct acpi_descriptor *desc ); +extern void acpi_del ( struct acpi_descriptor *desc ); +extern int acpi_install ( int ( * install ) ( struct acpi_header *acpi ) ); #endif /* _IPXE_ACPI_H */ diff --git a/src/include/ipxe/aoe.h b/src/include/ipxe/aoe.h index 0c656e7c..a51044d1 100644 --- a/src/include/ipxe/aoe.h +++ b/src/include/ipxe/aoe.h @@ -117,7 +117,7 @@ struct aoehdr { */ struct abft_table { /** ACPI header */ - struct acpi_description_header acpi; + struct acpi_header acpi; /** AoE shelf */ uint16_t shelf; /** AoE slot */ diff --git a/src/include/ipxe/ibft.h b/src/include/ipxe/ibft.h index 35f15105..51ce781a 100644 --- a/src/include/ipxe/ibft.h +++ b/src/include/ipxe/ibft.h @@ -49,6 +49,9 @@ FILE_LICENCE ( BSD2 ); /** iSCSI Boot Firmware Table signature */ #define IBFT_SIG ACPI_SIGNATURE ( 'i', 'B', 'F', 'T' ) +/** Alignment of structures within iBFT */ +#define IBFT_ALIGN 16 + /** An offset from the start of the iBFT */ typedef uint16_t ibft_off_t; @@ -97,6 +100,20 @@ struct ibft_header { uint8_t flags; } __attribute__ (( packed )); +/** + * iBFT NIC and Target offset pair + * + * There is no implicit relation between the NIC and the Target, but + * using this structure simplifies the table construction code while + * matching the expected table layout. + */ +struct ibft_offset_pair { + /** Offset to NIC structure */ + ibft_off_t nic; + /** Offset to Target structure */ + ibft_off_t target; +} __attribute__ (( packed )); + /** * iBFT Control structure * @@ -108,14 +125,8 @@ struct ibft_control { uint16_t extensions; /** Offset to Initiator structure */ ibft_off_t initiator; - /** Offset to NIC structure for NIC 0 */ - ibft_off_t nic_0; - /** Offset to Target structure for target 0 */ - ibft_off_t target_0; - /** Offset to NIC structure for NIC 1 */ - ibft_off_t nic_1; - /** Offset to Target structure for target 1 */ - ibft_off_t target_1; + /** Offsets to NIC and Target structures */ + struct ibft_offset_pair pair[2]; } __attribute__ (( packed )); /** Structure ID for Control section */ @@ -262,18 +273,13 @@ struct ibft_target { */ struct ibft_table { /** ACPI header */ - struct acpi_description_header acpi; + struct acpi_header acpi; /** Reserved */ uint8_t reserved[12]; /** Control structure */ struct ibft_control control; } __attribute__ (( packed )); -struct iscsi_session; -struct net_device; - -extern int ibft_describe ( struct iscsi_session *iscsi, - struct acpi_description_header *acpi, - size_t len ); +extern struct acpi_model ibft_model __acpi_model; #endif /* _IPXE_IBFT_H */ diff --git a/src/include/ipxe/iscsi.h b/src/include/ipxe/iscsi.h index c75ff418..966cf52b 100644 --- a/src/include/ipxe/iscsi.h +++ b/src/include/ipxe/iscsi.h @@ -16,6 +16,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include +#include /** Default iSCSI port */ #define ISCSI_PORT 3260 @@ -647,6 +649,8 @@ struct iscsi_session { struct sockaddr target_sockaddr; /** SCSI LUN (for boot firmware table) */ struct scsi_lun lun; + /** ACPI descriptor */ + struct acpi_descriptor desc; }; /** iSCSI session is currently in the security negotiation phase */ @@ -697,4 +701,7 @@ struct iscsi_session { /** Default initiator IQN prefix */ #define ISCSI_DEFAULT_IQN_PREFIX "iqn.2010-04.org.ipxe" +extern const struct setting +initiator_iqn_setting __setting ( SETTING_SANBOOT_EXTRA, initiator-iqn ); + #endif /* _IPXE_ISCSI_H */ diff --git a/src/include/ipxe/sanboot.h b/src/include/ipxe/sanboot.h index 64b665a5..8737bbc0 100644 --- a/src/include/ipxe/sanboot.h +++ b/src/include/ipxe/sanboot.h @@ -18,6 +18,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** A SAN path */ @@ -37,6 +38,9 @@ struct san_path { struct process process; /** Path status */ int path_rc; + + /** ACPI descriptor (if applicable) */ + struct acpi_descriptor *desc; }; /** A SAN device */ @@ -48,6 +52,8 @@ struct san_device { /** Drive number */ unsigned int drive; + /** Flags */ + unsigned int flags; /** Command interface */ struct interface command; @@ -83,6 +89,12 @@ struct san_device { struct san_path path[0]; }; +/** SAN device flags */ +enum san_device_flags { + /** Device should not be included in description tables */ + SAN_NO_DESCRIBE = 0x0001, +}; + /** * Calculate static inline sanboot API function name * @@ -126,9 +138,11 @@ struct san_device { * @v drive Drive number * @v uris List of URIs * @v count Number of URIs + * @v flags Flags * @ret drive Drive number, or negative error */ -int san_hook ( unsigned int drive, struct uri **uris, unsigned int count ); +int san_hook ( unsigned int drive, struct uri **uris, unsigned int count, + unsigned int flags ); /** * Unhook SAN device @@ -146,12 +160,11 @@ void san_unhook ( unsigned int drive ); int san_boot ( unsigned int drive ); /** - * Describe SAN device for SAN-booted operating system + * Describe SAN devices for SAN-booted operating system * - * @v drive Drive number * @ret rc Return status code */ -int san_describe ( unsigned int drive ); +int san_describe ( void ); extern struct list_head san_devices; @@ -230,7 +243,8 @@ extern int sandev_rw ( struct san_device *sandev, uint64_t lba, userptr_t buffer, size_t len ) ); extern struct san_device * alloc_sandev ( struct uri **uris, unsigned int count, size_t priv_size ); -extern int register_sandev ( struct san_device *sandev ); +extern int register_sandev ( struct san_device *sandev, unsigned int drive, + unsigned int flags ); extern void unregister_sandev ( struct san_device *sandev ); extern unsigned int san_default_drive ( void ); diff --git a/src/include/ipxe/srp.h b/src/include/ipxe/srp.h index 8d7f799c..3abb0995 100644 --- a/src/include/ipxe/srp.h +++ b/src/include/ipxe/srp.h @@ -790,7 +790,7 @@ typedef uint16_t sbft_off_t; */ struct sbft_table { /** ACPI header */ - struct acpi_description_header acpi; + struct acpi_header acpi; /** Offset to SCSI subtable */ sbft_off_t scsi_offset; /** Offset to SRP subtable */ diff --git a/src/interface/efi/efi_block.c b/src/interface/efi/efi_block.c index 9679fc0d..fa2271b3 100644 --- a/src/interface/efi/efi_block.c +++ b/src/interface/efi/efi_block.c @@ -254,10 +254,11 @@ static void efi_block_connect ( struct san_device *sandev ) { * @v drive Drive number * @v uris List of URIs * @v count Number of URIs + * @v flags Flags * @ret drive Drive number, or negative error */ static int efi_block_hook ( unsigned int drive, struct uri **uris, - unsigned int count ) { + unsigned int count, unsigned int flags ) { EFI_BOOT_SERVICES *bs = efi_systab->BootServices; EFI_DEVICE_PATH_PROTOCOL *end; struct efi_block_vendor_path *vendor; @@ -301,7 +302,6 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris, rc = -ENOMEM; goto err_alloc; } - sandev->drive = drive; block = sandev->priv; block->sandev = sandev; block->media.MediaPresent = 1; @@ -331,12 +331,12 @@ static int efi_block_hook ( unsigned int drive, struct uri **uris, end->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; end->Length[0] = sizeof ( *end ); DBGC ( sandev, "EFIBLK %#02x has device path %s\n", - sandev->drive, efi_devpath_text ( block->path ) ); + drive, efi_devpath_text ( block->path ) ); /* Register SAN device */ - if ( ( rc = register_sandev ( sandev ) ) != 0 ) { + if ( ( rc = register_sandev ( sandev, drive, flags ) ) != 0 ) { DBGC ( sandev, "EFIBLK %#02x could not register: %s\n", - sandev->drive, strerror ( rc ) ); + drive, strerror ( rc ) ); goto err_register; } @@ -408,85 +408,105 @@ static void efi_block_unhook ( unsigned int drive ) { sandev_put ( sandev ); } +/** An installed ACPI table */ +struct efi_acpi_table { + /** List of installed tables */ + struct list_head list; + /** Table key */ + UINTN key; +}; + +/** List of installed ACPI tables */ +static LIST_HEAD ( efi_acpi_tables ); + /** - * Describe EFI block device + * Install ACPI table * - * @v drive Drive number + * @v hdr ACPI description header * @ret rc Return status code */ -static int efi_block_describe ( unsigned int drive ) { - static union { - /** ACPI header */ - struct acpi_description_header acpi; - /** Padding */ - char pad[768]; - } xbftab; - static UINTN key; - struct san_device *sandev; - struct san_path *sanpath; - size_t len; +static int efi_block_install ( struct acpi_header *hdr ) { + size_t len = le32_to_cpu ( hdr->length ); + struct efi_acpi_table *installed; EFI_STATUS efirc; int rc; - /* Find SAN device */ - sandev = sandev_find ( drive ); - if ( ! sandev ) { - DBG ( "EFIBLK cannot find drive %#02x\n", drive ); - return -ENODEV; + /* Allocate installed table record */ + installed = zalloc ( sizeof ( *installed ) ); + if ( ! installed ) { + rc = -ENOMEM; + goto err_alloc; } + /* Fill in common parameters */ + strncpy ( hdr->oem_id, "FENSYS", sizeof ( hdr->oem_id ) ); + strncpy ( hdr->oem_table_id, "iPXE", sizeof ( hdr->oem_table_id ) ); + + /* Fix up ACPI checksum */ + acpi_fix_checksum ( hdr ); + + /* Install table */ + if ( ( efirc = acpi->InstallAcpiTable ( acpi, hdr, len, + &installed->key ) ) != 0 ){ + rc = -EEFI ( efirc ); + DBGC ( acpi, "EFIBLK could not install %s: %s\n", + acpi_name ( hdr->signature ), strerror ( rc ) ); + DBGC_HDA ( acpi, 0, hdr, len ); + goto err_install; + } + + /* Add to list of installed tables */ + list_add_tail ( &installed->list, &efi_acpi_tables ); + + DBGC ( acpi, "EFIBLK installed %s as ACPI table %#lx:\n", + acpi_name ( hdr->signature ), + ( ( unsigned long ) installed->key ) ); + DBGC_HDA ( acpi, 0, hdr, len ); + return 0; + + list_del ( &installed->list ); + err_install: + free ( installed ); + err_alloc: + return rc; +} + +/** + * Describe EFI block devices + * + * @ret rc Return status code + */ +static int efi_block_describe ( void ) { + struct efi_acpi_table *installed; + struct efi_acpi_table *tmp; + UINTN key; + EFI_STATUS efirc; + int rc; + /* Sanity check */ if ( ! acpi ) { - DBGC ( sandev, "EFIBLK %#02x has no ACPI table protocol\n", - sandev->drive ); + DBG ( "EFIBLK has no ACPI table protocol\n" ); return -ENOTSUP; } - /* Remove existing table, if any */ - if ( key ) { + /* Uninstall any existing ACPI tables */ + list_for_each_entry_safe ( installed, tmp, &efi_acpi_tables, list ) { + key = installed->key; if ( ( efirc = acpi->UninstallAcpiTable ( acpi, key ) ) != 0 ) { rc = -EEFI ( efirc ); - DBGC ( sandev, "EFIBLK %#02x could not uninstall ACPI " - "table: %s\n", sandev->drive, strerror ( rc ) ); + DBGC ( acpi, "EFIBLK could not uninstall ACPI table " + "%#lx: %s\n", ( ( unsigned long ) key ), + strerror ( rc ) ); /* Continue anyway */ } - key = 0; + list_del ( &installed->list ); + free ( installed ); } - /* Reopen block device if necessary */ - if ( sandev_needs_reopen ( sandev ) && - ( ( rc = sandev_reopen ( sandev ) ) != 0 ) ) - return rc; - sanpath = sandev->active; - assert ( sanpath != NULL ); - - /* Clear table */ - memset ( &xbftab, 0, sizeof ( xbftab ) ); - - /* 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, "EFIBLK %#02x could not create ACPI " - "description: %s\n", sandev->drive, strerror ( rc ) ); - return rc; - } - len = le32_to_cpu ( xbftab.acpi.length ); - - /* Fix up ACPI checksum */ - acpi_fix_checksum ( &xbftab.acpi ); - - /* Install table */ - if ( ( efirc = acpi->InstallAcpiTable ( acpi, &xbftab, len, - &key ) ) != 0 ) { - rc = -EEFI ( efirc ); - DBGC ( sandev, "EFIBLK %#02x could not install ACPI table: " - "%s\n", sandev->drive, strerror ( rc ) ); + /* Install ACPI tables */ + if ( ( rc = acpi_install ( efi_block_install ) ) != 0 ) { + DBGC ( acpi, "EFIBLK could not install ACPI tables: %s\n", + strerror ( rc ) ); return rc; } diff --git a/src/net/aoe.c b/src/net/aoe.c index 2da8655b..3a6611d0 100644 --- a/src/net/aoe.c +++ b/src/net/aoe.c @@ -53,6 +53,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); FEATURE ( FEATURE_PROTOCOL, "AoE", DHCP_EB_FEATURE_AOE, 1 ); struct net_protocol aoe_protocol __net_protocol; +struct acpi_model abft_model __acpi_model; /****************************************************************************** * @@ -91,6 +92,9 @@ struct aoe_device { struct interface config; /** Device is configued */ int configured; + + /** ACPI descriptor */ + struct acpi_descriptor desc; }; /** An AoE command */ @@ -790,32 +794,13 @@ static struct device * aoedev_identify_device ( struct aoe_device *aoedev ) { } /** - * Describe AoE device in an ACPI table + * Get AoE ACPI descriptor * * @v aoedev AoE device - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code + * @ret desc ACPI descriptor */ -static int aoedev_describe ( struct aoe_device *aoedev, - struct acpi_description_header *acpi, - size_t len ) { - struct abft_table *abft = - container_of ( acpi, struct abft_table, acpi ); - - /* Sanity check */ - if ( len < sizeof ( *abft ) ) - return -ENOBUFS; - - /* Populate table */ - abft->acpi.signature = cpu_to_le32 ( ABFT_SIG ); - abft->acpi.length = cpu_to_le32 ( sizeof ( *abft ) ); - abft->acpi.revision = 1; - abft->shelf = cpu_to_le16 ( aoedev->major ); - abft->slot = aoedev->minor; - memcpy ( abft->mac, aoedev->netdev->ll_addr, sizeof ( abft->mac ) ); - - return 0; +static struct acpi_descriptor * aoedev_describe ( struct aoe_device *aoedev ) { + return &aoedev->desc; } /** AoE device ATA interface operations */ @@ -869,6 +854,7 @@ static int aoedev_open ( struct interface *parent, struct net_device *netdev, aoedev->minor = minor; memcpy ( aoedev->target, netdev->ll_broadcast, netdev->ll_protocol->ll_addr_len ); + acpi_init ( &aoedev->desc, &abft_model, &aoedev->refcnt ); /* Initiate configuration */ if ( ( rc = aoedev_cfg_command ( aoedev, &aoedev->config ) ) < 0 ) { @@ -1059,3 +1045,61 @@ struct uri_opener aoe_uri_opener __uri_opener = { .scheme = "aoe", .open = aoe_open, }; + +/****************************************************************************** + * + * AoE boot firmware table (aBFT) + * + ****************************************************************************** + */ + +/** + * Check if AoE boot firmware table descriptor is complete + * + * @v desc ACPI descriptor + * @ret rc Return status code + */ +static int abft_complete ( struct acpi_descriptor *desc __unused ) { + return 0; +} + +/** + * Install AoE boot firmware table(s) + * + * @v install Installation method + * @ret rc Return status code + */ +static int abft_install ( int ( * install ) ( struct acpi_header *acpi ) ) { + struct aoe_device *aoedev; + struct abft_table abft; + int rc; + + list_for_each_entry ( aoedev, &abft_model.descs, desc.list ) { + + /* Populate table */ + memset ( &abft, 0, sizeof ( abft ) ); + abft.acpi.signature = cpu_to_le32 ( ABFT_SIG ); + abft.acpi.length = cpu_to_le32 ( sizeof ( abft ) ); + abft.acpi.revision = 1; + abft.shelf = cpu_to_le16 ( aoedev->major ); + abft.slot = aoedev->minor; + memcpy ( abft.mac, aoedev->netdev->ll_addr, + sizeof ( abft.mac ) ); + + /* Install table */ + if ( ( rc = install ( &abft.acpi ) ) != 0 ) { + DBGC ( aoedev, "AoE %s could not install aBFT: %s\n", + aoedev_name ( aoedev ), strerror ( rc ) ); + return rc; + } + } + + return 0; +} + +/** aBFT model */ +struct acpi_model abft_model __acpi_model = { + .descs = LIST_HEAD_INIT ( abft_model.descs ), + .complete = abft_complete, + .install = abft_install, +}; diff --git a/src/net/fcp.c b/src/net/fcp.c index 930bf7dd..d92cfdcf 100644 --- a/src/net/fcp.c +++ b/src/net/fcp.c @@ -843,25 +843,6 @@ static size_t fcpdev_window ( struct fcp_device *fcpdev ) { ~( ( size_t ) 0 ) : 0 ); } -/** - * Describe FCP device in an ACPI table - * - * @v fcpdev FCP device - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code - */ -static int fcpdev_acpi_describe ( struct fcp_device *fcpdev, - struct acpi_description_header *acpi, - size_t len ) { - - DBGC ( fcpdev, "FCP %p cannot yet describe device in an ACPI table\n", - fcpdev ); - ( void ) acpi; - ( void ) len; - return 0; -} - /** * Describe FCP device using EDD * @@ -917,7 +898,6 @@ static struct interface_operation fcpdev_scsi_op[] = { INTF_OP ( scsi_command, struct fcp_device *, fcpdev_scsi_command ), INTF_OP ( xfer_window, struct fcp_device *, fcpdev_window ), INTF_OP ( intf_close, struct fcp_device *, fcpdev_close ), - INTF_OP ( acpi_describe, struct fcp_device *, fcpdev_acpi_describe ), INTF_OP ( edd_describe, struct fcp_device *, fcpdev_edd_describe ), INTF_OP ( identify_device, struct fcp_device *, fcpdev_identify_device ), diff --git a/src/net/infiniband/ib_srp.c b/src/net/infiniband/ib_srp.c index 3b4914ab..cf1ef3bf 100644 --- a/src/net/infiniband/ib_srp.c +++ b/src/net/infiniband/ib_srp.c @@ -60,6 +60,8 @@ FILE_LICENCE ( BSD2 ); #define EINFO_EINVAL_RP_TOO_SHORT __einfo_uniqify \ ( EINFO_EINVAL, 0x04, "Root path too short" ) +struct acpi_model ib_sbft_model __acpi_model; + /****************************************************************************** * * IB SRP devices @@ -67,6 +69,20 @@ FILE_LICENCE ( BSD2 ); ****************************************************************************** */ +/** + * An IB SRP sBFT created by iPXE + */ +struct ipxe_ib_sbft { + /** The table header */ + struct sbft_table table; + /** The SCSI subtable */ + struct sbft_scsi_subtable scsi; + /** The SRP subtable */ + struct sbft_srp_subtable srp; + /** The Infiniband subtable */ + struct sbft_ib_subtable ib; +}; + /** An Infiniband SRP device */ struct ib_srp_device { /** Reference count */ @@ -80,10 +96,10 @@ struct ib_srp_device { /** Infiniband device */ struct ib_device *ibdev; - /** Destination GID (for boot firmware table) */ - union ib_gid dgid; - /** Service ID (for boot firmware table) */ - union ib_guid service_id; + /** ACPI descriptor */ + struct acpi_descriptor desc; + /** Boot firmware table parameters */ + struct ipxe_ib_sbft sbft; }; /** @@ -113,43 +129,15 @@ static void ib_srp_close ( struct ib_srp_device *ib_srp, int rc ) { } /** - * Describe IB SRP device in an ACPI table + * Get IB SRP ACPI descriptor * - * @v srpdev SRP device - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code + * @v ib_srp IB SRP device + * @ret desc ACPI descriptor */ -static int ib_srp_describe ( struct ib_srp_device *ib_srp, - struct acpi_description_header *acpi, - size_t len ) { - struct ib_device *ibdev = ib_srp->ibdev; - struct sbft_table *sbft = - container_of ( acpi, struct sbft_table, acpi ); - struct sbft_ib_subtable *ib_sbft; - size_t used; +static struct acpi_descriptor * +ib_srp_describe ( struct ib_srp_device *ib_srp ) { - /* Sanity check */ - if ( acpi->signature != SBFT_SIG ) - return -EINVAL; - - /* Append IB subtable to existing table */ - used = le32_to_cpu ( sbft->acpi.length ); - sbft->ib_offset = cpu_to_le16 ( used ); - ib_sbft = ( ( ( void * ) sbft ) + used ); - used += sizeof ( *ib_sbft ); - if ( used > len ) - return -ENOBUFS; - sbft->acpi.length = cpu_to_le32 ( used ); - - /* Populate subtable */ - memcpy ( &ib_sbft->sgid, &ibdev->gid, sizeof ( ib_sbft->sgid ) ); - memcpy ( &ib_sbft->dgid, &ib_srp->dgid, sizeof ( ib_sbft->dgid ) ); - memcpy ( &ib_sbft->service_id, &ib_srp->service_id, - sizeof ( ib_sbft->service_id ) ); - ib_sbft->pkey = cpu_to_le16 ( ibdev->pkey ); - - return 0; + return &ib_srp->desc; } /** IB SRP CMRC interface operations */ @@ -188,6 +176,7 @@ static int ib_srp_open ( struct interface *block, struct ib_device *ibdev, union srp_port_id *initiator, union srp_port_id *target, struct scsi_lun *lun ) { struct ib_srp_device *ib_srp; + struct ipxe_ib_sbft *sbft; int rc; /* Allocate and initialise structure */ @@ -200,13 +189,19 @@ static int ib_srp_open ( struct interface *block, struct ib_device *ibdev, intf_init ( &ib_srp->srp, &ib_srp_srp_desc, &ib_srp->refcnt ); intf_init ( &ib_srp->cmrc, &ib_srp_cmrc_desc, &ib_srp->refcnt ); ib_srp->ibdev = ibdev_get ( ibdev ); + acpi_init ( &ib_srp->desc, &ib_sbft_model, &ib_srp->refcnt ); DBGC ( ib_srp, "IBSRP %p for " IB_GID_FMT " " IB_GUID_FMT "\n", ib_srp, IB_GID_ARGS ( dgid ), IB_GUID_ARGS ( service_id ) ); /* Preserve parameters required for boot firmware table */ - memcpy ( &ib_srp->dgid, dgid, sizeof ( ib_srp->dgid ) ); - memcpy ( &ib_srp->service_id, service_id, - sizeof ( ib_srp->service_id ) ); + sbft = &ib_srp->sbft; + memcpy ( &sbft->scsi.lun, lun, sizeof ( sbft->scsi.lun ) ); + memcpy ( &sbft->srp.initiator, initiator, + sizeof ( sbft->srp.initiator ) ); + memcpy ( &sbft->srp.target, target, sizeof ( sbft->srp.target ) ); + memcpy ( &sbft->ib.dgid, dgid, sizeof ( sbft->ib.dgid ) ); + memcpy ( &sbft->ib.service_id, service_id, + sizeof ( sbft->ib.service_id ) ); /* Open CMRC socket */ if ( ( rc = ib_cmrc_open ( &ib_srp->cmrc, ibdev, dgid, @@ -579,3 +574,67 @@ struct uri_opener ib_srp_uri_opener __uri_opener = { .scheme = "ib_srp", .open = ib_srp_open_uri, }; + +/****************************************************************************** + * + * IB SRP boot firmware table (sBFT) + * + ****************************************************************************** + */ + +/** + * Check if IB SRP boot firmware table descriptor is complete + * + * @v desc ACPI descriptor + * @ret rc Return status code + */ +static int ib_sbft_complete ( struct acpi_descriptor *desc __unused ) { + return 0; +} + +/** + * Install IB SRP boot firmware table(s) + * + * @v install Installation method + * @ret rc Return status code + */ +static int ib_sbft_install ( int ( * install ) ( struct acpi_header *acpi ) ) { + struct ib_srp_device *ib_srp; + struct ipxe_ib_sbft *sbft; + struct ib_device *ibdev; + int rc; + + list_for_each_entry ( ib_srp, &ib_sbft_model.descs, desc.list ) { + + /* Complete table */ + sbft = &ib_srp->sbft; + ibdev = ib_srp->ibdev; + sbft->table.acpi.signature = cpu_to_le32 ( SBFT_SIG ); + sbft->table.acpi.length = cpu_to_le32 ( sizeof ( *sbft ) ); + sbft->table.acpi.revision = 1; + sbft->table.scsi_offset = + cpu_to_le16 ( offsetof ( typeof ( *sbft ), scsi ) ); + sbft->table.srp_offset = + cpu_to_le16 ( offsetof ( typeof ( *sbft ), srp ) ); + sbft->table.ib_offset = + cpu_to_le16 ( offsetof ( typeof ( *sbft ), ib ) ); + memcpy ( &sbft->ib.sgid, &ibdev->gid, sizeof ( sbft->ib.sgid )); + sbft->ib.pkey = cpu_to_le16 ( ibdev->pkey ); + + /* Install table */ + if ( ( rc = install ( &sbft->table.acpi ) ) != 0 ) { + DBGC ( ib_srp, "IBSRP %p could not install sBFT: %s\n", + ib_srp, strerror ( rc ) ); + return rc; + } + } + + return 0; +} + +/** IB sBFT model */ +struct acpi_model ib_sbft_model __acpi_model = { + .descs = LIST_HEAD_INIT ( ib_sbft_model.descs ), + .complete = ib_sbft_complete, + .install = ib_sbft_install, +}; diff --git a/src/net/tcp/httpblock.c b/src/net/tcp/httpblock.c index e124ad2d..1abd6b34 100644 --- a/src/net/tcp/httpblock.c +++ b/src/net/tcp/httpblock.c @@ -114,21 +114,3 @@ int http_block_read_capacity ( struct http_transaction *http, err_open: return rc; } - -/** - * Describe device in ACPI table - * - * @v http HTTP transaction - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code - */ -int http_acpi_describe ( struct http_transaction *http, - struct acpi_description_header *acpi, size_t len ) { - - DBGC ( http, "HTTP %p cannot yet describe device in an ACPI table\n", - http ); - ( void ) acpi; - ( void ) len; - return 0; -} diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index ec527c64..ce53a212 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -509,28 +509,11 @@ __weak int http_block_read_capacity ( struct http_transaction *http __unused, return -ENOTSUP; } -/** - * Describe device in ACPI table (when HTTP block device support is not present) - * - * @v http HTTP transaction - * @v acpi ACPI table - * @v len Length of ACPI table - * @ret rc Return status code - */ -__weak int http_acpi_describe ( struct http_transaction *http __unused, - struct acpi_description_header *acpi __unused, - size_t len __unused ) { - - return -ENOTSUP; -} - /** HTTP data transfer interface operations */ static struct interface_operation http_xfer_operations[] = { INTF_OP ( block_read, struct http_transaction *, http_block_read ), INTF_OP ( block_read_capacity, struct http_transaction *, http_block_read_capacity ), - INTF_OP ( acpi_describe, struct http_transaction *, - http_acpi_describe ), INTF_OP ( xfer_window_changed, struct http_transaction *, http_step ), INTF_OP ( intf_close, struct http_transaction *, http_close ), }; diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 1e6fd1f5..7de4a7bf 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -1810,12 +1810,23 @@ static int iscsi_scsi_command ( struct iscsi_session *iscsi, return iscsi->itt; } +/** + * Get iSCSI ACPI descriptor + * + * @v iscsi iSCSI session + * @ret desc ACPI descriptor + */ +static struct acpi_descriptor * iscsi_describe ( struct iscsi_session *iscsi ) { + + return &iscsi->desc; +} + /** iSCSI SCSI command-issuing interface operations */ static struct interface_operation iscsi_control_op[] = { INTF_OP ( scsi_command, struct iscsi_session *, iscsi_scsi_command ), INTF_OP ( xfer_window, struct iscsi_session *, iscsi_scsi_window ), INTF_OP ( intf_close, struct iscsi_session *, iscsi_close ), - INTF_OP ( acpi_describe, struct iscsi_session *, ibft_describe ), + INTF_OP ( acpi_describe, struct iscsi_session *, iscsi_describe ), }; /** iSCSI SCSI command-issuing interface descriptor */ @@ -2064,6 +2075,7 @@ static int iscsi_open ( struct interface *parent, struct uri *uri ) { intf_init ( &iscsi->socket, &iscsi_socket_desc, &iscsi->refcnt ); process_init_stopped ( &iscsi->process, &iscsi_process_desc, &iscsi->refcnt ); + acpi_init ( &iscsi->desc, &ibft_model, &iscsi->refcnt ); /* Parse root path */ if ( ( rc = iscsi_parse_root_path ( iscsi, uri->opaque ) ) != 0 ) diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index a0c79351..10ccdc1d 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -128,7 +128,9 @@ int uriboot ( struct uri *filename, struct uri **root_paths, /* Hook SAN device, if applicable */ if ( root_path_count ) { - drive = san_hook ( drive, root_paths, root_path_count ); + drive = san_hook ( drive, root_paths, root_path_count, + ( ( flags & URIBOOT_NO_SAN_DESCRIBE ) ? + SAN_NO_DESCRIBE : 0 ) ); if ( drive < 0 ) { rc = drive; printf ( "Could not open SAN device: %s\n", @@ -140,9 +142,9 @@ int uriboot ( struct uri *filename, struct uri **root_paths, /* Describe SAN device, if applicable */ if ( ! ( flags & URIBOOT_NO_SAN_DESCRIBE ) ) { - if ( ( rc = san_describe ( drive ) ) != 0 ) { - printf ( "Could not describe SAN device %#02x: %s\n", - drive, strerror ( rc ) ); + if ( ( rc = san_describe() ) != 0 ) { + printf ( "Could not describe SAN devices: %s\n", + strerror ( rc ) ); goto err_san_describe; } }