740 lines
24 KiB
C
740 lines
24 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;
|
||
|
}
|