mirror of https://github.com/ipxe/ipxe.git
[efi] Provide ACPI table description for SAN devices
Provide a basic proof of concept ACPI table description (e.g. iBFT for iSCSI) for SAN devices in a UEFI environment, using a control flow that is functionally identical to that used in a BIOS environment. Originally-implemented-by: Vishvananda Ishaya Abrams <vish.ishaya@oracle.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/58/merge
parent
553f485734
commit
fdcdc5203b
|
@ -46,15 +46,21 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|||
#include <ipxe/process.h>
|
||||
#include <ipxe/sanboot.h>
|
||||
#include <ipxe/iso9660.h>
|
||||
#include <ipxe/acpi.h>
|
||||
#include <ipxe/efi/efi.h>
|
||||
#include <ipxe/efi/Protocol/BlockIo.h>
|
||||
#include <ipxe/efi/Protocol/SimpleFileSystem.h>
|
||||
#include <ipxe/efi/Protocol/AcpiTable.h>
|
||||
#include <ipxe/efi/efi_driver.h>
|
||||
#include <ipxe/efi/efi_strings.h>
|
||||
#include <ipxe/efi/efi_snp.h>
|
||||
#include <ipxe/efi/efi_utils.h>
|
||||
#include <ipxe/efi/efi_block.h>
|
||||
|
||||
/** ACPI table protocol protocol */
|
||||
static EFI_ACPI_TABLE_PROTOCOL *acpi;
|
||||
EFI_REQUEST_PROTOCOL ( EFI_ACPI_TABLE_PROTOCOL, &acpi );
|
||||
|
||||
/** Boot filename */
|
||||
static wchar_t efi_block_boot_filename[] = EFI_REMOVABLE_MEDIA_FILE_NAME;
|
||||
|
||||
|
@ -399,7 +405,17 @@ static void efi_block_unhook ( unsigned int drive ) {
|
|||
* @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;
|
||||
size_t len;
|
||||
EFI_STATUS efirc;
|
||||
int rc;
|
||||
|
||||
/* Find SAN device */
|
||||
sandev = sandev_find ( drive );
|
||||
|
@ -408,6 +424,59 @@ static int efi_block_describe ( unsigned int drive ) {
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if ( ! acpi ) {
|
||||
DBGC ( sandev, "EFIBLK %#02x has no ACPI table protocol\n",
|
||||
sandev->drive );
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Remove existing table, if any */
|
||||
if ( 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 ) );
|
||||
/* Continue anyway */
|
||||
}
|
||||
key = 0;
|
||||
}
|
||||
|
||||
/* Reopen block device if necessary */
|
||||
if ( sandev_needs_reopen ( sandev ) &&
|
||||
( ( rc = sandev_reopen ( sandev ) ) != 0 ) )
|
||||
return rc;
|
||||
|
||||
/* 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 ( &sandev->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 ) );
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue