Re: [PATCH] efi: pstore: Support late setup with TEE-backed efivars ops

Ilias Apalodimas
2025-12-04T09:50:22Z

Hi Val,

On Wed, 3 Dec 2025 at 06:29, Val Packett <val@packett.cool> wrote:
>
> On some platforms, EFI variable services only become available when an
> appropriate TEE driver is initialized such as qseecom, gsmi or stmm.
>
> This would work fine when efi_pstore was built as a module and loaded
> late by userspace, but with CONFIG_EFI_VARS_PSTORE=y this driver would
> quit due to non-writable efivars before the necessary driver had any
> chance to load.

The problem, at least for OP-TEE/StMM, is that writing the variables
to an RPMB depends on a userspace application If CONFIG_RPMB is not
selected. We have no guarantees that the app will still be alive.
I don't know how gsmi or qseecom deal with writing variables. We can
probably allow it for StMM if CONFIG_RPMB is enabled, but we'll have
the right trigger to do so.

>
> Listen to efivar_ops_nh notifications and retry the initialization when
> writable EFI variable ops become available.
>
> Signed-off-by: Val Packett <val@packett.cool>

Thanks
/Ilias
> ---
> drivers/firmware/efi/efi-pstore.c | 32 +++++++++++++++++++++++++++----
> 1 file changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
> index a253b6144945..ad5192d5892e 100644
> --- a/drivers/firmware/efi/efi-pstore.c
> +++ b/drivers/firmware/efi/efi-pstore.c
> @@ -253,14 +253,11 @@ static struct pstore_info efi_pstore_info = {
> .erase = efi_pstore_erase,
> };
>
> -static int efivars_pstore_init(void)
> +static int efivars_pstore_setup(void)
> {
> if (!efivar_supports_writes())
> return 0;
>
> - if (pstore_disable)
> - return 0;
> -
> /*
> * Notice that 1024 is the minimum here to prevent issues with
> * decompression algorithms that were spotted during tests;
> @@ -285,8 +282,35 @@ static int efivars_pstore_init(void)
> return 0;
> }
>
> +static int efivars_pstore_ops_notifier(struct notifier_block *nb,
> + unsigned long event, void *data)
> +{
> + if (event == EFIVAR_OPS_RDWR && !efi_pstore_info.bufsize)
> + efivars_pstore_setup();
> +
> + return NOTIFY_OK;
> +}
> +
> +static struct notifier_block efivars_pstore_ops_notifier_block = {
> + .notifier_call = efivars_pstore_ops_notifier,
> +};
> +
> +static int efivars_pstore_init(void)
> +{
> + if (pstore_disable)
> + return 0;
> +
> + blocking_notifier_chain_register(&efivar_ops_nh,
> + &efivars_pstore_ops_notifier_block);
> +
> + return efivars_pstore_setup();
> +}
> +
> static void efivars_pstore_exit(void)
> {
> + blocking_notifier_chain_unregister(&efivar_ops_nh,
> + &efivars_pstore_ops_notifier_block);
> +
> if (!efi_pstore_info.bufsize)
> return;
>
> --
> 2.51.0
>
>