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