[ipxe-devel] [PATCH 1/1 WIP] [efi] setup ibft tables in uefi sanboot mode
Vishvananda Ishaya
vishvananda at gmail.com
Mon Dec 12 20:39:05 UTC 2016
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.ishaya at 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 at lists.ipxe.org
> https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ipxe.org/pipermail/ipxe-devel/attachments/20161212/34f67997/attachment.htm>
More information about the ipxe-devel
mailing list