Re: [PATCH] efi: add dynamic control interface for EFI runtime services
"Ard Biesheuvel" <[email protected]> Sat, 01 Aug 2026 15:45:17 +0200
| Newsgroups | org.kernel.vger.linux-efi,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi Junxiao, On Fri, 31 Jul 2026, at 08:24, Junxiao Chang wrote: > Add an interface for PREEMPT_RT kernels to dynamically enable or > disable EFI runtime services. > > EFI runtime services are typically disabled on RT systems using > kernel parameters such as "noefi" or "efi=disable" to avoid > long latency caused by firmware calls. However, this permanently > disables EFI runtime services, preventing operations such as UEFI > firmware updates. > > With this change, EFI runtime services can be disabled while > real-time workloads are running and re-enabled afterwards, > providing low-latency operation without permanently sacrificing > firmware functionality. > > Signed-off-by: Junxiao Chang <[email protected]> > --- > drivers/firmware/efi/efi.c | 31 +++++++++++++++++++++++++ > drivers/firmware/efi/runtime-wrappers.c | 15 ++++++++++++ > include/linux/efi.h | 1 + > 3 files changed, 47 insertions(+) > > diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c > index 0327a39d31fa5..f57784a815c61 100644 > --- a/drivers/firmware/efi/efi.c > +++ b/drivers/firmware/efi/efi.c > @@ -401,6 +401,32 @@ static void __init efi_debugfs_init(void) > static inline void efi_debugfs_init(void) {} > #endif > > +static ssize_t efi_dynamic_show(struct kobject *kobj, struct > kobj_attribute *attr, char *buf) > +{ > + return sprintf(buf, "%d\n", efi_enabled(EFI_RUNTIME_SERVICES)); > +} > + > +static ssize_t efi_dynamic_store(struct kobject *kobj, struct > kobj_attribute *attr, > + const char *buf, size_t count) > +{ > + int ret; > + bool enable; > + > + ret = kstrtobool(buf, &enable); > + if (ret) > + return ret; > + > + if (efi_runtime_set_enable_flag(enable) != EFI_SUCCESS) { > + pr_warn("unable to enable/disable efi runtime service\n"); > + return -EAGAIN; > + } > + > + return count; > +} > + > +static struct kobj_attribute efi_dynamic_attr = > + __ATTR(dynamic_enable, 0644, efi_dynamic_show, efi_dynamic_store); > + > static int __init efipostcore_init(void) > { > if (!efi_enabled(EFI_RUNTIME_SERVICES)) > @@ -446,6 +472,11 @@ static int __init efisubsys_init(void) > goto err_destroy_wq; > } > > + if (IS_ENABLED(CONFIG_PREEMPT_RT) && efi.runtime_supported_mask) { > + if (sysfs_create_file(efi_kobj, &efi_dynamic_attr.attr)) > + pr_warn("unable to register efi dynamic sysfs interface\n"); > + } > + > if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE | > EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME)) { > error = generic_ops_register(); > diff --git a/drivers/firmware/efi/runtime-wrappers.c > b/drivers/firmware/efi/runtime-wrappers.c > index da8d296216441..8d1554714e3f4 100644 > --- a/drivers/firmware/efi/runtime-wrappers.c > +++ b/drivers/firmware/efi/runtime-wrappers.c > @@ -602,3 +602,18 @@ void efi_runtime_assert_lock_held(void) > { > WARN_ON(efi_runtime_lock_owner != current); > } > + > +efi_status_t efi_runtime_set_enable_flag(bool enable) > +{ > + if (down_interruptible(&efi_runtime_lock)) > + return EFI_ABORTED; > + > + if (enable) > + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); This interface allows enabling of EFI_RUNTIME_SERVICES even if it was disabled for other reasons, e.g., a firmware crash or a command line option. IOW, the set_bit() path is only permitted if the clear_bit() path was taken first. > + else > + clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); > + > + up(&efi_runtime_lock); > + > + return EFI_SUCCESS; > +} > diff --git a/include/linux/efi.h b/include/linux/efi.h > index ccbc35479684a..98b76008fd426 100644 > --- a/include/linux/efi.h > +++ b/include/linux/efi.h > @@ -1109,6 +1109,7 @@ extern void efi_call_virt_check_flags(unsigned > long flags, const void *caller); > extern unsigned long efi_call_virt_save_flags(void); > > void efi_runtime_assert_lock_held(void); > +efi_status_t efi_runtime_set_enable_flag(bool enable); > > enum efi_secureboot_mode { > efi_secureboot_mode_unset, > -- > 2.43.0