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