[PATCH] mefi: add dynamic control interface for EFI runtime services
Junxiao Chang <[email protected]> Sat, 4 Jul 2026 08:33:41 +0800
| Newsgroups | org.kernel.vger.linux-efi,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Add an interface to dynamically enable or disable EFI runtime services at runtime. By default, EFI runtime services remain enabled, but they can be temporarily disabled to improve real-time latency. Currently, EFI runtime services are typically disabled on RT systems using kernel parameters such as "noefi" or "efi=disable". However, this permanently disables EFI services, preventing use cases such as UEFI firmware updates. With this change, EFI runtime services can be disabled during execution of real-time workloads and re-enabled afterwards, allowing better balance between real-time performance and firmware service availability. Signed-off-by: Junxiao Chang <[email protected]> --- .../admin-guide/kernel-parameters.txt | 5 ++- drivers/firmware/efi/efi.c | 39 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index b5493a7f8f228..533213101f808 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1595,7 +1595,8 @@ Kernel parameters efi= [EFI,EARLY] Format: { "debug", "disable_early_pci_dma", "nochunk", "noruntime", "nosoftreserve", - "novamap", "no_disable_early_pci_dma" } + "novamap", "no_disable_early_pci_dma", + "dynamic" } debug: enable misc debug output. disable_early_pci_dma: disable the busmaster bit on all PCI bridges while in the EFI boot stub. @@ -1612,6 +1613,8 @@ Kernel parameters novamap: do not call SetVirtualAddressMap(). no_disable_early_pci_dma: Leave the busmaster bit set on all PCI bridges while in the EFI boot stub + dynamic: enable EFI runtime services, which can be + disabled via /sys/firmware/efi/dynamic_enable. efi_no_storage_paranoia [EFI,X86,EARLY] Using this parameter you can use more than 50% of diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 0327a39d31fa5..18d5d99fab821 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -81,6 +81,7 @@ struct mm_struct efi_mm = { struct workqueue_struct *efi_rts_wq; +static bool efi_in_dynamic __initdata; static bool disable_runtime = IS_ENABLED(CONFIG_EFI_DISABLE_RUNTIME); static int __init setup_noefi(char *arg) { @@ -115,6 +116,11 @@ static int __init parse_efi_cmdline(char *str) if (parse_option_str(str, "runtime")) disable_runtime = false; + if (parse_option_str(str, "dynamic")) { + disable_runtime = false; + efi_in_dynamic = true; + } + if (parse_option_str(str, "nosoftreserve")) set_bit(EFI_MEM_NO_SOFT_RESERVE, &efi.flags); @@ -401,6 +407,34 @@ 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 (enable) + set_bit(EFI_RUNTIME_SERVICES, &efi.flags); + else { + clear_bit(EFI_RUNTIME_SERVICES, &efi.flags); + if (efi_rts_wq) + flush_workqueue(efi_rts_wq); + } + + 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 +480,11 @@ static int __init efisubsys_init(void) goto err_destroy_wq; } + if (efi_in_dynamic && 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(); -- 2.43.0