aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/efi/nii.c1134
-rw-r--r--src/include/ipxe/efi/IndustryStandard/Acpi10.h663
-rw-r--r--src/include/ipxe/efi/IndustryStandard/AcpiAml.h177
-rw-r--r--src/include/ipxe/errfile.h1
-rw-r--r--src/include/ipxe/ethernet.h2
5 files changed, 1977 insertions, 0 deletions
diff --git a/src/drivers/net/efi/nii.c b/src/drivers/net/efi/nii.c
new file mode 100644
index 0000000..5b1872c
--- /dev/null
+++ b/src/drivers/net/efi/nii.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ipxe/netdevice.h>
+#include <ipxe/ethernet.h>
+#include <ipxe/umalloc.h>
+#include <ipxe/efi/efi.h>
+#include <ipxe/efi/efi_driver.h>
+#include <ipxe/efi/efi_snp.h>
+#include <ipxe/efi/efi_pci.h>
+#include <ipxe/efi/efi_utils.h>
+#include <ipxe/efi/IndustryStandard/Acpi10.h>
+
+/** @file
+ *
+ * NII driver
+ *
+ */
+
+/* Error numbers generated by NII */
+#define EIO_INVALID_CDB __einfo_error ( EINFO_EIO_INVALID_CDB )
+#define EINFO_EIO_INVALID_CDB \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_CDB, \
+ "Invalid CDB" )
+#define EIO_INVALID_CPB __einfo_error ( EINFO_EIO_INVALID_CPB )
+#define EINFO_EIO_INVALID_CPB \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_CPB, \
+ "Invalid CPB" )
+#define EIO_BUSY __einfo_error ( EINFO_EIO_BUSY )
+#define EINFO_EIO_BUSY \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_BUSY, \
+ "Busy" )
+#define EIO_QUEUE_FULL __einfo_error ( EINFO_EIO_QUEUE_FULL )
+#define EINFO_EIO_QUEUE_FULL \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_QUEUE_FULL, \
+ "Queue full" )
+#define EIO_ALREADY_STARTED __einfo_error ( EINFO_EIO_ALREADY_STARTED )
+#define EINFO_EIO_ALREADY_STARTED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_ALREADY_STARTED, \
+ "Already started" )
+#define EIO_NOT_STARTED __einfo_error ( EINFO_EIO_NOT_STARTED )
+#define EINFO_EIO_NOT_STARTED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_STARTED, \
+ "Not started" )
+#define EIO_NOT_SHUTDOWN __einfo_error ( EINFO_EIO_NOT_SHUTDOWN )
+#define EINFO_EIO_NOT_SHUTDOWN \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_SHUTDOWN, \
+ "Not shutdown" )
+#define EIO_ALREADY_INITIALIZED __einfo_error ( EINFO_EIO_ALREADY_INITIALIZED )
+#define EINFO_EIO_ALREADY_INITIALIZED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_ALREADY_INITIALIZED, \
+ "Already initialized" )
+#define EIO_NOT_INITIALIZED __einfo_error ( EINFO_EIO_NOT_INITIALIZED )
+#define EINFO_EIO_NOT_INITIALIZED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_INITIALIZED, \
+ "Not initialized" )
+#define EIO_DEVICE_FAILURE __einfo_error ( EINFO_EIO_DEVICE_FAILURE )
+#define EINFO_EIO_DEVICE_FAILURE \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_DEVICE_FAILURE, \
+ "Device failure" )
+#define EIO_NVDATA_FAILURE __einfo_error ( EINFO_EIO_NVDATA_FAILURE )
+#define EINFO_EIO_NVDATA_FAILURE \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NVDATA_FAILURE, \
+ "Non-volatile data failure" )
+#define EIO_UNSUPPORTED __einfo_error ( EINFO_EIO_UNSUPPORTED )
+#define EINFO_EIO_UNSUPPORTED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_UNSUPPORTED, \
+ "Unsupported" )
+#define EIO_BUFFER_FULL __einfo_error ( EINFO_EIO_BUFFER_FULL )
+#define EINFO_EIO_BUFFER_FULL \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_BUFFER_FULL, \
+ "Buffer full" )
+#define EIO_INVALID_PARAMETER __einfo_error ( EINFO_EIO_INVALID_PARAMETER )
+#define EINFO_EIO_INVALID_PARAMETER \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_PARAMETER, \
+ "Invalid parameter" )
+#define EIO_INVALID_UNDI __einfo_error ( EINFO_EIO_INVALID_UNDI )
+#define EINFO_EIO_INVALID_UNDI \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_INVALID_UNDI, \
+ "Invalid UNDI" )
+#define EIO_IPV4_NOT_SUPPORTED __einfo_error ( EINFO_EIO_IPV4_NOT_SUPPORTED )
+#define EINFO_EIO_IPV4_NOT_SUPPORTED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_IPV4_NOT_SUPPORTED, \
+ "IPv4 not supported" )
+#define EIO_IPV6_NOT_SUPPORTED __einfo_error ( EINFO_EIO_IPV6_NOT_SUPPORTED )
+#define EINFO_EIO_IPV6_NOT_SUPPORTED \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_IPV6_NOT_SUPPORTED, \
+ "IPv6 not supported" )
+#define EIO_NOT_ENOUGH_MEMORY __einfo_error ( EINFO_EIO_NOT_ENOUGH_MEMORY )
+#define EINFO_EIO_NOT_ENOUGH_MEMORY \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NOT_ENOUGH_MEMORY, \
+ "Not enough memory" )
+#define EIO_NO_DATA __einfo_error ( EINFO_EIO_NO_DATA )
+#define EINFO_EIO_NO_DATA \
+ __einfo_uniqify ( EINFO_EIO, PXE_STATCODE_NO_DATA, \
+ "No data" )
+#define EIO_STAT( stat ) \
+ EUNIQ ( EINFO_EIO, -(stat), EIO_INVALID_CDB, EIO_INVALID_CPB, \
+ EIO_BUSY, EIO_QUEUE_FULL, EIO_ALREADY_STARTED, \
+ EIO_NOT_STARTED, EIO_NOT_SHUTDOWN, EIO_ALREADY_INITIALIZED, \
+ EIO_NOT_INITIALIZED, EIO_DEVICE_FAILURE, EIO_NVDATA_FAILURE, \
+ EIO_UNSUPPORTED, EIO_BUFFER_FULL, EIO_INVALID_PARAMETER, \
+ EIO_INVALID_UNDI, EIO_IPV4_NOT_SUPPORTED, \
+ EIO_IPV6_NOT_SUPPORTED, EIO_NOT_ENOUGH_MEMORY, EIO_NO_DATA )
+
+/** Maximum PCI BAR
+ *
+ * This is defined in <ipxe/efi/IndustryStandard/Pci22.h>, but we
+ * can't #include that since it collides with <ipxe/pci.h>.
+ */
+#define PCI_MAX_BAR 6
+
+/** An NII NIC */
+struct nii_nic {
+ /** EFI device */
+ struct efi_device *efidev;
+ /** Network interface identifier protocol */
+ EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *nii;
+ /** !PXE structure */
+ PXE_SW_UNDI *undi;
+ /** Entry point */
+ EFIAPI VOID ( * issue ) ( UINT64 cdb );
+ /** Generic device */
+ struct device dev;
+
+ /** PCI device */
+ EFI_HANDLE pci_device;
+ /** PCI I/O protocol */
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ /** Memory BAR */
+ unsigned int mem_bar;
+ /** I/O BAR */
+ unsigned int io_bar;
+
+ /** Broadcast address */
+ PXE_MAC_ADDR broadcast;
+ /** Maximum packet length */
+ size_t mtu;
+
+ /** Hardware transmit/receive buffer */
+ userptr_t buffer;
+ /** Hardware transmit/receive buffer length */
+ size_t buffer_len;
+
+ /** Saved task priority level */
+ EFI_TPL saved_tpl;
+
+ /** Current transmit buffer */
+ struct io_buffer *txbuf;
+ /** Current receive buffer */
+ struct io_buffer *rxbuf;
+};
+
+/** Maximum number of received packets per poll */
+#define NII_RX_QUOTA 4
+
+/**
+ * Open PCI I/O protocol and identify BARs
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_pci_open ( struct nii_nic *nii ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE device = nii->efidev->device;
+ EFI_HANDLE pci_device;
+ union {
+ EFI_PCI_IO_PROTOCOL *pci_io;
+ void *interface;
+ } pci_io;
+ union {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *acpi;
+ void *resource;
+ } desc;
+ unsigned int bar;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Locate PCI I/O protocol */
+ if ( ( rc = efi_locate_device ( device, &efi_pci_io_protocol_guid,
+ &pci_device ) ) != 0 ) {
+ DBGC ( nii, "NII %s could not locate PCI I/O protocol: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ goto err_locate;
+ }
+ nii->pci_device = pci_device;
+
+ /* Open PCI I/O protocol */
+ if ( ( efirc = bs->OpenProtocol ( pci_device, &efi_pci_io_protocol_guid,
+ &pci_io.interface, efi_image_handle,
+ device,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL ))!=0){
+ rc = -EEFI ( efirc );
+ DBGC ( nii, "NII %s could not open PCI I/O protocol: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ goto err_open;
+ }
+ nii->pci_io = pci_io.pci_io;
+
+ /* Identify memory and I/O BARs */
+ nii->mem_bar = PCI_MAX_BAR;
+ nii->io_bar = PCI_MAX_BAR;
+ for ( bar = 0 ; bar < PCI_MAX_BAR ; bar++ ) {
+ efirc = nii->pci_io->GetBarAttributes ( nii->pci_io, bar, NULL,
+ &desc.resource );
+ if ( efirc == EFI_UNSUPPORTED ) {
+ /* BAR not present; ignore */
+ continue;
+ }
+ if ( efirc != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( nii, "NII %s could not get BAR %d attributes: "
+ "%s\n", nii->dev.name, bar, strerror ( rc ) );
+ goto err_get_bar_attributes;
+ }
+ if ( desc.acpi->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM ) {
+ nii->mem_bar = bar;
+ } else if ( desc.acpi->ResType == ACPI_ADDRESS_SPACE_TYPE_IO ) {
+ nii->io_bar = bar;
+ }
+ bs->FreePool ( desc.resource );
+ }
+ DBGC ( nii, "NII %s has ", nii->dev.name );
+ if ( nii->mem_bar < PCI_MAX_BAR ) {
+ DBGC ( nii, "memory BAR %d and ", nii->mem_bar );
+ } else {
+ DBGC ( nii, "no memory BAR and " );
+ }
+ if ( nii->io_bar < PCI_MAX_BAR ) {
+ DBGC ( nii, "I/O BAR %d\n", nii->io_bar );
+ } else {
+ DBGC ( nii, "no I/O BAR\n" );
+ }
+
+ return 0;
+
+ err_get_bar_attributes:
+ bs->CloseProtocol ( pci_device, &efi_pci_io_protocol_guid,
+ efi_image_handle, device );
+ err_open:
+ err_locate:
+ return rc;
+}
+
+/**
+ * Close PCI I/O protocol
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static void nii_pci_close ( struct nii_nic *nii ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ bs->CloseProtocol ( nii->pci_device, &efi_pci_io_protocol_guid,
+ efi_image_handle, nii->efidev->device );
+}
+
+/**
+ * I/O callback
+ *
+ * @v unique_id NII NIC
+ * @v op Operations
+ * @v len Length of data
+ * @v addr Address
+ * @v data Data buffer
+ */
+static EFIAPI VOID nii_io ( UINT64 unique_id, UINT8 op, UINT8 len, UINT64 addr,
+ UINT64 data ) {
+ struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
+ EFI_PCI_IO_PROTOCOL_ACCESS *access;
+ EFI_PCI_IO_PROTOCOL_IO_MEM io;
+ EFI_PCI_IO_PROTOCOL_WIDTH width;
+ unsigned int bar;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Determine accessor and BAR */
+ if ( op & ( PXE_MEM_READ | PXE_MEM_WRITE ) ) {
+ access = &nii->pci_io->Mem;
+ bar = nii->mem_bar;
+ } else {
+ access = &nii->pci_io->Io;
+ bar = nii->io_bar;
+ }
+
+ /* Determine operaton */
+ io = ( ( op & ( PXE_IO_WRITE | PXE_MEM_WRITE ) ) ?
+ access->Write : access->Read );
+
+ /* Determine width */
+ width = ( fls ( len ) - 1 );
+
+ /* Issue operation */
+ if ( ( efirc = io ( nii->pci_io, width, bar, addr, 1,
+ ( ( void * ) ( intptr_t ) data ) ) ) != 0 ) {
+ rc = -EEFI ( efirc );
+ DBGC ( nii, "NII %s I/O operation %#x failed: %s\n",
+ nii->dev.name, op, strerror ( rc ) );
+ /* No way to report failure */
+ return;
+ }
+}
+
+/**
+ * Delay callback
+ *
+ * @v unique_id NII NIC
+ * @v microseconds Delay in microseconds
+ */
+static EFIAPI VOID nii_delay ( UINT64 unique_id __unused, UINTN microseconds ) {
+
+ udelay ( microseconds );
+}
+
+/**
+ * Block callback
+ *
+ * @v unique_id NII NIC
+ * @v acquire Acquire lock
+ */
+static EFIAPI VOID nii_block ( UINT64 unique_id, UINT32 acquire ) {
+ struct nii_nic *nii = ( ( void * ) ( intptr_t ) unique_id );
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+
+ /* This functionality (which is copied verbatim from the
+ * SnpDxe implementation of this function) appears to be
+ * totally brain-dead, since it produces no actual blocking
+ * behaviour.
+ */
+ if ( acquire ) {
+ nii->saved_tpl = bs->RaiseTPL ( TPL_NOTIFY );
+ } else {
+ bs->RestoreTPL ( nii->saved_tpl );
+ }
+}
+
+/**
+ * Construct operation from opcode and flags
+ *
+ * @v opcode Opcode
+ * @v opflags Flags
+ * @ret op Operation
+ */
+#define NII_OP( opcode, opflags ) ( (opcode) | ( (opflags) << 16 ) )
+
+/**
+ * Extract opcode from operation
+ *
+ * @v op Operation
+ * @ret opcode Opcode
+ */
+#define NII_OPCODE( op ) ( (op) & 0xffff )
+
+/**
+ * Extract flags from operation
+ *
+ * @v op Operation
+ * @ret opflags Flags
+ */
+#define NII_OPFLAGS( op ) ( (op) >> 16 )
+
+/**
+ * Issue command with parameter block and data block
+ *
+ * @v nii NII NIC
+ * @v op Operation
+ * @v cpb Command parameter block, or NULL
+ * @v cpb_len Command parameter block length
+ * @v db Data block, or NULL
+ * @v db_len Data block length
+ * @ret stat Status flags, or negative status code
+ */
+static int nii_issue_cpb_db ( struct nii_nic *nii, unsigned int op, void *cpb,
+ size_t cpb_len, void *db, size_t db_len ) {
+ PXE_CDB cdb;
+
+ /* Prepare command descriptor block */
+ memset ( &cdb, 0, sizeof ( cdb ) );
+ cdb.OpCode = NII_OPCODE ( op );
+ cdb.OpFlags = NII_OPFLAGS ( op );
+ cdb.CPBaddr = ( ( intptr_t ) cpb );
+ cdb.CPBsize = cpb_len;
+ cdb.DBaddr = ( ( intptr_t ) db );
+ cdb.DBsize = db_len;
+ cdb.IFnum = nii->nii->IfNum;
+
+ /* Issue command */
+ nii->issue ( ( intptr_t ) &cdb );
+
+ /* Check completion status */
+ if ( cdb.StatCode != PXE_STATCODE_SUCCESS )
+ return -cdb.StatCode;
+
+ /* Return command-specific status flags */
+ return ( cdb.StatFlags & ~PXE_STATFLAGS_STATUS_MASK );
+}
+
+/**
+ * Issue command with parameter block
+ *
+ * @v nii NII NIC
+ * @v op Operation
+ * @v cpb Command parameter block, or NULL
+ * @v cpb_len Command parameter block length
+ * @ret stat Status flags, or negative status code
+ */
+static int nii_issue_cpb ( struct nii_nic *nii, unsigned int op, void *cpb,
+ size_t cpb_len ) {
+
+ return nii_issue_cpb_db ( nii, op, cpb, cpb_len, NULL, 0 );
+}
+
+/**
+ * Issue command with data block
+ *
+ * @v nii NII NIC
+ * @v op Operation
+ * @v db Data block, or NULL
+ * @v db_len Data block length
+ * @ret stat Status flags, or negative status code
+ */
+static int nii_issue_db ( struct nii_nic *nii, unsigned int op, void *db,
+ size_t db_len ) {
+
+ return nii_issue_cpb_db ( nii, op, NULL, 0, db, db_len );
+}
+
+/**
+ * Issue command
+ *
+ *
+ * @v nii NII NIC
+ * @v op Operation
+ * @ret stat Status flags, or negative status code
+ */
+static int nii_issue ( struct nii_nic *nii, unsigned int op ) {
+
+ return nii_issue_cpb_db ( nii, op, NULL, 0, NULL, 0 );
+}
+
+/**
+ * Start UNDI
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_start_undi ( struct nii_nic *nii ) {
+ PXE_CPB_START_31 cpb;
+ int stat;
+ int rc;
+
+ /* Construct parameter block */
+ memset ( &cpb, 0, sizeof ( cpb ) );
+ cpb.Delay = ( ( intptr_t ) nii_delay );
+ cpb.Block = ( ( intptr_t ) nii_block );
+ cpb.Mem_IO = ( ( intptr_t ) nii_io );
+ cpb.Unique_ID = ( ( intptr_t ) nii );
+
+ /* Issue command */
+ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_START, &cpb,
+ sizeof ( cpb ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not start: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Stop UNDI
+ *
+ * @v nii NII NIC
+ */
+static void nii_stop_undi ( struct nii_nic *nii ) {
+ int stat;
+ int rc;
+
+ /* Issue command */
+ if ( ( stat = nii_issue ( nii, PXE_OPCODE_STOP ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not stop: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ /* Nothing we can do about it */
+ return;
+ }
+}
+
+/**
+ * Get initialisation information
+ *
+ * @v nii NII NIC
+ * @v netdev Network device to fill in
+ * @ret rc Return status code
+ */
+static int nii_get_init_info ( struct nii_nic *nii,
+ struct net_device *netdev ) {
+ PXE_DB_GET_INIT_INFO db;
+ int stat;
+ int rc;
+
+ /* Issue command */
+ if ( ( stat = nii_issue_db ( nii, PXE_OPCODE_GET_INIT_INFO, &db,
+ sizeof ( db ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not get initialisation info: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Determine link layer protocol */
+ switch ( db.IFtype ) {
+ case PXE_IFTYPE_ETHERNET :
+ netdev->ll_protocol = &ethernet_protocol;
+ break;
+ default:
+ DBGC ( nii, "NII %s unknown interface type %#02x\n",
+ nii->dev.name, db.IFtype );
+ return -ENOTSUP;
+ }
+
+ /* Sanity checks */
+ assert ( db.MediaHeaderLen == netdev->ll_protocol->ll_header_len );
+ assert ( db.HWaddrLen == netdev->ll_protocol->hw_addr_len );
+ assert ( db.HWaddrLen == netdev->ll_protocol->ll_addr_len );
+
+ /* Extract parameters */
+ nii->buffer_len = db.MemoryRequired;
+ nii->mtu = ( db.FrameDataLen + db.MediaHeaderLen );
+ netdev->max_pkt_len = nii->mtu;
+
+ return 0;
+}
+
+/**
+ * Initialise UNDI
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_initialise ( struct nii_nic *nii ) {
+ PXE_CPB_INITIALIZE cpb;
+ unsigned int op;
+ int stat;
+ int rc;
+
+ /* Allocate memory buffer */
+ nii->buffer = umalloc ( nii->buffer_len );
+ if ( ! nii->buffer ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Construct parameter block */
+ memset ( &cpb, 0, sizeof ( cpb ) );
+ cpb.MemoryAddr = ( ( intptr_t ) nii->buffer );
+ cpb.MemoryLength = nii->buffer_len;
+
+ /* Issue command */
+ op = NII_OP ( PXE_OPCODE_INITIALIZE,
+ PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE );
+ if ( ( stat = nii_issue_cpb ( nii, op, &cpb, sizeof ( cpb ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not initialise: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ goto err_initialize;
+ }
+
+ return 0;
+
+ err_initialize:
+ ufree ( nii->buffer );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Shut down UNDI
+ *
+ * @v nii NII NIC
+ */
+static void nii_shutdown ( struct nii_nic *nii ) {
+ int stat;
+ int rc;
+
+ /* Issue command */
+ if ( ( stat = nii_issue ( nii, PXE_OPCODE_SHUTDOWN ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not shut down: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ /* Leak memory to avoid corruption */
+ return;
+ }
+
+ /* Free buffer */
+ ufree ( nii->buffer );
+}
+
+/**
+ * Get station addresses
+ *
+ * @v nii NII NIC
+ * @v netdev Network device to fill in
+ * @ret rc Return status code
+ */
+static int nii_get_station_address ( struct nii_nic *nii,
+ struct net_device *netdev ) {
+ PXE_DB_STATION_ADDRESS db;
+ int stat;
+ int rc;
+
+ /* Initialise UNDI */
+ if ( ( rc = nii_initialise ( nii ) ) != 0 )
+ goto err_initialise;
+
+ /* Issue command */
+ if ( ( stat = nii_issue_db ( nii, PXE_OPCODE_STATION_ADDRESS, &db,
+ sizeof ( db ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not get station address: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ goto err_station_address;
+ }
+
+ /* Copy MAC addresses */
+ memcpy ( netdev->ll_addr, db.StationAddr,
+ netdev->ll_protocol->ll_addr_len );
+ memcpy ( netdev->hw_addr, db.PermanentAddr,
+ netdev->ll_protocol->hw_addr_len );
+ memcpy ( nii->broadcast, db.BroadcastAddr,
+ sizeof ( nii->broadcast ) );
+
+ err_station_address:
+ nii_shutdown ( nii );
+ err_initialise:
+ return rc;
+}
+
+/**
+ * Set station address
+ *
+ * @v nii NII NIC
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int nii_set_station_address ( struct nii_nic *nii,
+ struct net_device *netdev ) {
+ PXE_CPB_STATION_ADDRESS cpb;
+ int stat;
+ int rc;
+
+ /* Construct parameter block */
+ memset ( &cpb, 0, sizeof ( cpb ) );
+ memcpy ( cpb.StationAddr, netdev->ll_addr,
+ netdev->ll_protocol->ll_addr_len );
+
+ /* Issue command */
+ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_STATION_ADDRESS,
+ &cpb, sizeof ( cpb ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not set station address: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Set receive filters
+ *
+ * @v nii NII NIC
+ * @ret rc Return status code
+ */
+static int nii_set_rx_filters ( struct nii_nic *nii ) {
+ unsigned int op;
+ int stat;
+ int rc;
+
+ /* Issue command */
+ op = NII_OP ( PXE_OPCODE_RECEIVE_FILTERS,
+ ( PXE_OPFLAGS_RECEIVE_FILTER_ENABLE |
+ PXE_OPFLAGS_RECEIVE_FILTER_UNICAST |
+ PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST |
+ PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS |
+ PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST ) );
+ if ( ( stat = nii_issue ( nii, op ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not set receive filters: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
+}
+
+/**
+ * Transmit packet
+ *
+ * @v netdev Network device
+ * @v iobuf I/O buffer
+ * @ret rc Return status code
+ */
+static int nii_transmit ( struct net_device *netdev,
+ struct io_buffer *iobuf ) {
+ struct nii_nic *nii = netdev->priv;
+ PXE_CPB_TRANSMIT cpb;
+ int stat;
+ int rc;
+
+ /* Defer the packet if there is already a transmission in progress */
+ if ( nii->txbuf ) {
+ netdev_tx_defer ( netdev, iobuf );
+ return 0;
+ }
+
+ /* Construct parameter block */
+ memset ( &cpb, 0, sizeof ( cpb ) );
+ cpb.FrameAddr = virt_to_bus ( iobuf->data );
+ cpb.DataLen = iob_len ( iobuf );
+ cpb.MediaheaderLen = netdev->ll_protocol->ll_header_len;
+
+ /* Transmit packet */
+ if ( ( stat = nii_issue_cpb ( nii, PXE_OPCODE_TRANSMIT, &cpb,
+ sizeof ( cpb ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not transmit: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return rc;
+ }
+ nii->txbuf = iobuf;
+
+ return 0;
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ * @v stat Status flags
+ */
+static void nii_poll_tx ( struct net_device *netdev, unsigned int stat ) {
+ struct nii_nic *nii = netdev->priv;
+ struct io_buffer *iobuf;
+
+ /* Do nothing unless we have a completion */
+ if ( stat & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN )
+ return;
+
+ /* Sanity check */
+ if ( ! nii->txbuf ) {
+ DBGC ( nii, "NII %s reported spurious TX completion\n",
+ nii->dev.name );
+ netdev_tx_err ( netdev, NULL, -EPIPE );
+ return;
+ }
+
+ /* Complete transmission */
+ iobuf = nii->txbuf;
+ nii->txbuf = NULL;
+ netdev_tx_complete ( netdev, iobuf );
+}
+
+/**
+ * Poll for received packets
+ *
+ * @v netdev Network device
+ */
+static void nii_poll_rx ( struct net_device *netdev ) {
+ struct nii_nic *nii = netdev->priv;
+ PXE_CPB_RECEIVE cpb;
+ PXE_DB_RECEIVE db;
+ unsigned int quota;
+ int stat;
+ int rc;
+
+ /* Retrieve up to NII_RX_QUOTA packets */
+ for ( quota = NII_RX_QUOTA ; quota ; quota-- ) {
+
+ /* Allocate buffer, if required */
+ if ( ! nii->rxbuf ) {
+ nii->rxbuf = alloc_iob ( nii->mtu );
+ if ( ! nii->rxbuf ) {
+ /* Leave for next poll */
+ break;
+ }
+ }
+
+ /* Construct parameter block */
+ memset ( &cpb, 0, sizeof ( cpb ) );
+ cpb.BufferAddr = virt_to_bus ( nii->rxbuf->data );
+ cpb.BufferLen = iob_tailroom ( nii->rxbuf );
+
+ /* Issue command */
+ if ( ( stat = nii_issue_cpb_db ( nii, PXE_OPCODE_RECEIVE,
+ &cpb, sizeof ( cpb ),
+ &db, sizeof ( db ) ) ) < 0 ) {
+
+ /* PXE_STATCODE_NO_DATA is just the usual "no packet"
+ * status indicator; ignore it.
+ */
+ if ( stat == -PXE_STATCODE_NO_DATA )
+ break;
+
+ /* Anything else is an error */
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not receive: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ netdev_rx_err ( netdev, NULL, rc );
+ break;
+ }
+
+ /* Hand off to network stack */
+ iob_put ( nii->rxbuf, db.FrameLen );
+ netdev_rx ( netdev, nii->rxbuf );
+ nii->rxbuf = NULL;
+ }
+}
+
+/**
+ * Check for link state changes
+ *
+ * @v netdev Network device
+ * @v stat Status flags
+ */
+static void nii_poll_link ( struct net_device *netdev, unsigned int stat ) {
+ int no_media = ( stat & PXE_STATFLAGS_GET_STATUS_NO_MEDIA );
+
+ if ( no_media && netdev_link_ok ( netdev ) ) {
+ netdev_link_down ( netdev );
+ } else if ( ( ! no_media ) && ( ! netdev_link_ok ( netdev ) ) ) {
+ netdev_link_up ( netdev );
+ }
+}
+
+/**
+ * Poll for completed packets
+ *
+ * @v netdev Network device
+ */
+static void nii_poll ( struct net_device *netdev ) {
+ struct nii_nic *nii = netdev->priv;
+ PXE_DB_GET_STATUS db;
+ unsigned int op;
+ int stat;
+ int rc;
+
+ /* Get status */
+ op = NII_OP ( PXE_OPCODE_GET_STATUS,
+ ( PXE_OPFLAGS_GET_INTERRUPT_STATUS |
+ PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS |
+ PXE_OPFLAGS_GET_MEDIA_STATUS ) );
+ if ( ( stat = nii_issue_db ( nii, op, &db, sizeof ( db ) ) ) < 0 ) {
+ rc = -EIO_STAT ( stat );
+ DBGC ( nii, "NII %s could not get status: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ return;
+ }
+
+ /* Process any TX completions */
+ nii_poll_tx ( netdev, stat );
+
+ /* Process any RX completions */
+ nii_poll_rx ( netdev );
+
+ /* Check for link state changes */
+ nii_poll_link ( netdev, stat );
+}
+
+/**
+ * Open network device
+ *
+ * @v netdev Network device
+ * @ret rc Return status code
+ */
+static int nii_open ( struct net_device *netdev ) {
+ struct nii_nic *nii = netdev->priv;
+ int rc;
+
+ /* Initialise NIC */
+ if ( ( rc = nii_initialise ( nii ) ) != 0 )
+ goto err_initialise;
+
+ /* Attempt to set station address */
+ if ( ( rc = nii_set_station_address ( nii, netdev ) ) != 0 ) {
+ DBGC ( nii, "NII %s could not set station address: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ /* Treat as non-fatal */
+ }
+
+ /* Set receive filters */
+ if ( ( rc = nii_set_rx_filters ( nii ) ) != 0 )
+ goto err_set_rx_filters;
+
+ return 0;
+
+ err_set_rx_filters:
+ nii_shutdown ( nii );
+ err_initialise:
+ return rc;
+}
+
+/**
+ * Close network device
+ *
+ * @v netdev Network device
+ */
+static void nii_close ( struct net_device *netdev ) {
+ struct nii_nic *nii = netdev->priv;
+
+ /* Shut down NIC */
+ nii_shutdown ( nii );
+
+ /* Discard transmit buffer, if applicable */
+ if ( nii->txbuf ) {
+ netdev_tx_complete_err ( netdev, nii->txbuf, -ECANCELED );
+ nii->txbuf = NULL;
+ }
+
+ /* Discard receive buffer, if applicable */
+ if ( nii->rxbuf ) {
+ free_iob ( nii->rxbuf );
+ nii->rxbuf = NULL;
+ }
+}
+
+/** NII network device operations */
+static struct net_device_operations nii_operations = {
+ .open = nii_open,
+ .close = nii_close,
+ .transmit = nii_transmit,
+ .poll = nii_poll,
+};
+
+/**
+ * Check to see if driver supports a device
+ *
+ * @v device EFI device handle
+ * @ret rc Return status code
+ */
+static int nii_supported ( EFI_HANDLE device ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_STATUS efirc;
+
+ /* Check that this is not a device we are providing ourselves */
+ if ( find_snpdev ( device ) != NULL ) {
+ DBGCP ( device, "NII %p %s is provided by this binary\n",
+ device, efi_handle_name ( device ) );
+ return -ENOTTY;
+ }
+
+ /* Test for presence of NII protocol */
+ if ( ( efirc = bs->OpenProtocol ( device,
+ &efi_nii31_protocol_guid,
+ NULL, efi_image_handle, device,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL))!=0){
+ DBGCP ( device, "NII %p %s is not an NII device\n",
+ device, efi_handle_name ( device ) );
+ return -EEFI ( efirc );
+ }
+ DBGC ( device, "NII %p %s is an NII device\n",
+ device, efi_handle_name ( device ) );
+
+ return 0;
+}
+
+/**
+ * Attach driver to device
+ *
+ * @v efidev EFI device
+ * @ret rc Return status code
+ */
+static int nii_start ( struct efi_device *efidev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ EFI_HANDLE device = efidev->device;
+ struct net_device *netdev;
+ struct nii_nic *nii;
+ void *interface;
+ EFI_STATUS efirc;
+ int rc;
+
+ /* Allocate and initialise structure */
+ netdev = alloc_netdev ( sizeof ( *nii ) );
+ if ( ! netdev ) {
+ rc = -ENOMEM;
+ goto err_alloc;
+ }
+ netdev_init ( netdev, &nii_operations );
+ nii = netdev->priv;
+ nii->efidev = efidev;
+ netdev->ll_broadcast = nii->broadcast;
+ efidev_set_drvdata ( efidev, netdev );
+
+ /* Populate underlying device information */
+ efi_device_info ( device, "NII", &nii->dev );
+ nii->dev.driver_name = "NII";
+ nii->dev.parent = &efidev->dev;
+ list_add ( &nii->dev.siblings, &efidev->dev.children );
+ INIT_LIST_HEAD ( &nii->dev.children );
+ netdev->dev = &nii->dev;
+
+ /* Open NII protocol */
+ if ( ( efirc = bs->OpenProtocol ( device, &efi_nii31_protocol_guid,
+ &interface, efi_image_handle, device,
+ ( EFI_OPEN_PROTOCOL_BY_DRIVER |
+ EFI_OPEN_PROTOCOL_EXCLUSIVE )))!=0){
+ rc = -EEFI ( efirc );
+ DBGC ( nii, "NII %s cannot open NII protocol: %s\n",
+ nii->dev.name, strerror ( rc ) );
+ DBGC_EFI_OPENERS ( device, device, &efi_nii31_protocol_guid );
+ goto err_open_protocol;
+ }
+ nii->nii = interface;
+
+ /* Locate UNDI and entry point */
+ nii->undi = ( ( void * ) ( intptr_t ) nii->nii->Id );
+ if ( nii->undi->Implementation & PXE_ROMID_IMP_HW_UNDI ) {
+ DBGC ( nii, "NII %s is a mythical hardware UNDI\n",
+ nii->dev.name );
+ rc = -ENOTSUP;
+ goto err_hw_undi;
+ }
+ if ( nii->undi->Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR ) {
+ nii->issue = ( ( void * ) ( intptr_t ) nii->undi->EntryPoint );
+ } else {
+ nii->issue = ( ( ( void * ) nii->undi ) +
+ nii->undi->EntryPoint );
+ }
+ DBGC ( nii, "NII %s using UNDI v%x.%x at %p entry %p\n", nii->dev.name,
+ nii->nii->MajorVer, nii->nii->MinorVer, nii->undi, nii->issue );
+
+ /* Open PCI I/O protocols and locate BARs */
+ if ( ( rc = nii_pci_open ( nii ) ) != 0 )
+ goto err_pci_open;
+
+ /* Start UNDI */
+ if ( ( rc = nii_start_undi ( nii ) ) != 0 )
+ goto err_start_undi;
+
+ /* Get initialisation information */
+ if ( ( rc = nii_get_init_info ( nii, netdev ) ) != 0 )
+ goto err_get_init_info;
+
+ /* Get MAC addresses */
+ if ( ( rc = nii_get_station_address ( nii, netdev ) ) != 0 )
+ goto err_get_station_address;
+
+ /* Register network device */
+ if ( ( rc = register_netdev ( netdev ) ) != 0 )
+ goto err_register_netdev;
+ DBGC ( nii, "NII %s registered as %s for %p %s\n", nii->dev.name,
+ netdev->name, device, efi_handle_name ( device ) );
+
+ return 0;
+
+ unregister_netdev ( netdev );
+ err_register_netdev:
+ err_get_station_address:
+ err_get_init_info:
+ nii_stop_undi ( nii );
+ err_start_undi:
+ nii_pci_close ( nii );
+ err_pci_open:
+ err_hw_undi:
+ bs->CloseProtocol ( device, &efi_nii31_protocol_guid,
+ efi_image_handle, device );
+ err_open_protocol:
+ list_del ( &nii->dev.siblings );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+ err_alloc:
+ return rc;
+}
+
+/**
+ * Detach driver from device
+ *
+ * @v efidev EFI device
+ */
+static void nii_stop ( struct efi_device *efidev ) {
+ EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
+ struct net_device *netdev = efidev_get_drvdata ( efidev );
+ struct nii_nic *nii = netdev->priv;
+ EFI_HANDLE device = efidev->device;
+
+ /* Unregister network device */
+ unregister_netdev ( netdev );
+
+ /* Stop UNDI */
+ nii_stop_undi ( nii );
+
+ /* Close PCI I/O protocols */
+ nii_pci_close ( nii );
+
+ /* Close NII protocol */
+ bs->CloseProtocol ( device, &efi_nii31_protocol_guid,
+ efi_image_handle, device );
+
+ /* Free network device */
+ list_del ( &nii->dev.siblings );
+ netdev_nullify ( netdev );
+ netdev_put ( netdev );
+}
+
+/** EFI NII driver */
+struct efi_driver nii_driver __efi_driver ( EFI_DRIVER_NORMAL ) = {
+ .name = "NII",
+ .supported = nii_supported,
+ .start = nii_start,
+ .stop = nii_stop,
+};
diff --git a/src/include/ipxe/efi/IndustryStandard/Acpi10.h b/src/include/ipxe/efi/IndustryStandard/Acpi10.h
new file mode 100644
index 0000000..7857047
--- /dev/null
+++ b/src/include/ipxe/efi/IndustryStandard/Acpi10.h
@@ -0,0 +1,663 @@
+/** @file
+ ACPI 1.0b definitions from the ACPI Specification, revision 1.0b
+
+Copyright (c) 2006 - 2011, 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 that 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_1_0_H_
+#define _ACPI_1_0_H_
+
+FILE_LICENCE ( BSD3 );
+
+#include <ipxe/efi/IndustryStandard/AcpiAml.h>
+
+///
+/// Common table header, this prefaces all ACPI tables, including FACS, but
+/// excluding the RSD PTR structure.
+///
+typedef struct {
+ UINT32 Signature;
+ UINT32 Length;
+} EFI_ACPI_COMMON_HEADER;
+
+#pragma pack(1)
+///
+/// The common ACPI description table header. This structure prefaces most ACPI tables.
+///
+typedef struct {
+ UINT32 Signature;
+ UINT32 Length;
+ UINT8 Revision;
+ UINT8 Checksum;
+ UINT8 OemId[6];
+ UINT64 OemTableId;
+ UINT32 OemRevision;
+ UINT32 CreatorId;
+ UINT32 CreatorRevision;
+} EFI_ACPI_DESCRIPTION_HEADER;
+#pragma pack()
+
+//
+// Define for Desriptor
+//
+#define ACPI_SMALL_ITEM_FLAG 0x00
+#define ACPI_LARGE_ITEM_FLAG 0x01
+
+//
+// Small Item Descriptor Name
+//
+#define ACPI_SMALL_IRQ_DESCRIPTOR_NAME 0x04
+#define ACPI_SMALL_DMA_DESCRIPTOR_NAME 0x05
+#define ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME 0x06
+#define ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME 0x07
+#define ACPI_SMALL_IO_PORT_DESCRIPTOR_NAME 0x08
+#define ACPI_SMALL_FIXED_IO_PORT_DESCRIPTOR_NAME 0x09
+#define ACPI_SMALL_VENDOR_DEFINED_DESCRIPTOR_NAME 0x0E
+#define ACPI_SMALL_END_TAG_DESCRIPTOR_NAME 0x0F
+
+//
+// Large Item Descriptor Name
+//
+#define ACPI_LARGE_24_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x01
+#define ACPI_LARGE_VENDOR_DEFINED_DESCRIPTOR_NAME 0x04
+#define ACPI_LARGE_32_BIT_MEMORY_RANGE_DESCRIPTOR_NAME 0x05
+#define ACPI_LARGE_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR_NAME 0x06
+#define ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x07
+#define ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x08
+#define ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME 0x09
+#define ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME 0x0A
+
+//
+// Small Item Descriptor Value
+//
+#define ACPI_IRQ_NOFLAG_DESCRIPTOR 0x22
+#define ACPI_IRQ_DESCRIPTOR 0x23
+#define ACPI_DMA_DESCRIPTOR 0x2A
+#define ACPI_START_DEPENDENT_DESCRIPTOR 0x30
+#define ACPI_START_DEPENDENT_EX_DESCRIPTOR 0x31
+#define ACPI_END_DEPENDENT_DESCRIPTOR 0x38
+#define ACPI_IO_PORT_DESCRIPTOR 0x47
+#define ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR 0x4B
+#define ACPI_END_TAG_DESCRIPTOR 0x79
+
+//
+// Large Item Descriptor Value
+//
+#define ACPI_24_BIT_MEMORY_RANGE_DESCRIPTOR 0x81
+#define ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR 0x85
+#define ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR 0x86
+#define ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR 0x87
+#define ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR 0x88
+#define ACPI_EXTENDED_INTERRUPT_DESCRIPTOR 0x89
+#define ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR 0x8A
+#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A
+
+//
+// Resource Type
+//
+#define ACPI_ADDRESS_SPACE_TYPE_MEM 0x00
+#define ACPI_ADDRESS_SPACE_TYPE_IO 0x01
+#define ACPI_ADDRESS_SPACE_TYPE_BUS 0x02
+
+///
+/// Power Management Timer frequency is fixed at 3.579545MHz.
+///
+#define ACPI_TIMER_FREQUENCY 3579545
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+
+///
+/// The commond definition of QWORD, DWORD, and WORD
+/// Address Space Descriptors.
+///
+typedef PACKED struct {
+ UINT8 Desc;
+ UINT16 Len;
+ UINT8 ResType;
+ UINT8 GenFlag;
+ UINT8 SpecificFlag;
+ UINT64 AddrSpaceGranularity;
+ UINT64 AddrRangeMin;
+ UINT64 AddrRangeMax;
+ UINT64 AddrTranslationOffset;
+ UINT64 AddrLen;
+} EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR;
+
+typedef PACKED union {
+ UINT8 Byte;
+ PACKED struct {
+ UINT8 Length : 3;
+ UINT8 Name : 4;
+ UINT8 Type : 1;
+ } Bits;
+} ACPI_SMALL_RESOURCE_HEADER;
+
+typedef PACKED struct {
+ PACKED union {
+ UINT8 Byte;
+ PACKED struct {
+ UINT8 Name : 7;
+ UINT8 Type : 1;
+ }Bits;
+ } Header;
+ UINT16 Length;
+} ACPI_LARGE_RESOURCE_HEADER;
+
+///
+/// IRQ Descriptor.
+///
+typedef PACKED struct {
+ ACPI_SMALL_RESOURCE_HEADER Header;
+ UINT16 Mask;
+} EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR;
+
+///
+/// IRQ Descriptor.
+///
+typedef PACKED struct {
+ ACPI_SMALL_RESOURCE_HEADER Header;
+ UINT16 Mask;
+ UINT8 Information;
+} EFI_ACPI_IRQ_DESCRIPTOR;
+
+///
+/// DMA Descriptor.
+///
+typedef PACKED struct {
+ ACPI_SMALL_RESOURCE_HEADER Header;
+ UINT8 ChannelMask;
+ UINT8 Information;
+} EFI_ACPI_DMA_DESCRIPTOR;
+
+///
+/// I/O Port Descriptor
+///
+typedef PACKED struct {
+ ACPI_SMALL_RESOURCE_HEADER Header;
+ UINT8 Information;
+ UINT16 BaseAddressMin;
+ UINT16 BaseAddressMax;
+ UINT8 Alignment;
+ UINT8 Length;
+} EFI_ACPI_IO_PORT_DESCRIPTOR;
+
+///
+/// Fixed Location I/O Port Descriptor.
+///
+typedef PACKED struct {
+ ACPI_SMALL_RESOURCE_HEADER Header;
+ UINT16 BaseAddress;
+ UINT8 Length;
+} EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR;
+
+///
+/// 24-Bit Memory Range Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 Information;
+ UINT16 BaseAddressMin;
+ UINT16 BaseAddressMax;
+ UINT16 Alignment;
+ UINT16 Length;
+} EFI_ACPI_24_BIT_MEMORY_RANGE_DESCRIPTOR;
+
+///
+/// 32-Bit Memory Range Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 Information;
+ UINT32 BaseAddressMin;
+ UINT32 BaseAddressMax;
+ UINT32 Alignment;
+ UINT32 Length;
+} EFI_ACPI_32_BIT_MEMORY_RANGE_DESCRIPTOR;
+
+///
+/// Fixed 32-Bit Fixed Memory Range Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 Information;
+ UINT32 BaseAddress;
+ UINT32 Length;
+} EFI_ACPI_32_BIT_FIXED_MEMORY_RANGE_DESCRIPTOR;
+
+///
+/// QWORD Address Space Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 ResType;
+ UINT8 GenFlag;
+ UINT8 SpecificFlag;
+ UINT64 AddrSpaceGranularity;
+ UINT64 AddrRangeMin;
+ UINT64 AddrRangeMax;
+ UINT64 AddrTranslationOffset;
+ UINT64 AddrLen;
+} EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR;
+
+///
+/// DWORD Address Space Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 ResType;
+ UINT8 GenFlag;
+ UINT8 SpecificFlag;
+ UINT32 AddrSpaceGranularity;
+ UINT32 AddrRangeMin;
+ UINT32 AddrRangeMax;
+ UINT32 AddrTranslationOffset;
+ UINT32 AddrLen;
+} EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR;
+
+///
+/// WORD Address Space Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 ResType;
+ UINT8 GenFlag;
+ UINT8 SpecificFlag;
+ UINT16 AddrSpaceGranularity;
+ UINT16 AddrRangeMin;
+ UINT16 AddrRangeMax;
+ UINT16 AddrTranslationOffset;
+ UINT16 AddrLen;
+} EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR;
+
+///
+/// Extended Interrupt Descriptor
+///
+typedef PACKED struct {
+ ACPI_LARGE_RESOURCE_HEADER Header;
+ UINT8 InterruptVectorFlags;
+ UINT8 InterruptTableLength;
+ UINT32 InterruptNumber[1];
+} EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR;
+
+#pragma pack()
+
+///
+/// The End tag identifies an end of resource data.
+///
+typedef struct {
+ UINT8 Desc;
+ UINT8 Checksum;
+} EFI_ACPI_END_TAG_DESCRIPTOR;
+
+//
+// General use definitions
+//
+#define EFI_ACPI_RESERVED_BYTE 0x00
+#define EFI_ACPI_RESERVED_WORD 0x0000
+#define EFI_ACPI_RESERVED_DWORD 0x00000000
+#define EFI_ACPI_RESERVED_QWORD 0x0000000000000000
+
+//
+// Resource Type Specific Flags
+// Ref ACPI specification 6.4.3.5.5
+//
+// Bit [0] : Write Status, _RW
+//
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_WRITE (1 << 0)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_ONLY (0 << 0)
+//
+// Bit [2:1] : Memory Attributes, _MEM
+//
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_NON_CACHEABLE (0 << 1)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE (1 << 1)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_WRITE_COMBINING (2 << 1)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE (3 << 1)
+//
+// Bit [4:3] : Memory Attributes, _MTP
+//
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_MEMORY (0 << 3)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_RESERVED (1 << 3)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_ACPI (2 << 3)
+#define EFI_APCI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_NVS (3 << 3)
+//
+// Bit [5] : Memory to I/O Translation, _TTP
+//
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_TRANSLATION (1 << 5)
+#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_STATIC (0 << 5)
+
+//
+// IRQ Information
+// Ref ACPI specification 6.4.2.1
+//
+#define EFI_ACPI_IRQ_SHARABLE_MASK 0x10
+#define EFI_ACPI_IRQ_SHARABLE 0x10
+
+#define EFI_ACPI_IRQ_POLARITY_MASK 0x08
+#define EFI_ACPI_IRQ_HIGH_TRUE 0x00
+#define EFI_ACPI_IRQ_LOW_FALSE 0x08
+
+#define EFI_ACPI_IRQ_MODE 0x01
+#define EFI_ACPI_IRQ_LEVEL_TRIGGERED 0x00
+#define EFI_ACPI_IRQ_EDGE_TRIGGERED 0x01
+
+//
+// DMA Information
+// Ref ACPI specification 6.4.2.2
+//
+#define EFI_ACPI_DMA_SPEED_TYPE_MASK 0x60
+#define EFI_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00
+#define EFI_ACPI_DMA_SPEED_TYPE_A 0x20
+#define EFI_ACPI_DMA_SPEED_TYPE_B 0x40
+#define EFI_ACPI_DMA_SPEED_TYPE_F 0x60
+
+#define EFI_ACPI_DMA_BUS_MASTER_MASK 0x04
+#define EFI_ACPI_DMA_BUS_MASTER 0x04
+
+#define EFI_ACPI_DMA_TRANSFER_TYPE_MASK 0x03
+#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x00
+#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x01
+#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x10
+
+//
+// IO Information
+// Ref ACPI specification 6.4.2.5
+//
+#define EFI_ACPI_IO_DECODE_MASK 0x01
+#define EFI_ACPI_IO_DECODE_16_BIT 0x01
+#define EFI_ACPI_IO_DECODE_10_BIT 0x00
+
+//
+// Memory Information
+// Ref ACPI specification 6.4.3.4
+//
+#define EFI_ACPI_MEMORY_WRITE_STATUS_MASK 0x01
+#define EFI_ACPI_MEMORY_WRITABLE 0x01
+#define EFI_ACPI_MEMORY_NON_WRITABLE 0x00
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+//
+// ACPI 1.0b table structures
+//
+
+///
+/// Root System Description Pointer Structure.
+///
+typedef struct {
+ UINT64 Signature;
+ UINT8 Checksum;
+ UINT8 OemId[6];
+ UINT8 Reserved;
+ UINT32 RsdtAddress;
+} EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER;
+
+//
+// Root System Description Table
+// No definition needed as it is a common description table header, the same with
+// EFI_ACPI_DESCRIPTION_HEADER, followed by a variable number of UINT32 table pointers.
+//
+
+///
+/// RSDT Revision (as defined in ACPI 1.0b specification).
+///
+#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01
+
+///
+/// Fixed ACPI Description Table Structure (FADT).
+///
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT32 FirmwareCtrl;
+ UINT32 Dsdt;
+ UINT8 IntModel;
+ UINT8 Reserved1;
+ UINT16 SciInt;
+ UINT32 SmiCmd;
+ UINT8 AcpiEnable;
+ UINT8 AcpiDisable;
+ UINT8 S4BiosReq;
+ UINT8 Reserved2;
+ UINT32 Pm1aEvtBlk;
+ UINT32 Pm1bEvtBlk;
+ UINT32 Pm1aCntBlk;
+ UINT32 Pm1bCntBlk;
+ UINT32 Pm2CntBlk;
+ UINT32 PmTmrBlk;
+ UINT32 Gpe0Blk;
+ UINT32 Gpe1Blk;
+ UINT8 Pm1EvtLen;
+ UINT8 Pm1CntLen;
+ UINT8 Pm2CntLen;
+ UINT8 PmTmLen;
+ UINT8 Gpe0BlkLen;
+ UINT8 Gpe1BlkLen;
+ UINT8 Gpe1Base;
+ UINT8 Reserved3;
+ UINT16 PLvl2Lat;
+ UINT16 PLvl3Lat;
+ UINT16 FlushSize;
+ UINT16 FlushStride;
+ UINT8 DutyOffset;
+ UINT8 DutyWidth;
+ UINT8 DayAlrm;
+ UINT8 MonAlrm;
+ UINT8 Century;
+ UINT8 Reserved4;
+ UINT8 Reserved5;
+ UINT8 Reserved6;
+ UINT32 Flags;
+} EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE;
+
+///
+/// FADT Version (as defined in ACPI 1.0b specification).
+///
+#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x01
+
+#define EFI_ACPI_1_0_INT_MODE_DUAL_PIC 0
+#define EFI_ACPI_1_0_INT_MODE_MULTIPLE_APIC 1
+
+//
+// Fixed ACPI Description Table Fixed Feature Flags
+// All other bits are reserved and must be set to 0.
+//
+#define EFI_ACPI_1_0_WBINVD BIT0
+#define EFI_ACPI_1_0_WBINVD_FLUSH BIT1
+#define EFI_ACPI_1_0_PROC_C1 BIT2
+#define EFI_ACPI_1_0_P_LVL2_UP BIT3
+#define EFI_ACPI_1_0_PWR_BUTTON BIT4
+#define EFI_ACPI_1_0_SLP_BUTTON BIT5
+#define EFI_ACPI_1_0_FIX_RTC BIT6
+#define EFI_ACPI_1_0_RTC_S4 BIT7
+#define EFI_ACPI_1_0_TMR_VAL_EXT BIT8
+#define EFI_ACPI_1_0_DCK_CAP BIT9
+
+///
+/// Firmware ACPI Control Structure.
+///
+typedef struct {
+ UINT32 Signature;
+ UINT32 Length;
+ UINT32 HardwareSignature;
+ UINT32 FirmwareWakingVector;
+ UINT32 GlobalLock;
+ UINT32 Flags;
+ UINT8 Reserved[40];
+} EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE;
+
+///
+/// Firmware Control Structure Feature Flags.
+/// All other bits are reserved and must be set to 0.
+///
+#define EFI_ACPI_1_0_S4BIOS_F BIT0
+
+///
+/// Multiple APIC Description Table header definition. The rest of the table
+/// must be defined in a platform-specific manner.
+///
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT32 LocalApicAddress;
+ UINT32 Flags;
+} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER;
+
+///
+/// MADT Revision (as defined in ACPI 1.0b specification).
+///
+#define EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01
+
+///
+/// Multiple APIC Flags
+/// All other bits are reserved and must be set to 0.
+///
+#define EFI_ACPI_1_0_PCAT_COMPAT BIT0
+
+//
+// Multiple APIC Description Table APIC structure types
+// All other values between 0x05 an 0xFF are reserved and
+// will be ignored by OSPM.
+//
+#define EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC 0x00
+#define EFI_ACPI_1_0_IO_APIC 0x01
+#define EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE 0x02
+#define EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03
+#define EFI_ACPI_1_0_LOCAL_APIC_NMI 0x04
+
+//
+// APIC Structure Definitions
+//
+
+///
+/// Processor Local APIC Structure Definition.
+///
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT8 AcpiProcessorId;
+ UINT8 ApicId;
+ UINT32 Flags;
+} EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE;
+
+///
+/// Local APIC Flags. All other bits are reserved and must be 0.
+///
+#define EFI_ACPI_1_0_LOCAL_APIC_ENABLED BIT0
+
+///
+/// IO APIC Structure.
+///
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT8 IoApicId;
+ UINT8 Reserved;
+ UINT32 IoApicAddress;
+ UINT32 SystemVectorBase;
+} EFI_ACPI_1_0_IO_APIC_STRUCTURE;
+
+///
+/// Interrupt Source Override Structure.
+///
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT8 Bus;
+ UINT8 Source;
+ UINT32 GlobalSystemInterruptVector;
+ UINT16 Flags;
+} EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE;
+
+///
+/// Non-Maskable Interrupt Source Structure.
+///
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT16 Flags;
+ UINT32 GlobalSystemInterruptVector;
+} EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE;
+
+///
+/// Local APIC NMI Structure.
+///
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT8 AcpiProcessorId;
+ UINT16 Flags;
+ UINT8 LocalApicInti;
+} EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE;
+
+///
+/// Smart Battery Description Table (SBST)
+///
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT32 WarningEnergyLevel;
+ UINT32 LowEnergyLevel;
+ UINT32 CriticalEnergyLevel;
+} EFI_ACPI_1_0_SMART_BATTERY_DESCRIPTION_TABLE;
+
+//
+// Known table signatures
+//
+
+///
+/// "RSD PTR " Root System Description Pointer.
+///
+#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE SIGNATURE_64('R', 'S', 'D', ' ', 'P', 'T', 'R', ' ')
+
+///
+/// "APIC" Multiple APIC Description Table.
+///
+#define EFI_ACPI_1_0_APIC_SIGNATURE SIGNATURE_32('A', 'P', 'I', 'C')
+
+///
+/// "DSDT" Differentiated System Description Table.
+///
+#define EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('D', 'S', 'D', 'T')
+
+///
+/// "FACS" Firmware ACPI Control Structure.
+///
+#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'S')
+
+///
+/// "FACP" Fixed ACPI Description Table.
+///
+#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('F', 'A', 'C', 'P')
+
+///
+/// "PSDT" Persistent System Description Table.
+///
+#define EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('P', 'S', 'D', 'T')
+
+///
+/// "RSDT" Root System Description Table.
+///
+#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('R', 'S', 'D', 'T')
+
+///
+/// "SBST" Smart Battery Specification Table.
+///
+#define EFI_ACPI_1_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE SIGNATURE_32('S', 'B', 'S', 'T')
+
+///
+/// "SSDT" Secondary System Description Table.
+///
+#define EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('S', 'S', 'D', 'T')
+
+#pragma pack()
+
+#endif
diff --git a/src/include/ipxe/efi/IndustryStandard/AcpiAml.h b/src/include/ipxe/efi/IndustryStandard/AcpiAml.h
new file mode 100644
index 0000000..a9186b4
--- /dev/null
+++ b/src/include/ipxe/efi/IndustryStandard/AcpiAml.h
@@ -0,0 +1,177 @@
+/** @file
+ This file contains AML code definition in the latest ACPI spec.
+
+ Copyright (c) 2011, 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_AML_H_
+#define _ACPI_AML_H_
+
+FILE_LICENCE ( BSD3 );
+
+//
+// ACPI AML definition
+//
+
+//
+// Primary OpCode
+//
+#define AML_ZERO_OP 0x00
+#define AML_ONE_OP 0x01
+#define AML_ALIAS_OP 0x06
+#define AML_NAME_OP 0x08
+#define AML_BYTE_PREFIX 0x0a
+#define AML_WORD_PREFIX 0x0b
+#define AML_DWORD_PREFIX 0x0c
+#define AML_STRING_PREFIX 0x0d
+#define AML_QWORD_PREFIX 0x0e
+#define AML_SCOPE_OP 0x10
+#define AML_BUFFER_OP 0x11
+#define AML_PACKAGE_OP 0x12
+#define AML_VAR_PACKAGE_OP 0x13
+#define AML_METHOD_OP 0x14
+#define AML_DUAL_NAME_PREFIX 0x2e
+#define AML_MULTI_NAME_PREFIX 0x2f
+#define AML_NAME_CHAR_A 0x41
+#define AML_NAME_CHAR_B 0x42
+#define AML_NAME_CHAR_C 0x43
+#define AML_NAME_CHAR_D 0x44
+#define AML_NAME_CHAR_E 0x45
+#define AML_NAME_CHAR_F 0x46
+#define AML_NAME_CHAR_G 0x47
+#define AML_NAME_CHAR_H 0x48
+#define AML_NAME_CHAR_I 0x49
+#define AML_NAME_CHAR_J 0x4a
+#define AML_NAME_CHAR_K 0x4b
+#define AML_NAME_CHAR_L 0x4c
+#define AML_NAME_CHAR_M 0x4d
+#define AML_NAME_CHAR_N 0x4e
+#define AML_NAME_CHAR_O 0x4f
+#define AML_NAME_CHAR_P 0x50
+#define AML_NAME_CHAR_Q 0x51
+#define AML_NAME_CHAR_R 0x52
+#define AML_NAME_CHAR_S 0x53
+#define AML_NAME_CHAR_T 0x54
+#define AML_NAME_CHAR_U 0x55
+#define AML_NAME_CHAR_V 0x56
+#define AML_NAME_CHAR_W 0x57
+#define AML_NAME_CHAR_X 0x58
+#define AML_NAME_CHAR_Y 0x59
+#define AML_NAME_CHAR_Z 0x5a
+#define AML_ROOT_CHAR 0x5c
+#define AML_PARENT_PREFIX_CHAR 0x5e
+#define AML_NAME_CHAR__ 0x5f
+#define AML_LOCAL0 0x60
+#define AML_LOCAL1 0x61
+#define AML_LOCAL2 0x62
+#define AML_LOCAL3 0x63
+#define AML_LOCAL4 0x64
+#define AML_LOCAL5 0x65
+#define AML_LOCAL6 0x66
+#define AML_LOCAL7 0x67
+#define AML_ARG0 0x68
+#define AML_ARG1 0x69
+#define AML_ARG2 0x6a
+#define AML_ARG3 0x6b
+#define AML_ARG4 0x6c
+#define AML_ARG5 0x6d
+#define AML_ARG6 0x6e
+#define AML_STORE_OP 0x70
+#define AML_REF_OF_OP 0x71
+#define AML_ADD_OP 0x72
+#define AML_CONCAT_OP 0x73
+#define AML_SUBTRACT_OP 0x74
+#define AML_INCREMENT_OP 0x75
+#define AML_DECREMENT_OP 0x76
+#define AML_MULTIPLY_OP 0x77
+#define AML_DIVIDE_OP 0x78
+#define AML_SHIFT_LEFT_OP 0x79
+#define AML_SHIFT_RIGHT_OP 0x7a
+#define AML_AND_OP 0x7b
+#define AML_NAND_OP 0x7c
+#define AML_OR_OP 0x7d
+#define AML_NOR_OP 0x7e
+#define AML_XOR_OP 0x7f
+#define AML_NOT_OP 0x80
+#define AML_FIND_SET_LEFT_BIT_OP 0x81
+#define AML_FIND_SET_RIGHT_BIT_OP 0x82
+#define AML_DEREF_OF_OP 0x83
+#define AML_CONCAT_RES_OP 0x84
+#define AML_MOD_OP 0x85
+#define AML_NOTIFY_OP 0x86
+#define AML_SIZE_OF_OP 0x87
+#define AML_INDEX_OP 0x88
+#define AML_MATCH_OP 0x89
+#define AML_CREATE_DWORD_FIELD_OP 0x8a
+#define AML_CREATE_WORD_FIELD_OP 0x8b
+#define AML_CREATE_BYTE_FIELD_OP 0x8c
+#define AML_CREATE_BIT_FIELD_OP 0x8d
+#define AML_OBJECT_TYPE_OP 0x8e
+#define AML_CREATE_QWORD_FIELD_OP 0x8f
+#define AML_LAND_OP 0x90
+#define AML_LOR_OP 0x91
+#define AML_LNOT_OP 0x92
+#define AML_LEQUAL_OP 0x93
+#define AML_LGREATER_OP 0x94
+#define AML_LLESS_OP 0x95
+#define AML_TO_BUFFER_OP 0x96
+#define AML_TO_DEC_STRING_OP 0x97
+#define AML_TO_HEX_STRING_OP 0x98
+#define AML_TO_INTEGER_OP 0x99
+#define AML_TO_STRING_OP 0x9c
+#define AML_COPY_OBJECT_OP 0x9d
+#define AML_MID_OP 0x9e
+#define AML_CONTINUE_OP 0x9f
+#define AML_IF_OP 0xa0
+#define AML_ELSE_OP 0xa1
+#define AML_WHILE_OP 0xa2
+#define AML_NOOP_OP 0xa3
+#define AML_RETURN_OP 0xa4
+#define AML_BREAK_OP 0xa5
+#define AML_BREAK_POINT_OP 0xcc
+#define AML_ONES_OP 0xff
+
+//
+// Extended OpCode
+//
+#define AML_EXT_OP 0x5b
+
+#define AML_EXT_MUTEX_OP 0x01
+#define AML_EXT_EVENT_OP 0x02
+#define AML_EXT_COND_REF_OF_OP 0x12
+#define AML_EXT_CREATE_FIELD_OP 0x13
+#define AML_EXT_LOAD_TABLE_OP 0x1f
+#define AML_EXT_LOAD_OP 0x20
+#define AML_EXT_STALL_OP 0x21
+#define AML_EXT_SLEEP_OP 0x22
+#define AML_EXT_ACQUIRE_OP 0x23
+#define AML_EXT_SIGNAL_OP 0x24
+#define AML_EXT_WAIT_OP 0x25
+#define AML_EXT_RESET_OP 0x26
+#define AML_EXT_RELEASE_OP 0x27
+#define AML_EXT_FROM_BCD_OP 0x28
+#define AML_EXT_TO_BCD_OP 0x29
+#define AML_EXT_UNLOAD_OP 0x2a
+#define AML_EXT_REVISION_OP 0x30
+#define AML_EXT_DEBUG_OP 0x31
+#define AML_EXT_FATAL_OP 0x32
+#define AML_EXT_TIMER_OP 0x33
+#define AML_EXT_REGION_OP 0x80
+#define AML_EXT_FIELD_OP 0x81
+#define AML_EXT_DEVICE_OP 0x82
+#define AML_EXT_PROCESSOR_OP 0x83
+#define AML_EXT_POWER_RES_OP 0x84
+#define AML_EXT_THERMAL_ZONE_OP 0x85
+#define AML_EXT_INDEX_FIELD_OP 0x86
+#define AML_EXT_BANK_FIELD_OP 0x87
+#define AML_EXT_DATA_REGION_OP 0x88
+
+#endif
diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h
index e3989a5..f809337 100644
--- a/src/include/ipxe/errfile.h
+++ b/src/include/ipxe/errfile.h
@@ -156,6 +156,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_intelx ( ERRFILE_DRIVER | 0x00670000 )
#define ERRFILE_snp ( ERRFILE_DRIVER | 0x00680000 )
#define ERRFILE_netfront ( ERRFILE_DRIVER | 0x00690000 )
+#define ERRFILE_nii ( ERRFILE_DRIVER | 0x006a0000 )
#define ERRFILE_scsi ( ERRFILE_DRIVER | 0x00700000 )
#define ERRFILE_arbel ( ERRFILE_DRIVER | 0x00710000 )
diff --git a/src/include/ipxe/ethernet.h b/src/include/ipxe/ethernet.h
index b28a6b8..d1263d7 100644
--- a/src/include/ipxe/ethernet.h
+++ b/src/include/ipxe/ethernet.h
@@ -80,6 +80,8 @@ static inline int is_valid_ether_addr ( const void *addr ) {
}
extern uint8_t eth_broadcast[];
+extern struct ll_protocol ethernet_protocol __ll_protocol;
+
extern int eth_push ( struct net_device *netdev, struct io_buffer *iobuf,
const void *ll_dest, const void *ll_source,
uint16_t net_proto );