From 045a22764afd75a0b887c7da6828d683c303ebb4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 4 Dec 2008 04:04:54 +0000 Subject: [PATCH] [efi] Allow use of EFI configuration tables 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 | 33 +++++++++++++++++++++++ src/interface/efi/efi_entry.c | 49 ++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/src/include/gpxe/efi/efi.h b/src/include/gpxe/efi/efi.h index 8c9f789a..b46d5ca5 100644 --- a/src/include/gpxe/efi/efi.h +++ b/src/include/gpxe/efi/efi.h @@ -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 diff --git a/src/interface/efi/efi_entry.c b/src/interface/efi/efi_entry.c index b00828ad..7b670f8e 100644 --- a/src/interface/efi/efi_entry.c +++ b/src/interface/efi/efi_entry.c @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -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() */