From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pg0-x241.google.com (mail-pg0-x241.google.com [IPv6:2607:f8b0:400e:c05::241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id D7FEC2041D9C9 for ; Wed, 29 Mar 2017 01:20:20 -0700 (PDT) Received: by mail-pg0-x241.google.com with SMTP id 81so1732950pgh.3 for ; Wed, 29 Mar 2017 01:20:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=philjordan-eu.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=HbpnHyQ3cI2hYwnPoovUPLzkm4GOgVF3kZmsI9s0DT0=; b=FJVKgAZeMx623pANd7TomOIsfJME+MGDrgU6oOHQhVfmHLDyPFIowHmvfGwvy+JyTV EZhVAClkFd8ZmA/jCHHYwYandK26N13mB7tCq21r40+yJk0c7NVCQ3hgGu/mV7X3csCF O2xBe/hWh7PkjI+dQEfW6fgzbr7KiQ9cYm3dahcbU6gxKEyZ2Ow/54XkNxBKCQItbwL+ lCBNj8KmT1Z8IzaMmJiezmr9CQR8qMpDBOzQn0zTruGv10zqTUoPQoy2GeSCtSVSfGJo 395P/ZJG99sQNt3LT0JFNz1x9uhHjUUg38z/kt3wSR8HLa6WmzbTF/mPvYxoBUVyI7bF IKOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=HbpnHyQ3cI2hYwnPoovUPLzkm4GOgVF3kZmsI9s0DT0=; b=fUrVsA+hE15zTu5pIVd5XQcX23ZvkKwkPOCghYn9AzSNlyBGBJ3ihpr0htG2RNn7dR Hwa4EN6G49ZTqCCAC9dqsrkpIIUH0gjDI4bciNHki6BfvZiTjnXpGS6tOjAJWZodZ/Ww cJHyuK+IivcITxA4u7dWfo/9xfNxxEEg32VXf5XzG2RLMQQ0gIMkKzsEoF54RtHT5QmV 1MVzajUcrAKQIz2U3jG6qBB64KYd3SBVeiB/IScVsPoFWELrkp8VrYrB5Fsm53egA0MP 8rT20VMnoguTRejG68OPv+AU57ygwZ2rg6Z0QiYhcOB2svn6RccnZ9P+jqkyswbKqd6J NSwQ== X-Gm-Message-State: AFeK/H38hfYWIQji1cujBiD8Oep2UZEOlY/cr1e8G4ITSQ2us2WZouezZSKueIEEwilAVw== X-Received: by 10.98.221.141 with SMTP id w135mr34878906pff.109.1490775619986; Wed, 29 Mar 2017 01:20:19 -0700 (PDT) Received: from localhost.localdomain ([118.82.182.58]) by smtp.gmail.com with ESMTPSA id v26sm11879729pfl.16.2017.03.29.01.20.16 (version=TLS1 cipher=AES128-SHA bits=128/128); Wed, 29 Mar 2017 01:20:19 -0700 (PDT) From: Phil Dennis-Jordan To: edk2-devel@lists.01.org Cc: Phil Dennis-Jordan , Jordan Justen , Laszlo Ersek Date: Wed, 29 Mar 2017 21:19:57 +1300 Message-Id: <1490775597-24007-3-git-send-email-lists@philjordan.eu> X-Mailer: git-send-email 2.3.2 (Apple Git-55) In-Reply-To: <1490775597-24007-1-git-send-email-lists@philjordan.eu> References: <1490775597-24007-1-git-send-email-lists@philjordan.eu> Subject: [RFC PATCH v1 2/2] OvmfPkg: Add VMWare SVGA II support in QemuVideoDxe. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 29 Mar 2017 08:20:21 -0000 From: Phil Dennis-Jordan In addition to the QXL, Cirrus, etc. VGA adapters, Qemu also implements a basic version of VMWare's SVGA2 display device. Drivers for this device exist for guest OSes which do not support Qemu's other display adapters, so supporting it in OVMF is useful in conjunction with those OSes. This change adds support for the SVGA2 device's framebuffer to QemuVideoDxe, based on VMWare's documentation. The most basic initialisation, framebuffer layout query, and mode setting are implemented. The device relies on port-based 32-bit I/O, unfortunately on misaligned addresses. This requires the addition of unaligned I/O helper functions for various compiler families, and limits the driver's support to the x86 family of platforms. Cc: Jordan Justen Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Phil Dennis-Jordan --- OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf | 6 ++ OvmfPkg/QemuVideoDxe/Qemu.h | 50 +++++++++++ OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h | 51 ++++++++++++ OvmfPkg/QemuVideoDxe/Driver.c | 67 +++++++++++++++ OvmfPkg/QemuVideoDxe/Gop.c | 71 +++++++++++++++- OvmfPkg/QemuVideoDxe/Initialize.c | 88 ++++++++++++++++++++ OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c | 59 +++++++++++++ OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c | 79 ++++++++++++++++++ OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c | 81 ++++++++++++++++++ OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c | 53 ++++++++++++ 10 files changed, 604 insertions(+), 1 deletion(-) diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf index affb6ffd88e0..346a5aed94fa 100644 --- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf +++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf @@ -41,6 +41,12 @@ [Sources.common] [Sources.Ia32, Sources.X64] VbeShim.c + UnalignedIoGcc.c | GCC + UnalignedIoMsc.c | MSFT + UnalignedIoIcc.c | INTEL + +[Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64] + UnalignedIoUnsupported.c [Packages] MdePkg/MdePkg.dec diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h index 2ce37defc5b8..7be2cac63130 100644 --- a/OvmfPkg/QemuVideoDxe/Qemu.h +++ b/OvmfPkg/QemuVideoDxe/Qemu.h @@ -56,6 +56,10 @@ typedef struct { UINT32 HorizontalResolution; UINT32 VerticalResolution; UINT32 ColorDepth; + // + // VMWare specific: + // + UINT32 PixelsPerLine; // includes any dead space } QEMU_VIDEO_MODE_DATA; #define PIXEL_RED_SHIFT 0 @@ -92,6 +96,7 @@ typedef enum { QEMU_VIDEO_CIRRUS_5446, QEMU_VIDEO_BOCHS, QEMU_VIDEO_BOCHS_MMIO, + QEMU_VIDEO_VMWARE_SVGA2, } QEMU_VIDEO_VARIANT; typedef struct { @@ -119,6 +124,8 @@ typedef struct { QEMU_VIDEO_VARIANT Variant; FRAME_BUFFER_CONFIGURE *FrameBufferBltConfigure; UINTN FrameBufferBltConfigureSize; + + UINT16 VMWareSVGA2_BasePort; } QEMU_VIDEO_PRIVATE_DATA; /// @@ -459,6 +466,13 @@ outw ( UINT16 Data ); +VOID +outl ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINTN Address, + UINT32 Data + ); + UINT8 inb ( QEMU_VIDEO_PRIVATE_DATA *Private, @@ -471,6 +485,12 @@ inw ( UINTN Address ); +UINT32 +inl ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINTN Address + ); + VOID BochsWrite ( QEMU_VIDEO_PRIVATE_DATA *Private, @@ -502,9 +522,39 @@ QemuVideoBochsModeSetup ( BOOLEAN IsQxl ); +EFI_STATUS +QemuVideoVmwareModeSetup ( + QEMU_VIDEO_PRIVATE_DATA *Private + ); + VOID InstallVbeShim ( IN CONST CHAR16 *CardName, IN EFI_PHYSICAL_ADDRESS FrameBufferBase ); + +VOID +QemuVideoVMWSVGA2RegisterWrite ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 reg, + UINT32 value + ); + +UINT32 +QemuVideoVMWSVGA2RegisterRead ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 reg + ); + +EFI_STATUS +QemuVideoVMWSVGA2CompleteModeData ( + IN QEMU_VIDEO_PRIVATE_DATA *Private, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode + ); + +void InitializeVMWSVGA2GraphicsMode ( + QEMU_VIDEO_PRIVATE_DATA *Private, + QEMU_VIDEO_BOCHS_MODES *ModeData + ); + #endif diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h new file mode 100644 index 000000000000..1b9f71afb6db --- /dev/null +++ b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h @@ -0,0 +1,51 @@ +/** @file + Unaligned port I/O, with implementations for various x86 compilers and a dummy + for platforms which do not support unaligned port I/O. + + Copyright (c) 2017, Phil Dennis-Jordan.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _UNALIGNED_IO_INTERNAL_H_ +#define _UNALIGNED_IO_INTERNAL_H_ + +/** + Performs a 32-bit write to the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port address + @param[in] Value 32-bit word to write + + @return The value written to the I/O port. + +**/ +UINT32 +UnalignedIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ); + +/** + Reads 32-bit word from the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port from which to read. + + @return The value read from the specified location. + +**/ +UINT32 +UnalignedIoRead32 ( + IN UINTN Port + ); + +#endif diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index fc8025ec46de..84caf1672675 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -15,6 +15,7 @@ **/ #include "Qemu.h" +#include "svga_reg.h" #include EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { @@ -58,6 +59,16 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = { QEMU_VIDEO_BOCHS_MMIO, L"QEMU VirtIO VGA" },{ +#if defined MDE_CPU_IA32 || defined MDE_CPU_X64 + // + // Support only platforms which can do unaligned port I/O + // + PCI_VENDOR_ID_VMWARE, + PCI_DEVICE_ID_VMWARE_SVGA2, + QEMU_VIDEO_VMWARE_SVGA2, + L"QEMU VMWare SVGA2" + },{ +#endif 0 /* end of list */ } }; @@ -317,6 +328,41 @@ QemuVideoControllerDriverStart ( } // + // Check if accessing VMWARE_SVGA2 interface works + // + if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) { + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *iodesc; + UINT32 TargetId; + UINT32 Svga2IDRead; + + Private->PciIo->GetBarAttributes ( + Private->PciIo, + PCI_BAR_IDX0, + NULL, + (VOID**) &iodesc + ); + Private->VMWareSVGA2_BasePort = iodesc->AddrRangeMin; + + TargetId = SVGA_ID_2; + while (1) { + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ID, TargetId); + Svga2IDRead = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_ID); + if ((Svga2IDRead == TargetId) || (TargetId <= SVGA_ID_0)) { + break; + } + --TargetId; + } + + if (Svga2IDRead != TargetId) { + DEBUG ((DEBUG_ERROR, "QemuVideo: QEMU_VIDEO_VMWARE_SVGA2 ID mismatch" + " (got 0x%x, base address 0x%x)\n", + Svga2IDRead, Private->VMWareSVGA2_BasePort)); + Status = EFI_DEVICE_ERROR; + goto RestoreAttributes; + } + } + + // // Get ParentDevicePath // Status = gBS->HandleProtocol ( @@ -371,6 +417,9 @@ QemuVideoControllerDriverStart ( case QEMU_VIDEO_BOCHS: Status = QemuVideoBochsModeSetup (Private, IsQxl); break; + case QEMU_VIDEO_VMWARE_SVGA2: + Status = QemuVideoVmwareModeSetup (Private); + break; default: ASSERT (FALSE); Status = EFI_DEVICE_ERROR; @@ -975,3 +1024,21 @@ InitializeQemuVideo ( return Status; } + +void InitializeVMWSVGA2GraphicsMode ( + QEMU_VIDEO_PRIVATE_DATA *Private, + QEMU_VIDEO_BOCHS_MODES *ModeData + ) +{ + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_WIDTH, ModeData->Width); + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_HEIGHT, ModeData->Height); + + UINT32 capabilities = QemuVideoVMWSVGA2RegisterRead ( + Private, SVGA_REG_CAPABILITIES); + if ((capabilities & SVGA_CAP_8BIT_EMULATION) != 0) { + QemuVideoVMWSVGA2RegisterWrite( + Private, SVGA_REG_BITS_PER_PIXEL, ModeData->ColorDepth); + } + SetDefaultPalette (Private); + ClearScreen (Private); +} diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c index 359e9217d3d1..05c571b78aa7 100644 --- a/OvmfPkg/QemuVideoDxe/Gop.c +++ b/OvmfPkg/QemuVideoDxe/Gop.c @@ -14,6 +14,7 @@ **/ #include "Qemu.h" +#include "svga_reg.h" STATIC VOID @@ -76,6 +77,63 @@ QemuVideoCompleteModeData ( } +EFI_STATUS +QemuVMSVGA2VideoCompleteModeData ( + IN QEMU_VIDEO_PRIVATE_DATA *Private, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode + ) +{ + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc; + UINT32 RedMask, GreenMask, BlueMask; + UINT32 BitsPerPixel, BytesPerLine, FBOffset; + + Info = Mode->Info; + Info->Version = 0; + Info->PixelFormat = PixelBitMask; + + RedMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_RED_MASK); + Info->PixelInformation.RedMask = RedMask; + + GreenMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_GREEN_MASK); + Info->PixelInformation.GreenMask = GreenMask; + + BlueMask = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BLUE_MASK); + Info->PixelInformation.BlueMask = BlueMask; + + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ENABLE, 1); + + FBOffset = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_FB_OFFSET); + BytesPerLine = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BYTES_PER_LINE); + BitsPerPixel = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BITS_PER_PIXEL); + + if (BitsPerPixel == 32) { + if (BlueMask == 0xff && GreenMask == 0xff00 && RedMask == 0xff0000) { + Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor; + } else if (BlueMask == 0xff0000 && GreenMask == 0xff00 && RedMask == 0xff) { + Info->PixelFormat = PixelRedGreenBlueReserved8BitPerColor; + } + } + + Info->PixelInformation.ReservedMask = ((0x2u << (BitsPerPixel - 1u)) - 1u) + & ~(RedMask | GreenMask | BlueMask); + Info->PixelsPerScanLine = BytesPerLine / (BitsPerPixel / 8); + + Private->PciIo->GetBarAttributes ( + Private->PciIo, + PCI_BAR_IDX1, + NULL, + (VOID**) &FrameBufDesc + ); + + Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FBOffset; + Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution; + + FreePool (FrameBufDesc); + return EFI_SUCCESS; +} + + // // Graphics Output Protocol Member Functions // @@ -129,6 +187,10 @@ Routine Description: (*Info)->VerticalResolution = ModeData->VerticalResolution; QemuVideoCompleteModeInfo (ModeData, *Info); + if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) { + (*Info)->PixelsPerScanLine = ModeData->PixelsPerLine; + } + return EFI_SUCCESS; } @@ -176,6 +238,9 @@ Routine Description: case QEMU_VIDEO_BOCHS: InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); break; + case QEMU_VIDEO_VMWARE_SVGA2: + InitializeVMWSVGA2GraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); + break; default: ASSERT (FALSE); return EFI_DEVICE_ERROR; @@ -186,7 +251,11 @@ Routine Description: This->Mode->Info->VerticalResolution = ModeData->VerticalResolution; This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); - QemuVideoCompleteModeData (Private, This->Mode); + if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA2) { + QemuVMSVGA2VideoCompleteModeData(Private, This->Mode); + } else { + QemuVideoCompleteModeData (Private, This->Mode); + } // // Re-initialize the frame buffer configure when mode changes. diff --git a/OvmfPkg/QemuVideoDxe/Initialize.c b/OvmfPkg/QemuVideoDxe/Initialize.c index d5d8cfef9661..a33d178b2d42 100644 --- a/OvmfPkg/QemuVideoDxe/Initialize.c +++ b/OvmfPkg/QemuVideoDxe/Initialize.c @@ -14,6 +14,8 @@ **/ #include "Qemu.h" +#include "svga_reg.h" +#include "UnalignedIoInternal.h" /// @@ -346,3 +348,89 @@ QemuVideoBochsModeSetup ( return EFI_SUCCESS; } +VOID +QemuVideoVMWSVGA2RegisterWrite ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 reg, + UINT32 value + ) +{ + UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_INDEX_PORT, reg); + UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_VALUE_PORT, value); +} + +UINT32 +QemuVideoVMWSVGA2RegisterRead ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 reg + ) +{ + UnalignedIoWrite32 (Private->VMWareSVGA2_BasePort + SVGA_INDEX_PORT, reg); + return UnalignedIoRead32 (Private->VMWareSVGA2_BasePort + SVGA_VALUE_PORT); +} + +EFI_STATUS +QemuVideoVmwareModeSetup ( + QEMU_VIDEO_PRIVATE_DATA *Private + ) +{ + UINT32 FBSize; + UINT32 MaxWidth, MaxHeight; + UINT32 Capabilities; + UINT32 HostBitsPerPixel; + UINT32 Index; + QEMU_VIDEO_MODE_DATA *ModeData; + QEMU_VIDEO_BOCHS_MODES *VideoMode; + + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_ENABLE, 0); + + Private->ModeData = + AllocatePool (sizeof (Private->ModeData[0]) * QEMU_VIDEO_BOCHS_MODE_COUNT); + if (Private->ModeData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FBSize = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_FB_SIZE); + MaxWidth = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_MAX_WIDTH); + MaxHeight = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_MAX_HEIGHT); + Capabilities = QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_CAPABILITIES); + if ((Capabilities & SVGA_CAP_8BIT_EMULATION) != 0) { + HostBitsPerPixel = + QemuVideoVMWSVGA2RegisterRead(Private, SVGA_REG_HOST_BITS_PER_PIXEL); + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_BITS_PER_PIXEL, HostBitsPerPixel); + } else { + HostBitsPerPixel = QemuVideoVMWSVGA2RegisterRead(Private, SVGA_REG_BITS_PER_PIXEL); + } + + ModeData = Private->ModeData; + VideoMode = &QemuVideoBochsModes[0]; + for (Index = 0; Index < QEMU_VIDEO_BOCHS_MODE_COUNT; Index ++) { + UINTN RequiredFbSize; + + ASSERT (HostBitsPerPixel % 8 == 0); + RequiredFbSize = (UINTN) VideoMode->Width * VideoMode->Height * + (HostBitsPerPixel / 8); + if (RequiredFbSize <= FBSize + && VideoMode->Width <= MaxWidth + && VideoMode->Height <= MaxHeight) + { + UINT32 BytesPerLine; + + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_WIDTH, VideoMode->Width); + QemuVideoVMWSVGA2RegisterWrite (Private, SVGA_REG_HEIGHT, VideoMode->Height); + BytesPerLine = + QemuVideoVMWSVGA2RegisterRead (Private, SVGA_REG_BYTES_PER_LINE); + ModeData->PixelsPerLine = BytesPerLine / (HostBitsPerPixel / 8); + + ModeData->InternalModeIndex = Index; + ModeData->HorizontalResolution = VideoMode->Width; + ModeData->VerticalResolution = VideoMode->Height; + ModeData->ColorDepth = HostBitsPerPixel; + + ModeData ++; + } + VideoMode ++; + } + Private->MaxMode = ModeData - Private->ModeData; + return EFI_SUCCESS; +} diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c new file mode 100644 index 000000000000..55e283b392e9 --- /dev/null +++ b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c @@ -0,0 +1,59 @@ +/** @file + Unaligned Port I/O. This file has compiler specifics for GCC as there is no + ANSI C standard for doing IO. + + Based on IoLibGcc.c. + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "UnalignedIoInternal.h" + +/** + Reads 32-bit word from the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port from which to read. + + @return The value read from the specified location. +**/ +UINT32 +UnalignedIoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + __asm__ __volatile__ ( "inl %1, %0" : "=a"(Data) : "Nd"((UINT16)Port) ); + return Data; +} + +/** + Performs a 32-bit write to the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port address + @param[in] Value 32-bit word to write + + @return The value written to the I/O port. + +**/ +UINT32 +UnalignedIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + __asm__ __volatile__ ( "outl %0, %1" : : "a"(Value), "Nd"((UINT16)Port) ); + return Value; +} diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c new file mode 100644 index 000000000000..cc2274462db9 --- /dev/null +++ b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c @@ -0,0 +1,79 @@ +/** @file + Unaligned port I/O. This file has compiler specifics for ICC as there + is no ANSI C standard for doing IO. + + Based on IoLibIcc.c. + + Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are + licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "UnalignedIoInternal.h" + +/** + Reads 32-bit word from the specified, possibly unaligned I/O-type address. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +UnalignedIoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + + __asm { + mov dx, word ptr [Port] + in eax, dx + mov dword ptr [Data], eax + } + + return Data; +} + +/** + Performs a 32-bit write to the specified, possibly unaligned I/O-type address. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +UnalignedIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + __asm { + mov eax, dword ptr [Value] + mov dx, word ptr [Port] + out dx, eax + } + + return Value; +} diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c new file mode 100644 index 000000000000..436ff39da253 --- /dev/null +++ b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c @@ -0,0 +1,81 @@ +/** @file + Unaligned port I/O. This file has compiler specifics for Microsoft C as there + is no ANSI C standard for doing IO. + + Based on IoLibMsc.c + + Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "UnalignedIoInternal.h" + +unsigned long _inpd (unsigned short port); +unsigned long _outpd (unsigned short port, unsigned long dataword ); +void _ReadWriteBarrier (void); + +/** + Reads 32-bit word from the specified, possibly unaligned I/O-type address. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +UnalignedIoRead32 ( + IN UINTN Port + ) +{ + UINT32 Value; + + _ReadWriteBarrier (); + Value = _inpd ((UINT16)Port); + _ReadWriteBarrier (); + return Value; +} + +/** + Performs a 32-bit write to the specified, possibly unaligned I/O-type address. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If Port is not aligned on a 32-bit boundary, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written to the I/O port. + +**/ +UINT32 +EFIAPI +UnalignedIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + _ReadWriteBarrier (); + _outpd ((UINT16)Port, Value); + _ReadWriteBarrier (); + return Value; +} diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c new file mode 100644 index 000000000000..20b185869ef5 --- /dev/null +++ b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c @@ -0,0 +1,53 @@ +/** @file + Unaligned port I/O dummy implementation for platforms which do not support it. + + Copyright (c) 2017, Phil Dennis-Jordan.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + + +#include "UnalignedIoInternal.h" + +/** + Reads 32-bit word from the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port from which to read. + + @return The value read from the specified location. +**/ +UINT32 +UnalignedIoRead32 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); +} + +/** + Performs a 32-bit write to the specified, possibly unaligned I/O-type address. + + If 32-bit unaligned I/O port operations are not supported, then ASSERT(). + + @param[in] Port I/O port address + @param[in] Value 32-bit word to write + + @return The value written to the I/O port. + +**/ +UINT32 +UnalignedIoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT (FALSE); +} -- 2.3.2 (Apple Git-55)