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