From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.groups.io with SMTP id smtpd.web12.11112.1639665021451295719 for ; Thu, 16 Dec 2021 06:30:21 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=TAXs0CQK; spf=pass (domain: redhat.com, ip: 170.10.133.124, mailfrom: kraxel@redhat.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1639665020; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=A1KaT88KAlpjCuDeIP6Db2LxHrVFsHH5xzrt4ROtf1Q=; b=TAXs0CQKRKyIKD9apBfVLHT6oJUNcqfV/gSJiYCcexewBNtBbQExxT+rXHgFshOtrrS0/P 5hI5mCpniIai+ru45P+U2BV4vbYU5jIhRPqri3QW7aHUG0+b9wQfEuaWYNc2kZ++6SJnx1 YnDmYfYbhm4ZwpK11B0nzY17D9ACriQ= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-56-ls561-JhO7iG7P85oXJ04Q-1; Thu, 16 Dec 2021 09:30:15 -0500 X-MC-Unique: ls561-JhO7iG7P85oXJ04Q-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id CB98F10247AB; Thu, 16 Dec 2021 14:30:11 +0000 (UTC) Received: from sirius.home.kraxel.org (unknown [10.39.192.14]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 479AA4D73A; Thu, 16 Dec 2021 14:30:11 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 4A28E18003BC; Thu, 16 Dec 2021 15:29:59 +0100 (CET) From: "Gerd Hoffmann" To: devel@edk2.groups.io Cc: Erdem Aktas , Julien Grall , Brijesh Singh , Pawel Polawski , Min Xu , Jiewen Yao , Tom Lendacky , Ard Biesheuvel , Jordan Justen , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , James Bottomley , Anthony Perard , Gerd Hoffmann Subject: [PATCH 5/5] OvmfPkg/QemuVideoDxe: parse edid blob, detect display resolution Date: Thu, 16 Dec 2021 15:29:59 +0100 Message-Id: <20211216142959.1998191-6-kraxel@redhat.com> In-Reply-To: <20211216142959.1998191-1-kraxel@redhat.com> References: <20211216142959.1998191-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" 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 1024x768 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 --- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 3 + OvmfPkg/QemuVideoDxe/Qemu.h | 2 + OvmfPkg/QemuVideoDxe/Initialize.c | 102 +++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf index fe8befd51d3c..43a6e07faa88 100644 --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf @@ -63,4 +63,7 @@ [Protocols] [Pcd] gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId + gUefiOvmfPkgTokenSpaceGuid.PcdVideoResolutionSource gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 1e6507f44caa..57341a0bbfc4 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/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index 8c5c9176ad21..2a3cbc65c32a 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, -- 2.33.1