490 lines
17 KiB
C
490 lines
17 KiB
C
/** @file
|
|
Entry point and initial functions for H2O local text display engine driver
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2013 - 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 "H2ODisplayEngineLocalText.h"
|
|
#include "LTDEPrint.h"
|
|
|
|
BOOLEAN mIsInNotifyProcess;
|
|
H2O_DISPLAY_ENGINE_PRIVATE_DATA *mDEPrivate;
|
|
|
|
/**
|
|
Get the corresponding mode number of input resolution for specific simple text output device.
|
|
|
|
@param[in] SimpleTextOut A pointer to the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL instance.
|
|
@param[in] TargetColumn Target column value
|
|
@param[in] TargetRow Target row value
|
|
|
|
@return The mode number or -1 if the input resolution is not supported by simple text output device.
|
|
**/
|
|
STATIC
|
|
INT32
|
|
GetModeNum (
|
|
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut,
|
|
IN UINTN TargetColumn,
|
|
IN UINTN TargetRow
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
INT32 Mode;
|
|
UINTN Columns;
|
|
UINTN Rows;
|
|
|
|
for (Mode = 0; Mode < SimpleTextOut->Mode->MaxMode; Mode++) {
|
|
Status = SimpleTextOut->QueryMode (SimpleTextOut, Mode, &Columns, &Rows);
|
|
if (!EFI_ERROR (Status) && Columns == TargetColumn && Rows == TargetRow) {
|
|
return Mode;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
Get the max supported resolution for all attached console output device.
|
|
|
|
@param[in] Private Pointer to display engine private data
|
|
@param[out] SupportedColumn Pointer to supported column value
|
|
@param[out] SupportedRow Pointer to supported row value
|
|
|
|
@retval EFI_SUCCESS Get the supported resolution successfully.
|
|
@retval EFI_NOT_FOUND There is no attached console device or fail to find the supported resolution.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
GetSupportedResolution (
|
|
IN H2O_DISPLAY_ENGINE_PRIVATE_DATA *Private,
|
|
OUT UINTN *SupportedColumn,
|
|
OUT UINTN *SupportedRow
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *Link;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *FirstConDevNode;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode;
|
|
INT32 Mode;
|
|
UINTN Columns;
|
|
UINTN Rows;
|
|
UINTN MaxColumns;
|
|
UINTN MaxRows;
|
|
BOOLEAN Support;
|
|
|
|
if (IsListEmpty (&Private->ConsoleDevListHead)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Link = GetFirstNode (&Private->ConsoleDevListHead);
|
|
FirstConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
|
|
|
|
//
|
|
// Go through all modes of first console device to find out the max resolution which are supported for all console devices.
|
|
//
|
|
MaxColumns = 0;
|
|
MaxRows = 0;
|
|
for (Mode = 0; Mode < FirstConDevNode->SimpleTextOut->Mode->MaxMode; Mode++) {
|
|
Status = FirstConDevNode->SimpleTextOut->QueryMode (FirstConDevNode->SimpleTextOut, Mode, &Columns, &Rows);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Support = TRUE;
|
|
Link = GetNextNode (&Private->ConsoleDevListHead, &FirstConDevNode->Link);
|
|
while (!IsNull (&Private->ConsoleDevListHead, Link)) {
|
|
ConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
|
|
Link = GetNextNode (&Private->ConsoleDevListHead, Link);
|
|
if (GetModeNum (ConDevNode->SimpleTextOut, Columns, Rows) == -1) {
|
|
Support = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (Support && Columns >= MaxColumns && Rows >= MaxRows) {
|
|
MaxColumns = Columns;
|
|
MaxRows = Rows;
|
|
}
|
|
}
|
|
if (MaxColumns != 0 && MaxRows != 0) {
|
|
*SupportedColumn = MaxColumns;
|
|
*SupportedRow = MaxRows;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Set all attached consolut output devices to assigned resolution
|
|
|
|
@param[in] Private Pointer to display engine private data
|
|
@param[in] TargetColumn Target column value
|
|
@param[in] TargetRow Target row value
|
|
|
|
@retval EFI_SUCCESS Set resolution successsfully.
|
|
@retval EFI_UNSUPPORTED Resolution is not supported on one console device.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
SetSimpleTextOutResolution (
|
|
IN H2O_DISPLAY_ENGINE_PRIVATE_DATA *Private,
|
|
IN UINTN TargetColumn,
|
|
IN UINTN TargetRow
|
|
)
|
|
{
|
|
INT32 Mode;
|
|
LIST_ENTRY *Link;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode;
|
|
|
|
//
|
|
// First, check if all console devices support this resolution.
|
|
// If not, return fail early to make sure all console devices keep the original resolution.
|
|
//
|
|
Link = GetFirstNode (&Private->ConsoleDevListHead);
|
|
while (!IsNull (&Private->ConsoleDevListHead, Link)) {
|
|
ConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
|
|
Link = GetNextNode (&Private->ConsoleDevListHead, Link);
|
|
|
|
Mode = GetModeNum (ConDevNode->SimpleTextOut, TargetColumn, TargetRow);
|
|
if (Mode == -1) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
}
|
|
|
|
Link = GetFirstNode (&Private->ConsoleDevListHead);
|
|
while (!IsNull (&Private->ConsoleDevListHead, Link)) {
|
|
ConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
|
|
Link = GetNextNode (&Private->ConsoleDevListHead, Link);
|
|
|
|
Mode = GetModeNum (ConDevNode->SimpleTextOut, TargetColumn, TargetRow);
|
|
if (Mode != ConDevNode->SimpleTextOut->Mode->Mode) {
|
|
ConDevNode->SimpleTextOut->SetMode (ConDevNode->SimpleTextOut, Mode);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add new console to the console list.
|
|
|
|
@param [in] This A pointer to the H2O_DISPLAY_ENGINE_PROTOCOL instance.
|
|
@param [in] ConsoleHandle A pointer to the input console handle instance.
|
|
|
|
@retval EFI_SUCCESS Add new console to console list successful.
|
|
@retval EFI_INVALID_PARAMETER This is NULL, or ConsoleDev is NULL.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LocalTextInitConsole (
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
if (This == NULL || ConsoleDev == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Attach a specific console to this display engine.
|
|
|
|
@param [in] This A pointer to the H2O_DISPLAY_ENGINE_PROTOCOL instance.
|
|
@param [in] ConsoleDev A pointer to input H2O_FORM_BROWSER_CONSOLE_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Attach new console successful.
|
|
@retval EFI_INVALID_PARAMETER This is NULL, or ConsoleDev is NULL.
|
|
@retval EFI_UNSUPPORTED This display engine doesn't support input console device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LocalTextAttachConsole (
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
H2O_DISPLAY_ENGINE_PRIVATE_DATA *Private;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode;
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOut;
|
|
UINT32 HorizontalResolution;
|
|
UINT32 VerticalResolution;
|
|
UINTN Column;
|
|
UINTN Row;
|
|
|
|
if (This == NULL || ConsoleDev == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (ConsoleDev->Handle, &gEfiSimpleTextOutProtocolGuid, (VOID **) &SimpleTextOut);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
Status = gBS->HandleProtocol (ConsoleDev->Handle, &gEfiGraphicsOutputProtocolGuid, (VOID **) &GraphicsOut);
|
|
if (EFI_ERROR (Status)) {
|
|
GraphicsOut = NULL;
|
|
}
|
|
|
|
Private = H2O_DISPLAY_ENGINE_PRIVATE_DATA_FROM_PROTOCOL (This);
|
|
|
|
ConDevNode = (H2O_FORM_BROWSER_CONSOLE_DEV_NODE *) AllocatePool (sizeof (H2O_FORM_BROWSER_CONSOLE_DEV_NODE));
|
|
if (ConDevNode == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
ConDevNode->Signature = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_SIGNATURE;
|
|
ConDevNode->SimpleTextOut = SimpleTextOut;
|
|
ConDevNode->GraphicsOut = GraphicsOut;
|
|
ConDevNode->Handle = ConsoleDev->Handle;
|
|
ConDevNode->ConDevStatus = CONSOLE_DEVICE_STATUS_INIT;
|
|
ConDevNode->ConsoleDev = AllocateCopyPool (sizeof (H2O_FORM_BROWSER_CONSOLE_DEV), ConsoleDev);
|
|
if (ConDevNode->ConsoleDev == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
InsertTailList (&Private->ConsoleDevListHead, &ConDevNode->Link);
|
|
|
|
SimpleTextOut->EnableCursor (SimpleTextOut, FALSE);
|
|
|
|
GetDisplayEngineResolutionByPcd (&This->Id, &HorizontalResolution, &VerticalResolution);
|
|
Status = SetSimpleTextOutResolution (Private, HorizontalResolution / EFI_GLYPH_WIDTH, VerticalResolution / EFI_GLYPH_HEIGHT);
|
|
if (!EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
Status = SetSimpleTextOutResolution (
|
|
Private,
|
|
PcdGet32 (PcdDefaultHorizontalResolution) / EFI_GLYPH_WIDTH,
|
|
PcdGet32 (PcdDefaultVerticalResolution) / EFI_GLYPH_HEIGHT
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
Status = GetSupportedResolution (Private, &Column, &Row);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = SetSimpleTextOutResolution (Private, Column, Row);
|
|
if (!EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
}
|
|
|
|
//
|
|
// After attaching this console, it can't find the supported resolution for all consoles. Remove it and return fail.
|
|
//
|
|
LocalTextDetachConsole (This, ConsoleDev);
|
|
return EFI_UNSUPPORTED;
|
|
|
|
Done:
|
|
Status = DEConOutQueryModeWithoutModeNumer (&mScreenMaxX, &mScreenMaxY);
|
|
if (!EFI_ERROR (Status)) {
|
|
mScreenMaxX--;
|
|
mScreenMaxY--;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Detach a specific console from this display engine.
|
|
|
|
@param [in] This A pointer to the H2O_DISPLAY_ENGINE_PROTOCOL instance.
|
|
@param [in] ConsoleDev A pointer to input H2O_FORM_BROWSER_CONSOLE_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Detach a console device from the device engine successful.
|
|
@retval EFI_INVALID_PARAMETER This is NULL, or ConsoleDev is NULL.
|
|
@retval EFI_NOT_FOUND The input device console isn't attached to the display engine.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LocalTextDetachConsole (
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
H2O_DISPLAY_ENGINE_PRIVATE_DATA *Private;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV_NODE *ConDevNode;
|
|
LIST_ENTRY *Link;
|
|
|
|
if (This == NULL || ConsoleDev == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private = H2O_DISPLAY_ENGINE_PRIVATE_DATA_FROM_PROTOCOL (This);
|
|
|
|
if (IsListEmpty (&Private->ConsoleDevListHead)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// If call this function during processing notify function, replace fake protocol on this console device.
|
|
// It can make sure that interruped notify function can be executed successfully.
|
|
// After interruped notify function is finished, remove the console device.
|
|
//
|
|
if (mIsInNotifyProcess) {
|
|
Status = DEReplaceFakeConOutDev (Private, ConsoleDev->Handle);
|
|
return Status;
|
|
}
|
|
|
|
Link = Private->ConsoleDevListHead.ForwardLink;
|
|
while (TRUE) {
|
|
ConDevNode = H2O_FORM_BROWSER_CONSOLE_DEV_NODE_FROM_LINK (Link);
|
|
if (ConsoleDev->Handle == ConDevNode->ConsoleDev->Handle) {
|
|
//
|
|
// Remove Console Device Node
|
|
//
|
|
RemoveEntryList (&ConDevNode->Link);
|
|
FreePool (ConDevNode->ConsoleDev);
|
|
FreePool (ConDevNode);
|
|
DEBUG ((EFI_D_INFO, "Device is detached\n"));
|
|
if (IsListEmpty (&Private->ConsoleDevListHead) && mDEPrivate->DEStatus != DISPLAY_ENGINE_STATUS_AT_POPUP_DIALOG) {
|
|
DEExit ();
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
//
|
|
// Get Next Console
|
|
//
|
|
if (IsNodeAtEnd (&Private->ConsoleDevListHead, Link)) {
|
|
break;
|
|
}
|
|
Link = Link->ForwardLink;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Report which console devices are supported by this display engine.
|
|
|
|
@param[in] This A pointer to the H2O_DISPLAY_ENGINE_PROTOCOL instance.
|
|
@param[in] ConsoleDev A pointer to input H2O_FORM_BROWSER_CONSOLE_DEV instance.
|
|
|
|
@retval EFI_SUCCESS Report supported console device type successful.
|
|
@retval EFI_UNSUPPORTED This display engine doesn't support input console device.
|
|
@retval EFI_INVALID_PARAMETER This is NULL or ConsoleDev is NULL.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LocalTextSupportConsole (
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
|
|
if (This == NULL || ConsoleDev == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (ConsoleDev->Handle, &gEfiSimpleTextOutProtocolGuid, (VOID **) &SimpleTextOut);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add the notification to the notification queue and signal the Notification event.
|
|
|
|
@param [in] This A pointer to the H2O_DISPLAY_ENGINE_PROTOCOL instance.
|
|
@param [in] Notify A pointer to the H2O_DISPLAY_ENGINE_EVT instance.
|
|
|
|
@retval EFI_SUCCESS Register notify successful.
|
|
@retval EFI_INVALID_PARAMETER This is NULL or Notify is NULL.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LocalTextNotify (
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *This,
|
|
IN CONST H2O_DISPLAY_ENGINE_EVT *Notify
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
mIsInNotifyProcess = TRUE;
|
|
Status = DEEventCallback (This, Notify);
|
|
mIsInNotifyProcess = FALSE;
|
|
|
|
DERemoveFakeConOutDev (mDEPrivate);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Initizlize private data for local text display engine and install display engine protocol
|
|
|
|
@param [in] ImageHandle The image handle
|
|
@param [in] SystemTable The system table
|
|
|
|
@retval EFI_SUCCESS Success to initialize private data and install display engine protocol
|
|
@retval EFI_OUT_OF_RESOURCES Display engine private data allocate fail
|
|
@retval Other Fail to initialize display engine private data
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
H2ODisplayEngineLocalTextEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_GUID Guid = H2O_DISPLAY_ENGINE_LOCAL_TEXT_GUID;
|
|
|
|
mDEPrivate = (H2O_DISPLAY_ENGINE_PRIVATE_DATA*) AllocateZeroPool (sizeof (H2O_DISPLAY_ENGINE_PRIVATE_DATA));
|
|
if (mDEPrivate == NULL) {
|
|
DEBUG ((EFI_D_INFO, "H2ODisplayEngineLocalTextEntryPoint() mDEPrivate allocate pool fail.\n"));
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
mDEPrivate->Signature = H2O_DISPLAY_ENGINE_SIGNATURE;
|
|
mDEPrivate->ImageHandle = ImageHandle;
|
|
mDEPrivate->DEStatus = DISPLAY_ENGINE_STATUS_AT_MENU;
|
|
InitializeListHead (&mDEPrivate->ConsoleDevListHead);
|
|
InitializeListHead (&mDEPrivate->PanelListHead);
|
|
|
|
Status = gBS->LocateProtocol (&gH2OFormBrowserProtocolGuid, NULL, (VOID **) &mDEPrivate->FBProtocol);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "[H2ODisplayEngineLib] locate protocol fail in\n"));
|
|
DEBUG ((EFI_D_ERROR, "H2ODisplayEngineLocalTextEntryPoint function\n"));
|
|
return Status;
|
|
}
|
|
|
|
mDEPrivate->DisplayEngine.Size = (UINT32) sizeof (H2O_DISPLAY_ENGINE_PROTOCOL);
|
|
mDEPrivate->DisplayEngine.InitConsole = LocalTextInitConsole;
|
|
mDEPrivate->DisplayEngine.AttachConsole = LocalTextAttachConsole;
|
|
mDEPrivate->DisplayEngine.DetachConsole = LocalTextDetachConsole;
|
|
mDEPrivate->DisplayEngine.SupportConsole = LocalTextSupportConsole;
|
|
mDEPrivate->DisplayEngine.Notify = LocalTextNotify;
|
|
CopyGuid (&mDEPrivate->DisplayEngine.Id, &Guid);
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gH2ODisplayEngineProtocolGuid,
|
|
&mDEPrivate->DisplayEngine,
|
|
NULL
|
|
);
|
|
return Status;
|
|
}
|