1 /** @file 2 PS/2 keyboard driver header file 3 4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> 5 SPDX-License-Identifier: BSD-2-Clause-Patent 6 7 **/ 8 9 #ifndef _PS2KEYBOARD_H_ 10 #define _PS2KEYBOARD_H_ 11 12 #include <Uefi.h> 13 14 #include <Protocol/SuperIo.h> 15 #include <Protocol/SimpleTextIn.h> 16 #include <Protocol/SimpleTextInEx.h> 17 #include <Protocol/DevicePath.h> 18 #include <Protocol/Ps2Policy.h> 19 20 #include <Library/IoLib.h> 21 #include <Library/DevicePathLib.h> 22 #include <Library/UefiDriverEntryPoint.h> 23 #include <Library/UefiLib.h> 24 #include <Library/UefiBootServicesTableLib.h> 25 #include <Library/ReportStatusCodeLib.h> 26 #include <Library/DebugLib.h> 27 #include <Library/UefiRuntimeServicesTableLib.h> 28 #include <Library/MemoryAllocationLib.h> 29 #include <Library/BaseLib.h> 30 #include <Library/BaseMemoryLib.h> 31 #include <Library/TimerLib.h> 32 #include <Library/PcdLib.h> 33 34 // 35 // Global Variables 36 // 37 extern EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver; 38 extern EFI_COMPONENT_NAME_PROTOCOL gPs2KeyboardComponentName; 39 extern EFI_COMPONENT_NAME2_PROTOCOL gPs2KeyboardComponentName2; 40 41 // 42 // Driver Private Data 43 // 44 #define KEYBOARD_CONSOLE_IN_DEV_SIGNATURE SIGNATURE_32 ('k', 'k', 'e', 'y') 45 #define KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 'n') 46 47 typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY { 48 UINTN Signature; 49 EFI_KEY_DATA KeyData; 50 EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; 51 LIST_ENTRY NotifyEntry; 52 } KEYBOARD_CONSOLE_IN_EX_NOTIFY; 53 54 #define KEYBOARD_SCAN_CODE_MAX_COUNT 32 55 typedef struct { 56 UINT8 Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT]; 57 UINTN Head; 58 UINTN Tail; 59 } SCAN_CODE_QUEUE; 60 61 #define KEYBOARD_EFI_KEY_MAX_COUNT 256 62 typedef struct { 63 EFI_KEY_DATA Buffer[KEYBOARD_EFI_KEY_MAX_COUNT]; 64 UINTN Head; 65 UINTN Tail; 66 } EFI_KEY_QUEUE; 67 68 typedef struct { 69 UINTN Signature; 70 71 EFI_HANDLE Handle; 72 EFI_SIMPLE_TEXT_INPUT_PROTOCOL ConIn; 73 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL ConInEx; 74 75 EFI_EVENT TimerEvent; 76 77 UINT32 DataRegisterAddress; 78 UINT32 StatusRegisterAddress; 79 UINT32 CommandRegisterAddress; 80 81 BOOLEAN LeftCtrl; 82 BOOLEAN RightCtrl; 83 BOOLEAN LeftAlt; 84 BOOLEAN RightAlt; 85 BOOLEAN LeftShift; 86 BOOLEAN RightShift; 87 BOOLEAN LeftLogo; 88 BOOLEAN RightLogo; 89 BOOLEAN Menu; 90 BOOLEAN SysReq; 91 92 BOOLEAN CapsLock; 93 BOOLEAN NumLock; 94 BOOLEAN ScrollLock; 95 96 BOOLEAN IsSupportPartialKey; 97 // 98 // Queue storing key scancodes 99 // 100 SCAN_CODE_QUEUE ScancodeQueue; 101 EFI_KEY_QUEUE EfiKeyQueue; 102 EFI_KEY_QUEUE EfiKeyQueueForNotify; 103 104 // 105 // Error state 106 // 107 BOOLEAN KeyboardErr; 108 109 EFI_UNICODE_STRING_TABLE *ControllerNameTable; 110 111 EFI_DEVICE_PATH_PROTOCOL *DevicePath; 112 // 113 // Notification Function List 114 // 115 LIST_ENTRY NotifyList; 116 EFI_EVENT KeyNotifyProcessEvent; 117 } KEYBOARD_CONSOLE_IN_DEV; 118 119 #define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) CR (a, KEYBOARD_CONSOLE_IN_DEV, ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE) 120 #define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \ 121 CR (a, \ 122 KEYBOARD_CONSOLE_IN_DEV, \ 123 ConInEx, \ 124 KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \ 125 ) 126 127 #define TABLE_END 0x0 128 129 // 130 // Driver entry point 131 // 132 /** 133 The user Entry Point for module Ps2Keyboard. The user code starts with this function. 134 135 @param[in] ImageHandle The firmware allocated handle for the EFI image. 136 @param[in] SystemTable A pointer to the EFI System Table. 137 138 @retval EFI_SUCCESS The entry point is executed successfully. 139 @retval other Some error occurs when executing this entry point. 140 141 **/ 142 EFI_STATUS 143 EFIAPI 144 InstallPs2KeyboardDriver ( 145 IN EFI_HANDLE ImageHandle, 146 IN EFI_SYSTEM_TABLE *SystemTable 147 ); 148 149 #define KEYBOARD_8042_DATA_REGISTER 0x60 150 #define KEYBOARD_8042_STATUS_REGISTER 0x64 151 #define KEYBOARD_8042_COMMAND_REGISTER 0x64 152 153 #define KEYBOARD_KBEN 0xF4 154 #define KEYBOARD_CMDECHO_ACK 0xFA 155 156 #define KEYBOARD_MAX_TRY 256 // 256 157 #define KEYBOARD_TIMEOUT 65536 // 0.07s 158 #define KEYBOARD_WAITFORVALUE_TIMEOUT 1000000 // 1s 159 #define KEYBOARD_BAT_TIMEOUT 4000000 // 4s 160 #define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s 161 #define SCANCODE_EXTENDED0 0xE0 162 #define SCANCODE_EXTENDED1 0xE1 163 #define SCANCODE_CTRL_MAKE 0x1D 164 #define SCANCODE_CTRL_BREAK 0x9D 165 #define SCANCODE_ALT_MAKE 0x38 166 #define SCANCODE_ALT_BREAK 0xB8 167 #define SCANCODE_LEFT_SHIFT_MAKE 0x2A 168 #define SCANCODE_LEFT_SHIFT_BREAK 0xAA 169 #define SCANCODE_RIGHT_SHIFT_MAKE 0x36 170 #define SCANCODE_RIGHT_SHIFT_BREAK 0xB6 171 #define SCANCODE_CAPS_LOCK_MAKE 0x3A 172 #define SCANCODE_NUM_LOCK_MAKE 0x45 173 #define SCANCODE_SCROLL_LOCK_MAKE 0x46 174 #define SCANCODE_DELETE_MAKE 0x53 175 #define SCANCODE_LEFT_LOGO_MAKE 0x5B //GUI key defined in Keyboard scan code 176 #define SCANCODE_LEFT_LOGO_BREAK 0xDB 177 #define SCANCODE_RIGHT_LOGO_MAKE 0x5C 178 #define SCANCODE_RIGHT_LOGO_BREAK 0xDC 179 #define SCANCODE_MENU_MAKE 0x5D //APPS key defined in Keyboard scan code 180 #define SCANCODE_MENU_BREAK 0xDD 181 #define SCANCODE_SYS_REQ_MAKE 0x37 182 #define SCANCODE_SYS_REQ_BREAK 0xB7 183 #define SCANCODE_SYS_REQ_MAKE_WITH_ALT 0x54 184 #define SCANCODE_SYS_REQ_BREAK_WITH_ALT 0xD4 185 186 #define SCANCODE_MAX_MAKE 0x60 187 188 189 #define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA BIT0 ///< 0 - Output register has no data; 1 - Output register has data 190 #define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA BIT1 ///< 0 - Input register has no data; 1 - Input register has data 191 #define KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG BIT2 ///< Set to 0 after power on reset 192 #define KEYBOARD_STATUS_REGISTER_INPUT_DATA_TYPE BIT3 ///< 0 - Data in input register is data; 1 - Data in input register is command 193 #define KEYBOARD_STATUS_REGISTER_ENABLE_FLAG BIT4 ///< 0 - Keyboard is disable; 1 - Keyboard is enable 194 #define KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT BIT5 ///< 0 - Transmit is complete without timeout; 1 - Transmit is timeout without complete 195 #define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT BIT6 ///< 0 - Receive is complete without timeout; 1 - Receive is timeout without complete 196 #define KEYBOARD_STATUS_REGISTER_PARITY BIT7 ///< 0 - Odd parity; 1 - Even parity 197 198 #define KEYBOARD_8042_COMMAND_READ 0x20 199 #define KEYBOARD_8042_COMMAND_WRITE 0x60 200 #define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE 0xA7 201 #define KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE 0xA8 202 #define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST 0xAA 203 #define KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST 0xAB 204 #define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE 0xAD 205 206 #define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA 0xF4 207 #define KEYBOARD_8048_COMMAND_RESET 0xFF 208 #define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET 0xF0 209 210 #define KEYBOARD_8048_RETURN_8042_BAT_SUCCESS 0xAA 211 #define KEYBOARD_8048_RETURN_8042_BAT_ERROR 0xFC 212 #define KEYBOARD_8048_RETURN_8042_ACK 0xFA 213 214 215 // 216 // Keyboard Controller Status 217 // 218 #define KBC_PARE 0x80 // Parity Error 219 #define KBC_TIM 0x40 // General Time Out 220 221 // 222 // Other functions that are used among .c files 223 // 224 /** 225 Show keyboard status lights according to 226 indicators in ConsoleIn. 227 228 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV 229 230 @return status 231 232 **/ 233 EFI_STATUS 234 UpdateStatusLights ( 235 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn 236 ); 237 238 /** 239 write key to keyboard. 240 241 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV 242 @param Data value wanted to be written 243 244 @retval EFI_TIMEOUT - GC_TODO: Add description for return value 245 @retval EFI_SUCCESS - GC_TODO: Add description for return value 246 247 **/ 248 EFI_STATUS 249 KeyboardRead ( 250 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, 251 OUT UINT8 *Data 252 ); 253 254 /** 255 Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec. 256 257 The function is always called in TPL_NOTIFY. 258 259 @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer 260 261 **/ 262 VOID 263 KeyGetchar ( 264 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn 265 ); 266 267 /** 268 Process key notify. 269 270 @param Event Indicates the event that invoke this function. 271 @param Context Indicates the calling context. 272 **/ 273 VOID 274 EFIAPI 275 KeyNotifyProcessHandler ( 276 IN EFI_EVENT Event, 277 IN VOID *Context 278 ); 279 280 /** 281 Perform 8042 controller and keyboard Initialization. 282 If ExtendedVerification is TRUE, do additional test for 283 the keyboard interface 284 285 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer 286 @param ExtendedVerification - indicates a thorough initialization 287 288 @retval EFI_DEVICE_ERROR Fail to init keyboard 289 @retval EFI_SUCCESS Success to init keyboard 290 **/ 291 EFI_STATUS 292 InitKeyboard ( 293 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, 294 IN BOOLEAN ExtendedVerification 295 ); 296 297 298 /** 299 Timer event handler: read a series of scancodes from 8042 300 and put them into memory scancode buffer. 301 it read as much scancodes to either fill 302 the memory buffer or empty the keyboard buffer. 303 It is registered as running under TPL_NOTIFY 304 305 @param Event - The timer event 306 @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer 307 308 **/ 309 VOID 310 EFIAPI 311 KeyboardTimerHandler ( 312 IN EFI_EVENT Event, 313 IN VOID *Context 314 ); 315 316 /** 317 logic reset keyboard 318 Implement SIMPLE_TEXT_IN.Reset() 319 Perform 8042 controller and keyboard initialization 320 321 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL 322 @param ExtendedVerification Indicate that the driver may perform a more 323 exhaustive verification operation of the device during 324 reset, now this par is ignored in this driver 325 326 **/ 327 EFI_STATUS 328 EFIAPI 329 KeyboardEfiReset ( 330 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 331 IN BOOLEAN ExtendedVerification 332 ); 333 334 /** 335 Implement SIMPLE_TEXT_IN.ReadKeyStroke(). 336 Retrieve key values for driver user. 337 338 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL 339 @param Key The output buffer for key value 340 341 @retval EFI_SUCCESS success to read key stroke 342 **/ 343 EFI_STATUS 344 EFIAPI 345 KeyboardReadKeyStroke ( 346 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, 347 OUT EFI_INPUT_KEY *Key 348 ); 349 350 /** 351 Event notification function for SIMPLE_TEXT_IN.WaitForKey event 352 Signal the event if there is key available 353 354 @param Event the event object 355 @param Context waiting context 356 357 **/ 358 VOID 359 EFIAPI 360 KeyboardWaitForKey ( 361 IN EFI_EVENT Event, 362 IN VOID *Context 363 ); 364 365 /** 366 Read status register. 367 368 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV 369 370 @return value in status register 371 372 **/ 373 UINT8 374 KeyReadStatusRegister ( 375 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn 376 ); 377 378 /** 379 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command 380 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device 381 should not be in system. 382 383 @param[in] ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV 384 385 @retval TRUE Keyboard in System. 386 @retval FALSE Keyboard not in System. 387 **/ 388 BOOLEAN 389 EFIAPI 390 CheckKeyboardConnect ( 391 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn 392 ); 393 394 /** 395 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event 396 Signal the event if there is key available 397 398 @param Event event object 399 @param Context waiting context 400 401 **/ 402 VOID 403 EFIAPI 404 KeyboardWaitForKeyEx ( 405 IN EFI_EVENT Event, 406 IN VOID *Context 407 ); 408 409 // 410 // Simple Text Input Ex protocol function prototypes 411 // 412 413 /** 414 Reset the input device and optionally run diagnostics 415 416 @param This - Protocol instance pointer. 417 @param ExtendedVerification - Driver may perform diagnostics on reset. 418 419 @retval EFI_SUCCESS - The device was reset. 420 @retval EFI_DEVICE_ERROR - The device is not functioning properly and could 421 not be reset. 422 423 **/ 424 EFI_STATUS 425 EFIAPI 426 KeyboardEfiResetEx ( 427 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 428 IN BOOLEAN ExtendedVerification 429 ); 430 431 /** 432 Reads the next keystroke from the input device. The WaitForKey Event can 433 be used to test for existence of a keystroke via WaitForEvent () call. 434 435 436 @param This - Protocol instance pointer. 437 @param KeyData - A pointer to a buffer that is filled in with the keystroke 438 state data for the key that was pressed. 439 440 @retval EFI_SUCCESS - The keystroke information was returned. 441 @retval EFI_NOT_READY - There was no keystroke data available. 442 @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to 443 hardware errors. 444 @retval EFI_INVALID_PARAMETER - KeyData is NULL. 445 446 **/ 447 EFI_STATUS 448 EFIAPI 449 KeyboardReadKeyStrokeEx ( 450 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 451 OUT EFI_KEY_DATA *KeyData 452 ); 453 454 /** 455 Set certain state for the input device. 456 457 @param This - Protocol instance pointer. 458 @param KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the 459 state for the input device. 460 461 @retval EFI_SUCCESS - The device state was set successfully. 462 @retval EFI_DEVICE_ERROR - The device is not functioning correctly and could 463 not have the setting adjusted. 464 @retval EFI_UNSUPPORTED - The device does not have the ability to set its state. 465 @retval EFI_INVALID_PARAMETER - KeyToggleState is NULL. 466 467 **/ 468 EFI_STATUS 469 EFIAPI 470 KeyboardSetState ( 471 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 472 IN EFI_KEY_TOGGLE_STATE *KeyToggleState 473 ); 474 475 /** 476 Register a notification function for a particular keystroke for the input device. 477 478 @param This - Protocol instance pointer. 479 @param KeyData - A pointer to a buffer that is filled in with the keystroke 480 information data for the key that was pressed. If KeyData.Key, 481 KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState are 0, 482 then any incomplete keystroke will trigger a notification of the KeyNotificationFunction. 483 @param KeyNotificationFunction - Points to the function to be called when the key 484 sequence is typed specified by KeyData. This notification function 485 should be called at <=TPL_CALLBACK. 486 @param NotifyHandle - Points to the unique handle assigned to the registered notification. 487 488 @retval EFI_SUCCESS - The notification function was registered successfully. 489 @retval EFI_OUT_OF_RESOURCES - Unable to allocate resources for necessary data structures. 490 @retval EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. 491 492 **/ 493 EFI_STATUS 494 EFIAPI 495 KeyboardRegisterKeyNotify ( 496 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 497 IN EFI_KEY_DATA *KeyData, 498 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, 499 OUT VOID **NotifyHandle 500 ); 501 502 /** 503 Remove a registered notification function from a particular keystroke. 504 505 @param This - Protocol instance pointer. 506 @param NotificationHandle - The handle of the notification function being unregistered. 507 508 509 @retval EFI_SUCCESS - The notification function was unregistered successfully. 510 @retval EFI_INVALID_PARAMETER - The NotificationHandle is invalid. 511 @retval EFI_NOT_FOUND - Can not find the matching entry in database. 512 513 **/ 514 EFI_STATUS 515 EFIAPI 516 KeyboardUnregisterKeyNotify ( 517 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, 518 IN VOID *NotificationHandle 519 ); 520 521 /** 522 Push one key data to the EFI key buffer. 523 524 @param Queue Pointer to instance of EFI_KEY_QUEUE. 525 @param KeyData The key data to push. 526 **/ 527 VOID 528 PushEfikeyBufTail ( 529 IN EFI_KEY_QUEUE *Queue, 530 IN EFI_KEY_DATA *KeyData 531 ); 532 533 /** 534 Judge whether is a registered key 535 536 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke 537 state data for the key that was registered. 538 @param InputData A pointer to a buffer that is filled in with the keystroke 539 state data for the key that was pressed. 540 541 @retval TRUE Key be pressed matches a registered key. 542 @retval FALSE Match failed. 543 544 **/ 545 BOOLEAN 546 IsKeyRegistered ( 547 IN EFI_KEY_DATA *RegsiteredData, 548 IN EFI_KEY_DATA *InputData 549 ); 550 551 /** 552 Initialize the key state. 553 554 @param ConsoleIn The KEYBOARD_CONSOLE_IN_DEV instance. 555 @param KeyState A pointer to receive the key state information. 556 **/ 557 VOID 558 InitializeKeyState ( 559 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn, 560 OUT EFI_KEY_STATE *KeyState 561 ); 562 563 #endif 564