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