diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2022-01-17 10:58:17 +0100 |
---|---|---|
committer | mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> | 2022-01-29 17:04:21 +0000 |
commit | 49a2d8cbf5191efd5c2709acd1a1e64f0d9599de (patch) | |
tree | af663fd0537dd257b588779478f1a3edf16682cc | |
parent | 55c05427b90230f15f4807a4daa2876e5e2f4998 (diff) | |
download | edk2-49a2d8cbf5191efd5c2709acd1a1e64f0d9599de.tar.gz edk2-49a2d8cbf5191efd5c2709acd1a1e64f0d9599de.tar.bz2 edk2-49a2d8cbf5191efd5c2709acd1a1e64f0d9599de.zip |
OvmfPkg/QemuVideoDxe: parse edid blob, detect display resolution
Check whenever an EDID blob is present. In case it is get the display
resolution from it. Unless PcdVideoResolutionSource indicates the
display resolution has been set already, update
PcdVideoHorizontalResolution and PcdVideoVerticalResolution accordingly.
Also add the resolution to the mode list.
This will make OVMF boot up with the display resolution configured by
QEMU, which is 1280x800 by default. The resolution can be set using the
xres and yres properties. Here is an example for FullHD:
qemu-system-x86_64 -device VGA,xres=1920,yres=1080
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3778
Ref: https://bugzilla.redhat.com/show_bug.cgi?id=1749250
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
-rw-r--r-- | OvmfPkg/QemuVideoDxe/Initialize.c | 102 | ||||
-rw-r--r-- | OvmfPkg/QemuVideoDxe/Qemu.h | 2 | ||||
-rw-r--r-- | OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 3 |
3 files changed, 105 insertions, 2 deletions
diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index 8c5c9176ad..2a3cbc65c3 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -284,6 +284,88 @@ QemuVideoBochsAddMode ( Private->MaxMode++;
}
+STATIC
+VOID
+QemuVideoBochsEdid (
+ QEMU_VIDEO_PRIVATE_DATA *Private,
+ UINT32 *XRes,
+ UINT32 *YRes
+ )
+{
+ EFI_STATUS Status;
+
+ if (Private->Variant != QEMU_VIDEO_BOCHS_MMIO) {
+ return;
+ }
+
+ Status = Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BAR_IDX2,
+ 0,
+ sizeof (Private->Edid),
+ Private->Edid
+ );
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: mmio read failed\n",
+ __FUNCTION__
+ ));
+ return;
+ }
+
+ if ((Private->Edid[0] != 0x00) ||
+ (Private->Edid[1] != 0xff))
+ {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: magic check failed\n",
+ __FUNCTION__
+ ));
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: blob found (extensions: %d)\n",
+ __FUNCTION__,
+ Private->Edid[126]
+ ));
+
+ if ((Private->Edid[54] == 0x00) &&
+ (Private->Edid[55] == 0x00))
+ {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: no detailed timing descriptor\n",
+ __FUNCTION__
+ ));
+ return;
+ }
+
+ *XRes = Private->Edid[56] | ((Private->Edid[58] & 0xf0) << 4);
+ *YRes = Private->Edid[59] | ((Private->Edid[61] & 0xf0) << 4);
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: default resolution: %dx%d\n",
+ __FUNCTION__,
+ *XRes,
+ *YRes
+ ));
+
+ if (PcdGet8 (PcdVideoResolutionSource) == 0) {
+ Status = PcdSet32S (PcdVideoHorizontalResolution, *XRes);
+ ASSERT_RETURN_ERROR (Status);
+ Status = PcdSet32S (PcdVideoVerticalResolution, *YRes);
+ ASSERT_RETURN_ERROR (Status);
+ Status = PcdSet8S (PcdVideoResolutionSource, 2);
+ ASSERT_RETURN_ERROR (Status);
+ }
+
+ // TODO: register edid as gEfiEdidDiscoveredProtocolGuid ?
+}
+
EFI_STATUS
QemuVideoBochsModeSetup (
QEMU_VIDEO_PRIVATE_DATA *Private,
@@ -291,7 +373,7 @@ QemuVideoBochsModeSetup ( )
{
UINT32 AvailableFbSize;
- UINT32 Index;
+ UINT32 Index, XRes = 0, YRes = 0;
//
// Fetch the available framebuffer size.
@@ -374,13 +456,29 @@ QemuVideoBochsModeSetup ( // Setup Video Modes
//
Private->ModeData = AllocatePool (
- sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT
+ sizeof (Private->ModeData[0]) * (QEMU_VIDEO_BOCHS_MODE_COUNT+1)
);
if (Private->ModeData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+ QemuVideoBochsEdid (Private, &XRes, &YRes);
+ if (XRes && YRes) {
+ QemuVideoBochsAddMode (
+ Private,
+ AvailableFbSize,
+ XRes,
+ YRes
+ );
+ }
+
for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index++) {
+ if ((QemuVideoBochsModes[Index].Width == XRes) &&
+ (QemuVideoBochsModes[Index].Height == YRes))
+ {
+ continue; // duplicate with edid resolution
+ }
+
QemuVideoBochsAddMode (
Private,
AvailableFbSize,
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 1e6507f44c..57341a0bbf 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -115,6 +115,8 @@ typedef struct { FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure;
UINTN FrameBufferBltConfigureSize;
UINT8 FrameBufferVramBarIndex;
+
+ UINT8 Edid[128];
} QEMU_VIDEO_PRIVATE_DATA;
///
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf index fe8befd51d..43a6e07faa 100644 --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf @@ -63,4 +63,7 @@ [Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+ gUefiOvmfPkgTokenSpaceGuid.PcdVideoResolutionSource
gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
|