2 ConsoleOut Routines that speak VGA.
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "BiosKeyboard.h"
20 // EFI Driver Binding Protocol Instance
22 EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding
= {
23 BiosKeyboardDriverBindingSupported
,
24 BiosKeyboardDriverBindingStart
,
25 BiosKeyboardDriverBindingStop
,
35 @param Queue The queue to be enqueued.
36 @param KeyData The key data to be enqueued.
38 @retval EFI_NOT_READY The queue is full.
39 @retval EFI_SUCCESS Successfully enqueued the key data.
44 IN SIMPLE_QUEUE
*Queue
,
45 IN EFI_KEY_DATA
*KeyData
48 if ((Queue
->Rear
+ 1) % QUEUE_MAX_COUNT
== Queue
->Front
) {
52 CopyMem (&Queue
->Buffer
[Queue
->Rear
], KeyData
, sizeof (EFI_KEY_DATA
));
53 Queue
->Rear
= (Queue
->Rear
+ 1) % QUEUE_MAX_COUNT
;
62 @param Queue The queue to be dequeued.
63 @param KeyData The key data to be dequeued.
65 @retval EFI_NOT_READY The queue is empty.
66 @retval EFI_SUCCESS Successfully dequeued the key data.
71 IN SIMPLE_QUEUE
*Queue
,
72 IN EFI_KEY_DATA
*KeyData
75 if (Queue
->Front
== Queue
->Rear
) {
79 CopyMem (KeyData
, &Queue
->Buffer
[Queue
->Front
], sizeof (EFI_KEY_DATA
));
80 Queue
->Front
= (Queue
->Front
+ 1) % QUEUE_MAX_COUNT
;
87 Check whether the queue is empty.
89 @param Queue The queue to be checked.
91 @retval EFI_NOT_READY The queue is empty.
92 @retval EFI_SUCCESS The queue is not empty.
97 IN SIMPLE_QUEUE
*Queue
100 if (Queue
->Front
== Queue
->Rear
) {
101 return EFI_NOT_READY
;
108 // EFI Driver Binding Protocol Functions
112 Check whether the driver supports this device.
114 @param This The Udriver binding protocol.
115 @param Controller The controller handle to check.
116 @param RemainingDevicePath The remaining device path.
118 @retval EFI_SUCCESS The driver supports this controller.
119 @retval other This device isn't supported.
124 BiosKeyboardDriverBindingSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE Controller
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
131 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
132 EFI_ISA_IO_PROTOCOL
*IsaIo
;
135 // See if the Legacy BIOS Protocol is available
137 Status
= gBS
->LocateProtocol (
138 &gEfiLegacyBiosProtocolGuid
,
140 (VOID
**) &LegacyBios
143 if (EFI_ERROR (Status
)) {
147 // Open the IO Abstraction(s) needed to perform the supported test
149 Status
= gBS
->OpenProtocol (
151 &gEfiIsaIoProtocolGuid
,
153 This
->DriverBindingHandle
,
155 EFI_OPEN_PROTOCOL_BY_DRIVER
158 if (EFI_ERROR (Status
)) {
162 // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
164 if (IsaIo
->ResourceList
->Device
.HID
!= EISA_PNP_ID (0x303) || IsaIo
->ResourceList
->Device
.UID
!= 0) {
165 Status
= EFI_UNSUPPORTED
;
170 &gEfiIsaIoProtocolGuid
,
171 This
->DriverBindingHandle
,
179 Starts the device with this driver.
181 @param This The driver binding instance.
182 @param Controller Handle of device to bind driver to.
183 @param RemainingDevicePath Optional parameter use to pick a specific child
186 @retval EFI_SUCCESS The controller is controlled by the driver.
187 @retval Other This controller cannot be started.
192 BiosKeyboardDriverBindingStart (
193 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
194 IN EFI_HANDLE Controller
,
195 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
199 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
200 EFI_ISA_IO_PROTOCOL
*IsaIo
;
201 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
202 EFI_IA32_REGISTER_SET Regs
;
204 EFI_PS2_POLICY_PROTOCOL
*Ps2Policy
;
206 EFI_STATUS_CODE_VALUE StatusCode
;
208 BiosKeyboardPrivate
= NULL
;
213 // Get Ps2 policy to set. Will be use if present.
215 gBS
->LocateProtocol (
216 &gEfiPs2PolicyProtocolGuid
,
222 // See if the Legacy BIOS Protocol is available
224 Status
= gBS
->LocateProtocol (
225 &gEfiLegacyBiosProtocolGuid
,
227 (VOID
**) &LegacyBios
230 if (EFI_ERROR (Status
)) {
234 // Open the IO Abstraction(s) needed
236 Status
= gBS
->OpenProtocol (
238 &gEfiIsaIoProtocolGuid
,
240 This
->DriverBindingHandle
,
242 EFI_OPEN_PROTOCOL_BY_DRIVER
244 if (EFI_ERROR (Status
)) {
249 // Allocate the private device structure
251 BiosKeyboardPrivate
= (BIOS_KEYBOARD_DEV
*) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV
));
252 if (NULL
== BiosKeyboardPrivate
) {
253 Status
= EFI_OUT_OF_RESOURCES
;
258 // Initialize the private device structure
260 BiosKeyboardPrivate
->Signature
= BIOS_KEYBOARD_DEV_SIGNATURE
;
261 BiosKeyboardPrivate
->Handle
= Controller
;
262 BiosKeyboardPrivate
->LegacyBios
= LegacyBios
;
263 BiosKeyboardPrivate
->IsaIo
= IsaIo
;
265 BiosKeyboardPrivate
->SimpleTextIn
.Reset
= BiosKeyboardReset
;
266 BiosKeyboardPrivate
->SimpleTextIn
.ReadKeyStroke
= BiosKeyboardReadKeyStroke
;
268 BiosKeyboardPrivate
->DataRegisterAddress
= KEYBOARD_8042_DATA_REGISTER
;
269 BiosKeyboardPrivate
->StatusRegisterAddress
= KEYBOARD_8042_STATUS_REGISTER
;
270 BiosKeyboardPrivate
->CommandRegisterAddress
= KEYBOARD_8042_COMMAND_REGISTER
;
271 BiosKeyboardPrivate
->ExtendedKeyboard
= TRUE
;
273 BiosKeyboardPrivate
->Queue
.Front
= 0;
274 BiosKeyboardPrivate
->Queue
.Rear
= 0;
275 BiosKeyboardPrivate
->QueueForNotify
.Front
= 0;
276 BiosKeyboardPrivate
->QueueForNotify
.Rear
= 0;
277 BiosKeyboardPrivate
->SimpleTextInputEx
.Reset
= BiosKeyboardResetEx
;
278 BiosKeyboardPrivate
->SimpleTextInputEx
.ReadKeyStrokeEx
= BiosKeyboardReadKeyStrokeEx
;
279 BiosKeyboardPrivate
->SimpleTextInputEx
.SetState
= BiosKeyboardSetState
;
280 BiosKeyboardPrivate
->SimpleTextInputEx
.RegisterKeyNotify
= BiosKeyboardRegisterKeyNotify
;
281 BiosKeyboardPrivate
->SimpleTextInputEx
.UnregisterKeyNotify
= BiosKeyboardUnregisterKeyNotify
;
282 InitializeListHead (&BiosKeyboardPrivate
->NotifyList
);
285 // Report that the keyboard is being enabled
289 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
293 // Setup the WaitForKey event
295 Status
= gBS
->CreateEvent (
298 BiosKeyboardWaitForKey
,
299 &(BiosKeyboardPrivate
->SimpleTextIn
),
300 &((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
)
302 if (EFI_ERROR (Status
)) {
303 (BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
= NULL
;
306 Status
= gBS
->CreateEvent (
309 BiosKeyboardWaitForKeyEx
,
310 &(BiosKeyboardPrivate
->SimpleTextInputEx
),
311 &(BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
)
313 if (EFI_ERROR (Status
)) {
314 BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
= NULL
;
319 // Setup a periodic timer, used for reading keystrokes at a fixed interval
321 Status
= gBS
->CreateEvent (
322 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
324 BiosKeyboardTimerHandler
,
326 &BiosKeyboardPrivate
->TimerEvent
328 if (EFI_ERROR (Status
)) {
329 Status
= EFI_OUT_OF_RESOURCES
;
330 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
334 Status
= gBS
->SetTimer (
335 BiosKeyboardPrivate
->TimerEvent
,
337 KEYBOARD_TIMER_INTERVAL
339 if (EFI_ERROR (Status
)) {
340 Status
= EFI_OUT_OF_RESOURCES
;
341 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
345 Status
= gBS
->CreateEvent (
348 KeyNotifyProcessHandler
,
350 &BiosKeyboardPrivate
->KeyNotifyProcessEvent
352 if (EFI_ERROR (Status
)) {
353 Status
= EFI_OUT_OF_RESOURCES
;
354 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
359 // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system
363 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
367 // Reset the keyboard device
369 Status
= BiosKeyboardPrivate
->SimpleTextInputEx
.Reset (
370 &BiosKeyboardPrivate
->SimpleTextInputEx
,
371 FeaturePcdGet (PcdPs2KbdExtendedVerification
)
373 if (EFI_ERROR (Status
)) {
374 DEBUG ((EFI_D_ERROR
, "[KBD]Reset Failed. Status - %r\n", Status
));
375 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
;
379 // Do platform specific policy like port swapping and keyboard light default
381 if (Ps2Policy
!= NULL
) {
383 Ps2Policy
->Ps2InitHardware (Controller
);
386 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_CAPSLOCK
) == EFI_KEYBOARD_CAPSLOCK
) {
390 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_NUMLOCK
) == EFI_KEYBOARD_NUMLOCK
) {
394 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_SCROLLLOCK
) == EFI_KEYBOARD_SCROLLLOCK
) {
398 KeyboardWrite (BiosKeyboardPrivate
, 0xed);
399 KeyboardWaitForValue (BiosKeyboardPrivate
, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT
);
400 KeyboardWrite (BiosKeyboardPrivate
, Command
);
402 // Call Legacy BIOS Protocol to set whatever is necessary
404 LegacyBios
->UpdateKeyboardLedStatus (LegacyBios
, Command
);
410 CarryFlag
= BiosKeyboardPrivate
->LegacyBios
->Int86 (
411 BiosKeyboardPrivate
->LegacyBios
,
418 // Check bit 6 of Feature Byte 2.
419 // If it is set, then Int 16 Func 09 is supported
421 if (*(UINT8
*)(UINTN
) ((Regs
.X
.ES
<< 4) + Regs
.X
.BX
+ 0x06) & 0x40) {
423 // Get Keyboard Functionality
426 CarryFlag
= BiosKeyboardPrivate
->LegacyBios
->Int86 (
427 BiosKeyboardPrivate
->LegacyBios
,
434 // Check bit 5 of AH.
435 // If it is set, then INT 16 Finc 10-12 are supported.
437 if ((Regs
.H
.AL
& 0x40) != 0) {
439 // Set the flag to use INT 16 Func 10-12
441 BiosKeyboardPrivate
->ExtendedKeyboard
= TRUE
;
446 DEBUG ((EFI_D_INFO
, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN
)BiosKeyboardPrivate
->ExtendedKeyboard
));
448 // Install protocol interfaces for the keyboard device.
450 Status
= gBS
->InstallMultipleProtocolInterfaces (
452 &gEfiSimpleTextInProtocolGuid
,
453 &BiosKeyboardPrivate
->SimpleTextIn
,
454 &gEfiSimpleTextInputExProtocolGuid
,
455 &BiosKeyboardPrivate
->SimpleTextInputEx
,
460 if (StatusCode
!= 0) {
462 // Report an Error Code for failing to start the keyboard device
465 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
470 if (EFI_ERROR (Status
)) {
472 if (BiosKeyboardPrivate
!= NULL
) {
473 if ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
!= NULL
) {
474 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
);
477 if ((BiosKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
!= NULL
) {
478 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
);
481 if (BiosKeyboardPrivate
->KeyNotifyProcessEvent
!= NULL
) {
482 gBS
->CloseEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
485 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate
->NotifyList
);
487 if (BiosKeyboardPrivate
->TimerEvent
!= NULL
) {
488 gBS
->CloseEvent (BiosKeyboardPrivate
->TimerEvent
);
491 FreePool (BiosKeyboardPrivate
);
497 &gEfiIsaIoProtocolGuid
,
498 This
->DriverBindingHandle
,
508 Stop the device handled by this driver.
510 @param This The driver binding protocol.
511 @param Controller The controller to release.
512 @param NumberOfChildren The number of handles in ChildHandleBuffer.
513 @param ChildHandleBuffer The array of child handle.
515 @retval EFI_SUCCESS The device was stopped.
516 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
517 @retval Others Fail to uninstall protocols attached on the device.
522 BiosKeyboardDriverBindingStop (
523 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
524 IN EFI_HANDLE Controller
,
525 IN UINTN NumberOfChildren
,
526 IN EFI_HANDLE
*ChildHandleBuffer
530 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleTextIn
;
531 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
536 Status
= gBS
->OpenProtocol (
538 &gEfiSimpleTextInProtocolGuid
,
539 (VOID
**) &SimpleTextIn
,
540 This
->DriverBindingHandle
,
542 EFI_OPEN_PROTOCOL_GET_PROTOCOL
544 if (EFI_ERROR (Status
)) {
548 Status
= gBS
->OpenProtocol (
550 &gEfiSimpleTextInputExProtocolGuid
,
552 This
->DriverBindingHandle
,
554 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
556 if (EFI_ERROR (Status
)) {
560 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn
);
562 Status
= gBS
->UninstallMultipleProtocolInterfaces (
564 &gEfiSimpleTextInProtocolGuid
,
565 &BiosKeyboardPrivate
->SimpleTextIn
,
566 &gEfiSimpleTextInputExProtocolGuid
,
567 &BiosKeyboardPrivate
->SimpleTextInputEx
,
570 if (EFI_ERROR (Status
)) {
574 // Release the IsaIo protocol on the controller handle
578 &gEfiIsaIoProtocolGuid
,
579 This
->DriverBindingHandle
,
584 // Free other resources
586 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
);
587 gBS
->CloseEvent (BiosKeyboardPrivate
->TimerEvent
);
588 gBS
->CloseEvent (BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
);
589 gBS
->CloseEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
590 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate
->NotifyList
);
592 FreePool (BiosKeyboardPrivate
);
598 Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.
600 @param BiosKeyboardPrivate Keyboard instance pointer.
602 @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.
606 KeyReadDataRegister (
607 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
613 // Use IsaIo protocol to perform IO operations
615 BiosKeyboardPrivate
->IsaIo
->Io
.Read (
616 BiosKeyboardPrivate
->IsaIo
,
618 BiosKeyboardPrivate
->DataRegisterAddress
,
627 Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.
629 @param BiosKeyboardPrivate Keyboard instance pointer.
631 @return The status byte read from status register of Keyboard Controller from command port which often is port 64H.
635 KeyReadStatusRegister (
636 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
642 // Use IsaIo protocol to perform IO operations
644 BiosKeyboardPrivate
->IsaIo
->Io
.Read (
645 BiosKeyboardPrivate
->IsaIo
,
647 BiosKeyboardPrivate
->StatusRegisterAddress
,
656 Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.
658 @param BiosKeyboardPrivate Keyboard instance pointer.
659 @param Data Data byte to write.
663 KeyWriteCommandRegister (
664 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
669 // Use IsaIo protocol to perform IO operations
671 BiosKeyboardPrivate
->IsaIo
->Io
.Write (
672 BiosKeyboardPrivate
->IsaIo
,
674 BiosKeyboardPrivate
->CommandRegisterAddress
,
681 Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.
683 @param BiosKeyboardPrivate Keyboard instance pointer.
684 @param Data Data byte to write.
688 KeyWriteDataRegister (
689 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
694 // Use IsaIo protocol to perform IO operations
696 BiosKeyboardPrivate
->IsaIo
->Io
.Write (
697 BiosKeyboardPrivate
->IsaIo
,
699 BiosKeyboardPrivate
->DataRegisterAddress
,
706 Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.
708 @param BiosKeyboardPrivate Keyboard instance pointer.
709 @param Data The pointer for data that being read out.
711 @retval EFI_SUCCESS The data byte read out successfully.
712 @retval EFI_TIMEOUT Timeout occurred during reading out data byte.
717 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
728 // wait till output buffer full then perform the read
730 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
731 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_OUTB
) != 0) {
733 *Data
= KeyReadDataRegister (BiosKeyboardPrivate
);
740 if (RegFilled
== 0) {
748 Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.
750 @param BiosKeyboardPrivate Keyboard instance pointer.
751 @param Data Data byte to write.
753 @retval EFI_SUCCESS The data byte is written successfully.
754 @retval EFI_TIMEOUT Timeout occurred during writing.
759 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
770 // wait for input buffer empty
772 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
773 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
781 if (RegEmptied
== 0) {
787 KeyWriteDataRegister (BiosKeyboardPrivate
, Data
);
793 Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.
795 @param BiosKeyboardPrivate Keyboard instance pointer.
796 @param Data Command byte to write.
798 @retval EFI_SUCCESS The command byte is written successfully.
799 @retval EFI_TIMEOUT Timeout occurred during writing.
804 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
815 // Wait For Input Buffer Empty
817 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
818 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
826 if (RegEmptied
== 0) {
832 KeyWriteCommandRegister (BiosKeyboardPrivate
, Data
);
835 // Wait For Input Buffer Empty again
838 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
839 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
847 if (RegEmptied
== 0) {
855 Wait for a specific value to be presented in
856 Data register of Keyboard Controller by keyboard and then read it,
857 used in keyboard commands ack
859 @param BiosKeyboardPrivate Keyboard instance pointer.
860 @param Value The value to be waited for
861 @param WaitForValueTimeOut The limit of microseconds for timeout
863 @retval EFI_SUCCESS The command byte is written successfully.
864 @retval EFI_TIMEOUT Timeout occurred during writing.
868 KeyboardWaitForValue (
869 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
871 IN UINTN WaitForValueTimeOut
884 // Make sure the initial value of 'Data' is different from 'Value'
891 // Read from 8042 (multiple times if needed)
892 // until the expected value appears
893 // use SumTimeOut to control the iteration
899 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
900 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_OUTB
) != 0) {
901 Data
= KeyReadDataRegister (BiosKeyboardPrivate
);
908 SumTimeOut
+= TimeOut
;
915 if (SumTimeOut
>= WaitForValueTimeOut
) {
931 Reads the next keystroke from the input device. The WaitForKey Event can
932 be used to test for existance of a keystroke via WaitForEvent () call.
934 @param BiosKeyboardPrivate Bioskeyboard driver private structure.
935 @param KeyData A pointer to a buffer that is filled in with the keystroke
936 state data for the key that was pressed.
938 @retval EFI_SUCCESS The keystroke information was returned.
939 @retval EFI_NOT_READY There was no keystroke data availiable.
940 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
942 @retval EFI_INVALID_PARAMETER KeyData is NULL.
946 KeyboardReadKeyStrokeWorker (
947 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
948 OUT EFI_KEY_DATA
*KeyData
953 if (KeyData
== NULL
) {
954 return EFI_INVALID_PARAMETER
;
958 // Use TimerEvent callback function to check whether there's any key pressed
962 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
963 // Csm will be used to check whether there is a key pending, but the csm will disable all
964 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
965 // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
966 // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,
967 // e.g. usb keyboard driver.
968 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
969 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
973 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
975 BiosKeyboardTimerHandler (NULL
, BiosKeyboardPrivate
);
977 // If there's no key, just return
979 Status
= CheckQueue (&BiosKeyboardPrivate
->Queue
);
980 if (EFI_ERROR (Status
)) {
981 gBS
->RestoreTPL (OldTpl
);
982 return EFI_NOT_READY
;
985 Status
= Dequeue (&BiosKeyboardPrivate
->Queue
, KeyData
);
987 gBS
->RestoreTPL (OldTpl
);
993 // EFI Simple Text In Protocol Functions
996 Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.
998 @param This Pointer of simple text Protocol.
999 @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
1001 @retval EFI_SUCCESS The command byte is written successfully.
1002 @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
1008 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
1009 IN BOOLEAN ExtendedVerification
1012 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1016 BOOLEAN MouseEnable
;
1019 MouseEnable
= FALSE
;
1020 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1024 // Report reset progress code
1026 REPORT_STATUS_CODE (
1028 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
1032 // Report a Progress Code for clearing the keyboard buffer
1034 REPORT_STATUS_CODE (
1036 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
1041 // Raise TPL to avoid mouse operation impact
1043 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1047 // Exhaust output buffer data
1050 Status
= BiosKeyboardReadKeyStroke (
1054 } while (!EFI_ERROR (Status
));
1057 // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H
1058 // if not skip step 4&5 and jump to step 6 to selftest KBC and report this
1061 if (!PcdGetBool (PcdFastPS2Detection
)) {
1062 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_SYSF
) != 0) {
1065 // CheckMouseStatus to decide enable it later or not
1068 // Read the command byte of KBC
1070 Status
= KeyboardCommand (
1071 BiosKeyboardPrivate
,
1072 KBC_CMDREG_VIA64_CMDBYTE_R
1075 if (EFI_ERROR (Status
)) {
1076 Status
= EFI_DEVICE_ERROR
;
1080 Status
= KeyboardRead (
1081 BiosKeyboardPrivate
,
1085 if (EFI_ERROR (Status
)) {
1086 Status
= EFI_DEVICE_ERROR
;
1090 // Check mouse enabled or not before
1092 if ((CommandByte
& KB_CMMBYTE_DISABLE_AUX
) != 0) {
1093 MouseEnable
= FALSE
;
1099 // disable mouse (via KBC) and Keyborad device
1101 Status
= KeyboardCommand (
1102 BiosKeyboardPrivate
,
1103 KBC_CMDREG_VIA64_AUX_DISABLE
1106 if (EFI_ERROR (Status
)) {
1107 Status
= EFI_DEVICE_ERROR
;
1111 Status
= KeyboardCommand (
1112 BiosKeyboardPrivate
,
1113 KBC_CMDREG_VIA64_KB_DISABLE
1116 if (EFI_ERROR (Status
)) {
1117 Status
= EFI_DEVICE_ERROR
;
1126 // Report a Progress Code for performing a self test on the keyboard controller
1128 REPORT_STATUS_CODE (
1130 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_SELF_TEST
1133 Status
= KeyboardCommand (
1134 BiosKeyboardPrivate
,
1135 KBC_CMDREG_VIA64_KBC_SLFTEST
1137 if (EFI_ERROR (Status
)) {
1138 Status
= EFI_DEVICE_ERROR
;
1142 Status
= KeyboardWaitForValue (
1143 BiosKeyboardPrivate
,
1144 KBC_CMDECHO_KBCSLFTEST_OK
,
1145 KEYBOARD_WAITFORVALUE_TIMEOUT
1147 if (EFI_ERROR (Status
)) {
1148 Status
= EFI_DEVICE_ERROR
;
1155 // Disable Mouse interface, enable Keyboard interface and declare selftest success
1157 // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.
1159 Status
= KeyboardCommand (
1160 BiosKeyboardPrivate
,
1161 KBC_CMDREG_VIA64_CMDBYTE_W
1164 if (EFI_ERROR (Status
)) {
1165 Status
= EFI_DEVICE_ERROR
;
1170 // Write 8042 Command Byte, set System Flag
1171 // While at the same time:
1172 // 1. disable mouse interface,
1173 // 2. enable kbd interface,
1174 // 3. enable PC/XT kbd translation mode
1175 // 4. enable mouse and kbd interrupts
1177 //Command Byte bits:
1179 // 6: PC/XT translation mode
1180 // 5: Disable Auxiliary device interface
1181 // 4: Disable keyboard interface
1184 // 1: Enable Auxiliary device interrupt
1185 // 0: Enable Keyboard interrupt
1188 Status
= KeyboardWrite (
1189 BiosKeyboardPrivate
,
1190 (UINT8
) ((CommandByte
&
1191 (~KB_CMMBYTE_DISABLE_KB
)) |
1192 KB_CMMBYTE_KSCAN2UNI_COV
|
1193 KB_CMMBYTE_ENABLE_AUXINT
|
1194 KB_CMMBYTE_ENABLE_KBINT
|
1195 KB_CMMBYTE_SLFTEST_SUCC
|
1196 KB_CMMBYTE_DISABLE_AUX
)
1200 // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1201 // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.
1202 // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
1203 // Real reset will not do.
1205 if (ExtendedVerification
&& CheckKeyboardConnect (BiosKeyboardPrivate
)) {
1208 // Send keyboard reset command then read ACK
1210 Status
= KeyboardWrite (
1211 BiosKeyboardPrivate
,
1212 KBC_INPBUF_VIA60_KBRESET
1215 if (EFI_ERROR (Status
)) {
1216 Status
= EFI_DEVICE_ERROR
;
1220 Status
= KeyboardWaitForValue (
1221 BiosKeyboardPrivate
,
1223 KEYBOARD_WAITFORVALUE_TIMEOUT
1226 if (EFI_ERROR (Status
)) {
1227 Status
= EFI_DEVICE_ERROR
;
1232 // Wait for keyboard return test OK.
1234 Status
= KeyboardWaitForValue (
1235 BiosKeyboardPrivate
,
1236 KBC_CMDECHO_BATTEST_OK
,
1237 KEYBOARD_WAITFORVALUE_TIMEOUT
1240 if (EFI_ERROR (Status
)) {
1241 Status
= EFI_DEVICE_ERROR
;
1246 // set keyboard scan code set = 02 (standard configuration)
1248 Status
= KeyboardWrite (
1249 BiosKeyboardPrivate
,
1250 KBC_INPBUF_VIA60_KBSCODE
1252 if (EFI_ERROR (Status
)) {
1253 Status
= EFI_DEVICE_ERROR
;
1257 Status
= KeyboardWaitForValue (
1258 BiosKeyboardPrivate
,
1260 KEYBOARD_WAITFORVALUE_TIMEOUT
1263 if (EFI_ERROR (Status
)) {
1264 Status
= EFI_DEVICE_ERROR
;
1268 Status
= KeyboardWrite (
1269 BiosKeyboardPrivate
,
1270 KBC_INPBUF_VIA60_SCODESET2
1272 if (EFI_ERROR (Status
)) {
1273 Status
= EFI_DEVICE_ERROR
;
1277 Status
= KeyboardWaitForValue (
1278 BiosKeyboardPrivate
,
1280 KEYBOARD_WAITFORVALUE_TIMEOUT
1283 if (EFI_ERROR (Status
)) {
1284 Status
= EFI_DEVICE_ERROR
;
1289 // enable keyboard itself (not via KBC) by writing CMD F4 via 60H
1291 Status
= KeyboardWrite (
1292 BiosKeyboardPrivate
,
1293 KBC_INPBUF_VIA60_KBEN
1295 if (EFI_ERROR (Status
)) {
1296 Status
= EFI_DEVICE_ERROR
;
1300 Status
= KeyboardWaitForValue (
1301 BiosKeyboardPrivate
,
1303 KEYBOARD_WAITFORVALUE_TIMEOUT
1306 if (EFI_ERROR (Status
)) {
1307 Status
= EFI_DEVICE_ERROR
;
1312 // Additional validation, do it as follow:
1313 // 1). check for status register of PARE && TIM via 64H
1314 // 2). perform KB checking by writing ABh via 64H
1316 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & (KBC_STSREG_VIA64_PARE
| KBC_STSREG_VIA64_TIM
)) != 0) {
1317 Status
= EFI_DEVICE_ERROR
;
1321 Status
= KeyboardCommand (
1322 BiosKeyboardPrivate
,
1323 KBC_CMDREG_VIA64_KB_CKECK
1325 if (EFI_ERROR (Status
)) {
1326 Status
= EFI_DEVICE_ERROR
;
1330 Status
= KeyboardWaitForValue (
1331 BiosKeyboardPrivate
,
1332 KBC_CMDECHO_KBCHECK_OK
,
1333 KEYBOARD_WAITFORVALUE_TIMEOUT
1336 if (EFI_ERROR (Status
)) {
1337 Status
= EFI_DEVICE_ERROR
;
1343 // Done for validating keyboard. Enable keyboard (via KBC)
1344 // and recover the command byte to proper value
1346 if (!PcdGetBool (PcdFastPS2Detection
)) {
1347 Status
= KeyboardCommand (
1348 BiosKeyboardPrivate
,
1349 KBC_CMDREG_VIA64_KB_ENABLE
1352 if (EFI_ERROR (Status
)) {
1353 Status
= EFI_DEVICE_ERROR
;
1360 // conditionally enable mouse (via KBC)
1363 Status
= KeyboardCommand (
1364 BiosKeyboardPrivate
,
1365 KBC_CMDREG_VIA64_AUX_ENABLE
1368 if (EFI_ERROR (Status
)) {
1369 Status
= EFI_DEVICE_ERROR
;
1377 // resume priority of task level
1379 gBS
->RestoreTPL (OldTpl
);
1386 Read out the scan code of the key that has just been stroked.
1388 @param This Pointer of simple text Protocol.
1389 @param Key Pointer for store the key that read out.
1391 @retval EFI_SUCCESS The key is read out successfully.
1392 @retval other The key reading failed.
1397 BiosKeyboardReadKeyStroke (
1398 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
1399 OUT EFI_INPUT_KEY
*Key
1402 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1404 EFI_KEY_DATA KeyData
;
1406 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1408 Status
= KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate
, &KeyData
);
1409 if (EFI_ERROR (Status
)) {
1414 // Convert the Ctrl+[a-z] to Ctrl+[1-26]
1416 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
1417 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
1418 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
1419 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
1420 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
1424 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
1430 Waiting on the keyboard event, if there's any key pressed by the user, signal the event
1432 @param Event The event that be siganlled when any key has been stroked.
1433 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1438 BiosKeyboardWaitForKey (
1444 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
1445 // Csm will be used to check whether there is a key pending, but the csm will disable all
1446 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
1447 // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
1448 // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,
1449 // e.g. usb keyboard driver.
1450 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
1451 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
1455 // Use TimerEvent callback function to check whether there's any key pressed
1457 BiosKeyboardTimerHandler (NULL
, BIOS_KEYBOARD_DEV_FROM_THIS (Context
));
1459 if (!EFI_ERROR (BiosKeyboardCheckForKey (Context
))) {
1460 gBS
->SignalEvent (Event
);
1465 Check key buffer to get the key stroke status.
1467 @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
1469 @retval EFI_SUCCESS A key is being pressed now.
1470 @retval Other No key is now pressed.
1475 BiosKeyboardCheckForKey (
1476 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
1479 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1481 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1483 return CheckQueue (&BiosKeyboardPrivate
->Queue
);
1486 // Private worker functions
1488 #define TABLE_END 0x0
1490 typedef struct _CONVERT_TABLE_ENTRY
{
1493 } CONVERT_TABLE_ENTRY
;
1495 CONVERT_TABLE_ENTRY mConvertTable
[] = {
1537 // Function Keys are only valid if KeyChar == 0x00
1538 // This function does not require KeyChar to be 0x00
1589 // Convert ALT + Fn keys
1638 Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.
1640 @param KeyChar Unicode of key.
1641 @param ScanCode Scan code of key.
1643 @return The value of EFI Scancode for the key.
1644 @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.
1648 ConvertToEFIScanCode (
1656 if (KeyChar
== CHAR_ESC
) {
1657 EfiScanCode
= SCAN_ESC
;
1658 } else if (KeyChar
== 0x00 || KeyChar
== 0xe0) {
1660 // Movement & Function Keys
1662 for (Index
= 0; (Index
< sizeof (mConvertTable
) / sizeof (CONVERT_TABLE_ENTRY
)) && (mConvertTable
[Index
].ScanCode
!= TABLE_END
); Index
+= 1) {
1663 if (ScanCode
== mConvertTable
[Index
].ScanCode
) {
1664 return mConvertTable
[Index
].EfiScanCode
;
1668 // Reach Table end, return default value
1679 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
1680 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
1681 should not be in system.
1683 @param BiosKeyboardPrivate Keyboard Private Data Struture
1685 @retval TRUE Keyboard in System.
1686 @retval FALSE Keyboard not in System.
1690 CheckKeyboardConnect (
1691 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
1696 Status
= EFI_SUCCESS
;
1698 // enable keyboard itself and wait for its ack
1699 // If can't receive ack, Keyboard should not be connected.
1701 if (!PcdGetBool (PcdFastPS2Detection
)) {
1702 Status
= KeyboardWrite (
1703 BiosKeyboardPrivate
,
1704 KBC_INPBUF_VIA60_KBEN
1706 if (EFI_ERROR (Status
)) {
1707 DEBUG ((EFI_D_ERROR
, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));
1708 REPORT_STATUS_CODE (
1709 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1710 EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
1715 Status
= KeyboardWaitForValue (
1716 BiosKeyboardPrivate
,
1718 KEYBOARD_WAITFORVALUE_TIMEOUT
1721 if (EFI_ERROR (Status
)) {
1722 DEBUG ((EFI_D_ERROR
, "[KBD]CheckKeyboardConnect - Timeout!\n"));
1723 REPORT_STATUS_CODE (
1724 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1725 EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
1736 Timer event handler: read a series of key stroke from 8042
1737 and put them into memory key buffer.
1738 It is registered as running under TPL_NOTIFY
1740 @param Event The timer event
1741 @param Context A BIOS_KEYBOARD_DEV pointer
1746 BiosKeyboardTimerHandler (
1752 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1753 EFI_IA32_REGISTER_SET Regs
;
1754 UINT8 KbFlag1
; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1
1755 UINT8 KbFlag2
; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2
1756 EFI_KEY_DATA KeyData
;
1758 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1760 BiosKeyboardPrivate
= Context
;
1763 // Enter critical section
1765 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1768 // if there is no key present, just return
1770 if (BiosKeyboardPrivate
->ExtendedKeyboard
) {
1776 BiosKeyboardPrivate
->LegacyBios
->Int86 (
1777 BiosKeyboardPrivate
->LegacyBios
,
1781 if (Regs
.X
.Flags
.ZF
!= 0) {
1782 gBS
->RestoreTPL (OldTpl
);
1789 if (BiosKeyboardPrivate
->ExtendedKeyboard
) {
1795 BiosKeyboardPrivate
->LegacyBios
->Int86 (
1796 BiosKeyboardPrivate
->LegacyBios
,
1801 KeyData
.Key
.ScanCode
= (UINT16
) Regs
.H
.AH
;
1802 KeyData
.Key
.UnicodeChar
= (UINT16
) Regs
.H
.AL
;
1805 "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
1806 KeyData
.Key
.ScanCode
,
1807 KeyData
.Key
.UnicodeChar
1810 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
1811 KeyData
.KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
1813 // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then
1814 // 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
1815 // 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
1816 // 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
1817 // 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
1818 // 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
1819 // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other drivers
1820 // performance, like USB.
1822 // 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
1823 // 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
1824 // 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
1827 // 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
1828 // 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,
1829 // which will let persist to press SHIFT has same effection as only press one time.
1831 //0040h:0017h - KEYBOARD - STATUS FLAGS 1
1833 // 6 Caps Lock active
1834 // 5 Num Lock active
1835 // 4 Scroll Lock active
1836 // 3 either Alt pressed
1837 // 2 either Ctrl pressed
1838 // 1 Left Shift pressed
1839 // 0 Right Shift pressed
1843 // Clear the CTRL and ALT BDA flag
1845 KbFlag1
= *((UINT8
*) (UINTN
) 0x417); // read the STATUS FLAGS 1
1846 KbFlag2
= *((UINT8
*) (UINTN
) 0x418); // read STATUS FLAGS 2
1850 if ((KbFlag1
& KB_CAPS_LOCK_BIT
) == KB_CAPS_LOCK_BIT
) {
1851 DEBUG ((EFI_D_INFO
, "[KBD]Caps Lock Key is pressed.\n"));
1853 if ((KbFlag1
& KB_NUM_LOCK_BIT
) == KB_NUM_LOCK_BIT
) {
1854 DEBUG ((EFI_D_INFO
, "[KBD]Num Lock Key is pressed.\n"));
1856 if ((KbFlag1
& KB_SCROLL_LOCK_BIT
) == KB_SCROLL_LOCK_BIT
) {
1857 DEBUG ((EFI_D_INFO
, "[KBD]Scroll Lock Key is pressed.\n"));
1859 if ((KbFlag1
& KB_ALT_PRESSED
) == KB_ALT_PRESSED
) {
1860 if ((KbFlag2
& KB_LEFT_ALT_PRESSED
) == KB_LEFT_ALT_PRESSED
) {
1861 DEBUG ((EFI_D_INFO
, "[KBD]Left Alt Key is pressed.\n"));
1863 DEBUG ((EFI_D_INFO
, "[KBD]Right Alt Key is pressed.\n"));
1866 if ((KbFlag1
& KB_CTRL_PRESSED
) == KB_CTRL_PRESSED
) {
1867 if ((KbFlag2
& KB_LEFT_CTRL_PRESSED
) == KB_LEFT_CTRL_PRESSED
) {
1868 DEBUG ((EFI_D_INFO
, "[KBD]Left Ctrl Key is pressed.\n"));
1870 DEBUG ((EFI_D_INFO
, "[KBD]Right Ctrl Key is pressed.\n"));
1873 if ((KbFlag1
& KB_LEFT_SHIFT_PRESSED
) == KB_LEFT_SHIFT_PRESSED
) {
1874 DEBUG ((EFI_D_INFO
, "[KBD]Left Shift Key is pressed.\n"));
1876 if ((KbFlag1
& KB_RIGHT_SHIFT_PRESSED
) == KB_RIGHT_SHIFT_PRESSED
) {
1877 DEBUG ((EFI_D_INFO
, "[KBD]Right Shift Key is pressed.\n"));
1883 // Record toggle state
1885 if ((KbFlag1
& KB_CAPS_LOCK_BIT
) == KB_CAPS_LOCK_BIT
) {
1886 KeyData
.KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1888 if ((KbFlag1
& KB_NUM_LOCK_BIT
) == KB_NUM_LOCK_BIT
) {
1889 KeyData
.KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1891 if ((KbFlag1
& KB_SCROLL_LOCK_BIT
) == KB_SCROLL_LOCK_BIT
) {
1892 KeyData
.KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1895 // Record shift state
1896 // BUGBUG: Need add Menu key and Left/Right Logo key state in the future
1898 if ((KbFlag1
& KB_ALT_PRESSED
) == KB_ALT_PRESSED
) {
1899 KeyData
.KeyState
.KeyShiftState
|= ((KbFlag2
& KB_LEFT_ALT_PRESSED
) == KB_LEFT_ALT_PRESSED
) ? EFI_LEFT_ALT_PRESSED
: EFI_RIGHT_ALT_PRESSED
;
1901 if ((KbFlag1
& KB_CTRL_PRESSED
) == KB_CTRL_PRESSED
) {
1902 KeyData
.KeyState
.KeyShiftState
|= ((KbFlag2
& KB_LEFT_CTRL_PRESSED
) == KB_LEFT_CTRL_PRESSED
) ? EFI_LEFT_CONTROL_PRESSED
: EFI_RIGHT_CONTROL_PRESSED
;
1904 if ((KbFlag1
& KB_LEFT_SHIFT_PRESSED
) == KB_LEFT_SHIFT_PRESSED
) {
1905 KeyData
.KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1907 if ((KbFlag1
& KB_RIGHT_SHIFT_PRESSED
) == KB_RIGHT_SHIFT_PRESSED
) {
1908 KeyData
.KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1912 // Clear left alt and left ctrl BDA flag
1914 KbFlag2
&= ~(KB_LEFT_ALT_PRESSED
| KB_LEFT_CTRL_PRESSED
);
1915 *((UINT8
*) (UINTN
) 0x418) = KbFlag2
;
1917 *((UINT8
*) (UINTN
) 0x417) = KbFlag1
;
1921 // Output EFI input key and shift/toggle state
1923 if (KeyData
.Key
.UnicodeChar
== CHAR_NULL
|| KeyData
.Key
.UnicodeChar
== CHAR_SCANCODE
|| KeyData
.Key
.UnicodeChar
== CHAR_ESC
) {
1924 KeyData
.Key
.ScanCode
= ConvertToEFIScanCode (KeyData
.Key
.UnicodeChar
, KeyData
.Key
.ScanCode
);
1925 KeyData
.Key
.UnicodeChar
= CHAR_NULL
;
1927 KeyData
.Key
.ScanCode
= SCAN_NULL
;
1931 // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.
1933 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
1934 if (KeyData
.Key
.UnicodeChar
>= 1 && KeyData
.Key
.UnicodeChar
<= 26) {
1935 if (((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ==
1936 ((KeyData
.KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0)
1938 KeyData
.Key
.UnicodeChar
= (UINT16
) (KeyData
.Key
.UnicodeChar
+ L
'a' - 1);
1940 KeyData
.Key
.UnicodeChar
= (UINT16
) (KeyData
.Key
.UnicodeChar
+ L
'A' - 1);
1947 "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
1948 KeyData
.Key
.ScanCode
,
1949 KeyData
.Key
.UnicodeChar
1953 // Need not return associated shift state if a class of printable characters that
1954 // are normally adjusted by shift modifiers.
1955 // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.
1957 if ((KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') ||
1958 (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z')
1960 DEBUG ((EFI_D_INFO
, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));
1961 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
1965 // Signal KeyNotify process event if this key pressed matches any key registered.
1967 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
1968 CurrentNotify
= CR (
1970 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1972 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1974 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1976 // The key notification function needs to run at TPL_CALLBACK
1977 // while current TPL is TPL_NOTIFY. It will be invoked in
1978 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
1980 Enqueue (&BiosKeyboardPrivate
->QueueForNotify
, &KeyData
);
1981 gBS
->SignalEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
1985 Enqueue (&BiosKeyboardPrivate
->Queue
, &KeyData
);
1987 // Leave critical section and return
1989 gBS
->RestoreTPL (OldTpl
);
1997 @param Event Indicates the event that invoke this function.
1998 @param Context Indicates the calling context.
2002 KeyNotifyProcessHandler (
2008 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2009 EFI_KEY_DATA KeyData
;
2011 LIST_ENTRY
*NotifyList
;
2012 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2015 BiosKeyboardPrivate
= (BIOS_KEYBOARD_DEV
*) Context
;
2018 // Invoke notification functions.
2020 NotifyList
= &BiosKeyboardPrivate
->NotifyList
;
2023 // Enter critical section
2025 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2026 Status
= Dequeue (&BiosKeyboardPrivate
->QueueForNotify
, &KeyData
);
2028 // Leave critical section
2030 gBS
->RestoreTPL (OldTpl
);
2031 if (EFI_ERROR (Status
)) {
2034 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
2035 CurrentNotify
= CR (Link
, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
2036 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
2037 CurrentNotify
->KeyNotificationFn (&KeyData
);
2044 Free keyboard notify list.
2046 @param ListHead The list head
2048 @retval EFI_SUCCESS Free the notify list successfully
2049 @retval EFI_INVALID_PARAMETER ListHead is invalid.
2053 BiosKeyboardFreeNotifyList (
2054 IN OUT LIST_ENTRY
*ListHead
2057 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
2059 if (ListHead
== NULL
) {
2060 return EFI_INVALID_PARAMETER
;
2062 while (!IsListEmpty (ListHead
)) {
2064 ListHead
->ForwardLink
,
2065 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2067 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2069 RemoveEntryList (ListHead
->ForwardLink
);
2070 gBS
->FreePool (NotifyNode
);
2077 Check if key is registered.
2079 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
2080 state data for the key that was registered.
2081 @param InputData A pointer to a buffer that is filled in with the keystroke
2082 state data for the key that was pressed.
2084 @retval TRUE Key be pressed matches a registered key.
2085 @retval FLASE Match failed.
2090 IN EFI_KEY_DATA
*RegsiteredData
,
2091 IN EFI_KEY_DATA
*InputData
2094 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
2096 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
2097 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
2102 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
2104 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
2105 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
2108 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
2109 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
2118 Waiting on the keyboard event, if there's any key pressed by the user, signal the event
2120 @param Event The event that be siganlled when any key has been stroked.
2121 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
2126 BiosKeyboardWaitForKeyEx (
2131 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2133 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context
);
2134 BiosKeyboardWaitForKey (Event
, &BiosKeyboardPrivate
->SimpleTextIn
);
2139 Reset the input device and optionaly run diagnostics
2141 @param This Protocol instance pointer.
2142 @param ExtendedVerification Driver may perform diagnostics on reset.
2144 @retval EFI_SUCCESS The device was reset.
2145 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
2151 BiosKeyboardResetEx (
2152 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2153 IN BOOLEAN ExtendedVerification
2156 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2160 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2162 Status
= BiosKeyboardPrivate
->SimpleTextIn
.Reset (
2163 &BiosKeyboardPrivate
->SimpleTextIn
,
2164 ExtendedVerification
2166 if (EFI_ERROR (Status
)) {
2167 return EFI_DEVICE_ERROR
;
2170 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2172 gBS
->RestoreTPL (OldTpl
);
2179 Reads the next keystroke from the input device. The WaitForKey Event can
2180 be used to test for existance of a keystroke via WaitForEvent () call.
2182 @param This Protocol instance pointer.
2183 @param KeyData A pointer to a buffer that is filled in with the keystroke
2184 state data for the key that was pressed.
2186 @retval EFI_SUCCESS The keystroke information was returned.
2187 @retval EFI_NOT_READY There was no keystroke data availiable.
2188 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
2190 @retval EFI_INVALID_PARAMETER KeyData is NULL.
2195 BiosKeyboardReadKeyStrokeEx (
2196 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2197 OUT EFI_KEY_DATA
*KeyData
2200 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2202 if (KeyData
== NULL
) {
2203 return EFI_INVALID_PARAMETER
;
2206 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2208 return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate
, KeyData
);
2213 Set certain state for the input device.
2215 @param This Protocol instance pointer.
2216 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
2217 state for the input device.
2219 @retval EFI_SUCCESS The device state was set successfully.
2220 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
2221 not have the setting adjusted.
2222 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
2223 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
2228 BiosKeyboardSetState (
2229 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2230 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
2234 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2236 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
2239 if (KeyToggleState
== NULL
) {
2240 return EFI_INVALID_PARAMETER
;
2244 // Thunk keyboard driver doesn't support partial keystroke.
2246 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
||
2247 (*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
2249 return EFI_UNSUPPORTED
;
2252 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2254 // See if the Legacy BIOS Protocol is available
2256 Status
= gBS
->LocateProtocol (
2257 &gEfiLegacyBiosProtocolGuid
,
2259 (VOID
**) &LegacyBios
2262 ASSERT_EFI_ERROR (Status
);
2264 // Enter critical section
2266 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2269 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
2272 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
2275 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
2279 Status
= KeyboardWrite (BiosKeyboardPrivate
, 0xed);
2280 if (EFI_ERROR (Status
)) {
2281 Status
= EFI_DEVICE_ERROR
;
2284 Status
= KeyboardWaitForValue (BiosKeyboardPrivate
, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT
);
2285 if (EFI_ERROR (Status
)) {
2286 Status
= EFI_DEVICE_ERROR
;
2289 Status
= KeyboardWrite (BiosKeyboardPrivate
, Command
);
2290 if (EFI_ERROR (Status
)) {
2291 Status
= EFI_DEVICE_ERROR
;
2295 // Call Legacy BIOS Protocol to set whatever is necessary
2297 LegacyBios
->UpdateKeyboardLedStatus (LegacyBios
, Command
);
2299 Status
= EFI_SUCCESS
;
2303 // Leave critical section and return
2305 gBS
->RestoreTPL (OldTpl
);
2312 Register a notification function for a particular keystroke for the input device.
2314 @param This Protocol instance pointer.
2315 @param KeyData A pointer to a buffer that is filled in with the keystroke
2316 information data for the key that was pressed.
2317 @param KeyNotificationFunction Points to the function to be called when the key
2318 sequence is typed specified by KeyData.
2319 @param NotifyHandle Points to the unique handle assigned to the registered notification.
2322 @retval EFI_SUCCESS The notification function was registered successfully.
2323 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
2324 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
2329 BiosKeyboardRegisterKeyNotify (
2330 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2331 IN EFI_KEY_DATA
*KeyData
,
2332 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
2333 OUT VOID
**NotifyHandle
2337 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2339 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
2341 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2343 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
2344 return EFI_INVALID_PARAMETER
;
2347 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2350 // Enter critical section
2352 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2355 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
2357 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
2358 CurrentNotify
= CR (
2360 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2362 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2364 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
2365 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
2366 *NotifyHandle
= CurrentNotify
;
2367 Status
= EFI_SUCCESS
;
2374 // Allocate resource to save the notification function
2377 NewNotify
= (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
2378 if (NewNotify
== NULL
) {
2379 Status
= EFI_OUT_OF_RESOURCES
;
2383 NewNotify
->Signature
= BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
2384 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
2385 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
2386 InsertTailList (&BiosKeyboardPrivate
->NotifyList
, &NewNotify
->NotifyEntry
);
2388 *NotifyHandle
= NewNotify
;
2389 Status
= EFI_SUCCESS
;
2393 // Leave critical section and return
2395 gBS
->RestoreTPL (OldTpl
);
2400 Remove a registered notification function from a particular keystroke.
2402 @param This Protocol instance pointer.
2403 @param NotificationHandle The handle of the notification function being unregistered.
2405 @retval EFI_SUCCESS The notification function was unregistered successfully.
2406 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
2411 BiosKeyboardUnregisterKeyNotify (
2412 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2413 IN VOID
*NotificationHandle
2417 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2420 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2423 // Check incoming notification handle
2425 if (NotificationHandle
== NULL
) {
2426 return EFI_INVALID_PARAMETER
;
2429 if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
2430 return EFI_INVALID_PARAMETER
;
2433 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2436 // Enter critical section
2438 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2440 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
2441 CurrentNotify
= CR (
2443 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2445 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2447 if (CurrentNotify
== NotificationHandle
) {
2449 // Remove the notification function from NotifyList and free resources
2451 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
2453 Status
= EFI_SUCCESS
;
2459 // Can not find the specified Notification Handle
2461 Status
= EFI_INVALID_PARAMETER
;
2465 // Leave critical section and return
2467 gBS
->RestoreTPL (OldTpl
);
2472 The user Entry Point for module BiosKeyboard. The user code starts with this function.
2474 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2475 @param[in] SystemTable A pointer to the EFI System Table.
2477 @retval EFI_SUCCESS The entry point is executed successfully.
2478 @retval other Some error occurs when executing this entry point.
2483 InitializeBiosKeyboard(
2484 IN EFI_HANDLE ImageHandle
,
2485 IN EFI_SYSTEM_TABLE
*SystemTable
2491 // Install driver model protocol(s).
2493 Status
= EfiLibInstallDriverBindingComponentName2 (
2496 &gBiosKeyboardDriverBinding
,
2498 &gBiosKeyboardComponentName
,
2499 &gBiosKeyboardComponentName2
2501 ASSERT_EFI_ERROR (Status
);