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