Am 15. Februar 2026 09:48:39 MEZ schrieb Heinrich Schuchardt 
<[email protected]>:
>On 2/11/26 16:56, Michal Simek 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]>
>> Tested-by: Neil Armstrong <[email protected]> # on AML-S905D3-CC
>> Acked-by: Ilias Apalodimas <[email protected]>
>> 
>> ---
>> 
>> Changes in v8:
>> - Add missing EFI_VARIABLE_SF_STORE dependency to 
>> EFI_VARIABLE_SF_DEVICE_INDEX
>> 
>> 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      | 35 +++++++++++++-
>>   lib/efi_loader/Makefile     |  1 +
>>   lib/efi_loader/efi_var_sf.c | 92 +++++++++++++++++++++++++++++++++++++
>>   3 files changed, 127 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 579eed658801..0f6f927ddaf1 100644
>> --- a/lib/efi_loader/Kconfig
>> +++ b/lib/efi_loader/Kconfig
>> @@ -124,6 +124,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
>> @@ -153,7 +171,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
>
>Hello Michal,
>
>If the backend store is SPI flash, we should not publish the variable 
>"RTStorageVolatile" at runtime as currently defined.
>
>For the background see this commit for the efivar library:
>
>https://github.com/rhboot/efivar/commit/68daa04654acbe1bbaa17ebfc23c371b39e69c6b
>
>The first three patches look correct to me and I will add them to a merge 
>request for efi-next.

The 3 prerequisite patches are now in origin/next. Just this one left to be 
reworked.

Best regards

Heinrich


>
>The usage of efi_var_mem_ins() and efi_var_mem_del() when SetVariable() does 
>not change anything is not flash-friendly. Michal, do you want to have a look 
>at this area?
>
>@Ilias, @Vincent:
>We currently lack documentation for the 3 variables.
>Would it make sense to add the definition of the variables to chapter 
>source/chapter5-variable-storage.rst.
>
>Would an efivar helper for SPI flash make sense?
>How should RTStorageVolatile describe a SPI flash location?
>
>Best regards
>
>Heinrich
>
>>      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
>> @@ -194,6 +212,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 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;
>> +}
>

Reply via email to