On Tue, 3 Feb 2026 at 13:52, Michal Simek <[email protected]> wrote:
>
> From: Shantur Rathore <[email protected]>
>
> 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 <[email protected]>
> Signed-off-by: Michal Simek <[email protected]>
> ---

Acked-by: Ilias Apalodimas <[email protected]>

>
> 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
>

Reply via email to