]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
IntelFrameworkModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdTextIn.c
1 /** @file
2 Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
3 provided by Ps2KbdCtrller.c.
4
5 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10
11 #include "Ps2Keyboard.h"
12
13 /**
14 Check whether the EFI key buffer is empty.
15
16 @param Queue Pointer to instance of EFI_KEY_QUEUE.
17
18 @retval TRUE The EFI key buffer is empty.
19 @retval FALSE The EFI key buffer isn't empty.
20 **/
21 BOOLEAN
22 IsEfikeyBufEmpty (
23 IN EFI_KEY_QUEUE *Queue
24 )
25 {
26 return (BOOLEAN) (Queue->Head == Queue->Tail);
27 }
28
29 /**
30 Read & remove one key data from the EFI key buffer.
31
32 @param Queue Pointer to instance of EFI_KEY_QUEUE.
33 @param KeyData Receive the key data.
34
35 @retval EFI_SUCCESS The key data is popped successfully.
36 @retval EFI_NOT_READY There is no key data available.
37 **/
38 EFI_STATUS
39 PopEfikeyBufHead (
40 IN EFI_KEY_QUEUE *Queue,
41 OUT EFI_KEY_DATA *KeyData OPTIONAL
42 )
43 {
44 if (IsEfikeyBufEmpty (Queue)) {
45 return EFI_NOT_READY;
46 }
47 //
48 // Retrieve and remove the values
49 //
50 if (KeyData != NULL) {
51 CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));
52 }
53 Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
54 return EFI_SUCCESS;
55 }
56
57 /**
58 Push one key data to the EFI key buffer.
59
60 @param Queue Pointer to instance of EFI_KEY_QUEUE.
61 @param KeyData The key data to push.
62 **/
63 VOID
64 PushEfikeyBufTail (
65 IN EFI_KEY_QUEUE *Queue,
66 IN EFI_KEY_DATA *KeyData
67 )
68 {
69 if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {
70 //
71 // If Queue is full, pop the one from head.
72 //
73 PopEfikeyBufHead (Queue, NULL);
74 }
75 CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));
76 Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
77 }
78
79 /**
80 Judge whether is a registed key
81
82 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
83 state data for the key that was registered.
84 @param InputData A pointer to a buffer that is filled in with the keystroke
85 state data for the key that was pressed.
86
87 @retval TRUE Key be pressed matches a registered key.
88 @retval FLASE Match failed.
89
90 **/
91 BOOLEAN
92 IsKeyRegistered (
93 IN EFI_KEY_DATA *RegsiteredData,
94 IN EFI_KEY_DATA *InputData
95 )
96
97 {
98 ASSERT (RegsiteredData != NULL && InputData != NULL);
99
100 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
101 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
102 return FALSE;
103 }
104
105 //
106 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
107 //
108 if (RegsiteredData->KeyState.KeyShiftState != 0 &&
109 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
110 return FALSE;
111 }
112 if (RegsiteredData->KeyState.KeyToggleState != 0 &&
113 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
114 return FALSE;
115 }
116
117 return TRUE;
118
119 }
120
121 /**
122 Reads the next keystroke from the input device. The WaitForKey Event can
123 be used to test for existance of a keystroke via WaitForEvent () call.
124
125 @param ConsoleInDev Ps2 Keyboard private structure
126 @param KeyData A pointer to a buffer that is filled in with the keystroke
127 state data for the key that was pressed.
128
129
130 @retval EFI_SUCCESS The keystroke information was returned.
131 @retval EFI_NOT_READY There was no keystroke data availiable.
132 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
133 hardware errors.
134 @retval EFI_INVALID_PARAMETER KeyData is NULL.
135
136 **/
137 EFI_STATUS
138 KeyboardReadKeyStrokeWorker (
139 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev,
140 OUT EFI_KEY_DATA *KeyData
141 )
142
143 {
144 EFI_STATUS Status;
145 EFI_TPL OldTpl;
146
147 if (KeyData == NULL) {
148 return EFI_INVALID_PARAMETER;
149 }
150
151 //
152 // Enter critical section
153 //
154 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
155
156 KeyboardTimerHandler (NULL, ConsoleInDev);
157
158 if (ConsoleInDev->KeyboardErr) {
159 Status = EFI_DEVICE_ERROR;
160 } else {
161 Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);
162 if (Status == EFI_NOT_READY) {
163 ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
164 InitializeKeyState (ConsoleInDev, &KeyData->KeyState);
165 }
166 }
167
168 gBS->RestoreTPL (OldTpl);
169 return Status;
170 }
171
172 /**
173 Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
174
175 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
176 @param ExtendedVerification Indicate that the driver may perform a more
177 exhaustive verification operation of the device during
178 reset, now this par is ignored in this driver
179
180 **/
181 EFI_STATUS
182 EFIAPI
183 KeyboardEfiReset (
184 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
185 IN BOOLEAN ExtendedVerification
186 )
187 {
188 EFI_STATUS Status;
189 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
190 EFI_TPL OldTpl;
191
192 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
193 if (ConsoleIn->KeyboardErr) {
194 return EFI_DEVICE_ERROR;
195 }
196
197 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
198 EFI_PROGRESS_CODE,
199 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
200 ConsoleIn->DevicePath
201 );
202
203 //
204 // Enter critical section
205 //
206 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
207
208 //
209 // Call InitKeyboard to initialize the keyboard
210 //
211 Status = InitKeyboard (ConsoleIn, ExtendedVerification);
212 if (EFI_ERROR (Status)) {
213 //
214 // Leave critical section and return
215 //
216 gBS->RestoreTPL (OldTpl);
217 return EFI_DEVICE_ERROR;
218 }
219
220 //
221 // Leave critical section and return
222 //
223 gBS->RestoreTPL (OldTpl);
224
225 //
226 // Report the status If a stuck key was detected
227 //
228 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
229 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
230 EFI_ERROR_CODE | EFI_ERROR_MINOR,
231 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,
232 ConsoleIn->DevicePath
233 );
234 }
235 //
236 // Report the status If keyboard is locked
237 //
238 if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {
239 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
240 EFI_ERROR_CODE | EFI_ERROR_MINOR,
241 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,
242 ConsoleIn->DevicePath
243 );
244 }
245
246 return EFI_SUCCESS;
247 }
248
249 /**
250 Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
251
252 @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
253 @param Key The output buffer for key value
254
255 @retval EFI_SUCCESS success to read key stroke
256 **/
257 EFI_STATUS
258 EFIAPI
259 KeyboardReadKeyStroke (
260 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
261 OUT EFI_INPUT_KEY *Key
262 )
263 {
264 EFI_STATUS Status;
265 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
266 EFI_KEY_DATA KeyData;
267
268 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
269
270 //
271 // Considering if the partial keystroke is enabled, there maybe a partial
272 // keystroke in the queue, so here skip the partial keystroke and get the
273 // next key from the queue
274 //
275 while (1) {
276 //
277 // If there is no pending key, then return.
278 //
279 Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
280 if (EFI_ERROR (Status)) {
281 return Status;
282 }
283 //
284 // If it is partial keystroke, skip it.
285 //
286 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
287 continue;
288 }
289 //
290 // Translate the CTRL-Alpha characters to their corresponding control value
291 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
292 //
293 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
294 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
295 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
296 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
297 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
298 }
299 }
300
301 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
302 return EFI_SUCCESS;
303 }
304 }
305
306 /**
307 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
308 Signal the event if there is key available
309
310 @param Event the event object
311 @param Context waitting context
312
313 **/
314 VOID
315 EFIAPI
316 KeyboardWaitForKey (
317 IN EFI_EVENT Event,
318 IN VOID *Context
319 )
320 {
321 EFI_TPL OldTpl;
322 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
323 EFI_KEY_DATA KeyData;
324
325 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
326
327 //
328 // Enter critical section
329 //
330 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
331
332 KeyboardTimerHandler (NULL, ConsoleIn);
333
334 if (!ConsoleIn->KeyboardErr) {
335 //
336 // WaitforKey doesn't suppor the partial key.
337 // Considering if the partial keystroke is enabled, there maybe a partial
338 // keystroke in the queue, so here skip the partial keystroke and get the
339 // next key from the queue
340 //
341 while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {
342 CopyMem (
343 &KeyData,
344 &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),
345 sizeof (EFI_KEY_DATA)
346 );
347 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
348 PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);
349 continue;
350 }
351 //
352 // if there is pending value key, signal the event.
353 //
354 gBS->SignalEvent (Event);
355 break;
356 }
357 }
358 //
359 // Leave critical section and return
360 //
361 gBS->RestoreTPL (OldTpl);
362 }
363
364 /**
365 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
366 Signal the event if there is key available
367
368 @param Event event object
369 @param Context waiting context
370
371 **/
372 VOID
373 EFIAPI
374 KeyboardWaitForKeyEx (
375 IN EFI_EVENT Event,
376 IN VOID *Context
377 )
378
379 {
380 KeyboardWaitForKey (Event, Context);
381 }
382
383 /**
384 Reset the input device and optionaly run diagnostics
385
386 @param This Protocol instance pointer.
387 @param ExtendedVerification Driver may perform diagnostics on reset.
388
389 @retval EFI_SUCCESS The device was reset.
390 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
391 not be reset.
392
393 **/
394 EFI_STATUS
395 EFIAPI
396 KeyboardEfiResetEx (
397 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
398 IN BOOLEAN ExtendedVerification
399 )
400
401 {
402 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
403
404 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
405
406 return ConsoleInDev->ConIn.Reset (
407 &ConsoleInDev->ConIn,
408 ExtendedVerification
409 );
410 }
411
412 /**
413 Reads the next keystroke from the input device. The WaitForKey Event can
414 be used to test for existance of a keystroke via WaitForEvent () call.
415
416
417 @param This Protocol instance pointer.
418 @param KeyData A pointer to a buffer that is filled in with the keystroke
419 state data for the key that was pressed.
420
421 @retval EFI_SUCCESS The keystroke information was returned.
422 @retval EFI_NOT_READY There was no keystroke data availiable.
423 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
424 hardware errors.
425 @retval EFI_INVALID_PARAMETER KeyData is NULL.
426
427 **/
428 EFI_STATUS
429 EFIAPI
430 KeyboardReadKeyStrokeEx (
431 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
432 OUT EFI_KEY_DATA *KeyData
433 )
434
435 {
436 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
437
438 if (KeyData == NULL) {
439 return EFI_INVALID_PARAMETER;
440 }
441
442 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
443 return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);
444 }
445
446 /**
447 Set certain state for the input device.
448
449 @param This Protocol instance pointer.
450 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
451 state for the input device.
452
453 @retval EFI_SUCCESS The device state was set successfully.
454 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
455 not have the setting adjusted.
456 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
457 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
458
459 **/
460 EFI_STATUS
461 EFIAPI
462 KeyboardSetState (
463 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
464 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
465 )
466
467 {
468 EFI_STATUS Status;
469 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
470 EFI_TPL OldTpl;
471
472 if (KeyToggleState == NULL) {
473 return EFI_INVALID_PARAMETER;
474 }
475
476 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
477
478 //
479 // Enter critical section
480 //
481 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
482
483 if (ConsoleInDev->KeyboardErr) {
484 Status = EFI_DEVICE_ERROR;
485 goto Exit;
486 }
487
488 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
489 Status = EFI_UNSUPPORTED;
490 goto Exit;
491 }
492
493 //
494 // Update the status light
495 //
496 ConsoleInDev->ScrollLock = FALSE;
497 ConsoleInDev->NumLock = FALSE;
498 ConsoleInDev->CapsLock = FALSE;
499 ConsoleInDev->IsSupportPartialKey = FALSE;
500
501 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
502 ConsoleInDev->ScrollLock = TRUE;
503 }
504 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
505 ConsoleInDev->NumLock = TRUE;
506 }
507 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
508 ConsoleInDev->CapsLock = TRUE;
509 }
510 if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
511 ConsoleInDev->IsSupportPartialKey = TRUE;
512 }
513
514 Status = UpdateStatusLights (ConsoleInDev);
515 if (EFI_ERROR (Status)) {
516 Status = EFI_DEVICE_ERROR;
517 }
518
519 Exit:
520 //
521 // Leave critical section and return
522 //
523 gBS->RestoreTPL (OldTpl);
524
525 return Status;
526
527 }
528
529 /**
530 Register a notification function for a particular keystroke for the input device.
531
532 @param This Protocol instance pointer.
533 @param KeyData A pointer to a buffer that is filled in with the keystroke
534 information data for the key that was pressed. If KeyData.Key,
535 KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState
536 are 0, then any incomplete keystroke will trigger a notification of
537 the KeyNotificationFunction.
538 @param KeyNotificationFunction Points to the function to be called when the key
539 sequence is typed specified by KeyData. This notification function
540 should be called at <=TPL_CALLBACK.
541 @param NotifyHandle Points to the unique handle assigned to the registered notification.
542
543 @retval EFI_SUCCESS The notification function was registered successfully.
544 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
545 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
546
547 **/
548 EFI_STATUS
549 EFIAPI
550 KeyboardRegisterKeyNotify (
551 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
552 IN EFI_KEY_DATA *KeyData,
553 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
554 OUT VOID **NotifyHandle
555 )
556 {
557 EFI_STATUS Status;
558 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
559 EFI_TPL OldTpl;
560 LIST_ENTRY *Link;
561 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
562 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
563
564 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
565 return EFI_INVALID_PARAMETER;
566 }
567
568 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
569
570 //
571 // Enter critical section
572 //
573 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
574
575 //
576 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
577 //
578 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
579 CurrentNotify = CR (
580 Link,
581 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
582 NotifyEntry,
583 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
584 );
585 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
586 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
587 *NotifyHandle = CurrentNotify;
588 Status = EFI_SUCCESS;
589 goto Exit;
590 }
591 }
592 }
593
594 //
595 // Allocate resource to save the notification function
596 //
597 NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
598 if (NewNotify == NULL) {
599 Status = EFI_OUT_OF_RESOURCES;
600 goto Exit;
601 }
602
603 NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
604 NewNotify->KeyNotificationFn = KeyNotificationFunction;
605 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
606 InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
607
608 *NotifyHandle = NewNotify;
609 Status = EFI_SUCCESS;
610
611 Exit:
612 //
613 // Leave critical section and return
614 //
615 gBS->RestoreTPL (OldTpl);
616 return Status;
617
618 }
619
620 /**
621 Remove a registered notification function from a particular keystroke.
622
623 @param This Protocol instance pointer.
624 @param NotificationHandle The handle of the notification function being unregistered.
625
626
627 @retval EFI_SUCCESS The notification function was unregistered successfully.
628 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
629
630 **/
631 EFI_STATUS
632 EFIAPI
633 KeyboardUnregisterKeyNotify (
634 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
635 IN VOID *NotificationHandle
636 )
637 {
638 EFI_STATUS Status;
639 KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;
640 EFI_TPL OldTpl;
641 LIST_ENTRY *Link;
642 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
643
644 if (NotificationHandle == NULL) {
645 return EFI_INVALID_PARAMETER;
646 }
647
648 ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
649
650 //
651 // Enter critical section
652 //
653 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
654
655 for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
656 CurrentNotify = CR (
657 Link,
658 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
659 NotifyEntry,
660 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
661 );
662 if (CurrentNotify == NotificationHandle) {
663 //
664 // Remove the notification function from NotifyList and free resources
665 //
666 RemoveEntryList (&CurrentNotify->NotifyEntry);
667
668 gBS->FreePool (CurrentNotify);
669 Status = EFI_SUCCESS;
670 goto Exit;
671 }
672 }
673
674 //
675 // Can not find the specified Notification Handle
676 //
677 Status = EFI_INVALID_PARAMETER;
678 Exit:
679 //
680 // Leave critical section and return
681 //
682 gBS->RestoreTPL (OldTpl);
683 return Status;
684 }
685
686 /**
687 Process key notify.
688
689 @param Event Indicates the event that invoke this function.
690 @param Context Indicates the calling context.
691 **/
692 VOID
693 EFIAPI
694 KeyNotifyProcessHandler (
695 IN EFI_EVENT Event,
696 IN VOID *Context
697 )
698 {
699 EFI_STATUS Status;
700 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
701 EFI_KEY_DATA KeyData;
702 LIST_ENTRY *Link;
703 LIST_ENTRY *NotifyList;
704 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
705 EFI_TPL OldTpl;
706
707 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
708
709 //
710 // Invoke notification functions.
711 //
712 NotifyList = &ConsoleIn->NotifyList;
713 while (TRUE) {
714 //
715 // Enter critical section
716 //
717 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
718 Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
719 //
720 // Leave critical section
721 //
722 gBS->RestoreTPL (OldTpl);
723 if (EFI_ERROR (Status)) {
724 break;
725 }
726 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
727 CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
728 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
729 CurrentNotify->KeyNotificationFn (&KeyData);
730 }
731 }
732 }
733 }
734