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. Listen to efivar_ops_nh notifications and retry the initialization when writable EFI variable ops become available. Signed-off-by: Val Packett <[email protected]> --- 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
