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