1564 lines
43 KiB
C
1564 lines
43 KiB
C
/** @file
|
|
RotateScreen
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
#include <Uefi.h>
|
|
|
|
#include <IndustryStandard/Acpi.h>
|
|
#include <IndustryStandard/Bmp.h>
|
|
#include <Guid/EfiSystemResourceTable.h>
|
|
#include <Guid/EventGroup.h>
|
|
#include <Guid/DebugMask.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
|
|
#include <Protocol/SimpleTextInEx.h>
|
|
#include <Protocol/GraphicsOutput.h>
|
|
#include <Protocol/AbsolutePointer.h>
|
|
#include <Protocol/DriverBinding.h>
|
|
#include <Protocol/ComponentName2.h>
|
|
#include <Protocol/AcpiTable.h>
|
|
#include <Protocol/AcpiSupport.h>
|
|
|
|
|
|
#include "HookLib.h"
|
|
|
|
typedef struct _ROTATE_SCREEN_GOP_ENTRY {
|
|
UINT32 Signature;
|
|
LIST_ENTRY Link;
|
|
|
|
BOOLEAN NeedFlip;
|
|
|
|
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBuffer;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION Info;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE Mode;
|
|
|
|
EFI_HANDLE GopHandle;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE OrgQueryMode;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE OrgSetMode;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT OrgBlt;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *OrgMode;
|
|
UINT32 OrgMaxMode;
|
|
} ROTATE_SCREEN_GOP_ENTRY;
|
|
|
|
#define ROTATE_SCREEN_GOP_ENTRY_SIGNATURE SIGNATURE_32 ('r', 's', 'g', 'e')
|
|
#define GOP_ENTYRY_FROM_LINK(_link) CR (_link, ROTATE_SCREEN_GOP_ENTRY, Link, ROTATE_SCREEN_GOP_ENTRY_SIGNATURE)
|
|
#define BUILD_21390 0x536A
|
|
|
|
LIST_ENTRY mGopEntryList;
|
|
VOID *mGopRegistration;
|
|
|
|
HOOK_DRIVER_BINDING_ENTRY *mHookGraphicsConsoleEntry;
|
|
LIST_ENTRY mHookGopEntryList;
|
|
|
|
|
|
BOOLEAN mReadyToBoot = FALSE;
|
|
BOOLEAN mSkipSetMode = FALSE;
|
|
|
|
EFI_GUID gEfiShellProtocolGuid = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}};
|
|
EFI_GUID gEfiShellEnvironment2Guid = {0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}};
|
|
|
|
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsRotateScreen (
|
|
VOID
|
|
)
|
|
{
|
|
ROTATE_SCREEN_GOP_ENTRY *Entry;
|
|
LIST_ENTRY *Link;
|
|
|
|
for (Link = GetFirstNode (&mGopEntryList);
|
|
!IsNull (&mGopEntryList, Link);
|
|
Link = GetNextNode (&mGopEntryList, Link)) {
|
|
|
|
Entry = GOP_ENTYRY_FROM_LINK (Link);
|
|
if (Entry->NeedFlip) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
ROTATE_SCREEN_GOP_ENTRY *
|
|
EFIAPI
|
|
FindGopEntryByHandle (
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Link;
|
|
|
|
for (Link = GetFirstNode (&mGopEntryList);
|
|
!IsNull (&mGopEntryList, Link);
|
|
Link = GetNextNode (&mGopEntryList, Link)) {
|
|
|
|
GopEntry = GOP_ENTYRY_FROM_LINK (Link);
|
|
if (GopEntry->GopHandle == Handle) {
|
|
return GopEntry;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ROTATE_SCREEN_GOP_ENTRY *
|
|
FindGopEntry (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
|
|
)
|
|
{
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Link;
|
|
|
|
for (Link = GetFirstNode (&mGopEntryList);
|
|
!IsNull (&mGopEntryList, Link);
|
|
Link = GetNextNode (&mGopEntryList, Link)) {
|
|
|
|
GopEntry = GOP_ENTYRY_FROM_LINK (Link);
|
|
if (GopEntry->GraphicsOutput == GraphicsOutput) {
|
|
return GopEntry;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
PatchGopMode (
|
|
IN ROTATE_SCREEN_GOP_ENTRY *GopEntry
|
|
)
|
|
{
|
|
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
|
|
GraphicsOutput = GopEntry->GraphicsOutput;
|
|
|
|
if (GopEntry->OrgMode == NULL && GraphicsOutput->Mode != NULL) {
|
|
CopyMem (&GopEntry->Mode, GraphicsOutput->Mode, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
|
|
CopyMem (&GopEntry->Info, GraphicsOutput->Mode->Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
|
|
|
|
GopEntry->OrgMode = GraphicsOutput->Mode;
|
|
GopEntry->OrgMaxMode = GraphicsOutput->Mode->MaxMode;
|
|
|
|
GopEntry->Mode.MaxMode = GraphicsOutput->Mode->MaxMode * 2;
|
|
GopEntry->Mode.Info = &GopEntry->Info;
|
|
GopEntry->Mode.SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
|
|
|
|
GraphicsOutput->Mode = &GopEntry->Mode;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RotateScreenGraphicsConsoleDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
|
|
GopEntry = FindGopEntryByHandle (ControllerHandle);
|
|
ASSERT (GopEntry != NULL);
|
|
if (GopEntry != NULL) {
|
|
PatchGopMode (GopEntry);
|
|
}
|
|
|
|
Status = mHookGraphicsConsoleEntry->Start (This, ControllerHandle, RemainingDevicePath);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RotateScreenGraphicsConsoleDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
|
|
GopEntry = FindGopEntryByHandle (ControllerHandle);
|
|
if (GopEntry != NULL) {
|
|
GopEntry->GraphicsOutput->QueryMode = GopEntry->OrgQueryMode;
|
|
GopEntry->GraphicsOutput->SetMode = GopEntry->OrgSetMode;
|
|
GopEntry->GraphicsOutput->Blt = GopEntry->OrgBlt;
|
|
GopEntry->GraphicsOutput->Mode = GopEntry->OrgMode;
|
|
if (GopEntry->GopBuffer != NULL) {
|
|
FreePool (GopEntry->GopBuffer);
|
|
}
|
|
RemoveEntryList (&GopEntry->Link);
|
|
FreePool (GopEntry);
|
|
}
|
|
|
|
Status = mHookGraphicsConsoleEntry->Stop (This, ControllerHandle, NumberOfChildren, ChildHandleBuffer);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RotateScreenQueryMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
|
|
IN UINT32 ModeNumber,
|
|
OUT UINTN *SizeOfInfo,
|
|
OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
BOOLEAN NeedFlip;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 TargetMode;
|
|
|
|
GopEntry = FindGopEntry (This);
|
|
if (GopEntry == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (This == NULL || Info == NULL || SizeOfInfo == NULL || ModeNumber >= This->Mode->MaxMode) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
NeedFlip = FALSE;
|
|
TargetMode = ModeNumber;
|
|
if ((ModeNumber >= GopEntry->OrgMode->MaxMode) &&
|
|
(ModeNumber < GopEntry->OrgMode->MaxMode * 2)) {
|
|
ModeNumber -= GopEntry->OrgMode->MaxMode;
|
|
NeedFlip = TRUE;
|
|
}
|
|
|
|
Status = GopEntry->OrgQueryMode (
|
|
This,
|
|
ModeNumber,
|
|
SizeOfInfo,
|
|
Info
|
|
);
|
|
|
|
if (!EFI_ERROR (Status) && NeedFlip) {
|
|
HorizontalResolution = (*Info)->HorizontalResolution;
|
|
(*Info)->HorizontalResolution = (*Info)->VerticalResolution;
|
|
(*Info)->VerticalResolution = HorizontalResolution;
|
|
(*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RotateScreenBltRotate90 (
|
|
IN ROTATE_SCREEN_GOP_ENTRY *GopEntry,
|
|
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_GRAPHICS_OUTPUT_PROTOCOL *This;
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Src;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Dst;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SrcBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *DstBuffer;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
INTN X;
|
|
UINTN Y;
|
|
|
|
This = GopEntry->GraphicsOutput;
|
|
GopBuffer = GopEntry->GopBuffer;
|
|
|
|
HorizontalResolution = This->Mode->Info->HorizontalResolution;
|
|
VerticalResolution = This->Mode->Info->VerticalResolution;
|
|
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
switch (BltOperation) {
|
|
|
|
case EfiBltVideoFill:
|
|
This->Mode = GopEntry->OrgMode;
|
|
CopyMem (
|
|
GopBuffer,
|
|
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)),
|
|
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
|
|
);
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
0,
|
|
0,
|
|
DestinationY,
|
|
HorizontalResolution - (Width + DestinationX),
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
case EfiBltVideoToBltBuffer:
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
SourceY,
|
|
HorizontalResolution - (Width + SourceX),
|
|
0,
|
|
0,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SrcBuffer = GopBuffer + (Width - 1) * Height;
|
|
DstBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
for (Y = 0; Y < Height; Y++) {
|
|
Src = SrcBuffer;
|
|
Dst = DstBuffer;
|
|
|
|
X = Width;
|
|
while (--X >= 0) {
|
|
*Dst = *Src;
|
|
Src -= Height;
|
|
Dst++;
|
|
}
|
|
SrcBuffer++;
|
|
DstBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)DstBuffer + Delta);
|
|
}
|
|
break;
|
|
|
|
case EfiBltBufferToVideo:
|
|
SrcBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
DstBuffer = GopBuffer + (Width - 1) * Height;
|
|
|
|
for (Y = 0; Y < Height; Y++) {
|
|
Src = SrcBuffer;
|
|
Dst = DstBuffer;
|
|
|
|
X = Width;
|
|
while (--X >= 0) {
|
|
*Dst = *Src;
|
|
Src++;
|
|
Dst -= Height;
|
|
}
|
|
|
|
SrcBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)SrcBuffer + Delta);
|
|
DstBuffer++;
|
|
}
|
|
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
0,
|
|
0,
|
|
DestinationY,
|
|
HorizontalResolution - (Width + DestinationX),
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
case EfiBltVideoToVideo:
|
|
//
|
|
// For improve GOP VideoToVideo performance in rotate mode,
|
|
// Use BltBufferToVideo to display
|
|
//
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
EfiBltVideoToBltBuffer,
|
|
SourceY,
|
|
HorizontalResolution - (Width + SourceX),
|
|
0,
|
|
0,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
EfiBltBufferToVideo,
|
|
0,
|
|
0,
|
|
DestinationY,
|
|
HorizontalResolution - (Width + DestinationX),
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RotateScreenBltRotate270 (
|
|
IN ROTATE_SCREEN_GOP_ENTRY *GopEntry,
|
|
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_GRAPHICS_OUTPUT_PROTOCOL *This;
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Src;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Dst;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GopBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SrcBuffer;
|
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *DstBuffer;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
INTN X;
|
|
UINTN Y;
|
|
|
|
This = GopEntry->GraphicsOutput;
|
|
GopBuffer = GopEntry->GopBuffer;
|
|
|
|
HorizontalResolution = This->Mode->Info->HorizontalResolution;
|
|
VerticalResolution = This->Mode->Info->VerticalResolution;
|
|
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
switch (BltOperation) {
|
|
|
|
case EfiBltVideoFill:
|
|
This->Mode = GopEntry->OrgMode;
|
|
CopyMem (
|
|
GopBuffer,
|
|
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)),
|
|
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
|
|
);
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
0,
|
|
0,
|
|
VerticalResolution - (Height + DestinationY),
|
|
DestinationX,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
case EfiBltVideoToBltBuffer:
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
VerticalResolution - (Height + SourceY),
|
|
SourceX,
|
|
0,
|
|
0,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
SrcBuffer = GopBuffer + (Height - 1);
|
|
DstBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
|
|
for (Y = 0; Y < Height; Y++) {
|
|
Src = SrcBuffer;
|
|
Dst = DstBuffer;
|
|
|
|
X = Width;
|
|
while (--X >= 0) {
|
|
*Dst = *Src;
|
|
Src += Height;
|
|
Dst++;
|
|
}
|
|
SrcBuffer--;
|
|
DstBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)DstBuffer + Delta);
|
|
}
|
|
break;
|
|
|
|
case EfiBltBufferToVideo:
|
|
SrcBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)BltBuffer + SourceY * Delta + SourceX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
|
|
DstBuffer = GopBuffer + (Height - 1);
|
|
|
|
for (Y = 0; Y < Height; Y++) {
|
|
Src = SrcBuffer;
|
|
Dst = DstBuffer;
|
|
|
|
X = Width;
|
|
while (--X >= 0) {
|
|
*Dst = *Src;
|
|
Src++;
|
|
Dst += Height;
|
|
}
|
|
|
|
SrcBuffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)((UINT8 *)SrcBuffer + Delta);
|
|
DstBuffer--;
|
|
}
|
|
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
BltOperation,
|
|
0,
|
|
0,
|
|
VerticalResolution - (Height + DestinationY),
|
|
DestinationX,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
case EfiBltVideoToVideo:
|
|
//
|
|
// For improve GOP VideoToVideo performance in rotate mode,
|
|
// Use BltBufferToVideo to display
|
|
//
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
EfiBltVideoToBltBuffer,
|
|
VerticalResolution - (Height + SourceY),
|
|
SourceX,
|
|
0,
|
|
0,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
GopBuffer,
|
|
EfiBltBufferToVideo,
|
|
0,
|
|
0,
|
|
VerticalResolution - (Height + DestinationY),
|
|
DestinationX,
|
|
Height,
|
|
Width,
|
|
0
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
This->Mode = &GopEntry->Mode;
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RotateScreenBlt (
|
|
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_STATUS Status;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
EFI_TPL OriginalTPL;
|
|
|
|
GopEntry = FindGopEntry (This);
|
|
if (GopEntry == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!GopEntry->NeedFlip) {
|
|
|
|
OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
|
|
This->Mode = GopEntry->OrgMode;
|
|
Status = GopEntry->OrgBlt (
|
|
This,
|
|
BltBuffer,
|
|
BltOperation,
|
|
SourceX,
|
|
SourceY,
|
|
DestinationX,
|
|
DestinationY,
|
|
Width,
|
|
Height,
|
|
Delta
|
|
);
|
|
This->Mode = &GopEntry->Mode;
|
|
gBS->RestoreTPL (OriginalTPL);
|
|
return Status;
|
|
}
|
|
|
|
if (BltOperation >= EfiGraphicsOutputBltOperationMax) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
HorizontalResolution = This->Mode->Info->HorizontalResolution;
|
|
VerticalResolution = This->Mode->Info->VerticalResolution;
|
|
|
|
if (HorizontalResolution == 0 || VerticalResolution == 0) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
if ((Width > HorizontalResolution) || (Height > VerticalResolution)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (GopEntry->GopBuffer == NULL) {
|
|
GopEntry->GopBuffer = AllocateZeroPool (
|
|
HorizontalResolution * VerticalResolution *
|
|
sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
|
|
);
|
|
if (GopEntry->GopBuffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check range: source is video
|
|
//
|
|
if (BltOperation == EfiBltVideoToBltBuffer || BltOperation == EfiBltVideoToVideo) {
|
|
if ((SourceX >= HorizontalResolution) || (SourceY >= VerticalResolution)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (SourceY + Height > VerticalResolution) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (SourceX + Width > HorizontalResolution) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
//
|
|
// check range: destination is video
|
|
//
|
|
if (BltOperation != EfiBltVideoToBltBuffer) {
|
|
if ((DestinationX >= HorizontalResolution) || (DestinationY >= VerticalResolution)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (DestinationX + Width > HorizontalResolution) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (DestinationY + Height > VerticalResolution) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
if (Delta == 0) {
|
|
Delta = Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
}
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
|
|
OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
|
|
|
|
if (PcdGetBool(PcdH2ORotateScreenIs90DegreeClockwise)) {
|
|
Status = RotateScreenBltRotate90 (
|
|
GopEntry,
|
|
BltBuffer,
|
|
BltOperation,
|
|
SourceX,
|
|
SourceY,
|
|
DestinationX,
|
|
DestinationY,
|
|
Width,
|
|
Height,
|
|
Delta
|
|
);
|
|
} else {
|
|
Status = RotateScreenBltRotate270 (
|
|
GopEntry,
|
|
BltBuffer,
|
|
BltOperation,
|
|
SourceX,
|
|
SourceY,
|
|
DestinationX,
|
|
DestinationY,
|
|
Width,
|
|
Height,
|
|
Delta
|
|
);
|
|
}
|
|
|
|
gBS->RestoreTPL (OriginalTPL);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
RotateScreenSetMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
|
|
IN UINT32 ModeNumber
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
UINT32 TargetMode;
|
|
BOOLEAN NeedFlip;
|
|
|
|
GopEntry = FindGopEntry (This);
|
|
if (GopEntry == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (ModeNumber >= This->Mode->MaxMode) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
NeedFlip = FALSE;
|
|
TargetMode = ModeNumber;
|
|
if ((ModeNumber >= GopEntry->OrgMode->MaxMode) &&
|
|
(ModeNumber < GopEntry->OrgMode->MaxMode * 2)) {
|
|
ModeNumber -= GopEntry->OrgMode->MaxMode;
|
|
NeedFlip = TRUE;
|
|
}
|
|
|
|
This->Mode = GopEntry->OrgMode;
|
|
This->Blt = GopEntry->OrgBlt;
|
|
if (mSkipSetMode) {
|
|
Status = EFI_SUCCESS;
|
|
} else {
|
|
Status = GopEntry->OrgSetMode (
|
|
This,
|
|
ModeNumber
|
|
);
|
|
}
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
This->Mode = &GopEntry->Mode;
|
|
This->Blt = RotateScreenBlt;
|
|
return Status;
|
|
}
|
|
|
|
if (GopEntry->GopBuffer != NULL) {
|
|
FreePool (GopEntry->GopBuffer);
|
|
}
|
|
GopEntry->GopBuffer = NULL;
|
|
|
|
GopEntry->NeedFlip = NeedFlip;
|
|
GopEntry->Mode.Mode = This->Mode->Mode;
|
|
GopEntry->Mode.FrameBufferSize = This->Mode->FrameBufferSize;
|
|
|
|
if (NeedFlip) {
|
|
GopEntry->Info.HorizontalResolution = This->Mode->Info->VerticalResolution;
|
|
GopEntry->Info.VerticalResolution = This->Mode->Info->HorizontalResolution;
|
|
GopEntry->Info.PixelsPerScanLine = GopEntry->Info.HorizontalResolution;
|
|
GopEntry->Mode.Mode = ModeNumber + GopEntry->OrgMode->MaxMode;
|
|
} else {
|
|
CopyMem (&GopEntry->Info, This->Mode->Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
|
|
}
|
|
|
|
GopEntry->OrgMode = This->Mode;
|
|
This->Mode = &GopEntry->Mode;
|
|
This->Blt = RotateScreenBlt;
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RotateScreenGopDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STATUS ReturnStatus;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
HOOK_DRIVER_BINDING_ENTRY *HookEntry;
|
|
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
|
|
UINTN EntryCount;
|
|
UINTN Index;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
|
|
HookEntry = FindHookDriverBindingEntry (This);
|
|
if (HookEntry == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
ReturnStatus = HookEntry->Start (This, ControllerHandle, RemainingDevicePath);
|
|
|
|
//
|
|
// check GOP hook
|
|
//
|
|
Status = gBS->OpenProtocolInformation (
|
|
ControllerHandle,
|
|
&gEfiPciIoProtocolGuid,
|
|
&OpenInfoBuffer,
|
|
&EntryCount
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
|
|
for (Index = 0; Index < EntryCount; Index++) {
|
|
//
|
|
// Query all the children
|
|
//
|
|
if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) == 0) {
|
|
continue;
|
|
}
|
|
|
|
if (OpenInfoBuffer[Index].AgentHandle != This->DriverBindingHandle) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
OpenInfoBuffer[Index].ControllerHandle,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
&GraphicsOutput
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
GopEntry = FindGopEntryByHandle (OpenInfoBuffer[Index].ControllerHandle);
|
|
if (GopEntry == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (GraphicsOutput->QueryMode == GopEntry->OrgQueryMode) {
|
|
GraphicsOutput->QueryMode = RotateScreenQueryMode;
|
|
}
|
|
if (GraphicsOutput->SetMode == GopEntry->OrgSetMode) {
|
|
GraphicsOutput->SetMode = RotateScreenSetMode;
|
|
}
|
|
if (GraphicsOutput->Blt == GopEntry->OrgBlt) {
|
|
GraphicsOutput->Blt = RotateScreenBlt;
|
|
}
|
|
|
|
if (GraphicsOutput->Mode->MaxMode == GopEntry->OrgMaxMode) {
|
|
//
|
|
// update MaxMode
|
|
//
|
|
if (GraphicsOutput->Mode == &GopEntry->Mode) {
|
|
GopEntry->Mode.MaxMode = GraphicsOutput->Mode->MaxMode * 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
FreePool (OpenInfoBuffer);
|
|
|
|
Done:
|
|
return ReturnStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
HookGopDriverBinding (
|
|
IN EFI_HANDLE GopHandle,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_HANDLE ParentHandle;
|
|
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
|
HOOK_DRIVER_BINDING_ENTRY *HookEntry;
|
|
|
|
//
|
|
// find gop driver's binding protocol
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
GopHandle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
&DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return ;
|
|
}
|
|
|
|
Status = gBS->LocateDevicePath (
|
|
&gEfiPciIoProtocolGuid,
|
|
&DevicePath,
|
|
&ParentHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return;
|
|
}
|
|
DriverBinding = LocateDriverBindingByProtocolGuid (
|
|
ParentHandle,
|
|
&gEfiPciIoProtocolGuid
|
|
);
|
|
if (DriverBinding == NULL) {
|
|
return ;
|
|
}
|
|
|
|
Status = HookDriverBinding (
|
|
DriverBinding,
|
|
NULL,
|
|
RotateScreenGopDriverBindingStart,
|
|
NULL,
|
|
&HookEntry
|
|
);
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
RotateScreenHookGop (
|
|
IN EFI_HANDLE GopHandle,
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
|
|
)
|
|
{
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
EFI_STATUS Status;
|
|
|
|
if (mHookGraphicsConsoleEntry == NULL) {
|
|
Status = HookDriverBindingByDriverName (
|
|
L"Graphics Console Driver",
|
|
NULL,
|
|
RotateScreenGraphicsConsoleDriverBindingStart,
|
|
RotateScreenGraphicsConsoleDriverBindingStop,
|
|
&mHookGraphicsConsoleEntry
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
if (FindGopEntry (GraphicsOutput) != NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
HookGopDriverBinding (GopHandle, GraphicsOutput);
|
|
|
|
|
|
GopEntry = AllocateZeroPool (sizeof (ROTATE_SCREEN_GOP_ENTRY));
|
|
if (GopEntry == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
GopEntry->Signature = ROTATE_SCREEN_GOP_ENTRY_SIGNATURE;
|
|
GopEntry->GopBuffer = NULL;
|
|
GopEntry->GraphicsOutput = GraphicsOutput;
|
|
GopEntry->GopHandle = GopHandle;
|
|
|
|
//
|
|
// hook GraphicsOutput
|
|
//
|
|
GopEntry->OrgQueryMode = GraphicsOutput->QueryMode;
|
|
GopEntry->OrgSetMode = GraphicsOutput->SetMode;
|
|
GopEntry->OrgBlt = GraphicsOutput->Blt;
|
|
|
|
GraphicsOutput->QueryMode = RotateScreenQueryMode;
|
|
GraphicsOutput->SetMode = RotateScreenSetMode;
|
|
GraphicsOutput->Blt = RotateScreenBlt;
|
|
|
|
InsertTailList (&mGopEntryList, &GopEntry->Link);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
RotateScreenGopCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Content
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
UINTN BufferSize;
|
|
VOID *DevicePath;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
|
|
while (TRUE) {
|
|
BufferSize = sizeof (EFI_HANDLE);
|
|
Status = gBS->LocateHandle (
|
|
ByRegisterNotify,
|
|
NULL,
|
|
mGopRegistration,
|
|
&BufferSize,
|
|
&Handle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
(VOID **) &GraphicsOutput
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
RotateScreenHookGop (Handle, GraphicsOutput);
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RegisterRotateTouchCallback (
|
|
VOID
|
|
);
|
|
|
|
|
|
EFI_IMAGE_START ImageStart;
|
|
|
|
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsWindows (
|
|
EFI_HANDLE Handle,
|
|
UINT32 *VersionMS,
|
|
UINT32 *VersionLS
|
|
);
|
|
|
|
|
|
EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE *
|
|
GetBgrtTable (
|
|
UINTN *TableKey
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
|
|
UINTN Index;
|
|
EFI_ACPI_DESCRIPTION_HEADER *Table;
|
|
UINTN Handle;
|
|
EFI_ACPI_TABLE_VERSION Version;
|
|
|
|
AcpiSupport = NULL;
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiAcpiSupportProtocolGuid,
|
|
NULL,
|
|
(VOID **)&AcpiSupport
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
Index = 0;
|
|
while (1) {
|
|
Table = NULL;
|
|
Status = AcpiSupport->GetAcpiTable (AcpiSupport, Index, (VOID **) &Table, &Version, &Handle);
|
|
if (Status == EFI_NOT_FOUND) {
|
|
break;
|
|
}
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
if (Table->Signature == EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE) {
|
|
*TableKey = Handle;
|
|
return (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE *)Table;
|
|
}
|
|
|
|
FreePool (Table);
|
|
Index++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RotateScreenStartImage (
|
|
IN EFI_HANDLE ImageHandle,
|
|
OUT UINTN *ExitDataSize,
|
|
OUT CHAR16 **ExitData OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Link;
|
|
UINTN Mode;
|
|
UINTN MaxMode;
|
|
UINTN Columns;
|
|
UINTN Rows;
|
|
UINTN ExpectColumns;
|
|
UINTN ExpectRows;
|
|
EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
|
|
EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE *OldBgrtTable;
|
|
EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE *NewBgrtTable;
|
|
UINTN AcpiTableKey;
|
|
UINT32 VersionMS;
|
|
UINT32 VersionLS;
|
|
BOOLEAN IsWindowsImage;
|
|
|
|
if (!mReadyToBoot) {
|
|
goto Done;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
gST->ConsoleOutHandle,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
&GraphicsOutput
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
for (Link = GetFirstNode (&mGopEntryList);
|
|
!IsNull (&mGopEntryList, Link);
|
|
Link = GetNextNode (&mGopEntryList, Link)) {
|
|
|
|
GopEntry = GOP_ENTYRY_FROM_LINK (Link);
|
|
if (GopEntry->GraphicsOutput->Mode->Info->VerticalResolution == GraphicsOutput->Mode->Info->VerticalResolution &&
|
|
GopEntry->GraphicsOutput->Mode->Info->HorizontalResolution == GraphicsOutput->Mode->Info->HorizontalResolution &&
|
|
!GopEntry->NeedFlip) {
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
ExpectColumns = GraphicsOutput->Mode->Info->VerticalResolution / EFI_GLYPH_WIDTH;
|
|
ExpectRows = GraphicsOutput->Mode->Info->HorizontalResolution / EFI_GLYPH_HEIGHT;
|
|
IsWindowsImage = IsWindows (ImageHandle, &VersionMS, &VersionLS);
|
|
|
|
MaxMode = gST->ConOut->Mode->MaxMode;
|
|
for (Mode = 0; Mode < MaxMode; Mode++) {
|
|
Status = gST->ConOut->QueryMode (
|
|
gST->ConOut,
|
|
Mode,
|
|
&Columns,
|
|
&Rows
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (Columns == ExpectColumns && Rows == ExpectRows) {
|
|
if (IsWindowsImage && ((VersionMS < 0xA0000) || ((VersionLS >> 16) < BUILD_21390))) {
|
|
mSkipSetMode = TRUE;
|
|
gST->ConOut->SetMode (gST->ConOut, Mode);
|
|
mSkipSetMode = FALSE;
|
|
goto Done;
|
|
}
|
|
|
|
OldBgrtTable = GetBgrtTable (&AcpiTableKey);
|
|
mSkipSetMode = TRUE;
|
|
gST->ConOut->SetMode (gST->ConOut, Mode);
|
|
mSkipSetMode = FALSE;
|
|
NewBgrtTable = GetBgrtTable (&AcpiTableKey);
|
|
|
|
//
|
|
// keep bgrt logo rotated image offset
|
|
//
|
|
if (OldBgrtTable != NULL && NewBgrtTable != NULL) {
|
|
|
|
NewBgrtTable->ImageOffsetX = OldBgrtTable->ImageOffsetX;
|
|
NewBgrtTable->ImageOffsetY = OldBgrtTable->ImageOffsetY;
|
|
|
|
if (PcdGetBool(PcdH2ORotateScreenIs90DegreeClockwise)) {
|
|
NewBgrtTable->Status |= (OldBgrtTable->Status | 0x02);
|
|
} else {
|
|
NewBgrtTable->Status |= (OldBgrtTable->Status | 0x06);
|
|
}
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiAcpiTableProtocolGuid,
|
|
NULL,
|
|
(VOID**)&AcpiTableProtocol
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
Status = AcpiTableProtocol->UninstallAcpiTable (
|
|
AcpiTableProtocol,
|
|
AcpiTableKey
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
AcpiTableKey = 0;
|
|
Status = AcpiTableProtocol->InstallAcpiTable (
|
|
AcpiTableProtocol,
|
|
NewBgrtTable,
|
|
sizeof (EFI_ACPI_5_0_BOOT_GRAPHICS_RESOURCE_TABLE),
|
|
&AcpiTableKey
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
}
|
|
if (OldBgrtTable != NULL) {
|
|
FreePool (OldBgrtTable);
|
|
}
|
|
if (NewBgrtTable != NULL) {
|
|
FreePool (NewBgrtTable);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
Done:
|
|
|
|
Status = ImageStart (ImageHandle, ExitDataSize, ExitData);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
VOID
|
|
EFIAPI
|
|
RotateScreenReadyToBootCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
gBS->CloseEvent (Event);
|
|
|
|
mReadyToBoot = TRUE;
|
|
}
|
|
|
|
VOID
|
|
EFIAPI
|
|
ShellImageCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
UINTN Mode;
|
|
UINTN MaxMode;
|
|
UINTN Columns;
|
|
UINTN Rows;
|
|
UINTN ExpectColumns;
|
|
UINTN ExpectRows;
|
|
ROTATE_SCREEN_GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Link;
|
|
UINTN NoHandles;
|
|
UINTN Index;
|
|
EFI_HANDLE *HandleBuffer;
|
|
VOID *Protocol;
|
|
|
|
if (!FeaturePcdGet (PcdH2ORotateShellSupported)) {
|
|
return ;
|
|
}
|
|
|
|
Link = GetFirstNode (&mGopEntryList);
|
|
if (IsNull (&mGopEntryList, Link)) {
|
|
return ;
|
|
}
|
|
|
|
GopEntry = GOP_ENTYRY_FROM_LINK (Link);
|
|
if (GopEntry->NeedFlip) {
|
|
return ;
|
|
}
|
|
|
|
//
|
|
// Locate the Handle that the AbsolutePointer interface is bound to
|
|
//
|
|
HandleBuffer = NULL;
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
NULL,
|
|
&NoHandles,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return ;
|
|
}
|
|
|
|
GraphicsOutput = NULL;
|
|
for (Index = 0; Index < NoHandles; Index++) {
|
|
|
|
//
|
|
// for ConSplitter, no device path
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
&Protocol
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
&Protocol
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
&Protocol
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
GraphicsOutput = Protocol;
|
|
break;
|
|
}
|
|
}
|
|
|
|
FreePool (HandleBuffer);
|
|
if (GraphicsOutput == NULL) {
|
|
return ;
|
|
}
|
|
|
|
ExpectColumns = GraphicsOutput->Mode->Info->VerticalResolution / EFI_GLYPH_WIDTH;
|
|
ExpectRows = GraphicsOutput->Mode->Info->HorizontalResolution / EFI_GLYPH_HEIGHT;
|
|
|
|
MaxMode = gST->ConOut->Mode->MaxMode;
|
|
for (Mode = 0; Mode < MaxMode; Mode++) {
|
|
Status = gST->ConOut->QueryMode (
|
|
gST->ConOut,
|
|
Mode,
|
|
&Columns,
|
|
&Rows
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (Columns == ExpectColumns && Rows == ExpectRows) {
|
|
gST->ConOut->SetMode (gST->ConOut, Mode);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Install Driver to produce rotate screen
|
|
|
|
Arguments:
|
|
(Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - RotateScreen init success
|
|
|
|
Other - No protocol installed, unload driver.
|
|
|
|
--*/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
RotateScreenInstall (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT Event;
|
|
EFI_TPL OrgTpl;
|
|
VOID *Registration;
|
|
|
|
HookDriverBindingLibConstructor (ImageHandle, SystemTable);
|
|
RegisterRotateTouchCallback ();
|
|
|
|
InitializeListHead (&mGopEntryList);
|
|
mHookGraphicsConsoleEntry = NULL;
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
RotateScreenGopCallback,
|
|
NULL,
|
|
&Event
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// Register for protocol notifications on this event
|
|
//
|
|
mGopRegistration = NULL;
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
Event,
|
|
&mGopRegistration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseEvent (Event);
|
|
}
|
|
|
|
//
|
|
// shell 2.0
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
ShellImageCallback,
|
|
NULL,
|
|
&Event
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
Registration = NULL;
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiShellProtocolGuid,
|
|
Event,
|
|
&Registration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseEvent (Event);
|
|
}
|
|
|
|
|
|
//
|
|
// shell 1.0
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
ShellImageCallback,
|
|
NULL,
|
|
&Event
|
|
);
|
|
if (Status != EFI_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
Registration = NULL;
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gEfiShellEnvironment2Guid,
|
|
Event,
|
|
&Registration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseEvent (Event);
|
|
}
|
|
|
|
|
|
mReadyToBoot = FALSE;
|
|
Status = EfiCreateEventReadyToBootEx (
|
|
TPL_NOTIFY,
|
|
RotateScreenReadyToBootCallback,
|
|
NULL,
|
|
&Event
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseEvent (Event);
|
|
}
|
|
|
|
ImageStart = gBS->StartImage;
|
|
gBS->StartImage = RotateScreenStartImage;
|
|
|
|
//
|
|
// re-calculate Boot Services header crc
|
|
//
|
|
OrgTpl = gBS->RaiseTPL (TPL_NOTIFY);
|
|
gBS->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32 (
|
|
(UINT8 *) &gBS->Hdr,
|
|
gBS->Hdr.HeaderSize,
|
|
&gBS->Hdr.CRC32
|
|
);
|
|
gBS->RestoreTPL (OrgTpl);
|
|
|
|
return Status;
|
|
}
|
|
|