summaryrefslogtreecommitdiff
path: root/lib/efi_loader
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-04-06 12:16:57 -0600
committerTom Rini <[email protected]>2026-04-06 12:16:57 -0600
commit93f84ee022a8401421cdaab84fe7d106d83fdb4a (patch)
treefb15a4af876e8faf9893fd86c1c0e127265dbe9a /lib/efi_loader
parent88dc2788777babfd6322fa655df549a019aa1e69 (diff)
parente2138cf1e6088f12ffa874e87cc8f4b198378635 (diff)
Merge branch 'next'
Diffstat (limited to 'lib/efi_loader')
-rw-r--r--lib/efi_loader/Kconfig38
-rw-r--r--lib/efi_loader/Makefile3
-rw-r--r--lib/efi_loader/efi_capsule.c8
-rw-r--r--lib/efi_loader/efi_conformance.c2
-rw-r--r--lib/efi_loader/efi_disk.c9
-rw-r--r--lib/efi_loader/efi_gop.c3
-rw-r--r--lib/efi_loader/efi_rng.c3
-rw-r--r--lib/efi_loader/efi_runtime.c24
-rw-r--r--lib/efi_loader/efi_var_common.c44
-rw-r--r--lib/efi_loader/efi_var_file.c65
-rw-r--r--lib/efi_loader/efi_var_mem.c29
-rw-r--r--lib/efi_loader/efi_var_sf.c111
-rw-r--r--lib/efi_loader/efi_variable.c44
13 files changed, 290 insertions, 93 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 13e44be1d06..b5f81e0ff53 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -15,6 +15,8 @@ config EFI_LOADER
# We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB
depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT
depends on !EFI_APP
+ # The EFI specification requires 128 KiB or more of stack space
+ depends on STACK_SIZE >= 0x20000
default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8
select EFI
select CHARSET
@@ -112,7 +114,8 @@ menu "UEFI Variables"
choice
prompt "Store for non-volatile UEFI variables"
- default EFI_VARIABLE_FILE_STORE
+ default EFI_VARIABLE_FILE_STORE if FAT_WRITE
+ default EFI_VARIABLE_NO_STORE
help
Select where non-volatile UEFI variables shall be stored.
@@ -123,6 +126,24 @@ config EFI_VARIABLE_FILE_STORE
Select this option if you want non-volatile UEFI variables to be
stored as file /ubootefi.var on the EFI system partition.
+config EFI_VARIABLE_SF_STORE
+ bool "Store non-volatile UEFI variables in SPI Flash"
+ depends on SPI_FLASH
+ help
+ Select this option if you want non-volatile UEFI variables to be
+ stored in SPI Flash.
+
+ Define CONFIG_EFI_VARIABLE_SF_OFFSET as offset in SPI Flash to use as
+ the storage for variables. CONFIG_EFI_VAR_BUF_SIZE defines the space
+ needed.
+
+ Note that SPI Flash devices have a limited number of program/erase
+ cycles. Frequent updates to UEFI variables may cause excessive wear
+ and can permanently damage the flash device, particularly on SPI NAND
+ or low-end SPI NOR parts without wear leveling. This option should be
+ used with care on such systems, and is not recommended for platforms
+ where UEFI variables are updated frequently.
+
config EFI_MM_COMM_TEE
bool "UEFI variables storage service via the trusted world"
depends on OPTEE
@@ -193,6 +214,21 @@ config FFA_SHARED_MM_BUF_ADDR
the MM SP in secure world.
It is assumed that the MM SP knows the address of the shared MM communication buffer.
+config EFI_VARIABLE_SF_OFFSET
+ hex "EFI variables in SPI flash offset"
+ depends on EFI_VARIABLE_SF_STORE
+ help
+ Offset from the start of the SPI Flash where EFI variables will be stored.
+ This should be aligned to the sector size of SPI Flash.
+
+config EFI_VARIABLE_SF_DEVICE_INDEX
+ int "Device Index for target SPI Flash"
+ depends on EFI_VARIABLE_SF_STORE
+ default 0
+ help
+ The index of SPI Flash device used for storing EFI variables. This would be
+ needed if there are more than 1 SPI Flash devices available to use.
+
config EFI_VARIABLES_PRESEED
bool "Initial values for UEFI variables"
depends on !COMPILE_TEST
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index f490081f654..d73ad43951b 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -53,7 +53,8 @@ ifeq ($(CONFIG_EFI_MM_COMM_TEE),y)
obj-y += efi_variable_tee.o
else
obj-y += efi_variable.o
-obj-y += efi_var_file.o
+obj-$(CONFIG_EFI_VARIABLE_FILE_STORE) += efi_var_file.o
+obj-$(CONFIG_EFI_VARIABLE_SF_STORE) += efi_var_sf.o
obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
endif
obj-y += efi_watchdog.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 89e63ed8dd5..52887f7c274 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -21,7 +21,6 @@
#include <mapmem.h>
#include <sort.h>
#include <sysreset.h>
-#include <asm/global_data.h>
#include <u-boot/uuid.h>
#include <asm/sections.h>
@@ -29,8 +28,6 @@
#include <crypto/pkcs7_parser.h>
#include <linux/err.h>
-DECLARE_GLOBAL_DATA_PTR;
-
const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
static const efi_guid_t efi_guid_firmware_management_capsule_id =
EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
@@ -465,7 +462,7 @@ static __maybe_unused efi_status_t fwu_empty_capsule_process(
log_err("Unable to set the Accept bit for the image %pUs\n",
image_guid);
- status = fwu_state_machine_updates(0, active_idx);
+ status = fwu_state_machine_updates(FWU_BANK_ACCEPTED, active_idx);
if (status < 0)
ret = EFI_DEVICE_ERROR;
@@ -510,7 +507,8 @@ static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os)
log_err("Failed to update FWU metadata index values\n");
} else {
log_debug("Successfully updated the active_index\n");
- status = fwu_state_machine_updates(fw_accept_os ? 1 : 0,
+ status = fwu_state_machine_updates(fw_accept_os ?
+ FWU_BANK_VALID : FWU_BANK_ACCEPTED,
update_index);
if (status < 0)
ret = EFI_DEVICE_ERROR;
diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c
index 2d31800ccb8..470141af483 100644
--- a/lib/efi_loader/efi_conformance.c
+++ b/lib/efi_loader/efi_conformance.c
@@ -12,7 +12,7 @@
#include <efi_api.h>
#include <malloc.h>
-static const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
+const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
/**
* efi_ecpt_register() - Install the ECPT system table.
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 130c4db9606..f8a57539ec6 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -475,9 +475,12 @@ static efi_status_t efi_disk_add_dev(
#if CONFIG_IS_ENABLED(DOS_PARTITION)
case PART_TYPE_DOS:
info->type = PARTITION_TYPE_MBR;
-
- /* TODO: implement support for MBR partition types */
- log_debug("EFI_PARTITION_INFO_PROTOCOL doesn't support MBR\n");
+ ret = part_get_mbr(desc, part, &info->info.mbr);
+ if (ret) {
+ log_debug("get MBR for part %d failed %ld\n",
+ part, ret);
+ goto error;
+ }
break;
#endif
default:
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 3abb47d610e..9403e09691e 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -13,9 +13,6 @@
#include <malloc.h>
#include <mapmem.h>
#include <video.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
static const efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c
index 4734f95eee1..7810b4e47ea 100644
--- a/lib/efi_loader/efi_rng.c
+++ b/lib/efi_loader/efi_rng.c
@@ -10,9 +10,6 @@
#include <efi_rng.h>
#include <log.h>
#include <rng.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID;
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 35eb6a77766..73d4097464c 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -210,6 +210,30 @@ void __efi_runtime efi_memcpy_runtime(void *dest, const void *src, size_t n)
}
/**
+ * efi_memcmp_runtime() - compare memory areas
+ *
+ * At runtime memcmp() is not available.
+ *
+ * @s1: first memory area
+ * @s2: second memory area
+ * @n: number of bytes to compare
+ * Return: 0 if equal, negative if s1 < s2, positive if s1 > s2
+ */
+int __efi_runtime efi_memcmp_runtime(const void *s1, const void *s2, size_t n)
+{
+ const u8 *pos1 = s1;
+ const u8 *pos2 = s2;
+
+ for (; n; --n) {
+ if (*pos1 != *pos2)
+ return *pos1 - *pos2;
+ ++pos1;
+ ++pos2;
+ }
+ return 0;
+}
+
+/**
* efi_update_table_header_crc32() - Update crc32 in table header
*
* @table: EFI table
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index 4b34a58b4cf..d63c2d1b1cd 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -41,6 +41,7 @@ static const struct efi_auth_var_name_type name_type[] = {
static bool efi_secure_boot;
static enum efi_secure_mode efi_secure_mode;
+static const efi_guid_t shim_lock_guid = SHIM_LOCK_GUID;
/**
* efi_efi_get_variable() - retrieve value of a UEFI variable
@@ -488,3 +489,46 @@ efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *
return EFI_SUCCESS;
}
+
+efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
+{
+ struct efi_var_entry *var, *last_var;
+ u16 *data;
+ efi_status_t ret;
+
+ if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
+ buf->length > EFI_VAR_BUF_SIZE ||
+ buf->length < sizeof(struct efi_var_file) ||
+ buf->crc32 != crc32(0, (u8 *)buf->var,
+ buf->length - sizeof(struct efi_var_file))) {
+ log_err("Invalid EFI variables file\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
+ for (var = buf->var; var < last_var;
+ var = (struct efi_var_entry *)ALIGN((uintptr_t)data + var->length, 8)) {
+ data = var->name + u16_strlen(var->name) + 1;
+
+ /*
+ * Secure boot related and volatile variables shall only be
+ * restored from U-Boot's preseed.
+ */
+ if (!safe &&
+ (efi_auth_var_get_type(var->name, &var->guid) !=
+ EFI_AUTH_VAR_NONE ||
+ !guidcmp(&var->guid, &shim_lock_guid) ||
+ !(var->attr & EFI_VARIABLE_NON_VOLATILE)))
+ continue;
+ if (!var->length)
+ continue;
+ if (efi_var_mem_find(&var->guid, var->name, NULL))
+ continue;
+ ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
+ var->length, data, 0, NULL,
+ var->time, NULL);
+ if (ret != EFI_SUCCESS)
+ log_err("Failed to set EFI variable %ls\n", var->name);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
index f23a964a418..9cda38f319e 100644
--- a/lib/efi_loader/efi_var_file.c
+++ b/lib/efi_loader/efi_var_file.c
@@ -14,17 +14,9 @@
#include <mapmem.h>
#include <efi_loader.h>
#include <efi_variable.h>
-#include <u-boot/crc.h>
#define PART_STR_LEN 10
-/* GUID used by Shim to store the MOK database */
-#define SHIM_LOCK_GUID \
- EFI_GUID(0x605dab50, 0xe046, 0x4300, \
- 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
-
-static const efi_guid_t shim_lock_guid = SHIM_LOCK_GUID;
-
/**
* efi_set_blk_dev_to_system_partition() - select EFI system partition
*
@@ -51,15 +43,14 @@ static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void)
}
/**
- * efi_var_to_file() - save non-volatile variables as file
+ * efi_var_to_storage() - save non-volatile variables as file
*
* File ubootefi.var is created on the EFI system partion.
*
* Return: status code
*/
-efi_status_t efi_var_to_file(void)
+efi_status_t efi_var_to_storage(void)
{
-#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
efi_status_t ret;
struct efi_var_file *buf;
loff_t len;
@@ -91,56 +82,10 @@ error:
out:
free(buf);
return ret;
-#else
- return EFI_SUCCESS;
-#endif
-}
-
-efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
-{
- struct efi_var_entry *var, *last_var;
- u16 *data;
- efi_status_t ret;
-
- if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
- buf->crc32 != crc32(0, (u8 *)buf->var,
- buf->length - sizeof(struct efi_var_file))) {
- log_err("Invalid EFI variables file\n");
- return EFI_INVALID_PARAMETER;
- }
-
- last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
- for (var = buf->var; var < last_var;
- var = (struct efi_var_entry *)
- ALIGN((uintptr_t)data + var->length, 8)) {
-
- data = var->name + u16_strlen(var->name) + 1;
-
- /*
- * Secure boot related and volatile variables shall only be
- * restored from U-Boot's preseed.
- */
- if (!safe &&
- (efi_auth_var_get_type(var->name, &var->guid) !=
- EFI_AUTH_VAR_NONE ||
- !guidcmp(&var->guid, &shim_lock_guid) ||
- !(var->attr & EFI_VARIABLE_NON_VOLATILE)))
- continue;
- if (!var->length)
- continue;
- if (efi_var_mem_find(&var->guid, var->name, NULL))
- continue;
- ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
- var->length, data, 0, NULL,
- var->time);
- if (ret != EFI_SUCCESS)
- log_err("Failed to set EFI variable %ls\n", var->name);
- }
- return EFI_SUCCESS;
}
/**
- * efi_var_from_file() - read variables from file
+ * efi_var_from_storage() - read variables from file
*
* File ubootefi.var is read from the EFI system partitions and the variables
* stored in the file are created.
@@ -153,9 +98,8 @@ efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
*
* Return: status code
*/
-efi_status_t efi_var_from_file(void)
+efi_status_t efi_var_from_storage(void)
{
-#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
struct efi_var_file *buf;
loff_t len;
efi_status_t ret;
@@ -180,6 +124,5 @@ efi_status_t efi_var_from_file(void)
log_err("Invalid EFI variables file\n");
error:
free(buf);
-#endif
return EFI_SUCCESS;
}
diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
index 31180df9e3a..8d5f99f4870 100644
--- a/lib/efi_loader/efi_var_mem.c
+++ b/lib/efi_loader/efi_var_mem.c
@@ -159,12 +159,39 @@ efi_status_t __efi_runtime efi_var_mem_ins(
const efi_guid_t *vendor, u32 attributes,
const efi_uintn_t size1, const void *data1,
const efi_uintn_t size2, const void *data2,
- const u64 time)
+ const u64 time, bool *changep)
{
u16 *data;
struct efi_var_entry *var;
u32 var_name_len;
+ if (changep)
+ *changep = true;
+
+ /*
+ * If this is not an append (size2 == 0), check whether the variable
+ * already exists with identical attributes and data. When nothing
+ * changed we can skip the write and avoid superfluous erases.
+ */
+ if (!size2 && changep) {
+ struct efi_var_entry *old;
+
+ old = efi_var_mem_find(vendor, variable_name, NULL);
+ if (old && old->attr == attributes &&
+ old->length == size1 && old->time == time) {
+ u16 *old_data;
+
+ for (old_data = old->name; *old_data; ++old_data)
+ ;
+ ++old_data;
+
+ if (!efi_memcmp_runtime(old_data, data1, size1)) {
+ *changep = false;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
var = (struct efi_var_entry *)
((uintptr_t)efi_var_buf + efi_var_buf->length);
var_name_len = u16_strlen(variable_name) + 1;
diff --git a/lib/efi_loader/efi_var_sf.c b/lib/efi_loader/efi_var_sf.c
new file mode 100644
index 00000000000..6eae8d46464
--- /dev/null
+++ b/lib/efi_loader/efi_var_sf.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SPI Flash interface for UEFI variables
+ *
+ * Copyright (c) 2023, Shantur Rathore
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <spi_flash.h>
+#include <dm.h>
+
+efi_status_t efi_var_to_storage(void)
+{
+ struct efi_var_file *buf;
+ struct spi_flash *flash;
+ struct udevice *sfdev;
+ efi_status_t ret;
+ size_t erase_len;
+ loff_t len;
+ int r;
+
+ ret = efi_var_collect(&buf, &len, EFI_VARIABLE_NON_VOLATILE);
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ if (len > EFI_VAR_BUF_SIZE) {
+ log_debug("EFI var buffer length more than target SPI Flash size\n");
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+
+ log_debug("Got buffer to write buf->len: %d\n", buf->length);
+
+ r = uclass_get_device(UCLASS_SPI_FLASH,
+ CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
+ if (r) {
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ flash = dev_get_uclass_priv(sfdev);
+ if (!flash) {
+ log_debug("Failed to get SPI Flash priv data\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+ erase_len = ALIGN(len, flash->sector_size);
+
+ r = spi_flash_erase_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
+ erase_len);
+ if (r) {
+ log_debug("Failed to erase SPI Flash\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ r = spi_flash_write_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET, len, buf);
+ if (r) {
+ log_debug("Failed to write to SPI Flash: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ }
+
+error:
+ free(buf);
+ return ret;
+}
+
+efi_status_t efi_var_from_storage(void)
+{
+ struct efi_var_file *buf;
+ struct udevice *sfdev;
+ efi_status_t ret;
+ int r;
+
+ buf = calloc(1, EFI_VAR_BUF_SIZE);
+ if (!buf) {
+ log_err("Unable to allocate buffer\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ r = uclass_get_device(UCLASS_SPI_FLASH,
+ CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
+ if (r) {
+ log_err("Failed to get SPI Flash device: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ r = spi_flash_read_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
+ EFI_VAR_BUF_SIZE, buf);
+ if (r) {
+ log_err("Failed to read from SPI Flash: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ if (efi_var_restore(buf, false) != EFI_SUCCESS) {
+ log_err("No valid EFI variables in SPI Flash\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ ret = EFI_SUCCESS;
+error:
+ free(buf);
+ return ret;
+}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index f3533f4def3..9923936c1b5 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -277,6 +277,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
struct efi_var_entry *var;
efi_uintn_t ret;
bool append, delete;
+ bool changed = false;
u64 time = 0;
enum efi_auth_var_type var_type;
@@ -366,6 +367,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
if (delete) {
/* EFI_NOT_FOUND has been handled before */
attributes = var->attr;
+ changed = true;
ret = EFI_SUCCESS;
} else if (append && var) {
/*
@@ -380,15 +382,19 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
ret = efi_var_mem_ins(variable_name, vendor,
attributes & ~EFI_VARIABLE_APPEND_WRITE,
var->length, old_data, data_size, data,
- time);
+ time, &changed);
} else {
ret = efi_var_mem_ins(variable_name, vendor, attributes,
- data_size, data, 0, NULL, time);
+ data_size, data, 0, NULL, time,
+ &changed);
}
if (ret != EFI_SUCCESS)
return ret;
+ if (!changed)
+ return EFI_SUCCESS;
+
efi_var_mem_del(var);
if (var_type == EFI_AUTH_VAR_PK)
@@ -396,12 +402,13 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
else
ret = EFI_SUCCESS;
- /*
- * Write non-volatile EFI variables to file
- * TODO: check if a value change has occured to avoid superfluous writes
- */
- if (attributes & EFI_VARIABLE_NON_VOLATILE)
- efi_var_to_file();
+ /* Write non-volatile EFI variables to storage */
+ if (attributes & EFI_VARIABLE_NON_VOLATILE) {
+ if (IS_ENABLED(CONFIG_EFI_VARIABLE_NO_STORE))
+ return EFI_SUCCESS;
+
+ efi_var_to_storage();
+ }
return EFI_SUCCESS;
}
@@ -494,6 +501,7 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
struct efi_var_entry *var;
efi_uintn_t ret;
bool append, delete;
+ bool changed = false;
u64 time = 0;
if (!IS_ENABLED(CONFIG_EFI_RT_VOLATILE_STORE))
@@ -545,6 +553,7 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
if (delete) {
/* EFI_NOT_FOUND has been handled before */
attributes = var->attr;
+ changed = true;
ret = EFI_SUCCESS;
} else if (append && var) {
u16 *old_data = (void *)((uintptr_t)var->name +
@@ -552,15 +561,19 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
ret = efi_var_mem_ins(variable_name, vendor, attributes,
var->length, old_data, data_size, data,
- time);
+ time, &changed);
} else {
ret = efi_var_mem_ins(variable_name, vendor, attributes,
- data_size, data, 0, NULL, time);
+ data_size, data, 0, NULL, time,
+ &changed);
}
if (ret != EFI_SUCCESS)
return ret;
- /* We are always inserting new variables, get rid of the old copy */
+
+ if (!changed)
+ return EFI_SUCCESS;
+
efi_var_mem_del(var);
return EFI_SUCCESS;
@@ -594,9 +607,12 @@ efi_status_t efi_init_variables(void)
if (ret != EFI_SUCCESS)
return ret;
- ret = efi_var_from_file();
- if (ret != EFI_SUCCESS)
- return ret;
+ if (!IS_ENABLED(CONFIG_EFI_VARIABLE_NO_STORE)) {
+ ret = efi_var_from_storage();
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+
if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
ret = efi_var_restore((struct efi_var_file *)
__efi_var_file_begin, true);