Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

efi: Support EDID information

In the EFI config table, rename LINUX_EFI_SCREEN_INFO_TABLE_GUID to
LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID. Read sysfb_primary_display from
the entry. In addition to the screen_info, the entry now also contains
EDID information.

In libstub, replace struct screen_info with struct sysfb_display_info
from the kernel's sysfb_primary_display and rename functions
accordingly. Transfer it to the runtime kernel using the kernel's
global state or the LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID config-table
entry.

With CONFIG_FIRMWARE_EDID=y, libstub now transfers the GOP device's EDID
information to the kernel. If CONFIG_FIRMWARE_EDID=n, EDID information
is disabled. Make the Kconfig symbol CONFIG_FIRMWARE_EDID available with
EFI. Setting the value to 'n' disables EDID support.

Also rename screen_info.c to primary_display.c and adapt the contained
comment according to the changes.

Link: https://lore.kernel.org/all/20251126160854.553077-8-tzimmermann@suse.de/
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
[ardb: depend on EFI_GENERIC_STUB not EFI, fix conflicts after dropping
the preceding patch from the series]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>

authored by

Thomas Zimmermann and committed by
Ard Biesheuvel
c5a8f13f 4fcae635

+124 -109
+9 -9
arch/loongarch/kernel/efi.c
··· 72 72 (acpi_gbl_reduced_hardware || acpi_no_s5); 73 73 } 74 74 75 - unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR; 75 + unsigned long __initdata primary_display_table = EFI_INVALID_TABLE_ADDR; 76 76 77 77 #if defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON) 78 78 struct sysfb_display_info sysfb_primary_display __section(".data"); ··· 81 81 82 82 static void __init init_primary_display(void) 83 83 { 84 - struct screen_info *si; 84 + struct sysfb_display_info *dpy; 85 85 86 - if (screen_info_table == EFI_INVALID_TABLE_ADDR) 86 + if (primary_display_table == EFI_INVALID_TABLE_ADDR) 87 87 return; 88 88 89 - si = early_memremap(screen_info_table, sizeof(*si)); 90 - if (!si) { 91 - pr_err("Could not map screen_info config table\n"); 89 + dpy = early_memremap(primary_display_table, sizeof(*dpy)); 90 + if (!dpy) { 91 + pr_err("Could not map primary_display config table\n"); 92 92 return; 93 93 } 94 - sysfb_primary_display.screen = *si; 95 - memset(si, 0, sizeof(*si)); 96 - early_memunmap(si, sizeof(*si)); 94 + sysfb_primary_display = *dpy; 95 + memset(dpy, 0, sizeof(*dpy)); 96 + early_memunmap(dpy, sizeof(*dpy)); 97 97 98 98 memblock_reserve(__screen_info_lfb_base(&sysfb_primary_display.screen), 99 99 sysfb_primary_display.screen.lfb_size);
+9 -9
drivers/firmware/efi/efi-init.c
··· 23 23 24 24 #include <asm/efi.h> 25 25 26 - unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR; 26 + unsigned long __initdata primary_display_table = EFI_INVALID_TABLE_ADDR; 27 27 28 28 static int __init is_memory(efi_memory_desc_t *md) 29 29 { ··· 67 67 68 68 static void __init init_primary_display(void) 69 69 { 70 - struct screen_info *si; 70 + struct sysfb_display_info *dpy; 71 71 72 - if (screen_info_table != EFI_INVALID_TABLE_ADDR) { 73 - si = early_memremap(screen_info_table, sizeof(*si)); 74 - if (!si) { 75 - pr_err("Could not map screen_info config table\n"); 72 + if (primary_display_table != EFI_INVALID_TABLE_ADDR) { 73 + dpy = early_memremap(primary_display_table, sizeof(*dpy)); 74 + if (!dpy) { 75 + pr_err("Could not map primary_display config table\n"); 76 76 return; 77 77 } 78 - sysfb_primary_display.screen = *si; 79 - memset(si, 0, sizeof(*si)); 80 - early_memunmap(si, sizeof(*si)); 78 + sysfb_primary_display = *dpy; 79 + memset(dpy, 0, sizeof(*dpy)); 80 + early_memunmap(dpy, sizeof(*dpy)); 81 81 82 82 if (memblock_is_map_memory(sysfb_primary_display.screen.lfb_base)) 83 83 memblock_mark_nomap(sysfb_primary_display.screen.lfb_base,
+2 -2
drivers/firmware/efi/efi.c
··· 63 63 static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR; 64 64 static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR; 65 65 66 - extern unsigned long screen_info_table; 66 + extern unsigned long primary_display_table; 67 67 68 68 struct mm_struct efi_mm = { 69 69 .mm_mt = MTREE_INIT_EXT(mm_mt, MM_MT_FLAGS, efi_mm.mmap_lock), ··· 641 641 {LINUX_EFI_UNACCEPTED_MEM_TABLE_GUID, &efi.unaccepted, "Unaccepted" }, 642 642 #endif 643 643 #ifdef CONFIG_EFI_GENERIC_STUB 644 - {LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table }, 644 + {LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID, &primary_display_table }, 645 645 #endif 646 646 {}, 647 647 };
+1 -1
drivers/firmware/efi/libstub/Makefile
··· 80 80 $(call if_changed_rule,cc_o_c) 81 81 82 82 lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ 83 - screen_info.o efi-stub-entry.o 83 + primary_display.o efi-stub-entry.o 84 84 85 85 lib-$(CONFIG_ARM) += arm32-stub.o 86 86 lib-$(CONFIG_ARM64) += kaslr.o arm64.o arm64-stub.o smbios.o
+4 -7
drivers/firmware/efi/libstub/efi-stub-entry.c
··· 14 14 return addr + kernel_image_offset; 15 15 } 16 16 17 - struct screen_info *alloc_screen_info(void) 17 + struct sysfb_display_info *alloc_primary_display(void) 18 18 { 19 19 if (IS_ENABLED(CONFIG_ARM)) 20 - return __alloc_screen_info(); 20 + return __alloc_primary_display(); 21 21 22 22 if (IS_ENABLED(CONFIG_X86) || 23 23 IS_ENABLED(CONFIG_EFI_EARLYCON) || 24 - IS_ENABLED(CONFIG_SYSFB)) { 25 - struct sysfb_display_info *dpy = kernel_image_addr(&sysfb_primary_display); 26 - 27 - return &dpy->screen; 28 - } 24 + IS_ENABLED(CONFIG_SYSFB)) 25 + return kernel_image_addr(&sysfb_primary_display); 29 26 30 27 return NULL; 31 28 }
+27 -16
drivers/firmware/efi/libstub/efi-stub.c
··· 10 10 */ 11 11 12 12 #include <linux/efi.h> 13 - #include <linux/screen_info.h> 13 + #include <linux/sysfb.h> 14 14 #include <asm/efi.h> 15 15 16 16 #include "efistub.h" ··· 48 48 static u64 virtmap_base = EFI_RT_VIRTUAL_BASE; 49 49 static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0); 50 50 51 - void __weak free_screen_info(struct screen_info *si) 51 + void __weak free_primary_display(struct sysfb_display_info *dpy) 52 + { } 53 + 54 + static struct sysfb_display_info *setup_primary_display(void) 52 55 { 53 - } 56 + struct sysfb_display_info *dpy; 57 + struct screen_info *screen = NULL; 58 + struct edid_info *edid = NULL; 59 + efi_status_t status; 54 60 55 - static struct screen_info *setup_graphics(void) 56 - { 57 - struct screen_info *si, tmp = {}; 58 - 59 - if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS) 61 + dpy = alloc_primary_display(); 62 + if (!dpy) 60 63 return NULL; 64 + screen = &dpy->screen; 65 + #if defined(CONFIG_FIRMWARE_EDID) 66 + edid = &dpy->edid; 67 + #endif 61 68 62 - si = alloc_screen_info(); 63 - if (!si) 64 - return NULL; 69 + status = efi_setup_graphics(screen, edid); 70 + if (status != EFI_SUCCESS) 71 + goto err_free_primary_display; 65 72 66 - *si = tmp; 67 - return si; 73 + return dpy; 74 + 75 + err_free_primary_display: 76 + free_primary_display(dpy); 77 + return NULL; 68 78 } 69 79 70 80 static void install_memreserve_table(void) ··· 155 145 unsigned long image_addr, 156 146 char *cmdline_ptr) 157 147 { 158 - struct screen_info *si; 148 + struct sysfb_display_info *dpy; 159 149 efi_status_t status; 160 150 161 151 status = check_platform_features(); 162 152 if (status != EFI_SUCCESS) 163 153 return status; 164 154 165 - si = setup_graphics(); 155 + dpy = setup_primary_display(); 166 156 167 157 efi_retrieve_eventlog(); 168 158 ··· 182 172 183 173 status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr); 184 174 185 - free_screen_info(si); 175 + free_primary_display(dpy); 176 + 186 177 return status; 187 178 } 188 179
+4 -3
drivers/firmware/efi/libstub/efistub.h
··· 36 36 37 37 struct edid_info; 38 38 struct screen_info; 39 + struct sysfb_display_info; 39 40 40 41 extern bool efi_no5lvl; 41 42 extern bool efi_nochunk; ··· 1176 1175 1177 1176 void efi_retrieve_eventlog(void); 1178 1177 1179 - struct screen_info *alloc_screen_info(void); 1180 - struct screen_info *__alloc_screen_info(void); 1181 - void free_screen_info(struct screen_info *si); 1178 + struct sysfb_display_info *alloc_primary_display(void); 1179 + struct sysfb_display_info *__alloc_primary_display(void); 1180 + void free_primary_display(struct sysfb_display_info *dpy); 1182 1181 1183 1182 void efi_cache_sync_image(unsigned long image_base, 1184 1183 unsigned long alloc_size);
+56
drivers/firmware/efi/libstub/primary_display.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/efi.h> 4 + #include <linux/sysfb.h> 5 + 6 + #include <asm/efi.h> 7 + 8 + #include "efistub.h" 9 + 10 + /* 11 + * There are two ways of populating the core kernel's sysfb_primary_display 12 + * via the stub: 13 + * 14 + * - using a configuration table, which relies on the EFI init code to 15 + * locate the table and copy the contents; or 16 + * 17 + * - by linking directly to the core kernel's copy of the global symbol. 18 + * 19 + * The latter is preferred because it makes the EFIFB earlycon available very 20 + * early, but it only works if the EFI stub is part of the core kernel image 21 + * itself. The zboot decompressor can only use the configuration table 22 + * approach. 23 + */ 24 + 25 + static efi_guid_t primary_display_guid = LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID; 26 + 27 + struct sysfb_display_info *__alloc_primary_display(void) 28 + { 29 + struct sysfb_display_info *dpy; 30 + efi_status_t status; 31 + 32 + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, 33 + sizeof(*dpy), (void **)&dpy); 34 + 35 + if (status != EFI_SUCCESS) 36 + return NULL; 37 + 38 + memset(dpy, 0, sizeof(*dpy)); 39 + 40 + status = efi_bs_call(install_configuration_table, 41 + &primary_display_guid, dpy); 42 + if (status == EFI_SUCCESS) 43 + return dpy; 44 + 45 + efi_bs_call(free_pool, dpy); 46 + return NULL; 47 + } 48 + 49 + void free_primary_display(struct sysfb_display_info *dpy) 50 + { 51 + if (!dpy) 52 + return; 53 + 54 + efi_bs_call(install_configuration_table, &primary_display_guid, NULL); 55 + efi_bs_call(free_pool, dpy); 56 + }
-53
drivers/firmware/efi/libstub/screen_info.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - #include <linux/efi.h> 4 - #include <linux/screen_info.h> 5 - 6 - #include <asm/efi.h> 7 - 8 - #include "efistub.h" 9 - 10 - /* 11 - * There are two ways of populating the core kernel's struct screen_info via the stub: 12 - * - using a configuration table, like below, which relies on the EFI init code 13 - * to locate the table and copy the contents; 14 - * - by linking directly to the core kernel's copy of the global symbol. 15 - * 16 - * The latter is preferred because it makes the EFIFB earlycon available very 17 - * early, but it only works if the EFI stub is part of the core kernel image 18 - * itself. The zboot decompressor can only use the configuration table 19 - * approach. 20 - */ 21 - 22 - static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID; 23 - 24 - struct screen_info *__alloc_screen_info(void) 25 - { 26 - struct screen_info *si; 27 - efi_status_t status; 28 - 29 - status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, 30 - sizeof(*si), (void **)&si); 31 - 32 - if (status != EFI_SUCCESS) 33 - return NULL; 34 - 35 - memset(si, 0, sizeof(*si)); 36 - 37 - status = efi_bs_call(install_configuration_table, 38 - &screen_info_guid, si); 39 - if (status == EFI_SUCCESS) 40 - return si; 41 - 42 - efi_bs_call(free_pool, si); 43 - return NULL; 44 - } 45 - 46 - void free_screen_info(struct screen_info *si) 47 - { 48 - if (!si) 49 - return; 50 - 51 - efi_bs_call(install_configuration_table, &screen_info_guid, NULL); 52 - efi_bs_call(free_pool, si); 53 - }
+2 -2
drivers/firmware/efi/libstub/zboot.c
··· 26 26 // executable code loaded into memory to be safe for execution. 27 27 } 28 28 29 - struct screen_info *alloc_screen_info(void) 29 + struct sysfb_display_info *alloc_primary_display(void) 30 30 { 31 - return __alloc_screen_info(); 31 + return __alloc_primary_display(); 32 32 } 33 33 34 34 asmlinkage efi_status_t __efiapi
+5 -3
drivers/video/Kconfig
··· 63 63 64 64 config FIRMWARE_EDID 65 65 bool "Enable firmware EDID" 66 - depends on X86 66 + depends on EFI_GENERIC_STUB || X86 67 67 help 68 68 This enables access to the EDID transferred from the firmware. 69 - On x86, this is from the VESA BIOS. DRM display drivers will 70 - be able to export the information to userspace. 69 + On EFI systems, the EDID comes from the same device as the 70 + primary GOP. On x86 with BIOS, it comes from the VESA BIOS. 71 + DRM display drivers will be able to export the information 72 + to userspace. 71 73 72 74 Also enable this if DDC/I2C transfers do not work for your driver 73 75 and if you are using nvidiafb, i810fb or savagefb.
+5 -4
include/linux/efi.h
··· 406 406 #define EFI_CC_FINAL_EVENTS_TABLE_GUID EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46) 407 407 408 408 /* 409 - * This GUID is used to pass to the kernel proper the struct screen_info 410 - * structure that was populated by the stub based on the GOP protocol instance 411 - * associated with ConOut 409 + * This GUIDs are used to pass to the kernel proper the primary 410 + * display that has been populated by the stub based on the GOP 411 + * instance associated with ConOut. 412 412 */ 413 - #define LINUX_EFI_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) 413 + #define LINUX_EFI_PRIMARY_DISPLAY_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) 414 + 414 415 #define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2) 415 416 #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) 416 417 #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)