[PATCH v7 3/3] efi_vars: Implement SPI Flash store
Ilias Apalodimas
ilias.apalodimas at linaro.org
Wed Feb 11 07:39:57 CET 2026
On Tue, 3 Feb 2026 at 13:52, Michal Simek <michal.simek at amd.com> wrote:
>
> From: Shantur Rathore <i at shantur.com>
>
> Currently U-Boot uses ESP as storage for EFI variables.
> Devices with SPI Flash are used for storing environment with this
> commit we allow EFI variables to be stored on SPI Flash.
>
> https://github.com/rhboot/efivar
> is not updated to support this location that's why you can mimic it by
> running:
> dd if=/sys/firmware/efi/efivars/VarToFile-b2ac5fc9-92b7-4acd-aeac-11e818c3130c \
> of=/tmp/vars skip=4 bs=1
> flashcp /tmp/vars /dev/mtdX
>
> where mtdX should match location defined by
> CONFIG_EFI_VARIABLE_SF_OFFSET/CONFIG_EFI_VAR_BUF_SIZE.
>
> Signed-off-by: Shantur Rathore <i at shantur.com>
> Signed-off-by: Michal Simek <michal.simek at amd.com>
> ---
Acked-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
>
> Changes in v7:
> - sed -i 's/efi_var_from/efi_var_from_storage/g'
>
> Changes in v6:
> - sed -i 's/efi_var_read/efi_var_from/g'
> - sed -i 's/efi_var_write/efi_var_to_storage/g'
>
> Changes in v4:
> - Extend Kconfig description
> - Extend commit message and describe efivar missing part
> - use unify methods for reading/writing variable
>
> Changes in v3:
> - Fixed compiler warnings.
>
> Changes in v2:
> - Refactored efi_var_file to move common parts out as requested
> - Changed ifdefs to use CONFIG_IS_DEFINED
> - Fixed typos
>
> lib/efi_loader/Kconfig | 34 +++++++++++++-
> lib/efi_loader/Makefile | 1 +
> lib/efi_loader/efi_var_sf.c | 92 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 126 insertions(+), 1 deletion(-)
> create mode 100644 lib/efi_loader/efi_var_sf.c
>
> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
> index 13e44be1d067..bb40cc899a13 100644
> --- a/lib/efi_loader/Kconfig
> +++ b/lib/efi_loader/Kconfig
> @@ -123,6 +123,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
> @@ -152,7 +170,7 @@ endchoice
>
> config EFI_RT_VOLATILE_STORE
> bool "Allow variable runtime services in volatile storage (e.g RAM)"
> - depends on EFI_VARIABLE_FILE_STORE
> + depends on EFI_VARIABLE_FILE_STORE || EFI_VARIABLE_SF_STORE
> help
> When EFI variables are stored on file we don't allow SetVariableRT,
> since the OS doesn't know how to write that file. At the same time
> @@ -193,6 +211,20 @@ 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"
> + 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 ca1775eb03be..d73ad43951b1 100644
> --- a/lib/efi_loader/Makefile
> +++ b/lib/efi_loader/Makefile
> @@ -54,6 +54,7 @@ obj-y += efi_variable_tee.o
> else
> obj-y += efi_variable.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_var_sf.c b/lib/efi_loader/efi_var_sf.c
> new file mode 100644
> index 000000000000..61d68f7c5c94
> --- /dev/null
> +++ b/lib/efi_loader/efi_var_sf.c
> @@ -0,0 +1,92 @@
> +// 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)
> +{
> + efi_status_t ret;
> + struct efi_var_file *buf;
> + loff_t len;
> + struct udevice *sfdev;
> +
> + ret = efi_var_collect(&buf, &len, EFI_VARIABLE_NON_VOLATILE);
> + if (len > EFI_VAR_BUF_SIZE) {
> + log_err("EFI var buffer length more than target SPI Flash size");
> + ret = EFI_OUT_OF_RESOURCES;
> + goto error;
> + }
> +
> + log_debug("%s - Got buffer to write buf->len : %d\n", __func__, buf->length);
> +
> + if (ret != EFI_SUCCESS)
> + goto error;
> +
> + ret = uclass_get_device(UCLASS_SPI_FLASH, CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
> + if (ret)
> + goto error;
> +
> + ret = spi_flash_erase_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET, EFI_VAR_BUF_SIZE);
> + log_debug("%s - Erased SPI Flash offset %x\n", __func__, CONFIG_EFI_VARIABLE_SF_OFFSET);
> + if (ret)
> + goto error;
> +
> + ret = spi_flash_write_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET, len, buf);
> + log_debug("%s - Wrote buffer to SPI Flash : %ld\n", __func__, ret);
> +
> + if (ret)
> + goto error;
> +
> + ret = EFI_SUCCESS;
> +error:
> + if (ret)
> + log_err("Failed to persist EFI variables in SF\n");
> + free(buf);
> + return ret;
> +}
> +
> +efi_status_t efi_var_from_storage(void)
> +{
> + struct efi_var_file *buf;
> + efi_status_t ret;
> + struct udevice *sfdev;
> +
> + buf = calloc(1, EFI_VAR_BUF_SIZE);
> + if (!buf) {
> + log_err("%s - Unable to allocate buffer\n", __func__);
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + ret = uclass_get_device(UCLASS_SPI_FLASH, 0, &sfdev);
> + if (ret)
> + goto error;
> +
> + ret = spi_flash_read_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
> + EFI_VAR_BUF_SIZE, buf);
> +
> + log_debug("%s - read buffer buf->length: %x\n", __func__, buf->length);
> +
> + if (ret || buf->length < sizeof(struct efi_var_file)) {
> + log_err("%s - buffer read from SPI Flash isn't valid\n", __func__);
> + goto error;
> + }
> +
> + ret = efi_var_restore(buf, false);
> + if (ret != EFI_SUCCESS)
> + log_err("%s - Unable to restore EFI variables from buffer\n", __func__);
> +
> + ret = EFI_SUCCESS;
> +error:
> + free(buf);
> + return ret;
> +}
> --
> 2.43.0
>
More information about the U-Boot
mailing list