[PATCH 04/12] efi_loader: enable EFI runtime SetVariable()/GetVariable() using FF-A transport

Simon Glass sjg at chromium.org
Tue Apr 28 20:16:05 CEST 2026


Hi Harsimran,

On 2026-04-24T17:31:50, Harsimran Singh Tungal
<harsimransingh.tungal at arm.com> wrote:
> efi_loader: enable EFI runtime SetVariable()/GetVariable() using FF-A transport
>
> Route EFI runtime variable APIs through FF-A MM communication
>
> This patch implements full EFI Runtime Variable Services (GetVariable,
> SetVariable, GetNextVariableName, and QueryVariableInfo) using the
> FF-A/MM communication backend. Once ExitBootServices() has been invoked,
> all variable operations now use the runtime-safe FF-A transport instead
> of the boot-time communication paths.
>
> Key changes:
> ============
>
>  - Add runtime-safe variable property handling via FF-A MM SP.
>  - Add runtime versions of variable access and property operations.
>  - Replace all standard memory operations with EFI-runtime-safe variants.
>
> Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal at arm.com>
>
> lib/charset.c                     |   2 +-
>  lib/efi_loader/efi_variable_tee.c | 322 +++++++++++++++++++++++++++++++++++++-
>  2 files changed, 318 insertions(+), 6 deletions(-)

> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> @@ -991,6 +1066,92 @@ out:
> +     /*
> +      * UEFI > 2.7 needs the attributes set even if the buffer is
> +      * smaller
> +      */
> +     if (attributes) {
> +             tmp = get_property_int_runtime(variable_name, name_size, vendor,
> +                                            &var_property);
> +             if (tmp != EFI_SUCCESS) {
> +                     ret = tmp;
> +                     return ret;
> +             }
> +             *attributes = var_acc->attr;
> +             if (var_property.property &
> +                 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
> +                     *attributes |= EFI_VARIABLE_READ_ONLY;
> +     }

get_property_int_runtime() ends up calling setup_mm_hdr() ->
get_comm_buf(), and at runtime get_comm_buf() does
efi_memset_runtime(ffa_shared_buf, 0, CONFIG_FFA_SHARED_MM_BUF_SIZE)
on the same shared buffer that var_acc points into.

By the time you read var_acc->attr it has been zeroed, so
'*attributes' will only ever come back as 0 (optionally OR'd with
EFI_VARIABLE_READ_ONLY). The boot-time path gets away with this
because get_property_int() calloc()s a fresh buffer; the runtime path
cannot. Please cache var_acc->attr in a local before the call, or move
the get_property_int_runtime() call ahead of the SP exchange.

> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> @@ -1228,7 +1477,70 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
> +     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;
> +
> +     /*
> +      * Allocate the buffer early, before switching to RW (if needed)
> +      * so we won't need to account for any failures in reading/setting
> +      * the properties, if the allocation fails
> +      */
> +     comm_buf = setup_mm_hdr((void **)&var_acc, payload_size,
> +                             SMM_VARIABLE_FUNCTION_SET_VARIABLE, &ret);
> +     if (!comm_buf)
> +             return ret;
> +
> +     if (var_property.property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY)
> +             return EFI_WRITE_PROTECTED;

The comment is copied from efi_set_variable_int() and no longer
matches the code - there is no RW switch in the runtime path (no
ro_check argument), and the allocation happens after the property
read, the opposite of what the comment claims. Either drop the comment
or, better, do the RO check before calling setup_mm_hdr() so the
early-return is quicker.

> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
> @@ -859,6 +859,38 @@ out:
> +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)

As mentioned elsewhere, the four new functions
(set_property_int_runtime, get_property_int_runtime,
efi_get_variable_runtime, efi_get_next_variable_name_runtime) are
near-line-for-line copies of their boot-time counterparts with
memcpy/guidcpy/memset swapped for the efi_*_runtime helpers and a
different mm_communicate(). Since setup_mm_hdr() was made runtime-safe
in patch 3, can the boot-time helpers be reused directly (with
mm_communicate() picking the right transport based on
efi_is_runtime_enabled())? It would also avoid the special-case free()
path.

> diff --git a/lib/charset.c b/lib/charset.c
> @@ -407,7 +407,7 @@ size_t __efi_runtime u16_strnlen(const u16 *in, size_t count)
> -size_t u16_strsize(const void *in)
> +size_t __efi_runtime u16_strsize(const void *in)

This change should really be in its own patch with a one-line note
that it's needed by the new runtime callers. It is unrelated to the
SetVariable/GetVariable wiring and is easy to lose in this 320-line
diff.

> Key changes:
> ============

>
>  - Add runtime-safe variable property handling via FF-A MM SP.
>  - Add runtime versions of variable access and property operations.
>  - Replace all standard memory operations with EFI-runtime-safe variants.

The'============' underline is more for rST documentation than commit
messages - please drop it. The third bullet is also misleading: only
the new runtime functions use the runtime-safe variants; the existing
boot-time helpers are unchanged. It is generally better to use prose
than bullet points in a commit message.

Regards,
Simon


More information about the U-Boot mailing list