1
0
forked from pool/grub2
Files
grub2/grub2-provide-edid.patch

136 lines
4.6 KiB
Diff
Raw Permalink Normal View History

We currently use simpledrm for early graphics on PCs. As you mention, we set gfxpayload in Grub to forward information about the system's framebuffer to the kernel. Simpledrm picks up the framebuffer for displaying graphics. The driver is good enough for the job, we can do better on platforms with EFI or VESA graphics. There are currently two drivers under review at https://patchwork.freedesktop.org/series/146477/. I expect them to enter upstream in v6.16. These drivers can use the EDID data provided by EFI and VESA interfaces. This allows user space, such as Gnome, to pick up information about the output device. On vesadrm, Gnome even supports gamma correction. With EFI systems, we'll fetch the EDID during the kernel's early boot stages. On VESA systems, we need the EDID information being passed on from Grub. The gfxpayload options only forwards information about the framebuffer itself (size, colors, memory address), but not information about the display device. To our advantage, the kernel already contains real-mode code for fetching the VESA EDID; see https://elixir.bootlin.com/linux/v6.13.7/source/arch/x86/boot/video-vesa.c#L236. Hence there's already the edid_info field in the boot parameters. But this code only runs when booting with Grub's 'linux16' (or old LILO). Modern Grub never utilized the field or provided the EDID information at all. That's what this patch implements. I've opened bsc#1240624 to track the progress of this project. - Add grub2-provide-edid.patch: Grub2 already retrieves the EDID from video adapters. Copy the raw data into the Linux kernel boot parameters, so that Linux can use this information. The necessary fields have been present in the boot parameters since at least commit f8eeaaf41803 ("[PATCH] Make the bzImage format self-terminating"), but never used. Within the kernel, the EDID data will be propagated to graphics drivers and finally to user space. (bsc#1240624) OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=539
2025-04-08 07:19:13 +00:00
Index: grub-2.12/grub-core/video/video.c
===================================================================
--- grub-2.12.orig/grub-core/video/video.c
+++ grub-2.12/grub-core/video/video.c
@@ -89,6 +89,27 @@ grub_video_get_info_and_fini (struct gru
return GRUB_ERR_NONE;
}
+/* Get information about connected display. */
+grub_err_t
+grub_video_get_edid (struct grub_video_edid_info *edid_info)
+{
+ grub_err_t err;
+
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
+
+ grub_memset (edid_info, 0, sizeof (*edid_info));
+
+ if (grub_video_adapter_active->get_edid)
+ {
+ err = grub_video_adapter_active->get_edid (edid_info);
+ if (err)
+ return err;
+ }
+
+ return GRUB_ERR_NONE;
+}
+
/* Determine optimized blitting formation for specified video mode info. */
enum grub_video_blit_format
grub_video_get_blit_format (struct grub_video_mode_info *mode_info)
Index: grub-2.12/include/grub/video.h
===================================================================
--- grub-2.12.orig/include/grub/video.h
+++ grub-2.12/include/grub/video.h
@@ -445,6 +445,8 @@ grub_err_t EXPORT_FUNC (grub_video_get_i
grub_err_t EXPORT_FUNC (grub_video_get_info_and_fini) (struct grub_video_mode_info *mode_info,
void **framebuffer);
+grub_err_t EXPORT_FUNC (grub_video_get_edid) (struct grub_video_edid_info *edid_info);
+
enum grub_video_blit_format EXPORT_FUNC(grub_video_get_blit_format) (struct grub_video_mode_info *mode_info);
grub_err_t grub_video_set_palette (unsigned int start, unsigned int count,
Index: grub-2.12/grub-core/loader/i386/linux.c
===================================================================
--- grub-2.12.orig/grub-core/loader/i386/linux.c
+++ grub-2.12/grub-core/loader/i386/linux.c
@@ -234,6 +234,7 @@ grub_e820_add_region (struct grub_e820_m
static grub_err_t
grub_linux_setup_video (struct linux_kernel_params *params)
{
+ struct grub_video_edid_info edid_info;
struct grub_video_mode_info mode_info;
void *framebuffer;
grub_err_t err;
@@ -245,6 +246,17 @@ grub_linux_setup_video (struct linux_ker
if (driver_id == GRUB_VIDEO_DRIVER_NONE)
return 1;
+ grub_video_get_edid (&edid_info); /* ignore errors */
+
+ /*
+ * We cannot transfer any extensions. Therefore clear
+ * the extension flag from the checksum and set the
+ * field to zero. Adding the extension flag to the
+ * checksum does the trick.
+ */
+ edid_info.checksum += edid_info.extension_flag;
+ edid_info.extension_flag = 0;
+
err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
if (err)
@@ -338,6 +350,17 @@ grub_linux_setup_video (struct linux_ker
}
#endif
+ if (grub_le_to_cpu16 (params->version) >= 0x0208)
+ {
+ grub_memcpy (params->v0208.edid_info, &edid_info,
+ sizeof (params->v0208.edid_info));
+ }
+ else if (grub_le_to_cpu16 (params->version) >= 0x0206)
+ {
+ grub_memcpy (params->v0206.edid_info, &edid_info,
+ sizeof (params->v0206.edid_info));
+ }
+
return GRUB_ERR_NONE;
}
Index: grub-2.12/include/grub/i386/linux.h
===================================================================
--- grub-2.12.orig/include/grub/i386/linux.h
+++ grub-2.12/include/grub/i386/linux.h
@@ -250,14 +250,15 @@ struct linux_kernel_params
grub_uint32_t ext_ramdisk_size; /* 0xc4 */
grub_uint32_t ext_cmd_line_ptr; /* 0xc8 */
- grub_uint8_t padding7[0x1b8 - 0xcc];
+ grub_uint8_t padding7[0x140 - 0xcc];
union
{
struct
{
+ grub_uint8_t padding7_1[0x1b8 - 0x140];
grub_uint32_t efi_system_table; /* 1b8 */
- grub_uint32_t padding7_1; /* 1bc */
+ grub_uint32_t padding7_2; /* 1bc */
grub_uint32_t efi_signature; /* 1c0 */
grub_uint32_t efi_mem_desc_size; /* 1c4 */
grub_uint32_t efi_mem_desc_version; /* 1c8 */
@@ -266,8 +267,7 @@ struct linux_kernel_params
} v0204;
struct
{
- grub_uint32_t padding7_1; /* 1b8 */
- grub_uint32_t padding7_2; /* 1bc */
+ grub_uint8_t edid_info[128]; /* 140 */
grub_uint32_t efi_signature; /* 1c0 */
grub_uint32_t efi_system_table; /* 1c4 */
grub_uint32_t efi_mem_desc_size; /* 1c8 */
@@ -277,8 +277,7 @@ struct linux_kernel_params
} v0206;
struct
{
- grub_uint32_t padding7_1; /* 1b8 */
- grub_uint32_t padding7_2; /* 1bc */
+ grub_uint8_t edid_info[128]; /* 140 */
grub_uint32_t efi_signature; /* 1c0 */
grub_uint32_t efi_system_table; /* 1c4 */
grub_uint32_t efi_mem_desc_size; /* 1c8 */