iPXE
efi_table.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <assert.h>
28#include <errno.h>
29#include <string.h>
30#include <ipxe/efi/efi.h>
31#include <ipxe/efi/efi_table.h>
32
33/** @file
34 *
35 * EFI configuration tables
36 *
37 */
38
39/**
40 * Look up EFI configuration table
41 *
42 * @v guid Configuration table GUID
43 * @ret table Configuration table, or NULL
44 */
46 void *table;
47 unsigned int i;
48
49 /* Scan for installed table */
50 for ( i = 0 ; i < efi_systab->NumberOfTableEntries ; i++ ) {
51 if ( memcmp ( &efi_systab->ConfigurationTable[i].VendorGuid,
52 guid, sizeof ( *guid ) ) == 0 ) {
53 table = efi_systab->ConfigurationTable[i].VendorTable;
54 DBGC ( guid, "EFITAB %s is at %p\n",
55 efi_guid_ntoa ( guid ), table );
56 return table;
57 }
58 }
59
60 return NULL;
61}
62
63/**
64 * Install EFI configuration table
65 *
66 * @v table Configuration table type
67 * @v data Configuration table data, or NULL to uninstall
68 * @v backup Table backup, or NULL to not back up old table
69 * @ret rc Return status code
70 */
71int efi_install_table ( struct efi_table *table, const void *data,
72 void **backup ) {
73 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
74 EFI_GUID *guid = table->guid;
75 void *copy;
76 void *new;
77 void *old;
78 size_t old_len;
79 size_t new_len;
80 EFI_STATUS efirc;
81 int rc;
82
83 /* Get currently installed table, if any */
85 old_len = ( old ? table->len ( old ) : 0 );
86
87 /* Create backup copy, if applicable */
88 if ( old_len && backup ) {
89 if ( ( efirc = bs->AllocatePool ( EfiBootServicesData, old_len,
90 &copy ) ) != 0 ) {
91 rc = -EEFI ( efirc );
92 goto err_backup;
93 }
94 memcpy ( copy, old, old_len );
95 DBGC ( table, "EFITAB %s %p+%#zx backed up\n",
96 efi_guid_ntoa ( guid ), old, old_len );
97 } else {
98 copy = NULL;
99 }
100
101 /* Create installable runtime services data copy, if applicable */
102 new_len = ( data ? table->len ( data ) : 0 );
103 if ( new_len ) {
104 if ( ( efirc = bs->AllocatePool ( EfiRuntimeServicesData,
105 new_len, &new ) ) != 0 ) {
106 rc = -EEFI ( efirc );
107 goto err_allocate;
108 }
109 memcpy ( new, data, new_len );
110 } else {
111 new = NULL;
112 }
113
114 /* (Un)install configuration table, if applicable */
115 if ( new || old ) {
116 if ( ( efirc = bs->InstallConfigurationTable ( guid,
117 new ) ) != 0 ) {
118 rc = -EEFI ( efirc );
119 DBGC ( table, "EFITAB %s could not install: %s\n",
120 efi_guid_ntoa ( guid ), strerror ( rc ) );
121 goto err_install;
122 }
123 if ( old ) {
124 DBGC ( table, "EFITAB %s %p+%#zx uninstalled\n",
125 efi_guid_ntoa ( guid ), old, old_len );
126 }
127 if ( new ) {
128 DBGC ( table, "EFITAB %s %p+%#zx installed\n",
129 efi_guid_ntoa ( guid ), new, new_len );
130 }
131 }
132
133 /* Record backup copy, if applicable */
134 if ( backup ) {
135 if ( *backup )
136 bs->FreePool ( *backup );
137 *backup = copy;
138 }
139
140 /* Sanity check */
141 assert ( efi_find_table ( guid ) == new );
142
143 return 0;
144
145 err_install:
146 if ( new )
147 bs->FreePool ( new );
148 err_allocate:
149 if ( copy )
150 bs->FreePool ( copy );
151 err_backup:
152 return rc;
153}
154
155/**
156 * Uninstall EFI configuration table
157 *
158 * @v table Configuration table type
159 * @v backup Table backup (or NULL to not restore old table)
160 * @ret rc Return status code
161 */
162int efi_uninstall_table ( struct efi_table *table, void **backup ) {
163 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
164 void *old;
165 int rc;
166
167 /* Uninstall or reinstall as applicable */
168 old = ( backup ? *backup : NULL );
169 if ( ( rc = efi_install_table ( table, old, NULL ) ) != 0 )
170 return rc;
171
172 /* Free backup copy, if applicable */
173 if ( backup && *backup ) {
174 bs->FreePool ( *backup );
175 *backup = NULL;
176 }
177
178 return 0;
179}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
GUID EFI_GUID
128-bit buffer containing a unique identifier value.
@ EfiBootServicesData
The data portions of a loaded Boot Serves Driver, and the default data allocation type used by a Boot...
@ EfiRuntimeServicesData
The data portions of a loaded Runtime Services Driver and the default data allocation type used by a ...
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
int old
Definition bitops.h:65
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
uint64_t guid
GUID.
Definition edd.h:1
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition efi_guid.c:726
int efi_install_table(struct efi_table *table, const void *data, void **backup)
Install EFI configuration table.
Definition efi_table.c:71
void * efi_find_table(EFI_GUID *guid)
Look up EFI configuration table.
Definition efi_table.c:45
int efi_uninstall_table(struct efi_table *table, void **backup)
Uninstall EFI configuration table.
Definition efi_table.c:162
EFI configuration tables.
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
EFI API.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:175
EFI_SYSTEM_TABLE * efi_systab
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable
Definition UefiSpec.h:1973
EFI_FREE_POOL FreePool
Definition UefiSpec.h:1950
EFI_ALLOCATE_POOL AllocatePool
Definition UefiSpec.h:1949
An installable EFI configuration table type.
Definition efi_table.h:16
size_t(* len)(const void *data)
Determine length of table.
Definition efi_table.h:30
EFI_GUID * guid
Table GUID.
Definition efi_table.h:18