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