diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c | 739 |
1 files changed, 739 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c new file mode 100644 index 00000000..8529ebaf --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutput.c @@ -0,0 +1,739 @@ +/** @file + Implementation for a generic GOP driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ + +#include "GraphicsOutput.h" +CONST ACPI_ADR_DEVICE_PATH mGraphicsOutputAdrNode = { + { + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + { sizeof (ACPI_ADR_DEVICE_PATH), 0 }, + }, + ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 0, 0) +}; + +EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = { + MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8 +}; + +// +// The driver should only start on one graphics controller. +// So a global flag is used to remember that the driver is already started. +// +BOOLEAN mDriverStarted = FALSE; + +/** + Returns information for an available graphics mode that the graphics device + and the set of active video output devices supports. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Valid mode information was returned. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_INVALID_PARAMETER ModeNumber is not valid. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputQueryMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +{ + if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + + *SizeOfInfo = This->Mode->SizeOfInfo; + *Info = AllocateCopyPool (*SizeOfInfo, This->Mode->Info); + return EFI_SUCCESS; +} + +/** + Set the video device into the specified mode and clears the visible portions of + the output display to black. + + @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance. + @param ModeNumber Abstraction that defines the current video mode. + + @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputSetMode ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber +) +{ + RETURN_STATUS Status; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + + Black.Blue = 0; + Black.Green = 0; + Black.Red = 0; + Black.Reserved = 0; + + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + &Black, + EfiBltVideoFill, + 0, 0, + 0, 0, + This->Mode->Info->HorizontalResolution, + This->Mode->Info->VerticalResolution, + 0 + ); + return RETURN_ERROR (Status) ? EFI_DEVICE_ERROR : EFI_SUCCESS; +} + +/** + Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer. + + @param This Protocol instance pointer. + @param BltBuffer The data to transfer to the graphics screen. + Size is at least Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL). + @param BltOperation The operation to perform when copying BltBuffer on to the graphics screen. + @param SourceX The X coordinate of source for the BltOperation. + @param SourceY The Y coordinate of source for the BltOperation. + @param DestinationX The X coordinate of destination for the BltOperation. + @param DestinationY The Y coordinate of destination for the BltOperation. + @param Width The width of a rectangle in the blt rectangle in pixels. + @param Height The height of a rectangle in the blt rectangle in pixels. + @param Delta Not used for EfiBltVideoFill or the EfiBltVideoToVideo operation. + If a Delta of zero is used, the entire BltBuffer is being operated on. + If a subrectangle of the BltBuffer is being used then Delta + represents the number of bytes in a row of the BltBuffer. + + @retval EFI_SUCCESS BltBuffer was drawn to the graphics screen. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + +**/ +EFI_STATUS +EFIAPI +GraphicsOutputBlt ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + RETURN_STATUS Status; + EFI_TPL Tpl; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (This); + // + // We have to raise to TPL_NOTIFY, so we make an atomic write to the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + Tpl = gBS->RaiseTPL (TPL_NOTIFY); + Status = FrameBufferBlt ( + Private->FrameBufferBltLibConfigure, + BltBuffer, + BltOperation, + SourceX, SourceY, + DestinationX, DestinationY, Width, Height, + Delta + ); + gBS->RestoreTPL (Tpl); + + return RETURN_ERROR (Status) ? EFI_INVALID_PARAMETER : EFI_SUCCESS; +} + +CONST GRAPHICS_OUTPUT_PRIVATE_DATA mGraphicsOutputInstanceTemplate = { + GRAPHICS_OUTPUT_PRIVATE_DATA_SIGNATURE, // Signature + NULL, // GraphicsOutputHandle + { + GraphicsOutputQueryMode, + GraphicsOutputSetMode, + GraphicsOutputBlt, + NULL // Mode + }, + { + 1, // MaxMode + 0, // Mode + NULL, // Info + sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION), // SizeOfInfo + 0, // FrameBufferBase + 0 // FrameBufferSize + }, + NULL, // DevicePath + NULL, // PciIo + 0, // PciAttributes + NULL, // FrameBufferBltLibConfigure + 0 // FrameBufferBltLibConfigureSize +}; + +/** + Test whether the Controller can be managed by the driver. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver can manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Since there is only one GraphicsInfo HOB, the driver only manages one video device. + // + if (mDriverStarted) { + return EFI_ALREADY_STARTED; + } + + // + // Test the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Test the DevicePath protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + if (EFI_ERROR (Status)) { + return Status; + } + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if ((RemainingDevicePath == NULL) || + IsDevicePathEnd (RemainingDevicePath) || + CompareMem (RemainingDevicePath, &mGraphicsOutputAdrNode, sizeof (mGraphicsOutputAdrNode)) == 0) { + return EFI_SUCCESS; + } else { + return EFI_INVALID_PARAMETER; + } +} + +/** + Start the video controller. + + @param This Driver Binding protocol instance pointer. + @param ControllerHandle The PCI controller. + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS The driver starts to manage the video device. + @retval other The driver cannot manage the video device. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + RETURN_STATUS ReturnStatus; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH *PciDevicePath; + PCI_TYPE00 Pci; + UINT8 Index; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources; + VOID *HobStart; + EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; + EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *DeviceInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + + FrameBufferBase = 0; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + ASSERT ((HobStart != NULL) && (GET_GUID_HOB_DATA_SIZE (HobStart) == sizeof (EFI_PEI_GRAPHICS_INFO_HOB))); + GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + + HobStart = GetFirstGuidHob (&gEfiGraphicsDeviceInfoHobGuid); + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (*DeviceInfo))) { + // + // Use default device infomation when the device info HOB doesn't exist + // + DeviceInfo = &mDefaultGraphicsDeviceInfo; + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB doesn't exist!\n", gEfiCallerBaseName)); + } else { + DeviceInfo = (EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *) (GET_GUID_HOB_DATA (HobStart)); + DEBUG ((DEBUG_INFO, "[%a]: GraphicsDeviceInfo HOB:\n" + " VendorId = %04x, DeviceId = %04x,\n" + " RevisionId = %02x, BarIndex = %x,\n" + " SubsystemVendorId = %04x, SubsystemId = %04x\n", + gEfiCallerBaseName, + DeviceInfo->VendorId, DeviceInfo->DeviceId, + DeviceInfo->RevisionId, DeviceInfo->BarIndex, + DeviceInfo->SubsystemVendorId, DeviceInfo->SubsystemId)); + } + + // + // Open the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &PciDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + Status = EFI_SUCCESS; + } + ASSERT_EFI_ERROR (Status); + + // + // Read the PCI Class Code from the PCI Device + // + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (Pci), &Pci); + if (!EFI_ERROR (Status)) { + if (!IS_PCI_DISPLAY (&Pci) || ( + ((DeviceInfo->VendorId != MAX_UINT16) && (DeviceInfo->VendorId != Pci.Hdr.VendorId)) || + ((DeviceInfo->DeviceId != MAX_UINT16) && (DeviceInfo->DeviceId != Pci.Hdr.DeviceId)) || + ((DeviceInfo->RevisionId != MAX_UINT8) && (DeviceInfo->RevisionId != Pci.Hdr.RevisionID)) || + ((DeviceInfo->SubsystemVendorId != MAX_UINT16) && (DeviceInfo->SubsystemVendorId != Pci.Device.SubsystemVendorID)) || + ((DeviceInfo->SubsystemId != MAX_UINT16) && (DeviceInfo->SubsystemId != Pci.Device.SubsystemID)) + ) + ) { + // + // It's not a video device, or device infomation doesn't match. + // + Status = EFI_UNSUPPORTED; + } else { + // + // If it's a video device and device information matches, use the BarIndex + // from device information, or any BAR if BarIndex is not specified + // whose size >= the frame buffer size from GraphicsInfo HOB. + // Store the new frame buffer base. + // + for (Index = 0; Index < MAX_PCI_BAR; Index++) { + if ((DeviceInfo->BarIndex != MAX_UINT8) && (DeviceInfo->BarIndex != Index)) { + continue; + } + Status = PciIo->GetBarAttributes (PciIo, Index, NULL, (VOID**) &Resources); + if (!EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "[%a]: BAR[%d]: Base = %lx, Length = %lx\n", + gEfiCallerBaseName, Index, Resources->AddrRangeMin, Resources->AddrLen)); + if ((Resources->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && + (Resources->Len == (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3)) && + (Resources->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && + (Resources->AddrLen >= GraphicsInfo->FrameBufferSize) + ) { + if (FrameBufferBase == 0) { + FrameBufferBase = Resources->AddrRangeMin; + } + if (DeviceInfo->BarIndex == MAX_UINT8) { + if (Resources->AddrRangeMin == GraphicsInfo->FrameBufferBase) { + FrameBufferBase = Resources->AddrRangeMin; + break; + } + } else { + break; + } + } + } + } + if (Index == MAX_PCI_BAR) { + Status = EFI_UNSUPPORTED; + } else { + DEBUG ((DEBUG_INFO, "[%a]: ... matched!\n", gEfiCallerBaseName)); + } + } + } + + if (EFI_ERROR (Status)) { + goto CloseProtocols; + } + + if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + + Private = AllocateCopyPool (sizeof (mGraphicsOutputInstanceTemplate), &mGraphicsOutputInstanceTemplate); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CloseProtocols; + } + + Private->GraphicsOutputMode.FrameBufferBase = FrameBufferBase; + Private->GraphicsOutputMode.FrameBufferSize = GraphicsInfo->FrameBufferSize; + Private->GraphicsOutputMode.Info = &GraphicsInfo->GraphicsMode; + + // + // Fix up Mode pointer in GraphicsOutput + // + Private->GraphicsOutput.Mode = &Private->GraphicsOutputMode; + + // + // Set attributes + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationGet, + 0, + &Private->PciAttributes + ); + if (!EFI_ERROR (Status)) { + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + if (EFI_ERROR (Status)) { + goto FreeMemory; + } + + // + // Create the FrameBufferBltLib configuration. + // + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + if (ReturnStatus == RETURN_BUFFER_TOO_SMALL) { + Private->FrameBufferBltLibConfigure = AllocatePool (Private->FrameBufferBltLibConfigureSize); + if (Private->FrameBufferBltLibConfigure != NULL) { + ReturnStatus = FrameBufferBltConfigure ( + (VOID *) (UINTN) Private->GraphicsOutput.Mode->FrameBufferBase, + Private->GraphicsOutput.Mode->Info, + Private->FrameBufferBltLibConfigure, + &Private->FrameBufferBltLibConfigureSize + ); + } + } + if (RETURN_ERROR (ReturnStatus)) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Private->DevicePath = AppendDevicePathNode (PciDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &mGraphicsOutputAdrNode); + if (Private->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto RestorePciAttributes; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + + if (!EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (!EFI_ERROR (Status)) { + mDriverStarted = TRUE; + } else { + gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + } + } + +RestorePciAttributes: + if (EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + } + +FreeMemory: + if (EFI_ERROR (Status)) { + if (Private != NULL) { + if (Private->DevicePath != NULL) { + FreePool (Private->DevicePath); + } + if (Private->FrameBufferBltLibConfigure != NULL) { + FreePool (Private->FrameBufferBltLibConfigure); + } + FreePool (Private); + } + } + +CloseProtocols: + if (EFI_ERROR (Status)) { + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + return Status; +} + +/** + Stop the video controller. + + @param This Driver Binding protocol instance pointer. + @param Controller The PCI controller. + @param NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. +**/ +EFI_STATUS +EFIAPI +GraphicsOutputDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop; + GRAPHICS_OUTPUT_PRIVATE_DATA *Private; + + if (NumberOfChildren == 0) { + + // + // Close the PCI I/O Protocol + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + } + + ASSERT (NumberOfChildren == 1); + Status = gBS->OpenProtocol ( + ChildHandleBuffer[0], + &gEfiGraphicsOutputProtocolGuid, + (VOID **) &Gop, + This->DriverBindingHandle, + ChildHandleBuffer[0], + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Private = GRAPHICS_OUTPUT_PRIVATE_FROM_THIS (Gop); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->GraphicsOutputHandle + ); + ASSERT_EFI_ERROR (Status); + // + // Remove the GOP protocol interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->GraphicsOutputHandle, + &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput, + &gEfiDevicePathProtocolGuid, Private->DevicePath, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Restore original PCI attributes + // + Status = Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationSet, + Private->PciAttributes, + NULL + ); + ASSERT_EFI_ERROR (Status); + + FreePool (Private->DevicePath); + FreePool (Private->FrameBufferBltLibConfigure); + mDriverStarted = FALSE; + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->GraphicsOutputHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + ASSERT_EFI_ERROR (Status); + } + return Status; +} + +EFI_DRIVER_BINDING_PROTOCOL mGraphicsOutputDriverBinding = { + GraphicsOutputDriverBindingSupported, + GraphicsOutputDriverBindingStart, + GraphicsOutputDriverBindingStop, + 0x10, + NULL, + NULL +}; + +/** + The Entry Point for GraphicsOutput driver. + + It installs DriverBinding, ComponentName and ComponentName2 protocol if there is + GraphicsInfo HOB passed from Graphics PEIM. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +InitializeGraphicsOutput ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + VOID *HobStart; + + HobStart = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); + + if ((HobStart == NULL) || (GET_GUID_HOB_DATA_SIZE (HobStart) < sizeof (EFI_PEI_GRAPHICS_INFO_HOB))) { + return EFI_NOT_FOUND; + } + + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mGraphicsOutputDriverBinding, + ImageHandle, + &mGraphicsOutputComponentName, + &mGraphicsOutputComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} |