iPXE
efi_settings.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2023 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 /**
28  * @file
29  *
30  * EFI variable settings
31  *
32  */
33 
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <ipxe/settings.h>
38 #include <ipxe/init.h>
39 #include <ipxe/efi/efi.h>
40 #include <ipxe/efi/efi_strings.h>
41 
42 /** EFI variable settings scope */
43 static const struct settings_scope efivars_scope;
44 
45 /** EFI variable settings */
46 static struct settings efivars;
47 
48 /**
49  * Check applicability of EFI variable setting
50  *
51  * @v settings Settings block
52  * @v setting Setting
53  * @ret applies Setting applies within this settings block
54  */
56  const struct setting *setting ) {
57 
58  return ( setting->scope == &efivars_scope );
59 }
60 
61 /**
62  * Find first matching EFI variable name
63  *
64  * @v wname Name
65  * @v guid GUID to fill in
66  * @ret rc Return status code
67  */
68 static int efivars_find ( const CHAR16 *wname, EFI_GUID *guid ) {
70  size_t wname_len = ( ( wcslen ( wname ) + 1 ) * sizeof ( wname[0] ) );
71  CHAR16 *buf;
72  CHAR16 *tmp;
73  UINTN size;
74  EFI_STATUS efirc;
75  int rc;
76 
77  /* Allocate single wNUL for first call to GetNextVariableName() */
78  size = sizeof ( buf[0] );
79  buf = zalloc ( size );
80  if ( ! buf )
81  return -ENOMEM;
82 
83  /* Iterate over all veriables */
84  while ( 1 ) {
85 
86  /* Get next variable name */
87  efirc = rs->GetNextVariableName ( &size, buf, guid );
88  if ( efirc == EFI_BUFFER_TOO_SMALL ) {
89  tmp = realloc ( buf, size );
90  if ( ! tmp ) {
91  rc = -ENOMEM;
92  break;
93  }
94  buf = tmp;
95  efirc = rs->GetNextVariableName ( &size, buf, guid );
96  }
97  if ( efirc == EFI_NOT_FOUND ) {
98  rc = -ENOENT;
99  break;
100  }
101  if ( efirc != 0 ) {
102  rc = -EEFI ( efirc );
103  DBGC ( &efivars, "EFIVARS %s:%ls could not fetch next "
104  "variable name: %s\n",
105  efi_guid_ntoa ( guid ), buf, strerror ( rc ) );
106  break;
107  }
108  DBGC2 ( &efivars, "EFIVARS %s:%ls exists\n",
109  efi_guid_ntoa ( guid ), buf );
110 
111  /* Check for matching variable name */
112  if ( memcmp ( wname, buf, wname_len ) == 0 ) {
113  rc = 0;
114  break;
115  }
116  }
117 
118  /* Free temporary buffer */
119  free ( buf );
120 
121  return rc;
122 }
123 
124 /**
125  * Fetch value of EFI variable setting
126  *
127  * @v settings Settings block
128  * @v setting Setting to fetch
129  * @v data Buffer to fill with setting data
130  * @v len Length of buffer
131  * @ret len Length of setting data, or negative error
132  */
134  struct setting *setting, void *data, size_t len ) {
136  size_t name_len = strlen ( setting->name );
137  CHAR16 wname[ name_len + 1 /* wNUL */ ];
138  EFI_GUID guid;
139  UINT32 attrs;
140  UINTN size;
141  void *buf;
142  EFI_STATUS efirc;
143  int rc;
144 
145  /* Convert name to UCS-2 */
146  efi_snprintf ( wname, sizeof ( wname ), "%s", setting->name );
147 
148  /* Find variable GUID */
149  if ( ( rc = efivars_find ( wname, &guid ) ) != 0 )
150  goto err_find;
151 
152  /* Get variable length */
153  size = 0;
154  if ( ( efirc = rs->GetVariable ( wname, &guid, &attrs, &size,
155  NULL ) != EFI_BUFFER_TOO_SMALL ) ) {
156  rc = -EEFI ( efirc );
157  DBGC ( &efivars, "EFIVARS %s:%ls could not get size: %s\n",
158  efi_guid_ntoa ( &guid ), wname, strerror ( rc ) );
159  goto err_len;
160  }
161 
162  /* Allocate temporary buffer, since GetVariable() is not
163  * guaranteed to return partial data for an underlength
164  * buffer.
165  */
166  buf = malloc ( size );
167  if ( ! buf ) {
168  rc = -ENOMEM;
169  goto err_alloc;
170  }
171 
172  /* Get variable value */
173  if ( ( efirc = rs->GetVariable ( wname, &guid, &attrs, &size,
174  buf ) ) != 0 ) {
175  rc = -EEFI ( efirc );
176  DBGC ( &efivars, "EFIVARS %s:%ls could not get %zd bytes: "
177  "%s\n", efi_guid_ntoa ( &guid ), wname,
178  ( ( size_t ) size ), strerror ( rc ) );
179  goto err_get;
180  }
181  DBGC ( &efivars, "EFIVARS %s:%ls:\n", efi_guid_ntoa ( &guid ), wname );
182  DBGC_HDA ( &efivars, 0, buf, size );
183 
184  /* Return setting value */
185  if ( len > size )
186  len = size;
187  memcpy ( data, buf, len );
188  if ( ! setting->type )
189  setting->type = &setting_type_hex;
190 
191  /* Free temporary buffer */
192  free ( buf );
193 
194  return size;
195 
196  err_get:
197  free ( buf );
198  err_alloc:
199  err_len:
200  err_find:
201  return rc;
202 }
203 
204 /** EFI variable settings operations */
207  .fetch = efivars_fetch,
208 };
209 
210 /** EFI variable settings */
211 static struct settings efivars = {
212  .refcnt = NULL,
213  .siblings = LIST_HEAD_INIT ( efivars.siblings ),
214  .children = LIST_HEAD_INIT ( efivars.children ),
215  .op = &efivars_operations,
216  .default_scope = &efivars_scope,
217 };
218 
219 /**
220  * Initialise EFI variable settings
221  *
222  */
223 static void efivars_init ( void ) {
224  int rc;
225 
226  /* Register settings block */
227  if ( ( rc = register_settings ( &efivars, NULL, "efi" ) ) != 0 ) {
228  DBGC ( &efivars, "EFIVARS could not register: %s\n",
229  strerror ( rc ) );
230  return;
231  }
232 }
233 
234 /** EFI variable settings initialiser */
235 struct init_fn efivars_init_fn __init_fn ( INIT_NORMAL ) = {
236  .name = "efivars",
237  .initialise = efivars_init,
238 };
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
static int efivars_fetch(struct settings *settings __unused, struct setting *setting, void *data, size_t len)
Fetch value of EFI variable setting.
Definition: efi_settings.c:133
Error codes.
FILE_SECBOOT(PERMITTED)
static struct settings_operations efivars_operations
EFI variable settings operations.
Definition: efi_settings.c:205
EFI strings.
uint16_t size
Buffer size.
Definition: dwmac.h:14
#define DBGC(...)
Definition: compiler.h:505
#define ENOENT
No such file or directory.
Definition: errno.h:515
unsigned int UINT32
Definition: ProcessorBind.h:99
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned short CHAR16
#define EFI_BUFFER_TOO_SMALL
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:120
static int efivars_find(const CHAR16 *wname, EFI_GUID *guid)
Find first matching EFI variable name.
Definition: efi_settings.c:68
size_t wcslen(const wchar_t *string)
Calculate length of wide-character string.
Definition: wchar.c:57
const char * name
Name.
Definition: settings.h:29
unsigned long tmp
Definition: linux_pci.h:65
#define ENOMEM
Not enough space.
Definition: errno.h:535
#define INIT_NORMAL
Normal initialisation.
Definition: init.h:32
void * memcpy(void *dest, const void *src, size_t len) __nonnull
An initialisation function.
Definition: init.h:15
#define DBGC_HDA(...)
Definition: compiler.h:506
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
static struct settings efivars
EFI variable settings.
Definition: efi_settings.c:46
ring len
Length.
Definition: dwmac.h:231
const char * name
Definition: init.h:16
int efi_snprintf(wchar_t *wbuf, size_t wsize, const char *fmt,...)
Write a formatted string to a buffer.
Definition: efi_strings.c:107
const struct setting_type * type
Setting type.
Definition: settings.h:37
EFI_GET_VARIABLE GetVariable
Definition: UefiSpec.h:1903
Configuration settings.
EFI Runtime Services Table.
Definition: UefiSpec.h:1880
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:55
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
static void efivars_init(void)
Initialise EFI variable settings.
Definition: efi_settings.c:223
size_t strlen(const char *src)
Get length of string.
Definition: string.c:244
Settings block operations.
Definition: settings.h:86
A settings block.
Definition: settings.h:133
UINT64 UINTN
Unsigned value of native width.
A setting scope.
Definition: settings.h:177
const char * efi_guid_ntoa(CONST EFI_GUID *guid)
Convert GUID to a printable string.
Definition: efi_guid.c:726
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:621
struct list_head siblings
Sibling settings blocks.
Definition: settings.h:141
EFI API.
A setting.
Definition: settings.h:24
uint64_t guid
GUID.
Definition: edd.h:31
struct init_fn efivars_init_fn __init_fn(INIT_NORMAL)
EFI variable settings initialiser.
EFI_RUNTIME_SERVICES * RuntimeServices
A pointer to the EFI Runtime Services Table.
Definition: UefiSpec.h:2095
#define EFI_NOT_FOUND
Enumeration of EFI_STATUS.
Definition: UefiBaseType.h:129
#define DBGC2(...)
Definition: compiler.h:522
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:32
EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName
Definition: UefiSpec.h:1904
uint8_t data[48]
Additional event data.
Definition: ena.h:22
static const struct settings_scope efivars_scope
EFI variable settings scope.
Definition: efi_settings.c:43
void * realloc(void *old_ptr, size_t new_size)
Reallocate memory.
Definition: malloc.c:607
int(* applies)(struct settings *settings, const struct setting *setting)
Check applicability of setting.
Definition: settings.h:99
struct list_head children
Child settings blocks.
Definition: settings.h:143
int register_settings(struct settings *settings, struct settings *parent, const char *name)
Register settings block.
Definition: settings.c:476
EFI_SYSTEM_TABLE * efi_systab
static int efivars_applies(struct settings *settings __unused, const struct setting *setting)
Check applicability of EFI variable setting.
Definition: efi_settings.c:55
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:31
const struct settings_scope * scope
Setting scope (or NULL)
Definition: settings.h:50
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.
struct refcnt * refcnt
Reference counter.
Definition: settings.h:135