With the other change, windows boots, so I think this doesn't need to be considered WIP. I have another version which also sets the OemId and OemTableId values to match what is provided by the firmware, which is how edk2 does it. It makes the code a bit more complicated though, so I'll leave that patch be unless someone feels strongly about matching the id.
Vish On Thu, Dec 8, 2016 at 6:25 PM Vishvananda Ishaya Abrams < vish.ish...@oracle.com> wrote: > This uses efi functions to register the ibft table when sanbooting in > uefi mode. It mirrors similar functionality in the int13 bios code > path. The AcpiTable.h code is pulled over from the edk2 source. > --- > src/include/ipxe/efi/Protocol/AcpiTable.h | 127 > ++++++++++++++++++++++++++++++ > src/interface/efi/efi_block.c | 92 ++++++++++++++++++++++ > 2 files changed, 219 insertions(+) > create mode 100644 src/include/ipxe/efi/Protocol/AcpiTable.h > > diff --git a/src/include/ipxe/efi/Protocol/AcpiTable.h > b/src/include/ipxe/efi/Protocol/AcpiTable.h > new file mode 100644 > index 0000000..6149b7e > --- /dev/null > +++ b/src/include/ipxe/efi/Protocol/AcpiTable.h > @@ -0,0 +1,127 @@ > +/** @file > + The file provides the protocol to install or remove an ACPI > + table from a platform. > + > + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> > + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the > BSD License > + which accompanies this distribution. The full text of the license may > be found at > + http://opensource.org/licenses/bsd-license.php > + > + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR > IMPLIED. > + > +**/ > + > +#ifndef __ACPI_TABLE_H___ > +#define __ACPI_TABLE_H___ > + > +#define EFI_ACPI_TABLE_PROTOCOL_GUID \ > + { 0xffe06bdd, 0x6107, 0x46a6, { 0x7b, 0xb2, 0x5a, 0x9c, 0x7e, 0xc5, > 0x27, 0x5c }} > + > + > +typedef struct _EFI_ACPI_TABLE_PROTOCOL EFI_ACPI_TABLE_PROTOCOL; > + > +/** > + > + The InstallAcpiTable() function allows a caller to install an > + ACPI table. When successful, the table will be linked by the > + RSDT/XSDT. AcpiTableBuffer specifies the table to be installed. > + InstallAcpiTable() will make a copy of the table and insert the > + copy into the RSDT/XSDT. InstallAcpiTable() must insert the new > + table at the end of the RSDT/XSDT. To prevent namespace > + collision, ACPI tables may be created using UEFI ACPI table > + format. If this protocol is used to install a table with a > + signature already present in the system, the new table will not > + replace the existing table. It is a platform implementation > + decision to add a new table with a signature matching an > + existing table or disallow duplicate table signatures and > + return EFI_ACCESS_DENIED. On successful output, TableKey is > + initialized with a unique key. Its value may be used in a > + subsequent call to UninstallAcpiTable to remove an ACPI table. > + If an EFI application is running at the time of this call, the > + relevant EFI_CONFIGURATION_TABLE pointer to the RSDT is no > + longer considered valid. > + > + > + @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. > + > + @param AcpiTableBuffer A pointer to a buffer containing the > + ACPI table to be installed. > + > + @param AcpiTableBufferSize Specifies the size, in bytes, of > + the AcpiTableBuffer buffer. > + > + > + @param TableKey Returns a key to refer to the ACPI table. > + > + @retval EFI_SUCCESS The table was successfully inserted > + > + @retval EFI_INVALID_PARAMETER Either AcpiTableBuffer is NULL, > + TableKey is NULL, or > + AcpiTableBufferSize and the size > + field embedded in the ACPI table > + pointed to by AcpiTableBuffer > + are not in sync. > + > + @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to > + complete the request. > + @retval EFI_ACCESS_DENIED The table signature matches a table > already > + present in the system and platform policy > + does not allow duplicate tables of this > type. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EFI_ACPI_TABLE_INSTALL_ACPI_TABLE)( > + IN EFI_ACPI_TABLE_PROTOCOL *This, > + IN VOID *AcpiTableBuffer, > + IN UINTN AcpiTableBufferSize, > + OUT UINTN *TableKey > +); > + > + > +/** > + > + The UninstallAcpiTable() function allows a caller to remove an > + ACPI table. The routine will remove its reference from the > + RSDT/XSDT. A table is referenced by the TableKey parameter > + returned from a prior call to InstallAcpiTable(). If an EFI > + application is running at the time of this call, the relevant > + EFI_CONFIGURATION_TABLE pointer to the RSDT is no longer > + considered valid. > + > + @param This A pointer to a EFI_ACPI_TABLE_PROTOCOL. > + > + @param TableKey Specifies the table to uninstall. The key > was > + returned from InstallAcpiTable(). > + > + @retval EFI_SUCCESS The table was successfully inserted > + > + @retval EFI_NOT_FOUND TableKey does not refer to a valid key > + for a table entry. > + > + @retval EFI_OUT_OF_RESOURCES Insufficient resources exist to > + complete the request. > + > +**/ > +typedef > +EFI_STATUS > +(EFIAPI *EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE)( > + IN EFI_ACPI_TABLE_PROTOCOL *This, > + IN UINTN TableKey > +); > + > +/// > +/// The EFI_ACPI_TABLE_PROTOCOL provides the ability for a component > +/// to install and uninstall ACPI tables from a platform. > +/// > +struct _EFI_ACPI_TABLE_PROTOCOL { > + EFI_ACPI_TABLE_INSTALL_ACPI_TABLE InstallAcpiTable; > + EFI_ACPI_TABLE_UNINSTALL_ACPI_TABLE UninstallAcpiTable; > +}; > + > +extern EFI_GUID gEfiAcpiTableProtocolGuid; > + > +#endif > + > diff --git a/src/interface/efi/efi_block.c b/src/interface/efi/efi_block.c > index 6240c9b..0609029 100644 > --- a/src/interface/efi/efi_block.c > +++ b/src/interface/efi/efi_block.c > @@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); > * > */ > > +#include <registers.h> > #include <stddef.h> > #include <stdio.h> > #include <stdlib.h> > @@ -44,11 +45,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); > #include <ipxe/open.h> > #include <ipxe/retry.h> > #include <ipxe/timer.h> > +#include <ipxe/acpi.h> > #include <ipxe/process.h> > #include <ipxe/sanboot.h> > #include <ipxe/iso9660.h> > #include <ipxe/settings.h> > #include <ipxe/efi/efi.h> > +#include <ipxe/efi/Protocol/AcpiTable.h> > #include <ipxe/efi/Protocol/BlockIo.h> > #include <ipxe/efi/Protocol/SimpleFileSystem.h> > #include <ipxe/efi/efi_driver.h> > @@ -892,6 +895,25 @@ static void efi_block_unhook ( unsigned int drive ) { > ref_put ( &block->refcnt ); > } > > +/** A boot firmware table generated by iPXE */ > +union xbft_table { > + /** ACPI header */ > + struct acpi_description_header acpi; > + /** Padding */ > + char pad[768]; > +}; > + > +/** The boot firmware table generated by iPXE */ > +static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 > ) )); > +#define xbftab __use_data16 ( xbftab ) > + > +/** BOFM1 protocol GUID */ > +static EFI_GUID acpi_table_protocol_guid = > + EFI_ACPI_TABLE_PROTOCOL_GUID; > + > +static BOOLEAN table_installed; > +static UINTN table_key; > + > /** > * Describe EFI block device > * > @@ -899,7 +921,15 @@ static void efi_block_unhook ( unsigned int drive ) { > * @ret rc Return status code > */ > static int efi_block_describe ( unsigned int drive ) { > + EFI_BOOT_SERVICES *bs = efi_systab->BootServices; > struct efi_block *block; > + struct segoff xbft_address; > + union { > + EFI_ACPI_TABLE_PROTOCOL *acpi; > + void *interface; > + } acpi; > + EFI_STATUS efirc; > + int rc; > > /* Find block device */ > block = efi_block_find ( drive ); > @@ -908,6 +938,68 @@ static int efi_block_describe ( unsigned int drive ) { > return -ENODEV; > } > > + /* Locate protocol */ > + if ( ( efirc = bs->LocateProtocol ( &acpi_table_protocol_guid, > NULL, > + &acpi.interface ) ) != 0 ) { > + rc = -EEFI ( efirc ); > + DBGC ( block, "EFIBLK %02x cannot find ACPI TABLE > protocol\n", > + block->drive ); > + return rc; > + } > + > + /* Uninstall existing table */ > + if (table_installed) { > + /* Install table */ > + if ( ( efirc = acpi.acpi->UninstallAcpiTable ( acpi.acpi, > + table_key ) ) != 0 ) { > + rc = -EEFI ( efirc ); > + DBGC ( block, "EFIBLK %02x cannot uninstall > table\n", > + block->drive ); > + return rc; > + } > + table_installed = FALSE; > + } > + > + /* 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 ( &block->intf, &xbftab.acpi, > + sizeof ( xbftab ) ) ) != 0 ) { > + DBGC ( block, "EFIBLK %02x could not create ACPI " > + "description: %s\n", block->drive, strerror ( rc ) > ); > + return rc; > + } > + > + /* Fix up ACPI checksum */ > + acpi_fix_checksum ( &xbftab.acpi ); > + > + /* Install table */ > + if ( ( efirc = acpi.acpi->InstallAcpiTable ( acpi.acpi, > &xbftab.acpi, > + xbftab.acpi.length, &table_key > ) ) != 0 ) { > + rc = -EEFI ( efirc ); > + DBGC ( block, "EFIBLK %02x cannot install table\n", > + block->drive ); > + return rc; > + } > + table_installed = TRUE; > + > + DBGC ( block, "EFIBLK %02x described using boot firmware " > + "table:\n", block->drive ); > + > + /* The xbft_address isn't necessary for the uefi registration, > + * but we use it to print out the table in debug mode */ > + xbft_address.segment = rm_ds; > + xbft_address.offset = __from_data16 ( &xbftab ); > + DBGC_HDA ( block, xbft_address, &xbftab, > + le32_to_cpu ( xbftab.acpi.length ) ); > + > return 0; > } > > -- > 2.5.0 > > _______________________________________________ > ipxe-devel mailing list > ipxe-devel@lists.ipxe.org > https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel >
_______________________________________________ ipxe-devel mailing list ipxe-devel@lists.ipxe.org https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel