I am trying to compile this and test it against the working non -FFA
case, However, I am getting a compilation error with the defconfig
below (which is basically the qemu defconfig + COONFIG_OPTEE and
CONFIG_EFI_MM_COMM_TEE)

 CONFIG_ARM=y
CONFIG_KVM_VIRT_INS=y
CONFIG_ARCH_QEMU=y
CONFIG_SYS_MALLOC_LEN=0x1000000
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x40200000
CONFIG_ENV_SIZE=0x40000
CONFIG_ENV_SECT_SIZE=0x40000
CONFIG_DEFAULT_DEVICE_TREE="qemu-arm64"
CONFIG_OF_LIBFDT_OVERLAY=y
CONFIG_SYS_LOAD_ADDR=0x40200000
CONFIG_DEBUG_UART_BASE=0x9000000
CONFIG_DEBUG_UART_CLOCK=0
CONFIG_ARMV8_CRYPTO=y
CONFIG_ENV_ADDR=0x4000000
CONFIG_PCI=y
CONFIG_DEBUG_UART=y
CONFIG_RELOC_ADDR_TOP=y
CONFIG_EFI_MM_COMM_TEE=y
CONFIG_EFI_HTTP_BOOT=y
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_FIT_VERBOSE=y
CONFIG_FIT_BEST_MATCH=y
CONFIG_BOOTSTD_FULL=y
CONFIG_LEGACY_IMAGE_FORMAT=y
CONFIG_USE_PREBOOT=y
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
# CONFIG_BOARD_INIT is not set
CONFIG_PCI_INIT_R=y
CONFIG_BLOBLIST=y
CONFIG_CMD_SMBIOS=y
CONFIG_CMD_BOOTZ=y
CONFIG_CMD_BOOTEFI_SELFTEST=y
CONFIG_CMD_NVEDIT_EFI=y
CONFIG_CMD_DFU=y
CONFIG_CMD_MTD=y
CONFIG_CMD_PCI=y
CONFIG_CMD_NFS=y
CONFIG_CMD_SNTP=y
CONFIG_CMD_TFTPSRV=y
CONFIG_WGET_HTTPS=y
CONFIG_WGET_CACERT=y
CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_TPM=y
CONFIG_CMD_MTDPARTS=y
CONFIG_CMD_SPAWN=y
CONFIG_ENV_IS_IN_FLASH=y
CONFIG_NET_LWIP=y
CONFIG_AHCI=y
CONFIG_SCSI_AHCI=y
CONFIG_AHCI_PCI=y
CONFIG_DFU_MTD=y
CONFIG_DFU_RAM=y
# CONFIG_MMC is not set
CONFIG_MTD=y
CONFIG_DM_MTD=y
CONFIG_MTD_NOR_FLASH=y
CONFIG_FLASH_SHOW_PROGRESS=0
CONFIG_CFI_FLASH=y
CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS=y
CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y
CONFIG_FLASH_CFI_MTD=y
CONFIG_SYS_FLASH_CFI=y
CONFIG_SYS_MAX_FLASH_SECT=256
CONFIG_SYS_MAX_FLASH_BANKS=2
CONFIG_SYS_MAX_FLASH_BANKS_DETECT=y
CONFIG_E1000=y
CONFIG_NVME_PCI=y
CONFIG_PCIE_ECAM_GENERIC=y
CONFIG_SCSI=y
CONFIG_DEBUG_UART_PL011=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYSINFO=y
CONFIG_SYSINFO_SMBIOS=y
CONFIG_SYSRESET=y
CONFIG_SYSRESET_CMD_POWEROFF=y
CONFIG_SYSRESET_PSCI=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_TPM2_MMIO=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_PCI=y
CONFIG_MBEDTLS_LIB=y
CONFIG_TPM=y
CONFIG_TPM_PCR_ALLOCATE=y
CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE=y
CONFIG_UTHREAD=y
CONFIG_UNIT_TEST=y

lib/efi_loader/efi_variable_tee.c: In function ‘get_comm_buf’:
lib/efi_loader/efi_variable_tee.c:562:45: error:
‘CONFIG_FFA_SHARED_MM_BUF_SIZE’ undeclared (first use in this
function); did you mean ‘CONFIG_EFI_VAR_BUF_SIZE’?
  562 |                         if (comm_buf_size >
CONFIG_FFA_SHARED_MM_BUF_SIZE)
      |
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                             CONFIG_EFI_VAR_BUF_SIZE
lib/efi_loader/efi_variable_tee.c:562:45: note: each undeclared
identifier is reported only once for each function it appears in
In file included from include/stdio.h:5,
                 from include/log.h:12,
                 from include/linux/printk.h:4,
                 from include/linux/kernel.h:5,
                 from include/linux/libfdt_env.h:13,
                 from include/linux/libfdt.h:6,
                 from include/fdtdec.h:17,
                 from include/dm/ofnode.h:11,
                 from include/dm/device.h:13,
                 from include/dm.h:13,
                 from lib/efi_loader/efi_variable_tee.c:20:
lib/efi_loader/efi_variable_tee.c: In function ‘efi_init_variables’:
lib/efi_loader/efi_variable_tee.c:1488:30: error:
‘CONFIG_FFA_SHARED_MM_BUF_ADDR’ undeclared (first use in this
function)
 1488 |                 BUILD_BUG_ON(CONFIG_FFA_SHARED_MM_BUF_ADDR &
EFI_PAGE_MASK);
      |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler.h:326:23: note: in definition of macro
‘__compiletime_assert’
  326 |                 if (!(condition))
         \
      |                       ^~~~~~~~~
include/linux/compiler.h:346:9: note: in expansion of macro
‘_compiletime_assert’
  346 |         _compiletime_assert(condition, msg,
__compiletime_assert_, __COUNTER__)
      |         ^~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:38:37: note: in expansion of macro
‘compiletime_assert’
   38 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:49:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   49 |         BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
      |         ^~~~~~~~~~~~~~~~
lib/efi_loader/efi_variable_tee.c:1488:17: note: in expansion of macro
‘BUILD_BUG_ON’
 1488 |                 BUILD_BUG_ON(CONFIG_FFA_SHARED_MM_BUF_ADDR &
EFI_PAGE_MASK);
      |                 ^~~~~~~~~~~~
lib/efi_loader/efi_variable_tee.c:1497:42: error:
‘CONFIG_FFA_SHARED_MM_BUF_SIZE’ undeclared (first use in this
function); did you mean ‘CONFIG_EFI_VAR_BUF_SIZE’?
 1497 |                                          CONFIG_FFA_SHARED_MM_BUF_SIZE,
      |                                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      |                                          CONFIG_EFI_VAR_BUF_SIZE
make[2]: *** [scripts/Makefile.build:272:
lib/efi_loader/efi_variable_tee.o] Error 1

Can you reproduce this?

Thanks
/Ilias

On Wed, 29 Jul 2026 at 11:52, Harsimran Singh Tungal
<[email protected]> wrote:
>
> Add the TEE-backed runtime SetVariable() implementation for the FF-A/MM
> variable backend. The runtime path uses EFI runtime-safe memory helpers
> and the shared MM communication path so SetVariable() can reach the MM
> secure partition after ExitBootServices().
>
> Add runtime-safe variable-property helpers for the SetVariable() path
> and use the original data_size argument when restoring the read-only
> property maxsize, instead of relying on the MM response buffer.
>
> Reviewed-by: Simon Glass <[email protected]>
> Signed-off-by: Harsimran Singh Tungal <[email protected]>
> ---
>  lib/efi_loader/efi_variable_tee.c | 147 ++++++++++++++++++++++++++++--
>  1 file changed, 140 insertions(+), 7 deletions(-)
>
> diff --git a/lib/efi_loader/efi_variable_tee.c 
> b/lib/efi_loader/efi_variable_tee.c
> index 5c7104662e9..d04b8dc1376 100644
> --- a/lib/efi_loader/efi_variable_tee.c
> +++ b/lib/efi_loader/efi_variable_tee.c
> @@ -717,6 +717,38 @@ out:
>         return ret;
>  }
>
> +static efi_status_t __efi_runtime set_property_int_runtime(const u16 
> *variable_name,
> +                                                          efi_uintn_t 
> name_size,
> +                                                          const efi_guid_t 
> *vendor,
> +                                                          struct 
> var_check_property *var_property)
> +{
> +       struct smm_variable_var_check_property *smm_property;
> +       efi_uintn_t payload_size;
> +       u8 *comm_buf = NULL;
> +       efi_status_t ret;
> +
> +       payload_size = sizeof(*smm_property) + name_size;
> +       if (payload_size > max_payload_size) {
> +               ret = EFI_INVALID_PARAMETER;
> +               return ret;
> +       }
> +       comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
> +                               
> SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_SET,
> +                               &ret);
> +       if (!comm_buf)
> +               return ret;
> +
> +       efi_memcpy_runtime(&smm_property->guid, vendor, sizeof(*vendor));
> +       smm_property->name_size = name_size;
> +       efi_memcpy_runtime(&smm_property->property, var_property,
> +                          sizeof(smm_property->property));
> +       efi_memcpy_runtime(smm_property->name, variable_name, name_size);
> +
> +       ret = mm_communicate(comm_buf, payload_size);
> +
> +       return ret;
> +}
> +
>  static efi_status_t get_property_int(const u16 *variable_name,
>                                      efi_uintn_t name_size,
>                                      const efi_guid_t *vendor,
> @@ -762,6 +794,49 @@ out:
>         return ret;
>  }
>
> +static efi_status_t __efi_runtime get_property_int_runtime(const u16 
> *variable_name,
> +                                                          efi_uintn_t 
> name_size,
> +                                                          const efi_guid_t 
> *vendor,
> +                                                          struct 
> var_check_property *var_property)
> +{
> +       struct smm_variable_var_check_property *smm_property;
> +       efi_uintn_t payload_size;
> +       u8 *comm_buf = NULL;
> +       efi_status_t ret;
> +
> +       efi_memset_runtime(var_property, 0, sizeof(*var_property));
> +       payload_size = sizeof(*smm_property) + name_size;
> +       if (payload_size > max_payload_size) {
> +               ret = EFI_INVALID_PARAMETER;
> +               return ret;
> +       }
> +       comm_buf = setup_mm_hdr((void **)&smm_property, payload_size,
> +                               
> SMM_VARIABLE_FUNCTION_VAR_CHECK_VARIABLE_PROPERTY_GET,
> +                               &ret);
> +       if (!comm_buf)
> +               return ret;
> +
> +       efi_memcpy_runtime(&smm_property->guid, vendor, 
> sizeof(smm_property->guid));
> +       smm_property->name_size = name_size;
> +       efi_memcpy_runtime(smm_property->name, variable_name, name_size);
> +
> +       ret = mm_communicate(comm_buf, payload_size);
> +       /*
> +        * Currently only R/O property is supported in StMM.
> +        * Variables that are not set to R/O will not set the property in StMM
> +        * and the call will return EFI_NOT_FOUND. We are setting the
> +        * properties to 0x0 so checking against that is enough for the
> +        * EFI_NOT_FOUND case.
> +        */
> +       if (ret == EFI_NOT_FOUND)
> +               return EFI_SUCCESS;
> +       if (ret != EFI_SUCCESS)
> +               return ret;
> +       efi_memcpy_runtime(var_property, &smm_property->property, 
> sizeof(*var_property));
> +
> +       return EFI_SUCCESS;
> +}
> +
>  efi_status_t efi_get_variable_int(const u16 *variable_name,
>                                   const efi_guid_t *vendor,
>                                   u32 *attributes, efi_uintn_t *data_size,
> @@ -995,7 +1070,7 @@ efi_status_t efi_set_variable_int(const u16 
> *variable_name,
>                 var_property.property |= 
> VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
>                 var_property.attributes = attributes;
>                 var_property.minsize = 1;
> -               var_property.maxsize = var_acc->data_size;
> +               var_property.maxsize = data_size;
>                 ret = set_property_int(variable_name, name_size, vendor, 
> &var_property);
>         }
>
> @@ -1072,7 +1147,7 @@ efi_query_variable_info_runtime(u32 attributes, u64 
> *max_variable_storage_size,
>  }
>
>  /**
> - * efi_set_variable_runtime() - runtime implementation of SetVariable()
> + * efi_set_variable_int_runtime() - runtime implementation of SetVariable()
>   *
>   * @variable_name:     name of the variable
>   * @guid:              vendor GUID
> @@ -1082,11 +1157,69 @@ efi_query_variable_info_runtime(u32 attributes, u64 
> *max_variable_storage_size,
>   * Return:             status code
>   */
>  static efi_status_t __efi_runtime EFIAPI
> -efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
> -                        u32 attributes, efi_uintn_t data_size,
> -                        const void *data)
> +efi_set_variable_int_runtime(u16 *variable_name, const efi_guid_t *guid,
> +                            u32 attributes, efi_uintn_t data_size,
> +                            const void *data)
>  {
> -       return EFI_UNSUPPORTED;
> +       efi_status_t ret, mm_communicate_ret = EFI_SUCCESS;
> +       struct var_check_property var_property;
> +       struct smm_variable_access *var_acc;
> +       efi_uintn_t payload_size;
> +       efi_uintn_t name_size;
> +       u8 *comm_buf = NULL;
> +       bool ro;
> +
> +       if (!variable_name || variable_name[0] == 0 || !guid)
> +               return EFI_INVALID_PARAMETER;
> +
> +       if (data_size > 0 && !data)
> +               return EFI_INVALID_PARAMETER;
> +
> +       /* Check payload size */
> +       name_size = u16_strsize(variable_name);
> +       payload_size = MM_VARIABLE_ACCESS_HEADER_SIZE + name_size + data_size;
> +       if (payload_size > max_payload_size)
> +               return EFI_INVALID_PARAMETER;
> +
> +       ro = !!(attributes & EFI_VARIABLE_READ_ONLY);
> +       attributes &= EFI_VARIABLE_MASK;
> +
> +       ret = get_property_int_runtime(variable_name, name_size, guid,
> +                                      &var_property);
> +       if (ret != EFI_SUCCESS)
> +               return ret;
> +
> +       if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
> +               return EFI_WRITE_PROTECTED;
> +
> +       comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
> +                               SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
> +       if (!comm_buf)
> +               return ret;
> +
> +       /* Fill in contents */
> +       efi_memcpy_runtime(&var_acc->guid, guid, sizeof(*guid));
> +       var_acc->data_size = data_size;
> +       var_acc->name_size = name_size;
> +       var_acc->attr = attributes;
> +       efi_memcpy_runtime(var_acc->name, variable_name, name_size);
> +       efi_memcpy_runtime((u8 *)var_acc->name + name_size, data, data_size);
> +
> +       /* Communicate */
> +       ret = mm_communicate(comm_buf, payload_size);
> +       if (ret != EFI_SUCCESS)
> +               mm_communicate_ret = ret;
> +
> +       if (ro && !(var_property.property & 
> VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)) {
> +               var_property.revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
> +               var_property.property |= 
> VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
> +               var_property.attributes = attributes;
> +               var_property.minsize = 1;
> +               var_property.maxsize = data_size;
> +               ret = set_property_int_runtime(variable_name, name_size, 
> guid, &var_property);
> +       }
> +
> +       return (mm_communicate_ret == EFI_SUCCESS) ? ret : mm_communicate_ret;
>  }
>
>  /**
> @@ -1123,7 +1256,7 @@ void efi_variables_boot_exit_notify(void)
>         efi_runtime_services.get_variable = efi_get_variable_runtime;
>         efi_runtime_services.get_next_variable_name =
>                         efi_get_next_variable_name_runtime;
> -       efi_runtime_services.set_variable = efi_set_variable_runtime;
> +       efi_runtime_services.set_variable = efi_set_variable_int_runtime;
>         efi_update_table_header_crc32(&efi_runtime_services.hdr);
>
>         /* Record that ExitBootServices() has been called */
> --
> 2.34.1
>

Reply via email to