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