1206 lines
34 KiB
C
1206 lines
34 KiB
C
/** @file
|
|
Console for formBrowser
|
|
;******************************************************************************
|
|
;* 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 "InternalH2OFormBrowser.h"
|
|
#include <Protocol/SetupMouse.h>
|
|
#include <Guid/HotKeyEvent.h>
|
|
|
|
extern EFI_GUID gH2ODisplayTypePrimaryDisplayGuid;
|
|
|
|
H2O_FORM_BROWSER_CONSOLE_DEV **mConsoleDevList = NULL;
|
|
UINT32 mConsoleDevListCount = 0;
|
|
#define EISA_SERIAL_DEVICE_ID 0x0501
|
|
|
|
CONSOLE_TYPE_MAP mConsoleMap[] = {
|
|
{&gEfiSimpleTextInProtocolGuid, H2O_FORM_BROWSER_CONSOLE_STI},
|
|
{&gEfiSimpleTextInputExProtocolGuid, H2O_FORM_BROWSER_CONSOLE_STI2},
|
|
{&gEfiSimplePointerProtocolGuid, H2O_FORM_BROWSER_CONSOLE_SP},
|
|
{&gEfiAbsolutePointerProtocolGuid, H2O_FORM_BROWSER_CONSOLE_AP},
|
|
{&gEfiSimpleTextOutProtocolGuid, H2O_FORM_BROWSER_CONSOLE_STO},
|
|
{&gEfiGraphicsOutputProtocolGuid, H2O_FORM_BROWSER_CONSOLE_GO},
|
|
{NULL, 0},
|
|
};
|
|
|
|
/**
|
|
Converts a device path to an Unicode string.
|
|
|
|
This function is dependent on the Device Path To Text protocol. If protocol
|
|
does not installed, then return unknown device path L"?" directly.
|
|
|
|
@param [in] DevPath Given device path instance
|
|
|
|
@return Converted string from given device path.(Caller is responsible to free the string)
|
|
@retval L"" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.
|
|
**/
|
|
STATIC
|
|
CHAR8 *
|
|
DevicePathToAsciiStr (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevPath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
|
|
CHAR16 *ToText;
|
|
CHAR8 *AsciiText;
|
|
UINTN AsciiTextSize;
|
|
|
|
AsciiText = NULL;
|
|
|
|
if (DevPath == NULL) {
|
|
AsciiText = AllocatePool (sizeof (CHAR8));
|
|
if (AsciiText != NULL) {
|
|
AsciiText[0] = '\0';
|
|
}
|
|
} else {
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiDevicePathToTextProtocolGuid,
|
|
NULL,
|
|
(VOID **) &DevPathToText
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
ToText = DevPathToText->ConvertDevicePathToText (
|
|
DevPath,
|
|
FALSE,
|
|
TRUE
|
|
);
|
|
if (ToText != NULL) {
|
|
AsciiTextSize = (StrLen (ToText) + 1);
|
|
AsciiText = AllocateZeroPool (AsciiTextSize);
|
|
if (AsciiText != NULL) {
|
|
UnicodeStrToAsciiStrS (ToText, AsciiText, AsciiTextSize);
|
|
}
|
|
FreePool (ToText);
|
|
}
|
|
}
|
|
}
|
|
return AsciiText;
|
|
}
|
|
|
|
/**
|
|
Check whether a given device handle belongs to console device type or not
|
|
|
|
@param[in] Handle The device handle to be processed
|
|
|
|
@return TRUE The device handle belongs to console device type
|
|
@retval FALSE The device handle does not belong to console device type
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsConsoleDeviceType (
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
UINTN Index;
|
|
VOID *Instance;
|
|
EFI_STATUS Status;
|
|
|
|
Index = 0;
|
|
while (mConsoleMap[Index].Guid != NULL) {
|
|
Status = gBS->HandleProtocol (Handle, mConsoleMap[Index].Guid, (VOID **) &Instance);
|
|
if (!EFI_ERROR (Status)) {
|
|
return TRUE;
|
|
}
|
|
|
|
Index++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check whether a given device type belongs to console input device type or not
|
|
|
|
@param[in] DeviceType The device type to be processed
|
|
|
|
@return TRUE The device type belongs to console input device type
|
|
@retval FALSE The device type does not belongs to console input device type
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsConInDeviceType (
|
|
IN H2O_CONSOLE_DEVICE_TYPE DeviceType
|
|
)
|
|
{
|
|
if ((DeviceType & H2O_FORM_BROWSER_CONSOLE_STI) ||
|
|
(DeviceType & H2O_FORM_BROWSER_CONSOLE_STI2) ||
|
|
(DeviceType & H2O_FORM_BROWSER_CONSOLE_SP) ||
|
|
(DeviceType & H2O_FORM_BROWSER_CONSOLE_AP)) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Check whether a given device type belongs to console output device type or not
|
|
|
|
@param[in] DeviceType The device type to be processed
|
|
|
|
@return TRUE The device type belongs to console output device type
|
|
@retval FALSE The device type does not belongs to console output device type
|
|
|
|
**/
|
|
BOOLEAN
|
|
IsConOutDeviceType (
|
|
IN H2O_CONSOLE_DEVICE_TYPE DeviceType
|
|
)
|
|
{
|
|
if ((DeviceType & H2O_FORM_BROWSER_CONSOLE_STO) ||
|
|
(DeviceType & H2O_FORM_BROWSER_CONSOLE_GO)) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsPrimaryDisplay (
|
|
IN EFI_HANDLE DevHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
VOID *Instance;
|
|
|
|
Status = gBS->HandleProtocol (DevHandle, &gH2ODisplayTypePrimaryDisplayGuid, (VOID **)&Instance);
|
|
if (Status == EFI_SUCCESS) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
HasPcdDisplayType (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN EFI_HANDLE DevHandle,
|
|
IN OUT EFI_GUID *DEGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
H2O_DISPLAY_ENGINE_PROTOCOL *H2ODisplayEngine;
|
|
UINT32 DEIndex;
|
|
VOID *Instance;
|
|
|
|
|
|
for (DEIndex = 0; DEIndex < Private->EngineListCount; DEIndex++) {
|
|
H2ODisplayEngine = Private->EngineList[DEIndex].DisplayEngine;
|
|
Status = gBS->HandleProtocol (DevHandle, &H2ODisplayEngine->Id, (VOID **)&Instance);
|
|
if (Status == EFI_SUCCESS) {
|
|
CopyMem (DEGuid, &H2ODisplayEngine->Id, sizeof (EFI_GUID));
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
ZeroMem (DEGuid, sizeof (EFI_GUID));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOLEAN
|
|
HasConOutDevice (
|
|
VOID
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
if (mConsoleDevList == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (Index = 0; Index < mConsoleDevListCount; Index++) {
|
|
if (IsConOutDeviceType (mConsoleDevList[Index]->DeviceType)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Adjust console pair if console redirection exist;
|
|
pair SimpleTextOut with UART to text mode display engine
|
|
|
|
@param [in,out] DisplayEngineList Pointer of the display engine list
|
|
@param [in] EngineListCount The count of the engine list
|
|
@param [in] ConsoleDevList Pointer of the console device list
|
|
@param [in] ConsoleDevListCount The count of console device list
|
|
|
|
@return EFI_SUCCESS Adjust console pair success
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
FormsBrowserArrangeConsoles (
|
|
IN OUT DISPLAY_ENGINE_LIST_ENTRY *DisplayEngineList,
|
|
IN UINTN EngineListCount,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV **ConsoleDevList,
|
|
IN UINT32 ConsoleDevListCount
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add display engine
|
|
|
|
@param [in] Private Formbrowser private data
|
|
@param [in] H2ODisplayEngine H2O diaplay engine instance
|
|
|
|
@return EFI_SUCCESS Adjust console pair success
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
FBAddDisplayEngine (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN H2O_DISPLAY_ENGINE_PROTOCOL *H2ODisplayEngine
|
|
)
|
|
{
|
|
UINTN OldBufferSize;
|
|
UINTN NewBufferSize;
|
|
|
|
OldBufferSize = Private->EngineListCount * sizeof (DISPLAY_ENGINE_LIST_ENTRY);
|
|
NewBufferSize = (Private->EngineListCount + 1) * sizeof (DISPLAY_ENGINE_LIST_ENTRY);
|
|
Private->EngineList = ReallocatePool (OldBufferSize, NewBufferSize, Private->EngineList);
|
|
if (Private->EngineList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Private->EngineList[Private->EngineListCount].DisplayEngine = H2ODisplayEngine;
|
|
Private->EngineList[Private->EngineListCount].AttachedConsoleCount = 0;
|
|
Private->EngineListCount++;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add those wait for event to input check event list
|
|
|
|
@param [in] Private Form browser pricvate data
|
|
@param [in] Handle Handle
|
|
@param [in] DevicePath Device path
|
|
@param [in] DeviceType Device type
|
|
|
|
@return EFI_SUCCESS Add input check event success
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
FBAddInputCheckEvent (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN EFI_HANDLE Handle,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConDev,
|
|
IN H2O_CONSOLE_DEVICE_TYPE DeviceType
|
|
)
|
|
{
|
|
EFI_EVENT *OldInputEventList;
|
|
H2O_INPUT_EVENT_DESCRIPTION *OldInputEventDescList;
|
|
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;
|
|
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
|
|
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
|
|
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
|
|
VOID *Protocol;
|
|
EFI_EVENT Event;
|
|
EFI_STATUS Status;
|
|
|
|
Event = NULL;
|
|
Protocol = NULL;
|
|
|
|
switch (DeviceType){
|
|
|
|
case H2O_FORM_BROWSER_CONSOLE_STI:
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
(VOID **) &SimpleTextIn
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Event = SimpleTextIn->WaitForKey;
|
|
Protocol = (VOID *)SimpleTextIn;
|
|
}
|
|
break;
|
|
|
|
case H2O_FORM_BROWSER_CONSOLE_STI2:
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
(VOID **) &SimpleTextInEx
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Event = SimpleTextInEx->WaitForKeyEx;
|
|
Protocol = (VOID *)SimpleTextInEx;
|
|
}
|
|
break;
|
|
|
|
case H2O_FORM_BROWSER_CONSOLE_SP:
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiSimplePointerProtocolGuid,
|
|
(VOID **) &SimplePointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Event = SimplePointer->WaitForInput;
|
|
Protocol = (VOID *)SimplePointer;
|
|
|
|
}
|
|
break;
|
|
|
|
case H2O_FORM_BROWSER_CONSOLE_AP:
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiAbsolutePointerProtocolGuid,
|
|
(VOID **) &AbsolutePointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Event = AbsolutePointer->WaitForInput;
|
|
Protocol = (VOID *)AbsolutePointer;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT (FALSE);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Event == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
|
|
OldInputEventList = mInputEventList;
|
|
OldInputEventDescList = mInputEventDescList;
|
|
mInputEventList = (EFI_EVENT*) AllocateZeroPool ((mInputEventListCount + 1) * sizeof (EFI_EVENT));
|
|
mInputEventDescList = (H2O_INPUT_EVENT_DESCRIPTION*) AllocateZeroPool ((mInputEventListCount + 1) * sizeof (H2O_INPUT_EVENT_DESCRIPTION));
|
|
if (mInputEventList == NULL || mInputEventDescList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
CopyMem (mInputEventList , OldInputEventList , sizeof (EFI_EVENT) * (UINTN)mInputEventListCount);
|
|
CopyMem (mInputEventDescList, OldInputEventDescList, sizeof (H2O_INPUT_EVENT_DESCRIPTION) * (UINTN)mInputEventListCount);
|
|
|
|
mInputEventList[mInputEventListCount] = Event;
|
|
mInputEventDescList[mInputEventListCount].DeviceType = DeviceType;
|
|
mInputEventDescList[mInputEventListCount].Protocol = Protocol;
|
|
mInputEventDescList[mInputEventListCount].Handle = Handle;
|
|
mInputEventDescList[mInputEventListCount].ConDev = ConDev;
|
|
|
|
mInputEventListCount++;
|
|
|
|
|
|
FBFreePool ((VOID **)&OldInputEventList);
|
|
FBFreePool ((VOID **)&OldInputEventDescList);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Remove device handle from input check event list
|
|
|
|
@param [in] Private Pointer to form browser pricvate data
|
|
@param [in] Handle The device handle to be processed
|
|
|
|
@return EFI_SUCCESS Remove input check event successfully
|
|
@return EFI_INVALID_PARAMETER Private is NULL
|
|
@return EFI_NOT_FOUND There is no event in the list
|
|
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
FBRemoveInputCheckEvent (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
EFI_TPL OriginalTpl;
|
|
EFI_EVENT *OldInputEventList;
|
|
H2O_INPUT_EVENT_DESCRIPTION *OldInputEventDescList;
|
|
|
|
|
|
if (Private == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (mInputEventListCount == 0 || mInputEventDescList == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// When modify mInputEventListCount and mInputEventList, reise TPL to prevent HotPlug Stop function to use these
|
|
//
|
|
OriginalTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
Index = 0;
|
|
while (Index < mInputEventListCount) {
|
|
if (mInputEventDescList[Index].Handle == Handle) {
|
|
if (mInputEventListCount == 1) {
|
|
FreePool (mInputEventList);
|
|
FreePool (mInputEventDescList);
|
|
mInputEventList = NULL;
|
|
mInputEventDescList = NULL;
|
|
mInputEventListCount = 0;
|
|
break;
|
|
}
|
|
|
|
OldInputEventList = mInputEventList;
|
|
OldInputEventDescList = mInputEventDescList;
|
|
|
|
mInputEventList = (EFI_EVENT *) AllocateZeroPool ((mInputEventListCount - 1) * sizeof (EFI_EVENT));
|
|
mInputEventDescList = (H2O_INPUT_EVENT_DESCRIPTION *) AllocateZeroPool ((mInputEventListCount - 1) * sizeof (H2O_INPUT_EVENT_DESCRIPTION));
|
|
if (mInputEventList == NULL || mInputEventDescList == NULL) {
|
|
mInputEventList = NULL;
|
|
mInputEventDescList = NULL;
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
if (Index == 0) {
|
|
CopyMem (mInputEventList , &OldInputEventList[1] , (mInputEventListCount - 1) * sizeof (EFI_EVENT));
|
|
CopyMem (mInputEventDescList, &OldInputEventDescList[1], (mInputEventListCount - 1) * sizeof (H2O_INPUT_EVENT_DESCRIPTION));
|
|
} else {
|
|
CopyMem (mInputEventList , OldInputEventList , Index * sizeof (EFI_EVENT));
|
|
CopyMem (mInputEventDescList, OldInputEventDescList, Index * sizeof (H2O_INPUT_EVENT_DESCRIPTION));
|
|
CopyMem (&mInputEventList[Index] , &OldInputEventList[Index + 1] , (mInputEventListCount - Index - 1) * sizeof (EFI_EVENT));
|
|
CopyMem (&mInputEventDescList[Index], &OldInputEventDescList[Index + 1], (mInputEventListCount - Index - 1) * sizeof (H2O_INPUT_EVENT_DESCRIPTION));
|
|
}
|
|
|
|
FBFreePool ((VOID **) &OldInputEventList);
|
|
FBFreePool ((VOID **) &OldInputEventDescList);
|
|
|
|
mInputEventListCount--;
|
|
continue;
|
|
}
|
|
|
|
Index++;
|
|
}
|
|
|
|
gBS->RestoreTPL (OriginalTpl);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
FBAddInputEventList (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConDev
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (!IsConInDeviceType (ConDev->DeviceType)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Status = FBAddInputCheckEvent (Private, ConDev->Handle, ConDev, H2O_FORM_BROWSER_CONSOLE_STI2);
|
|
if (EFI_ERROR (Status)) {
|
|
FBAddInputCheckEvent (Private, ConDev->Handle, ConDev, H2O_FORM_BROWSER_CONSOLE_STI);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Add console device in console device list
|
|
|
|
@param [in] Private Pointer to form browser pricvate data
|
|
@param [in] Handle The device handle to be processed
|
|
|
|
@return A pointer to the added console device data or NULL if it is not a physical device or allocate pool fail
|
|
|
|
**/
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *
|
|
FBAddConsoleDevice (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *ConDev;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
EFI_STATUS Status;
|
|
UINTN OldBufferSize;
|
|
UINTN NewBufferSize;
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Handle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DevicePath = NULL;
|
|
}
|
|
|
|
ConDev = AllocateZeroPool (sizeof (H2O_FORM_BROWSER_CONSOLE_DEV));
|
|
if (ConDev == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
OldBufferSize = mConsoleDevListCount * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *);
|
|
NewBufferSize = (mConsoleDevListCount + 1) * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *);
|
|
mConsoleDevList = ReallocatePool (OldBufferSize, NewBufferSize, mConsoleDevList);
|
|
if (mConsoleDevList == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
mConsoleDevList[mConsoleDevListCount] = ConDev;
|
|
mConsoleDevListCount++;
|
|
|
|
ConDev->Size = sizeof (H2O_FORM_BROWSER_CONSOLE_DEV);
|
|
ConDev->Name = DevicePathToAsciiStr (DevicePath);
|
|
ConDev->DevicePath = DevicePath;
|
|
ConDev->Handle = Handle;
|
|
ConDev->DeviceType = FBGetDeviceType (Handle);
|
|
ConDev->ConsoleId = H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED;
|
|
CopyGuid (&ConDev->DisplayEngine, &gZeroGuid);
|
|
|
|
return ConDev;
|
|
}
|
|
|
|
/**
|
|
Remove console device from console device list
|
|
|
|
@param [in] Private Pointer to form browser pricvate data
|
|
@param [in] Handle The device handle to be processed
|
|
|
|
@return EFI_SUCCESS Add input check event success
|
|
@return EFI_INVALID_PARAMETER Private is NULL
|
|
@return EFI_NOT_FOUND There is no device in the list
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FBRemoveConsoleDevice (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV **OldConsoleDevList;
|
|
|
|
if (Private == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (mConsoleDevListCount == 0 || mConsoleDevList == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
for (Index = 0; Index < mConsoleDevListCount; Index++) {
|
|
if (mConsoleDevList[Index]->Handle == Handle) {
|
|
break;
|
|
}
|
|
}
|
|
if (Index == mConsoleDevListCount) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
FBRemoveInputCheckEvent (Private, Handle);
|
|
OldConsoleDevList = mConsoleDevList;
|
|
|
|
if (mConsoleDevListCount >= 2) {
|
|
mConsoleDevList = (H2O_FORM_BROWSER_CONSOLE_DEV **) AllocateZeroPool ((mConsoleDevListCount - 1) * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *));
|
|
if (mConsoleDevList == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
if (Index == 0) {
|
|
CopyMem (mConsoleDevList, &OldConsoleDevList[1], (mConsoleDevListCount - 1) * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *));
|
|
} else {
|
|
CopyMem (mConsoleDevList , OldConsoleDevList , Index * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *));
|
|
CopyMem (&mConsoleDevList[Index], &OldConsoleDevList[Index + 1] , (mConsoleDevListCount - Index - 1) * sizeof (H2O_FORM_BROWSER_CONSOLE_DEV *));
|
|
}
|
|
} else {
|
|
mConsoleDevList = NULL;
|
|
}
|
|
|
|
FBFreePool ((VOID **) &OldConsoleDevList);
|
|
mConsoleDevListCount--;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Free console list
|
|
|
|
@param [in] Private Pointer to form browser private data
|
|
|
|
@retval EFI_SUCCESS Console list in not find
|
|
Free console list successfully
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FBFreeConsoleDevList (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
|
|
if (mConsoleDevList == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
for (Index = 0; Index < mConsoleDevListCount; Index++) {
|
|
if (mConsoleDevList[Index] != NULL) {
|
|
if (mConsoleDevList[Index]->Name != NULL) {
|
|
FreePool ((VOID *)mConsoleDevList[Index]->Name);
|
|
}
|
|
FreePool ((VOID *)mConsoleDevList[Index]);
|
|
}
|
|
}
|
|
|
|
FreePool (mConsoleDevList);
|
|
mConsoleDevList = NULL;
|
|
mConsoleDevListCount = 0;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get device type
|
|
|
|
@param [in] Handle Handle whcih belong to device
|
|
|
|
@retval DeviceType Device type
|
|
Free console list successfully
|
|
|
|
**/
|
|
H2O_CONSOLE_DEVICE_TYPE
|
|
FBGetDeviceType (
|
|
IN EFI_HANDLE Handle
|
|
)
|
|
{
|
|
UINTN TypeIndex;
|
|
UINT8 *DummyProtocol;
|
|
H2O_CONSOLE_DEVICE_TYPE DeviceType;
|
|
EFI_STATUS Status;
|
|
|
|
DeviceType = H2O_FORM_BROWSER_CONSOLE_SYSTEM;
|
|
for (TypeIndex = 0; mConsoleMap[TypeIndex].Guid != NULL; TypeIndex++) {
|
|
Status = gBS->HandleProtocol (Handle, mConsoleMap[TypeIndex].Guid, (VOID **) &DummyProtocol);
|
|
if (!EFI_ERROR (Status)) {
|
|
DeviceType |= mConsoleMap[TypeIndex].Type;
|
|
}
|
|
}
|
|
|
|
return DeviceType;
|
|
}
|
|
|
|
/**
|
|
Set activated engine
|
|
|
|
@param [in] Private Formvrwser private data
|
|
@param [in] ConsoleId Console id
|
|
|
|
@retval EFI_SUCCESS Set activated engine successfully
|
|
Free console list successfully
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FBSetActivedEngine (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN H2O_CONSOLE_ID ConsoleId
|
|
)
|
|
{
|
|
ASSERT (ConsoleId > 0 && ((UINTN)ConsoleId <= Private->EngineListCount));
|
|
if (ConsoleId <= 0 || ((UINTN)ConsoleId > Private->EngineListCount)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private->ActivatedEngine = (INT32)(ConsoleId - 1);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Install USB enumeration protocol to make sure USB keyboard is initialized.
|
|
**/
|
|
VOID
|
|
NotifyUsbKbInitial (
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE Handle;
|
|
UINT8 *Instance;
|
|
|
|
Status = gBS->LocateProtocol (&gEfiUsbEnumerationGuid, NULL, (VOID **) &Instance);
|
|
if (EFI_ERROR (Status)) {
|
|
Handle = 0;
|
|
gBS->InstallProtocolInterface (
|
|
&Handle,
|
|
&gEfiUsbEnumerationGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Find device path node.
|
|
|
|
@param [in] DevPath Given device path instance
|
|
@param [in] DevPathType Device path type
|
|
@param [in] DevPathSubType Device path sub type
|
|
|
|
@return Device path
|
|
**/
|
|
EFI_DEVICE_PATH_PROTOCOL *
|
|
LocateDevicePathNode (
|
|
IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
IN UINT8 DevPathType,
|
|
IN UINT8 DevPathSubType
|
|
)
|
|
{
|
|
if (DevicePath == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
while (!IsDevicePathEnd (DevicePath)) {
|
|
if (DevicePath->Type == DevPathType && DevicePath->SubType == DevPathSubType) {
|
|
return DevicePath;
|
|
}
|
|
DevicePath = NextDevicePathNode(DevicePath);
|
|
}
|
|
|
|
if (DevPathType == END_DEVICE_PATH_TYPE && DevPathSubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) {
|
|
return DevicePath;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
H2O_CONSOLE_ID
|
|
FindPreferedEngineConsoleId (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
IN BOOLEAN CheckGOP
|
|
)
|
|
{
|
|
UINTN Index;
|
|
DISPLAY_ENGINE_LIST_ENTRY *EngineEntry;
|
|
INT32 EngineIndex;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev;
|
|
EFI_DEVICE_PATH_PROTOCOL *UartDP;
|
|
|
|
//
|
|
// check actived engine firstly
|
|
//
|
|
EngineIndex = Private->ActivatedEngine;
|
|
|
|
do {
|
|
|
|
//
|
|
// check Engine whether has GOP or UART
|
|
//
|
|
EngineEntry = &Private->EngineList[EngineIndex];
|
|
for (Index = 0; Index < EngineEntry->AttachedConsoleCount; Index++) {
|
|
|
|
ConsoleDev = EngineEntry->AttachedConsoleList[Index];
|
|
|
|
if (CheckGOP) {
|
|
if ((ConsoleDev->DeviceType & H2O_FORM_BROWSER_CONSOLE_GO) == H2O_FORM_BROWSER_CONSOLE_GO) {
|
|
break;
|
|
}
|
|
} else {
|
|
UartDP = LocateDevicePathNode (
|
|
ConsoleDev->DevicePath,
|
|
MESSAGING_DEVICE_PATH,
|
|
MSG_UART_DP
|
|
);
|
|
if (UartDP != NULL) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (Index != EngineEntry->AttachedConsoleCount) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// search next engine
|
|
//
|
|
EngineIndex = (EngineIndex + 1) % Private->EngineListCount;
|
|
|
|
} while (EngineIndex != Private->ActivatedEngine);
|
|
|
|
|
|
return (H2O_CONSOLE_ID)(EngineIndex + 1);
|
|
}
|
|
|
|
EFI_STATUS
|
|
FBAddConInDev (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private,
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *UartDP;
|
|
|
|
if (!IsConInDeviceType (ConsoleDev->DeviceType)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (ConsoleDev->ConsoleId == H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED) {
|
|
//
|
|
// new ConIn device
|
|
//
|
|
if (Private->EngineListCount == 1) {
|
|
ConsoleDev->ConsoleId = (H2O_CONSOLE_ID)(Private->ActivatedEngine + 1);
|
|
} else {
|
|
UartDP = LocateDevicePathNode (
|
|
ConsoleDev->DevicePath,
|
|
MESSAGING_DEVICE_PATH,
|
|
MSG_UART_DP
|
|
);
|
|
if (UartDP == NULL) {
|
|
ConsoleDev->ConsoleId = FindPreferedEngineConsoleId (Private, TRUE);
|
|
} else {
|
|
ConsoleDev->ConsoleId = FindPreferedEngineConsoleId (Private, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
FBAddInputEventList (Private, ConsoleDev);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Attach console output device on first supported display engine
|
|
|
|
@param[in] ConsoleDev Pointer to console device
|
|
|
|
@retval EFI_SUCCESS This driver is removed ControllerHandle
|
|
@retval EFI_INVALID_PARAMETER ConsoleDev is NULL
|
|
@retval EFI_NOT_FOUND There is no support display engine for this console device
|
|
|
|
**/
|
|
EFI_STATUS
|
|
AttachToDE (
|
|
IN H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 Index;
|
|
H2O_DISPLAY_ENGINE_PROTOCOL *H2ODisplayEngine;
|
|
EFI_GUID DevDEGuid;
|
|
DISPLAY_ENGINE_LIST_ENTRY *EngineEntry;
|
|
|
|
if (ConsoleDev == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (ConsoleDev->ConsoleId != H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
for (Index = 0; Index < mFBPrivate.EngineListCount; Index++) {
|
|
H2ODisplayEngine = mFBPrivate.EngineList[Index].DisplayEngine;
|
|
if (!IsConOutDeviceType (ConsoleDev->DeviceType)) {
|
|
continue;
|
|
}
|
|
if (HasPcdDisplayType (&mFBPrivate, ConsoleDev->Handle, &DevDEGuid)){
|
|
if (!CompareGuid (&DevDEGuid, &H2ODisplayEngine->Id)) {
|
|
continue;
|
|
}
|
|
}
|
|
Status = H2ODisplayEngine->SupportConsole (H2ODisplayEngine, ConsoleDev);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
ConsoleDev->ConsoleId = (H2O_CONSOLE_ID)(Index + 1);
|
|
CopyGuid (&ConsoleDev->DisplayEngine, &H2ODisplayEngine->Id);
|
|
Status = H2ODisplayEngine->AttachConsole (H2ODisplayEngine, ConsoleDev);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
EngineEntry = &mFBPrivate.EngineList[ConsoleDev->ConsoleId - 1];
|
|
EngineEntry->AttachedConsoleList[EngineEntry->AttachedConsoleCount++] = ConsoleDev;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Init consoles
|
|
|
|
@param [in] Private Formbrowser private data
|
|
|
|
@retval EFI_SUCCESS Init consoles successfully
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FBInitConsoles (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN NumberOfHandle;
|
|
EFI_HANDLE *HandleBuffer;
|
|
H2O_DISPLAY_ENGINE_PROTOCOL *H2ODisplayEngine;
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev;
|
|
UINT32 HandleIndex;
|
|
UINT32 DevIndex;
|
|
INT32 ActivatedEngine;
|
|
|
|
HandleBuffer = NULL;
|
|
|
|
NotifyUsbKbInitial ();
|
|
FBHotPlugInit ();
|
|
if (!Private->IsBdsHotKeyDisabled) {
|
|
Private->OrgBdsHotKeyState = EnableBdsHotKey (FALSE);
|
|
Private->IsBdsHotKeyDisabled = TRUE;
|
|
}
|
|
//
|
|
// Setup Mouse
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gSetupMouseProtocolGuid,
|
|
NULL,
|
|
(VOID **) &Private->SetupMouse
|
|
);
|
|
|
|
//
|
|
// Get all Display Engines
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gH2ODisplayEngineProtocolGuid,
|
|
NULL,
|
|
&NumberOfHandle,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error;
|
|
}
|
|
for (HandleIndex = 0; HandleIndex < NumberOfHandle; HandleIndex++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[HandleIndex],
|
|
&gH2ODisplayEngineProtocolGuid,
|
|
(VOID **) &H2ODisplayEngine
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error;
|
|
}
|
|
|
|
Status = FBAddDisplayEngine (Private, H2ODisplayEngine);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error;
|
|
}
|
|
}
|
|
FreePool (HandleBuffer);
|
|
HandleBuffer = NULL;
|
|
|
|
//
|
|
// Get all console devices
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiDevicePathProtocolGuid,
|
|
NULL,
|
|
&NumberOfHandle,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error;
|
|
}
|
|
for (HandleIndex = 0; HandleIndex < NumberOfHandle; HandleIndex++) {
|
|
if (IsConsoleDeviceType (HandleBuffer[HandleIndex])) {
|
|
ConsoleDev = FBAddConsoleDevice (Private, HandleBuffer[HandleIndex]);
|
|
if (ConsoleDev == NULL) {
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
FreePool (HandleBuffer);
|
|
HandleBuffer = NULL;
|
|
|
|
//
|
|
// If no physical console output device, attach ConSplitter's console device.
|
|
//
|
|
if (!HasConOutDevice ()) {
|
|
if (IsConsoleDeviceType (gST->ConsoleOutHandle)) {
|
|
ConsoleDev = FBAddConsoleDevice (Private, gST->ConsoleOutHandle);
|
|
if (ConsoleDev == NULL) {
|
|
goto Error;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// OEM Kernel Service FormsBrowserArrangeConsoles
|
|
//
|
|
FormsBrowserArrangeConsoles (
|
|
Private->EngineList,
|
|
Private->EngineListCount,
|
|
mConsoleDevList,
|
|
mConsoleDevListCount
|
|
);
|
|
|
|
//
|
|
// process and attach output console
|
|
//
|
|
ActivatedEngine = H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED;
|
|
for (DevIndex = 0; DevIndex < mConsoleDevListCount; DevIndex++) {
|
|
ConsoleDev = mConsoleDevList[DevIndex];
|
|
|
|
if (!IsConOutDeviceType (ConsoleDev->DeviceType)) {
|
|
continue;
|
|
}
|
|
Status = AttachToDE (ConsoleDev);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
if (IsPrimaryDisplay (ConsoleDev->Handle)) {
|
|
ActivatedEngine = ConsoleDev->ConsoleId - 1;
|
|
} else if (!IsConInDeviceType (ConsoleDev->DeviceType) &&
|
|
(ActivatedEngine == H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED)) {
|
|
ActivatedEngine = ConsoleDev->ConsoleId - 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set actived DE to first DE
|
|
//
|
|
if (ActivatedEngine == H2O_FORM_BROWSER_CONSOLE_NOT_ASSIGNED) {
|
|
ActivatedEngine = 0;
|
|
}
|
|
FBSetActivedEngine (Private, (H2O_CONSOLE_ID)(ActivatedEngine + 1));
|
|
|
|
//
|
|
// Set SetupMouseActivatedEngine to first DE with GOP
|
|
//
|
|
Private->SetupMouseConsoleId = FindPreferedEngineConsoleId (Private, TRUE);
|
|
|
|
//
|
|
// Create input event list
|
|
//
|
|
for (DevIndex = 0; DevIndex < mConsoleDevListCount; DevIndex++) {
|
|
ConsoleDev = mConsoleDevList[DevIndex];
|
|
|
|
if (!IsConInDeviceType (ConsoleDev->DeviceType)) {
|
|
continue;
|
|
}
|
|
|
|
FBAddConInDev (Private, ConsoleDev);
|
|
}
|
|
|
|
FBConsplitterUpdateModeData ();
|
|
Private->ConsoleInitComplete = TRUE;
|
|
|
|
if (Private->SetupMouse != NULL) {
|
|
Private->SetupMouse->Start(Private->SetupMouse);
|
|
Private->SetupMouse->SetMode (Private->SetupMouse, EfiSetupMouseScreenGraphics);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
Error:
|
|
|
|
if (HandleBuffer != NULL) {
|
|
FreePool (HandleBuffer);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
if (Private->EngineList != NULL) {
|
|
FreePool (Private->EngineList);
|
|
Private->EngineList = NULL;
|
|
Private->EngineListCount = 0;
|
|
}
|
|
}
|
|
|
|
FBFreeConsoleDevList (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Detach consoles
|
|
|
|
@param [in] Private Formbrowser private data
|
|
|
|
@retval EFI_SUCCESS Detach consoles successfully
|
|
|
|
**/
|
|
EFI_STATUS
|
|
FBDetachConsoles (
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA *Private
|
|
)
|
|
{
|
|
//
|
|
// detach console
|
|
//
|
|
UINT32 Index;
|
|
UINTN Index2;
|
|
EFI_STATUS Status;
|
|
|
|
if (Private->SetupMouse != NULL) {
|
|
Private->SetupMouse->Close (Private->SetupMouse);
|
|
}
|
|
|
|
FBHotPlugShutdown ();
|
|
|
|
for (Index = 0; Index < mConsoleDevListCount; Index++) {
|
|
H2O_FORM_BROWSER_CONSOLE_DEV *ConsoleDev;
|
|
H2O_DISPLAY_ENGINE_PROTOCOL *H2ODisplayEngine;
|
|
|
|
ConsoleDev = mConsoleDevList[Index];
|
|
if (!(ConsoleDev->DeviceType & H2O_FORM_BROWSER_CONSOLE_STO) &&
|
|
!(ConsoleDev->DeviceType & H2O_FORM_BROWSER_CONSOLE_GO)) {
|
|
continue;
|
|
}
|
|
|
|
if (ConsoleDev->ConsoleId != 0) {
|
|
for (Index2 = 0; Index2 < Private->EngineListCount; Index2++) {
|
|
H2ODisplayEngine = Private->EngineList[Index2].DisplayEngine;
|
|
Private->EngineList[Index2].AttachedConsoleCount--;
|
|
Status = H2ODisplayEngine->DetachConsole (H2ODisplayEngine, ConsoleDev);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// free all resource and deattach console
|
|
//
|
|
FBFreePool ((VOID **)&Private->EngineList);
|
|
Private->EngineListCount = 0;
|
|
|
|
FBFreePool ((VOID **)&mInputEventList);
|
|
FBFreePool ((VOID **)&mInputEventDescList);
|
|
|
|
mInputEventListCount = 0;
|
|
|
|
FBFreeConsoleDevList (Private);
|
|
|
|
Private->ConsoleInitComplete = FALSE;
|
|
|
|
if (Private->IsBdsHotKeyDisabled) {
|
|
EnableBdsHotKey (Private->OrgBdsHotKeyState);
|
|
Private->IsBdsHotKeyDisabled = FALSE;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
/**
|
|
Check whether console of formbrowser is initialized
|
|
|
|
@param [in] ConsoleInitComplete Check console is init Complete flag
|
|
@param [in] Private Formbrowser private data
|
|
|
|
**/
|
|
VOID
|
|
FBIsConsoleInit (
|
|
IN BOOLEAN *ConsoleInitComplete,
|
|
IN H2O_FORM_BROWSER_PRIVATE_DATA **Private
|
|
)
|
|
{
|
|
*Private = &mFBPrivate;
|
|
*ConsoleInitComplete = (*Private)->ConsoleInitComplete;
|
|
}
|