You've already forked edk2-platforms
mirror of
https://github.com/Dasharo/edk2-platforms.git
synced 2026-03-06 14:51:43 -08:00
Commit 0c2af04985 added mDriverBinding
extern module global, but did not remove the STATIC declaration, which
caused the build to break. Fix the build error by removing STATIC for
that module global variable.
Signed-off-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
Reviewed-by: Pete Batard <pete@akeo.ie>
Reviewed-by: Andrei Warkentin <andrey.warkentin@gmail.com>
656 lines
18 KiB
C
656 lines
18 KiB
C
/** @file
|
|
*
|
|
* Copyright (c) 2020, ARM Limited. All rights reserved.
|
|
* Copyright (c) 2017-2018, Andrei Warkentin <andrey.warkentin@gmail.com>
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
*
|
|
**/
|
|
|
|
#include <Base.h>
|
|
#include "DisplayDxe.h"
|
|
|
|
#define MODE_800_ENABLED BIT0
|
|
#define MODE_640_ENABLED BIT1
|
|
#define MODE_1024_ENABLED BIT2
|
|
#define MODE_720P_ENABLED BIT3
|
|
#define MODE_1080P_ENABLED BIT4
|
|
#define MODE_NATIVE_ENABLED BIT5
|
|
#define JUST_NATIVE_ENABLED MODE_NATIVE_ENABLED
|
|
#define ALL_MODES (BIT6 - 1)
|
|
#define POS_TO_FB(posX, posY) ((UINT8*) \
|
|
((UINTN)This->Mode->FrameBufferBase + \
|
|
(posY) * This->Mode->Info->PixelsPerScanLine * \
|
|
PI3_BYTES_PER_PIXEL + \
|
|
(posX) * PI3_BYTES_PER_PIXEL))
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
);
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
);
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
);
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplayQueryMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
|
IN UINT32 ModeNumber,
|
|
OUT UINTN *SizeOfInfo,
|
|
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
|
);
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplaySetMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
|
IN UINT32 ModeNumber
|
|
);
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplayBlt (
|
|
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
|
|
);
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
|
|
DriverSupported,
|
|
DriverStart,
|
|
DriverStop,
|
|
0xa,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
typedef struct {
|
|
VENDOR_DEVICE_PATH DisplayDevicePath;
|
|
EFI_DEVICE_PATH EndDevicePath;
|
|
} DISPLAY_DEVICE_PATH;
|
|
|
|
typedef struct {
|
|
UINT32 Width;
|
|
UINT32 Height;
|
|
} GOP_MODE_DATA;
|
|
|
|
STATIC UINT32 mBootWidth;
|
|
STATIC UINT32 mBootHeight;
|
|
STATIC EFI_HANDLE mDevice;
|
|
STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
|
|
STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
|
|
|
|
STATIC UINTN mLastMode;
|
|
STATIC GOP_MODE_DATA mGopModeTemplate[] = {
|
|
{ 800, 600 }, /* Legacy */
|
|
{ 640, 480 }, /* Legacy */
|
|
{ 1024, 768 }, /* Legacy */
|
|
{ 1280, 720 }, /* 720p */
|
|
{ 1920, 1080 }, /* 1080p */
|
|
{ 0, 0 }, /* Physical */
|
|
};
|
|
|
|
STATIC UINTN mLastMode;
|
|
STATIC GOP_MODE_DATA mGopModeData[ARRAY_SIZE (mGopModeTemplate)];
|
|
|
|
STATIC DISPLAY_DEVICE_PATH mDisplayProtoDevicePath =
|
|
{
|
|
{
|
|
{
|
|
HARDWARE_DEVICE_PATH,
|
|
HW_VENDOR_DP,
|
|
{
|
|
(UINT8)(sizeof (VENDOR_DEVICE_PATH)),
|
|
(UINT8)((sizeof (VENDOR_DEVICE_PATH)) >> 8),
|
|
}
|
|
},
|
|
EFI_CALLER_ID_GUID,
|
|
},
|
|
{
|
|
END_DEVICE_PATH_TYPE,
|
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
|
{
|
|
sizeof (EFI_DEVICE_PATH_PROTOCOL),
|
|
0
|
|
}
|
|
}
|
|
};
|
|
|
|
#define PI3_BITS_PER_PIXEL (32)
|
|
#define PI3_BYTES_PER_PIXEL (PI3_BITS_PER_PIXEL / 8)
|
|
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL gDisplayProto = {
|
|
DisplayQueryMode,
|
|
DisplaySetMode,
|
|
DisplayBlt,
|
|
NULL
|
|
};
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplayQueryMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
|
IN UINT32 ModeNumber,
|
|
OUT UINTN *SizeOfInfo,
|
|
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
GOP_MODE_DATA *Mode;
|
|
|
|
if (Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = gBS->AllocatePool (
|
|
EfiBootServicesData,
|
|
sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION),
|
|
(VOID**)Info
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Mode = &mGopModeData[ModeNumber];
|
|
|
|
*SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
|
(*Info)->Version = This->Mode->Info->Version;
|
|
(*Info)->HorizontalResolution = Mode->Width;
|
|
(*Info)->VerticalResolution = Mode->Height;
|
|
(*Info)->PixelFormat = This->Mode->Info->PixelFormat;
|
|
(*Info)->PixelInformation.RedMask = This->Mode->Info->PixelInformation.RedMask;
|
|
(*Info)->PixelInformation.GreenMask = This->Mode->Info->PixelInformation.GreenMask;
|
|
(*Info)->PixelInformation.BlueMask = This->Mode->Info->PixelInformation.BlueMask;
|
|
(*Info)->PixelInformation.ReservedMask = This->Mode->Info->PixelInformation.ReservedMask;
|
|
(*Info)->PixelsPerScanLine = Mode->Width;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
ClearScreen (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This
|
|
)
|
|
{
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
|
|
|
|
Fill.Red = 0x00;
|
|
Fill.Green = 0x00;
|
|
Fill.Blue = 0x00;
|
|
This->Blt (This, &Fill, EfiBltVideoFill,
|
|
0, 0, 0, 0, This->Mode->Info->HorizontalResolution,
|
|
This->Mode->Info->VerticalResolution,
|
|
This->Mode->Info->HorizontalResolution *
|
|
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplaySetMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
|
IN UINT32 ModeNumber
|
|
)
|
|
{
|
|
UINTN FbSize;
|
|
UINTN FbPitch;
|
|
EFI_STATUS Status;
|
|
EFI_PHYSICAL_ADDRESS FbBase;
|
|
GOP_MODE_DATA *Mode = &mGopModeData[ModeNumber];
|
|
|
|
if (ModeNumber >= This->Mode->MaxMode) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Setting mode %u from %u: %u x %u\n",
|
|
ModeNumber, This->Mode->Mode, Mode->Width, Mode->Height));
|
|
Status = mFwProtocol->GetFB (Mode->Width, Mode->Height,
|
|
PI3_BITS_PER_PIXEL, &FbBase,
|
|
&FbSize, &FbPitch);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Could not set mode %u\n", ModeNumber));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n",
|
|
ModeNumber, Mode->Width, Mode->Height, FbSize, FbBase));
|
|
|
|
if (FbPitch / PI3_BYTES_PER_PIXEL != Mode->Width) {
|
|
DEBUG ((DEBUG_ERROR, "Error: Expected width %u, got width %u\n",
|
|
Mode->Width, FbPitch / PI3_BYTES_PER_PIXEL));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
/*
|
|
* WT, because certain OS loaders access the frame buffer directly
|
|
* and we don't want to see corruption due to missing WB cache
|
|
* maintenance. Performance with WT is good.
|
|
*/
|
|
Status = mCpu->SetMemoryAttributes (mCpu, FbBase,
|
|
ALIGN_VALUE (FbSize, EFI_PAGE_SIZE),
|
|
EFI_MEMORY_WT);
|
|
if (Status != EFI_SUCCESS) {
|
|
DEBUG ((DEBUG_ERROR, "Couldn't set framebuffer attributes: %r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
This->Mode->Mode = ModeNumber;
|
|
This->Mode->Info->Version = 0;
|
|
This->Mode->Info->HorizontalResolution = Mode->Width;
|
|
This->Mode->Info->VerticalResolution = Mode->Height;
|
|
/*
|
|
* NOTE: Windows REQUIRES BGR in 32 or 24 bit format.
|
|
*/
|
|
This->Mode->Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
|
|
This->Mode->Info->PixelsPerScanLine = Mode->Width;
|
|
This->Mode->SizeOfInfo = sizeof (*This->Mode->Info);
|
|
This->Mode->FrameBufferBase = FbBase;
|
|
This->Mode->FrameBufferSize = Mode->Width * Mode->Height * PI3_BYTES_PER_PIXEL;
|
|
DEBUG((DEBUG_INFO, "Reported Mode->FrameBufferSize is %u\n", This->Mode->FrameBufferSize));
|
|
|
|
ClearScreen (This);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplayBlt (
|
|
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
|
|
)
|
|
{
|
|
UINT8 *VidBuf, *BltBuf, *VidBuf1;
|
|
UINTN i;
|
|
|
|
if ((UINTN)BltOperation >= EfiGraphicsOutputBltOperationMax) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Width == 0 || Height == 0) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (BltOperation) {
|
|
case EfiBltVideoFill:
|
|
BltBuf = (UINT8*)BltBuffer;
|
|
|
|
for (i = 0; i < Height; i++) {
|
|
VidBuf = POS_TO_FB (DestinationX, DestinationY + i);
|
|
|
|
SetMem32 (VidBuf, Width * PI3_BYTES_PER_PIXEL, *(UINT32*)BltBuf);
|
|
}
|
|
break;
|
|
|
|
case EfiBltVideoToBltBuffer:
|
|
if (Delta == 0) {
|
|
Delta = Width * PI3_BYTES_PER_PIXEL;
|
|
}
|
|
|
|
for (i = 0; i < Height; i++) {
|
|
VidBuf = POS_TO_FB (SourceX, SourceY + i);
|
|
|
|
BltBuf = (UINT8*)((UINTN)BltBuffer + (DestinationY + i) * Delta +
|
|
DestinationX * PI3_BYTES_PER_PIXEL);
|
|
|
|
gBS->CopyMem ((VOID*)BltBuf, (VOID*)VidBuf, PI3_BYTES_PER_PIXEL * Width);
|
|
}
|
|
break;
|
|
|
|
case EfiBltBufferToVideo:
|
|
if (Delta == 0) {
|
|
Delta = Width * PI3_BYTES_PER_PIXEL;
|
|
}
|
|
|
|
for (i = 0; i < Height; i++) {
|
|
VidBuf = POS_TO_FB (DestinationX, DestinationY + i);
|
|
BltBuf = (UINT8*)((UINTN)BltBuffer + (SourceY + i) * Delta +
|
|
SourceX * PI3_BYTES_PER_PIXEL);
|
|
|
|
gBS->CopyMem ((VOID*)VidBuf, (VOID*)BltBuf, Width * PI3_BYTES_PER_PIXEL);
|
|
}
|
|
break;
|
|
|
|
case EfiBltVideoToVideo:
|
|
for (i = 0; i < Height; i++) {
|
|
VidBuf = POS_TO_FB (SourceX, SourceY + i);
|
|
VidBuf1 = POS_TO_FB (DestinationX, DestinationY + i);
|
|
|
|
gBS->CopyMem ((VOID*)VidBuf1, (VOID*)VidBuf, Width * PI3_BYTES_PER_PIXEL);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return EFI_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Initialize the state information for the Display Dxe
|
|
|
|
@param ImageHandle of the loaded driver
|
|
@param SystemTable Pointer to the System Table
|
|
|
|
@retval EFI_SUCCESS Protocol registered
|
|
@retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure
|
|
@retval EFI_DEVICE_ERROR Hardware problems
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DisplayDxeInitialize (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->LocateProtocol (&gRaspberryPiFirmwareProtocolGuid, NULL,
|
|
(VOID**)&mFwProtocol);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,
|
|
(VOID**)&mCpu);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
// Query the current display resolution from mailbox
|
|
Status = mFwProtocol->GetFBSize (&mBootWidth, &mBootHeight);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Display boot mode is %u x %u\n",
|
|
mBootWidth, mBootHeight));
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&mDevice, &gEfiDevicePathProtocolGuid,
|
|
&mDisplayProtoDevicePath, &gEfiCallerIdGuid,
|
|
NULL, NULL);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&mDriverBinding,
|
|
ImageHandle,
|
|
&gComponentName,
|
|
&gComponentName2
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
VOID *Temp;
|
|
|
|
if (Controller != mDevice) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (gBS->HandleProtocol (Controller, &gEfiGraphicsOutputProtocolGuid,
|
|
(VOID**)&Temp) == EFI_SUCCESS) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN TempIndex;
|
|
EFI_STATUS Status;
|
|
VOID *Dummy;
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiCallerIdGuid,
|
|
(VOID**)&Dummy,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gDisplayProto.Mode = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
|
|
if (gDisplayProto.Mode == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Done;
|
|
}
|
|
|
|
gDisplayProto.Mode->Info = AllocateZeroPool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
|
|
if (gDisplayProto.Mode->Info == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Done;
|
|
}
|
|
|
|
Status = PcdSet8S (PcdDisplayEnableScaledVModes,
|
|
PcdGet8 (PcdDisplayEnableScaledVModes) & ALL_MODES);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (PcdGet8 (PcdDisplayEnableScaledVModes) == 0) {
|
|
Status = PcdSet8S (PcdDisplayEnableScaledVModes, JUST_NATIVE_ENABLED);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
mLastMode = 0;
|
|
for (TempIndex = 0, Index = 0;
|
|
TempIndex < ARRAY_SIZE (mGopModeTemplate); TempIndex++) {
|
|
if ((PcdGet8 (PcdDisplayEnableScaledVModes) & (1 << TempIndex)) != 0) {
|
|
DEBUG ((DEBUG_ERROR, "Mode %u: %u x %u present\n",
|
|
TempIndex, mGopModeTemplate[TempIndex].Width,
|
|
mGopModeTemplate[TempIndex].Height));
|
|
|
|
CopyMem (&mGopModeData[Index], &mGopModeTemplate[TempIndex],
|
|
sizeof (GOP_MODE_DATA));
|
|
mLastMode = Index;
|
|
Index++;
|
|
}
|
|
}
|
|
|
|
if (PcdGet8 (PcdDisplayEnableScaledVModes) == JUST_NATIVE_ENABLED) {
|
|
/*
|
|
* mBootWidth x mBootHeight may not be sensible,
|
|
* so clean it up, since we won't be adding
|
|
* any other extra vmodes.
|
|
*/
|
|
if (mBootWidth < 640 || mBootHeight < 480) {
|
|
mBootWidth = 640;
|
|
mBootHeight = 480;
|
|
} else if (mBootWidth == 800 && mBootHeight == 480) {
|
|
/* The Pi 7" screen is close to 800x600, just pretend it is. */
|
|
mBootHeight = 600;
|
|
}
|
|
}
|
|
|
|
if ((PcdGet8(PcdDisplayEnableScaledVModes) & MODE_NATIVE_ENABLED) != 0) {
|
|
/*
|
|
* Adjust actual native res only if native res is enabled
|
|
* (so last mode is native res).
|
|
*/
|
|
mGopModeData[mLastMode].Width = mBootWidth;
|
|
mGopModeData[mLastMode].Height = mBootHeight;
|
|
}
|
|
|
|
for (Index = 0; Index <= mLastMode; Index++) {
|
|
UINTN FbSize;
|
|
UINTN FbPitch;
|
|
EFI_PHYSICAL_ADDRESS FbBase;
|
|
|
|
GOP_MODE_DATA *Mode = &mGopModeData[Index];
|
|
|
|
Status = mFwProtocol->GetFB (Mode->Width, Mode->Height,
|
|
PI3_BITS_PER_PIXEL, &FbBase,
|
|
&FbSize, &FbPitch);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// There is no way to communicate pitch back to OS. OS and even UEFI
|
|
// expect a fully linear frame buffer. So the width should
|
|
// be based on the frame buffer's pitch value. In some cases VC
|
|
// firmware would allocate ao frame buffer with some padding
|
|
// presumably to be 8 byte align.
|
|
//
|
|
Mode->Width = FbPitch / PI3_BYTES_PER_PIXEL;
|
|
|
|
DEBUG ((DEBUG_INFO, "Mode %u: %u x %u framebuffer is %u bytes at %p\n",
|
|
Index, Mode->Width, Mode->Height, FbSize, FbBase));
|
|
|
|
ASSERT (FbPitch != 0);
|
|
ASSERT (FbBase != 0);
|
|
ASSERT (FbSize != 0);
|
|
}
|
|
|
|
// Both set the mode and initialize current mode information.
|
|
gDisplayProto.Mode->MaxMode = mLastMode + 1;
|
|
DisplaySetMode (&gDisplayProto, 0);
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Controller, &gEfiGraphicsOutputProtocolGuid,
|
|
&gDisplayProto, NULL);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
if (PcdGet32 (PcdDisplayEnableSShot)) {
|
|
RegisterScreenshotHandlers ();
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "Screenshot capture disabled\n"));
|
|
}
|
|
|
|
Done:
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Could not start DisplayDxe: %r\n", Status));
|
|
if (gDisplayProto.Mode->Info != NULL) {
|
|
FreePool (gDisplayProto.Mode->Info);
|
|
gDisplayProto.Mode->Info = NULL;
|
|
}
|
|
|
|
if (gDisplayProto.Mode != NULL) {
|
|
FreePool (gDisplayProto.Mode);
|
|
gDisplayProto.Mode = NULL;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEfiCallerIdGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DriverStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
ClearScreen (&gDisplayProto);
|
|
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller, &gEfiGraphicsOutputProtocolGuid,
|
|
&gDisplayProto, NULL);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
FreePool (gDisplayProto.Mode->Info);
|
|
gDisplayProto.Mode->Info = NULL;
|
|
FreePool (gDisplayProto.Mode);
|
|
gDisplayProto.Mode = NULL;
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEfiCallerIdGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
return Status;
|
|
}
|