X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FQemuVideoDxe%2FDriver.c;h=b91909a14e590b262d520e4383b02820109313a9;hb=HEAD;hp=cb3e34970dc0e1efe7f9d449230d150a1758ed8e;hpb=eaf4f336ea42dc32e1a5b31d6b7822c125a15d34;p=mirror_edk2.git diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index cb3e34970d..c28171d137 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -2,21 +2,16 @@ This driver is a sample implementation of the Graphics Output Protocol for the QEMU (Cirrus Logic 5446) video controller. - Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2006 - 2019, 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. + SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Qemu.h" +#include -EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { +EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { QemuVideoControllerDriverSupported, QemuVideoControllerDriverStart, QemuVideoControllerDriverStop, @@ -25,6 +20,83 @@ EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { NULL }; +QEMU_VIDEO_CARD gQemuVideoCardList[] = { + { + PCI_CLASS_DISPLAY_VGA, + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5430_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5430, + L"Cirrus 5430" + },{ + PCI_CLASS_DISPLAY_VGA, + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5430, + L"Cirrus 5430" + },{ + PCI_CLASS_DISPLAY_VGA, + CIRRUS_LOGIC_VENDOR_ID, + CIRRUS_LOGIC_5446_DEVICE_ID, + QEMU_VIDEO_CIRRUS_5446, + L"Cirrus 5446" + },{ + PCI_CLASS_DISPLAY_VGA, + 0x1234, + 0x1111, + QEMU_VIDEO_BOCHS_MMIO, + L"QEMU Standard VGA" + },{ + PCI_CLASS_DISPLAY_OTHER, + 0x1234, + 0x1111, + QEMU_VIDEO_BOCHS_MMIO, + L"QEMU Standard VGA (secondary)" + },{ + PCI_CLASS_DISPLAY_VGA, + 0x1b36, + 0x0100, + QEMU_VIDEO_BOCHS, + L"QEMU QXL VGA" + },{ + PCI_CLASS_DISPLAY_VGA, + 0x1af4, + 0x1050, + QEMU_VIDEO_BOCHS_MMIO, + L"QEMU VirtIO VGA" + },{ + PCI_CLASS_DISPLAY_VGA, + 0x15ad, + 0x0405, + QEMU_VIDEO_VMWARE_SVGA, + L"QEMU VMWare SVGA" + },{ + 0 /* end of list */ + } +}; + +static QEMU_VIDEO_CARD * +QemuVideoDetect ( + IN UINT8 SubClass, + IN UINT16 VendorId, + IN UINT16 DeviceId + ) +{ + UINTN Index = 0; + + while (gQemuVideoCardList[Index].VendorId != 0) { + if ((gQemuVideoCardList[Index].SubClass == SubClass) && + (gQemuVideoCardList[Index].VendorId == VendorId) && + (gQemuVideoCardList[Index].DeviceId == DeviceId)) + { + return gQemuVideoCardList + Index; + } + + Index++; + } + + return NULL; +} + /** Check if this device is supported. @@ -39,15 +111,15 @@ EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { EFI_STATUS EFIAPI QemuVideoControllerDriverSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - PCI_TYPE00 Pci; - EFI_DEV_PATH *Node; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + QEMU_VIDEO_CARD *Card; // // Open the PCI I/O Protocol @@ -55,7 +127,7 @@ QemuVideoControllerDriverSupported ( Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, + (VOID **)&PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER @@ -79,46 +151,14 @@ QemuVideoControllerDriverSupported ( } Status = EFI_UNSUPPORTED; - // - // See if the I/O enable is on. Most systems only allow one VGA device to be turned on - // at a time, so see if this is one that is turned on. - // - // if (((Pci.Hdr.Command & 0x01) == 0x01)) { - // - // See if this is a Cirrus Logic PCI controller - // - if (Pci.Hdr.VendorId == CIRRUS_LOGIC_VENDOR_ID) { - // - // See if this is a 5430 or a 5446 PCI controller - // - if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_DEVICE_ID || - Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID || - Pci.Hdr.DeviceId == CIRRUS_LOGIC_5446_DEVICE_ID) { - - Status = EFI_SUCCESS; - // - // If this is an Intel 945 graphics controller, - // go further check RemainingDevicePath validation - // - if (RemainingDevicePath != NULL) { - Node = (EFI_DEV_PATH *) RemainingDevicePath; - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, return EFI_SUCCESS - // - if (!IsDevicePathEnd (Node)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - if (Node->DevPath.Type != ACPI_DEVICE_PATH || - Node->DevPath.SubType != ACPI_ADR_DP || - DevicePathNodeLength(&Node->DevPath) != sizeof(ACPI_ADR_DEVICE_PATH)) { - Status = EFI_UNSUPPORTED; - } - } - } - } + if (!IS_PCI_DISPLAY (&Pci)) { + goto Done; + } + + Card = QemuVideoDetect (Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId); + if (Card != NULL) { + DEBUG ((DEBUG_INFO, "QemuVideo: %s detected\n", Card->Name)); + Status = EFI_SUCCESS; } Done: @@ -126,11 +166,11 @@ Done: // Close the PCI I/O Protocol // gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); return Status; } @@ -151,32 +191,37 @@ Done: EFI_STATUS EFIAPI QemuVideoControllerDriverStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { - EFI_STATUS Status; - QEMU_VIDEO_PRIVATE_DATA *Private; - BOOLEAN PciAttributesSaved; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + EFI_TPL OldTpl; + EFI_STATUS Status; + QEMU_VIDEO_PRIVATE_DATA *Private; + BOOLEAN IsQxl; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + PCI_TYPE00 Pci; + QEMU_VIDEO_CARD *Card; + EFI_PCI_IO_PROTOCOL *ChildPciIo; + UINT64 SupportedVgaIo; + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - PciAttributesSaved = FALSE; // - // Allocate Private context data for GOP inteface. + // Allocate Private context data for GOP interface. // Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA)); if (Private == NULL) { Status = EFI_OUT_OF_RESOURCES; - goto Error; + goto RestoreTpl; } // // Set up context record // - Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE; - Private->Handle = NULL; + Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE; // // Open PCI I/O Protocol @@ -184,38 +229,143 @@ QemuVideoControllerDriverStart ( Status = gBS->OpenProtocol ( Controller, &gEfiPciIoProtocolGuid, - (VOID **) &Private->PciIo, + (VOID **)&Private->PciIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { - goto Error; + goto FreePrivate; } + // + // Read the PCI Configuration Header from the PCI Device + // + Status = Private->PciIo->Pci.Read ( + Private->PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + goto ClosePciIo; + } + + // + // Determine card variant. + // + Card = QemuVideoDetect (Pci.Hdr.ClassCode[1], Pci.Hdr.VendorId, Pci.Hdr.DeviceId); + if (Card == NULL) { + Status = EFI_DEVICE_ERROR; + goto ClosePciIo; + } + + Private->Variant = Card->Variant; + + // + // IsQxl is based on the detected Card->Variant, which at a later point might + // not match Private->Variant. + // + IsQxl = (BOOLEAN)(Card->Variant == QEMU_VIDEO_BOCHS); + // // Save original PCI attributes // Status = Private->PciIo->Attributes ( - Private->PciIo, - EfiPciIoAttributeOperationGet, - 0, - &Private->OriginalPciAttributes - ); + Private->PciIo, + EfiPciIoAttributeOperationGet, + 0, + &Private->OriginalPciAttributes + ); if (EFI_ERROR (Status)) { - goto Error; + goto ClosePciIo; } - PciAttributesSaved = TRUE; + // + // Get supported PCI attributes + // Status = Private->PciIo->Attributes ( - Private->PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, - NULL - ); + Private->PciIo, + EfiPciIoAttributeOperationSupported, + 0, + &SupportedVgaIo + ); if (EFI_ERROR (Status)) { - goto Error; + goto ClosePciIo; + } + + SupportedVgaIo &= (UINT64)(EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_VGA_IO_16); + if ((SupportedVgaIo == 0) && IS_PCI_VGA (&Pci)) { + Status = EFI_UNSUPPORTED; + goto ClosePciIo; + } + + // + // Set new PCI attributes + // + Status = Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | SupportedVgaIo, + NULL + ); + if (EFI_ERROR (Status)) { + goto ClosePciIo; + } + + // + // Check whenever the qemu stdvga mmio bar is present (qemu 1.3+). + // + if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) { + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc; + + Status = Private->PciIo->GetBarAttributes ( + Private->PciIo, + PCI_BAR_IDX2, + NULL, + (VOID **)&MmioDesc + ); + if (EFI_ERROR (Status) || + (MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM)) + { + DEBUG ((DEBUG_INFO, "QemuVideo: No mmio bar, fallback to port io\n")); + Private->Variant = QEMU_VIDEO_BOCHS; + } else { + DEBUG (( + DEBUG_INFO, + "QemuVideo: Using mmio bar @ 0x%lx\n", + MmioDesc->AddrRangeMin + )); + } + + if (!EFI_ERROR (Status)) { + FreePool (MmioDesc); + } + } + + // + // VMWare SVGA is handled like Bochs (with port IO only). + // + if (Private->Variant == QEMU_VIDEO_VMWARE_SVGA) { + Private->Variant = QEMU_VIDEO_BOCHS; + Private->FrameBufferVramBarIndex = PCI_BAR_IDX1; + } + + // + // Check if accessing the bochs interface works. + // + if ((Private->Variant == QEMU_VIDEO_BOCHS_MMIO) || + (Private->Variant == QEMU_VIDEO_BOCHS)) + { + UINT16 BochsId; + BochsId = BochsRead (Private, VBE_DISPI_INDEX_ID); + if ((BochsId & 0xFFF0) != VBE_DISPI_ID0) { + DEBUG ((DEBUG_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId)); + Status = EFI_DEVICE_ERROR; + goto RestoreAttributes; + } } // @@ -224,113 +374,155 @@ QemuVideoControllerDriverStart ( Status = gBS->HandleProtocol ( Controller, &gEfiDevicePathProtocolGuid, - (VOID **) &ParentDevicePath + (VOID **)&ParentDevicePath ); if (EFI_ERROR (Status)) { - goto Error; + goto RestoreAttributes; } // // Set Gop Device Path // - if (RemainingDevicePath == NULL) { - ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); - AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; - AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; - AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); - SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); - - Private->GopDevicePath = AppendDevicePathNode ( - ParentDevicePath, - (EFI_DEVICE_PATH_PROTOCOL *) &AcpiDeviceNode - ); - } else if (!IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // only scan the specified device by RemainingDevicePath - // - Private->GopDevicePath = AppendDevicePathNode (ParentDevicePath, RemainingDevicePath); - } else { - // - // If RemainingDevicePath is the End of Device Path Node, - // don't create child device and return EFI_SUCCESS - // - Private->GopDevicePath = NULL; + ZeroMem (&AcpiDeviceNode, sizeof (ACPI_ADR_DEVICE_PATH)); + AcpiDeviceNode.Header.Type = ACPI_DEVICE_PATH; + AcpiDeviceNode.Header.SubType = ACPI_ADR_DP; + AcpiDeviceNode.ADR = ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0); + SetDevicePathNodeLength (&AcpiDeviceNode.Header, sizeof (ACPI_ADR_DEVICE_PATH)); + + Private->GopDevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&AcpiDeviceNode + ); + if (Private->GopDevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RestoreAttributes; } - - if (Private->GopDevicePath != NULL) { - // - // Creat child handle and device path protocol firstly - // - Private->Handle = NULL; - Status = gBS->InstallMultipleProtocolInterfaces ( - &Private->Handle, - &gEfiDevicePathProtocolGuid, - Private->GopDevicePath, - NULL - ); + + // + // Create new child handle and install the device path protocol on it. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->GopDevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto FreeGopDevicePath; } // // Construct video mode buffer // - Status = QemuVideoVideoModeSetup (Private); - if (EFI_ERROR (Status)) { - goto Error; + switch (Private->Variant) { + case QEMU_VIDEO_CIRRUS_5430: + case QEMU_VIDEO_CIRRUS_5446: + Status = QemuVideoCirrusModeSetup (Private); + break; + case QEMU_VIDEO_BOCHS_MMIO: + case QEMU_VIDEO_BOCHS: + Status = QemuVideoBochsModeSetup (Private, IsQxl); + break; + default: + ASSERT (FALSE); + Status = EFI_DEVICE_ERROR; + break; } - if (Private->GopDevicePath == NULL) { - // - // If RemainingDevicePath is the End of Device Path Node, - // don't create child device and return EFI_SUCCESS - // - Status = EFI_SUCCESS; - } else { + if (EFI_ERROR (Status)) { + goto UninstallGopDevicePath; + } - // - // Start the GOP software stack. - // - Status = QemuVideoGraphicsOutputConstructor (Private); - ASSERT_EFI_ERROR (Status); + // + // Start the GOP software stack. + // + Status = QemuVideoGraphicsOutputConstructor (Private); + if (EFI_ERROR (Status)) { + goto FreeModeData; + } - Status = gBS->InstallMultipleProtocolInterfaces ( - &Private->Handle, - &gEfiGraphicsOutputProtocolGuid, - &Private->GraphicsOutput, - NULL - ); + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput, + NULL + ); + if (EFI_ERROR (Status)) { + goto DestructQemuVideoGraphics; } -Error: + // + // Reference parent handle from child handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **)&ChildPciIo, + This->DriverBindingHandle, + Private->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); if (EFI_ERROR (Status)) { - if (Private) { - if (Private->PciIo) { - if (PciAttributesSaved == TRUE) { - // - // Restore original PCI attributes - // - Private->PciIo->Attributes ( - Private->PciIo, - EfiPciIoAttributeOperationSet, - Private->OriginalPciAttributes, - NULL - ); - } - // - // Close the PCI I/O Protocol - // - gBS->CloseProtocol ( - Private->Handle, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Private->Handle - ); - } + goto UninstallGop; + } - gBS->FreePool (Private); - } + #if defined MDE_CPU_IA32 || defined MDE_CPU_X64 + if ((Private->Variant == QEMU_VIDEO_BOCHS_MMIO) || + (Private->Variant == QEMU_VIDEO_BOCHS)) + { + InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase); } + #endif + + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; + +UninstallGop: + gBS->UninstallProtocolInterface ( + Private->Handle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput + ); + +DestructQemuVideoGraphics: + QemuVideoGraphicsOutputDestructor (Private); + +FreeModeData: + FreePool (Private->ModeData); + +UninstallGopDevicePath: + gBS->UninstallProtocolInterface ( + Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->GopDevicePath + ); + +FreeGopDevicePath: + FreePool (Private->GopDevicePath); + +RestoreAttributes: + Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationSet, + Private->OriginalPciAttributes, + NULL + ); + +ClosePciIo: + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + +FreePrivate: + FreePool (Private); + +RestoreTpl: + gBS->RestoreTPL (OldTpl); + return Status; } @@ -350,21 +542,39 @@ Error: EFI_STATUS EFIAPI QemuVideoControllerDriverStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer ) { - EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; + EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; - EFI_STATUS Status; + EFI_STATUS Status; QEMU_VIDEO_PRIVATE_DATA *Private; + if (NumberOfChildren == 0) { + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + } + + // + // free all resources for whose access we need the child handle, because the + // child handle is going away + // + ASSERT (NumberOfChildren == 1); Status = gBS->OpenProtocol ( - Controller, + ChildHandleBuffer[0], &gEfiGraphicsOutputProtocolGuid, - (VOID **) &GraphicsOutput, + (VOID **)&GraphicsOutput, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL @@ -377,6 +587,7 @@ QemuVideoControllerDriverStop ( // Get our private context information // Private = QEMU_VIDEO_PRIVATE_DATA_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput); + ASSERT (Private->Handle == ChildHandleBuffer[0]); QemuVideoGraphicsOutputDestructor (Private); // @@ -397,21 +608,26 @@ QemuVideoControllerDriverStop ( // Restore original PCI attributes // Private->PciIo->Attributes ( - Private->PciIo, - EfiPciIoAttributeOperationSet, - Private->OriginalPciAttributes, - NULL - ); + Private->PciIo, + EfiPciIoAttributeOperationSet, + Private->OriginalPciAttributes, + NULL + ); - // - // Close the PCI I/O Protocol - // gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->Handle + ); + + FreePool (Private->ModeData); + gBS->UninstallProtocolInterface ( + Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->GopDevicePath + ); + FreePool (Private->GopDevicePath); // // Free our instance data @@ -434,18 +650,18 @@ QemuVideoControllerDriverStop ( VOID outb ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN Address, - UINT8 Data + UINTN Address, + UINT8 Data ) { Private->PciIo->Io.Write ( - Private->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - Address, - 1, - &Data - ); + Private->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); } /** @@ -461,18 +677,18 @@ outb ( VOID outw ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN Address, - UINT16 Data + UINTN Address, + UINT16 Data ) { Private->PciIo->Io.Write ( - Private->PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - Address, - 1, - &Data - ); + Private->PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); } /** @@ -487,19 +703,19 @@ outw ( UINT8 inb ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN Address + UINTN Address ) { - UINT8 Data; + UINT8 Data; Private->PciIo->Io.Read ( - Private->PciIo, - EfiPciIoWidthUint8, - EFI_PCI_IO_PASS_THROUGH_BAR, - Address, - 1, - &Data - ); + Private->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); return Data; } @@ -515,19 +731,19 @@ inb ( UINT16 inw ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN Address + UINTN Address ) { UINT16 Data; Private->PciIo->Io.Read ( - Private->PciIo, - EfiPciIoWidthUint16, - EFI_PCI_IO_PASS_THROUGH_BAR, - Address, - 1, - &Data - ); + Private->PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); return Data; } @@ -546,16 +762,16 @@ inw ( VOID SetPaletteColor ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN Index, - UINT8 Red, - UINT8 Green, - UINT8 Blue + UINTN Index, + UINT8 Red, + UINT8 Green, + UINT8 Blue ) { - outb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index); - outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2)); - outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2)); - outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2)); + VgaOutb (Private, PALETTE_INDEX_REGISTER, (UINT8)Index); + VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Red >> 2)); + VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Green >> 2)); + VgaOutb (Private, PALETTE_DATA_REGISTER, (UINT8)(Blue >> 2)); } /** @@ -571,16 +787,16 @@ SetDefaultPalette ( QEMU_VIDEO_PRIVATE_DATA *Private ) { - UINTN Index; - UINTN RedIndex; - UINTN GreenIndex; - UINTN BlueIndex; + UINTN Index; + UINTN RedIndex; + UINTN GreenIndex; + UINTN BlueIndex; Index = 0; for (RedIndex = 0; RedIndex < 8; RedIndex++) { for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) { for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) { - SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6)); + SetPaletteColor (Private, Index, (UINT8)(RedIndex << 5), (UINT8)(GreenIndex << 5), (UINT8)(BlueIndex << 6)); Index++; } } @@ -606,7 +822,7 @@ ClearScreen ( Private->PciIo->Mem.Write ( Private->PciIo, EfiPciIoWidthFillUint32, - 0, + Private->FrameBufferVramBarIndex, 0, 0x400000 >> 2, &Color @@ -624,8 +840,8 @@ ClearScreen ( VOID DrawLogo ( QEMU_VIDEO_PRIVATE_DATA *Private, - UINTN ScreenWidth, - UINTN ScreenHeight + UINTN ScreenWidth, + UINTN ScreenHeight ) { } @@ -640,27 +856,13 @@ DrawLogo ( **/ VOID -InitializeGraphicsMode ( +InitializeCirrusGraphicsMode ( QEMU_VIDEO_PRIVATE_DATA *Private, - QEMU_VIDEO_VIDEO_MODES *ModeData + QEMU_VIDEO_CIRRUS_MODES *ModeData ) { - UINT8 Byte; - UINTN Index; - UINT16 DeviceId; - EFI_STATUS Status; - - Status = Private->PciIo->Pci.Read ( - Private->PciIo, - EfiPciIoWidthUint16, - PCI_DEVICE_ID_OFFSET, - 1, - &DeviceId - ); - // - // Read the PCI Configuration Header from the PCI Device - // - ASSERT_EFI_ERROR (Status); + UINT8 Byte; + UINTN Index; outw (Private, SEQ_ADDRESS_REGISTER, 0x1206); outw (Private, SEQ_ADDRESS_REGISTER, 0x0012); @@ -669,9 +871,9 @@ InitializeGraphicsMode ( outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]); } - if (DeviceId != CIRRUS_LOGIC_5446_DEVICE_ID) { + if (Private->Variant == QEMU_VIDEO_CIRRUS_5430) { outb (Private, SEQ_ADDRESS_REGISTER, 0x0f); - Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30); + Byte = (UINT8)((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30); outb (Private, SEQ_DATA_REGISTER, Byte); } @@ -681,17 +883,17 @@ InitializeGraphicsMode ( outw (Private, CRTC_ADDRESS_REGISTER, 0x2011); for (Index = 0; Index < 28; Index++) { - outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index)); + outw (Private, CRTC_ADDRESS_REGISTER, (UINT16)((ModeData->CrtcSettings[Index] << 8) | Index)); } for (Index = 0; Index < 9; Index++) { - outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16)((GraphicsController[Index] << 8) | Index)); } inb (Private, INPUT_STATUS_1_REGISTER); for (Index = 0; Index < 21; Index++) { - outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index); + outb (Private, ATT_ADDRESS_REGISTER, (UINT8)Index); outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]); } @@ -706,14 +908,160 @@ InitializeGraphicsMode ( ClearScreen (Private); } +VOID +BochsWrite ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg, + UINT16 Data + ) +{ + EFI_STATUS Status; + + if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) { + Status = Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthUint16, + PCI_BAR_IDX2, + 0x500 + (Reg << 1), + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); + } else { + outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); + outw (Private, VBE_DISPI_IOPORT_DATA, Data); + } +} + +UINT16 +BochsRead ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINT16 Reg + ) +{ + EFI_STATUS Status; + UINT16 Data; + + if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) { + Status = Private->PciIo->Mem.Read ( + Private->PciIo, + EfiPciIoWidthUint16, + PCI_BAR_IDX2, + 0x500 + (Reg << 1), + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); + } else { + outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); + Data = inw (Private, VBE_DISPI_IOPORT_DATA); + } + + return Data; +} + +VOID +VgaOutb ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINTN Reg, + UINT8 Data + ) +{ + EFI_STATUS Status; + + if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) { + Status = Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthUint8, + PCI_BAR_IDX2, + 0x400 - 0x3c0 + Reg, + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); + } else { + outb (Private, Reg, Data); + } +} + +STATIC +UINT8 +VgaInb ( + QEMU_VIDEO_PRIVATE_DATA *Private, + UINTN Reg + ) +{ + EFI_STATUS Status; + UINT8 Data; + + if (Private->Variant == QEMU_VIDEO_BOCHS_MMIO) { + Data = 0; + Status = Private->PciIo->Mem.Read ( + Private->PciIo, + EfiPciIoWidthUint8, + PCI_BAR_IDX2, + 0x400 - 0x3c0 + Reg, + 1, + &Data + ); + ASSERT_EFI_ERROR (Status); + } else { + Data = inb (Private, Reg); + } + + return Data; +} + +VOID +InitializeBochsGraphicsMode ( + QEMU_VIDEO_PRIVATE_DATA *Private, + QEMU_VIDEO_MODE_DATA *ModeData + ) +{ + DEBUG (( + DEBUG_INFO, + "InitializeBochsGraphicsMode: %dx%d @ %d\n", + ModeData->HorizontalResolution, + ModeData->VerticalResolution, + ModeData->ColorDepth + )); + + /* set color mode */ + VgaOutb (Private, MISC_OUTPUT_REGISTER, 0x01); + + /* reset flip flop + unblank */ + VgaInb (Private, INPUT_STATUS_1_REGISTER); + VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20); + + BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0); + BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0); + BochsWrite (Private, VBE_DISPI_INDEX_X_OFFSET, 0); + BochsWrite (Private, VBE_DISPI_INDEX_Y_OFFSET, 0); + + BochsWrite (Private, VBE_DISPI_INDEX_BPP, (UINT16)ModeData->ColorDepth); + BochsWrite (Private, VBE_DISPI_INDEX_XRES, (UINT16)ModeData->HorizontalResolution); + BochsWrite (Private, VBE_DISPI_INDEX_VIRT_WIDTH, (UINT16)ModeData->HorizontalResolution); + BochsWrite (Private, VBE_DISPI_INDEX_YRES, (UINT16)ModeData->VerticalResolution); + BochsWrite (Private, VBE_DISPI_INDEX_VIRT_HEIGHT, (UINT16)ModeData->VerticalResolution); + + BochsWrite ( + Private, + VBE_DISPI_INDEX_ENABLE, + VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED + ); + + SetDefaultPalette (Private); + ClearScreen (Private); +} + EFI_STATUS EFIAPI InitializeQemuVideo ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, @@ -725,18 +1073,5 @@ InitializeQemuVideo ( ); ASSERT_EFI_ERROR (Status); - // - // Install EFI Driver Supported EFI Version Protocol required for - // EFI drivers that are on PCI and other plug in cards. - // - gQemuVideoDriverSupportedEfiVersion.FirmwareVersion = PcdGet32 (PcdDriverSupportedEfiVersion); - Status = gBS->InstallMultipleProtocolInterfaces ( - &ImageHandle, - &gEfiDriverSupportedEfiVersionProtocolGuid, - &gQemuVideoDriverSupportedEfiVersion, - NULL - ); - ASSERT_EFI_ERROR (Status); - return Status; }