| /** @file | |
| PS/2 keyboard driver header file | |
| Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #ifndef _PS2KEYBOARD_H_ | |
| #define _PS2KEYBOARD_H_ | |
| #include <Uefi.h> | |
| #include <Protocol/SuperIo.h> | |
| #include <Protocol/SimpleTextIn.h> | |
| #include <Protocol/SimpleTextInEx.h> | |
| #include <Protocol/DevicePath.h> | |
| #include <Protocol/Ps2Policy.h> | |
| #include <Library/IoLib.h> | |
| #include <Library/DevicePathLib.h> | |
| #include <Library/UefiDriverEntryPoint.h> | |
| #include <Library/UefiLib.h> | |
| #include <Library/UefiBootServicesTableLib.h> | |
| #include <Library/ReportStatusCodeLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/UefiRuntimeServicesTableLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/TimerLib.h> | |
| #include <Library/PcdLib.h> | |
| // | |
| // Global Variables | |
| // | |
| extern EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver; | |
| extern EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName; | |
| extern EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2; | |
| // | |
| // Driver Private Data | |
| // | |
| #define KEYBOARD_CONSOLE_IN_DEV_SIGNATURE SIGNATURE_32 ('k', 'k', 'e', 'y') | |
| #define KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 'n') | |
| typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY { | |
| UINTN Signature; | |
| EFI_KEY_DATA KeyData; | |
| EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; | |
| LIST_ENTRY NotifyEntry; | |
| } KEYBOARD_CONSOLE_IN_EX_NOTIFY; | |
| #define KEYBOARD_SCAN_CODE_MAX_COUNT 32 | |
| typedef struct { | |
| UINT8 Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT]; | |
| UINTN Head; | |
| UINTN Tail; | |
| } SCAN_CODE_QUEUE; | |
| #define KEYBOARD_EFI_KEY_MAX_COUNT 256 | |
| typedef struct { | |
| EFI_KEY_DATA Buffer[KEYBOARD_EFI_KEY_MAX_COUNT]; | |
| UINTN Head; | |
| UINTN Tail; | |
| } EFI_KEY_QUEUE; | |
| typedef struct { | |
| UINTN Signature; | |
| EFI_HANDLE Handle; | |
| EFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; | |
| EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ConInEx; | |
| EFI_EVENT TimerEvent; | |
| UINT32 DataRegisterAddress; | |
| UINT32 StatusRegisterAddress; | |
| UINT32 CommandRegisterAddress; | |
| BOOLEAN LeftCtrl; | |
| BOOLEAN RightCtrl; | |
| BOOLEAN LeftAlt; | |
| BOOLEAN RightAlt; | |
| BOOLEAN LeftShift; | |
| BOOLEAN RightShift; | |
| BOOLEAN LeftLogo; | |
| BOOLEAN RightLogo; | |
| BOOLEAN Menu; | |
| BOOLEAN SysReq; | |
| BOOLEAN CapsLock; | |
| BOOLEAN NumLock; | |
| BOOLEAN ScrollLock; | |
| BOOLEAN IsSupportPartialKey; | |
| // | |
| // Queue storing key scancodes | |
| // | |
| SCAN_CODE_QUEUE ScancodeQueue; | |
| EFI_KEY_QUEUE EfiKeyQueue; | |
| EFI_KEY_QUEUE EfiKeyQueueForNotify; | |
| // | |
| // Error state | |
| // | |
| BOOLEAN KeyboardErr; | |
| EFI_UNICODE_STRING_TABLE *ControllerNameTable; | |
| EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
| // | |
| // Notification Function List | |
| // | |
| LIST_ENTRY NotifyList; | |
| EFI_EVENT KeyNotifyProcessEvent; | |
| } KEYBOARD_CONSOLE_IN_DEV; | |
| #define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE) | |
| #define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \ | |
| CR (a, \ | |
| KEYBOARD_CONSOLE_IN_DEV, \ | |
| ConInEx, \ | |
| KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \ | |
| ) | |
| #define TABLE_END 0x0 | |
| // | |
| // Driver entry point | |
| // | |
| /** | |
| The user Entry Point for module Ps2Keyboard. 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 | |
| InstallPs2KeyboardDriver ( | |
| IN EFI_HANDLE ImageHandle, | |
| IN EFI_SYSTEM_TABLE *SystemTable | |
| ); | |
| #define KEYBOARD_8042_DATA_REGISTER 0x60 | |
| #define KEYBOARD_8042_STATUS_REGISTER 0x64 | |
| #define KEYBOARD_8042_COMMAND_REGISTER 0x64 | |
| #define KEYBOARD_KBEN 0xF4 | |
| #define KEYBOARD_CMDECHO_ACK 0xFA | |
| #define KEYBOARD_MAX_TRY 256 // 256 | |
| #define KEYBOARD_TIMEOUT 65536 // 0.07s | |
| #define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s | |
| #define KEYBOARD_BAT_TIMEOUT 4000000 // 4s | |
| #define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s | |
| #define SCANCODE_EXTENDED0 0xE0 | |
| #define SCANCODE_EXTENDED1 0xE1 | |
| #define SCANCODE_CTRL_MAKE 0x1D | |
| #define SCANCODE_CTRL_BREAK 0x9D | |
| #define SCANCODE_ALT_MAKE 0x38 | |
| #define SCANCODE_ALT_BREAK 0xB8 | |
| #define SCANCODE_LEFT_SHIFT_MAKE 0x2A | |
| #define SCANCODE_LEFT_SHIFT_BREAK 0xAA | |
| #define SCANCODE_RIGHT_SHIFT_MAKE 0x36 | |
| #define SCANCODE_RIGHT_SHIFT_BREAK 0xB6 | |
| #define SCANCODE_CAPS_LOCK_MAKE 0x3A | |
| #define SCANCODE_NUM_LOCK_MAKE 0x45 | |
| #define SCANCODE_SCROLL_LOCK_MAKE 0x46 | |
| #define SCANCODE_DELETE_MAKE 0x53 | |
| #define SCANCODE_LEFT_LOGO_MAKE 0x5B// GUI key defined in Keyboard scan code | |
| #define SCANCODE_LEFT_LOGO_BREAK 0xDB | |
| #define SCANCODE_RIGHT_LOGO_MAKE 0x5C | |
| #define SCANCODE_RIGHT_LOGO_BREAK 0xDC | |
| #define SCANCODE_MENU_MAKE 0x5D// APPS key defined in Keyboard scan code | |
| #define SCANCODE_MENU_BREAK 0xDD | |
| #define SCANCODE_SYS_REQ_MAKE 0x37 | |
| #define SCANCODE_SYS_REQ_BREAK 0xB7 | |
| #define SCANCODE_SYS_REQ_MAKE_WITH_ALT 0x54 | |
| #define SCANCODE_SYS_REQ_BREAK_WITH_ALT 0xD4 | |
| #define SCANCODE_MAX_MAKE 0x60 | |
| #define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA BIT0 ///< 0 - Output register has no data; 1 - Output register has data | |
| #define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA BIT1 ///< 0 - Input register has no data; 1 - Input register has data | |
| #define KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG BIT2 ///< Set to 0 after power on reset | |
| #define KEYBOARD_STATUS_REGISTER_INPUT_DATA_TYPE BIT3 ///< 0 - Data in input register is data; 1 - Data in input register is command | |
| #define KEYBOARD_STATUS_REGISTER_ENABLE_FLAG BIT4 ///< 0 - Keyboard is disable; 1 - Keyboard is enable | |
| #define KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT BIT5 ///< 0 - Transmit is complete without timeout; 1 - Transmit is timeout without complete | |
| #define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT BIT6 ///< 0 - Receive is complete without timeout; 1 - Receive is timeout without complete | |
| #define KEYBOARD_STATUS_REGISTER_PARITY BIT7 ///< 0 - Odd parity; 1 - Even parity | |
| #define KEYBOARD_8042_COMMAND_READ 0x20 | |
| #define KEYBOARD_8042_COMMAND_WRITE 0x60 | |
| #define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE 0xA7 | |
| #define KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE 0xA8 | |
| #define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST 0xAA | |
| #define KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST 0xAB | |
| #define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE 0xAD | |
| #define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA 0xF4 | |
| #define KEYBOARD_8048_COMMAND_RESET 0xFF | |
| #define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET 0xF0 | |
| #define KEYBOARD_8048_RETURN_8042_BAT_SUCCESS 0xAA | |
| #define KEYBOARD_8048_RETURN_8042_BAT_ERROR 0xFC | |
| #define KEYBOARD_8048_RETURN_8042_ACK 0xFA | |
| // | |
| // Keyboard Controller Status | |
| // | |
| #define KBC_PARE 0x80 // Parity Error | |
| #define KBC_TIM 0x40 // General Time Out | |
| // | |
| // Other functions that are used among .c files | |
| // | |
| /** | |
| Show keyboard status lights according to | |
| indicators in ConsoleIn. | |
| @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV | |
| @return status | |
| **/ | |
| EFI_STATUS | |
| UpdateStatusLights ( | |
| IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn | |
| ); | |
| /** | |
| write key to keyboard. | |
| @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV | |
| @param Data value wanted to be written | |
| @retval EFI_TIMEOUT - GC_TODO: Add description for return value | |
| @retval EFI_SUCCESS - GC_TODO: Add description for return value | |
| **/ | |
| EFI_STATUS | |
| KeyboardRead ( | |
| IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, | |
| OUT UINT8 *Data | |
| ); | |
| /** | |
| Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. | |
| The function is always called in TPL_NOTIFY. | |
| @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer | |
| **/ | |
| VOID | |
| KeyGetchar ( | |
| IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn | |
| ); | |
| /** | |
| Process key notify. | |
| @param Event Indicates the event that invoke this function. | |
| @param Context Indicates the calling context. | |
| **/ | |
| VOID | |
| EFIAPI | |
| KeyNotifyProcessHandler ( | |
| IN EFI_EVENT Event, | |
| IN VOID *Context | |
| ); | |
| /** | |
| Perform 8042 controller and keyboard Initialization. | |
| If ExtendedVerification is TRUE, do additional test for | |
| the keyboard interface | |
| @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer | |
| @param ExtendedVerification - indicates a thorough initialization | |
| @retval EFI_DEVICE_ERROR Fail to init keyboard | |
| @retval EFI_SUCCESS Success to init keyboard | |
| **/ | |
| EFI_STATUS | |
| InitKeyboard ( | |
| IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, | |
| IN BOOLEAN ExtendedVerification | |
| ); | |
| /** | |
| Timer event handler: read a series of scancodes from 8042 | |
| and put them into memory scancode buffer. | |
| it read as much scancodes to either fill | |
| the memory buffer or empty the keyboard buffer. | |
| It is registered as running under TPL_NOTIFY | |
| @param Event - The timer event | |
| @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer | |
| **/ | |
| VOID | |
| EFIAPI | |
| KeyboardTimerHandler ( | |
| IN EFI_EVENT Event, | |
| IN VOID *Context | |
| ); | |
| /** | |
| logic reset keyboard | |
| Implement SIMPLE_TEXT_IN.Reset() | |
| Perform 8042 controller and keyboard initialization | |
| @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL | |
| @param ExtendedVerification Indicate that the driver may perform a more | |
| exhaustive verification operation of the device during | |
| reset, now this par is ignored in this driver | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| KeyboardEfiReset ( | |
| IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, | |
| IN BOOLEAN ExtendedVerification | |
| ); | |
| /** | |
| Implement SIMPLE_TEXT_IN.ReadKeyStroke(). | |
| Retrieve key values for driver user. | |
| @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL | |
| @param Key The output buffer for key value | |
| @retval EFI_SUCCESS success to read key stroke | |
| @retval EFI_UNSUPPORTED The device does not support the ability to read keystroke data. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| KeyboardReadKeyStroke ( | |
| IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, | |
| OUT EFI_INPUT_KEY *Key | |
| ); | |
| /** | |
| Event notification function for SIMPLE_TEXT_IN.WaitForKey event | |
| Signal the event if there is key available | |
| @param Event the event object | |
| @param Context waiting context | |
| **/ | |
| VOID | |
| EFIAPI | |
| KeyboardWaitForKey ( | |
| IN EFI_EVENT Event, | |
| IN VOID *Context | |
| ); | |
| /** | |
| Read status register. | |
| @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV | |
| @return value in status register | |
| **/ | |
| UINT8 | |
| KeyReadStatusRegister ( | |
| IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn | |
| ); | |
| /** | |
| 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[in] ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV | |
| @retval TRUE Keyboard in System. | |
| @retval FALSE Keyboard not in System. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| CheckKeyboardConnect ( | |
| IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn | |
| ); | |
| /** | |
| Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event | |
| Signal the event if there is key available | |
| @param Event event object | |
| @param Context waiting context | |
| **/ | |
| VOID | |
| EFIAPI | |
| KeyboardWaitForKeyEx ( | |
| IN EFI_EVENT Event, | |
| IN VOID *Context | |
| ); | |
| // | |
| // Simple Text Input Ex protocol function prototypes | |
| // | |
| /** | |
| Reset the input device and optionally 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 | |
| KeyboardEfiResetEx ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, | |
| IN BOOLEAN ExtendedVerification | |
| ); | |
| /** | |
| Reads the next keystroke from the input device. The WaitForKey Event can | |
| be used to test for existence 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 available. | |
| @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to | |
| hardware errors. | |
| @retval EFI_INVALID_PARAMETER - KeyData is NULL. | |
| @retval EFI_UNSUPPORTED - The device does not support the ability to read | |
| keystroke data. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| KeyboardReadKeyStrokeEx ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, | |
| OUT EFI_KEY_DATA *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 | |
| KeyboardSetState ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, | |
| IN EFI_KEY_TOGGLE_STATE *KeyToggleState | |
| ); | |
| /** | |
| 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. If KeyData.Key, | |
| KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState are 0, | |
| then any incomplete keystroke will trigger a notification of the KeyNotificationFunction. | |
| @param KeyNotificationFunction - Points to the function to be called when the key | |
| sequence is typed specified by KeyData. This notification function | |
| should be called at <=TPL_CALLBACK. | |
| @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 necessary data structures. | |
| @retval EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| KeyboardRegisterKeyNotify ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, | |
| IN EFI_KEY_DATA *KeyData, | |
| IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, | |
| OUT VOID **NotifyHandle | |
| ); | |
| /** | |
| 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. | |
| @retval EFI_NOT_FOUND - Can not find the matching entry in database. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| KeyboardUnregisterKeyNotify ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, | |
| IN VOID *NotificationHandle | |
| ); | |
| /** | |
| Push one key data to the EFI key buffer. | |
| @param Queue Pointer to instance of EFI_KEY_QUEUE. | |
| @param KeyData The key data to push. | |
| **/ | |
| VOID | |
| PushEfikeyBufTail ( | |
| IN EFI_KEY_QUEUE *Queue, | |
| IN EFI_KEY_DATA *KeyData | |
| ); | |
| /** | |
| Judge whether is a registered key | |
| @param RegsiteredData 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 FALSE Match failed. | |
| **/ | |
| BOOLEAN | |
| IsKeyRegistered ( | |
| IN EFI_KEY_DATA *RegsiteredData, | |
| IN EFI_KEY_DATA *InputData | |
| ); | |
| /** | |
| Initialize the key state. | |
| @param ConsoleIn The KEYBOARD_CONSOLE_IN_DEV instance. | |
| @param KeyState A pointer to receive the key state information. | |
| **/ | |
| VOID | |
| InitializeKeyState ( | |
| IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, | |
| OUT EFI_KEY_STATE *KeyState | |
| ); | |
| #endif |