2019-09-03 11:58:42 +02:00
/** @file
Copyright ( c ) 2006 - 2011 , Intel Corporation . All rights reserved . < BR >
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution . The
full text of the license may be found at
http : //opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN " AS IS " BASIS ,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND , EITHER EXPRESS OR IMPLIED .
* */
// Slice - exclude LegacyBios
// Jief Machak - adopted to AppleKey protocol, 2018
//#include "BiosKeyboard.h"
# include "AppleKey.h"
// DBG_TO: 0=no debug, 1=serial, 2=console 3=log
// serial requires
// [PcdsFixedAtBuild]
// gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x07
// gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0xFFFFFFFF
// in package DSC file
# define DBG_BIOSKEYBOARD 0
# if DBG_BIOSKEYBOARD == 3
# define DBG(...) MemLog(FALSE, 0, __VA_ARGS__)
# elif DBG_BIOSKEYBOARD == 2
# define DBG(...) AsciiPrint(__VA_ARGS__)
# elif DBG_BIOSKEYBOARD == 1
# define DBG(...) DebugPrint(1, __VA_ARGS__)
# else
# define DBG(...)
# endif
extern int MapBiosKey ( EFI_KEY_DATA KeyData , APPLE_KEY * pKey , UINT8 * pCurModifierMap ) ;
//
// EFI Driver Binding Protocol Instance
//
EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = {
BiosKeyboardDriverBindingSupported ,
BiosKeyboardDriverBindingStart ,
BiosKeyboardDriverBindingStop ,
0x3 ,
NULL ,
NULL
} ;
EFI_LEGACY_8259_PROTOCOL * mLegacy8259 = NULL ;
THUNK_CONTEXT mThunkContext ;
/**
Enqueue the key .
@ param Queue The queue to be enqueued .
@ param KeyData The key data to be enqueued .
@ retval EFI_NOT_READY The queue is full .
@ retval EFI_SUCCESS Successfully enqueued the key data .
* */
EFI_STATUS
Enqueue (
IN SIMPLE_QUEUE * Queue ,
IN EFI_KEY_DATA * KeyData
)
{
if ( ( Queue - > Rear + 1 ) % QUEUE_MAX_COUNT = = Queue - > Front ) {
return EFI_NOT_READY ;
}
CopyMem ( & Queue - > Buffer [ Queue - > Rear ] , KeyData , sizeof ( EFI_KEY_DATA ) ) ;
Queue - > Rear = ( Queue - > Rear + 1 ) % QUEUE_MAX_COUNT ;
return EFI_SUCCESS ;
}
/**
Dequeue the key .
@ param Queue The queue to be dequeued .
@ param KeyData The key data to be dequeued .
@ retval EFI_NOT_READY The queue is empty .
@ retval EFI_SUCCESS Successfully dequeued the key data .
* */
EFI_STATUS
Dequeue (
IN SIMPLE_QUEUE * Queue ,
IN EFI_KEY_DATA * KeyData
)
{
if ( Queue - > Front = = Queue - > Rear ) {
return EFI_NOT_READY ;
}
CopyMem ( KeyData , & Queue - > Buffer [ Queue - > Front ] , sizeof ( EFI_KEY_DATA ) ) ;
Queue - > Front = ( Queue - > Front + 1 ) % QUEUE_MAX_COUNT ;
return EFI_SUCCESS ;
}
/**
Check whether the queue is empty .
@ param Queue The queue to be checked .
@ retval EFI_NOT_READY The queue is empty .
@ retval EFI_SUCCESS The queue is not empty .
* */
EFI_STATUS
CheckQueue (
IN SIMPLE_QUEUE * Queue
)
{
if ( Queue - > Front = = Queue - > Rear ) {
return EFI_NOT_READY ;
}
return EFI_SUCCESS ;
}
//
// EFI Driver Binding Protocol Functions
//
/**
Check whether the driver supports this device .
@ param This The Udriver binding protocol .
@ param Controller The controller handle to check .
@ param RemainingDevicePath The remaining device path .
@ retval EFI_SUCCESS The driver supports this controller .
@ retval other This device isn ' t supported .
* */
EFI_STATUS
EFIAPI
BiosKeyboardDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This ,
IN EFI_HANDLE Controller ,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath
)
{
//DBG("BiosKeyboardDriverBindingSupported\n");
EFI_STATUS Status ;
EFI_LEGACY_8259_PROTOCOL * Legacy8259 ;
EFI_ISA_IO_PROTOCOL * IsaIo ;
//
// See if the Legacy BIOS Protocol is available
//
/* Status = gBS->LocateProtocol (
& gEfiLegacyBiosProtocolGuid ,
NULL ,
( VOID * * ) & LegacyBios
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
} */
//
// See if the Legacy 8259 Protocol is available
//
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( VOID * * ) & Legacy8259 ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
DBG ( " Legacy 8259 Protocol NOT available \n " ) ;
return Status ;
}
//
// Open the IO Abstraction(s) needed to perform the supported test
//
Status = gBS - > OpenProtocol (
Controller ,
& gEfiIsaIoProtocolGuid ,
( VOID * * ) & IsaIo ,
This - > DriverBindingHandle ,
Controller ,
EFI_OPEN_PROTOCOL_BY_DRIVER
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
//DBG("OpenProtocol gEfiIsaIoProtocolGuid failed, status=%x\n", Status);
return Status ;
}
//
// Use the ISA I/O Protocol to see if Controller is the Keyboard controller
//
if ( IsaIo - > ResourceList - > Device . HID ! = EISA_PNP_ID ( 0x303 ) | | IsaIo - > ResourceList - > Device . UID ! = 0 ) {
//DBG("EFI_UNSUPPORTED\n");
Status = EFI_UNSUPPORTED ;
}
gBS - > CloseProtocol (
Controller ,
& gEfiIsaIoProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
if ( Status = = 0 ) {
DBG ( " BiosKeyboardDriverBindingSupported return %x \n " , Status ) ;
}
return Status ;
}
/**
Starts the device with this driver .
@ param This The driver binding instance .
@ param Controller Handle of device to bind driver to .
@ param RemainingDevicePath Optional parameter use to pick a specific child
device to start .
@ retval EFI_SUCCESS The controller is controlled by the driver .
@ retval Other This controller cannot be started .
* */
EFI_STATUS
EFIAPI
BiosKeyboardDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This ,
IN EFI_HANDLE Controller ,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath
)
{
//DBG("BiosKeyboardDriverBindingStart This=%x. Controller=%d, RemainingDevicePath=%x\n", This, Controller, RemainingDevicePath);
EFI_STATUS Status ;
// EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
EFI_ISA_IO_PROTOCOL * IsaIo ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
IA32_REGISTER_SET Regs ;
BOOLEAN CarryFlag ;
EFI_PS2_POLICY_PROTOCOL * Ps2Policy ;
UINT8 Command ;
EFI_STATUS_CODE_VALUE StatusCode ;
EFI_DEVICE_PATH_PROTOCOL * ParentDevicePath ;
ZeroMem ( & Regs , sizeof ( EFI_IA32_REGISTER_SET ) ) ;
BiosKeyboardPrivate = NULL ;
IsaIo = NULL ;
StatusCode = 0 ;
//
// Get Ps2 policy to set. Will be use if present.
//
gBS - > LocateProtocol (
& gEfiPs2PolicyProtocolGuid ,
NULL ,
( VOID * * ) & Ps2Policy
) ;
//
// See if the Legacy BIOS Protocol is available
//
/* Status = gBS->LocateProtocol (
& gEfiLegacyBiosProtocolGuid ,
NULL ,
( VOID * * ) & LegacyBios
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
} */
//
// Establish legacy environment for thunk call for all children handle.
//
if ( mLegacy8259 = = NULL ) {
Status = gBS - > LocateProtocol ( & gEfiLegacy8259ProtocolGuid , NULL , ( VOID * * ) & mLegacy8259 ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
goto Done ;
}
InitializeBiosIntCaller ( & mThunkContext ) ;
InitializeInterruptRedirection ( mLegacy8259 ) ;
}
Status = gBS - > OpenProtocol (
Controller ,
& gEfiDevicePathProtocolGuid ,
( VOID * * ) & ParentDevicePath ,
This - > DriverBindingHandle ,
Controller ,
EFI_OPEN_PROTOCOL_BY_DRIVER
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
//
// Open the IO Abstraction(s) needed
//
Status = gBS - > OpenProtocol (
Controller ,
& gEfiIsaIoProtocolGuid ,
( VOID * * ) & IsaIo ,
This - > DriverBindingHandle ,
Controller ,
EFI_OPEN_PROTOCOL_BY_DRIVER
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
gBS - > CloseProtocol (
Controller ,
& gEfiDevicePathProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
return Status ;
}
//
// Allocate the private device structure
//
BiosKeyboardPrivate = ( BIOS_KEYBOARD_DEV * ) AllocateZeroPool ( sizeof ( BIOS_KEYBOARD_DEV ) ) ;
if ( NULL = = BiosKeyboardPrivate ) {
Status = EFI_OUT_OF_RESOURCES ;
goto Done ;
}
BiosKbLocateAppleKeyMapDb ( BiosKeyboardPrivate ) ;
//
// Initialize the private device structure
//
BiosKeyboardPrivate - > Signature = BIOS_KEYBOARD_DEV_SIGNATURE ;
BiosKeyboardPrivate - > Handle = Controller ;
//BiosKeyboardPrivate->LegacyBios = NULL; //LegacyBios;
//
// Child handle need to consume the Legacy Bios protocol
//
BiosKeyboardPrivate - > Legacy8259 = mLegacy8259 ;
BiosKeyboardPrivate - > ThunkContext = & mThunkContext ;
BiosKeyboardPrivate - > IsaIo = IsaIo ;
BiosKeyboardPrivate - > DevicePath = ParentDevicePath ;
BiosKeyboardPrivate - > SimpleTextIn . Reset = BiosKeyboardReset ;
BiosKeyboardPrivate - > SimpleTextIn . ReadKeyStroke = BiosKeyboardReadKeyStroke ;
BiosKeyboardPrivate - > DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER ;
BiosKeyboardPrivate - > StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER ;
BiosKeyboardPrivate - > CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER ;
BiosKeyboardPrivate - > ExtendedKeyboard = TRUE ;
BiosKeyboardPrivate - > Queue . Front = 0 ;
BiosKeyboardPrivate - > Queue . Rear = 0 ;
BiosKeyboardPrivate - > SimpleTextInputEx . Reset = BiosKeyboardResetEx ;
BiosKeyboardPrivate - > SimpleTextInputEx . ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx ;
BiosKeyboardPrivate - > SimpleTextInputEx . SetState = BiosKeyboardSetState ;
BiosKeyboardPrivate - > SimpleTextInputEx . RegisterKeyNotify = BiosKeyboardRegisterKeyNotify ;
BiosKeyboardPrivate - > SimpleTextInputEx . UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify ;
InitializeListHead ( & BiosKeyboardPrivate - > NotifyList ) ;
//
// Report that the keyboard is being enabled
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE
) ;
//
// Setup the WaitForKey event
//
Status = gBS - > CreateEvent (
EVT_NOTIFY_WAIT ,
TPL_NOTIFY ,
BiosKeyboardWaitForKey ,
& ( BiosKeyboardPrivate - > SimpleTextIn ) ,
& ( ( BiosKeyboardPrivate - > SimpleTextIn ) . WaitForKey )
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
( BiosKeyboardPrivate - > SimpleTextIn ) . WaitForKey = NULL ;
goto Done ;
}
Status = gBS - > CreateEvent (
EVT_NOTIFY_WAIT ,
TPL_NOTIFY ,
BiosKeyboardWaitForKeyEx ,
& ( BiosKeyboardPrivate - > SimpleTextInputEx ) ,
& ( BiosKeyboardPrivate - > SimpleTextInputEx . WaitForKeyEx )
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
BiosKeyboardPrivate - > SimpleTextInputEx . WaitForKeyEx = NULL ;
goto Done ;
}
//
// Setup a periodic timer, used for reading keystrokes at a fixed interval
//
Status = gBS - > CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL ,
TPL_NOTIFY ,
BiosKeyboardTimerHandler ,
BiosKeyboardPrivate ,
& BiosKeyboardPrivate - > TimerEvent
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_OUT_OF_RESOURCES ;
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR ;
goto Done ;
}
Status = gBS - > SetTimer (
BiosKeyboardPrivate - > TimerEvent ,
TimerPeriodic ,
KEYBOARD_TIMER_INTERVAL
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_OUT_OF_RESOURCES ;
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR ;
goto Done ;
}
//
// Report a Progress Code for an attempt to detect the presence of the keyboard device in the system
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT
) ;
//DBG("BiosKeyboardDriverBindingStart 2.1\n");
//
// Reset the keyboard device
//
BOOLEAN extVerif = FeaturePcdGet ( PcdPs2KbdExtendedVerification ) ;
Status = BiosKeyboardPrivate - > SimpleTextInputEx . Reset (
& BiosKeyboardPrivate - > SimpleTextInputEx ,
extVerif
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
// DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));
StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED ;
goto Done ;
}
//
// Do platform specific policy like port swapping and keyboard light default
//
//DBG("BiosKeyboardDriverBindingStart 3\n");
if ( Ps2Policy ! = NULL ) {
Ps2Policy - > Ps2InitHardware ( Controller ) ;
Command = 0 ;
if ( ( Ps2Policy - > KeyboardLight & EFI_KEYBOARD_CAPSLOCK ) = = EFI_KEYBOARD_CAPSLOCK ) {
Command | = 4 ;
}
if ( ( Ps2Policy - > KeyboardLight & EFI_KEYBOARD_NUMLOCK ) = = EFI_KEYBOARD_NUMLOCK ) {
Command | = 2 ;
}
if ( ( Ps2Policy - > KeyboardLight & EFI_KEYBOARD_SCROLLLOCK ) = = EFI_KEYBOARD_SCROLLLOCK ) {
Command | = 1 ;
}
KeyboardWrite ( BiosKeyboardPrivate , 0xed ) ;
KeyboardWaitForValue ( BiosKeyboardPrivate , 0xfa , KEYBOARD_WAITFORVALUE_TIMEOUT ) ;
KeyboardWrite ( BiosKeyboardPrivate , Command ) ;
//
// Call Legacy BIOS Protocol to set whatever is necessary
//
// LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
}
//
// Get Configuration
//
Regs . H . AH = 0xc0 ;
/* CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
BiosKeyboardPrivate - > LegacyBios ,
0x15 ,
& Regs
) ; */
CarryFlag = LegacyBiosInt86 ( BiosKeyboardPrivate , 0x15 , & Regs ) ;
if ( ! CarryFlag ) {
//
// Check bit 6 of Feature Byte 2.
// If it is set, then Int 16 Func 09 is supported
//
if ( * ( UINT8 * ) ( UINTN ) ( ( Regs . E . ES < < 4 ) + Regs . X . BX + 0x06 ) & 0x40 ) {
//
// Get Keyboard Functionality
//
Regs . H . AH = 0x09 ;
/* CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
BiosKeyboardPrivate - > LegacyBios ,
0x16 ,
& Regs
) ; */
CarryFlag = LegacyBiosInt86 ( BiosKeyboardPrivate , 0x16 , & Regs ) ;
if ( ! CarryFlag ) {
//
// Check bit 5 of AH.
// If it is set, then INT 16 Finc 10-12 are supported.
//
if ( ( Regs . H . AL & 0x40 ) ! = 0 ) {
//
// Set the flag to use INT 16 Func 10-12
//
BiosKeyboardPrivate - > ExtendedKeyboard = TRUE ;
}
}
}
}
// DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard));
BiosKeyboardPrivate - > ControllerNameTable = NULL ;
AddUnicodeString2 (
" eng " ,
gBiosKeyboardComponentName . SupportedLanguages ,
& BiosKeyboardPrivate - > ControllerNameTable ,
L " BIOS[INT16] Keyboard Device " ,
TRUE
) ;
AddUnicodeString2 (
" en " ,
gBiosKeyboardComponentName2 . SupportedLanguages ,
& BiosKeyboardPrivate - > ControllerNameTable ,
L " BIOS[INT16] Keyboard Device " ,
FALSE
) ;
//
// Install protocol interfaces for the keyboard device.
//
Status = gBS - > InstallMultipleProtocolInterfaces (
& Controller ,
& gEfiSimpleTextInProtocolGuid ,
& BiosKeyboardPrivate - > SimpleTextIn ,
& gEfiSimpleTextInputExProtocolGuid ,
& BiosKeyboardPrivate - > SimpleTextInputEx ,
NULL
) ;
Done :
if ( StatusCode ! = 0 ) {
//
// Report an Error Code for failing to start the keyboard device
//
REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR ,
StatusCode
) ;
}
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
if ( BiosKeyboardPrivate ! = NULL ) {
if ( ( BiosKeyboardPrivate - > SimpleTextIn ) . WaitForKey ! = NULL ) {
gBS - > CloseEvent ( ( BiosKeyboardPrivate - > SimpleTextIn ) . WaitForKey ) ;
}
if ( ( BiosKeyboardPrivate - > SimpleTextInputEx ) . WaitForKeyEx ! = NULL ) {
gBS - > CloseEvent ( ( BiosKeyboardPrivate - > SimpleTextInputEx ) . WaitForKeyEx ) ;
}
BiosKeyboardFreeNotifyList ( & BiosKeyboardPrivate - > NotifyList ) ;
if ( BiosKeyboardPrivate - > TimerEvent ! = NULL ) {
gBS - > CloseEvent ( BiosKeyboardPrivate - > TimerEvent ) ;
}
2020-04-23 11:08:10 +02:00
FreePool ( BiosKeyboardPrivate ) ;
2019-09-03 11:58:42 +02:00
}
gBS - > CloseProtocol (
Controller ,
& gEfiDevicePathProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
if ( IsaIo ! = NULL ) {
gBS - > CloseProtocol (
Controller ,
& gEfiIsaIoProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
}
}
return Status ;
}
/**
Stop the device handled by this driver .
@ param This The driver binding protocol .
@ param Controller The controller to release .
@ param NumberOfChildren The number of handles in ChildHandleBuffer .
@ param ChildHandleBuffer The array of child handle .
@ retval EFI_SUCCESS The device was stopped .
@ retval EFI_DEVICE_ERROR The device could not be stopped due to a device error .
@ retval Others Fail to uninstall protocols attached on the device .
* */
EFI_STATUS
EFIAPI
BiosKeyboardDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL * This ,
IN EFI_HANDLE Controller ,
IN UINTN NumberOfChildren ,
IN EFI_HANDLE * ChildHandleBuffer
)
{
EFI_STATUS Status ;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL * SimpleTextIn ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
//
// Disable Keyboard
//
Status = gBS - > OpenProtocol (
Controller ,
& gEfiSimpleTextInProtocolGuid ,
( VOID * * ) & SimpleTextIn ,
This - > DriverBindingHandle ,
Controller ,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
Status = gBS - > OpenProtocol (
Controller ,
& gEfiSimpleTextInputExProtocolGuid ,
NULL ,
This - > DriverBindingHandle ,
Controller ,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS ( SimpleTextIn ) ;
BiosKbFreeAppleKeyMapDb ( BiosKeyboardPrivate ) ;
Status = gBS - > UninstallMultipleProtocolInterfaces (
Controller ,
& gEfiSimpleTextInProtocolGuid ,
& BiosKeyboardPrivate - > SimpleTextIn ,
& gEfiSimpleTextInputExProtocolGuid ,
& BiosKeyboardPrivate - > SimpleTextInputEx ,
NULL
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
return Status ;
}
//
// Release the IsaIo protocol on the controller handle
//
gBS - > CloseProtocol (
Controller ,
& gEfiDevicePathProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
gBS - > CloseProtocol (
Controller ,
& gEfiIsaIoProtocolGuid ,
This - > DriverBindingHandle ,
Controller
) ;
//
// Free other resources
//
gBS - > CloseEvent ( ( BiosKeyboardPrivate - > SimpleTextIn ) . WaitForKey ) ;
gBS - > CloseEvent ( BiosKeyboardPrivate - > TimerEvent ) ;
gBS - > CloseEvent ( BiosKeyboardPrivate - > SimpleTextInputEx . WaitForKeyEx ) ;
BiosKeyboardFreeNotifyList ( & BiosKeyboardPrivate - > NotifyList ) ;
2020-04-23 11:08:10 +02:00
FreePool ( BiosKeyboardPrivate ) ;
2019-09-03 11:58:42 +02:00
return EFI_SUCCESS ;
}
/**
Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ return The data byte read from output buffer of Keyboard Controller from data port which often is port 60 H .
* */
UINT8
KeyReadDataRegister (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate
)
{
UINT8 Data ;
//
// Use IsaIo protocol to perform IO operations
//
BiosKeyboardPrivate - > IsaIo - > Io . Read (
BiosKeyboardPrivate - > IsaIo ,
EfiIsaIoWidthUint8 ,
BiosKeyboardPrivate - > DataRegisterAddress ,
1 ,
& Data
) ;
return Data ;
}
/**
Read status byte from status register of Keyboard Controller without delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ return The status byte read from status register of Keyboard Controller from command port which often is port 64 H .
* */
UINT8
KeyReadStatusRegister (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate
)
{
UINT8 Data ;
//
// Use IsaIo protocol to perform IO operations
//
BiosKeyboardPrivate - > IsaIo - > Io . Read (
BiosKeyboardPrivate - > IsaIo ,
EfiIsaIoWidthUint8 ,
BiosKeyboardPrivate - > StatusRegisterAddress ,
1 ,
& Data
) ;
return Data ;
}
/**
Write command byte to control register of Keyboard Controller without delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Data Data byte to write .
* */
VOID
KeyWriteCommandRegister (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
IN UINT8 Data
)
{
//
// Use IsaIo protocol to perform IO operations
//
BiosKeyboardPrivate - > IsaIo - > Io . Write (
BiosKeyboardPrivate - > IsaIo ,
EfiIsaIoWidthUint8 ,
BiosKeyboardPrivate - > CommandRegisterAddress ,
1 ,
& Data
) ;
}
/**
Write data byte to input buffer or input / output ports of Keyboard Controller without delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Data Data byte to write .
* */
VOID
KeyWriteDataRegister (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
IN UINT8 Data
)
{
//
// Use IsaIo protocol to perform IO operations
//
BiosKeyboardPrivate - > IsaIo - > Io . Write (
BiosKeyboardPrivate - > IsaIo ,
EfiIsaIoWidthUint8 ,
BiosKeyboardPrivate - > DataRegisterAddress ,
1 ,
& Data
) ;
}
/**
Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Data The pointer for data that being read out .
@ retval EFI_SUCCESS The data byte read out successfully .
@ retval EFI_TIMEOUT Timeout occurred during reading out data byte .
* */
EFI_STATUS
KeyboardRead (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
OUT UINT8 * Data
)
{
UINT32 TimeOut ;
UINT32 RegFilled ;
TimeOut = 0 ;
RegFilled = 0 ;
//
// wait till output buffer full then perform the read
//
for ( TimeOut = 0 ; TimeOut < KEYBOARD_TIMEOUT ; TimeOut + = 30 ) {
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_OUTB ) ! = 0 ) {
RegFilled = 1 ;
* Data = KeyReadDataRegister ( BiosKeyboardPrivate ) ;
break ;
}
gBS - > Stall ( 30 ) ;
}
if ( RegFilled = = 0 ) {
return EFI_TIMEOUT ;
}
return EFI_SUCCESS ;
}
/**
Write data byte to input buffer or input / output ports of Keyboard Controller with delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Data Data byte to write .
@ retval EFI_SUCCESS The data byte is written successfully .
@ retval EFI_TIMEOUT Timeout occurred during writing .
* */
EFI_STATUS
KeyboardWrite (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
IN UINT8 Data
)
{
UINT32 TimeOut ;
UINT32 RegEmptied ;
TimeOut = 0 ;
RegEmptied = 0 ;
//
// wait for input buffer empty
//
for ( TimeOut = 0 ; TimeOut < KEYBOARD_TIMEOUT ; TimeOut + = 30 ) {
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_INPB ) = = 0 ) {
RegEmptied = 1 ;
break ;
}
gBS - > Stall ( 30 ) ;
}
if ( RegEmptied = = 0 ) {
return EFI_TIMEOUT ;
}
//
// Write it
//
KeyWriteDataRegister ( BiosKeyboardPrivate , Data ) ;
return EFI_SUCCESS ;
}
/**
Write command byte to control register of Keyboard Controller with delay and waiting for buffer - empty state .
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Data Command byte to write .
@ retval EFI_SUCCESS The command byte is written successfully .
@ retval EFI_TIMEOUT Timeout occurred during writing .
* */
EFI_STATUS
KeyboardCommand (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
IN UINT8 Data
)
{
UINT32 TimeOut ;
UINT32 RegEmptied ;
TimeOut = 0 ;
RegEmptied = 0 ;
//
// Wait For Input Buffer Empty
//
for ( TimeOut = 0 ; TimeOut < KEYBOARD_TIMEOUT ; TimeOut + = 30 ) {
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_INPB ) = = 0 ) {
RegEmptied = 1 ;
break ;
}
gBS - > Stall ( 30 ) ;
}
if ( RegEmptied = = 0 ) {
return EFI_TIMEOUT ;
}
//
// issue the command
//
KeyWriteCommandRegister ( BiosKeyboardPrivate , Data ) ;
//
// Wait For Input Buffer Empty again
//
RegEmptied = 0 ;
for ( TimeOut = 0 ; TimeOut < KEYBOARD_TIMEOUT ; TimeOut + = 30 ) {
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_INPB ) = = 0 ) {
RegEmptied = 1 ;
break ;
}
gBS - > Stall ( 30 ) ;
}
if ( RegEmptied = = 0 ) {
return EFI_TIMEOUT ;
}
return EFI_SUCCESS ;
}
/**
Wait for a specific value to be presented in
Data register of Keyboard Controller by keyboard and then read it ,
used in keyboard commands ack
@ param BiosKeyboardPrivate Keyboard instance pointer .
@ param Value The value to be waited for
@ param WaitForValueTimeOut The limit of microseconds for timeout
@ retval EFI_SUCCESS The command byte is written successfully .
@ retval EFI_TIMEOUT Timeout occurred during writing .
* */
EFI_STATUS
KeyboardWaitForValue (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
IN UINT8 Value ,
IN UINTN WaitForValueTimeOut
)
{
UINT8 Data ;
UINT32 TimeOut ;
UINT32 SumTimeOut ;
UINT32 GotIt ;
GotIt = 0 ;
TimeOut = 0 ;
SumTimeOut = 0 ;
//
// Make sure the initial value of 'Data' is different from 'Value'
//
Data = 0 ;
if ( Data = = Value ) {
Data = 1 ;
}
//
// Read from 8042 (multiple times if needed)
// until the expected value appears
// use SumTimeOut to control the iteration
//
while ( 1 ) {
//
// Perform a read
//
for ( TimeOut = 0 ; TimeOut < KEYBOARD_TIMEOUT ; TimeOut + = 30 ) {
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_OUTB ) ! = 0 ) {
Data = KeyReadDataRegister ( BiosKeyboardPrivate ) ;
break ;
}
gBS - > Stall ( 30 ) ;
}
SumTimeOut + = TimeOut ;
if ( Data = = Value ) {
GotIt = 1 ;
break ;
}
if ( SumTimeOut > = WaitForValueTimeOut ) {
break ;
}
}
//
// Check results
//
if ( GotIt ! = 0 ) {
return EFI_SUCCESS ;
} else {
return EFI_TIMEOUT ;
}
}
/**
Reads the next keystroke from the input device . The WaitForKey Event can
be used to test for existance of a keystroke via WaitForEvent ( ) call .
@ param BiosKeyboardPrivate Bioskeyboard driver private structure .
@ param KeyData A pointer to a buffer that is filled in with the keystroke
state data for the key that was pressed .
@ retval EFI_SUCCESS The keystroke information was returned .
@ retval EFI_NOT_READY There was no keystroke data availiable .
@ retval EFI_DEVICE_ERROR The keystroke information was not returned due to
hardware errors .
@ retval EFI_INVALID_PARAMETER KeyData is NULL .
* */
EFI_STATUS
KeyboardReadKeyStrokeWorker (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ,
OUT EFI_KEY_DATA * KeyData
)
{
EFI_STATUS Status ;
EFI_TPL OldTpl ;
if ( KeyData = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
//
// Use TimerEvent callback function to check whether there's any key pressed
//
//
// Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
// Csm will be used to check whether there is a key pending, but the csm will disable all
// interrupt before switch to compatibility16, which mean all the efiCompatibility timer
// event will stop work during the compatibility16. And If a caller recursivly invoke this function,
// e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,
// e.g. usb keyboard driver.
// Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
// 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
//
gBS - > Stall ( 1000 ) ;
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
BiosKeyboardTimerHandler ( NULL , BiosKeyboardPrivate ) ;
//
// If there's no key, just return
//
Status = CheckQueue ( & BiosKeyboardPrivate - > Queue ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
gBS - > RestoreTPL ( OldTpl ) ;
return EFI_NOT_READY ;
}
/*Status = */ Dequeue ( & BiosKeyboardPrivate - > Queue , KeyData ) ;
gBS - > RestoreTPL ( OldTpl ) ;
return EFI_SUCCESS ;
}
//
// EFI Simple Text In Protocol Functions
//
/**
Reset the Keyboard and do BAT test for it , if ( ExtendedVerification = = TRUE ) then do some extra keyboard validations .
@ param This Pointer of simple text Protocol .
@ param ExtendedVerification Whether perform the extra validation of keyboard . True : perform ; FALSE : skip .
@ retval EFI_SUCCESS The command byte is written successfully .
@ retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard .
* */
EFI_STATUS
EFIAPI
BiosKeyboardReset (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This ,
IN BOOLEAN ExtendedVerification
)
{
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_STATUS Status = 0 ;
EFI_TPL OldTpl ;
UINT8 CommandByte ;
BOOLEAN MouseEnable ;
EFI_INPUT_KEY Key ;
MouseEnable = FALSE ;
BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
//
// 1
// Report reset progress code
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET
) ;
//
// Report a Progress Code for clearing the keyboard buffer
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER
) ;
//
// 2
// Raise TPL to avoid mouse operation impact
//
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
//
//
// Exhaust output buffer data
//
do {
Status = BiosKeyboardReadKeyStroke (
This ,
& Key
) ;
2020-04-23 11:08:10 +02:00
} while ( ! EFI_ERROR ( Status ) ) ;
2019-09-03 11:58:42 +02:00
//
// 3
// check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H
// if not skip step 4&5 and jump to step 6 to selftest KBC and report this
// else go step 4
//
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & KBC_STSREG_VIA64_SYSF ) ! = 0 ) {
//
// 4
// CheckMouseStatus to decide enable it later or not
//
//
// Read the command byte of KBC
//
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_CMDBYTE_R
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardRead (
BiosKeyboardPrivate ,
& CommandByte
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// Check mouse enabled or not before
//
if ( ( CommandByte & KB_CMMBYTE_DISABLE_AUX ) ! = 0 ) {
MouseEnable = FALSE ;
} else {
MouseEnable = TRUE ;
}
//
// 5
// disable mouse (via KBC) and Keyboard device
//
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_AUX_DISABLE
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_KB_DISABLE
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
} else {
//
// 6
// KBC Self Test
//
//
// Report a Progress Code for performing a self test on the keyboard controller
//
REPORT_STATUS_CODE (
EFI_PROGRESS_CODE ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST
) ;
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_KBC_SLFTEST
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_KBCSLFTEST_OK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
}
//
// 7
// Disable Mouse interface, enable Keyboard interface and declare selftest success
//
// Mouse device will block keyboard interface before it be configured, so we should disable mouse first.
//
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_CMDBYTE_W
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// Write 8042 Command Byte, set System Flag
// While at the same time:
// 1. disable mouse interface,
// 2. enable kbd interface,
// 3. enable PC/XT kbd translation mode
// 4. enable mouse and kbd interrupts
//
//Command Byte bits:
// 7: Reserved
// 6: PC/XT translation mode
// 5: Disable Auxiliary device interface
// 4: Disable keyboard interface
// 3: Reserved
// 2: System Flag
// 1: Enable Auxiliary device interrupt
// 0: Enable Keyboard interrupt
//
CommandByte = 0 ;
Status = KeyboardWrite (
BiosKeyboardPrivate ,
( UINT8 ) ( ( CommandByte &
( ~ KB_CMMBYTE_DISABLE_KB ) ) |
KB_CMMBYTE_KSCAN2UNI_COV |
KB_CMMBYTE_ENABLE_AUXINT |
KB_CMMBYTE_ENABLE_KBINT |
KB_CMMBYTE_SLFTEST_SUCC |
KB_CMMBYTE_DISABLE_AUX )
) ;
//
// For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
// so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.
// Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
// Real reset will not do.
//
if ( ExtendedVerification & & CheckKeyboardConnect ( BiosKeyboardPrivate ) ) {
//
// 8
// Send keyboard reset command then read ACK
//
Status = KeyboardWrite (
BiosKeyboardPrivate ,
KBC_INPBUF_VIA60_KBRESET
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_ACK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// 9
// Wait for keyboard return test OK.
//
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_BATTEST_OK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// 10
// set keyboard scan code set = 02 (standard configuration)
//
Status = KeyboardWrite (
BiosKeyboardPrivate ,
KBC_INPBUF_VIA60_KBSCODE
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_ACK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWrite (
BiosKeyboardPrivate ,
KBC_INPBUF_VIA60_SCODESET2
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_ACK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// 11
// enable keyboard itself (not via KBC) by writing CMD F4 via 60H
//
Status = KeyboardWrite (
BiosKeyboardPrivate ,
KBC_INPBUF_VIA60_KBEN
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_ACK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// 12
// Additional validation, do it as follow:
// 1). check for status register of PARE && TIM via 64H
// 2). perform KB checking by writing ABh via 64H
//
if ( ( KeyReadStatusRegister ( BiosKeyboardPrivate ) & ( KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM ) ) ! = 0 ) {
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_KB_CKECK
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_KBCHECK_OK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
}
//
// 13
// Done for validating keyboard. Enable keyboard (via KBC)
// and recover the command byte to proper value
//
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_KB_ENABLE
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Exit ;
}
//
// 14
// conditionally enable mouse (via KBC)
//
if ( MouseEnable ) {
Status = KeyboardCommand (
BiosKeyboardPrivate ,
KBC_CMDREG_VIA64_AUX_ENABLE
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
}
}
Exit :
//
// 15
// resume priority of task level
//
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
/**
Read out the scan code of the key that has just been stroked .
@ param This Pointer of simple text Protocol .
@ param Key Pointer for store the key that read out .
@ retval EFI_SUCCESS The key is read out successfully .
@ retval other The key reading failed .
* */
EFI_STATUS
EFIAPI
BiosKeyboardReadKeyStroke (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This ,
OUT EFI_INPUT_KEY * Key
)
{
//DBG("BiosKeyboardReadKeyStroke\n");
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_STATUS Status ;
EFI_KEY_DATA KeyData ;
BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
Status = KeyboardReadKeyStrokeWorker ( BiosKeyboardPrivate , & KeyData ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) { //EFI_NOT_READY mean the queue is empty
2019-09-03 11:58:42 +02:00
return Status ;
}
//
// Convert the Ctrl+[a-z] to Ctrl+[1-26]
//
if ( ( KeyData . KeyState . KeyShiftState & ( EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED ) ) ! = 0 ) {
if ( KeyData . Key . UnicodeChar > = L ' a ' & & KeyData . Key . UnicodeChar < = L ' z ' ) {
KeyData . Key . UnicodeChar = ( CHAR16 ) ( KeyData . Key . UnicodeChar - L ' a ' + 1 ) ;
} else if ( KeyData . Key . UnicodeChar > = L ' A ' & & KeyData . Key . UnicodeChar < = L ' Z ' ) {
KeyData . Key . UnicodeChar = ( CHAR16 ) ( KeyData . Key . UnicodeChar - L ' A ' + 1 ) ;
}
}
CopyMem ( Key , & KeyData . Key , sizeof ( EFI_INPUT_KEY ) ) ;
return EFI_SUCCESS ;
}
/**
Waiting on the keyboard event , if there ' s any key pressed by the user , signal the event
@ param Event The event that be siganlled when any key has been stroked .
@ param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL .
* */
VOID
EFIAPI
BiosKeyboardWaitForKey (
IN EFI_EVENT Event ,
IN VOID * Context
)
{
//
// Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
// Csm will be used to check whether there is a key pending, but the csm will disable all
// interrupt before switch to compatibility16, which mean all the efiCompatibility timer
// event will stop work during the compatibility16. And If a caller recursivly invoke this function,
// e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,
// e.g. usb keyboard driver.
// Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
// 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
//
gBS - > Stall ( 1000 ) ;
//
// Use TimerEvent callback function to check whether there's any key pressed
//
BiosKeyboardTimerHandler ( NULL , BIOS_KEYBOARD_DEV_FROM_THIS ( Context ) ) ;
2020-04-23 11:08:10 +02:00
if ( ! EFI_ERROR ( BiosKeyboardCheckForKey ( Context ) ) ) {
2019-09-03 11:58:42 +02:00
gBS - > SignalEvent ( Event ) ;
}
}
/**
Check key buffer to get the key stroke status .
@ param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL .
@ retval EFI_SUCCESS A key is being pressed now .
@ retval Other No key is now pressed .
* */
EFI_STATUS
EFIAPI
BiosKeyboardCheckForKey (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This
)
{
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
return CheckQueue ( & BiosKeyboardPrivate - > Queue ) ;
}
//
// Private worker functions
//
# define TABLE_END 0x0
typedef struct _CONVERT_TABLE_ENTRY {
UINT16 ScanCode ;
UINT16 EfiScanCode ;
} CONVERT_TABLE_ENTRY ;
CONVERT_TABLE_ENTRY mConvertTable [ ] = {
{
0x47 ,
SCAN_HOME
} ,
{
0x48 ,
SCAN_UP
} ,
{
0x49 ,
SCAN_PAGE_UP
} ,
{
0x4b ,
SCAN_LEFT
} ,
{
0x4d ,
SCAN_RIGHT
} ,
{
0x4f ,
SCAN_END
} ,
{
0x50 ,
SCAN_DOWN
} ,
{
0x51 ,
SCAN_PAGE_DOWN
} ,
{
0x52 ,
SCAN_INSERT
} ,
{
0x53 ,
SCAN_DELETE
} ,
//
// Function Keys are only valid if KeyChar == 0x00
// This function does not require KeyChar to be 0x00
//
{
0x3b ,
SCAN_F1
} ,
{
0x3c ,
SCAN_F2
} ,
{
0x3d ,
SCAN_F3
} ,
{
0x3e ,
SCAN_F4
} ,
{
0x3f ,
SCAN_F5
} ,
{
0x40 ,
SCAN_F6
} ,
{
0x41 ,
SCAN_F7
} ,
{
0x42 ,
SCAN_F8
} ,
{
0x43 ,
SCAN_F9
} ,
{
0x44 ,
SCAN_F10
} ,
{
0x85 ,
SCAN_F11
} ,
{
0x86 ,
SCAN_F12
} ,
//
// Convert ALT + Fn keys
//
{
0x68 ,
SCAN_F1
} ,
{
0x69 ,
SCAN_F2
} ,
{
0x6a ,
SCAN_F3
} ,
{
0x6b ,
SCAN_F4
} ,
{
0x6c ,
SCAN_F5
} ,
{
0x6d ,
SCAN_F6
} ,
{
0x6e ,
SCAN_F7
} ,
{
0x6f ,
SCAN_F8
} ,
{
0x70 ,
SCAN_F9
} ,
{
0x71 ,
SCAN_F10
} ,
{
TABLE_END ,
SCAN_NULL
} ,
} ;
/**
Convert unicode combined with scan code of key to the counterpart of EFIScancode of it .
@ param KeyChar Unicode of key .
@ param ScanCode Scan code of key .
@ return The value of EFI Scancode for the key .
@ retval SCAN_NULL No corresponding value in the EFI convert table is found for the key .
* */
UINT16
ConvertToEFIScanCode (
IN CHAR16 KeyChar ,
IN UINT16 ScanCode
)
{
UINT16 EfiScanCode ;
UINT16 Index ;
if ( KeyChar = = CHAR_ESC ) {
EfiScanCode = SCAN_ESC ;
} else if ( KeyChar = = 0x00 | | KeyChar = = 0xe0 ) {
//
// Movement & Function Keys
//
for ( Index = 0 ; ( Index < sizeof ( mConvertTable ) / sizeof ( CONVERT_TABLE_ENTRY ) ) & & ( mConvertTable [ Index ] . ScanCode ! = TABLE_END ) ; Index + = 1 ) {
if ( ScanCode = = mConvertTable [ Index ] . ScanCode ) {
return mConvertTable [ Index ] . EfiScanCode ;
}
}
//
// Reach Table end, return default value
//
return SCAN_NULL ;
} else {
return SCAN_NULL ;
}
return EfiScanCode ;
}
/**
Check whether there is Ps / 2 Keyboard device in system by 0xF4 Keyboard Command
If Keyboard receives 0xF4 , it will respond with ' ACK ' . If it doesn ' t respond , the device
should not be in system .
@ param BiosKeyboardPrivate Keyboard Private Data Struture
@ retval TRUE Keyboard in System .
@ retval FALSE Keyboard not in System .
* */
BOOLEAN
CheckKeyboardConnect (
IN BIOS_KEYBOARD_DEV * BiosKeyboardPrivate
)
{
EFI_STATUS Status ;
// Status = EFI_SUCCESS;
//
// enable keyboard itself and wait for its ack
// If can't receive ack, Keyboard should not be connected.
//
Status = KeyboardWrite (
BiosKeyboardPrivate ,
KBC_INPBUF_VIA60_KBEN
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
// DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));
REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
) ;
return FALSE ;
}
Status = KeyboardWaitForValue (
BiosKeyboardPrivate ,
KBC_CMDECHO_ACK ,
KEYBOARD_WAITFORVALUE_TIMEOUT
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
// DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n"));
REPORT_STATUS_CODE (
EFI_ERROR_CODE | EFI_ERROR_MINOR ,
EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
) ;
return FALSE ;
}
return TRUE ;
}
/**
Timer event handler : read a series of key stroke from 8042
and put them into memory key buffer .
It is registered as running under TPL_NOTIFY
@ param Event The timer event
@ param Context A BIOS_KEYBOARD_DEV pointer
* */
static int apple_need_zero = 0 ;
int MapBiosKey ( EFI_KEY_DATA KeyData , APPLE_KEY * pKey , UINT8 * pCurModifierMap )
{
if ( KeyData . Key . UnicodeChar = = 0 )
{
* pCurModifierMap = 0 ;
switch ( KeyData . Key . ScanCode ) {
case 0x01 : // up arrow
* pKey = 0x7052 ;
return 1 ;
case 0x02 : // down arrow
* pKey = 0x7051 ;
return 1 ;
case 0x03 : // left arrow
* pKey = 0x7050 ;
return 1 ;
case 0x04 : // right arrow
* pKey = 0x704F ;
return 1 ;
}
return 0 ;
}
if ( KeyData . Key . UnicodeChar > = ' a ' & & KeyData . Key . UnicodeChar < = ' z ' ) {
* pKey = 0x7004 + ( KeyData . Key . UnicodeChar - ' a ' ) ;
* pCurModifierMap = 0 ;
return 1 ;
}
if ( KeyData . Key . UnicodeChar > = ' A ' & & KeyData . Key . UnicodeChar < = ' Z ' ) {
* pKey = 0x7004 + ( KeyData . Key . UnicodeChar - ' A ' ) ;
* pCurModifierMap = 2 ;
return 1 ;
}
if ( KeyData . Key . UnicodeChar = = ' 0 ' ) { // Could have put that in the switch, but wanted to make very clear that the 0 wasn't forgotten and that this : "KeyData.Key.UnicodeChar >= '1'" (instead of '0') is not a mistake !!!
* pKey = 0x7027 ;
return 1 ;
}
if ( KeyData . Key . UnicodeChar > = ' 1 ' & & KeyData . Key . UnicodeChar < = ' 9 ' ) {
* pKey = 0x701E + ( KeyData . Key . UnicodeChar - ' 1 ' ) ;
return 1 ;
}
* pCurModifierMap = 0 ;
switch ( KeyData . Key . UnicodeChar ) {
case 0x01 : // up arrow
* pKey = 0x7052 ;
return 1 ;
case 0x02 : // down arrow
* pKey = 0x7051 ;
return 1 ;
case 0x03 : // left arrow
* pKey = 0x7050 ;
return 1 ;
case 0x04 : // right arrow
* pKey = 0x704F ;
return 1 ;
case 0x08 : // backspace
* pKey = 0x702A ;
return 1 ;
case 0x0D : // return
* pKey = 0x7028 ;
return 1 ;
case ' ' : // return
* pKey = 0x702C ;
return 1 ;
case ' ! ' : // return
* pKey = 0x701E ;
* pCurModifierMap = 2 ;
return 1 ;
case ' " ' : // return
* pKey = 0x7034 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' # ' : // return
* pKey = 0x7020 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' $ ' : // return
* pKey = 0x7021 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' % ' : // return
* pKey = 0x7022 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' & ' : // return
* pKey = 0x7024 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' \' ' : // return
* pKey = 0x7034 ;
return 1 ;
case ' ( ' : // return
* pKey = 0x7026 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' ) ' : // return
* pKey = 0x7027 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' * ' : // return
* pKey = 0x7025 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' + ' : // return
* pKey = 0x702E ;
* pCurModifierMap = 2 ;
return 1 ;
case ' , ' : // return
* pKey = 0x7036 ;
return 1 ;
case ' - ' : // return
* pKey = 0x702D ;
return 1 ;
case ' . ' : // return
* pKey = 0x7037 ;
return 1 ;
case ' / ' : // return
* pKey = 0x7038 ;
return 1 ;
case ' : ' : // return
* pKey = 0x7033 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' ; ' : // return
* pKey = 0x7033 ;
return 1 ;
case ' < ' : // return
* pKey = 0x7036 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' = ' : // return
* pKey = 0x702E ;
return 1 ;
case ' > ' : // return
* pKey = 0x7037 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' ? ' : // return
* pKey = 0x7038 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' @ ' : // return
* pKey = 0x701F ;
* pCurModifierMap = 2 ;
return 1 ;
case ' [ ' : // return
* pKey = 0x702F ;
return 1 ;
case ' \\ ' : // return
* pKey = 0x7031 ;
return 1 ;
case ' ] ' : // return
* pKey = 0x7030 ;
return 1 ;
case ' ^ ' : // return
* pKey = 0x7023 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' _ ' : // return
* pKey = 0x702D ;
* pCurModifierMap = 2 ;
return 1 ;
case ' ` ' : // return
* pKey = 0x7035 ;
return 1 ;
case ' { ' : // return
* pKey = 0x702F ;
* pCurModifierMap = 2 ;
return 1 ;
case ' | ' : // return
* pKey = 0x7031 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' } ' : // return
* pKey = 0x7030 ;
* pCurModifierMap = 2 ;
return 1 ;
case ' ~ ' : // return
* pKey = 0x7035 ;
* pCurModifierMap = 2 ;
return 1 ;
}
return 0 ;
}
VOID
EFIAPI
BiosKeyboardTimerHandler (
IN EFI_EVENT Event ,
IN VOID * Context
)
{
EFI_TPL OldTpl ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
IA32_REGISTER_SET Regs ;
UINT8 KbFlag1 ; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1
UINT8 KbFlag2 ; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2
EFI_KEY_DATA KeyData ;
LIST_ENTRY * Link ;
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * CurrentNotify ;
//for AppleDb
UINTN NumberOfKeys ;
APPLE_KEY Keys [ 8 ] ; // APPLE_KEY is UINT16
ZeroMem ( & Regs , sizeof ( EFI_IA32_REGISTER_SET ) ) ;
BiosKeyboardPrivate = Context ;
//
// Enter critical section
//
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
//
// if there is no key present, just return
//
if ( BiosKeyboardPrivate - > ExtendedKeyboard ) {
Regs . H . AH = 0x11 ;
} else {
Regs . H . AH = 0x01 ;
}
/* BiosKeyboardPrivate->LegacyBios->Int86 (
BiosKeyboardPrivate - > LegacyBios ,
0x16 ,
& Regs
) ; */
LegacyBiosInt86 ( BiosKeyboardPrivate , 0x16 , & Regs ) ;
if ( Regs . E . EFLAGS . Bits . ZF ! = 0 ) {
gBS - > RestoreTPL ( OldTpl ) ;
if ( apple_need_zero ) {
//DBG("BiosKeyboardPrivate->KeyMapDb->SetKeyStrokeBufferKeys 0\n");
BiosKeyboardPrivate - > KeyMapDb - > SetKeyStrokeBufferKeys (
BiosKeyboardPrivate - > KeyMapDb ,
BiosKeyboardPrivate - > KeyMapDbIndex ,
( APPLE_MODIFIER_MAP ) 0 ,
0 ,
& Keys [ 0 ]
) ;
apple_need_zero = 0 ;
}
return ;
}
//
// Read the key
//
if ( BiosKeyboardPrivate - > ExtendedKeyboard ) {
Regs . H . AH = 0x10 ;
} else {
Regs . H . AH = 0x00 ;
}
/* BiosKeyboardPrivate->LegacyBios->Int86 (
BiosKeyboardPrivate - > LegacyBios ,
0x16 ,
& Regs
) ; */
LegacyBiosInt86 ( BiosKeyboardPrivate , 0x16 , & Regs ) ;
KeyData . Key . ScanCode = ( UINT16 ) Regs . H . AH ;
KeyData . Key . UnicodeChar = ( UINT16 ) Regs . H . AL ;
/* DEBUG ((
EFI_D_INFO ,
" [KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x \n " ,
KeyData . Key . ScanCode ,
KeyData . Key . UnicodeChar
) ) ; */
KeyData . KeyState . KeyShiftState = EFI_SHIFT_STATE_VALID ;
KeyData . KeyState . KeyToggleState = EFI_TOGGLE_STATE_VALID ;
//
// Legacy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then
// Int 16 depend KB buffer and some key bits in BDA to translate the scancode to ASCII code, and return both the scancode and ASCII
// code to Int 16 caller. This translation process works well if the Int 9 could response user input in time. But in Tiano enviorment, the Int 9
// will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when
// KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit
// in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode
// to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers
// performance, like USB.
//
// 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In
// this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA
// after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the
// CTRL and ALT.
//
// 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost
// SHIFT again, the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA,
// which will let persist to press SHIFT has same effection as only press one time.
//
//0040h:0017h - KEYBOARD - STATUS FLAGS 1
// 7 INSert active
// 6 Caps Lock active
// 5 Num Lock active
// 4 Scroll Lock active
// 3 either Alt pressed
// 2 either Ctrl pressed
// 1 Left Shift pressed
// 0 Right Shift pressed
//
// Clear the CTRL and ALT BDA flag
//
KbFlag1 = * ( ( UINT8 * ) ( UINTN ) 0x417 ) ; // read the STATUS FLAGS 1
KbFlag2 = * ( ( UINT8 * ) ( UINTN ) 0x418 ) ; // read STATUS FLAGS 2
/*
DEBUG_CODE (
{
if ( ( KbFlag1 & KB_CAPS_LOCK_BIT ) = = KB_CAPS_LOCK_BIT ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Caps Lock Key is pressed. \n " ) ) ;
}
if ( ( KbFlag1 & KB_NUM_LOCK_BIT ) = = KB_NUM_LOCK_BIT ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Num Lock Key is pressed. \n " ) ) ;
}
if ( ( KbFlag1 & KB_SCROLL_LOCK_BIT ) = = KB_SCROLL_LOCK_BIT ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Scroll Lock Key is pressed. \n " ) ) ;
}
if ( ( KbFlag1 & KB_ALT_PRESSED ) = = KB_ALT_PRESSED ) {
if ( ( KbFlag2 & KB_LEFT_ALT_PRESSED ) = = KB_LEFT_ALT_PRESSED ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Left Alt Key is pressed. \n " ) ) ;
} else {
DEBUG ( ( EFI_D_INFO , " [KBD]Right Alt Key is pressed. \n " ) ) ;
}
}
if ( ( KbFlag1 & KB_CTRL_PRESSED ) = = KB_CTRL_PRESSED ) {
if ( ( KbFlag2 & KB_LEFT_CTRL_PRESSED ) = = KB_LEFT_CTRL_PRESSED ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Left Ctrl Key is pressed. \n " ) ) ;
} else {
DEBUG ( ( EFI_D_INFO , " [KBD]Right Ctrl Key is pressed. \n " ) ) ;
}
}
if ( ( KbFlag1 & KB_LEFT_SHIFT_PRESSED ) = = KB_LEFT_SHIFT_PRESSED ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Left Shift Key is pressed. \n " ) ) ;
}
if ( ( KbFlag1 & KB_RIGHT_SHIFT_PRESSED ) = = KB_RIGHT_SHIFT_PRESSED ) {
DEBUG ( ( EFI_D_INFO , " [KBD]Right Shift Key is pressed. \n " ) ) ;
}
}
) ;
*/
//
// Record toggle state
//
if ( ( KbFlag1 & KB_CAPS_LOCK_BIT ) = = KB_CAPS_LOCK_BIT ) {
KeyData . KeyState . KeyToggleState | = EFI_CAPS_LOCK_ACTIVE ;
}
if ( ( KbFlag1 & KB_NUM_LOCK_BIT ) = = KB_NUM_LOCK_BIT ) {
KeyData . KeyState . KeyToggleState | = EFI_NUM_LOCK_ACTIVE ;
}
if ( ( KbFlag1 & KB_SCROLL_LOCK_BIT ) = = KB_SCROLL_LOCK_BIT ) {
KeyData . KeyState . KeyToggleState | = EFI_SCROLL_LOCK_ACTIVE ;
}
//
// Record shift state
// BUGBUG: Need add Menu key and Left/Right Logo key state in the future
//
if ( ( KbFlag1 & KB_ALT_PRESSED ) = = KB_ALT_PRESSED ) {
KeyData . KeyState . KeyShiftState | = ( ( KbFlag2 & KB_LEFT_ALT_PRESSED ) = = KB_LEFT_ALT_PRESSED ) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED ;
}
if ( ( KbFlag1 & KB_CTRL_PRESSED ) = = KB_CTRL_PRESSED ) {
KeyData . KeyState . KeyShiftState | = ( ( KbFlag2 & KB_LEFT_CTRL_PRESSED ) = = KB_LEFT_CTRL_PRESSED ) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED ;
}
if ( ( KbFlag1 & KB_LEFT_SHIFT_PRESSED ) = = KB_LEFT_SHIFT_PRESSED ) {
KeyData . KeyState . KeyShiftState | = EFI_LEFT_SHIFT_PRESSED ;
}
if ( ( KbFlag1 & KB_RIGHT_SHIFT_PRESSED ) = = KB_RIGHT_SHIFT_PRESSED ) {
KeyData . KeyState . KeyShiftState | = EFI_RIGHT_SHIFT_PRESSED ;
}
//
// Clear left alt and left ctrl BDA flag
//
KbFlag2 & = ~ ( KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED ) ;
* ( ( UINT8 * ) ( UINTN ) 0x418 ) = KbFlag2 ;
KbFlag1 & = ~ 0x0C ;
* ( ( UINT8 * ) ( UINTN ) 0x417 ) = KbFlag1 ;
//
// Output EFI input key and shift/toggle state
//
if ( KeyData . Key . UnicodeChar = = CHAR_NULL | | KeyData . Key . UnicodeChar = = CHAR_SCANCODE | | KeyData . Key . UnicodeChar = = CHAR_ESC ) {
KeyData . Key . ScanCode = ConvertToEFIScanCode ( KeyData . Key . UnicodeChar , KeyData . Key . ScanCode ) ;
KeyData . Key . UnicodeChar = CHAR_NULL ;
} else {
KeyData . Key . ScanCode = SCAN_NULL ;
}
//
// CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.
//
/* if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
if ( KeyData . Key . UnicodeChar > = 1 & & KeyData . Key . UnicodeChar < = 26 ) {
if ( ( ( KeyData . KeyState . KeyShiftState & ( EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED ) ) ! = 0 ) = =
( ( KeyData . KeyState . KeyToggleState & EFI_CAPS_LOCK_ACTIVE ) ! = 0 )
) {
KeyData . Key . UnicodeChar = ( UINT16 ) ( KeyData . Key . UnicodeChar + L ' a ' - 1 ) ;
} else {
KeyData . Key . UnicodeChar = ( UINT16 ) ( KeyData . Key . UnicodeChar + L ' A ' - 1 ) ;
}
}
}
DEBUG ( (
EFI_D_INFO ,
" [KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x \n " ,
KeyData . Key . ScanCode ,
KeyData . Key . UnicodeChar
) ) ;
*/
//
// Need not return associated shift state if a class of printable characters that
// are normally adjusted by shift modifiers.
// e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.
//
if ( ( KeyData . Key . UnicodeChar > = L ' A ' & & KeyData . Key . UnicodeChar < = L ' Z ' ) | |
( KeyData . Key . UnicodeChar > = L ' a ' & & KeyData . Key . UnicodeChar < = L ' z ' )
) {
// DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));
KeyData . KeyState . KeyShiftState & = ~ ( EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED ) ;
}
//
// Invoke notification functions if exist
//
for ( Link = BiosKeyboardPrivate - > NotifyList . ForwardLink ; Link ! = & BiosKeyboardPrivate - > NotifyList ; Link = Link - > ForwardLink ) {
CurrentNotify = CR (
Link ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY ,
NotifyEntry ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) ;
if ( IsKeyRegistered ( & CurrentNotify - > KeyData , & KeyData ) ) {
CurrentNotify - > KeyNotificationFn ( & KeyData ) ;
}
}
Enqueue ( & BiosKeyboardPrivate - > Queue , & KeyData ) ;
//
// Leave critical section and return
//
gBS - > RestoreTPL ( OldTpl ) ;
/* a method from UsbKb
// Following code checks current keyboard input report against old key code buffer.
// According to USB HID Firmware Specification, the report consists of 8 bytes.
// Byte 0 is map of Modifier keys.
// Byte 1 is reserved.
// Bytes 2 to 7 are keycodes. -> KeyData.Key.ScanCode
//
CurKeyCodeBuffer = ( UINT8 * ) Data ;
CurModifierMap = CurKeyCodeBuffer [ 0 ] ; - > KeyData . KeyState . KeyShiftState
NumberOfKeys = 0 ;
//
// Pass the data to the Apple protocol
//
for ( Index = 2 ; Index < 8 ; Index + + ) {
if ( USBKBD_VALID_KEYCODE ( CurKeyCodeBuffer [ Index ] ) ) {
Keys [ NumberOfKeys ] = APPLE_HID_USB_KB_KP_USAGE ( CurKeyCodeBuffer [ Index ] ) ;
+ + NumberOfKeys ;
}
}
*/
// NumberOfKeys = 3;
// Keys[0] = (APPLE_KEY)KeyData.KeyState.KeyShiftState;
// Keys[1] = (APPLE_KEY)KeyData.KeyState.KeyToggleState; //or 0?
// Keys[2] = (APPLE_KEY)KeyData.Key.ScanCode;
// Parse the modifier key, which is the first byte of keyboard input report.
//
DBG ( " 2 Got bios key ScanCode=%x, Uchar=%x, ShiftState=%x, ToogleState=%x \n " , KeyData . Key . ScanCode , KeyData . Key . UnicodeChar , KeyData . KeyState . KeyShiftState , KeyData . KeyState . KeyToggleState ) ;
UINT8 CurModifierMap = 0 ;
// DBG("Key %d\n", KeyData.Key.ScanCode);
// if (BiosKeyboardPrivate->KeyMapDb == NULL) {
// EFI_STATUS Status = BiosKbLocateAppleKeyMapDb (BiosKeyboardPrivate);
//#ifdef TRACE_KEYS
// DBG("BiosKeyboardTimerHandler: BiosKbLocateAppleKeyMapDb status=%x\n", Status);
//#endif
// }
if ( BiosKeyboardPrivate - > KeyMapDb ! = NULL ) {
// DBG("BiosKeyboardTimerHandler: SetKeyStrokeBufferKeys\n");
if ( MapBiosKey ( KeyData , & Keys [ 0 ] , & CurModifierMap ) )
{
NumberOfKeys = 1 ;
DBG ( " 3BiosKeyboardPrivate->KeyMapDb(0x%x)->SetKeyStrokeBufferKeys CurModifierMap=%x, NumberOfKeys=%d " , BiosKeyboardPrivate - > KeyMapDb , CurModifierMap , NumberOfKeys ) ;
UINTN zud ; for ( zud = 0 ; zud < NumberOfKeys ; zud + + ) {
DBG ( " Keys[%d]=%d(%d %d) 0x%x " , zud , Keys [ zud ] , Keys [ zud ] > > 8 , Keys [ zud ] & 0xFF , Keys [ zud ] ) ;
}
DBG ( " \n " ) ;
BiosKeyboardPrivate - > KeyMapDb - > SetKeyStrokeBufferKeys (
BiosKeyboardPrivate - > KeyMapDb ,
BiosKeyboardPrivate - > KeyMapDbIndex ,
( APPLE_MODIFIER_MAP ) CurModifierMap ,
NumberOfKeys ,
& Keys [ 0 ]
) ;
apple_need_zero = 1 ;
}
} else {
// DBG("BiosKeyboardPrivate->KeyMapDb == NULL\n");
}
return ;
}
/**
Free keyboard notify list .
@ param ListHead The list head
@ retval EFI_SUCCESS Free the notify list successfully
@ retval EFI_INVALID_PARAMETER ListHead is invalid .
* */
EFI_STATUS
BiosKeyboardFreeNotifyList (
IN OUT LIST_ENTRY * ListHead
)
{
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * NotifyNode ;
if ( ListHead = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
while ( ! IsListEmpty ( ListHead ) ) {
NotifyNode = CR (
ListHead - > ForwardLink ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY ,
NotifyEntry ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) ;
RemoveEntryList ( ListHead - > ForwardLink ) ;
2020-04-23 11:08:10 +02:00
gBS - > FreePool ( NotifyNode ) ;
2019-09-03 11:58:42 +02:00
}
return EFI_SUCCESS ;
}
/**
Check if key is registered .
@ param RegisteredData A pointer to a buffer that is filled in with the keystroke
state data for the key that was registered .
@ param InputData A pointer to a buffer that is filled in with the keystroke
state data for the key that was pressed .
@ retval TRUE Key be pressed matches a registered key .
@ retval FLASE Match failed .
* */
BOOLEAN
IsKeyRegistered (
IN EFI_KEY_DATA * RegisteredData ,
IN EFI_KEY_DATA * InputData
)
{
// ASSERT (RegisteredData != NULL && InputData != NULL);
if ( ! RegisteredData | | ! InputData ) {
return FALSE ;
}
if ( ( RegisteredData - > Key . ScanCode ! = InputData - > Key . ScanCode ) | |
( RegisteredData - > Key . UnicodeChar ! = InputData - > Key . UnicodeChar ) ) {
return FALSE ;
}
//
// Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
//
if ( RegisteredData - > KeyState . KeyShiftState ! = 0 & &
RegisteredData - > KeyState . KeyShiftState ! = InputData - > KeyState . KeyShiftState ) {
return FALSE ;
}
if ( RegisteredData - > KeyState . KeyToggleState ! = 0 & &
RegisteredData - > KeyState . KeyToggleState ! = InputData - > KeyState . KeyToggleState ) {
return FALSE ;
}
return TRUE ;
}
/**
Waiting on the keyboard event , if there ' s any key pressed by the user , signal the event
@ param Event The event that be signalled when any key has been stroked .
@ param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL .
* */
VOID
EFIAPI
BiosKeyboardWaitForKeyEx (
IN EFI_EVENT Event ,
IN VOID * Context
)
{
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( Context ) ;
BiosKeyboardWaitForKey ( Event , & BiosKeyboardPrivate - > SimpleTextIn ) ;
}
/**
Reset the input device and optionaly run diagnostics
@ param This Protocol instance pointer .
@ param ExtendedVerification Driver may perform diagnostics on reset .
@ retval EFI_SUCCESS The device was reset .
@ retval EFI_DEVICE_ERROR The device is not functioning properly and could
not be reset .
* */
EFI_STATUS
EFIAPI
BiosKeyboardResetEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This ,
IN BOOLEAN ExtendedVerification
)
{
DBG ( " BiosKeyboardResetEx -> Enter \n " ) ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_STATUS Status ;
EFI_TPL OldTpl ;
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
Status = BiosKeyboardPrivate - > SimpleTextIn . Reset (
& BiosKeyboardPrivate - > SimpleTextIn ,
ExtendedVerification
) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
DBG ( " BiosKeyboardResetEx -> Leave EFI_DEVICE_ERROR \n " ) ;
return EFI_DEVICE_ERROR ;
}
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
gBS - > RestoreTPL ( OldTpl ) ;
DBG ( " BiosKeyboardResetEx -> Leave sucess \n " ) ;
return EFI_SUCCESS ;
}
/**
Reads the next keystroke from the input device . The WaitForKey Event can
be used to test for existance of a keystroke via WaitForEvent ( ) call .
@ param This Protocol instance pointer .
@ param KeyData A pointer to a buffer that is filled in with the keystroke
state data for the key that was pressed .
@ retval EFI_SUCCESS The keystroke information was returned .
@ retval EFI_NOT_READY There was no keystroke data availiable .
@ retval EFI_DEVICE_ERROR The keystroke information was not returned due to
hardware errors .
@ retval EFI_INVALID_PARAMETER KeyData is NULL .
* */
EFI_STATUS
EFIAPI
BiosKeyboardReadKeyStrokeEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This ,
OUT EFI_KEY_DATA * KeyData
)
{
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
if ( KeyData = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
return KeyboardReadKeyStrokeWorker ( BiosKeyboardPrivate , KeyData ) ;
}
/**
Set certain state for the input device .
@ param This Protocol instance pointer .
@ param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
state for the input device .
@ retval EFI_SUCCESS The device state was set successfully .
@ retval EFI_DEVICE_ERROR The device is not functioning correctly and could
not have the setting adjusted .
@ retval EFI_UNSUPPORTED The device does not have the ability to set its state .
@ retval EFI_INVALID_PARAMETER KeyToggleState is NULL .
* */
EFI_STATUS
EFIAPI
BiosKeyboardSetState (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This ,
IN EFI_KEY_TOGGLE_STATE * KeyToggleState
)
{
EFI_STATUS Status ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_TPL OldTpl ;
// EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
UINT8 Command ;
if ( KeyToggleState = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
//
// Thunk keyboard driver doesn't support partial keystroke.
//
if ( ( * KeyToggleState & EFI_TOGGLE_STATE_VALID ) ! = EFI_TOGGLE_STATE_VALID | |
( * KeyToggleState & EFI_KEY_STATE_EXPOSED ) = = EFI_KEY_STATE_EXPOSED
) {
return EFI_UNSUPPORTED ;
}
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
//
// See if the Legacy BIOS Protocol is available
//
/* Status = gBS->LocateProtocol (
& gEfiLegacyBiosProtocolGuid ,
NULL ,
( VOID * * ) & LegacyBios
) ;
2020-04-23 11:08:10 +02:00
ASSERT_EFI_ERROR ( Status ) ; */
2019-09-03 11:58:42 +02:00
//
// Enter critical section
//
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
Command = 0 ;
if ( ( * KeyToggleState & EFI_CAPS_LOCK_ACTIVE ) = = EFI_CAPS_LOCK_ACTIVE ) {
Command | = 4 ;
}
if ( ( * KeyToggleState & EFI_NUM_LOCK_ACTIVE ) = = EFI_NUM_LOCK_ACTIVE ) {
Command | = 2 ;
}
if ( ( * KeyToggleState & EFI_SCROLL_LOCK_ACTIVE ) = = EFI_SCROLL_LOCK_ACTIVE ) {
Command | = 1 ;
}
Status = KeyboardWrite ( BiosKeyboardPrivate , 0xed ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Done ;
}
Status = KeyboardWaitForValue ( BiosKeyboardPrivate , 0xfa , KEYBOARD_WAITFORVALUE_TIMEOUT ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Done ;
}
Status = KeyboardWrite ( BiosKeyboardPrivate , Command ) ;
2020-04-23 11:08:10 +02:00
if ( EFI_ERROR ( Status ) ) {
2019-09-03 11:58:42 +02:00
Status = EFI_DEVICE_ERROR ;
goto Done ;
}
//
// Call Legacy BIOS Protocol to set whatever is necessary
//
// LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
Status = EFI_SUCCESS ;
Done :
//
// Leave critical section and return
//
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
/**
Register a notification function for a particular keystroke for the input device .
@ param This Protocol instance pointer .
@ param KeyData A pointer to a buffer that is filled in with the keystroke
information data for the key that was pressed .
@ param KeyNotificationFunction Points to the function to be called when the key
sequence is typed specified by KeyData .
@ param NotifyHandle Points to the unique handle assigned to the registered notification .
@ retval EFI_SUCCESS The notification function was registered successfully .
@ retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures .
@ retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL .
* */
EFI_STATUS
EFIAPI
BiosKeyboardRegisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This ,
IN EFI_KEY_DATA * KeyData ,
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction ,
OUT EFI_HANDLE * NotifyHandle
)
{
EFI_STATUS Status ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_TPL OldTpl ;
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * NewNotify ;
LIST_ENTRY * Link ;
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * CurrentNotify ;
if ( KeyData = = NULL | | NotifyHandle = = NULL | | KeyNotificationFunction = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
//
// Enter critical section
//
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
//
// Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
//
for ( Link = BiosKeyboardPrivate - > NotifyList . ForwardLink ; Link ! = & BiosKeyboardPrivate - > NotifyList ; Link = Link - > ForwardLink ) {
CurrentNotify = CR (
Link ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY ,
NotifyEntry ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) ;
if ( IsKeyRegistered ( & CurrentNotify - > KeyData , KeyData ) ) {
//DBG("BiosKbd CurrentNotify ok key ScanCode=%x, Uchar=%x, ShiftState=%x, ToogleState=%x\n", CurrentNotify->KeyData.Key.ScanCode, CurrentNotify->KeyData.Key.UnicodeChar, CurrentNotify->KeyData.KeyState.KeyShiftState, CurrentNotify->KeyData.KeyState.KeyToggleState);
if ( CurrentNotify - > KeyNotificationFn = = KeyNotificationFunction ) {
* NotifyHandle = CurrentNotify - > NotifyHandle ;
Status = EFI_SUCCESS ;
goto Exit ;
}
} else {
//DBG("BiosKbd CurrentNotify !ok key ScanCode=%x, Uchar=%x, ShiftState=%x, ToogleState=%x\n", CurrentNotify->KeyData.Key.ScanCode, CurrentNotify->KeyData.Key.UnicodeChar, CurrentNotify->KeyData.KeyState.KeyShiftState, CurrentNotify->KeyData.KeyState.KeyToggleState);
}
}
//
// Allocate resource to save the notification function
//
NewNotify = ( BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * ) AllocateZeroPool ( sizeof ( BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY ) ) ;
if ( NewNotify = = NULL ) {
Status = EFI_OUT_OF_RESOURCES ;
goto Exit ;
}
NewNotify - > Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE ;
NewNotify - > KeyNotificationFn = KeyNotificationFunction ;
NewNotify - > NotifyHandle = ( EFI_HANDLE ) NewNotify ;
CopyMem ( & NewNotify - > KeyData , KeyData , sizeof ( EFI_KEY_DATA ) ) ;
InsertTailList ( & BiosKeyboardPrivate - > NotifyList , & NewNotify - > NotifyEntry ) ;
* NotifyHandle = NewNotify - > NotifyHandle ;
Status = EFI_SUCCESS ;
Exit :
//
// Leave critical section and return
//
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
/**
Remove a registered notification function from a particular keystroke .
@ param This Protocol instance pointer .
@ param NotificationHandle The handle of the notification function being unregistered .
@ retval EFI_SUCCESS The notification function was unregistered successfully .
@ retval EFI_INVALID_PARAMETER The NotificationHandle is invalid .
* */
EFI_STATUS
EFIAPI
BiosKeyboardUnregisterKeyNotify (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL * This ,
IN EFI_HANDLE NotificationHandle
)
{
EFI_STATUS Status ;
BIOS_KEYBOARD_DEV * BiosKeyboardPrivate ;
EFI_TPL OldTpl ;
LIST_ENTRY * Link ;
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * CurrentNotify ;
//
// Check incoming notification handle
//
if ( NotificationHandle = = NULL ) {
return EFI_INVALID_PARAMETER ;
}
if ( ( ( BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY * ) NotificationHandle ) - > Signature ! = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE ) {
return EFI_INVALID_PARAMETER ;
}
BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS ( This ) ;
//
// Enter critical section
//
OldTpl = gBS - > RaiseTPL ( TPL_NOTIFY ) ;
for ( Link = BiosKeyboardPrivate - > NotifyList . ForwardLink ; Link ! = & BiosKeyboardPrivate - > NotifyList ; Link = Link - > ForwardLink ) {
CurrentNotify = CR (
Link ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY ,
NotifyEntry ,
BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) ;
if ( CurrentNotify - > NotifyHandle = = NotificationHandle ) {
//
// Remove the notification function from NotifyList and free resources
//
RemoveEntryList ( & CurrentNotify - > NotifyEntry ) ;
Status = EFI_SUCCESS ;
goto Exit ;
}
}
//
// Can not find the specified Notification Handle
//
Status = EFI_INVALID_PARAMETER ;
Exit :
//
// Leave critical section and return
//
gBS - > RestoreTPL ( OldTpl ) ;
return Status ;
}
/**
The user Entry Point for module BiosKeyboard . The user code starts with this function .
@ param [ in ] ImageHandle The firmware allocated handle for the EFI image .
@ param [ in ] SystemTable A pointer to the EFI System Table .
@ retval EFI_SUCCESS The entry point is executed successfully .
@ retval other Some error occurs when executing this entry point .
* */
EFI_STATUS
EFIAPI
InitializeBiosKeyboard (
IN EFI_HANDLE ImageHandle ,
IN EFI_SYSTEM_TABLE * SystemTable
)
{
EFI_STATUS Status ;
//
// Install driver model protocol(s).
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle ,
SystemTable ,
& gBiosKeyboardDriverBinding ,
ImageHandle ,
& gBiosKeyboardComponentName ,
& gBiosKeyboardComponentName2
) ;
2020-04-23 11:08:10 +02:00
// ASSERT_EFI_ERROR(Status);
2019-09-03 11:58:42 +02:00
return Status ;
}