[PATCH v2 09/10] efi: libstub: Transfer EDID to kernel
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: 2025-11-24 16:51:40
Also in:
dri-devel, linux-arm-kernel, linux-efi, linux-hyperv, linux-pci, linux-riscv, lkml, loongarch
Subsystem:
extensible firmware interface (efi), the rest · Maintainers:
Ard Biesheuvel, Linus Torvalds
Replace struct screen_info with struct sysfb_display_info from the kernel's sysfb_primary_display and rename functions accordingly. Transfer the it to the runtime kernel using the kernel's global state or the config-table entry LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID. Also rename screen_info.c to primary_display.c and adapt the contained comment according to the changes. With CONFIG_FIRMWARE_EDID=y, libstub now transfers the GOP device's EDID information to the kernel. Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> --- drivers/firmware/efi/libstub/Makefile | 2 +- drivers/firmware/efi/libstub/efi-stub-entry.c | 11 ++-- drivers/firmware/efi/libstub/efi-stub.c | 41 +++++++++----- drivers/firmware/efi/libstub/efistub.h | 7 ++- .../firmware/efi/libstub/primary_display.c | 56 +++++++++++++++++++ drivers/firmware/efi/libstub/screen_info.c | 53 ------------------ drivers/firmware/efi/libstub/zboot.c | 4 +- 7 files changed, 93 insertions(+), 81 deletions(-) create mode 100644 drivers/firmware/efi/libstub/primary_display.c delete mode 100644 drivers/firmware/efi/libstub/screen_info.c
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 7d15a85d579f..e386ffd009b7 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile@@ -80,7 +80,7 @@ $(obj)/lib-%.o: $(srctree)/lib/%.c FORCE $(call if_changed_rule,cc_o_c) lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ - screen_info.o efi-stub-entry.o + primary_display.o efi-stub-entry.o lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
index 401ecbbdf331..aa85e910fe59 100644
--- a/drivers/firmware/efi/libstub/efi-stub-entry.c
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c@@ -14,18 +14,15 @@ static void *kernel_image_addr(void *addr) return addr + kernel_image_offset; } -struct screen_info *alloc_screen_info(void) +struct sysfb_display_info *alloc_primary_display(void) { if (IS_ENABLED(CONFIG_ARM)) - return __alloc_screen_info(); + return __alloc_primary_display(); if (IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_EFI_EARLYCON) || - IS_ENABLED(CONFIG_SYSFB)) { - struct sysfb_display_info *dpy = kernel_image_addr(&sysfb_primary_display); - - return &dpy->screen; - } + IS_ENABLED(CONFIG_SYSFB)) + return kernel_image_addr(&sysfb_primary_display); return NULL; }
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 9cb814c5ba1b..42d6073bcd06 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c@@ -10,7 +10,7 @@ */ #include <linux/efi.h> -#include <linux/screen_info.h> +#include <linux/sysfb.h> #include <asm/efi.h> #include "efistub.h"
@@ -48,23 +48,33 @@ static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0); -void __weak free_screen_info(struct screen_info *si) -{ -} +void __weak free_primary_display(struct sysfb_display_info *dpy) +{ } -static struct screen_info *setup_graphics(void) +static struct sysfb_display_info *setup_primary_display(void) { - struct screen_info *si, tmp = {}; + struct sysfb_display_info *dpy; + struct screen_info *screen = NULL; + struct edid_info *edid = NULL; + efi_status_t status; - if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS) + dpy = alloc_primary_display(); + if (!dpy) return NULL; + screen = &dpy->screen; +#if defined(CONFIG_FIRMWARE_EDID) + edid = &dpy->edid; +#endif - si = alloc_screen_info(); - if (!si) - return NULL; + status = efi_setup_graphics(screen, edid); + if (status != EFI_SUCCESS) + goto err_free_primary_display; - *si = tmp; - return si; + return dpy; + +err_free_primary_display: + free_primary_display(dpy); + return NULL; } static void install_memreserve_table(void)
@@ -145,14 +155,14 @@ efi_status_t efi_stub_common(efi_handle_t handle, unsigned long image_addr, char *cmdline_ptr) { - struct screen_info *si; + struct sysfb_display_info *dpy; efi_status_t status; status = check_platform_features(); if (status != EFI_SUCCESS) return status; - si = setup_graphics(); + dpy = setup_primary_display(); efi_retrieve_eventlog();
@@ -172,7 +182,8 @@ efi_status_t efi_stub_common(efi_handle_t handle, status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr); - free_screen_info(si); + free_primary_display(dpy); + return status; }
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index b2fb0c3fa721..979a21818cc1 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h@@ -36,6 +36,7 @@ struct edid_info; struct screen_info; +struct sysfb_display_info; extern bool efi_no5lvl; extern bool efi_nochunk;
@@ -1175,9 +1176,9 @@ efi_enable_reset_attack_mitigation(void) { } void efi_retrieve_eventlog(void); -struct screen_info *alloc_screen_info(void); -struct screen_info *__alloc_screen_info(void); -void free_screen_info(struct screen_info *si); +struct sysfb_display_info *alloc_primary_display(void); +struct sysfb_display_info *__alloc_primary_display(void); +void free_primary_display(struct sysfb_display_info *dpy); void efi_cache_sync_image(unsigned long image_base, unsigned long alloc_size);
diff --git a/drivers/firmware/efi/libstub/primary_display.c b/drivers/firmware/efi/libstub/primary_display.c
new file mode 100644
index 000000000000..cdaebab26514
--- /dev/null
+++ b/drivers/firmware/efi/libstub/primary_display.c@@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/efi.h> +#include <linux/sysfb.h> + +#include <asm/efi.h> + +#include "efistub.h" + +/* + * There are two ways of populating the core kernel's sysfb_primary_display + * via the stub: + * + * - using a configuration table, which relies on the EFI init code to + * locate the table and copy the contents; or + * + * - by linking directly to the core kernel's copy of the global symbol. + * + * The latter is preferred because it makes the EFIFB earlycon available very + * early, but it only works if the EFI stub is part of the core kernel image + * itself. The zboot decompressor can only use the configuration table + * approach. + */ + +static efi_guid_t primary_display_guid = LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID; + +struct sysfb_display_info *__alloc_primary_display(void) +{ + struct sysfb_display_info *dpy; + efi_status_t status; + + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, + sizeof(*dpy), (void **)&dpy); + + if (status != EFI_SUCCESS) + return NULL; + + memset(dpy, 0, sizeof(*dpy)); + + status = efi_bs_call(install_configuration_table, + &primary_display_guid, dpy); + if (status == EFI_SUCCESS) + return dpy; + + efi_bs_call(free_pool, dpy); + return NULL; +} + +void free_primary_display(struct sysfb_display_info *dpy) +{ + if (!dpy) + return; + + efi_bs_call(install_configuration_table, &primary_display_guid, NULL); + efi_bs_call(free_pool, dpy); +}
diff --git a/drivers/firmware/efi/libstub/screen_info.c b/drivers/firmware/efi/libstub/screen_info.c
deleted file mode 100644
index 5d3a1e32d177..000000000000
--- a/drivers/firmware/efi/libstub/screen_info.c
+++ /dev/null@@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#include <linux/efi.h> -#include <linux/screen_info.h> - -#include <asm/efi.h> - -#include "efistub.h" - -/* - * There are two ways of populating the core kernel's struct screen_info via the stub: - * - using a configuration table, like below, which relies on the EFI init code - * to locate the table and copy the contents; - * - by linking directly to the core kernel's copy of the global symbol. - * - * The latter is preferred because it makes the EFIFB earlycon available very - * early, but it only works if the EFI stub is part of the core kernel image - * itself. The zboot decompressor can only use the configuration table - * approach. - */ - -static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID; - -struct screen_info *__alloc_screen_info(void) -{ - struct screen_info *si; - efi_status_t status; - - status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, - sizeof(*si), (void **)&si); - - if (status != EFI_SUCCESS) - return NULL; - - memset(si, 0, sizeof(*si)); - - status = efi_bs_call(install_configuration_table, - &screen_info_guid, si); - if (status == EFI_SUCCESS) - return si; - - efi_bs_call(free_pool, si); - return NULL; -} - -void free_screen_info(struct screen_info *si) -{ - if (!si) - return; - - efi_bs_call(install_configuration_table, &screen_info_guid, NULL); - efi_bs_call(free_pool, si); -}
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index c47ace06f010..4b76f74c56da 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c@@ -26,9 +26,9 @@ void __weak efi_cache_sync_image(unsigned long image_base, // executable code loaded into memory to be safe for execution. } -struct screen_info *alloc_screen_info(void) +struct sysfb_display_info *alloc_primary_display(void) { - return __alloc_screen_info(); + return __alloc_primary_display(); } asmlinkage efi_status_t __efiapi
--
2.51.1