From 56d50ea2e8651020f3c02e4a153118aed11ac37f Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Thu, 21 Mar 2024 15:40:09 +0100 Subject: [PATCH] Implement EDID support for getting the preferred screen resolution --- sdk/xtdk/bltypes.h | 2 + xtldr/modules/framebuf/framebuf.c | 58 ++++++++++++++++++++++ xtldr/modules/framebuf/includes/framebuf.h | 5 ++ 3 files changed, 65 insertions(+) diff --git a/sdk/xtdk/bltypes.h b/sdk/xtdk/bltypes.h index 063ba79..86a767f 100644 --- a/sdk/xtdk/bltypes.h +++ b/sdk/xtdk/bltypes.h @@ -129,6 +129,7 @@ typedef EFI_STATUS (*PBL_EXECIMAGE_UNLOAD_IMAGE)(IN PVOID ImagePointer); typedef EFI_STATUS (*PBL_EXECIMAGE_VERIFY_IMAGE)(IN PVOID ImagePointer); typedef EFI_STATUS (*PBL_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PEFI_GRAPHICS_PROTOCOL Protocol); typedef EFI_STATUS (*PBL_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, OUT PULONG_PTR FrameBufferSize, OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo); +typedef EFI_STATUS (*PBL_FRAMEBUFFER_GET_PREFERRED_SCREEN_RESOLUTION)(OUT PUINT PreferredWidth, OUT PUINT PreferredHeight); typedef EFI_STATUS (*PBL_FRAMEBUFFER_INITIALIZE)(); typedef EFI_STATUS (*PBL_FRAMEBUFFER_SET_SCREEN_RESOLUTION)(IN UINT Width, IN UINT Height); @@ -334,6 +335,7 @@ typedef struct _XTBL_FRAMEBUFFER_PROTOCOL { PBL_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver; PBL_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation; + PBL_FRAMEBUFFER_GET_PREFERRED_SCREEN_RESOLUTION GetPreferredScreenResolution; PBL_FRAMEBUFFER_INITIALIZE Initialize; PBL_FRAMEBUFFER_SET_SCREEN_RESOLUTION SetScreenResolution; } XTBL_FRAMEBUFFER_PROTOCOL, *PXTBL_FRAMEBUFFER_PROTOCOL; diff --git a/xtldr/modules/framebuf/framebuf.c b/xtldr/modules/framebuf/framebuf.c index fda20b4..250e1c1 100644 --- a/xtldr/modules/framebuf/framebuf.c +++ b/xtldr/modules/framebuf/framebuf.c @@ -86,6 +86,63 @@ FbGetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, return STATUS_EFI_SUCCESS; } +/** + * Determines the preferred (native) screen resolution from EDID. This works only with GOP. + * + * @param PreferredWidth + * Supplies a pointer to the memory area where preferred screen width will be stored. + * + * @param PreferredHeight + * Supplies a pointer to the memory area where preferred screen height will be stored. + * + * @return This routine returns a status code. + * + * @since XT 1.0 + */ +XTCDECL +EFI_STATUS +FbGetPreferredScreenResolution(OUT PUINT PreferredWidth, + OUT PUINT PreferredHeight) +{ + EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GUID EdidGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID; + PEFI_EDID_ACTIVE_PROTOCOL ActiveEdid; + EFI_STATUS Status; + + /* Check if framebuffer is initialized */ + if(!FbpDisplayInfo.Initialized) + { + /* Framebuffer not ready to use EDID protocol */ + return STATUS_EFI_NOT_READY; + } + + /* Check if GOP device driver is used */ + if(FbpDisplayInfo.Protocol != GOP) + { + /* Unsupported device driver */ + return STATUS_EFI_UNSUPPORTED; + } + + /* Open EDID protocol */ + Status = XtLdrProtocol->Protocol.OpenHandle(FbpDisplayInfo.Handle, (PVOID *)&ActiveEdid, &EdidGuid); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to open EDID protocol, close GOP protocol and return */ + XtLdrProtocol->Protocol.Close(FbpDisplayInfo.Handle, &GopGuid); + return Status; + } + + /* Return preferred screen resolution */ + *PreferredWidth = ActiveEdid->Edid[0x38] | ((ActiveEdid->Edid[0x3A] & 0xF0) << 4); + *PreferredHeight = ActiveEdid->Edid[0x3B] | ((ActiveEdid->Edid[0x3D] & 0xF0) << 4); + + /* Close EDID & GOP protocols */ + XtLdrProtocol->Protocol.Close(FbpDisplayInfo.Handle, &EdidGuid); + + /* Return success */ + return STATUS_EFI_SUCCESS; +} + /** * Initializes FrameBuffer device on GOP and UGA compatible adapters. * @@ -717,6 +774,7 @@ XtLdrModuleMain(IN EFI_HANDLE ImageHandle, /* Set routines available via XTLDR framebuffer protocol */ FbpFrameBufferProtocol.GetDisplayDriver = FbGetDisplayDriver; FbpFrameBufferProtocol.GetDisplayInformation = FbGetDisplayInformation; + FbpFrameBufferProtocol.GetPreferredScreenResolution = FbGetPreferredScreenResolution; FbpFrameBufferProtocol.Initialize = FbInitializeDisplay; FbpFrameBufferProtocol.SetScreenResolution = FbSetScreenResolution; diff --git a/xtldr/modules/framebuf/includes/framebuf.h b/xtldr/modules/framebuf/includes/framebuf.h index f93605c..85bad6c 100644 --- a/xtldr/modules/framebuf/includes/framebuf.h +++ b/xtldr/modules/framebuf/includes/framebuf.h @@ -24,6 +24,11 @@ FbGetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase, OUT PULONG_PTR FrameBufferSize, OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo); +XTCDECL +EFI_STATUS +FbGetPreferredScreenResolution(OUT PUINT PreferredWidth, + OUT PUINT PreferredHeight); + XTCDECL EFI_STATUS FbInitializeDisplay();