<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>