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