]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2KbdCtrller.c
1 /** @file
2 Routines that access 8042 keyboard controller
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "Ps2Keyboard.h"
10
11 struct {
12 UINT8 ScanCode; ///< follows value defined in Scan Code Set1
13 UINT16 EfiScanCode;
14 CHAR16 UnicodeChar;
15 CHAR16 ShiftUnicodeChar;
16 }
17 ConvertKeyboardScanCodeToEfiKey[] = {
18
19 {
20 0x01, // Escape
21 SCAN_ESC,
22 0x0000,
23 0x0000
24 },
25 {
26 0x02,
27 SCAN_NULL,
28 L'1',
29 L'!'
30 },
31 {
32 0x03,
33 SCAN_NULL,
34 L'2',
35 L'@'
36 },
37 {
38 0x04,
39 SCAN_NULL,
40 L'3',
41 L'#'
42 },
43 {
44 0x05,
45 SCAN_NULL,
46 L'4',
47 L'$'
48 },
49 {
50 0x06,
51 SCAN_NULL,
52 L'5',
53 L'%'
54 },
55 {
56 0x07,
57 SCAN_NULL,
58 L'6',
59 L'^'
60 },
61 {
62 0x08,
63 SCAN_NULL,
64 L'7',
65 L'&'
66 },
67 {
68 0x09,
69 SCAN_NULL,
70 L'8',
71 L'*'
72 },
73 {
74 0x0A,
75 SCAN_NULL,
76 L'9',
77 L'('
78 },
79 {
80 0x0B,
81 SCAN_NULL,
82 L'0',
83 L')'
84 },
85 {
86 0x0C,
87 SCAN_NULL,
88 L'-',
89 L'_'
90 },
91 {
92 0x0D,
93 SCAN_NULL,
94 L'=',
95 L'+'
96 },
97 {
98 0x0E, // BackSpace
99 SCAN_NULL,
100 0x0008,
101 0x0008
102 },
103 {
104 0x0F, // Tab
105 SCAN_NULL,
106 0x0009,
107 0x0009
108 },
109 {
110 0x10,
111 SCAN_NULL,
112 L'q',
113 L'Q'
114 },
115 {
116 0x11,
117 SCAN_NULL,
118 L'w',
119 L'W'
120 },
121 {
122 0x12,
123 SCAN_NULL,
124 L'e',
125 L'E'
126 },
127 {
128 0x13,
129 SCAN_NULL,
130 L'r',
131 L'R'
132 },
133 {
134 0x14,
135 SCAN_NULL,
136 L't',
137 L'T'
138 },
139 {
140 0x15,
141 SCAN_NULL,
142 L'y',
143 L'Y'
144 },
145 {
146 0x16,
147 SCAN_NULL,
148 L'u',
149 L'U'
150 },
151 {
152 0x17,
153 SCAN_NULL,
154 L'i',
155 L'I'
156 },
157 {
158 0x18,
159 SCAN_NULL,
160 L'o',
161 L'O'
162 },
163 {
164 0x19,
165 SCAN_NULL,
166 L'p',
167 L'P'
168 },
169 {
170 0x1a,
171 SCAN_NULL,
172 L'[',
173 L'{'
174 },
175 {
176 0x1b,
177 SCAN_NULL,
178 L']',
179 L'}'
180 },
181 {
182 0x1c, // Enter
183 SCAN_NULL,
184 0x000d,
185 0x000d
186 },
187 {
188 0x1d,
189 SCAN_NULL,
190 0x0000,
191 0x0000
192 },
193 {
194 0x1e,
195 SCAN_NULL,
196 L'a',
197 L'A'
198 },
199 {
200 0x1f,
201 SCAN_NULL,
202 L's',
203 L'S'
204 },
205 {
206 0x20,
207 SCAN_NULL,
208 L'd',
209 L'D'
210 },
211 {
212 0x21,
213 SCAN_NULL,
214 L'f',
215 L'F'
216 },
217 {
218 0x22,
219 SCAN_NULL,
220 L'g',
221 L'G'
222 },
223 {
224 0x23,
225 SCAN_NULL,
226 L'h',
227 L'H'
228 },
229 {
230 0x24,
231 SCAN_NULL,
232 L'j',
233 L'J'
234 },
235 {
236 0x25,
237 SCAN_NULL,
238 L'k',
239 L'K'
240 },
241 {
242 0x26,
243 SCAN_NULL,
244 L'l',
245 L'L'
246 },
247 {
248 0x27,
249 SCAN_NULL,
250 L';',
251 L':'
252 },
253 {
254 0x28,
255 SCAN_NULL,
256 L'\'',
257 L'"'
258 },
259 {
260 0x29,
261 SCAN_NULL,
262 L'`',
263 L'~'
264 },
265 {
266 0x2a, // Left Shift
267 SCAN_NULL,
268 0x0000,
269 0x0000
270 },
271 {
272 0x2b,
273 SCAN_NULL,
274 L'\\',
275 L'|'
276 },
277 {
278 0x2c,
279 SCAN_NULL,
280 L'z',
281 L'Z'
282 },
283 {
284 0x2d,
285 SCAN_NULL,
286 L'x',
287 L'X'
288 },
289 {
290 0x2e,
291 SCAN_NULL,
292 L'c',
293 L'C'
294 },
295 {
296 0x2f,
297 SCAN_NULL,
298 L'v',
299 L'V'
300 },
301 {
302 0x30,
303 SCAN_NULL,
304 L'b',
305 L'B'
306 },
307 {
308 0x31,
309 SCAN_NULL,
310 L'n',
311 L'N'
312 },
313 {
314 0x32,
315 SCAN_NULL,
316 L'm',
317 L'M'
318 },
319 {
320 0x33,
321 SCAN_NULL,
322 L',',
323 L'<'
324 },
325 {
326 0x34,
327 SCAN_NULL,
328 L'.',
329 L'>'
330 },
331 {
332 0x35,
333 SCAN_NULL,
334 L'/',
335 L'?'
336 },
337 {
338 0x36, //Right Shift
339 SCAN_NULL,
340 0x0000,
341 0x0000
342 },
343 {
344 0x37, // Numeric Keypad *
345 SCAN_NULL,
346 L'*',
347 L'*'
348 },
349 {
350 0x38, //Left Alt/Extended Right Alt
351 SCAN_NULL,
352 0x0000,
353 0x0000
354 },
355 {
356 0x39,
357 SCAN_NULL,
358 L' ',
359 L' '
360 },
361 {
362 0x3A, //CapsLock
363 SCAN_NULL,
364 0x0000,
365 0x0000
366 },
367 {
368 0x3B,
369 SCAN_F1,
370 0x0000,
371 0x0000
372 },
373 {
374 0x3C,
375 SCAN_F2,
376 0x0000,
377 0x0000
378 },
379 {
380 0x3D,
381 SCAN_F3,
382 0x0000,
383 0x0000
384 },
385 {
386 0x3E,
387 SCAN_F4,
388 0x0000,
389 0x0000
390 },
391 {
392 0x3F,
393 SCAN_F5,
394 0x0000,
395 0x0000
396 },
397 {
398 0x40,
399 SCAN_F6,
400 0x0000,
401 0x0000
402 },
403 {
404 0x41,
405 SCAN_F7,
406 0x0000,
407 0x0000
408 },
409 {
410 0x42,
411 SCAN_F8,
412 0x0000,
413 0x0000
414 },
415 {
416 0x43,
417 SCAN_F9,
418 0x0000,
419 0x0000
420 },
421 {
422 0x44,
423 SCAN_F10,
424 0x0000,
425 0x0000
426 },
427 {
428 0x45, // NumLock
429 SCAN_NULL,
430 0x0000,
431 0x0000
432 },
433 {
434 0x46, // ScrollLock
435 SCAN_NULL,
436 0x0000,
437 0x0000
438 },
439 {
440 0x47,
441 SCAN_HOME,
442 L'7',
443 L'7'
444 },
445 {
446 0x48,
447 SCAN_UP,
448 L'8',
449 L'8'
450 },
451 {
452 0x49,
453 SCAN_PAGE_UP,
454 L'9',
455 L'9'
456 },
457 {
458 0x4a,
459 SCAN_NULL,
460 L'-',
461 L'-'
462 },
463 {
464 0x4b,
465 SCAN_LEFT,
466 L'4',
467 L'4'
468 },
469 {
470 0x4c, // Numeric Keypad 5
471 SCAN_NULL,
472 L'5',
473 L'5'
474 },
475 {
476 0x4d,
477 SCAN_RIGHT,
478 L'6',
479 L'6'
480 },
481 {
482 0x4e,
483 SCAN_NULL,
484 L'+',
485 L'+'
486 },
487 {
488 0x4f,
489 SCAN_END,
490 L'1',
491 L'1'
492 },
493 {
494 0x50,
495 SCAN_DOWN,
496 L'2',
497 L'2'
498 },
499 {
500 0x51,
501 SCAN_PAGE_DOWN,
502 L'3',
503 L'3'
504 },
505 {
506 0x52,
507 SCAN_INSERT,
508 L'0',
509 L'0'
510 },
511 {
512 0x53,
513 SCAN_DELETE,
514 L'.',
515 L'.'
516 },
517 {
518 0x57,
519 SCAN_F11,
520 0x0000,
521 0x0000
522 },
523 {
524 0x58,
525 SCAN_F12,
526 0x0000,
527 0x0000
528 },
529 {
530 0x5B, //Left LOGO
531 SCAN_NULL,
532 0x0000,
533 0x0000
534 },
535 {
536 0x5C, //Right LOGO
537 SCAN_NULL,
538 0x0000,
539 0x0000
540 },
541 {
542 0x5D, //Menu key
543 SCAN_NULL,
544 0x0000,
545 0x0000
546 },
547 {
548 TABLE_END,
549 TABLE_END,
550 SCAN_NULL,
551 SCAN_NULL
552 },
553 };
554
555 //
556 // The WaitForValue time out
557 //
558 UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
559
560 BOOLEAN mEnableMouseInterface;
561
562
563
564 /**
565 Return the count of scancode in the queue.
566
567 @param Queue Pointer to instance of SCAN_CODE_QUEUE.
568
569 @return Count of the scancode.
570 **/
571 UINTN
572 GetScancodeBufCount (
573 IN SCAN_CODE_QUEUE *Queue
574 )
575 {
576 if (Queue->Head <= Queue->Tail) {
577 return Queue->Tail - Queue->Head;
578 } else {
579 return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;
580 }
581 }
582
583 /**
584 Read several bytes from the scancode buffer without removing them.
585 This function is called to see if there are enough bytes of scancode
586 representing a single key.
587
588 @param Queue Pointer to instance of SCAN_CODE_QUEUE.
589 @param Count Number of bytes to be read
590 @param Buf Store the results
591
592 @retval EFI_SUCCESS success to scan the keyboard code
593 @retval EFI_NOT_READY invalid parameter
594 **/
595 EFI_STATUS
596 GetScancodeBufHead (
597 IN SCAN_CODE_QUEUE *Queue,
598 IN UINTN Count,
599 OUT UINT8 *Buf
600 )
601 {
602 UINTN Index;
603 UINTN Pos;
604
605 //
606 // check the valid range of parameter 'Count'
607 //
608 if (GetScancodeBufCount (Queue) < Count) {
609 return EFI_NOT_READY;
610 }
611 //
612 // retrieve the values
613 //
614 for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
615 Buf[Index] = Queue->Buffer[Pos];
616 }
617
618 return EFI_SUCCESS;
619 }
620
621 /**
622
623 Read & remove several bytes from the scancode buffer.
624 This function is usually called after GetScancodeBufHead()
625
626 @param Queue Pointer to instance of SCAN_CODE_QUEUE.
627 @param Count Number of bytes to be read
628 @param Buf Store the results
629
630 @retval EFI_SUCCESS success to scan the keyboard code
631 @retval EFI_NOT_READY invalid parameter
632 **/
633 EFI_STATUS
634 PopScancodeBufHead (
635 IN SCAN_CODE_QUEUE *Queue,
636 IN UINTN Count,
637 OUT UINT8 *Buf OPTIONAL
638 )
639 {
640 UINTN Index;
641
642 //
643 // Check the valid range of parameter 'Count'
644 //
645 if (GetScancodeBufCount (Queue) < Count) {
646 return EFI_NOT_READY;
647 }
648 //
649 // Retrieve and remove the values
650 //
651 for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
652 if (Buf != NULL) {
653 Buf[Index] = Queue->Buffer[Queue->Head];
654 }
655 }
656
657 return EFI_SUCCESS;
658 }
659
660 /**
661 Push one byte to the scancode buffer.
662
663 @param Queue Pointer to instance of SCAN_CODE_QUEUE.
664 @param Scancode The byte to push.
665 **/
666 VOID
667 PushScancodeBufTail (
668 IN SCAN_CODE_QUEUE *Queue,
669 IN UINT8 Scancode
670 )
671 {
672 if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {
673 PopScancodeBufHead (Queue, 1, NULL);
674 }
675
676 Queue->Buffer[Queue->Tail] = Scancode;
677 Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;
678 }
679
680 /**
681 Read data register .
682
683 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
684
685 @return return the value
686
687 **/
688 UINT8
689 KeyReadDataRegister (
690 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
691 )
692
693 {
694 return IoRead8 (ConsoleIn->DataRegisterAddress);
695 }
696
697 /**
698 Write data register.
699
700 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
701 @param Data value wanted to be written
702
703 **/
704 VOID
705 KeyWriteDataRegister (
706 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
707 IN UINT8 Data
708 )
709 {
710 IoWrite8 (ConsoleIn->DataRegisterAddress, Data);
711 }
712
713 /**
714 Read status register.
715
716 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
717
718 @return value in status register
719
720 **/
721 UINT8
722 KeyReadStatusRegister (
723 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
724 )
725 {
726 return IoRead8 (ConsoleIn->StatusRegisterAddress);
727 }
728
729 /**
730 Write command register .
731
732 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
733 @param Data The value wanted to be written
734
735 **/
736 VOID
737 KeyWriteCommandRegister (
738 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
739 IN UINT8 Data
740 )
741 {
742 IoWrite8 (ConsoleIn->CommandRegisterAddress, Data);
743 }
744
745 /**
746 Display error message.
747
748 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
749 @param ErrMsg Unicode string of error message
750
751 **/
752 VOID
753 KeyboardError (
754 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
755 IN CHAR16 *ErrMsg
756 )
757 {
758 ConsoleIn->KeyboardErr = TRUE;
759 }
760
761 /**
762 Timer event handler: read a series of scancodes from 8042
763 and put them into memory scancode buffer.
764 it read as much scancodes to either fill
765 the memory buffer or empty the keyboard buffer.
766 It is registered as running under TPL_NOTIFY
767
768 @param Event The timer event
769 @param Context A KEYBOARD_CONSOLE_IN_DEV pointer
770
771 **/
772 VOID
773 EFIAPI
774 KeyboardTimerHandler (
775 IN EFI_EVENT Event,
776 IN VOID *Context
777 )
778
779 {
780 UINT8 Data;
781 EFI_TPL OldTpl;
782 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
783
784 ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
785
786 //
787 // Enter critical section
788 //
789 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
790
791 if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
792 //
793 // Leave critical section and return
794 //
795 gBS->RestoreTPL (OldTpl);
796 return ;
797 }
798
799 //
800 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
801 // KB is not connected to system. If KB is not connected to system, driver will find there's something
802 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
803 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
804 // Just skip the 'resend' process simply.
805 //
806
807 while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==
808 KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA
809 ) {
810 //
811 // Read one byte of the scan code and store it into the memory buffer
812 //
813 Data = KeyReadDataRegister (ConsoleIn);
814 PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);
815 }
816 KeyGetchar (ConsoleIn);
817
818 //
819 // Leave critical section and return
820 //
821 gBS->RestoreTPL (OldTpl);
822 }
823
824 /**
825 Read key value .
826
827 @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
828 @param Data - Pointer to outof buffer for keeping key value
829
830 @retval EFI_TIMEOUT Status resigter time out
831 @retval EFI_SUCCESS Success to read keyboard
832
833 **/
834 EFI_STATUS
835 KeyboardRead (
836 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
837 OUT UINT8 *Data
838 )
839
840 {
841 UINT32 TimeOut;
842 UINT32 RegFilled;
843
844 TimeOut = 0;
845 RegFilled = 0;
846
847 //
848 // wait till output buffer full then perform the read
849 //
850 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
851 if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
852 RegFilled = 1;
853 *Data = KeyReadDataRegister (ConsoleIn);
854 break;
855 }
856
857 MicroSecondDelay (30);
858 }
859
860 if (RegFilled == 0) {
861 return EFI_TIMEOUT;
862 }
863
864 return EFI_SUCCESS;
865 }
866
867 /**
868 write key to keyboard
869
870 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
871 @param Data value wanted to be written
872
873 @retval EFI_TIMEOUT The input buffer register is full for putting new value util timeout
874 @retval EFI_SUCCESS The new value is sucess put into input buffer register.
875
876 **/
877 EFI_STATUS
878 KeyboardWrite (
879 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
880 IN UINT8 Data
881 )
882 {
883 UINT32 TimeOut;
884 UINT32 RegEmptied;
885
886 TimeOut = 0;
887 RegEmptied = 0;
888
889 //
890 // wait for input buffer empty
891 //
892 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
893 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
894 RegEmptied = 1;
895 break;
896 }
897
898 MicroSecondDelay (30);
899 }
900
901 if (RegEmptied == 0) {
902 return EFI_TIMEOUT;
903 }
904 //
905 // Write it
906 //
907 KeyWriteDataRegister (ConsoleIn, Data);
908
909 return EFI_SUCCESS;
910 }
911
912 /**
913 Issue keyboard command.
914
915 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
916 @param Data The buff holding the command
917
918 @retval EFI_TIMEOUT Keyboard is not ready to issuing
919 @retval EFI_SUCCESS Success to issue keyboard command
920
921 **/
922 EFI_STATUS
923 KeyboardCommand (
924 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
925 IN UINT8 Data
926 )
927 {
928 UINT32 TimeOut;
929 UINT32 RegEmptied;
930
931 TimeOut = 0;
932 RegEmptied = 0;
933
934 //
935 // Wait For Input Buffer Empty
936 //
937 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
938 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
939 RegEmptied = 1;
940 break;
941 }
942
943 MicroSecondDelay (30);
944 }
945
946 if (RegEmptied == 0) {
947 return EFI_TIMEOUT;
948 }
949 //
950 // issue the command
951 //
952 KeyWriteCommandRegister (ConsoleIn, Data);
953
954 //
955 // Wait For Input Buffer Empty again
956 //
957 RegEmptied = 0;
958 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
959 if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
960 RegEmptied = 1;
961 break;
962 }
963
964 MicroSecondDelay (30);
965 }
966
967 if (RegEmptied == 0) {
968 return EFI_TIMEOUT;
969 }
970
971 return EFI_SUCCESS;
972 }
973
974 /**
975 wait for a specific value to be presented on
976 8042 Data register by keyboard and then read it,
977 used in keyboard commands ack
978
979 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
980 @param Value the value wanted to be waited.
981
982 @retval EFI_TIMEOUT Fail to get specific value in given time
983 @retval EFI_SUCCESS Success to get specific value in given time.
984
985 **/
986 EFI_STATUS
987 KeyboardWaitForValue (
988 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
989 IN UINT8 Value
990 )
991 {
992 UINT8 Data;
993 UINT32 TimeOut;
994 UINT32 SumTimeOut;
995 UINT32 GotIt;
996
997 GotIt = 0;
998 TimeOut = 0;
999 SumTimeOut = 0;
1000
1001 //
1002 // Make sure the initial value of 'Data' is different from 'Value'
1003 //
1004 Data = 0;
1005 if (Data == Value) {
1006 Data = 1;
1007 }
1008 //
1009 // Read from 8042 (multiple times if needed)
1010 // until the expected value appears
1011 // use SumTimeOut to control the iteration
1012 //
1013 while (1) {
1014 //
1015 // Perform a read
1016 //
1017 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1018 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
1019 Data = KeyReadDataRegister (ConsoleIn);
1020 break;
1021 }
1022
1023 MicroSecondDelay (30);
1024 }
1025
1026 SumTimeOut += TimeOut;
1027
1028 if (Data == Value) {
1029 GotIt = 1;
1030 break;
1031 }
1032
1033 if (SumTimeOut >= mWaitForValueTimeOut) {
1034 break;
1035 }
1036 }
1037 //
1038 // Check results
1039 //
1040 if (GotIt == 1) {
1041 return EFI_SUCCESS;
1042 } else {
1043 return EFI_TIMEOUT;
1044 }
1045
1046 }
1047
1048 /**
1049 Show keyboard status lights according to
1050 indicators in ConsoleIn.
1051
1052 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1053
1054 @return status of updating keyboard register
1055
1056 **/
1057 EFI_STATUS
1058 UpdateStatusLights (
1059 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1060 )
1061 {
1062 EFI_STATUS Status;
1063 UINT8 Command;
1064
1065 //
1066 // Send keyboard command
1067 //
1068 Status = KeyboardWrite (ConsoleIn, 0xed);
1069 if (EFI_ERROR (Status)) {
1070 return Status;
1071 }
1072
1073 KeyboardWaitForValue (ConsoleIn, 0xfa);
1074
1075 //
1076 // Light configuration
1077 //
1078 Command = 0;
1079 if (ConsoleIn->CapsLock) {
1080 Command |= 4;
1081 }
1082
1083 if (ConsoleIn->NumLock) {
1084 Command |= 2;
1085 }
1086
1087 if (ConsoleIn->ScrollLock) {
1088 Command |= 1;
1089 }
1090
1091 Status = KeyboardWrite (ConsoleIn, Command);
1092
1093 if (EFI_ERROR (Status)) {
1094 return Status;
1095 }
1096
1097 KeyboardWaitForValue (ConsoleIn, 0xfa);
1098 return Status;
1099 }
1100
1101 /**
1102 Initialize the key state.
1103
1104 @param ConsoleIn The KEYBOARD_CONSOLE_IN_DEV instance.
1105 @param KeyState A pointer to receive the key state information.
1106 **/
1107 VOID
1108 InitializeKeyState (
1109 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1110 OUT EFI_KEY_STATE *KeyState
1111 )
1112 {
1113 KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID
1114 | (ConsoleIn->LeftCtrl ? EFI_LEFT_CONTROL_PRESSED : 0)
1115 | (ConsoleIn->RightCtrl ? EFI_RIGHT_CONTROL_PRESSED : 0)
1116 | (ConsoleIn->LeftAlt ? EFI_LEFT_ALT_PRESSED : 0)
1117 | (ConsoleIn->RightAlt ? EFI_RIGHT_ALT_PRESSED : 0)
1118 | (ConsoleIn->LeftShift ? EFI_LEFT_SHIFT_PRESSED : 0)
1119 | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED : 0)
1120 | (ConsoleIn->LeftLogo ? EFI_LEFT_LOGO_PRESSED : 0)
1121 | (ConsoleIn->RightLogo ? EFI_RIGHT_LOGO_PRESSED : 0)
1122 | (ConsoleIn->Menu ? EFI_MENU_KEY_PRESSED : 0)
1123 | (ConsoleIn->SysReq ? EFI_SYS_REQ_PRESSED : 0)
1124 ;
1125 KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID
1126 | (ConsoleIn->CapsLock ? EFI_CAPS_LOCK_ACTIVE : 0)
1127 | (ConsoleIn->NumLock ? EFI_NUM_LOCK_ACTIVE : 0)
1128 | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)
1129 | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0)
1130 ;
1131 }
1132
1133 /**
1134 Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.
1135
1136 The function is always called in TPL_NOTIFY.
1137
1138 @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
1139
1140 **/
1141 VOID
1142 KeyGetchar (
1143 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1144 )
1145 {
1146 EFI_STATUS Status;
1147 UINT16 ScanCode;
1148 BOOLEAN Extend0;
1149 BOOLEAN Extend1;
1150 UINTN Index;
1151 EFI_KEY_DATA KeyData;
1152 LIST_ENTRY *Link;
1153 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1154 //
1155 // 3 bytes most
1156 //
1157 UINT8 ScancodeArr[3];
1158 UINT32 ScancodeArrPos;
1159
1160 //
1161 // Check if there are enough bytes of scancode representing a single key
1162 // available in the buffer
1163 //
1164 while (TRUE) {
1165 Extend0 = FALSE;
1166 Extend1 = FALSE;
1167 ScancodeArrPos = 0;
1168 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1169 if (EFI_ERROR (Status)) {
1170 return ;
1171 }
1172
1173 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
1174 //
1175 // E0 to look ahead 2 bytes
1176 //
1177 Extend0 = TRUE;
1178 ScancodeArrPos = 1;
1179 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1180 if (EFI_ERROR (Status)) {
1181 return ;
1182 }
1183 } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
1184 //
1185 // E1 to look ahead 3 bytes
1186 //
1187 Extend1 = TRUE;
1188 ScancodeArrPos = 2;
1189 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1190 if (EFI_ERROR (Status)) {
1191 return ;
1192 }
1193 }
1194 //
1195 // if we reach this position, scancodes for a key is in buffer now,pop them
1196 //
1197 Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1198 ASSERT_EFI_ERROR (Status);
1199
1200 //
1201 // store the last available byte, this byte of scancode will be checked
1202 //
1203 ScanCode = ScancodeArr[ScancodeArrPos];
1204
1205 if (!Extend1) {
1206 //
1207 // Check for special keys and update the driver state.
1208 //
1209 switch (ScanCode) {
1210
1211 case SCANCODE_CTRL_MAKE:
1212 if (Extend0) {
1213 ConsoleIn->RightCtrl = TRUE;
1214 } else {
1215 ConsoleIn->LeftCtrl = TRUE;
1216 }
1217 break;
1218 case SCANCODE_CTRL_BREAK:
1219 if (Extend0) {
1220 ConsoleIn->RightCtrl = FALSE;
1221 } else {
1222 ConsoleIn->LeftCtrl = FALSE;
1223 }
1224 break;
1225
1226 case SCANCODE_ALT_MAKE:
1227 if (Extend0) {
1228 ConsoleIn->RightAlt = TRUE;
1229 } else {
1230 ConsoleIn->LeftAlt = TRUE;
1231 }
1232 break;
1233 case SCANCODE_ALT_BREAK:
1234 if (Extend0) {
1235 ConsoleIn->RightAlt = FALSE;
1236 } else {
1237 ConsoleIn->LeftAlt = FALSE;
1238 }
1239 break;
1240
1241 case SCANCODE_LEFT_SHIFT_MAKE:
1242 //
1243 // To avoid recognize PRNT_SCRN key as a L_SHIFT key
1244 // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.
1245 // If it the second byte of the PRNT_ScRN skip it.
1246 //
1247 if (!Extend0) {
1248 ConsoleIn->LeftShift = TRUE;
1249 break;
1250 }
1251 continue;
1252
1253 case SCANCODE_LEFT_SHIFT_BREAK:
1254 if (!Extend0) {
1255 ConsoleIn->LeftShift = FALSE;
1256 }
1257 break;
1258
1259 case SCANCODE_RIGHT_SHIFT_MAKE:
1260 ConsoleIn->RightShift = TRUE;
1261 break;
1262 case SCANCODE_RIGHT_SHIFT_BREAK:
1263 ConsoleIn->RightShift = FALSE;
1264 break;
1265
1266 case SCANCODE_LEFT_LOGO_MAKE:
1267 ConsoleIn->LeftLogo = TRUE;
1268 break;
1269 case SCANCODE_LEFT_LOGO_BREAK:
1270 ConsoleIn->LeftLogo = FALSE;
1271 break;
1272
1273 case SCANCODE_RIGHT_LOGO_MAKE:
1274 ConsoleIn->RightLogo = TRUE;
1275 break;
1276 case SCANCODE_RIGHT_LOGO_BREAK:
1277 ConsoleIn->RightLogo = FALSE;
1278 break;
1279
1280 case SCANCODE_MENU_MAKE:
1281 ConsoleIn->Menu = TRUE;
1282 break;
1283 case SCANCODE_MENU_BREAK:
1284 ConsoleIn->Menu = FALSE;
1285 break;
1286
1287 case SCANCODE_SYS_REQ_MAKE:
1288 if (Extend0) {
1289 ConsoleIn->SysReq = TRUE;
1290 }
1291 break;
1292 case SCANCODE_SYS_REQ_BREAK:
1293 if (Extend0) {
1294 ConsoleIn->SysReq = FALSE;
1295 }
1296 break;
1297
1298 case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
1299 ConsoleIn->SysReq = TRUE;
1300 break;
1301 case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
1302 ConsoleIn->SysReq = FALSE;
1303 break;
1304
1305 case SCANCODE_CAPS_LOCK_MAKE:
1306 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
1307 UpdateStatusLights (ConsoleIn);
1308 break;
1309 case SCANCODE_NUM_LOCK_MAKE:
1310 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
1311 UpdateStatusLights (ConsoleIn);
1312 break;
1313 case SCANCODE_SCROLL_LOCK_MAKE:
1314 if (!Extend0) {
1315 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
1316 UpdateStatusLights (ConsoleIn);
1317 }
1318 break;
1319 }
1320 }
1321
1322 //
1323 // If this is above the valid range, ignore it
1324 //
1325 if (ScanCode >= SCANCODE_MAX_MAKE) {
1326 continue;
1327 } else {
1328 break;
1329 }
1330 }
1331
1332 //
1333 // Handle Ctrl+Alt+Del hotkey
1334 //
1335 if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
1336 (ConsoleIn->LeftAlt || ConsoleIn->RightAlt ) &&
1337 ScanCode == SCANCODE_DELETE_MAKE
1338 ) {
1339 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1340 }
1341
1342 //
1343 // Save the Shift/Toggle state
1344 //
1345 InitializeKeyState (ConsoleIn, &KeyData.KeyState);
1346 KeyData.Key.ScanCode = SCAN_NULL;
1347 KeyData.Key.UnicodeChar = CHAR_NULL;
1348
1349 //
1350 // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix
1351 //
1352 if (Extend0 && ScanCode == 0x35) {
1353 KeyData.Key.UnicodeChar = L'/';
1354 KeyData.Key.ScanCode = SCAN_NULL;
1355
1356 //
1357 // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
1358 //
1359 } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
1360 KeyData.Key.UnicodeChar = CHAR_NULL;
1361 KeyData.Key.ScanCode = SCAN_PAUSE;
1362
1363 //
1364 // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix
1365 //
1366 } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
1367 KeyData.Key.UnicodeChar = CHAR_NULL;
1368 KeyData.Key.ScanCode = SCAN_PAUSE;
1369
1370 //
1371 // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix
1372 //
1373 } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
1374 KeyData.Key.UnicodeChar = CHAR_NULL;
1375 KeyData.Key.ScanCode = SCAN_NULL;
1376
1377 //
1378 // Except the above special case, all others can be handled by convert table
1379 //
1380 } else {
1381 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {
1382 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
1383 KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
1384 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
1385
1386 if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
1387 (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
1388 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
1389 //
1390 // Need not return associated shift state if a class of printable characters that
1391 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1392 //
1393 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
1394 }
1395 //
1396 // alphabetic key is affected by CapsLock State
1397 //
1398 if (ConsoleIn->CapsLock) {
1399 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
1400 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');
1401 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
1402 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');
1403 }
1404 }
1405 break;
1406 }
1407 }
1408 }
1409
1410 //
1411 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1412 //
1413 if (ScanCode >= 0x47 && ScanCode <= 0x53) {
1414 if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {
1415 KeyData.Key.ScanCode = SCAN_NULL;
1416 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
1417 KeyData.Key.UnicodeChar = CHAR_NULL;
1418 }
1419 }
1420
1421 //
1422 // If the key can not be converted then just return.
1423 //
1424 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
1425 if (!ConsoleIn->IsSupportPartialKey) {
1426 return ;
1427 }
1428 }
1429
1430 //
1431 // Signal KeyNotify process event if this key pressed matches any key registered.
1432 //
1433 for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {
1434 CurrentNotify = CR (
1435 Link,
1436 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
1437 NotifyEntry,
1438 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1439 );
1440 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
1441 //
1442 // The key notification function needs to run at TPL_CALLBACK
1443 // while current TPL is TPL_NOTIFY. It will be invoked in
1444 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
1445 //
1446 PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
1447 gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent);
1448 break;
1449 }
1450 }
1451
1452 PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
1453 }
1454
1455 /**
1456 Perform 8042 controller and keyboard Initialization.
1457 If ExtendedVerification is TRUE, do additional test for
1458 the keyboard interface
1459
1460 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1461 @param ExtendedVerification - indicates a thorough initialization
1462
1463 @retval EFI_DEVICE_ERROR Fail to init keyboard
1464 @retval EFI_SUCCESS Success to init keyboard
1465 **/
1466 EFI_STATUS
1467 InitKeyboard (
1468 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1469 IN BOOLEAN ExtendedVerification
1470 )
1471 {
1472 EFI_STATUS Status;
1473 EFI_STATUS Status1;
1474 UINT8 CommandByte;
1475 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
1476 UINT32 TryTime;
1477
1478 Status = EFI_SUCCESS;
1479 mEnableMouseInterface = TRUE;
1480 TryTime = 0;
1481
1482 //
1483 // Get Ps2 policy to set this
1484 //
1485 gBS->LocateProtocol (
1486 &gEfiPs2PolicyProtocolGuid,
1487 NULL,
1488 (VOID **) &Ps2Policy
1489 );
1490
1491 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1492 EFI_PROGRESS_CODE,
1493 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
1494 ConsoleIn->DevicePath
1495 );
1496
1497 //
1498 // Perform a read to cleanup the Status Register's
1499 // output buffer full bits within MAX TRY times
1500 //
1501 if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
1502 while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
1503 Status = KeyboardRead (ConsoleIn, &CommandByte);
1504 TryTime ++;
1505 }
1506 //
1507 // Exceed the max try times. The device may be error.
1508 //
1509 if (TryTime == KEYBOARD_MAX_TRY) {
1510 Status = EFI_DEVICE_ERROR;
1511 goto Done;
1512 }
1513 }
1514 //
1515 // We should disable mouse interface during the initialization process
1516 // since mouse device output could block keyboard device output in the
1517 // 60H port of 8042 controller.
1518 //
1519 // So if we are not initializing 8042 controller for the
1520 // first time, we have to remember the previous mouse interface
1521 // enabling state
1522 //
1523 // Test the system flag in to determine whether this is the first
1524 // time initialization
1525 //
1526 if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
1527 if (!PcdGetBool (PcdFastPS2Detection)) {
1528 //
1529 // 8042 controller is already setup (by myself or by mouse driver):
1530 // See whether mouse interface is already enabled
1531 // which determines whether we should enable it later
1532 //
1533 //
1534 // Read the command byte of 8042 controller
1535 //
1536 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
1537 if (EFI_ERROR (Status)) {
1538 KeyboardError (ConsoleIn, L"\n\r");
1539 goto Done;
1540 }
1541
1542 Status = KeyboardRead (ConsoleIn, &CommandByte);
1543 if (EFI_ERROR (Status)) {
1544 KeyboardError (ConsoleIn, L"\n\r");
1545 goto Done;
1546 }
1547 //
1548 // Test the mouse enabling bit
1549 //
1550 if ((CommandByte & 0x20) != 0) {
1551 mEnableMouseInterface = FALSE;
1552 } else {
1553 mEnableMouseInterface = TRUE;
1554 }
1555 } else {
1556 mEnableMouseInterface = FALSE;
1557 }
1558 } else {
1559 //
1560 // 8042 controller is not setup yet:
1561 // 8042 controller selftest;
1562 // Don't enable mouse interface later.
1563 //
1564 //
1565 // Disable keyboard and mouse interfaces
1566 //
1567 if (!PcdGetBool (PcdFastPS2Detection)) {
1568 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
1569 if (EFI_ERROR (Status)) {
1570 KeyboardError (ConsoleIn, L"\n\r");
1571 goto Done;
1572 }
1573
1574 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
1575 if (EFI_ERROR (Status)) {
1576 KeyboardError (ConsoleIn, L"\n\r");
1577 goto Done;
1578 }
1579
1580 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1581 EFI_PROGRESS_CODE,
1582 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
1583 ConsoleIn->DevicePath
1584 );
1585 //
1586 // 8042 Controller Self Test
1587 //
1588 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
1589 if (EFI_ERROR (Status)) {
1590 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1591 goto Done;
1592 }
1593
1594 Status = KeyboardWaitForValue (ConsoleIn, 0x55);
1595 if (EFI_ERROR (Status)) {
1596 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
1597 goto Done;
1598 }
1599 }
1600 //
1601 // Don't enable mouse interface later
1602 //
1603 mEnableMouseInterface = FALSE;
1604
1605 }
1606
1607 if (Ps2Policy != NULL) {
1608 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
1609 }
1610 //
1611 // Write 8042 Command Byte, set System Flag
1612 // While at the same time:
1613 // 1. disable mouse interface,
1614 // 2. enable kbd interface,
1615 // 3. enable PC/XT kbd translation mode
1616 // 4. enable mouse and kbd interrupts
1617 //
1618 // ( Command Byte bits:
1619 // 7: Reserved
1620 // 6: PC/XT translation mode
1621 // 5: Disable Auxiliary device interface
1622 // 4: Disable keyboard interface
1623 // 3: Reserved
1624 // 2: System Flag
1625 // 1: Enable Auxiliary device interrupt
1626 // 0: Enable Keyboard interrupt )
1627 //
1628 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
1629 if (EFI_ERROR (Status)) {
1630 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1631 goto Done;
1632 }
1633
1634 Status = KeyboardWrite (ConsoleIn, 0x67);
1635 if (EFI_ERROR (Status)) {
1636 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1637 goto Done;
1638 }
1639
1640 //
1641 // Clear Memory Scancode Buffer
1642 //
1643 ConsoleIn->ScancodeQueue.Head = 0;
1644 ConsoleIn->ScancodeQueue.Tail = 0;
1645 ConsoleIn->EfiKeyQueue.Head = 0;
1646 ConsoleIn->EfiKeyQueue.Tail = 0;
1647 ConsoleIn->EfiKeyQueueForNotify.Head = 0;
1648 ConsoleIn->EfiKeyQueueForNotify.Tail = 0;
1649
1650 //
1651 // Reset the status indicators
1652 //
1653 ConsoleIn->CapsLock = FALSE;
1654 ConsoleIn->NumLock = FALSE;
1655 ConsoleIn->ScrollLock = FALSE;
1656 ConsoleIn->LeftCtrl = FALSE;
1657 ConsoleIn->RightCtrl = FALSE;
1658 ConsoleIn->LeftAlt = FALSE;
1659 ConsoleIn->RightAlt = FALSE;
1660 ConsoleIn->LeftShift = FALSE;
1661 ConsoleIn->RightShift = FALSE;
1662 ConsoleIn->LeftLogo = FALSE;
1663 ConsoleIn->RightLogo = FALSE;
1664 ConsoleIn->Menu = FALSE;
1665 ConsoleIn->SysReq = FALSE;
1666
1667 ConsoleIn->IsSupportPartialKey = FALSE;
1668 //
1669 // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1670 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1671 // to system. So we only do the real resetting for keyboard when user asks and there is a real KB connected t system,
1672 // and normally during booting an OS, it's skipped.
1673 //
1674 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
1675 //
1676 // Additional verifications for keyboard interface
1677 //
1678 //
1679 // Keyboard Interface Test
1680 //
1681 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
1682 if (EFI_ERROR (Status)) {
1683 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1684 goto Done;
1685 }
1686
1687 Status = KeyboardWaitForValue (ConsoleIn, 0x00);
1688 if (EFI_ERROR (Status)) {
1689 KeyboardError (
1690 ConsoleIn,
1691 L"Some specific value not aquired from 8042 controller!\n\r"
1692 );
1693 goto Done;
1694 }
1695 //
1696 // Keyboard reset with a BAT(Basic Assurance Test)
1697 //
1698 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
1699 if (EFI_ERROR (Status)) {
1700 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1701 goto Done;
1702 }
1703
1704 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1705 if (EFI_ERROR (Status)) {
1706 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1707 goto Done;
1708 }
1709 //
1710 // wait for BAT completion code
1711 //
1712 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;
1713
1714 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
1715 if (EFI_ERROR (Status)) {
1716 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
1717 goto Done;
1718 }
1719
1720 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
1721
1722 //
1723 // Set Keyboard to use Scan Code Set 2
1724 //
1725 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
1726 if (EFI_ERROR (Status)) {
1727 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1728 goto Done;
1729 }
1730
1731 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1732 if (EFI_ERROR (Status)) {
1733 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1734 goto Done;
1735 }
1736
1737 Status = KeyboardWrite (ConsoleIn, 0x02);
1738 if (EFI_ERROR (Status)) {
1739 KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
1740 goto Done;
1741 }
1742
1743 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1744 if (EFI_ERROR (Status)) {
1745 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1746 goto Done;
1747 }
1748
1749 //
1750 // Clear Keyboard Scancode Buffer
1751 //
1752 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
1753 if (EFI_ERROR (Status)) {
1754 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1755 goto Done;
1756 }
1757
1758 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1759 if (EFI_ERROR (Status)) {
1760 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1761 goto Done;
1762 }
1763 //
1764 if (Ps2Policy != NULL) {
1765 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
1766 ConsoleIn->CapsLock = TRUE;
1767 }
1768
1769 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
1770 ConsoleIn->NumLock = TRUE;
1771 }
1772
1773 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
1774 ConsoleIn->ScrollLock = TRUE;
1775 }
1776 }
1777 //
1778 // Update Keyboard Lights
1779 //
1780 Status = UpdateStatusLights (ConsoleIn);
1781 if (EFI_ERROR (Status)) {
1782 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
1783 goto Done;
1784 }
1785 }
1786 //
1787 // At last, we can now enable the mouse interface if appropriate
1788 //
1789 Done:
1790
1791 if (mEnableMouseInterface) {
1792 //
1793 // Enable mouse interface
1794 //
1795 Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
1796 if (EFI_ERROR (Status1)) {
1797 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1798 return EFI_DEVICE_ERROR;
1799 }
1800 }
1801
1802 if (!EFI_ERROR (Status)) {
1803 return EFI_SUCCESS;
1804 } else {
1805 return EFI_DEVICE_ERROR;
1806 }
1807
1808 }
1809
1810
1811 /**
1812 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
1813 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
1814 should not be in system.
1815
1816 @param[in] ConsoleIn Keyboard Private Data Structure
1817
1818 @retval TRUE Keyboard in System.
1819 @retval FALSE Keyboard not in System.
1820 **/
1821 BOOLEAN
1822 EFIAPI
1823 CheckKeyboardConnect (
1824 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1825 )
1826 {
1827 EFI_STATUS Status;
1828 UINTN WaitForValueTimeOutBcakup;
1829
1830 //
1831 // enable keyboard itself and wait for its ack
1832 // If can't receive ack, Keyboard should not be connected.
1833 //
1834 if (!PcdGetBool (PcdFastPS2Detection)) {
1835 Status = KeyboardWrite (
1836 ConsoleIn,
1837 KEYBOARD_KBEN
1838 );
1839
1840 if (EFI_ERROR (Status)) {
1841 return FALSE;
1842 }
1843 //
1844 // wait for 1s
1845 //
1846 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
1847 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
1848 Status = KeyboardWaitForValue (
1849 ConsoleIn,
1850 KEYBOARD_CMDECHO_ACK
1851 );
1852 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
1853
1854 if (EFI_ERROR (Status)) {
1855 return FALSE;
1856 }
1857
1858 return TRUE;
1859 } else {
1860 return TRUE;
1861 }
1862 }
1863