X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=OvmfPkg%2FQemuVideoDxe%2FGop.c;h=b479d24a87634a31c4d563dd542fa3ef637c7c8a;hp=d364630c47609407a1062d84a35557bea4570474;hb=81feb6d3059d6dfdfecd47f6b1f0c7d2b9f66e65;hpb=eaf4f336ea42dc32e1a5b31d6b7822c125a15d34 diff --git a/OvmfPkg/QemuVideoDxe/Gop.c b/OvmfPkg/QemuVideoDxe/Gop.c index d364630c47..b479d24a87 100644 --- a/OvmfPkg/QemuVideoDxe/Gop.c +++ b/OvmfPkg/QemuVideoDxe/Gop.c @@ -1,7 +1,7 @@ /** @file Graphics Output Protocol functions for the QEMU video controller. - Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2007 - 2018, 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 @@ -13,9 +13,8 @@ **/ +#include #include "Qemu.h" -#include -#include STATIC VOID @@ -70,11 +69,49 @@ QemuVideoCompleteModeData ( Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin; Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution; Mode->FrameBufferSize = Mode->FrameBufferSize * ((ModeData->ColorDepth + 7) / 8); - DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", Mode->FrameBufferBase, Mode->FrameBufferSize)); + DEBUG ((EFI_D_INFO, "FrameBufferBase: 0x%Lx, FrameBufferSize: 0x%Lx\n", + Mode->FrameBufferBase, (UINT64)Mode->FrameBufferSize)); + FreePool (FrameBufDesc); return EFI_SUCCESS; } +STATIC +EFI_STATUS +QemuVideoVmwareSvgaCompleteModeData ( + IN QEMU_VIDEO_PRIVATE_DATA *Private, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *FrameBufDesc; + UINT32 BytesPerLine, FbOffset, BytesPerPixel; + + Info = Mode->Info; + CopyMem (Info, &Private->VmwareSvgaModeInfo[Mode->Mode], sizeof (*Info)); + BytesPerPixel = Private->ModeData[Mode->Mode].ColorDepth / 8; + BytesPerLine = Info->PixelsPerScanLine * BytesPerPixel; + + FbOffset = VmwareSvgaRead (Private, VmwareSvgaRegFbOffset); + + Status = Private->PciIo->GetBarAttributes ( + Private->PciIo, + PCI_BAR_IDX1, + NULL, + (VOID**) &FrameBufDesc + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Mode->FrameBufferBase = FrameBufDesc->AddrRangeMin + FbOffset; + Mode->FrameBufferSize = BytesPerLine * Info->VerticalResolution; + + FreePool (FrameBufDesc); + return Status; +} + // // Graphics Output Protocol Member Functions @@ -113,10 +150,6 @@ Routine Description: Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); - if (Private->HardwareNeedsStarting) { - return EFI_NOT_STARTED; - } - if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { return EFI_INVALID_PARAMETER; } @@ -128,10 +161,14 @@ Routine Description: *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION); - ModeData = &Private->ModeData[ModeNumber]; - (*Info)->HorizontalResolution = ModeData->HorizontalResolution; - (*Info)->VerticalResolution = ModeData->VerticalResolution; - QemuVideoCompleteModeInfo (ModeData, *Info); + if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) { + CopyMem (*Info, &Private->VmwareSvgaModeInfo[ModeNumber], sizeof (**Info)); + } else { + ModeData = &Private->ModeData[ModeNumber]; + (*Info)->HorizontalResolution = ModeData->HorizontalResolution; + (*Info)->VerticalResolution = ModeData->VerticalResolution; + QemuVideoCompleteModeInfo (ModeData, *Info); + } return EFI_SUCCESS; } @@ -159,9 +196,10 @@ Routine Description: --*/ { - QEMU_VIDEO_PRIVATE_DATA *Private; - QEMU_VIDEO_MODE_DATA *ModeData; -// UINTN Count; + QEMU_VIDEO_PRIVATE_DATA *Private; + QEMU_VIDEO_MODE_DATA *ModeData; + RETURN_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); @@ -171,31 +209,83 @@ Routine Description: ModeData = &Private->ModeData[ModeNumber]; - if (Private->LineBuffer) { - gBS->FreePool (Private->LineBuffer); - } - - Private->LineBuffer = NULL; - Private->LineBuffer = AllocatePool (4 * ModeData->HorizontalResolution); - if (Private->LineBuffer == NULL) { - return EFI_OUT_OF_RESOURCES; + switch (Private->Variant) { + case QEMU_VIDEO_CIRRUS_5430: + case QEMU_VIDEO_CIRRUS_5446: + InitializeCirrusGraphicsMode (Private, &QemuVideoCirrusModes[ModeData->InternalModeIndex]); + break; + case QEMU_VIDEO_BOCHS_MMIO: + case QEMU_VIDEO_BOCHS: + InitializeBochsGraphicsMode (Private, &QemuVideoBochsModes[ModeData->InternalModeIndex]); + break; + case QEMU_VIDEO_VMWARE_SVGA: + InitializeVmwareSvgaGraphicsMode ( + Private, + &QemuVideoBochsModes[ModeData->InternalModeIndex] + ); + break; + default: + ASSERT (FALSE); + return EFI_DEVICE_ERROR; } - InitializeGraphicsMode (Private, &QemuVideoVideoModes[ModeData->ModeNumber]); - This->Mode->Mode = ModeNumber; This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution; 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_SVGA) { + QemuVideoVmwareSvgaCompleteModeData (Private, This->Mode); + } else { + QemuVideoCompleteModeData (Private, This->Mode); + } - BltLibConfigure ( - (VOID*)(UINTN) This->Mode->FrameBufferBase, - This->Mode->Info - ); + // + // Re-initialize the frame buffer configure when mode changes. + // + Status = FrameBufferBltConfigure ( + (VOID*) (UINTN) This->Mode->FrameBufferBase, + This->Mode->Info, + Private->FrameBufferBltConfigure, + &Private->FrameBufferBltConfigureSize + ); + if (Status == RETURN_BUFFER_TOO_SMALL) { + // + // Frame buffer configure may be larger in new mode. + // + if (Private->FrameBufferBltConfigure != NULL) { + FreePool (Private->FrameBufferBltConfigure); + } + Private->FrameBufferBltConfigure = + AllocatePool (Private->FrameBufferBltConfigureSize); + ASSERT (Private->FrameBufferBltConfigure != NULL); + + // + // Create the configuration for FrameBufferBltLib + // + Status = FrameBufferBltConfigure ( + (VOID*) (UINTN) This->Mode->FrameBufferBase, + This->Mode->Info, + Private->FrameBufferBltConfigure, + &Private->FrameBufferBltConfigureSize + ); + } + ASSERT (Status == RETURN_SUCCESS); - Private->HardwareNeedsStarting = FALSE; + // + // Per UEFI Spec, need to clear the visible portions of the output display to black. + // + ZeroMem (&Black, sizeof (Black)); + Status = FrameBufferBlt ( + Private->FrameBufferBltConfigure, + &Black, + EfiBltVideoFill, + 0, 0, + 0, 0, + This->Mode->Info->HorizontalResolution, This->Mode->Info->VerticalResolution, + 0 + ); + ASSERT_RETURN_ERROR (Status); return EFI_SUCCESS; } @@ -245,7 +335,9 @@ Returns: { EFI_STATUS Status; EFI_TPL OriginalTPL; + QEMU_VIDEO_PRIVATE_DATA *Private; + Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (This); // // We have to raise to TPL Notify, so we make an atomic write the frame buffer. // We would not want a timer based event (Cursor, ...) to come in while we are @@ -258,7 +350,8 @@ Returns: case EfiBltBufferToVideo: case EfiBltVideoFill: case EfiBltVideoToVideo: - Status = BltLibGopBlt ( + Status = FrameBufferBlt ( + Private->FrameBufferBltConfigure, BltBuffer, BltOperation, SourceX, @@ -306,23 +399,28 @@ QemuVideoGraphicsOutputConstructor ( if (EFI_ERROR (Status)) { return Status; } + Status = gBS->AllocatePool ( EfiBootServicesData, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), (VOID **) &Private->GraphicsOutput.Mode->Info ); if (EFI_ERROR (Status)) { - return Status; + goto FreeMode; } Private->GraphicsOutput.Mode->MaxMode = (UINT32) Private->MaxMode; Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER; - Private->HardwareNeedsStarting = TRUE; - Private->LineBuffer = NULL; + Private->FrameBufferBltConfigure = NULL; + Private->FrameBufferBltConfigureSize = 0; // // Initialize the hardware // - GraphicsOutput->SetMode (GraphicsOutput, 0); + Status = GraphicsOutput->SetMode (GraphicsOutput, 0); + if (EFI_ERROR (Status)) { + goto FreeInfo; + } + DrawLogo ( Private, Private->ModeData[Private->GraphicsOutput.Mode->Mode].HorizontalResolution, @@ -330,6 +428,15 @@ QemuVideoGraphicsOutputConstructor ( ); return EFI_SUCCESS; + +FreeInfo: + FreePool (Private->GraphicsOutput.Mode->Info); + +FreeMode: + FreePool (Private->GraphicsOutput.Mode); + Private->GraphicsOutput.Mode = NULL; + + return Status; } EFI_STATUS @@ -348,6 +455,10 @@ Returns: --*/ { + if (Private->FrameBufferBltConfigure != NULL) { + FreePool (Private->FrameBufferBltConfigure); + } + if (Private->GraphicsOutput.Mode != NULL) { if (Private->GraphicsOutput.Mode->Info != NULL) { gBS->FreePool (Private->GraphicsOutput.Mode->Info);