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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_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++ ) {
52  guid, sizeof ( *guid ) ) == 0 ) {
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  */
71 int efi_install_table ( struct efi_table *table, const void *data,
72  void **backup ) {
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 */
84  old = efi_find_table ( guid );
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  */
162 int efi_uninstall_table ( struct efi_table *table, void **backup ) {
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 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2099
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:175
128 bit buffer containing a unique identifier value.
Definition: Base.h:216
Error codes.
EFI_GUID VendorGuid
The 128-bit GUID value that uniquely identifies the system configuration table.
Definition: UefiSpec.h:2034
#define DBGC(...)
Definition: compiler.h:505
int old
Definition: bitops.h:65
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
void * memcpy(void *dest, const void *src, size_t len) __nonnull
EFI configuration tables.
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
EFI Boot Services Table.
Definition: UefiSpec.h:1931
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_guid.c:726
EFI_FREE_POOL FreePool
Definition: UefiSpec.h:1950
EFI API.
uint64_t guid
GUID.
Definition: edd.h:31
int efi_uninstall_table(struct efi_table *table, void **backup)
Uninstall EFI configuration table.
Definition: efi_table.c:162
The data portions of a loaded Runtime Services Driver and the default data allocation type used by a ...
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:32
UINTN NumberOfTableEntries
The number of system configuration tables in the buffer ConfigurationTable.
Definition: UefiSpec.h:2103
uint8_t data[48]
Additional event data.
Definition: ena.h:22
EFI_SYSTEM_TABLE * efi_systab
The data portions of a loaded Boot Serves Driver, and the default data allocation type used by a Boot...
EFI_GUID * guid
Table GUID.
Definition: efi_table.h:18
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:115
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
FILE_SECBOOT(PERMITTED)
void * efi_find_table(EFI_GUID *guid)
Look up EFI configuration table.
Definition: efi_table.c:45
EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable
Definition: UefiSpec.h:1973
EFI_ALLOCATE_POOL AllocatePool
Definition: UefiSpec.h:1949
EFI_CONFIGURATION_TABLE * ConfigurationTable
A pointer to the system configuration tables.
Definition: UefiSpec.h:2108
int efi_install_table(struct efi_table *table, const void *data, void **backup)
Install EFI configuration table.
Definition: efi_table.c:71
VOID * VendorTable
A pointer to the table associated with VendorGuid.
Definition: UefiSpec.h:2038