/** @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; | |
} |