X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FQemuVideoDxe%2FDriver.c;h=508e1acb1018becf6715400f0677857c0c1b8e2f;hb=42d0cad751d610a8e6680ffd468fc40c970e96c0;hp=04f73f3ba1d335a06cba3ead8a87855da829269b;hpb=54f9b9accbcb6dc7f965342fc75b478464de21a3;p=mirror_edk2.git diff --git a/OvmfPkg/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c index 04f73f3ba1..508e1acb10 100644 --- a/OvmfPkg/QemuVideoDxe/Driver.c +++ b/OvmfPkg/QemuVideoDxe/Driver.c @@ -15,6 +15,7 @@ **/ #include "Qemu.h" +#include EFI_DRIVER_BINDING_PROTOCOL gQemuVideoDriverBinding = { QemuVideoControllerDriverSupported, @@ -44,7 +45,7 @@ QEMU_VIDEO_CARD gQemuVideoCardList[] = { },{ 0x1234, 0x1111, - QEMU_VIDEO_BOCHS, + QEMU_VIDEO_BOCHS_MMIO, L"QEMU Standard VGA" },{ 0x1b36, @@ -96,7 +97,6 @@ QemuVideoControllerDriverSupported ( EFI_STATUS Status; EFI_PCI_IO_PROTOCOL *PciIo; PCI_TYPE00 Pci; - EFI_DEV_PATH *Node; QEMU_VIDEO_CARD *Card; // @@ -129,40 +129,10 @@ 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 - // Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId); if (Card != NULL) { DEBUG ((EFI_D_INFO, "QemuVideo: %s detected\n", Card->Name)); 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; - } - } - } } Done: @@ -200,29 +170,26 @@ QemuVideoControllerDriverStart ( 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; - PCI_TYPE00 Pci; - QEMU_VIDEO_CARD *Card; + EFI_STATUS Status; + QEMU_VIDEO_PRIVATE_DATA *Private; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + ACPI_ADR_DEVICE_PATH AcpiDeviceNode; + PCI_TYPE00 Pci; + QEMU_VIDEO_CARD *Card; + EFI_PCI_IO_PROTOCOL *ChildPciIo; - PciAttributesSaved = FALSE; // // Allocate Private context data for GOP inteface. // Private = AllocateZeroPool (sizeof (QEMU_VIDEO_PRIVATE_DATA)); if (Private == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Error; + return EFI_OUT_OF_RESOURCES; } // // Set up context record // Private->Signature = QEMU_VIDEO_PRIVATE_DATA_SIGNATURE; - Private->Handle = NULL; // // Open PCI I/O Protocol @@ -236,7 +203,7 @@ QemuVideoControllerDriverStart ( EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { - goto Error; + goto FreePrivate; } // @@ -250,13 +217,16 @@ QemuVideoControllerDriverStart ( &Pci ); if (EFI_ERROR (Status)) { - goto Error; + goto ClosePciIo; } + // + // Determine card variant. + // Card = QemuVideoDetect(Pci.Hdr.VendorId, Pci.Hdr.DeviceId); if (Card == NULL) { Status = EFI_DEVICE_ERROR; - goto Error; + goto ClosePciIo; } Private->Variant = Card->Variant; @@ -271,10 +241,12 @@ QemuVideoControllerDriverStart ( ); if (EFI_ERROR (Status)) { - goto Error; + goto ClosePciIo; } - PciAttributesSaved = TRUE; + // + // Set new PCI attributes + // Status = Private->PciIo->Attributes ( Private->PciIo, EfiPciIoAttributeOperationEnable, @@ -282,19 +254,46 @@ QemuVideoControllerDriverStart ( NULL ); if (EFI_ERROR (Status)) { - goto Error; + 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 ((EFI_D_INFO, "QemuVideo: No mmio bar, fallback to port io\n")); + Private->Variant = QEMU_VIDEO_BOCHS; + } else { + DEBUG ((EFI_D_INFO, "QemuVideo: Using mmio bar @ 0x%lx\n", + MmioDesc->AddrRangeMin)); + } + + if (!EFI_ERROR (Status)) { + FreePool (MmioDesc); + } } // // Check if accessing the bochs interface works. // - if (Private->Variant == QEMU_VIDEO_BOCHS) { + 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 ((EFI_D_INFO, "QemuVideo: BochsID mismatch (got 0x%x)\n", BochsId)); Status = EFI_DEVICE_ERROR; - goto Error; + goto RestoreAttributes; } } @@ -307,48 +306,38 @@ QemuVideoControllerDriverStart ( (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; } // @@ -359,6 +348,7 @@ QemuVideoControllerDriverStart ( case QEMU_VIDEO_CIRRUS_5446: Status = QemuVideoCirrusModeSetup (Private); break; + case QEMU_VIDEO_BOCHS_MMIO: case QEMU_VIDEO_BOCHS: Status = QemuVideoBochsModeSetup (Private); break; @@ -368,61 +358,72 @@ QemuVideoControllerDriverStart ( break; } if (EFI_ERROR (Status)) { - goto Error; + goto UninstallGopDevicePath; } - 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 { - - // - // Start the GOP software stack. - // - Status = QemuVideoGraphicsOutputConstructor (Private); - ASSERT_EFI_ERROR (Status); - - Status = gBS->InstallMultipleProtocolInterfaces ( - &Private->Handle, - &gEfiGraphicsOutputProtocolGuid, - &Private->GraphicsOutput, - NULL - ); + // + // Start the GOP software stack. + // + Status = QemuVideoGraphicsOutputConstructor (Private); + if (EFI_ERROR (Status)) { + goto FreeModeData; } -Error: + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiGraphicsOutputProtocolGuid, + &Private->GraphicsOutput, + NULL + ); 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 DestructQemuVideoGraphics; + } - gBS->FreePool (Private); - } + // + // 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)) { + goto UninstallGop; } + 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); + return Status; } @@ -505,6 +506,13 @@ QemuVideoControllerDriverStop ( Controller ); + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->Handle + ); + // // Free our instance data // @@ -644,10 +652,10 @@ SetPaletteColor ( 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)); } /** @@ -791,8 +799,22 @@ BochsWrite ( UINT16 Data ) { - outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); - outw (Private, VBE_DISPI_IOPORT_DATA, 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 @@ -801,13 +823,50 @@ BochsRead ( UINT16 Reg ) { - UINT16 Data; - - outw (Private, VBE_DISPI_IOPORT_INDEX, Reg); - Data = inw (Private, VBE_DISPI_IOPORT_DATA); + 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); + } +} + VOID InitializeBochsGraphicsMode ( QEMU_VIDEO_PRIVATE_DATA *Private, @@ -818,7 +877,7 @@ InitializeBochsGraphicsMode ( ModeData->Width, ModeData->Height, ModeData->ColorDepth)); /* unblank */ - outb (Private, ATT_ADDRESS_REGISTER, 0x20); + VgaOutb (Private, ATT_ADDRESS_REGISTER, 0x20); BochsWrite (Private, VBE_DISPI_INDEX_ENABLE, 0); BochsWrite (Private, VBE_DISPI_INDEX_BANK, 0);