1605 lines
43 KiB
C
1605 lines
43 KiB
C
/** @file
|
|
Setup Mouse Protocol implementation
|
|
|
|
;******************************************************************************
|
|
;* 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 "SetupMouse.h"
|
|
#include <Protocol/LegacyBios.h>
|
|
#include <Protocol/DriverBinding.h>
|
|
#include <Guid/ReturnFromImage.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
PRIVATE_MOUSE_DATA *mPrivate = NULL;
|
|
EFI_HII_HANDLE mImageHiiHandle;
|
|
|
|
//
|
|
// BugBug:
|
|
// For detect device is disconnected, so we hook protocol's driver binding protocol stop function.
|
|
// Besides we only except below function to been hooked
|
|
//
|
|
// ConSplitter using EFI_OPEN_PROTOCOL_BY_DRIVER for SimplePointer / AbsolutePointer protocol;
|
|
// ConSplitterSimplePointerDriverBindingStop and ConSplitterAbsolutePointerDriverBindingStop
|
|
//
|
|
// GraphicsConsole using EFI_OPEN_PROTOCOL_BY_DRIVER for GraphicsOutput protocol
|
|
// GraphicsConsoleControllerDriverStop
|
|
//
|
|
#define SETUP_MOUSE_DRIVER_BINDING_HOOK_LIST_COUNT 3
|
|
|
|
struct {
|
|
EFI_GUID *ProtocolGuid;
|
|
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
|
EFI_DRIVER_BINDING_STOP StopFunction;
|
|
} mSetupMouseDriverBindingHookList[SETUP_MOUSE_DRIVER_BINDING_HOOK_LIST_COUNT] = {
|
|
{&gEfiSimplePointerProtocolGuid, NULL, NULL},
|
|
{&gEfiAbsolutePointerProtocolGuid, NULL, NULL},
|
|
{&gEfiGraphicsOutputProtocolGuid, NULL, NULL}
|
|
};
|
|
|
|
EFI_STATUS
|
|
HookDeviceStopFunction (
|
|
IN EFI_GUID *ProtocolGuid
|
|
);
|
|
|
|
/**
|
|
Get number of physical device according to assigned protocol guid.
|
|
|
|
|
|
@param [in] ProtocolGuid Search physical device protocol guid.
|
|
|
|
|
|
@retval Count of physical device according to protocol guid.
|
|
|
|
**/
|
|
STATIC
|
|
UINT32
|
|
GetNumberOfDevices (
|
|
IN EFI_GUID *ProtocolGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN NumberOfHandles;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINT32 Count;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
ProtocolGuid,
|
|
NULL,
|
|
&NumberOfHandles,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// make sure it is physical device
|
|
//
|
|
Count = 0;
|
|
for (Index = 0; Index < NumberOfHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
Count++;
|
|
}
|
|
|
|
FreePool (HandleBuffer);
|
|
|
|
return Count;
|
|
}
|
|
|
|
/**
|
|
Get GOP device path.
|
|
|
|
@param[in] GraphicsOutput Pointer to the GOP.
|
|
|
|
@return The pointer of device path or NULL if not found.
|
|
**/
|
|
STATIC
|
|
EFI_DEVICE_PATH_PROTOCOL *
|
|
GetGopDevPath (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN Count;
|
|
UINTN Index;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *Instance;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
if (GraphicsOutput == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
NULL,
|
|
&Count,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
for (Index = 0; Index < Count; Index++) {
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiGraphicsOutputProtocolGuid, (VOID **) &Instance);
|
|
if (!EFI_ERROR (Status) && Instance == GraphicsOutput) {
|
|
break;
|
|
}
|
|
}
|
|
if (Index == Count) {
|
|
FreePool (HandleBuffer);
|
|
return NULL;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **) &DevicePath);
|
|
FreePool (HandleBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
return NULL;
|
|
}
|
|
|
|
return DevicePath;
|
|
}
|
|
|
|
VOID
|
|
FreeGopEntry (
|
|
IN OUT GOP_ENTRY *GopEntry,
|
|
IN BOOLEAN RestoreHook
|
|
)
|
|
{
|
|
ASSERT (GopEntry != NULL);
|
|
|
|
//
|
|
// Restore GOP
|
|
//
|
|
if (RestoreHook) {
|
|
if (GopEntry->GraphicsOutput != NULL && GopEntry->OriginalBlt != NULL) {
|
|
GopEntry->GraphicsOutput->Blt = GopEntry->OriginalBlt;
|
|
GopEntry->GraphicsOutput->SetMode = GopEntry->OriginalSetMode;
|
|
}
|
|
}
|
|
|
|
if (GopEntry->BlendBuffer != NULL) {
|
|
FreePool (GopEntry->BlendBuffer);
|
|
}
|
|
if (GopEntry->FillLine != NULL) {
|
|
FreePool (GopEntry->FillLine);
|
|
}
|
|
|
|
if (GopEntry->CheckBuffer != NULL) {
|
|
FreePool (GopEntry->CheckBuffer);
|
|
}
|
|
|
|
if (GopEntry->Screen.Image != NULL) {
|
|
FreePool (GopEntry->Screen.Image);
|
|
}
|
|
|
|
FreePool (GopEntry);
|
|
}
|
|
|
|
EFI_STATUS
|
|
InitialGopEntry (
|
|
GOP_ENTRY *GopEntry,
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
|
|
)
|
|
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN ScreenBufferSize;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo;
|
|
|
|
GopEntry->Signature = GOP_ENTRY_SIGNATURE;
|
|
|
|
ModeInfo = GraphicsOutput->Mode->Info;
|
|
|
|
GopEntry->BytesPerScanLine = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * ModeInfo->HorizontalResolution;
|
|
|
|
if (GopEntry->FillLine != NULL) {
|
|
FreePool (GopEntry->FillLine);
|
|
}
|
|
GopEntry->FillLine = AllocateZeroPool (GopEntry->BytesPerScanLine);
|
|
if (GopEntry->FillLine == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Error;
|
|
}
|
|
|
|
SetRect (&GopEntry->Screen.ImageRc, 0, 0, ModeInfo->HorizontalResolution, ModeInfo->VerticalResolution);
|
|
SetRect (&GopEntry->InvalidateRc, 0, 0, ModeInfo->HorizontalResolution, ModeInfo->VerticalResolution);
|
|
ScreenBufferSize = ModeInfo->HorizontalResolution * ModeInfo->VerticalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
|
|
|
if (GopEntry->Screen.Image != NULL) {
|
|
FreePool (GopEntry->Screen.Image);
|
|
}
|
|
GopEntry->Screen.Image = AllocateZeroPool (ScreenBufferSize);
|
|
if (GopEntry->Screen.Image == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Error;
|
|
}
|
|
|
|
if (mPrivate->IsStart) {
|
|
Status = GraphicsOutput->Blt (
|
|
GraphicsOutput,
|
|
GopEntry->Screen.Image,
|
|
EfiBltVideoToBltBuffer,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
ModeInfo->HorizontalResolution,
|
|
ModeInfo->VerticalResolution,
|
|
GopEntry->BytesPerScanLine
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
if (GopEntry->BlendBuffer != NULL) {
|
|
FreePool (GopEntry->BlendBuffer);
|
|
}
|
|
GopEntry->BlendBuffer = AllocateZeroPool (ScreenBufferSize);
|
|
if (GopEntry->BlendBuffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Error;
|
|
}
|
|
|
|
if (GopEntry->CheckBuffer != NULL) {
|
|
FreePool (GopEntry->CheckBuffer);
|
|
}
|
|
GopEntry->CheckBuffer = AllocateZeroPool (ScreenBufferSize);
|
|
if (GopEntry->CheckBuffer == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Error;
|
|
}
|
|
GopEntry->DevicePath = GetGopDevPath (GraphicsOutput);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
Error:
|
|
if (GopEntry->FillLine != NULL) {
|
|
FreePool (GopEntry->FillLine);
|
|
GopEntry->FillLine = NULL;
|
|
}
|
|
if (GopEntry->Screen.Image != NULL) {
|
|
FreePool (GopEntry->Screen.Image);
|
|
GopEntry->Screen.Image = NULL;
|
|
}
|
|
if (GopEntry->BlendBuffer != NULL) {
|
|
FreePool (GopEntry->BlendBuffer);
|
|
GopEntry->BlendBuffer = NULL;
|
|
|
|
}
|
|
if (GopEntry->CheckBuffer != NULL) {
|
|
FreePool (GopEntry->CheckBuffer);
|
|
GopEntry->CheckBuffer = NULL;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseGopSetMode (
|
|
IN EFI_GRAPHICS_OUTPUT_PROTOCOL * This,
|
|
IN UINT32 ModeNumber
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
LIST_ENTRY *Node;
|
|
GOP_ENTRY *GopEntry;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE GopSetMode;
|
|
EFI_TPL Tpl;
|
|
UINT32 X;
|
|
UINT32 Y;
|
|
BOOLEAN KeyboardStarted;
|
|
EFI_STATUS ReturnStatus;
|
|
BOOLEAN SetupMouseIsStart;
|
|
|
|
Private = mPrivate;
|
|
GopEntry = NULL;
|
|
|
|
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
|
|
|
|
Node = GetFirstNode (&Private->GopList);
|
|
while (!IsNull (&Private->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
if (GopEntry->GraphicsOutput == This) {
|
|
break;
|
|
}
|
|
Node = GetNextNode (&Private->GopList, Node);
|
|
}
|
|
|
|
ASSERT (!IsNull (&Private->GopList, Node));
|
|
if (IsNull (&Private->GopList, Node) || GopEntry == NULL) {
|
|
gBS->RestoreTPL (Tpl);
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
KeyboardStarted = Private->Keyboard.Visible;
|
|
X = 0;
|
|
Y = 0;
|
|
if (KeyboardStarted) {
|
|
X = (INT32)Private->Keyboard.ImageRc.left;
|
|
Y = (INT32)Private->Keyboard.ImageRc.top;
|
|
}
|
|
|
|
SetupMouseIsStart = Private->IsStart;
|
|
|
|
GopSetMode = GopEntry->OriginalSetMode;
|
|
if (Private->IsStart) {
|
|
SetupMouseClose (&Private->SetupMouse);
|
|
}
|
|
|
|
//
|
|
// Free GOP list
|
|
//
|
|
while (!IsListEmpty (&Private->GopList)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (GetFirstNode (&Private->GopList));
|
|
RemoveEntryList (&GopEntry->Link);
|
|
FreeGopEntry (GopEntry, TRUE);
|
|
}
|
|
|
|
ReturnStatus = GopSetMode (This, ModeNumber);
|
|
|
|
if (EFI_ERROR (ReturnStatus)) {
|
|
gBS->RestoreTPL (Tpl);
|
|
return ReturnStatus;
|
|
}
|
|
|
|
if (!SetupMouseIsStart) {
|
|
if (Private->GopHotplugEvent != NULL) {
|
|
gBS->SignalEvent (Private->GopHotplugEvent);
|
|
}
|
|
} else {
|
|
SetupMouseStart (&Private->SetupMouse);
|
|
|
|
if (KeyboardStarted) {
|
|
StartKeyboard (&Private->SetupMouse, X, Y);
|
|
}
|
|
}
|
|
|
|
gBS->RestoreTPL (Tpl);
|
|
|
|
return ReturnStatus;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RetrieveGraphicsOutputInfo (
|
|
OUT PRIVATE_MOUSE_DATA *Private
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN Count;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL **GraphicsOutputList;
|
|
UINTN GopCount;
|
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Node;
|
|
|
|
ASSERT_LOCKED (&Private->SetupMouseLock);
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiGraphicsOutputProtocolGuid,
|
|
NULL,
|
|
&Count,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Retrieve GOP list
|
|
//
|
|
GraphicsOutputList = AllocateZeroPool (Count * sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL*));
|
|
if (GraphicsOutputList == NULL) {
|
|
FreePool (HandleBuffer);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
GopCount = 0;
|
|
for (Index = 0; Index < Count; Index++) {
|
|
|
|
Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiSimpleTextOutProtocolGuid, (VOID **)&SimpleTextOut);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
|
|
Status = gBS->HandleProtocol(HandleBuffer[Index], &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
|
|
GraphicsOutputList[GopCount++] = GraphicsOutput;
|
|
}
|
|
FreePool (HandleBuffer);
|
|
|
|
//
|
|
// check the gop list valid
|
|
//
|
|
Node = GetFirstNode (&Private->GopList);
|
|
while (!IsNull (&Private->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
for (Index = 0; Index < GopCount; Index++) {
|
|
if (GraphicsOutputList[Index] == GopEntry->GraphicsOutput) {
|
|
GraphicsOutputList[Index] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// remove invalid GopEntry
|
|
//
|
|
if (Index == GopCount) {
|
|
Node = RemoveEntryList (&GopEntry->Link);
|
|
FreeGopEntry (GopEntry, FALSE);
|
|
continue;
|
|
}
|
|
|
|
Node = GetNextNode (&Private->GopList, Node);
|
|
}
|
|
|
|
//
|
|
// add new GOP
|
|
//
|
|
for (Index = 0; Index < GopCount; Index++) {
|
|
|
|
GraphicsOutput = GraphicsOutputList[Index];
|
|
if (GraphicsOutput == NULL) {
|
|
continue;
|
|
}
|
|
|
|
GopEntry = AllocateZeroPool (sizeof (GOP_ENTRY));
|
|
if (GopEntry == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
continue;
|
|
}
|
|
|
|
Status = InitialGopEntry (GopEntry, GraphicsOutput);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (GopEntry);
|
|
continue;
|
|
}
|
|
|
|
InsertTailList (&Private->GopList, &GopEntry->Link);
|
|
|
|
//
|
|
// hook gop blt function
|
|
//
|
|
GopEntry->GraphicsOutput = GraphicsOutput;
|
|
GopEntry->OriginalBlt = GraphicsOutput->Blt;
|
|
GraphicsOutput->Blt = SetupMouseScreenBlt;
|
|
GopEntry->OriginalSetMode = GraphicsOutput->SetMode;
|
|
GraphicsOutput->SetMode = SetupMouseGopSetMode;
|
|
}
|
|
|
|
FreePool (GraphicsOutputList);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetCursorPos (
|
|
IN UINTN X,
|
|
IN UINTN Y
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_STATUS Status;
|
|
|
|
Private = mPrivate;
|
|
AcquireSetupMouseLock (Private);
|
|
Status = InternalSetCursorPos (X, Y);
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Determine mouse or touch devices are existence.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
DetermineDevicesExistence (
|
|
VOID
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
UINT32 MouseCount;
|
|
UINT32 TouchCount;
|
|
GOP_ENTRY *GopEntry;
|
|
|
|
Private = mPrivate;
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
|
|
RetrieveGraphicsOutputInfo (Private);
|
|
|
|
if (!Private->IsStart) {
|
|
ReleaseSetupMouseLock (Private);
|
|
return ;
|
|
}
|
|
|
|
MouseCount = GetNumberOfDevices (&gEfiSimplePointerProtocolGuid);
|
|
TouchCount = GetNumberOfDevices (&gEfiAbsolutePointerProtocolGuid);
|
|
//
|
|
// Gop == 0 : reset cursor
|
|
// SaveCursorX == -1 and SaveCursorY == -1 : set cursor in center of screen
|
|
//
|
|
if (IsListEmpty (&Private->GopList)) {
|
|
Private->MouseRange.StartX = 0;
|
|
Private->MouseRange.StartY = 0;
|
|
Private->MouseRange.EndX = 0;
|
|
Private->MouseRange.EndY = 0;
|
|
Private->SaveCursorX = (UINT32) -1;
|
|
Private->SaveCursorY = (UINT32) -1;
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
return ;
|
|
}
|
|
|
|
GopEntry = GOP_ENTRY_FROM_THIS (GetFirstNode (&Private->GopList));
|
|
Private->MouseRange.StartX = 0;
|
|
Private->MouseRange.StartY = 0;
|
|
Private->MouseRange.EndX = GopEntry->GraphicsOutput->Mode->Info->HorizontalResolution - 1;
|
|
Private->MouseRange.EndY = GopEntry->GraphicsOutput->Mode->Info->VerticalResolution - 1;
|
|
|
|
if ((Private->SaveCursorX == (UINT32) -1) && (Private->SaveCursorY == (UINT32) -1)) {
|
|
Private->SaveCursorX = GopEntry->GraphicsOutput->Mode->Info->HorizontalResolution / 2;
|
|
Private->SaveCursorY = GopEntry->GraphicsOutput->Mode->Info->VerticalResolution / 2;
|
|
}
|
|
|
|
InternalSetCursorPos (Private->SaveCursorX, Private->SaveCursorY);
|
|
|
|
if (MouseCount == 0) {
|
|
HideImage (&Private->Cursor);
|
|
} else if (!Private->HideCursor) {
|
|
ShowImage (&Private->Cursor);
|
|
}
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
}
|
|
|
|
/**
|
|
Callback function for devices plugs in, it will hook device's DriverBinding stop function.
|
|
|
|
@param [in] Event Event for SimplePointer / AbsolutePointer.
|
|
@param [in] Context Context of event.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InputDevicePluginCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_TPL Tpl;
|
|
|
|
Private = mPrivate;
|
|
|
|
HookDeviceStopFunction (&gEfiSimplePointerProtocolGuid);
|
|
HookDeviceStopFunction (&gEfiAbsolutePointerProtocolGuid);
|
|
|
|
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
|
|
DetermineDevicesExistence ();
|
|
gBS->RestoreTPL (Tpl);
|
|
|
|
}
|
|
|
|
/**
|
|
Callback function for devices plugs in, it will hook device's DriverBinding stop function.
|
|
|
|
@param [in] Event Event for SimplePointer / AbsolutePointer.
|
|
@param [in] Context Context of event.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
OutputDevicePluginCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_TPL Tpl;
|
|
|
|
Private = mPrivate;
|
|
|
|
HookDeviceStopFunction (&gEfiGraphicsOutputProtocolGuid);
|
|
|
|
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
|
|
DetermineDevicesExistence ();
|
|
gBS->RestoreTPL (Tpl);
|
|
}
|
|
|
|
/**
|
|
Callback function for EDID active protocol to hook GOP Blt function again if it is restored by GOP driver.
|
|
|
|
@param [in] Event Event for Edid active protocol
|
|
@param [in] Context Context of event.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EdidActivePluginCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
LIST_ENTRY *Node;
|
|
GOP_ENTRY *GopEntry;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
Private = mPrivate;
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
|
|
for (Node = GetFirstNode (&Private->GopList); !IsNull (&Private->GopList, Node); Node = GetNextNode (&Private->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
if (GopEntry->GraphicsOutput->Blt == SetupMouseScreenBlt &&
|
|
GopEntry->GraphicsOutput->SetMode == SetupMouseGopSetMode) {
|
|
continue;
|
|
}
|
|
|
|
DevicePath = GetGopDevPath (GopEntry->GraphicsOutput);
|
|
if (GopEntry->DevicePath != DevicePath) {
|
|
GopEntry->GraphicsOutput->Blt = SetupMouseScreenBlt;
|
|
GopEntry->GraphicsOutput->SetMode = SetupMouseGopSetMode;
|
|
GopEntry->DevicePath = DevicePath;
|
|
}
|
|
}
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
}
|
|
|
|
/**
|
|
According to ProtocolGuid to search which DriverBinding protocol OpenProtocol by EFI_OPEN_PROTOCOL_BY_DRIVER,
|
|
and then hook the DriverBinding protocol stop function
|
|
|
|
@param [in] ControllerHandle To hook driver binding stop function from ControllerHandle.
|
|
@param [in] ProtocolGuid ProtocolGuid which OpenProtocol by EFI_OPEN_PROTOCOL_BY_DRIVER.
|
|
|
|
@retval EFI_SUCCESS Hook DriverBinding protocol stop function success.
|
|
@retval EFI_NOT_FOUND Can't found the assigned DriverBinding protocol.
|
|
@retval Others Fail to get return status data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
EFI_DRIVER_BINDING_STOP StopFunction;
|
|
EFI_GUID *ProtocolGuid;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = mPrivate;
|
|
|
|
StopFunction = NULL;
|
|
ProtocolGuid = NULL;
|
|
for (Index = 0; Index < SETUP_MOUSE_DRIVER_BINDING_HOOK_LIST_COUNT; Index++) {
|
|
if (This == mSetupMouseDriverBindingHookList[Index].DriverBinding) {
|
|
ProtocolGuid = mSetupMouseDriverBindingHookList[Index].ProtocolGuid;
|
|
StopFunction = mSetupMouseDriverBindingHookList[Index].StopFunction;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT (StopFunction != NULL);
|
|
ASSERT (ProtocolGuid != NULL);
|
|
if (StopFunction == NULL || ProtocolGuid == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = StopFunction (This, ControllerHandle, NumberOfChildren, ChildHandleBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (CompareGuid (ProtocolGuid, &gEfiGraphicsOutputProtocolGuid) || Private->IsStart) {
|
|
DetermineDevicesExistence ();
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
According to ProtocolGuid to search which DriverBinding protocol OpenProtocol by EFI_OPEN_PROTOCOL_BY_DRIVER,
|
|
and then hook the DriverBinding protocol stop function
|
|
|
|
@param [in] ControllerHandle To hook driver binding stop function from ControllerHandle.
|
|
@param [in] ProtocolGuid ProtocolGuid which OpenProtocol by EFI_OPEN_PROTOCOL_BY_DRIVER.
|
|
|
|
@retval EFI_SUCCESS Hook DriverBinding protocol stop function success.
|
|
@retval EFI_NOT_FOUND Can't found the assigned DriverBinding protocol.
|
|
@retval Others Fail to get return status data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
HookSingleDeviceStopFunction (
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_GUID *ProtocolGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE AgentHandle;
|
|
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
|
|
UINTN EntryCount;
|
|
UINTN Index;
|
|
EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_TPL OriginalTPL;
|
|
|
|
ASSERT (ProtocolGuid != NULL);
|
|
|
|
Private = mPrivate;
|
|
|
|
Status = gBS->OpenProtocolInformation (
|
|
ControllerHandle,
|
|
(EFI_GUID *) ProtocolGuid,
|
|
&OpenInfoBuffer,
|
|
&EntryCount
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
AgentHandle = NULL;
|
|
for (Index = 0; Index < EntryCount; Index++) {
|
|
if ((OpenInfoBuffer[Index].ControllerHandle == ControllerHandle) &&
|
|
(OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
|
|
AgentHandle = OpenInfoBuffer[Index].AgentHandle;
|
|
break;
|
|
}
|
|
}
|
|
|
|
FreePool (OpenInfoBuffer);
|
|
if (AgentHandle == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// locate driver binding protocol
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
AgentHandle,
|
|
&gEfiDriverBindingProtocolGuid,
|
|
(VOID **) &DriverBinding
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// hook driver binding stop function
|
|
//
|
|
for (Index = 0; Index < SETUP_MOUSE_DRIVER_BINDING_HOOK_LIST_COUNT; Index++) {
|
|
if (CompareGuid (mSetupMouseDriverBindingHookList[Index].ProtocolGuid, ProtocolGuid)) {
|
|
if (DriverBinding->Stop != SetupMouseDriverBindingStop) {
|
|
OriginalTPL = gBS->RaiseTPL(TPL_NOTIFY);
|
|
mSetupMouseDriverBindingHookList[Index].DriverBinding = DriverBinding;
|
|
mSetupMouseDriverBindingHookList[Index].StopFunction = DriverBinding->Stop;
|
|
DriverBinding->Stop = SetupMouseDriverBindingStop;
|
|
gBS->RestoreTPL (OriginalTPL);
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
|
|
/**
|
|
Search physical device protocol which OpenProtocol by OPEN_PROTOCOL_BY_DRIVER and then
|
|
hook the DriverBinding protocol stop function for monitor the protocol.
|
|
|
|
@param [in] ProtocolGuid Searched physical device protocol
|
|
|
|
|
|
@retval EFI_SUCCESS Hook DriverBinding protocol stop function success.
|
|
@retval Others Fail to get return status data.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
HookDeviceStopFunction (
|
|
IN EFI_GUID *ProtocolGuid
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINTN NumberOfHandles;
|
|
EFI_HANDLE *HandleBuffer;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
ProtocolGuid,
|
|
NULL,
|
|
&NumberOfHandles,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// make sure it is physical device
|
|
//
|
|
for (Index = 0; Index < NumberOfHandles; Index++) {
|
|
Status = gBS->HandleProtocol (
|
|
HandleBuffer[Index],
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
continue;
|
|
}
|
|
HookSingleDeviceStopFunction (HandleBuffer[Index], ProtocolGuid);
|
|
}
|
|
|
|
FreePool (HandleBuffer);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
StartImageSupportVirtualKeyboard (
|
|
IN EFI_HANDLE ImageHandle,
|
|
OUT UINTN *ExitDataSize,
|
|
OUT CHAR16 **ExitData OPTIONAL
|
|
);
|
|
|
|
|
|
/**
|
|
This function uses to enable sync frame buffer
|
|
|
|
@param Event Event whose notification function is being invoked.
|
|
@param Context Pointer to the notification function's context.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SetupMouseReadyToBootCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (Context);
|
|
|
|
Private->NeedSyncFrameBuffer = TRUE;
|
|
|
|
if (Private->OrgStartImage == NULL) {
|
|
Private->OrgStartImage = gBS->StartImage;
|
|
gBS->StartImage = StartImageSupportVirtualKeyboard;
|
|
gBS->Hdr.CRC32 = 0;
|
|
gBS->CalculateCrc32 ((UINT8 *)gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function uses to disable sync frame buffer
|
|
|
|
@param Event Event whose notification function is being invoked.
|
|
@param Context Pointer to the notification function's context.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
SetupMouseReturnFromImageCallback (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (Context);
|
|
|
|
Private->NeedSyncFrameBuffer = FALSE;
|
|
}
|
|
|
|
/**
|
|
Initialize Setup
|
|
|
|
@param [in] ImageHandle
|
|
@param [in] SystemTable
|
|
|
|
@retval EFI_SUCCESS Setup Mouse loaded.
|
|
@return other Setup Mouse Error
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeSetupMouse (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_EVENT Event;
|
|
VOID *Registration;
|
|
|
|
Private = AllocateZeroPool (sizeof (PRIVATE_MOUSE_DATA));
|
|
if (Private == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Private->Signature = SETUP_MOUSE_SIGNATURE;
|
|
Private->SetupMouse.Start = SetupMouseStart;
|
|
Private->SetupMouse.Close = SetupMouseClose;
|
|
Private->SetupMouse.QueryState = QueryState;
|
|
Private->SetupMouse.StartKeyboard = StartKeyboard;
|
|
Private->SetupMouse.CloseKeyboard = CloseKeyboard;
|
|
Private->SetupMouse.SetMode = SetupMouseSetMode;
|
|
Private->SetupMouse.SetKeyboardAttributes = SetupMouseSetKeyboardAttributes;
|
|
Private->SetupMouse.GetKeyboardAttributes = SetupMouseGetKeyboardAttributes;
|
|
Private->SetupMouse.SetMouseAttributes = SetupMouseSetMouseAttributes;
|
|
Private->SetupMouse.GetMouseAttributes = SetupMouseGetMouseAttributes;
|
|
Private->SaveCursorX = (UINT32) -1;
|
|
Private->SaveCursorY = (UINT32) -1;
|
|
|
|
Private->IsStart = FALSE;
|
|
Private->HideCursor = FALSE;
|
|
Private->HideCursorWhenTouch = TRUE;
|
|
Private->NeedSyncFrameBuffer = FALSE;
|
|
|
|
InitializeListHead (&Private->GopList);
|
|
EfiInitializeLock (&Private->SetupMouseLock, TPL_NOTIFY);
|
|
|
|
mPrivate = Private;
|
|
|
|
Status = EfiCreateEventReadyToBootEx (
|
|
TPL_NOTIFY,
|
|
SetupMouseReadyToBootCallback,
|
|
(VOID *) &Private->SetupMouse,
|
|
&Event
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
SetupMouseReturnFromImageCallback,
|
|
(VOID *) &Private->SetupMouse,
|
|
&Event
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->RegisterProtocolNotify (
|
|
&gReturnFromImageGuid,
|
|
Event,
|
|
&Registration
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
mImageHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, NULL, SetupMouseDxeImages, NULL);
|
|
Status = gBS->InstallProtocolInterface (
|
|
&(Private->Handle),
|
|
&gSetupMouseProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&(Private->SetupMouse)
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
SetupMouse set to graphics / text mode coordinate
|
|
Can avoid user call SetupMouse->Start in graphics Mode,
|
|
but he want use SetupMouse in text mode and vice versa.
|
|
|
|
@param [in] SetupMouse EFI_SETUP_MOUSE_PROTOCOL
|
|
@param [in] Mode Graphics / Text mode
|
|
|
|
@retval EFI_SUCCESS Set mode success
|
|
@retval EFI_NOT_READY SetupMouse doesn't start
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseSetMode (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
IN EFI_SETUP_MOUSE_SCREEN_MODE Mode
|
|
)
|
|
{
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
RetrievePointerProtocolInfo (
|
|
PRIVATE_MOUSE_DATA *Private
|
|
)
|
|
{
|
|
UINTN Count;
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
|
|
EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;
|
|
POINTER_PROTOCOL_INFO *PointerProtocolInfo;
|
|
EFI_SIMPLE_POINTER_STATE SimplePointerState;
|
|
|
|
|
|
Count = 0;
|
|
//
|
|
// Initial ConSplitter's Simple Pointer
|
|
//
|
|
SimplePointer = NULL;
|
|
Status = gBS->HandleProtocol(
|
|
gST->ConsoleInHandle,
|
|
&gEfiSimplePointerProtocolGuid,
|
|
(VOID**)&SimplePointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = SimplePointer->Reset (SimplePointer, TRUE);
|
|
if (!EFI_ERROR (Status)) {
|
|
Count ++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Initial ConSplitter's Absolute Pointer
|
|
//
|
|
AbsolutePointer = NULL;
|
|
Status = gBS->HandleProtocol(
|
|
gST->ConsoleInHandle,
|
|
&gEfiAbsolutePointerProtocolGuid,
|
|
(VOID**)&AbsolutePointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = AbsolutePointer->Reset (AbsolutePointer, TRUE);
|
|
if (!EFI_ERROR (Status)) {
|
|
Count ++;
|
|
}
|
|
}
|
|
|
|
if (!Count) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
PointerProtocolInfo = (POINTER_PROTOCOL_INFO *) AllocateZeroPool (
|
|
sizeof (POINTER_PROTOCOL_INFO) + sizeof (POINTER_PROTOCOL_INFO_DATA) * Count);
|
|
if (PointerProtocolInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
PointerProtocolInfo->Count = 0;
|
|
//
|
|
// Fill in PointerProtocolInfo with ConSplitter's Simple Pointer protocol
|
|
//
|
|
if (SimplePointer) {
|
|
//
|
|
// PS2 mouse GetState() will reset mouse in first time, it will waste much time.
|
|
// So we call GetState() early to avoid interrupt other process.
|
|
//
|
|
SimplePointer->GetState(SimplePointer, &SimplePointerState);
|
|
PointerProtocolInfo->Data[PointerProtocolInfo->Count].Attributes = ATTRIBUTE_VALUE_SIMPLE;
|
|
PointerProtocolInfo->Data[PointerProtocolInfo->Count].PointerProtocol = SimplePointer;
|
|
PointerProtocolInfo->Count++;
|
|
}
|
|
//
|
|
// Fill in PointerProtocolInfo with information about all the Absolute Pointer protocols
|
|
//
|
|
if (AbsolutePointer) {
|
|
PointerProtocolInfo->Data[PointerProtocolInfo->Count].Attributes = ATTRIBUTE_VALUE_ABSOLUTE;
|
|
PointerProtocolInfo->Data[PointerProtocolInfo->Count].PointerProtocol = AbsolutePointer;
|
|
PointerProtocolInfo->Count++;
|
|
}
|
|
//
|
|
// Update PointerProtocolInfo to private data
|
|
//
|
|
Private->PointerProtocolInfo = PointerProtocolInfo;
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
VOID
|
|
FreeGopEntryList (
|
|
PRIVATE_MOUSE_DATA *Private
|
|
)
|
|
{
|
|
GOP_ENTRY *GopEntry;
|
|
|
|
while (!IsListEmpty (&Private->GopList)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (GetFirstNode (&Private->GopList));
|
|
RemoveEntryList (&GopEntry->Link);
|
|
FreeGopEntry (GopEntry, TRUE);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Start SetupMouse
|
|
|
|
@param [in] SetupMouse EFI_SETUP_MOUSE_PROTOCOL
|
|
|
|
@retval EFI_SUCCESS Start success
|
|
@retval EFI_NOT_FOUND Can't find GOP protocol
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseStart (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
|
|
VOID *Registration;
|
|
GOP_ENTRY *GopEntry;
|
|
LIST_ENTRY *Node;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
|
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *ModeInfo;
|
|
|
|
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
if (Private->IsStart) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
|
|
Status = RetrievePointerProtocolInfo (Private);
|
|
if (EFI_ERROR (Status)) {
|
|
goto QUIT;
|
|
}
|
|
|
|
Status = InitializeCursor (Private);
|
|
if (EFI_ERROR (Status)) {
|
|
goto QUIT;
|
|
}
|
|
|
|
Private->MouseRange.StartX = 0;
|
|
Private->MouseRange.StartY = 0;
|
|
Private->MouseRange.EndX = 0;
|
|
Private->MouseRange.EndY = 0;
|
|
|
|
//
|
|
// Reset setup mouse state queue
|
|
//
|
|
ZeroMem (Private->State, sizeof (Private->State));
|
|
Private->BufferIn = 0;
|
|
Private->BufferOut = 0;
|
|
|
|
//
|
|
// Using CSM enable to make sure BDA existence.
|
|
//
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiLegacyBiosProtocolGuid,
|
|
NULL,
|
|
(VOID **)&LegacyBios
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Private->IsCsmEnabled = TRUE;
|
|
} else {
|
|
Private->IsCsmEnabled = FALSE;
|
|
}
|
|
|
|
//
|
|
// Set start flag, let SetupMouseSetMode work
|
|
//
|
|
Private->IsStart = TRUE;
|
|
|
|
//
|
|
//Create Setup Mouse event
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
ProcessMouse,
|
|
(VOID*)SetupMouse,
|
|
&SetupMouse->Event
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = gBS->SetTimer (SetupMouse->Event, TimerPeriodic, MOUSE_TIMER);
|
|
if (EFI_ERROR (Status)) {
|
|
goto QUIT;
|
|
}
|
|
|
|
Private->MouseHotplugEvent = EfiCreateProtocolNotifyEvent (
|
|
&gEfiSimplePointerProtocolGuid,
|
|
TPL_NOTIFY - 1,
|
|
InputDevicePluginCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
Private->TouchHotplugEvent = EfiCreateProtocolNotifyEvent (
|
|
&gEfiAbsolutePointerProtocolGuid,
|
|
TPL_NOTIFY - 1,
|
|
InputDevicePluginCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
Private->EdidActiveHotplugEvent = EfiCreateProtocolNotifyEvent (
|
|
&gEfiEdidActiveProtocolGuid,
|
|
TPL_NOTIFY - 1,
|
|
EdidActivePluginCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
|
|
if (Private->GopHotplugEvent == NULL) {
|
|
Private->GopHotplugEvent = EfiCreateProtocolNotifyEvent (
|
|
&gEfiSimpleTextOutProtocolGuid,
|
|
TPL_NOTIFY - 1,
|
|
OutputDevicePluginCallback,
|
|
NULL,
|
|
&Registration
|
|
);
|
|
}
|
|
|
|
|
|
Node = GetFirstNode (&mPrivate->GopList);
|
|
while (!IsNull (&mPrivate->GopList, Node)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (Node);
|
|
GraphicsOutput = GopEntry->GraphicsOutput;
|
|
ModeInfo = GraphicsOutput->Mode->Info;
|
|
Status = GraphicsOutput->Blt (
|
|
GraphicsOutput,
|
|
GopEntry->Screen.Image,
|
|
EfiBltVideoToBltBuffer,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
ModeInfo->HorizontalResolution,
|
|
ModeInfo->VerticalResolution,
|
|
GopEntry->BytesPerScanLine
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
Node = GetNextNode (&Private->GopList, Node);
|
|
}
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
DetermineDevicesExistence ();
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
QUIT:
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
Private->IsStart = FALSE;
|
|
|
|
if (Private->PointerProtocolInfo != NULL) {
|
|
FreePool (Private->PointerProtocolInfo);
|
|
Private->PointerProtocolInfo = NULL;
|
|
}
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseClose (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Stop SetupMouse
|
|
|
|
Arguments:
|
|
|
|
SetupMouse - EFI_SETUP_MOUSE_PROTOCOL
|
|
|
|
Returns:
|
|
Start setup mouse
|
|
|
|
--*/
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
GOP_ENTRY *GopEntry;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
if (!Private->IsStart) {
|
|
ReleaseSetupMouseLock (Private);
|
|
return EFI_SUCCESS;
|
|
}
|
|
Private->IsStart = FALSE;
|
|
Private->HideCursor = FALSE;
|
|
gBS->CloseEvent (SetupMouse->Event);
|
|
gBS->CloseEvent (Private->MouseHotplugEvent);
|
|
gBS->CloseEvent (Private->TouchHotplugEvent);
|
|
gBS->CloseEvent (Private->EdidActiveHotplugEvent);
|
|
gBS->CloseEvent (Private->GopHotplugEvent);
|
|
Private->GopHotplugEvent = NULL;
|
|
|
|
HideImage (&Private->Cursor);
|
|
InternalCloseKeyboard (SetupMouse);
|
|
|
|
RenderImageForAllGop (Private);
|
|
DestroyCursor (Private);
|
|
|
|
//
|
|
// Free GOP list
|
|
//
|
|
while (!IsListEmpty (&Private->GopList)) {
|
|
GopEntry = GOP_ENTRY_FROM_THIS (GetFirstNode (&Private->GopList));
|
|
RemoveEntryList (&GopEntry->Link);
|
|
FreeGopEntry (GopEntry, TRUE);
|
|
}
|
|
|
|
if (Private->PointerProtocolInfo) {
|
|
FreePool (Private->PointerProtocolInfo);
|
|
Private->PointerProtocolInfo = NULL;
|
|
}
|
|
|
|
Private->LButton = FALSE;
|
|
Private->RButton = FALSE;
|
|
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Query cursor coordinate and button state,
|
|
if ScreenMode is text, it will convert coordinate
|
|
|
|
@param [in] SetupMouse EFI_SETUP_MOUSE_PROTOCOL
|
|
@param [out] X X coordinate
|
|
@param [out] Y Y coordinate
|
|
@param [out] LeftButton Mouse left button is pressed or Touch panel is touched
|
|
@param [out] RightButton Right button is touched
|
|
|
|
@retval EFI_NOT_READY There was no keystroke data availiable
|
|
@retval EFI_SUCCESS Query status success
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
QueryState (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
OUT UINTN *X,
|
|
OUT UINTN *Y,
|
|
OUT BOOLEAN *LeftButton,
|
|
OUT BOOLEAN *RightButton
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
SETUP_MOUSE_STATE *State;
|
|
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
if (!Private->IsStart) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
if (!Private->HaveRawData) {
|
|
return EFI_NOT_READY;
|
|
}
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
|
|
State = &Private->State[Private->BufferOut];
|
|
|
|
*X = (UINTN) State->CurrentX;
|
|
*Y = (UINTN) State->CurrentY;
|
|
*LeftButton = State->LButton;
|
|
*RightButton = State->RButton;
|
|
|
|
if (Private->BufferOut != Private->BufferIn) {
|
|
Private->BufferOut++;
|
|
if (Private->BufferOut == STATE_BUFFER_SIZE) Private->BufferOut = 0;
|
|
}
|
|
if (Private->BufferOut == Private->BufferIn) {
|
|
Private->HaveRawData = FALSE;
|
|
}
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// SetupMouse Virtual Keyboard
|
|
//
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
StartKeyboard (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
IN UINTN X,
|
|
IN UINTN Y
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
SetupMouse->Start (SetupMouse);
|
|
|
|
if (PcdGetBool (PcdDisableVirtualKeyboard)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
AcquireSetupMouseLock (Private);
|
|
Status = InternalStartKeyboard (SetupMouse, X, Y);
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
KeyboardData function restores data from blt buffer to the screen.
|
|
|
|
@param [in] SetupMouse
|
|
|
|
@retval EFI_SUCCESS Screen has been restored from blt buffer successfully
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CloseKeyboard (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
Status = InternalCloseKeyboard (SetupMouse);
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseSetKeyboardAttributes (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
IN KEYBOARD_ATTRIBUTES *KeyboardAttributes
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
Status = InternalSetupMouseSetKeyboardAttributes (SetupMouse, KeyboardAttributes);
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseGetKeyboardAttributes (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
IN KEYBOARD_ATTRIBUTES *KeyboardAttributes
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
Status = InternalSetupMouseGetKeyboardAttributes (SetupMouse, KeyboardAttributes);
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseSetMouseAttributes (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
IN MOUSE_ATTRIBUTES *MouseAttributes
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
if (SetupMouse == NULL || MouseAttributes == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
if ((MouseAttributes->Flags & MOUSE_FLAG_VISIBLE) == MOUSE_FLAG_VISIBLE) {
|
|
Private->HideCursor = !MouseAttributes->Visible;
|
|
|
|
if (MouseAttributes->Visible) {
|
|
if (!Private->Cursor.Visible) {
|
|
ShowImage (&Private->Cursor);
|
|
RenderImageForAllGop (Private);
|
|
}
|
|
} else {
|
|
if (Private->Cursor.Visible) {
|
|
HideImage (&Private->Cursor);
|
|
RenderImageForAllGop (Private);
|
|
}
|
|
}
|
|
}
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
SetupMouseGetMouseAttributes (
|
|
IN EFI_SETUP_MOUSE_PROTOCOL *SetupMouse,
|
|
OUT MOUSE_ATTRIBUTES *MouseAttributes
|
|
)
|
|
{
|
|
PRIVATE_MOUSE_DATA *Private;
|
|
|
|
if (SetupMouse == NULL || MouseAttributes == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Private = SETUP_MOUSE_DEV_FROM_THIS (SetupMouse);
|
|
|
|
AcquireSetupMouseLock (Private);
|
|
MouseAttributes->Length = sizeof (MOUSE_ATTRIBUTES);
|
|
MouseAttributes->Flags = MOUSE_FLAG_VISIBLE;
|
|
MouseAttributes->Visible = !Private->HideCursor;
|
|
ReleaseSetupMouseLock (Private);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|