[efi] Allow use of EFI configuration tables
authorMichael Brown <mcb30@etherboot.org>
Thu, 4 Dec 2008 04:04:54 +0000 (04:04 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 4 Dec 2008 23:18:32 +0000 (23:18 +0000)
EFI passes in copies of SMBIOS and other system configuration tables
via the EFI system table.  Allow configuration tables to be requested
using a mechanism similar to the current method for requesting EFI
protocols.

src/include/gpxe/efi/efi.h
src/interface/efi/efi_entry.c

index 8c9f789..b46d5ca 100644 (file)
@@ -43,6 +43,7 @@
 
 /** An EFI protocol used by gPXE */
 struct efi_protocol {
+       /** GUID */
        union {
                /** EFI protocol GUID */
                EFI_GUID guid;
@@ -70,6 +71,38 @@ struct efi_protocol {
                                (_ptr) : (_ptr) ) ),                         \
        }
 
+/** An EFI configuration table used by gPXE */
+struct efi_config_table {
+       /** GUID */
+       union {
+               /** EFI configuration table GUID */
+               EFI_GUID guid;
+               /** UUID structure understood by gPXE */
+               union uuid uuid;
+       } u;
+       /** Variable containing pointer to configuration table */
+       void **table;
+       /** Table is required for operation */
+       int required;
+};
+
+/** Declare an EFI configuration table used by gPXE */
+#define __efi_config_table \
+       __table ( struct efi_config_table, efi_config_tables, 01 )
+
+/** Declare an EFI configuration table to be used by gPXE
+ *
+ * @v _table           EFI configuration table name
+ * @v _ptr             Pointer to configuration table
+ * @v _required                Table is required for operation
+ */
+#define EFI_USE_TABLE( _table, _ptr, _required )                            \
+       struct efi_config_table __ ## _table __efi_config_table = {          \
+               .u.guid = _table ## _GUID,                                   \
+               .table = ( ( void ** ) ( void * ) (_ptr) ),                  \
+               .required = (_required),                                     \
+       }
+
 /** Convert a gPXE status code to an EFI status code
  *
  * FIXME: actually perform some kind of conversion.  gPXE error codes
index b00828a..7b670f8 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include <gpxe/efi/efi.h>
 #include <gpxe/uuid.h>
 
@@ -32,6 +33,30 @@ static struct efi_protocol efi_protocols[0] \
 static struct efi_protocol efi_protocols_end[0] \
        __table_end ( struct efi_protocol, efi_protocols );
 
+/** Declared used EFI configuration tables */
+static struct efi_config_table efi_config_tables[0] \
+       __table_start ( struct efi_config_table, efi_config_tables );
+static struct efi_config_table efi_config_tables_end[0] \
+       __table_end ( struct efi_config_table, efi_config_tables );
+
+/**
+ * Look up EFI configuration table
+ *
+ * @v guid             Configuration table GUID
+ * @ret table          Configuration table, or NULL
+ */
+static void * efi_find_table ( EFI_GUID *guid ) {
+       unsigned int i;
+
+       for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
+               if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid,
+                             guid, sizeof ( *guid ) ) == 0 )
+                       return efi_systab->ConfigurationTable[i].VendorTable;
+       }
+
+       return NULL;
+}
+
 /**
  * EFI entry point
  *
@@ -43,6 +68,7 @@ EFI_STATUS EFIAPI efi_entry ( EFI_HANDLE image_handle,
                              EFI_SYSTEM_TABLE *systab ) {
        EFI_BOOT_SERVICES *bs;
        struct efi_protocol *prot;
+       struct efi_config_table *tab;
        EFI_STATUS efirc;
 
        /* Store image handle and system table pointer for future use */
@@ -65,17 +91,32 @@ EFI_STATUS EFIAPI efi_entry ( EFI_HANDLE image_handle,
        }
        DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab );
 
-       /* Look up required protocols */
+       /* Look up used protocols */
        bs = systab->BootServices;
        for ( prot = efi_protocols ; prot < efi_protocols_end ; prot++ ) {
                if ( ( efirc = bs->LocateProtocol ( &prot->u.guid, NULL,
-                                                   prot->protocol ) ) != 0 ) {
+                                                   prot->protocol ) ) == 0 ) {
+                       DBGC ( systab, "EFI protocol %s is at %p\n",
+                              uuid_ntoa ( &prot->u.uuid ), *(prot->protocol));
+               } else {
                        DBGC ( systab, "EFI does not provide protocol %s\n",
                               uuid_ntoa ( &prot->u.uuid ) );
+                       /* All protocols are required */
                        return efirc;
                }
-               DBGC ( systab, "EFI protocol %s is at %p\n",
-                      uuid_ntoa ( &prot->u.uuid ), *(prot->protocol) );
+       }
+
+       /* Look up used configuration tables */
+       for ( tab = efi_config_tables ; tab < efi_config_tables_end ; tab++ ) {
+               if ( ( *(tab->table) = efi_find_table ( &tab->u.guid ) ) ) {
+                       DBGC ( systab, "EFI configuration table %s is at %p\n",
+                              uuid_ntoa ( &tab->u.uuid ), *(tab->table) );
+               } else {
+                       DBGC ( systab, "EFI does not provide configuration "
+                              "table %s\n", uuid_ntoa ( &tab->u.uuid ) );
+                       if ( tab->required )
+                               return EFI_NOT_AVAILABLE_YET;
+               }
        }
 
        /* Call to main() */