alder_lake_bios/Insyde/InsydeModulePkg/Universal/UserInterface/SetupMouseDxe/BitlockerVirtualKeyboard.c

392 lines
11 KiB
C

/** @file
Routines for displaying virtual keyboard in bitlocker
;******************************************************************************
;* Copyright (c) 2014 - 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 <PiDxe.h>
#include <Guid/ReturnFromImage.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DevicePathLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/SetupMouse.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimplePointer.h>
#include <Protocol/AbsolutePointer.h>
#include <Protocol/LoadedImage.h>
#include "SetupMouse.h"
#define TICKS_PER_MS 10000U
extern PRIVATE_MOUSE_DATA *mPrivate;
BOOLEAN
EFIAPI
IsWindows (
EFI_HANDLE Handle,
UINT32 *VersionMS,
UINT32 *VersionLS
);
VOID
EFIAPI
OutputDevicePluginCallback (
IN EFI_EVENT Event,
IN VOID *Context
);
/**
Check if this image is from CDROM device.
@param[in] ImageHandle The image handle being queried.
@retval TRUE This image is from CDROM device.
@retval FALSE This image is not from CDROM device.
**/
STATIC
BOOLEAN
IsCdRomDevice (
IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
EFI_LOADED_IMAGE *LoadedImage;
EFI_DEVICE_PATH_PROTOCOL *DevPath;
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage);
if (EFI_ERROR (Status)) {
return FALSE;
}
Status = gBS->HandleProtocol (LoadedImage->DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **) &DevPath);
if (EFI_ERROR (Status)) {
return FALSE;
}
while (!IsDevicePathEnd (DevPath)) {
if ((DevicePathType (DevPath) == MEDIA_DEVICE_PATH) &&
(DevicePathSubType (DevPath) == MEDIA_CDROM_DP)) {
return TRUE;
}
DevPath = NextDevicePathNode (DevPath);
}
return FALSE;
}
/**
Close check read key event
@param [in] Event Event
@param [in] Context Passed parameter to event handler
**/
VOID
EFIAPI
DisableCheckReadKeyHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
PRIVATE_MOUSE_DATA *Private;
Private = mPrivate;
gBS->CloseEvent (Private->DisableCheckReadKeyEvent);
Private->DisableCheckReadKeyEvent = NULL;
if (Private->CheckReadKeyEvent != NULL) {
gBS->CloseEvent (Private->CheckReadKeyEvent);
Private->CheckReadKeyEvent = NULL;
}
}
/**
Close setup mouse if no read key at a period time
@param [in] Event Event
@param [in] Context Passed parameter to event handler
**/
VOID
EFIAPI
CheckReadKeyHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
PRIVATE_MOUSE_DATA *Private;
Private = mPrivate;
if (!Private->ReadKeyFlag) {
Private->NoReadKeyCount++;
} else {
Private->NoReadKeyCount = 0;
}
Private->ReadKeyFlag = FALSE;
if (Private->NoReadKeyCount > 2) {
gBS->CloseEvent (Private->CheckReadKeyEvent);
Private->CheckReadKeyEvent = NULL;
if (Private->DisableCheckReadKeyEvent != NULL) {
gBS->CloseEvent (Private->DisableCheckReadKeyEvent);
Private->DisableCheckReadKeyEvent = NULL;
}
Private->SetupMouse.Close (&Private->SetupMouse);
}
}
/**
Monitor readkeystroke function to create timer event of bitlocker.
@param [in] This Protocol instance pointer of SimpleTextInputEx.
@param [out] KeyData EFI key data.
@retval Origianl ReadKeyStrokeEx function return status
**/
EFI_STATUS
EFIAPI
BitlockerKeyboardReadKeyStrokeEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
OUT EFI_KEY_DATA *KeyData
)
{
EFI_STATUS Status;
EFI_SIMPLE_POINTER_STATE SimplePointerState;
EFI_ABSOLUTE_POINTER_STATE AbsolutePointerState;
KEYBOARD_ATTRIBUTES KeyboardAttrs;
PRIVATE_MOUSE_DATA *Private;
UINTN X;
UINTN Y;
BOOLEAN LeftButton;
BOOLEAN RightButton;
EFI_SETUP_MOUSE_PROTOCOL *SetupMouse;
BOOLEAN ShowVirtualKeyboard;
BOOLEAN StartSetupMouse;
Private = mPrivate;
if (!Private->InStartImage) {
return Private->OrgReadKeyStrokeEx (This, KeyData);
}
if (Private->FirstIn) {
Private->FirstIn = FALSE;
Status = gBS->HandleProtocol (
gST->ConsoleInHandle,
&gEfiSimplePointerProtocolGuid,
(VOID **) &Private->SimplePointer
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
goto CheckReadKey;
}
Status = gBS->HandleProtocol (
gST->ConsoleInHandle,
&gEfiAbsolutePointerProtocolGuid,
(VOID **) &Private->AbsolutePointer
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
goto CheckReadKey;
}
Private->SimplePointer->Reset (Private->SimplePointer, TRUE);
Private->AbsolutePointer->Reset (Private->AbsolutePointer, TRUE);
}
ShowVirtualKeyboard = FALSE;
StartSetupMouse = FALSE;
SetupMouse = &Private->SetupMouse;
if (!Private->IsStart) {
Status = Private->SimplePointer->GetState(Private->SimplePointer, &SimplePointerState);
if (!EFI_ERROR (Status)) {
StartSetupMouse = TRUE;
if (SimplePointerState.LeftButton) {
ShowVirtualKeyboard = TRUE;
}
}
Status = Private->AbsolutePointer->GetState(Private->AbsolutePointer, &AbsolutePointerState);
if (!EFI_ERROR (Status)) {
StartSetupMouse = TRUE;
if ((AbsolutePointerState.ActiveButtons & EFI_ABSP_TouchActive) == EFI_ABSP_TouchActive) {
ShowVirtualKeyboard = TRUE;
}
}
if (StartSetupMouse) {
SetupMouse->Start (SetupMouse);
}
}
if (Private->IsStart) {
if (!ShowVirtualKeyboard) {
LeftButton = FALSE;
Status = SetupMouse->QueryState (SetupMouse, &X, &Y, &LeftButton, &RightButton);
if (!EFI_ERROR (Status) && LeftButton) {
ShowVirtualKeyboard = TRUE;
}
}
if (ShowVirtualKeyboard) {
SetupMouse->GetKeyboardAttributes (SetupMouse, &KeyboardAttrs);
if (Private->FirstDisplayKB) {
Private->FirstDisplayKB = FALSE;
SetupMouse->StartKeyboard (SetupMouse, (UINTN) 10000, (UINTN) 10000); // right-bottom
} else {
SetupMouse->StartKeyboard (SetupMouse, (UINTN) KeyboardAttrs.X, (UINTN) KeyboardAttrs.Y);
}
}
}
CheckReadKey:
Private->ReadKeyFlag = TRUE;
Status = Private->OrgReadKeyStrokeEx (This, KeyData);
if (EFI_ERROR (Status) || !Private->IsStart) {
return Status;
}
if (Private->DisableCheckReadKeyEvent == NULL &&
Private->CheckReadKeyEvent == NULL &&
(KeyData->Key.ScanCode == SCAN_ESC || KeyData->Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) {
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
DisableCheckReadKeyHandler,
Private,
&Private->DisableCheckReadKeyEvent
);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer(Private->DisableCheckReadKeyEvent, TimerRelative, 500 * TICKS_PER_MS);
}
Private->NoReadKeyCount = 0;
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
CheckReadKeyHandler,
Private,
&Private->CheckReadKeyEvent
);
ASSERT_EFI_ERROR (Status);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer(Private->CheckReadKeyEvent, TimerPeriodic, 50 * TICKS_PER_MS);
}
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
StartImageSupportVirtualKeyboard (
IN EFI_HANDLE ImageHandle,
OUT UINTN *ExitDataSize,
OUT CHAR16 **ExitData OPTIONAL
)
{
EFI_STATUS Status;
UINT32 VersionMS;
UINT32 VersionLS;
PRIVATE_MOUSE_DATA *Private;
VOID *Registration;
Private = mPrivate;
if (!IsWindows (ImageHandle, &VersionMS, &VersionLS) || IsCdRomDevice (ImageHandle)) {
goto Done;
}
Status = gBS->HandleProtocol (
gST->ConsoleInHandle,
&gEfiSimpleTextInputExProtocolGuid,
(VOID **) &Private->SimpleTextInputEx
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
goto Done;
}
Private->FirstIn = TRUE;
Private->FirstDisplayKB = TRUE;
if (Private->GopHotplugEvent == NULL) {
AcquireSetupMouseLock (Private);
Private->GopHotplugEvent = EfiCreateProtocolNotifyEvent (
&gEfiSimpleTextOutProtocolGuid,
TPL_NOTIFY - 1,
OutputDevicePluginCallback,
NULL,
&Registration
);
ReleaseSetupMouseLock (Private);
}
//
// hook ReadKeyStrokeEx of SimpleTextInEx
//
if (Private->OrgReadKeyStrokeEx == NULL) {
Private->OrgReadKeyStrokeEx = Private->SimpleTextInputEx->ReadKeyStrokeEx;
Private->SimpleTextInputEx->ReadKeyStrokeEx = BitlockerKeyboardReadKeyStrokeEx;
}
Private->InStartImage = TRUE;
Done:
Status = Private->OrgStartImage (ImageHandle, ExitDataSize, ExitData);
if (Private->OrgReadKeyStrokeEx != NULL) {
Private->SimpleTextInputEx->ReadKeyStrokeEx = Private->OrgReadKeyStrokeEx;
}
Private->InStartImage = FALSE;
if (Private->CheckReadKeyEvent != NULL) {
gBS->CloseEvent (Private->CheckReadKeyEvent);
Private->CheckReadKeyEvent = NULL;
}
if (Private->DisableCheckReadKeyEvent != NULL) {
gBS->CloseEvent (Private->DisableCheckReadKeyEvent);
Private->DisableCheckReadKeyEvent = NULL;
}
if (Private->GopHotplugEvent != NULL) {
gBS->CloseEvent (Private->GopHotplugEvent);
Private->GopHotplugEvent = NULL;
}
if (Private->IsStart) {
Private->SetupMouse.Close (&Private->SetupMouse);
}
return Status;
}