blob: e509d6dbf0cfc23338429ad7b99c00dad9df9859 [file] [log] [blame]
Tom Rini70df9d62018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Rob Clark15f3d742017-09-13 18:05:37 -04002/*
Heinrich Schuchardtc69addd2020-03-19 17:15:18 +00003 * UEFI runtime variable services
Rob Clark15f3d742017-09-13 18:05:37 -04004 *
Heinrich Schuchardtc69addd2020-03-19 17:15:18 +00005 * Copyright (c) 2017 Rob Clark
Rob Clark15f3d742017-09-13 18:05:37 -04006 */
7
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +02008#define LOG_CATEGORY LOGC_EFI
9
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +020010#include <common.h>
Rob Clark15f3d742017-09-13 18:05:37 -040011#include <efi_loader.h>
Heinrich Schuchardt9827e842020-06-22 18:10:27 +020012#include <efi_variable.h>
Simon Glassed38aef2020-05-10 11:40:03 -060013#include <env.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060014#include <env_internal.h>
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +020015#include <hexdump.h>
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +020016#include <log.h>
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +020017#include <malloc.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090018#include <rtc.h>
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +010019#include <search.h>
Simon Glass6f044982020-05-10 11:39:52 -060020#include <uuid.h>
AKASHI Takahiro6ec67672020-04-21 09:38:17 +090021#include <crypto/pkcs7_parser.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090022#include <linux/compat.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070023#include <u-boot/crc.h>
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +020024#include <asm/sections.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090025
26#ifdef CONFIG_EFI_SECURE_BOOT
27static u8 pkcs7_hdr[] = {
28 /* SEQUENCE */
29 0x30, 0x82, 0x05, 0xc7,
30 /* OID: pkcs7-signedData */
31 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
32 /* Context Structured? */
33 0xa0, 0x82, 0x05, 0xb8,
34};
35
36/**
37 * efi_variable_parse_signature - parse a signature in variable
38 * @buf: Pointer to variable's value
39 * @buflen: Length of @buf
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010040 *
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090041 * Parse a signature embedded in variable's value and instantiate
42 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
43 * pkcs7's signedData, some header needed be prepended for correctly
44 * parsing authentication data, particularly for variable's.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010045 *
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090046 * Return: Pointer to pkcs7_message structure on success, NULL on error
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010047 */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090048static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
49 size_t buflen)
50{
51 u8 *ebuf;
52 size_t ebuflen, len;
53 struct pkcs7_message *msg;
54
55 /*
56 * This is the best assumption to check if the binary is
57 * already in a form of pkcs7's signedData.
58 */
59 if (buflen > sizeof(pkcs7_hdr) &&
60 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
61 msg = pkcs7_parse_message(buf, buflen);
62 goto out;
63 }
64
65 /*
66 * Otherwise, we should add a dummy prefix sequence for pkcs7
67 * message parser to be able to process.
68 * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
69 * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
70 * TODO:
71 * The header should be composed in a more refined manner.
72 */
AKASHI Takahiro37123732020-06-09 14:09:34 +090073 EFI_PRINT("Makeshift prefix added to authentication data\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090074 ebuflen = sizeof(pkcs7_hdr) + buflen;
75 if (ebuflen <= 0x7f) {
AKASHI Takahiro37123732020-06-09 14:09:34 +090076 EFI_PRINT("Data is too short\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090077 return NULL;
78 }
79
80 ebuf = malloc(ebuflen);
81 if (!ebuf) {
AKASHI Takahiro37123732020-06-09 14:09:34 +090082 EFI_PRINT("Out of memory\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090083 return NULL;
84 }
85
86 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
87 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
88 len = ebuflen - 4;
89 ebuf[2] = (len >> 8) & 0xff;
90 ebuf[3] = len & 0xff;
91 len = ebuflen - 0x13;
92 ebuf[0x11] = (len >> 8) & 0xff;
93 ebuf[0x12] = len & 0xff;
94
95 msg = pkcs7_parse_message(ebuf, ebuflen);
96
97 free(ebuf);
98
99out:
100 if (IS_ERR(msg))
101 return NULL;
102
103 return msg;
104}
105
106/**
107 * efi_variable_authenticate - authenticate a variable
108 * @variable: Variable name in u16
109 * @vendor: Guid of variable
110 * @data_size: Size of @data
111 * @data: Pointer to variable's value
112 * @given_attr: Attributes to be given at SetVariable()
113 * @env_attr: Attributes that an existing variable holds
114 * @time: signed time that an existing variable holds
115 *
116 * Called by efi_set_variable() to verify that the input is correct.
117 * Will replace the given data pointer with another that points to
118 * the actual data to store in the internal memory.
119 * On success, @data and @data_size will be replaced with variable's
120 * actual data, excluding authentication data, and its size, and variable's
121 * attributes and signed time will also be returned in @env_attr and @time,
122 * respectively.
123 *
Heinrich Schuchardte2c43da2020-05-03 16:29:00 +0200124 * Return: status code
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900125 */
126static efi_status_t efi_variable_authenticate(u16 *variable,
127 const efi_guid_t *vendor,
128 efi_uintn_t *data_size,
129 const void **data, u32 given_attr,
130 u32 *env_attr, u64 *time)
131{
132 const struct efi_variable_authentication_2 *auth;
133 struct efi_signature_store *truststore, *truststore2;
134 struct pkcs7_message *var_sig;
135 struct efi_image_regions *regs;
136 struct efi_time timestamp;
137 struct rtc_time tm;
138 u64 new_time;
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200139 enum efi_auth_var_type var_type;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900140 efi_status_t ret;
141
142 var_sig = NULL;
143 truststore = NULL;
144 truststore2 = NULL;
145 regs = NULL;
146 ret = EFI_SECURITY_VIOLATION;
147
148 if (*data_size < sizeof(struct efi_variable_authentication_2))
149 goto err;
150
151 /* authentication data */
152 auth = *data;
153 if (*data_size < (sizeof(auth->time_stamp)
154 + auth->auth_info.hdr.dwLength))
155 goto err;
156
157 if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
158 goto err;
159
Heinrich Schuchardt7a76a3f2020-07-01 12:44:00 +0200160 memcpy(&timestamp, &auth->time_stamp, sizeof(timestamp));
161 if (timestamp.pad1 || timestamp.nanosecond || timestamp.timezone ||
162 timestamp.daylight || timestamp.pad2)
163 goto err;
164
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900165 *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;
166 *data_size -= (sizeof(auth->time_stamp)
167 + auth->auth_info.hdr.dwLength);
168
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900169 memset(&tm, 0, sizeof(tm));
170 tm.tm_year = timestamp.year;
171 tm.tm_mon = timestamp.month;
172 tm.tm_mday = timestamp.day;
173 tm.tm_hour = timestamp.hour;
174 tm.tm_min = timestamp.minute;
175 tm.tm_sec = timestamp.second;
176 new_time = rtc_mktime(&tm);
177
178 if (!efi_secure_boot_enabled()) {
179 /* finished checking */
180 *time = new_time;
181 return EFI_SUCCESS;
182 }
183
184 if (new_time <= *time)
185 goto err;
186
187 /* data to be digested */
188 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 5, 1);
189 if (!regs)
190 goto err;
191 regs->max = 5;
192 efi_image_region_add(regs, (uint8_t *)variable,
193 (uint8_t *)variable
194 + u16_strlen(variable) * sizeof(u16), 1);
195 efi_image_region_add(regs, (uint8_t *)vendor,
196 (uint8_t *)vendor + sizeof(*vendor), 1);
197 efi_image_region_add(regs, (uint8_t *)&given_attr,
198 (uint8_t *)&given_attr + sizeof(given_attr), 1);
199 efi_image_region_add(regs, (uint8_t *)&timestamp,
200 (uint8_t *)&timestamp + sizeof(timestamp), 1);
201 efi_image_region_add(regs, (uint8_t *)*data,
202 (uint8_t *)*data + *data_size, 1);
203
204 /* variable's signature list */
205 if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
206 goto err;
207 var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
208 auth->auth_info.hdr.dwLength
209 - sizeof(auth->auth_info));
Patrick Wildtcd8a55b2020-05-07 02:13:18 +0200210 if (!var_sig) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900211 EFI_PRINT("Parsing variable's signature failed\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900212 goto err;
213 }
214
215 /* signature database used for authentication */
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200216 var_type = efi_auth_var_get_type(variable, vendor);
217 switch (var_type) {
218 case EFI_AUTH_VAR_PK:
219 case EFI_AUTH_VAR_KEK:
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900220 /* with PK */
221 truststore = efi_sigstore_parse_sigdb(L"PK");
222 if (!truststore)
223 goto err;
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200224 break;
225 case EFI_AUTH_VAR_DB:
226 case EFI_AUTH_VAR_DBX:
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900227 /* with PK and KEK */
228 truststore = efi_sigstore_parse_sigdb(L"KEK");
229 truststore2 = efi_sigstore_parse_sigdb(L"PK");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900230 if (!truststore) {
231 if (!truststore2)
232 goto err;
233
234 truststore = truststore2;
235 truststore2 = NULL;
236 }
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200237 break;
238 default:
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900239 /* TODO: support private authenticated variables */
240 goto err;
241 }
242
243 /* verify signature */
244 if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900245 EFI_PRINT("Verified\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900246 } else {
247 if (truststore2 &&
248 efi_signature_verify_with_sigdb(regs, var_sig,
249 truststore2, NULL)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900250 EFI_PRINT("Verified\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900251 } else {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900252 EFI_PRINT("Verifying variable's signature failed\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900253 goto err;
254 }
255 }
256
257 /* finished checking */
Heinrich Schuchardt5106dc72020-06-30 12:02:14 +0200258 *time = new_time;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900259 ret = EFI_SUCCESS;
260
261err:
262 efi_sigstore_free(truststore);
263 efi_sigstore_free(truststore2);
264 pkcs7_free_message(var_sig);
265 free(regs);
266
267 return ret;
268}
269#else
270static efi_status_t efi_variable_authenticate(u16 *variable,
271 const efi_guid_t *vendor,
272 efi_uintn_t *data_size,
273 const void **data, u32 given_attr,
274 u32 *env_attr, u64 *time)
275{
276 return EFI_SUCCESS;
277}
278#endif /* CONFIG_EFI_SECURE_BOOT */
279
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200280efi_status_t __efi_runtime
281efi_get_variable_int(u16 *variable_name, const efi_guid_t *vendor,
282 u32 *attributes, efi_uintn_t *data_size, void *data,
283 u64 *timep)
Rob Clark15f3d742017-09-13 18:05:37 -0400284{
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300285 return efi_get_variable_mem(variable_name, vendor, attributes, data_size, data, timep);
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100286}
287
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200288efi_status_t __efi_runtime
289efi_get_next_variable_name_int(efi_uintn_t *variable_name_size,
290 u16 *variable_name, efi_guid_t *vendor)
Rob Clark15f3d742017-09-13 18:05:37 -0400291{
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300292 return efi_get_next_variable_name_mem(variable_name_size, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400293}
294
Heinrich Schuchardt9827e842020-06-22 18:10:27 +0200295efi_status_t efi_set_variable_int(u16 *variable_name, const efi_guid_t *vendor,
296 u32 attributes, efi_uintn_t data_size,
297 const void *data, bool ro_check)
Rob Clark15f3d742017-09-13 18:05:37 -0400298{
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200299 struct efi_var_entry *var;
300 efi_uintn_t ret;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900301 bool append, delete;
302 u64 time = 0;
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200303 enum efi_auth_var_type var_type;
Rob Clark15f3d742017-09-13 18:05:37 -0400304
Heinrich Schuchardtadba3962019-06-12 23:28:42 +0200305 if (!variable_name || !*variable_name || !vendor ||
306 ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200307 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)))
308 return EFI_INVALID_PARAMETER;
Rob Clark15f3d742017-09-13 18:05:37 -0400309
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900310 /* check if a variable exists */
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200311 var = efi_var_mem_find(vendor, variable_name, NULL);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900312 append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
313 attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE;
314 delete = !append && (!data_size || !attributes);
315
316 /* check attributes */
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +0200317 var_type = efi_auth_var_get_type(variable_name, vendor);
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200318 if (var) {
319 if (ro_check && (var->attr & EFI_VARIABLE_READ_ONLY))
320 return EFI_WRITE_PROTECTED;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900321
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +0200322 if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
323 if (var_type != EFI_AUTH_VAR_NONE)
324 return EFI_WRITE_PROTECTED;
325 }
326
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900327 /* attributes won't be changed */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900328 if (!delete &&
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200329 ((ro_check && var->attr != attributes) ||
330 (!ro_check && ((var->attr & ~(u32)EFI_VARIABLE_READ_ONLY)
Heinrich Schuchardt9827e842020-06-22 18:10:27 +0200331 != (attributes & ~(u32)EFI_VARIABLE_READ_ONLY))))) {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200332 return EFI_INVALID_PARAMETER;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900333 }
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200334 time = var->time;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900335 } else {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200336 if (delete || append)
Heinrich Schuchardt8021bbe2019-09-26 21:40:18 +0200337 /*
338 * Trying to delete or to update a non-existent
339 * variable.
340 */
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200341 return EFI_NOT_FOUND;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900342 }
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900343
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200344 if (var_type != EFI_AUTH_VAR_NONE) {
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900345 /* authentication is mandatory */
346 if (!(attributes &
347 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200348 EFI_PRINT("%ls: TIME_BASED_AUTHENTICATED_WRITE_ACCESS required\n",
AKASHI Takahiro37123732020-06-09 14:09:34 +0900349 variable_name);
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200350 return EFI_INVALID_PARAMETER;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900351 }
352 }
353
354 /* authenticate a variable */
355 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200356 if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS)
357 return EFI_INVALID_PARAMETER;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900358 if (attributes &
359 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200360 u32 env_attr;
361
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900362 ret = efi_variable_authenticate(variable_name, vendor,
363 &data_size, &data,
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200364 attributes, &env_attr,
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900365 &time);
366 if (ret != EFI_SUCCESS)
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200367 return ret;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900368
369 /* last chance to check for delete */
370 if (!data_size)
371 delete = true;
372 }
373 } else {
374 if (attributes &
375 (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
376 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900377 EFI_PRINT("Secure boot is not configured\n");
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200378 return EFI_INVALID_PARAMETER;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900379 }
380 }
381
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900382 if (delete) {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200383 /* EFI_NOT_FOUND has been handled before */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900384 ret = EFI_SUCCESS;
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200385 } else if (append) {
386 u16 *old_data = var->name;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900387
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200388 for (; *old_data; ++old_data)
389 ;
390 ++old_data;
391 ret = efi_var_mem_ins(variable_name, vendor, attributes,
392 var->length, old_data, data_size, data,
393 time);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900394 } else {
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200395 ret = efi_var_mem_ins(variable_name, vendor, attributes,
396 data_size, data, 0, NULL, time);
Rob Clark15f3d742017-09-13 18:05:37 -0400397 }
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200398 efi_var_mem_del(var);
Rob Clark15f3d742017-09-13 18:05:37 -0400399
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200400 if (ret != EFI_SUCCESS)
401 return ret;
Rob Clark15f3d742017-09-13 18:05:37 -0400402
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200403 if (var_type == EFI_AUTH_VAR_PK)
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200404 ret = efi_init_secure_state();
405 else
406 ret = EFI_SUCCESS;
Rob Clark15f3d742017-09-13 18:05:37 -0400407
Heinrich Schuchardt09a8d502020-03-19 18:21:58 +0000408 /* Write non-volatile EFI variables to file */
409 if (attributes & EFI_VARIABLE_NON_VOLATILE &&
410 ret == EFI_SUCCESS && efi_obj_list_initialized == EFI_SUCCESS)
411 efi_var_to_file();
412
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200413 return EFI_SUCCESS;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900414}
415
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200416efi_status_t efi_query_variable_info_int(u32 attributes,
417 u64 *maximum_variable_storage_size,
418 u64 *remaining_variable_storage_size,
419 u64 *maximum_variable_size)
420{
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200421 *maximum_variable_storage_size = EFI_VAR_BUF_SIZE -
422 sizeof(struct efi_var_file);
423 *remaining_variable_storage_size = efi_var_mem_free();
424 *maximum_variable_size = EFI_VAR_BUF_SIZE -
425 sizeof(struct efi_var_file) -
426 sizeof(struct efi_var_entry);
427 return EFI_SUCCESS;
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200428}
429
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900430/**
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200431 * efi_query_variable_info_runtime() - runtime implementation of
432 * QueryVariableInfo()
Heinrich Schuchardt9b19dae2019-06-20 12:13:05 +0200433 *
434 * @attributes: bitmask to select variables to be
435 * queried
436 * @maximum_variable_storage_size: maximum size of storage area for the
437 * selected variable types
438 * @remaining_variable_storage_size: remaining size of storage are for the
439 * selected variable types
440 * @maximum_variable_size: maximum size of a variable of the
441 * selected type
442 * Returns: status code
443 */
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200444efi_status_t __efi_runtime EFIAPI efi_query_variable_info_runtime(
Heinrich Schuchardt9b19dae2019-06-20 12:13:05 +0200445 u32 attributes,
446 u64 *maximum_variable_storage_size,
447 u64 *remaining_variable_storage_size,
448 u64 *maximum_variable_size)
449{
450 return EFI_UNSUPPORTED;
451}
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +0200452
453/**
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200454 * efi_set_variable_runtime() - runtime implementation of SetVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200455 *
456 * @variable_name: name of the variable
457 * @vendor: vendor GUID
458 * @attributes: attributes of the variable
459 * @data_size: size of the buffer with the variable value
460 * @data: buffer with the variable value
461 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200462 */
463static efi_status_t __efi_runtime EFIAPI
464efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
465 u32 attributes, efi_uintn_t data_size,
466 const void *data)
467{
468 return EFI_UNSUPPORTED;
469}
470
471/**
472 * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
473 */
474void efi_variables_boot_exit_notify(void)
475{
Heinrich Schuchardt09a8d502020-03-19 18:21:58 +0000476 /* Switch variable services functions to runtime version */
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200477 efi_runtime_services.get_variable = efi_get_variable_runtime;
478 efi_runtime_services.get_next_variable_name =
479 efi_get_next_variable_name_runtime;
480 efi_runtime_services.set_variable = efi_set_variable_runtime;
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200481 efi_runtime_services.query_variable_info =
482 efi_query_variable_info_runtime;
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +0200483 efi_update_table_header_crc32(&efi_runtime_services.hdr);
484}
485
486/**
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +0200487 * efi_init_variables() - initialize variable services
488 *
489 * Return: status code
490 */
491efi_status_t efi_init_variables(void)
492{
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900493 efi_status_t ret;
494
Heinrich Schuchardt047276c2020-07-04 18:34:15 +0200495 ret = efi_var_mem_init();
496 if (ret != EFI_SUCCESS)
497 return ret;
498
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900499 ret = efi_init_secure_state();
Heinrich Schuchardt09a8d502020-03-19 18:21:58 +0000500 if (ret != EFI_SUCCESS)
501 return ret;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900502
Heinrich Schuchardt4b7d5c12020-07-14 21:25:28 +0200503 if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
504 ret = efi_var_restore((struct efi_var_file *)
505 __efi_var_file_begin);
506 if (ret != EFI_SUCCESS)
507 log_err("Invalid EFI variable seed\n");
508 }
509
Heinrich Schuchardt09a8d502020-03-19 18:21:58 +0000510 return efi_var_from_file();
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +0200511}