2 ConsoleOut Routines that speak VGA.
4 Copyright (c) 2006 - 2018, 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
->KeyState
.KeyShiftState
= 0;
274 BiosKeyboardPrivate
->KeyState
.KeyToggleState
= 0;
275 BiosKeyboardPrivate
->Queue
.Front
= 0;
276 BiosKeyboardPrivate
->Queue
.Rear
= 0;
277 BiosKeyboardPrivate
->QueueForNotify
.Front
= 0;
278 BiosKeyboardPrivate
->QueueForNotify
.Rear
= 0;
279 BiosKeyboardPrivate
->SimpleTextInputEx
.Reset
= BiosKeyboardResetEx
;
280 BiosKeyboardPrivate
->SimpleTextInputEx
.ReadKeyStrokeEx
= BiosKeyboardReadKeyStrokeEx
;
281 BiosKeyboardPrivate
->SimpleTextInputEx
.SetState
= BiosKeyboardSetState
;
282 BiosKeyboardPrivate
->SimpleTextInputEx
.RegisterKeyNotify
= BiosKeyboardRegisterKeyNotify
;
283 BiosKeyboardPrivate
->SimpleTextInputEx
.UnregisterKeyNotify
= BiosKeyboardUnregisterKeyNotify
;
284 InitializeListHead (&BiosKeyboardPrivate
->NotifyList
);
287 // Report that the keyboard is being enabled
291 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
295 // Setup the WaitForKey event
297 Status
= gBS
->CreateEvent (
300 BiosKeyboardWaitForKey
,
301 &(BiosKeyboardPrivate
->SimpleTextIn
),
302 &((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
)
304 if (EFI_ERROR (Status
)) {
305 (BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
= NULL
;
308 Status
= gBS
->CreateEvent (
311 BiosKeyboardWaitForKeyEx
,
312 &(BiosKeyboardPrivate
->SimpleTextInputEx
),
313 &(BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
)
315 if (EFI_ERROR (Status
)) {
316 BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
= NULL
;
321 // Setup a periodic timer, used for reading keystrokes at a fixed interval
323 Status
= gBS
->CreateEvent (
324 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
326 BiosKeyboardTimerHandler
,
328 &BiosKeyboardPrivate
->TimerEvent
330 if (EFI_ERROR (Status
)) {
331 Status
= EFI_OUT_OF_RESOURCES
;
332 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
336 Status
= gBS
->SetTimer (
337 BiosKeyboardPrivate
->TimerEvent
,
339 KEYBOARD_TIMER_INTERVAL
341 if (EFI_ERROR (Status
)) {
342 Status
= EFI_OUT_OF_RESOURCES
;
343 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
347 Status
= gBS
->CreateEvent (
350 KeyNotifyProcessHandler
,
352 &BiosKeyboardPrivate
->KeyNotifyProcessEvent
354 if (EFI_ERROR (Status
)) {
355 Status
= EFI_OUT_OF_RESOURCES
;
356 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
;
361 // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system
365 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
369 // Reset the keyboard device
371 Status
= BiosKeyboardPrivate
->SimpleTextInputEx
.Reset (
372 &BiosKeyboardPrivate
->SimpleTextInputEx
,
373 FeaturePcdGet (PcdPs2KbdExtendedVerification
)
375 if (EFI_ERROR (Status
)) {
376 DEBUG ((EFI_D_ERROR
, "[KBD]Reset Failed. Status - %r\n", Status
));
377 StatusCode
= EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
;
381 // Do platform specific policy like port swapping and keyboard light default
383 if (Ps2Policy
!= NULL
) {
385 Ps2Policy
->Ps2InitHardware (Controller
);
388 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_CAPSLOCK
) == EFI_KEYBOARD_CAPSLOCK
) {
392 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_NUMLOCK
) == EFI_KEYBOARD_NUMLOCK
) {
396 if ((Ps2Policy
->KeyboardLight
& EFI_KEYBOARD_SCROLLLOCK
) == EFI_KEYBOARD_SCROLLLOCK
) {
400 KeyboardWrite (BiosKeyboardPrivate
, 0xed);
401 KeyboardWaitForValue (BiosKeyboardPrivate
, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT
);
402 KeyboardWrite (BiosKeyboardPrivate
, Command
);
404 // Call Legacy BIOS Protocol to set whatever is necessary
406 LegacyBios
->UpdateKeyboardLedStatus (LegacyBios
, Command
);
412 CarryFlag
= BiosKeyboardPrivate
->LegacyBios
->Int86 (
413 BiosKeyboardPrivate
->LegacyBios
,
420 // Check bit 6 of Feature Byte 2.
421 // If it is set, then Int 16 Func 09 is supported
423 if (*(UINT8
*) (((UINTN
) Regs
.X
.ES
<< 4) + Regs
.X
.BX
+ 0x06) & 0x40) {
425 // Get Keyboard Functionality
428 CarryFlag
= BiosKeyboardPrivate
->LegacyBios
->Int86 (
429 BiosKeyboardPrivate
->LegacyBios
,
436 // Check bit 5 of AH.
437 // If it is set, then INT 16 Finc 10-12 are supported.
439 if ((Regs
.H
.AL
& 0x40) != 0) {
441 // Set the flag to use INT 16 Func 10-12
443 BiosKeyboardPrivate
->ExtendedKeyboard
= TRUE
;
448 DEBUG ((EFI_D_INFO
, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN
)BiosKeyboardPrivate
->ExtendedKeyboard
));
450 // Install protocol interfaces for the keyboard device.
452 Status
= gBS
->InstallMultipleProtocolInterfaces (
454 &gEfiSimpleTextInProtocolGuid
,
455 &BiosKeyboardPrivate
->SimpleTextIn
,
456 &gEfiSimpleTextInputExProtocolGuid
,
457 &BiosKeyboardPrivate
->SimpleTextInputEx
,
462 if (StatusCode
!= 0) {
464 // Report an Error Code for failing to start the keyboard device
467 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
472 if (EFI_ERROR (Status
)) {
474 if (BiosKeyboardPrivate
!= NULL
) {
475 if ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
!= NULL
) {
476 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
);
479 if ((BiosKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
!= NULL
) {
480 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
);
483 if (BiosKeyboardPrivate
->KeyNotifyProcessEvent
!= NULL
) {
484 gBS
->CloseEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
487 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate
->NotifyList
);
489 if (BiosKeyboardPrivate
->TimerEvent
!= NULL
) {
490 gBS
->CloseEvent (BiosKeyboardPrivate
->TimerEvent
);
493 FreePool (BiosKeyboardPrivate
);
499 &gEfiIsaIoProtocolGuid
,
500 This
->DriverBindingHandle
,
510 Stop the device handled by this driver.
512 @param This The driver binding protocol.
513 @param Controller The controller to release.
514 @param NumberOfChildren The number of handles in ChildHandleBuffer.
515 @param ChildHandleBuffer The array of child handle.
517 @retval EFI_SUCCESS The device was stopped.
518 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
519 @retval Others Fail to uninstall protocols attached on the device.
524 BiosKeyboardDriverBindingStop (
525 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
526 IN EFI_HANDLE Controller
,
527 IN UINTN NumberOfChildren
,
528 IN EFI_HANDLE
*ChildHandleBuffer
532 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleTextIn
;
533 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
538 Status
= gBS
->OpenProtocol (
540 &gEfiSimpleTextInProtocolGuid
,
541 (VOID
**) &SimpleTextIn
,
542 This
->DriverBindingHandle
,
544 EFI_OPEN_PROTOCOL_GET_PROTOCOL
546 if (EFI_ERROR (Status
)) {
550 Status
= gBS
->OpenProtocol (
552 &gEfiSimpleTextInputExProtocolGuid
,
554 This
->DriverBindingHandle
,
556 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
558 if (EFI_ERROR (Status
)) {
562 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn
);
564 Status
= gBS
->UninstallMultipleProtocolInterfaces (
566 &gEfiSimpleTextInProtocolGuid
,
567 &BiosKeyboardPrivate
->SimpleTextIn
,
568 &gEfiSimpleTextInputExProtocolGuid
,
569 &BiosKeyboardPrivate
->SimpleTextInputEx
,
572 if (EFI_ERROR (Status
)) {
576 // Release the IsaIo protocol on the controller handle
580 &gEfiIsaIoProtocolGuid
,
581 This
->DriverBindingHandle
,
586 // Free other resources
588 gBS
->CloseEvent ((BiosKeyboardPrivate
->SimpleTextIn
).WaitForKey
);
589 gBS
->CloseEvent (BiosKeyboardPrivate
->TimerEvent
);
590 gBS
->CloseEvent (BiosKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
);
591 gBS
->CloseEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
592 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate
->NotifyList
);
594 FreePool (BiosKeyboardPrivate
);
600 Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.
602 @param BiosKeyboardPrivate Keyboard instance pointer.
604 @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.
608 KeyReadDataRegister (
609 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
615 // Use IsaIo protocol to perform IO operations
617 BiosKeyboardPrivate
->IsaIo
->Io
.Read (
618 BiosKeyboardPrivate
->IsaIo
,
620 BiosKeyboardPrivate
->DataRegisterAddress
,
629 Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.
631 @param BiosKeyboardPrivate Keyboard instance pointer.
633 @return The status byte read from status register of Keyboard Controller from command port which often is port 64H.
637 KeyReadStatusRegister (
638 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
644 // Use IsaIo protocol to perform IO operations
646 BiosKeyboardPrivate
->IsaIo
->Io
.Read (
647 BiosKeyboardPrivate
->IsaIo
,
649 BiosKeyboardPrivate
->StatusRegisterAddress
,
658 Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.
660 @param BiosKeyboardPrivate Keyboard instance pointer.
661 @param Data Data byte to write.
665 KeyWriteCommandRegister (
666 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
671 // Use IsaIo protocol to perform IO operations
673 BiosKeyboardPrivate
->IsaIo
->Io
.Write (
674 BiosKeyboardPrivate
->IsaIo
,
676 BiosKeyboardPrivate
->CommandRegisterAddress
,
683 Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.
685 @param BiosKeyboardPrivate Keyboard instance pointer.
686 @param Data Data byte to write.
690 KeyWriteDataRegister (
691 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
696 // Use IsaIo protocol to perform IO operations
698 BiosKeyboardPrivate
->IsaIo
->Io
.Write (
699 BiosKeyboardPrivate
->IsaIo
,
701 BiosKeyboardPrivate
->DataRegisterAddress
,
708 Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.
710 @param BiosKeyboardPrivate Keyboard instance pointer.
711 @param Data The pointer for data that being read out.
713 @retval EFI_SUCCESS The data byte read out successfully.
714 @retval EFI_TIMEOUT Timeout occurred during reading out data byte.
719 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
730 // wait till output buffer full then perform the read
732 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
733 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_OUTB
) != 0) {
735 *Data
= KeyReadDataRegister (BiosKeyboardPrivate
);
742 if (RegFilled
== 0) {
750 Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.
752 @param BiosKeyboardPrivate Keyboard instance pointer.
753 @param Data Data byte to write.
755 @retval EFI_SUCCESS The data byte is written successfully.
756 @retval EFI_TIMEOUT Timeout occurred during writing.
761 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
772 // wait for input buffer empty
774 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
775 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
783 if (RegEmptied
== 0) {
789 KeyWriteDataRegister (BiosKeyboardPrivate
, Data
);
795 Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.
797 @param BiosKeyboardPrivate Keyboard instance pointer.
798 @param Data Command byte to write.
800 @retval EFI_SUCCESS The command byte is written successfully.
801 @retval EFI_TIMEOUT Timeout occurred during writing.
806 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
817 // Wait For Input Buffer Empty
819 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
820 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
828 if (RegEmptied
== 0) {
834 KeyWriteCommandRegister (BiosKeyboardPrivate
, Data
);
837 // Wait For Input Buffer Empty again
840 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
841 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_INPB
) == 0) {
849 if (RegEmptied
== 0) {
857 Wait for a specific value to be presented in
858 Data register of Keyboard Controller by keyboard and then read it,
859 used in keyboard commands ack
861 @param BiosKeyboardPrivate Keyboard instance pointer.
862 @param Value The value to be waited for
863 @param WaitForValueTimeOut The limit of microseconds for timeout
865 @retval EFI_SUCCESS The command byte is written successfully.
866 @retval EFI_TIMEOUT Timeout occurred during writing.
870 KeyboardWaitForValue (
871 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
873 IN UINTN WaitForValueTimeOut
886 // Make sure the initial value of 'Data' is different from 'Value'
893 // Read from 8042 (multiple times if needed)
894 // until the expected value appears
895 // use SumTimeOut to control the iteration
901 for (TimeOut
= 0; TimeOut
< KEYBOARD_TIMEOUT
; TimeOut
+= 30) {
902 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_OUTB
) != 0) {
903 Data
= KeyReadDataRegister (BiosKeyboardPrivate
);
910 SumTimeOut
+= TimeOut
;
917 if (SumTimeOut
>= WaitForValueTimeOut
) {
933 Reads the next keystroke from the input device. The WaitForKey Event can
934 be used to test for existance of a keystroke via WaitForEvent () call.
936 @param BiosKeyboardPrivate Bioskeyboard driver private structure.
937 @param KeyData A pointer to a buffer that is filled in with the keystroke
938 state data for the key that was pressed.
940 @retval EFI_SUCCESS The keystroke information was returned.
941 @retval EFI_NOT_READY There was no keystroke data availiable.
942 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
944 @retval EFI_INVALID_PARAMETER KeyData is NULL.
948 KeyboardReadKeyStrokeWorker (
949 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
,
950 OUT EFI_KEY_DATA
*KeyData
955 if (KeyData
== NULL
) {
956 return EFI_INVALID_PARAMETER
;
960 // Use TimerEvent callback function to check whether there's any key pressed
964 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
965 // Csm will be used to check whether there is a key pending, but the csm will disable all
966 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
967 // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
968 // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,
969 // e.g. usb keyboard driver.
970 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
971 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
975 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
977 BiosKeyboardTimerHandler (NULL
, BiosKeyboardPrivate
);
979 // If there's no key, just return
981 Status
= CheckQueue (&BiosKeyboardPrivate
->Queue
);
982 if (EFI_ERROR (Status
)) {
983 ZeroMem (&KeyData
->Key
, sizeof (KeyData
->Key
));
984 CopyMem (&KeyData
->KeyState
, &BiosKeyboardPrivate
->KeyState
, sizeof (EFI_KEY_STATE
));
985 gBS
->RestoreTPL (OldTpl
);
986 return EFI_NOT_READY
;
989 Status
= Dequeue (&BiosKeyboardPrivate
->Queue
, KeyData
);
991 gBS
->RestoreTPL (OldTpl
);
997 // EFI Simple Text In Protocol Functions
1000 Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.
1002 @param This Pointer of simple text Protocol.
1003 @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
1005 @retval EFI_SUCCESS The command byte is written successfully.
1006 @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
1012 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
1013 IN BOOLEAN ExtendedVerification
1016 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1020 BOOLEAN MouseEnable
;
1023 MouseEnable
= FALSE
;
1024 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1028 // Report reset progress code
1030 REPORT_STATUS_CODE (
1032 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
1036 // Report a Progress Code for clearing the keyboard buffer
1038 REPORT_STATUS_CODE (
1040 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
1045 // Raise TPL to avoid mouse operation impact
1047 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1051 // Exhaust output buffer data
1054 Status
= BiosKeyboardReadKeyStroke (
1058 } while (!EFI_ERROR (Status
));
1061 // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H
1062 // if not skip step 4&5 and jump to step 6 to selftest KBC and report this
1065 if (!PcdGetBool (PcdFastPS2Detection
)) {
1066 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & KBC_STSREG_VIA64_SYSF
) != 0) {
1069 // CheckMouseStatus to decide enable it later or not
1072 // Read the command byte of KBC
1074 Status
= KeyboardCommand (
1075 BiosKeyboardPrivate
,
1076 KBC_CMDREG_VIA64_CMDBYTE_R
1079 if (EFI_ERROR (Status
)) {
1080 Status
= EFI_DEVICE_ERROR
;
1084 Status
= KeyboardRead (
1085 BiosKeyboardPrivate
,
1089 if (EFI_ERROR (Status
)) {
1090 Status
= EFI_DEVICE_ERROR
;
1094 // Check mouse enabled or not before
1096 if ((CommandByte
& KB_CMMBYTE_DISABLE_AUX
) != 0) {
1097 MouseEnable
= FALSE
;
1103 // disable mouse (via KBC) and Keyborad device
1105 Status
= KeyboardCommand (
1106 BiosKeyboardPrivate
,
1107 KBC_CMDREG_VIA64_AUX_DISABLE
1110 if (EFI_ERROR (Status
)) {
1111 Status
= EFI_DEVICE_ERROR
;
1115 Status
= KeyboardCommand (
1116 BiosKeyboardPrivate
,
1117 KBC_CMDREG_VIA64_KB_DISABLE
1120 if (EFI_ERROR (Status
)) {
1121 Status
= EFI_DEVICE_ERROR
;
1130 // Report a Progress Code for performing a self test on the keyboard controller
1132 REPORT_STATUS_CODE (
1134 EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_SELF_TEST
1137 Status
= KeyboardCommand (
1138 BiosKeyboardPrivate
,
1139 KBC_CMDREG_VIA64_KBC_SLFTEST
1141 if (EFI_ERROR (Status
)) {
1142 Status
= EFI_DEVICE_ERROR
;
1146 Status
= KeyboardWaitForValue (
1147 BiosKeyboardPrivate
,
1148 KBC_CMDECHO_KBCSLFTEST_OK
,
1149 KEYBOARD_WAITFORVALUE_TIMEOUT
1151 if (EFI_ERROR (Status
)) {
1152 Status
= EFI_DEVICE_ERROR
;
1159 // Disable Mouse interface, enable Keyboard interface and declare selftest success
1161 // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.
1163 Status
= KeyboardCommand (
1164 BiosKeyboardPrivate
,
1165 KBC_CMDREG_VIA64_CMDBYTE_W
1168 if (EFI_ERROR (Status
)) {
1169 Status
= EFI_DEVICE_ERROR
;
1174 // Write 8042 Command Byte, set System Flag
1175 // While at the same time:
1176 // 1. disable mouse interface,
1177 // 2. enable kbd interface,
1178 // 3. enable PC/XT kbd translation mode
1179 // 4. enable mouse and kbd interrupts
1181 //Command Byte bits:
1183 // 6: PC/XT translation mode
1184 // 5: Disable Auxiliary device interface
1185 // 4: Disable keyboard interface
1188 // 1: Enable Auxiliary device interrupt
1189 // 0: Enable Keyboard interrupt
1192 Status
= KeyboardWrite (
1193 BiosKeyboardPrivate
,
1194 (UINT8
) ((CommandByte
&
1195 (~KB_CMMBYTE_DISABLE_KB
)) |
1196 KB_CMMBYTE_KSCAN2UNI_COV
|
1197 KB_CMMBYTE_ENABLE_AUXINT
|
1198 KB_CMMBYTE_ENABLE_KBINT
|
1199 KB_CMMBYTE_SLFTEST_SUCC
|
1200 KB_CMMBYTE_DISABLE_AUX
)
1204 // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1205 // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.
1206 // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
1207 // Real reset will not do.
1209 if (ExtendedVerification
&& CheckKeyboardConnect (BiosKeyboardPrivate
)) {
1212 // Send keyboard reset command then read ACK
1214 Status
= KeyboardWrite (
1215 BiosKeyboardPrivate
,
1216 KBC_INPBUF_VIA60_KBRESET
1219 if (EFI_ERROR (Status
)) {
1220 Status
= EFI_DEVICE_ERROR
;
1224 Status
= KeyboardWaitForValue (
1225 BiosKeyboardPrivate
,
1227 KEYBOARD_WAITFORVALUE_TIMEOUT
1230 if (EFI_ERROR (Status
)) {
1231 Status
= EFI_DEVICE_ERROR
;
1236 // Wait for keyboard return test OK.
1238 Status
= KeyboardWaitForValue (
1239 BiosKeyboardPrivate
,
1240 KBC_CMDECHO_BATTEST_OK
,
1241 KEYBOARD_WAITFORVALUE_TIMEOUT
1244 if (EFI_ERROR (Status
)) {
1245 Status
= EFI_DEVICE_ERROR
;
1250 // set keyboard scan code set = 02 (standard configuration)
1252 Status
= KeyboardWrite (
1253 BiosKeyboardPrivate
,
1254 KBC_INPBUF_VIA60_KBSCODE
1256 if (EFI_ERROR (Status
)) {
1257 Status
= EFI_DEVICE_ERROR
;
1261 Status
= KeyboardWaitForValue (
1262 BiosKeyboardPrivate
,
1264 KEYBOARD_WAITFORVALUE_TIMEOUT
1267 if (EFI_ERROR (Status
)) {
1268 Status
= EFI_DEVICE_ERROR
;
1272 Status
= KeyboardWrite (
1273 BiosKeyboardPrivate
,
1274 KBC_INPBUF_VIA60_SCODESET2
1276 if (EFI_ERROR (Status
)) {
1277 Status
= EFI_DEVICE_ERROR
;
1281 Status
= KeyboardWaitForValue (
1282 BiosKeyboardPrivate
,
1284 KEYBOARD_WAITFORVALUE_TIMEOUT
1287 if (EFI_ERROR (Status
)) {
1288 Status
= EFI_DEVICE_ERROR
;
1293 // enable keyboard itself (not via KBC) by writing CMD F4 via 60H
1295 Status
= KeyboardWrite (
1296 BiosKeyboardPrivate
,
1297 KBC_INPBUF_VIA60_KBEN
1299 if (EFI_ERROR (Status
)) {
1300 Status
= EFI_DEVICE_ERROR
;
1304 Status
= KeyboardWaitForValue (
1305 BiosKeyboardPrivate
,
1307 KEYBOARD_WAITFORVALUE_TIMEOUT
1310 if (EFI_ERROR (Status
)) {
1311 Status
= EFI_DEVICE_ERROR
;
1316 // Additional validation, do it as follow:
1317 // 1). check for status register of PARE && TIM via 64H
1318 // 2). perform KB checking by writing ABh via 64H
1320 if ((KeyReadStatusRegister (BiosKeyboardPrivate
) & (KBC_STSREG_VIA64_PARE
| KBC_STSREG_VIA64_TIM
)) != 0) {
1321 Status
= EFI_DEVICE_ERROR
;
1325 Status
= KeyboardCommand (
1326 BiosKeyboardPrivate
,
1327 KBC_CMDREG_VIA64_KB_CKECK
1329 if (EFI_ERROR (Status
)) {
1330 Status
= EFI_DEVICE_ERROR
;
1334 Status
= KeyboardWaitForValue (
1335 BiosKeyboardPrivate
,
1336 KBC_CMDECHO_KBCHECK_OK
,
1337 KEYBOARD_WAITFORVALUE_TIMEOUT
1340 if (EFI_ERROR (Status
)) {
1341 Status
= EFI_DEVICE_ERROR
;
1347 // Done for validating keyboard. Enable keyboard (via KBC)
1348 // and recover the command byte to proper value
1350 if (!PcdGetBool (PcdFastPS2Detection
)) {
1351 Status
= KeyboardCommand (
1352 BiosKeyboardPrivate
,
1353 KBC_CMDREG_VIA64_KB_ENABLE
1356 if (EFI_ERROR (Status
)) {
1357 Status
= EFI_DEVICE_ERROR
;
1364 // conditionally enable mouse (via KBC)
1367 Status
= KeyboardCommand (
1368 BiosKeyboardPrivate
,
1369 KBC_CMDREG_VIA64_AUX_ENABLE
1372 if (EFI_ERROR (Status
)) {
1373 Status
= EFI_DEVICE_ERROR
;
1381 // resume priority of task level
1383 gBS
->RestoreTPL (OldTpl
);
1390 Read out the scan code of the key that has just been stroked.
1392 @param This Pointer of simple text Protocol.
1393 @param Key Pointer for store the key that read out.
1395 @retval EFI_SUCCESS The key is read out successfully.
1396 @retval other The key reading failed.
1401 BiosKeyboardReadKeyStroke (
1402 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
1403 OUT EFI_INPUT_KEY
*Key
1406 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1408 EFI_KEY_DATA KeyData
;
1410 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1412 Status
= KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate
, &KeyData
);
1413 if (EFI_ERROR (Status
)) {
1418 // Convert the Ctrl+[a-z] to Ctrl+[1-26]
1420 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
1421 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
1422 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
1423 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
1424 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
1428 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
1434 Waiting on the keyboard event, if there's any key pressed by the user, signal the event
1436 @param Event The event that be siganlled when any key has been stroked.
1437 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1442 BiosKeyboardWaitForKey (
1448 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
1449 // Csm will be used to check whether there is a key pending, but the csm will disable all
1450 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
1451 // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
1452 // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,
1453 // e.g. usb keyboard driver.
1454 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
1455 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
1459 // Use TimerEvent callback function to check whether there's any key pressed
1461 BiosKeyboardTimerHandler (NULL
, BIOS_KEYBOARD_DEV_FROM_THIS (Context
));
1463 if (!EFI_ERROR (BiosKeyboardCheckForKey (Context
))) {
1464 gBS
->SignalEvent (Event
);
1469 Check key buffer to get the key stroke status.
1471 @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
1473 @retval EFI_SUCCESS A key is being pressed now.
1474 @retval Other No key is now pressed.
1479 BiosKeyboardCheckForKey (
1480 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
1483 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1485 BiosKeyboardPrivate
= BIOS_KEYBOARD_DEV_FROM_THIS (This
);
1487 return CheckQueue (&BiosKeyboardPrivate
->Queue
);
1490 // Private worker functions
1492 #define TABLE_END 0x0
1494 typedef struct _CONVERT_TABLE_ENTRY
{
1497 } CONVERT_TABLE_ENTRY
;
1499 CONVERT_TABLE_ENTRY mConvertTable
[] = {
1541 // Function Keys are only valid if KeyChar == 0x00
1542 // This function does not require KeyChar to be 0x00
1593 // Convert ALT + Fn keys
1642 Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.
1644 @param KeyChar Unicode of key.
1645 @param ScanCode Scan code of key.
1647 @return The value of EFI Scancode for the key.
1648 @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.
1652 ConvertToEFIScanCode (
1660 if (KeyChar
== CHAR_ESC
) {
1661 EfiScanCode
= SCAN_ESC
;
1662 } else if (KeyChar
== 0x00 || KeyChar
== 0xe0) {
1664 // Movement & Function Keys
1666 for (Index
= 0; (Index
< sizeof (mConvertTable
) / sizeof (CONVERT_TABLE_ENTRY
)) && (mConvertTable
[Index
].ScanCode
!= TABLE_END
); Index
+= 1) {
1667 if (ScanCode
== mConvertTable
[Index
].ScanCode
) {
1668 return mConvertTable
[Index
].EfiScanCode
;
1672 // Reach Table end, return default value
1683 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
1684 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
1685 should not be in system.
1687 @param BiosKeyboardPrivate Keyboard Private Data Struture
1689 @retval TRUE Keyboard in System.
1690 @retval FALSE Keyboard not in System.
1694 CheckKeyboardConnect (
1695 IN BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
1700 Status
= EFI_SUCCESS
;
1702 // enable keyboard itself and wait for its ack
1703 // If can't receive ack, Keyboard should not be connected.
1705 if (!PcdGetBool (PcdFastPS2Detection
)) {
1706 Status
= KeyboardWrite (
1707 BiosKeyboardPrivate
,
1708 KBC_INPBUF_VIA60_KBEN
1710 if (EFI_ERROR (Status
)) {
1711 DEBUG ((EFI_D_ERROR
, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));
1712 REPORT_STATUS_CODE (
1713 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1714 EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
1719 Status
= KeyboardWaitForValue (
1720 BiosKeyboardPrivate
,
1722 KEYBOARD_WAITFORVALUE_TIMEOUT
1725 if (EFI_ERROR (Status
)) {
1726 DEBUG ((EFI_D_ERROR
, "[KBD]CheckKeyboardConnect - Timeout!\n"));
1727 REPORT_STATUS_CODE (
1728 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1729 EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_CONTROLLER_ERROR
1740 Timer event handler: read a series of key stroke from 8042
1741 and put them into memory key buffer.
1742 It is registered as running under TPL_NOTIFY
1744 @param Event The timer event
1745 @param Context A BIOS_KEYBOARD_DEV pointer
1750 BiosKeyboardTimerHandler (
1756 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
1757 EFI_IA32_REGISTER_SET Regs
;
1758 UINT8 KbFlag1
; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1
1759 UINT8 KbFlag2
; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2
1760 EFI_KEY_DATA KeyData
;
1762 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1764 BiosKeyboardPrivate
= Context
;
1767 // Enter critical section
1769 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1772 // if there is no key present, just return
1774 if (BiosKeyboardPrivate
->ExtendedKeyboard
) {
1780 BiosKeyboardPrivate
->LegacyBios
->Int86 (
1781 BiosKeyboardPrivate
->LegacyBios
,
1785 if (Regs
.X
.Flags
.ZF
!= 0) {
1786 gBS
->RestoreTPL (OldTpl
);
1793 if (BiosKeyboardPrivate
->ExtendedKeyboard
) {
1799 BiosKeyboardPrivate
->LegacyBios
->Int86 (
1800 BiosKeyboardPrivate
->LegacyBios
,
1805 KeyData
.Key
.ScanCode
= (UINT16
) Regs
.H
.AH
;
1806 KeyData
.Key
.UnicodeChar
= (UINT16
) Regs
.H
.AL
;
1809 "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
1810 KeyData
.Key
.ScanCode
,
1811 KeyData
.Key
.UnicodeChar
1814 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
1815 KeyData
.KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
1817 // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then
1818 // 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
1819 // 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
1820 // 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
1821 // 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
1822 // 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
1823 // 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
1824 // performance, like USB.
1826 // 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
1827 // 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
1828 // 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
1831 // 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
1832 // 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,
1833 // which will let persist to press SHIFT has same effection as only press one time.
1835 //0040h:0017h - KEYBOARD - STATUS FLAGS 1
1837 // 6 Caps Lock active
1838 // 5 Num Lock active
1839 // 4 Scroll Lock active
1840 // 3 either Alt pressed
1841 // 2 either Ctrl pressed
1842 // 1 Left Shift pressed
1843 // 0 Right Shift pressed
1847 // Clear the CTRL and ALT BDA flag
1850 KbFlag1
= *((UINT8
*) (UINTN
) 0x417); // read the STATUS FLAGS 1
1851 KbFlag2
= *((UINT8
*) (UINTN
) 0x418); // read STATUS FLAGS 2
1856 if ((KbFlag1
& KB_CAPS_LOCK_BIT
) == KB_CAPS_LOCK_BIT
) {
1857 DEBUG ((EFI_D_INFO
, "[KBD]Caps Lock Key is pressed.\n"));
1859 if ((KbFlag1
& KB_NUM_LOCK_BIT
) == KB_NUM_LOCK_BIT
) {
1860 DEBUG ((EFI_D_INFO
, "[KBD]Num Lock Key is pressed.\n"));
1862 if ((KbFlag1
& KB_SCROLL_LOCK_BIT
) == KB_SCROLL_LOCK_BIT
) {
1863 DEBUG ((EFI_D_INFO
, "[KBD]Scroll Lock Key is pressed.\n"));
1865 if ((KbFlag1
& KB_ALT_PRESSED
) == KB_ALT_PRESSED
) {
1866 if ((KbFlag2
& KB_LEFT_ALT_PRESSED
) == KB_LEFT_ALT_PRESSED
) {
1867 DEBUG ((EFI_D_INFO
, "[KBD]Left Alt Key is pressed.\n"));
1869 DEBUG ((EFI_D_INFO
, "[KBD]Right Alt Key is pressed.\n"));
1872 if ((KbFlag1
& KB_CTRL_PRESSED
) == KB_CTRL_PRESSED
) {
1873 if ((KbFlag2
& KB_LEFT_CTRL_PRESSED
) == KB_LEFT_CTRL_PRESSED
) {
1874 DEBUG ((EFI_D_INFO
, "[KBD]Left Ctrl Key is pressed.\n"));
1876 DEBUG ((EFI_D_INFO
, "[KBD]Right Ctrl Key is pressed.\n"));
1879 if ((KbFlag1
& KB_LEFT_SHIFT_PRESSED
) == KB_LEFT_SHIFT_PRESSED
) {
1880 DEBUG ((EFI_D_INFO
, "[KBD]Left Shift Key is pressed.\n"));
1882 if ((KbFlag1
& KB_RIGHT_SHIFT_PRESSED
) == KB_RIGHT_SHIFT_PRESSED
) {
1883 DEBUG ((EFI_D_INFO
, "[KBD]Right Shift Key is pressed.\n"));
1889 // Record toggle state
1891 if ((KbFlag1
& KB_CAPS_LOCK_BIT
) == KB_CAPS_LOCK_BIT
) {
1892 KeyData
.KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
1894 if ((KbFlag1
& KB_NUM_LOCK_BIT
) == KB_NUM_LOCK_BIT
) {
1895 KeyData
.KeyState
.KeyToggleState
|= EFI_NUM_LOCK_ACTIVE
;
1897 if ((KbFlag1
& KB_SCROLL_LOCK_BIT
) == KB_SCROLL_LOCK_BIT
) {
1898 KeyData
.KeyState
.KeyToggleState
|= EFI_SCROLL_LOCK_ACTIVE
;
1901 // Record shift state
1902 // BUGBUG: Need add Menu key and Left/Right Logo key state in the future
1904 if ((KbFlag1
& KB_ALT_PRESSED
) == KB_ALT_PRESSED
) {
1905 KeyData
.KeyState
.KeyShiftState
|= ((KbFlag2
& KB_LEFT_ALT_PRESSED
) == KB_LEFT_ALT_PRESSED
) ? EFI_LEFT_ALT_PRESSED
: EFI_RIGHT_ALT_PRESSED
;
1907 if ((KbFlag1
& KB_CTRL_PRESSED
) == KB_CTRL_PRESSED
) {
1908 KeyData
.KeyState
.KeyShiftState
|= ((KbFlag2
& KB_LEFT_CTRL_PRESSED
) == KB_LEFT_CTRL_PRESSED
) ? EFI_LEFT_CONTROL_PRESSED
: EFI_RIGHT_CONTROL_PRESSED
;
1910 if ((KbFlag1
& KB_LEFT_SHIFT_PRESSED
) == KB_LEFT_SHIFT_PRESSED
) {
1911 KeyData
.KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
1913 if ((KbFlag1
& KB_RIGHT_SHIFT_PRESSED
) == KB_RIGHT_SHIFT_PRESSED
) {
1914 KeyData
.KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
1918 // Clear left alt and left ctrl BDA flag
1921 KbFlag2
&= ~(KB_LEFT_ALT_PRESSED
| KB_LEFT_CTRL_PRESSED
);
1922 *((UINT8
*) (UINTN
) 0x418) = KbFlag2
;
1924 *((UINT8
*) (UINTN
) 0x417) = KbFlag1
;
1928 // Output EFI input key and shift/toggle state
1930 if (KeyData
.Key
.UnicodeChar
== CHAR_NULL
|| KeyData
.Key
.UnicodeChar
== CHAR_SCANCODE
|| KeyData
.Key
.UnicodeChar
== CHAR_ESC
) {
1931 KeyData
.Key
.ScanCode
= ConvertToEFIScanCode (KeyData
.Key
.UnicodeChar
, KeyData
.Key
.ScanCode
);
1932 KeyData
.Key
.UnicodeChar
= CHAR_NULL
;
1934 KeyData
.Key
.ScanCode
= SCAN_NULL
;
1938 // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.
1940 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
1941 if (KeyData
.Key
.UnicodeChar
>= 1 && KeyData
.Key
.UnicodeChar
<= 26) {
1942 if (((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ==
1943 ((KeyData
.KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0)
1945 KeyData
.Key
.UnicodeChar
= (UINT16
) (KeyData
.Key
.UnicodeChar
+ L
'a' - 1);
1947 KeyData
.Key
.UnicodeChar
= (UINT16
) (KeyData
.Key
.UnicodeChar
+ L
'A' - 1);
1954 "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
1955 KeyData
.Key
.ScanCode
,
1956 KeyData
.Key
.UnicodeChar
1960 // Need not return associated shift state if a class of printable characters that
1961 // are normally adjusted by shift modifiers.
1962 // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.
1964 if ((KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') ||
1965 (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z')
1967 DEBUG ((EFI_D_INFO
, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));
1968 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
1972 // Signal KeyNotify process event if this key pressed matches any key registered.
1974 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
1975 CurrentNotify
= CR (
1977 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1979 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1981 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1983 // The key notification function needs to run at TPL_CALLBACK
1984 // while current TPL is TPL_NOTIFY. It will be invoked in
1985 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
1987 Enqueue (&BiosKeyboardPrivate
->QueueForNotify
, &KeyData
);
1988 gBS
->SignalEvent (BiosKeyboardPrivate
->KeyNotifyProcessEvent
);
1992 Enqueue (&BiosKeyboardPrivate
->Queue
, &KeyData
);
1995 // Save the current key state
1997 CopyMem (&BiosKeyboardPrivate
->KeyState
, &KeyData
.KeyState
, sizeof (EFI_KEY_STATE
));
2000 // Leave critical section and return
2002 gBS
->RestoreTPL (OldTpl
);
2010 @param Event Indicates the event that invoke this function.
2011 @param Context Indicates the calling context.
2015 KeyNotifyProcessHandler (
2021 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2022 EFI_KEY_DATA KeyData
;
2024 LIST_ENTRY
*NotifyList
;
2025 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2028 BiosKeyboardPrivate
= (BIOS_KEYBOARD_DEV
*) Context
;
2031 // Invoke notification functions.
2033 NotifyList
= &BiosKeyboardPrivate
->NotifyList
;
2036 // Enter critical section
2038 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2039 Status
= Dequeue (&BiosKeyboardPrivate
->QueueForNotify
, &KeyData
);
2041 // Leave critical section
2043 gBS
->RestoreTPL (OldTpl
);
2044 if (EFI_ERROR (Status
)) {
2047 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
2048 CurrentNotify
= CR (Link
, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
2049 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
2050 CurrentNotify
->KeyNotificationFn (&KeyData
);
2057 Free keyboard notify list.
2059 @param ListHead The list head
2061 @retval EFI_SUCCESS Free the notify list successfully
2062 @retval EFI_INVALID_PARAMETER ListHead is invalid.
2066 BiosKeyboardFreeNotifyList (
2067 IN OUT LIST_ENTRY
*ListHead
2070 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
2072 if (ListHead
== NULL
) {
2073 return EFI_INVALID_PARAMETER
;
2075 while (!IsListEmpty (ListHead
)) {
2077 ListHead
->ForwardLink
,
2078 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2080 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2082 RemoveEntryList (ListHead
->ForwardLink
);
2083 gBS
->FreePool (NotifyNode
);
2090 Check if key is registered.
2092 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
2093 state data for the key that was registered.
2094 @param InputData A pointer to a buffer that is filled in with the keystroke
2095 state data for the key that was pressed.
2097 @retval TRUE Key be pressed matches a registered key.
2098 @retval FLASE Match failed.
2103 IN EFI_KEY_DATA
*RegsiteredData
,
2104 IN EFI_KEY_DATA
*InputData
2107 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
2109 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
2110 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
2115 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
2117 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
2118 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
2121 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
2122 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
2131 Waiting on the keyboard event, if there's any key pressed by the user, signal the event
2133 @param Event The event that be siganlled when any key has been stroked.
2134 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
2139 BiosKeyboardWaitForKeyEx (
2144 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2146 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context
);
2147 BiosKeyboardWaitForKey (Event
, &BiosKeyboardPrivate
->SimpleTextIn
);
2152 Reset the input device and optionaly run diagnostics
2154 @param This Protocol instance pointer.
2155 @param ExtendedVerification Driver may perform diagnostics on reset.
2157 @retval EFI_SUCCESS The device was reset.
2158 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
2164 BiosKeyboardResetEx (
2165 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2166 IN BOOLEAN ExtendedVerification
2169 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2173 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2175 Status
= BiosKeyboardPrivate
->SimpleTextIn
.Reset (
2176 &BiosKeyboardPrivate
->SimpleTextIn
,
2177 ExtendedVerification
2179 if (EFI_ERROR (Status
)) {
2180 return EFI_DEVICE_ERROR
;
2183 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2185 gBS
->RestoreTPL (OldTpl
);
2192 Reads the next keystroke from the input device. The WaitForKey Event can
2193 be used to test for existance of a keystroke via WaitForEvent () call.
2195 @param This Protocol instance pointer.
2196 @param KeyData A pointer to a buffer that is filled in with the keystroke
2197 state data for the key that was pressed.
2199 @retval EFI_SUCCESS The keystroke information was returned.
2200 @retval EFI_NOT_READY There was no keystroke data availiable.
2201 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
2203 @retval EFI_INVALID_PARAMETER KeyData is NULL.
2208 BiosKeyboardReadKeyStrokeEx (
2209 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2210 OUT EFI_KEY_DATA
*KeyData
2213 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2215 if (KeyData
== NULL
) {
2216 return EFI_INVALID_PARAMETER
;
2219 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2221 return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate
, KeyData
);
2226 Set certain state for the input device.
2228 @param This Protocol instance pointer.
2229 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
2230 state for the input device.
2232 @retval EFI_SUCCESS The device state was set successfully.
2233 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
2234 not have the setting adjusted.
2235 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
2236 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
2241 BiosKeyboardSetState (
2242 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2243 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
2247 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2249 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
2252 if (KeyToggleState
== NULL
) {
2253 return EFI_INVALID_PARAMETER
;
2257 // Thunk keyboard driver doesn't support partial keystroke.
2259 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
||
2260 (*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
2262 return EFI_UNSUPPORTED
;
2265 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2267 // See if the Legacy BIOS Protocol is available
2269 Status
= gBS
->LocateProtocol (
2270 &gEfiLegacyBiosProtocolGuid
,
2272 (VOID
**) &LegacyBios
2275 ASSERT_EFI_ERROR (Status
);
2277 // Enter critical section
2279 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2282 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
2285 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
2288 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
2292 Status
= KeyboardWrite (BiosKeyboardPrivate
, 0xed);
2293 if (EFI_ERROR (Status
)) {
2294 Status
= EFI_DEVICE_ERROR
;
2297 Status
= KeyboardWaitForValue (BiosKeyboardPrivate
, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT
);
2298 if (EFI_ERROR (Status
)) {
2299 Status
= EFI_DEVICE_ERROR
;
2302 Status
= KeyboardWrite (BiosKeyboardPrivate
, Command
);
2303 if (EFI_ERROR (Status
)) {
2304 Status
= EFI_DEVICE_ERROR
;
2308 // Call Legacy BIOS Protocol to set whatever is necessary
2310 LegacyBios
->UpdateKeyboardLedStatus (LegacyBios
, Command
);
2312 Status
= EFI_SUCCESS
;
2316 // Leave critical section and return
2318 gBS
->RestoreTPL (OldTpl
);
2325 Register a notification function for a particular keystroke for the input device.
2327 @param This Protocol instance pointer.
2328 @param KeyData A pointer to a buffer that is filled in with the keystroke
2329 information data for the key that was pressed. If KeyData.Key,
2330 KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState
2331 are 0, then any incomplete keystroke will trigger a notification of
2332 the KeyNotificationFunction.
2333 @param KeyNotificationFunction Points to the function to be called when the key
2334 sequence is typed specified by KeyData. This notification function
2335 should be called at <=TPL_CALLBACK.
2336 @param NotifyHandle Points to the unique handle assigned to the registered notification.
2338 @retval EFI_SUCCESS The notification function was registered successfully.
2339 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
2340 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
2345 BiosKeyboardRegisterKeyNotify (
2346 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2347 IN EFI_KEY_DATA
*KeyData
,
2348 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
2349 OUT VOID
**NotifyHandle
2353 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2355 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
2357 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2359 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
2360 return EFI_INVALID_PARAMETER
;
2363 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2366 // Enter critical section
2368 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2371 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
2373 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
2374 CurrentNotify
= CR (
2376 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2378 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2380 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
2381 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
2382 *NotifyHandle
= CurrentNotify
;
2383 Status
= EFI_SUCCESS
;
2390 // Allocate resource to save the notification function
2393 NewNotify
= (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
2394 if (NewNotify
== NULL
) {
2395 Status
= EFI_OUT_OF_RESOURCES
;
2399 NewNotify
->Signature
= BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
2400 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
2401 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
2402 InsertTailList (&BiosKeyboardPrivate
->NotifyList
, &NewNotify
->NotifyEntry
);
2404 *NotifyHandle
= NewNotify
;
2405 Status
= EFI_SUCCESS
;
2409 // Leave critical section and return
2411 gBS
->RestoreTPL (OldTpl
);
2416 Remove a registered notification function from a particular keystroke.
2418 @param This Protocol instance pointer.
2419 @param NotificationHandle The handle of the notification function being unregistered.
2421 @retval EFI_SUCCESS The notification function was unregistered successfully.
2422 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
2427 BiosKeyboardUnregisterKeyNotify (
2428 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
2429 IN VOID
*NotificationHandle
2433 BIOS_KEYBOARD_DEV
*BiosKeyboardPrivate
;
2436 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
2439 // Check incoming notification handle
2441 if (NotificationHandle
== NULL
) {
2442 return EFI_INVALID_PARAMETER
;
2445 if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
2446 return EFI_INVALID_PARAMETER
;
2449 BiosKeyboardPrivate
= TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This
);
2452 // Enter critical section
2454 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
2456 for (Link
= BiosKeyboardPrivate
->NotifyList
.ForwardLink
; Link
!= &BiosKeyboardPrivate
->NotifyList
; Link
= Link
->ForwardLink
) {
2457 CurrentNotify
= CR (
2459 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
2461 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
2463 if (CurrentNotify
== NotificationHandle
) {
2465 // Remove the notification function from NotifyList and free resources
2467 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
2469 Status
= EFI_SUCCESS
;
2475 // Can not find the specified Notification Handle
2477 Status
= EFI_INVALID_PARAMETER
;
2481 // Leave critical section and return
2483 gBS
->RestoreTPL (OldTpl
);
2488 The user Entry Point for module BiosKeyboard. The user code starts with this function.
2490 @param[in] ImageHandle The firmware allocated handle for the EFI image.
2491 @param[in] SystemTable A pointer to the EFI System Table.
2493 @retval EFI_SUCCESS The entry point is executed successfully.
2494 @retval other Some error occurs when executing this entry point.
2499 InitializeBiosKeyboard(
2500 IN EFI_HANDLE ImageHandle
,
2501 IN EFI_SYSTEM_TABLE
*SystemTable
2507 // Install driver model protocol(s).
2509 Status
= EfiLibInstallDriverBindingComponentName2 (
2512 &gBiosKeyboardDriverBinding
,
2514 &gBiosKeyboardComponentName
,
2515 &gBiosKeyboardComponentName2
2517 ASSERT_EFI_ERROR (Status
);