mirror of https://github.com/acidanthera/audk.git
780 lines
25 KiB
C
780 lines
25 KiB
C
/** @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;
|
|
}
|