/** @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 #include 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; }