1 // SPDX-License-Identifier: GPL-2.0+
3 * File interface for UEFI variables
5 * Copyright (c) 2020, Heinrich Schuchardt
8 #define LOG_CATEGORY LOGC_EFI
16 #include <efi_loader.h>
17 #include <efi_variable.h>
18 #include <u-boot/crc.h>
20 #define PART_STR_LEN 10
23 * efi_set_blk_dev_to_system_partition() - select EFI system partition
25 * Set the EFI system partition as current block device.
29 static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void)
31 char part_str[PART_STR_LEN];
34 if (!efi_system_partition.if_type) {
35 log_err("No EFI system partition\n");
36 return EFI_DEVICE_ERROR;
38 snprintf(part_str, PART_STR_LEN, "%x:%x",
39 efi_system_partition.devnum, efi_system_partition.part);
40 r = fs_set_blk_dev(blk_get_if_type_name(efi_system_partition.if_type),
41 part_str, FS_TYPE_ANY);
43 log_err("Cannot read EFI system partition\n");
44 return EFI_DEVICE_ERROR;
49 efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp,
52 size_t len = EFI_VAR_BUF_SIZE;
53 struct efi_var_file *buf;
54 struct efi_var_entry *var, *old_var;
55 size_t old_var_name_length = 2;
57 *bufp = NULL; /* Avoid double free() */
60 return EFI_OUT_OF_RESOURCES;
64 efi_uintn_t data_length, var_name_length;
68 if ((uintptr_t)buf + len <=
69 (uintptr_t)var->name + old_var_name_length)
70 return EFI_BUFFER_TOO_SMALL;
72 var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name;
73 memcpy(var->name, old_var->name, old_var_name_length);
74 guidcpy(&var->guid, &old_var->guid);
75 ret = efi_get_next_variable_name_int(
76 &var_name_length, var->name, &var->guid);
77 if (ret == EFI_NOT_FOUND)
79 if (ret != EFI_SUCCESS) {
83 old_var_name_length = var_name_length;
86 data = (u8 *)var->name + old_var_name_length;
87 data_length = (uintptr_t)buf + len - (uintptr_t)data;
88 ret = efi_get_variable_int(var->name, &var->guid,
89 &var->attr, &data_length, data,
91 if (ret != EFI_SUCCESS) {
95 if ((var->attr & check_attr_mask) == check_attr_mask) {
96 var->length = data_length;
97 var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8);
102 buf->magic = EFI_VAR_FILE_MAGIC;
103 len = (uintptr_t)var - (uintptr_t)buf;
104 buf->crc32 = crc32(0, (u8 *)buf->var,
105 len - sizeof(struct efi_var_file));
114 * efi_var_to_file() - save non-volatile variables as file
116 * File ubootefi.var is created on the EFI system partion.
118 * Return: status code
120 efi_status_t efi_var_to_file(void)
122 #ifdef CONFIG_EFI_VARIABLE_FILE_STORE
124 struct efi_var_file *buf;
129 ret = efi_var_collect(&buf, &len, EFI_VARIABLE_NON_VOLATILE);
130 if (ret != EFI_SUCCESS)
133 ret = efi_set_blk_dev_to_system_partition();
134 if (ret != EFI_SUCCESS)
137 r = fs_write(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, len, &actlen);
138 if (r || len != actlen)
139 ret = EFI_DEVICE_ERROR;
142 if (ret != EFI_SUCCESS)
143 log_err("Failed to persist EFI variables\n");
151 efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
153 struct efi_var_entry *var, *last_var;
157 if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
158 buf->crc32 != crc32(0, (u8 *)buf->var,
159 buf->length - sizeof(struct efi_var_file))) {
160 log_err("Invalid EFI variables file\n");
161 return EFI_INVALID_PARAMETER;
164 last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
165 for (var = buf->var; var < last_var;
166 var = (struct efi_var_entry *)
167 ALIGN((uintptr_t)data + var->length, 8)) {
169 data = var->name + u16_strlen(var->name) + 1;
172 * Secure boot related and non-volatile variables shall only be
173 * restored from U-Boot's preseed.
176 (efi_auth_var_get_type(var->name, &var->guid) !=
178 !(var->attr & EFI_VARIABLE_NON_VOLATILE)))
182 ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
183 var->length, data, 0, NULL,
185 if (ret != EFI_SUCCESS)
186 log_err("Failed to set EFI variable %ls\n", var->name);
192 * efi_var_from_file() - read variables from file
194 * File ubootefi.var is read from the EFI system partitions and the variables
195 * stored in the file are created.
197 * In case the file does not exist yet or a variable cannot be set EFI_SUCCESS
200 * Return: status code
202 efi_status_t efi_var_from_file(void)
204 #ifdef CONFIG_EFI_VARIABLE_FILE_STORE
205 struct efi_var_file *buf;
210 buf = calloc(1, EFI_VAR_BUF_SIZE);
212 log_err("Out of memory\n");
213 return EFI_OUT_OF_RESOURCES;
216 ret = efi_set_blk_dev_to_system_partition();
217 if (ret != EFI_SUCCESS)
219 r = fs_read(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, EFI_VAR_BUF_SIZE,
221 if (r || len < sizeof(struct efi_var_file)) {
222 log_err("Failed to load EFI variables\n");
225 if (buf->length != len || efi_var_restore(buf, false) != EFI_SUCCESS)
226 log_err("Invalid EFI variables file\n");