From: Thomas Zimmermann <tzimmermann@suse.de>
To: Ard Biesheuvel <ardb@kernel.org>
Cc: jonathan@marek.ca, javierm@redhat.com, linux-efi@vger.kernel.org,
dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 0/5] efi: x86: Provide EDID from GOP device
Date: Mon, 17 Nov 2025 09:01:56 +0100 [thread overview]
Message-ID: <b6801420-6ae4-44cb-9d86-e9353a2a59d8@suse.de> (raw)
In-Reply-To: <CAMj1kXF62pEMUJAM12HnF7qMt5xhZaZXpPoMdebMUKCfoAYisQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2817 bytes --]
Hi
Am 14.11.25 um 09:31 schrieb Ard Biesheuvel:
> On Wed, 15 Oct 2025 at 18:08, Thomas Zimmermann <tzimmermann@suse.de> wrote:
>> Add support for EFI_EDID_ACTIVE_PROTOCOL and EFI_EDID_DISCOVERED_PROTOCOL
>> on x86. Refactor the GOP helpers for EDID support, then retrieve the EDID
>> into x86 boot_params.
>>
>> Later boot code copies the EDID from the boot parameters into the global
>> variable edid_info. Graphics drivers, such as efidrm, can pick up the
>> information from there. In the case of efidrm, it provides the EDID to
>> user-space compositors, which use it for improved QoS on the display
>> output. Similar functionality is already available on old VESA systems
>> with vesadrm.
>>
>> Tested on x86 EFI systems.
>>
>> Another patch is required to provide EDID on non-x86 systems via the
>> generic EFI stub. The implementation can directly build upon this
>> series.
>>
>> Thomas Zimmermann (5):
>> efi: Fix trailing whitespace in header file
>> efi/libstub: gop: Find GOP handle instead of GOP data
>> efi/libstub: gop: Initialize screen_info in helper function
>> efi/libstub: gop: Add support for reading EDID
>> efi/libstub: x86: Store EDID in boot_params
>>
> Hi,
>
> Apologies for the delay. This series looks fine to me, although I
> would prefer it if we could make things a bit more generic?
>
> Everything you are adding here is arch-agnostic, except for the bit
> where we use x86-specific plumbing to pass the EDID info between the
> EFI stub and the core kernel.
Attached is an RFC patch that I already have. This would be the next
step for EDID support. I've not yet sent the generic-EFI patch, as I did
not have opportunity to test it. The patch addresses most of what you
ask for, I think.
>
> More specifically, could we do the following:
> - move struct edid_info edid_info into common code
edid_info is related to screen_info, so it follows the same conventions.
Arnd Bergmann made x86-specific changes for screen_info in commit
b8466fe82b79 ("efi: move screen_info into efi init code"). x86 has it's
own thing, sort of. See the attached patch for my non-x86 solution.
> - pass the detected EDID info block via a EFI config table instead of
> boot_params
The x86 code uses boot params for screen_info already and also transfers
edid_info on VESA systems via boot params (or if grub set up boot_params
for us). [1] It's all there and working already. If we transfer
edid_info via config table, we'd need extra code on x86.
> - make CONFIG_FIRMWARE_EDID depend on (X86 || EFI_STUB)
See the attached patch.
Best regards
Thomas
--
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)
[-- Attachment #2: 0001-efi-transfer-EDID-from-stub-to-kernel.patch --]
[-- Type: text/x-patch, Size: 11641 bytes --]
From 10be917b0cf90f22f2fd900620cb9acf5838ff55 Mon Sep 17 00:00:00 2001
From: Thomas Zimmermann <tzimmermann@suse.de>
Date: Wed, 15 Oct 2025 13:36:06 +0200
Subject: [PATCH] efi: transfer EDID from stub to kernel
- Add UUID for storing the EDID data in the UEFI configuration table.
- The UUID has been created by uuidgen.
- Enable edid_info on EFI systems
---
drivers/firmware/efi/efi-init.c | 33 +++++++++++++-
drivers/firmware/efi/efi.c | 2 +
drivers/firmware/efi/libstub/Makefile | 2 +-
drivers/firmware/efi/libstub/edid_info.c | 40 +++++++++++++++++
drivers/firmware/efi/libstub/efi-stub-entry.c | 17 +++++++
drivers/firmware/efi/libstub/efi-stub.c | 44 +++++++++++++------
drivers/firmware/efi/libstub/efistub.h | 4 ++
drivers/video/Kconfig | 8 ++--
include/linux/efi.h | 8 ++--
9 files changed, 136 insertions(+), 22 deletions(-)
create mode 100644 drivers/firmware/efi/libstub/edid_info.c
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index a65c2d5b9e7b..2719311f2d43 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -23,7 +23,10 @@
#include <asm/efi.h>
+#include <video/edid.h>
+
unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
+unsigned long __initdata edid_info_table = EFI_INVALID_TABLE_ADDR;
static int __init is_memory(efi_memory_desc_t *md)
{
@@ -57,14 +60,19 @@ static phys_addr_t __init efi_to_phys(unsigned long addr)
extern __weak const efi_config_table_type_t efi_arch_tables[];
/*
- * x86 defines its own screen_info and uses it even without EFI,
- * everything else can get it from here.
+ * x86 defines its own screen_info and edid_info and uses them even
+ * without EFI, everything else can get them from here.
*/
#if !defined(CONFIG_X86) && (defined(CONFIG_SYSFB) || defined(CONFIG_EFI_EARLYCON))
struct screen_info screen_info __section(".data");
EXPORT_SYMBOL_GPL(screen_info);
#endif
+#if !defined(CONFIG_X86) && defined(CONFIG_FIRMWARE_EDID)
+struct edid_info edid_info __section(".data");
+EXPORT_SYMBOL_GPL(edid_info);
+#endif
+
static void __init init_screen_info(void)
{
struct screen_info *si;
@@ -88,6 +96,23 @@ static void __init init_screen_info(void)
}
}
+static void __init init_edid_info(void)
+{
+#if defined(CONFIG_FIRMWARE_EDID)
+ struct edid_info *edid;
+
+ if (edid_info_table == EFI_INVALID_TABLE_ADDR)
+ return;
+
+ edid = early_memremap(edid_info_table, sizeof(*edid));
+ if (!edid)
+ return; /* not an error; EDID is optional */
+ edid_info = *edid;
+ memset(edid, 0, sizeof(*edid));
+ early_memunmap(edid, sizeof(*edid));
+#endif
+}
+
static int __init uefi_init(u64 efi_system_table)
{
efi_config_table_t *config_tables;
@@ -275,4 +300,8 @@ void __init efi_init(void)
IS_ENABLED(CONFIG_SYSFB) ||
IS_ENABLED(CONFIG_EFI_EARLYCON))
init_screen_info();
+
+ if (IS_ENABLED(CONFIG_X86) ||
+ IS_ENABLED(CONFIG_FIRMWARE_EDID))
+ init_edid_info();
}
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 1ce428e2ac8a..7a3047a238ae 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -64,6 +64,7 @@ static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;
extern unsigned long screen_info_table;
+extern unsigned long edid_info_table;
struct mm_struct efi_mm = {
.mm_mt = MTREE_INIT_EXT(mm_mt, MM_MT_FLAGS, efi_mm.mmap_lock),
@@ -639,6 +640,7 @@ static const efi_config_table_type_t common_tables[] __initconst = {
#endif
#ifdef CONFIG_EFI_GENERIC_STUB
{LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table },
+ {LINUX_EFI_EDID_INFO_TABLE_GUID, &edid_info_table },
#endif
{},
};
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index 94b05e4451dd..12ae5c6be028 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
+ screen_info.o edid_info.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/edid_info.c b/drivers/firmware/efi/libstub/edid_info.c
new file mode 100644
index 000000000000..882c85faf395
--- /dev/null
+++ b/drivers/firmware/efi/libstub/edid_info.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/efi.h>
+#include <video/edid.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+static efi_guid_t edid_info_guid = LINUX_EFI_EDID_INFO_TABLE_GUID;
+
+struct edid_info *__alloc_edid_info(void)
+{
+ struct edid_info *edid;
+ efi_status_t status;
+
+ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ sizeof(*edid), (void **)&edid);
+
+ if (status != EFI_SUCCESS)
+ return NULL;
+
+ memset(edid, 0, sizeof(*edid));
+
+ status = efi_bs_call(install_configuration_table,
+ &edid_info_guid, edid);
+ if (status == EFI_SUCCESS)
+ return edid;
+
+ efi_bs_call(free_pool, edid);
+ return NULL;
+}
+
+void free_edid_info(struct edid_info *edid)
+{
+ if (!edid)
+ return;
+
+ efi_bs_call(install_configuration_table, &edid_info_guid, NULL);
+ efi_bs_call(free_pool, edid);
+}
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
index a6c049835190..7ba8a23bbc55 100644
--- a/drivers/firmware/efi/libstub/efi-stub-entry.c
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
@@ -5,9 +5,12 @@
#include <asm/efi.h>
+#include <video/edid.h>
+
#include "efistub.h"
static unsigned long screen_info_offset;
+static unsigned long edid_info_offset;
struct screen_info *alloc_screen_info(void)
{
@@ -22,6 +25,19 @@ struct screen_info *alloc_screen_info(void)
return NULL;
}
+struct edid_info *alloc_edid_info(void)
+{
+#if defined(CONFIG_FIRMWARE_EDID)
+ if (IS_ENABLED(CONFIG_ARM))
+ return __alloc_edid_info();
+
+ if (IS_ENABLED(CONFIG_X86) &&
+ IS_ENABLED(CONFIG_FIRMWARE_EDID))
+ return (void *)&edid_info + edid_info_offset;
+#endif
+ return NULL;
+}
+
/*
* EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
* LoongArch. This is the entrypoint that is described in the PE/COFF header
@@ -74,6 +90,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
}
screen_info_offset = image_addr - (unsigned long)image->image_base;
+ edid_info_offset = image_addr - (unsigned long)image->image_base;
status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index 9cb814c5ba1b..9cb2a5c154b4 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -12,6 +12,7 @@
#include <linux/efi.h>
#include <linux/screen_info.h>
#include <asm/efi.h>
+#include <video/edid.h>
#include "efistub.h"
@@ -49,22 +50,37 @@ 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_edid_info(struct edid_info *edid)
+{ }
-static struct screen_info *setup_graphics(void)
+static void setup_graphics(struct screen_info **si, struct edid_info **edid)
{
- struct screen_info *si, tmp = {};
+ efi_status_t status;
+
+ *si = alloc_screen_info();
+ *edid = alloc_edid_info();
- if (efi_setup_graphics(&tmp, NULL) != EFI_SUCCESS)
- return NULL;
+ if (!*si && !*edid)
+ return;
- si = alloc_screen_info();
- if (!si)
- return NULL;
+ status = efi_setup_graphics(*si, *edid);
+ if (status) {
+ /* Clear on error */
+ if (*edid)
+ memset(*edid, 0, sizeof(**edid));
+ if (*si)
+ memset(*si, 0, sizeof(**si));
+ }
+}
- *si = tmp;
- return si;
+static void release_graphics(struct screen_info *si, struct edid_info *edid)
+{
+ if (edid)
+ free_edid_info(edid);
+ if (si)
+ free_screen_info(si);
}
static void install_memreserve_table(void)
@@ -146,13 +162,14 @@ efi_status_t efi_stub_common(efi_handle_t handle,
char *cmdline_ptr)
{
struct screen_info *si;
+ struct edid_info *edid;
efi_status_t status;
status = check_platform_features();
if (status != EFI_SUCCESS)
return status;
- si = setup_graphics();
+ setup_graphics(&si, &edid);
efi_retrieve_eventlog();
@@ -172,7 +189,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);
+ release_graphics(si, edid);
+
return status;
}
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index b2fb0c3fa721..120c9a499362 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -1179,6 +1179,10 @@ struct screen_info *alloc_screen_info(void);
struct screen_info *__alloc_screen_info(void);
void free_screen_info(struct screen_info *si);
+struct edid_info *alloc_edid_info(void);
+struct edid_info *__alloc_edid_info(void);
+void free_edid_info(struct edid_info *edid);
+
void efi_cache_sync_image(unsigned long image_base,
unsigned long alloc_size);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d51777df12d1..f452fac90a9f 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -63,11 +63,13 @@ endif # HAS_IOMEM
config FIRMWARE_EDID
bool "Enable firmware EDID"
- depends on X86
+ depends on EFI || X86
help
This enables access to the EDID transferred from the firmware.
- On x86, this is from the VESA BIOS. DRM display drivers will
- be able to export the information to userspace.
+ On EFI systems, the EDID comes from the same device as the
+ primary GOP. On x86 with BIOS, it comes from the VESA BIOS.
+ DRM display drivers will be able to export the information
+ to userspace.
Also enable this if DDC/I2C transfers do not work for your driver
and if you are using nvidiafb, i810fb or savagefb.
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 11e267492efd..eeff8393c9c0 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -406,11 +406,13 @@ void efi_native_runtime_setup(void);
#define EFI_CC_FINAL_EVENTS_TABLE_GUID EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46)
/*
- * This GUID is used to pass to the kernel proper the struct screen_info
- * structure that was populated by the stub based on the GOP protocol instance
- * associated with ConOut
+ * These GUIDs are used to pass to the kernel proper the struct screen_info
+ * and struct edid_info structures that were populated by the stub based on
+ * the GOP protocol instance associated with ConOut.
*/
#define LINUX_EFI_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
+#define LINUX_EFI_EDID_INFO_TABLE_GUID EFI_GUID(0x4e6c17ea, 0x6ec0, 0x4838, 0x8c, 0xae, 0x2c, 0xf5, 0x4d, 0x5f, 0x58, 0x64)
+
#define LINUX_EFI_ARM_CPU_STATE_TABLE_GUID EFI_GUID(0xef79e4aa, 0x3c3d, 0x4989, 0xb9, 0x02, 0x07, 0xa9, 0x43, 0xe5, 0x50, 0xd2)
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
--
2.51.1
next prev parent reply other threads:[~2025-11-17 8:01 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-15 15:56 [PATCH 0/5] efi: x86: Provide EDID from GOP device Thomas Zimmermann
2025-10-15 15:56 ` [PATCH 1/5] efi: Fix trailing whitespace in header file Thomas Zimmermann
2025-10-24 9:19 ` Javier Martinez Canillas
2025-10-15 15:56 ` [PATCH 2/5] efi/libstub: gop: Find GOP handle instead of GOP data Thomas Zimmermann
2025-10-24 9:47 ` Javier Martinez Canillas
2025-10-24 12:06 ` Thomas Zimmermann
2025-10-15 15:56 ` [PATCH 3/5] efi/libstub: gop: Initialize screen_info in helper function Thomas Zimmermann
2025-10-24 9:53 ` Javier Martinez Canillas
2025-11-17 7:37 ` Thomas Zimmermann
2025-10-15 15:56 ` [PATCH 4/5] efi/libstub: gop: Add support for reading EDID Thomas Zimmermann
2025-10-24 9:56 ` Javier Martinez Canillas
2025-11-17 7:40 ` Thomas Zimmermann
2025-10-15 15:56 ` [PATCH 5/5] efi/libstub: x86: Store EDID in boot_params Thomas Zimmermann
2025-10-24 9:57 ` Javier Martinez Canillas
2025-11-14 8:31 ` [PATCH 0/5] efi: x86: Provide EDID from GOP device Ard Biesheuvel
2025-11-17 8:01 ` Thomas Zimmermann [this message]
2025-11-18 16:52 ` Ard Biesheuvel
2025-11-18 19:41 ` Ard Biesheuvel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b6801420-6ae4-44cb-9d86-e9353a2a59d8@suse.de \
--to=tzimmermann@suse.de \
--cc=ardb@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=javierm@redhat.com \
--cc=jonathan@marek.ca \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox