]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
Coding style modification.
[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 /**
639 Read data register
640
641 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
642
643 @return return the value
644
645 **/
646 STATIC
647 UINT8
648 KeyReadDataRegister (
649 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
650 )
651
652 {
653 EFI_ISA_IO_PROTOCOL *IsaIo;
654 UINT8 Data;
655
656 //
657 // Use IsaIo protocol to perform IO operations
658 //
659 IsaIo = ConsoleIn->IsaIo;
660
661 IsaIo->Io.Read (
662 IsaIo,
663 EfiIsaIoWidthUint8,
664 ConsoleIn->DataRegisterAddress,
665 1,
666 &Data
667 );
668
669 return Data;
670 }
671
672 /**
673 Write data register
674
675 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
676 @param Data value wanted to be written
677
678 **/
679 STATIC
680 VOID
681 KeyWriteDataRegister (
682 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
683 IN UINT8 Data
684 )
685
686 {
687 EFI_ISA_IO_PROTOCOL *IsaIo;
688
689 //
690 // Use IsaIo protocol to perform IO operations
691 //
692 IsaIo = ConsoleIn->IsaIo;
693
694 IsaIo->Io.Write (
695 IsaIo,
696 EfiIsaIoWidthUint8,
697 ConsoleIn->DataRegisterAddress,
698 1,
699 &Data
700 );
701
702 //
703 // outp(ConsoleIn->DataRegisterAddress, Data);
704 //
705 }
706
707 /**
708 Read status register
709
710 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
711
712 @return value in status register
713
714 **/
715 UINT8
716 KeyReadStatusRegister (
717 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
718 )
719 {
720 EFI_ISA_IO_PROTOCOL *IsaIo;
721 UINT8 Data;
722
723 //
724 // Use IsaIo protocol to perform IO operations
725 //
726 IsaIo = ConsoleIn->IsaIo;
727
728 IsaIo->Io.Read (
729 IsaIo,
730 EfiIsaIoWidthUint8,
731 ConsoleIn->StatusRegisterAddress,
732 1,
733 &Data
734 );
735
736 return Data;
737
738 }
739
740 /**
741 Write command register
742
743 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
744 @param Data The value wanted to be written
745
746 **/
747
748 STATIC
749 VOID
750 KeyWriteCommandRegister (
751 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
752 IN UINT8 Data
753 )
754 {
755 EFI_ISA_IO_PROTOCOL *IsaIo;
756
757 //
758 // Use IsaIo protocol to perform IO operations
759 //
760 IsaIo = ConsoleIn->IsaIo;
761
762 IsaIo->Io.Write (
763 IsaIo,
764 EfiIsaIoWidthUint8,
765 ConsoleIn->CommandRegisterAddress,
766 1,
767 &Data
768 );
769
770 }
771
772 /**
773 Display error message
774
775 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
776 @param ErrMsg Unicode string of error message
777
778 **/
779 STATIC
780 VOID
781 KeyboardError (
782 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
783 IN CHAR16 *ErrMsg
784 )
785 {
786 ConsoleIn->KeyboardErr = TRUE;
787
788 //
789 // gST -> ConOut -> OutputString (gST -> ConOut, L"Keyboard Driver: ");
790 // gST -> ConOut -> OutputString (gST -> ConOut, ErrMsg);
791 //
792 }
793
794 /**
795 Timer event handler: read a series of scancodes from 8042
796 and put them into memory scancode buffer.
797 it read as much scancodes to either fill
798 the memory buffer or empty the keyboard buffer.
799 It is registered as running under TPL_NOTIFY
800
801 @param Event - The timer event
802 @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer
803
804 **/
805 VOID
806 EFIAPI
807 KeyboardTimerHandler (
808 IN EFI_EVENT Event,
809 IN VOID *Context
810 )
811
812 {
813 UINT8 Data;
814 EFI_TPL OldTpl;
815 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
816
817 ConsoleIn = Context;
818
819 //
820 // Enter critical section
821 //
822 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
823
824 if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
825 //
826 // Leave critical section and return
827 //
828 gBS->RestoreTPL (OldTpl);
829 return ;
830 }
831 //
832 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
833 // KB is not connected to system. If KB is not connected to system, driver will find there's something
834 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
835 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
836 // Just skip the 'resend' process simply.
837 //
838
839 Data = 0;
840
841 //
842 // if there is no key present, just return
843 //
844 if ((KeyReadStatusRegister (Context) & 0x21) != 0x1) {
845 //
846 // Leave critical section and return
847 //
848 gBS->RestoreTPL (OldTpl);
849
850 return ;
851 }
852 //
853 // Read one byte of the scan code and store it into the memory buffer
854 //
855 if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {
856
857 Data = KeyReadDataRegister (Context);
858 //
859 // put the scancode into the memory scancode buffer
860 //
861 ConsoleIn->ScancodeBufCount++;
862 ConsoleIn->ScancodeBufEndPos++;
863 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
864 ConsoleIn->ScancodeBufEndPos = 0;
865 }
866
867 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;
868
869 //
870 // Handle Alt+Ctrl+Del Key combination
871 //
872 switch (Data) {
873 case SCANCODE_CTRL_MAKE:
874 ConsoleIn->Ctrled = TRUE;
875 break;
876
877 case SCANCODE_CTRL_BREAK:
878 ConsoleIn->Ctrled = FALSE;
879 break;
880
881 case SCANCODE_ALT_MAKE:
882 ConsoleIn->Alted = TRUE;
883 break;
884
885 case SCANCODE_ALT_BREAK:
886 ConsoleIn->Alted = FALSE;
887 break;
888 }
889 //
890 // if Alt+Ctrl+Del, Reboot the System
891 //
892 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {
893 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
894 }
895 }
896 //
897 // Leave critical section and return
898 //
899 gBS->RestoreTPL (OldTpl);
900
901 return ;
902 }
903
904 /**
905 Read several bytes from the scancode buffer without removing them.
906 This function is called to see if there are enough bytes of scancode
907 representing a single key.
908
909 @param Count - Number of bytes to be read
910 @param Buf - Store the results
911
912 @retval EFI_SUCCESS success to scan the keyboard code
913 @retval EFI_NOT_READY invalid parameter
914 **/
915 STATIC
916 EFI_STATUS
917 GetScancodeBufHead (
918 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
919 IN UINT32 Count,
920 OUT UINT8 *Buf
921 )
922 {
923 UINT32 Index;
924 UINT32 Pos;
925
926 Index = 0;
927 Pos = 0;
928
929 //
930 // check the valid range of parameter 'Count'
931 //
932 if (Count <= 0 || ConsoleIn->ScancodeBufCount < Count) {
933 return EFI_NOT_READY;
934 }
935 //
936 // retrieve the values
937 //
938 for (Index = 0; Index < Count; Index++) {
939
940 if (Index == 0) {
941
942 Pos = ConsoleIn->ScancodeBufStartPos;
943 } else {
944
945 Pos = Pos + 1;
946 if (Pos >= KEYBOARD_BUFFER_MAX_COUNT) {
947 Pos = 0;
948 }
949 }
950
951 Buf[Index] = ConsoleIn->ScancodeBuf[Pos];
952 }
953
954 return EFI_SUCCESS;
955 }
956
957 /**
958
959 Read & remove several bytes from the scancode buffer.
960 This function is usually called after GetScancodeBufHead()
961
962 @param Count - Number of bytes to be read
963 @param Buf - Store the results
964
965 @retval EFI_SUCCESS success to scan the keyboard code
966 @retval EFI_NOT_READY invalid parameter
967 **/
968 STATIC
969 EFI_STATUS
970 PopScancodeBufHead (
971 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
972 IN UINT32 Count,
973 OUT UINT8 *Buf
974 )
975 {
976 UINT32 Index;
977
978 Index = 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 and remove the values
988 //
989 for (Index = 0; Index < Count; Index++) {
990
991 if (Index != 0) {
992
993 ConsoleIn->ScancodeBufStartPos++;
994 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
995 ConsoleIn->ScancodeBufStartPos = 0;
996 }
997 }
998
999 Buf[Index] = ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufStartPos];
1000 ConsoleIn->ScancodeBufCount--;
1001 }
1002
1003 ConsoleIn->ScancodeBufStartPos++;
1004 if (ConsoleIn->ScancodeBufStartPos >= KEYBOARD_BUFFER_MAX_COUNT) {
1005 ConsoleIn->ScancodeBufStartPos = 0;
1006 }
1007
1008 return EFI_SUCCESS;
1009 }
1010
1011 /**
1012 Read key value
1013
1014 @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1015 @param Data - Pointer to outof buffer for keeping key value
1016
1017 @retval EFI_TIMEOUT Status resigter time out
1018 @retval EFI_SUCCESS Success to read keyboard
1019
1020 **/
1021 EFI_STATUS
1022 KeyboardRead (
1023 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1024 OUT UINT8 *Data
1025 )
1026
1027 {
1028 UINT32 TimeOut;
1029 UINT32 RegFilled;
1030
1031 TimeOut = 0;
1032 RegFilled = 0;
1033
1034 //
1035 // wait till output buffer full then perform the read
1036 //
1037 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1038 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
1039 RegFilled = 1;
1040 *Data = KeyReadDataRegister (ConsoleIn);
1041 break;
1042 }
1043
1044 gBS->Stall (30);
1045 }
1046
1047 if (!RegFilled) {
1048 return EFI_TIMEOUT;
1049 }
1050
1051 return EFI_SUCCESS;
1052 }
1053
1054 /**
1055 write key to keyboard
1056
1057 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1058 @param Data value wanted to be written
1059
1060 @retval EFI_TIMEOUT - GC_TODO: Add description for return value
1061 @retval EFI_SUCCESS - GC_TODO: Add description for return value
1062
1063 **/
1064 STATIC
1065 EFI_STATUS
1066 KeyboardWrite (
1067 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1068 IN UINT8 Data
1069 )
1070 {
1071 UINT32 TimeOut;
1072 UINT32 RegEmptied;
1073
1074 TimeOut = 0;
1075 RegEmptied = 0;
1076
1077 //
1078 // wait for input buffer empty
1079 //
1080 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1081 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
1082 RegEmptied = 1;
1083 break;
1084 }
1085
1086 gBS->Stall (30);
1087 }
1088
1089 if (!RegEmptied) {
1090 return EFI_TIMEOUT;
1091 }
1092 //
1093 // Write it
1094 //
1095 KeyWriteDataRegister (ConsoleIn, Data);
1096
1097 return EFI_SUCCESS;
1098 }
1099
1100 /**
1101 Issue keyboard command
1102
1103 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1104 @param Data The buff holding the command
1105
1106 @retval EFI_TIMEOUT Keyboard is not ready to issuing
1107 @retval EFI_SUCCESS Success to issue keyboard command
1108
1109 **/
1110 STATIC
1111 EFI_STATUS
1112 KeyboardCommand (
1113 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1114 IN UINT8 Data
1115 )
1116 {
1117 UINT32 TimeOut;
1118 UINT32 RegEmptied;
1119
1120 TimeOut = 0;
1121 RegEmptied = 0;
1122
1123 //
1124 // Wait For Input Buffer Empty
1125 //
1126 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1127 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
1128 RegEmptied = 1;
1129 break;
1130 }
1131
1132 gBS->Stall (30);
1133 }
1134
1135 if (!RegEmptied) {
1136 return EFI_TIMEOUT;
1137 }
1138 //
1139 // issue the command
1140 //
1141 KeyWriteCommandRegister (ConsoleIn, Data);
1142
1143 //
1144 // Wait For Input Buffer Empty again
1145 //
1146 RegEmptied = 0;
1147 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1148 if (!(KeyReadStatusRegister (ConsoleIn) & 0x02)) {
1149 RegEmptied = 1;
1150 break;
1151 }
1152
1153 gBS->Stall (30);
1154 }
1155
1156 if (!RegEmptied) {
1157 return EFI_TIMEOUT;
1158 }
1159
1160 return EFI_SUCCESS;
1161 }
1162
1163 /**
1164 wait for a specific value to be presented on
1165 8042 Data register by keyboard and then read it,
1166 used in keyboard commands ack
1167
1168 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1169 @param Value the value wanted to be waited.
1170
1171 @retval EFI_TIMEOUT Fail to get specific value in given time
1172 @retval EFI_SUCCESS Success to get specific value in given time.
1173
1174 **/
1175 STATIC
1176 EFI_STATUS
1177 KeyboardWaitForValue (
1178 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1179 IN UINT8 Value
1180 )
1181 {
1182 UINT8 Data;
1183 UINT32 TimeOut;
1184 UINT32 SumTimeOut;
1185 UINT32 GotIt;
1186
1187 GotIt = 0;
1188 TimeOut = 0;
1189 SumTimeOut = 0;
1190
1191 //
1192 // Make sure the initial value of 'Data' is different from 'Value'
1193 //
1194 Data = 0;
1195 if (Data == Value) {
1196 Data = 1;
1197 }
1198 //
1199 // Read from 8042 (multiple times if needed)
1200 // until the expected value appears
1201 // use SumTimeOut to control the iteration
1202 //
1203 while (1) {
1204 //
1205 // Perform a read
1206 //
1207 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
1208 if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
1209 Data = KeyReadDataRegister (ConsoleIn);
1210 break;
1211 }
1212
1213 gBS->Stall (30);
1214 }
1215
1216 SumTimeOut += TimeOut;
1217
1218 if (Data == Value) {
1219 GotIt = 1;
1220 break;
1221 }
1222
1223 if (SumTimeOut >= mWaitForValueTimeOut) {
1224 break;
1225 }
1226 }
1227 //
1228 // Check results
1229 //
1230 if (GotIt) {
1231 return EFI_SUCCESS;
1232 } else {
1233 return EFI_TIMEOUT;
1234 }
1235
1236 }
1237
1238 /**
1239 Show keyboard status lights according to
1240 indicators in ConsoleIn.
1241
1242 @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
1243
1244 @return status
1245
1246 **/
1247 EFI_STATUS
1248 UpdateStatusLights (
1249 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1250 )
1251 {
1252 EFI_STATUS Status;
1253 UINT8 Command;
1254
1255 //
1256 // Send keyboard command
1257 //
1258 Status = KeyboardWrite (ConsoleIn, 0xed);
1259 if (EFI_ERROR (Status)) {
1260 return Status;
1261 }
1262
1263 KeyboardWaitForValue (ConsoleIn, 0xfa);
1264
1265 //
1266 // Light configuration
1267 //
1268 Command = 0;
1269 if (ConsoleIn->CapsLock) {
1270 Command |= 4;
1271 }
1272
1273 if (ConsoleIn->NumLock) {
1274 Command |= 2;
1275 }
1276
1277 if (ConsoleIn->ScrollLock) {
1278 Command |= 1;
1279 }
1280
1281 Status = KeyboardWrite (ConsoleIn, Command);
1282
1283 if (EFI_ERROR (Status)) {
1284 return Status;
1285 }
1286
1287 KeyboardWaitForValue (ConsoleIn, 0xfa);
1288 return Status;
1289 }
1290
1291 /**
1292 Get scancode from scancode buffer
1293 and translate into EFI-scancode and unicode defined by EFI spec
1294 The function is always called in TPL_NOTIFY
1295
1296 @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
1297
1298 @retval EFI_NOT_READY - Input from console not ready yet.
1299 @retval EFI_SUCCESS - Function executed successfully.
1300
1301 **/
1302 EFI_STATUS
1303 KeyGetchar (
1304 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1305 )
1306 {
1307 EFI_STATUS Status;
1308 UINT8 ScanCode;
1309 UINT8 Readed;
1310 BOOLEAN Extended;
1311 UINT8 ScancodeArr[4];
1312 UINTN Index;
1313 //
1314 // 4 bytes most
1315 //
1316 UINT32 ScancodeArrPos;
1317 //
1318 // point to the current position in ScancodeArr
1319 //
1320
1321 Readed = 0;
1322 Extended = FALSE;
1323 ScancodeArrPos = 0;
1324
1325 //
1326 // Read one byte of the scan code and store it into the memory buffer
1327 // This block of code is added to insert an action that is equivalent to
1328 // the timer event handling function, so as to increase the frequency of
1329 // detecting the availability of keys. Timer event has a max frequency of
1330 // 18Hz which is insufficient
1331 //
1332 //
1333 // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
1334 // KB is not connected to system. If KB is not connected to system, driver will find there's something
1335 // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
1336 // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
1337 // Just skip the 'resend' process simply.
1338 //
1339
1340
1341 if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {
1342
1343 Readed = KeyReadDataRegister (ConsoleIn);
1344 //
1345 // put the scancode into the memory scancode buffer
1346 //
1347 ConsoleIn->ScancodeBufCount++;
1348 ConsoleIn->ScancodeBufEndPos++;
1349 if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
1350 ConsoleIn->ScancodeBufEndPos = 0;
1351 }
1352
1353 ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;
1354
1355 //
1356 // Handle Alt+Ctrl+Del Key combination
1357 //
1358 switch (Readed) {
1359
1360 case SCANCODE_CTRL_MAKE:
1361 ConsoleIn->Ctrled = TRUE;
1362 break;
1363
1364 case SCANCODE_CTRL_BREAK:
1365 ConsoleIn->Ctrled = FALSE;
1366 break;
1367
1368 case SCANCODE_ALT_MAKE:
1369 ConsoleIn->Alted = TRUE;
1370 break;
1371
1372 case SCANCODE_ALT_BREAK:
1373 ConsoleIn->Alted = FALSE;
1374 break;
1375 }
1376 //
1377 // if Alt+Ctrl+Del, Reboot the System
1378 //
1379 if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {
1380 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1381 }
1382 }
1383 //
1384 // Check if there are enough bytes of scancode representing a single key
1385 // available in the buffer
1386 //
1387 while (1) {
1388
1389 Status = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);
1390 ScancodeArrPos = 0;
1391 if (EFI_ERROR (Status)) {
1392 return EFI_NOT_READY;
1393 }
1394
1395 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {
1396 Extended = TRUE;
1397 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
1398 ScancodeArrPos = 1;
1399 if (EFI_ERROR (Status)) {
1400 return EFI_NOT_READY;
1401 }
1402 }
1403 //
1404 // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
1405 // if present, ignore them
1406 //
1407 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
1408
1409 Status = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
1410 ScancodeArrPos = 1;
1411
1412 if (EFI_ERROR (Status)) {
1413 return EFI_NOT_READY;
1414 }
1415
1416 Status = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);
1417 ScancodeArrPos = 2;
1418
1419 if (EFI_ERROR (Status)) {
1420 return EFI_NOT_READY;
1421 }
1422
1423 PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);
1424 return EFI_NOT_READY;
1425 }
1426 //
1427 // if we reach this position, scancodes for a key is in buffer now,pop them
1428 //
1429 Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);
1430 if (EFI_ERROR (Status)) {
1431 return EFI_NOT_READY;
1432 }
1433 //
1434 // store the last available byte, this byte of scancode will be checked
1435 //
1436 ScanCode = ScancodeArr[ScancodeArrPos];
1437
1438 //
1439 // Check for special keys and update the driver state.
1440 //
1441 switch (ScanCode) {
1442
1443 case SCANCODE_CTRL_MAKE:
1444 ConsoleIn->Ctrl = TRUE;
1445 break;
1446
1447 case SCANCODE_CTRL_BREAK:
1448 ConsoleIn->Ctrl = FALSE;
1449 break;
1450
1451 case SCANCODE_ALT_MAKE:
1452 ConsoleIn->Alt = TRUE;
1453 break;
1454
1455 case SCANCODE_ALT_BREAK:
1456 ConsoleIn->Alt = FALSE;
1457 break;
1458
1459 case SCANCODE_LEFT_SHIFT_MAKE:
1460 if (!Extended) {
1461 ConsoleIn->Shift = TRUE;
1462 ConsoleIn->LeftShift = TRUE;
1463 }
1464 break;
1465 case SCANCODE_RIGHT_SHIFT_MAKE:
1466 if (!Extended) {
1467 ConsoleIn->Shift = TRUE;
1468 ConsoleIn->RightShift = TRUE;
1469 }
1470 break;
1471
1472 case SCANCODE_LEFT_SHIFT_BREAK:
1473 if (!Extended) {
1474 ConsoleIn->Shift = FALSE;
1475 ConsoleIn->LeftShift = FALSE;
1476 } else {
1477 ConsoleIn->SysReq = FALSE;
1478 }
1479 break;
1480 case SCANCODE_RIGHT_SHIFT_BREAK:
1481 if (!Extended) {
1482 ConsoleIn->Shift = FALSE;
1483 ConsoleIn->RightShift = FALSE;
1484 }
1485 break;
1486
1487 case SCANCODE_LEFT_LOGO_MAKE:
1488 ConsoleIn->LeftLogo = TRUE;
1489 break;
1490 case SCANCODE_LEFT_LOGO_BREAK:
1491 ConsoleIn->LeftLogo = FALSE;
1492 break;
1493 case SCANCODE_RIGHT_LOGO_MAKE:
1494 ConsoleIn->RightLogo = TRUE;
1495 break;
1496 case SCANCODE_RIGHT_LOGO_BREAK:
1497 ConsoleIn->RightLogo = FALSE;
1498 break;
1499 case SCANCODE_MENU_MAKE:
1500 ConsoleIn->Menu = TRUE;
1501 break;
1502 case SCANCODE_MENU_BREAK:
1503 ConsoleIn->Menu = FALSE;
1504 break;
1505 case SCANCODE_SYS_REQ_MAKE:
1506 if (Extended) {
1507 ConsoleIn->SysReq = TRUE;
1508 }
1509 case SCANCODE_CAPS_LOCK_MAKE:
1510 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
1511 UpdateStatusLights (ConsoleIn);
1512 break;
1513
1514 case SCANCODE_NUM_LOCK_MAKE:
1515 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
1516 UpdateStatusLights (ConsoleIn);
1517 break;
1518
1519 case SCANCODE_SCROLL_LOCK_MAKE:
1520 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
1521 UpdateStatusLights (ConsoleIn);
1522 break;
1523 }
1524 //
1525 // If this is a BREAK Key or above the valid range, ignore it
1526 //
1527 if (ScanCode >= SCANCODE_MAX_MAKE) {
1528 continue;
1529 } else {
1530 break;
1531 }
1532 }
1533 //
1534 // Treat Numeric Key Pad "/" specially
1535 //
1536 if (Extended && ScanCode == 0x35) {
1537 ConsoleIn->Key.ScanCode = SCAN_NULL;
1538 ConsoleIn->Key.UnicodeChar = '/';
1539 return EFI_SUCCESS;
1540 }
1541 //
1542 // Convert Keyboard ScanCode into an EFI Key
1543 //
1544 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {
1545 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
1546 ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
1547 if (ConsoleIn->Shift) {
1548 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
1549 //
1550 // Need not return associated shift state if a class of printable characters that
1551 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1552 //
1553 if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
1554 ConsoleIn->LeftShift = FALSE;
1555 ConsoleIn->RightShift = FALSE;
1556 }
1557 } else {
1558 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
1559 }
1560 //
1561 // alphabetic key is affected by CapsLock State
1562 //
1563 if (ConsoleIn->CapsLock) {
1564 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {
1565 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
1566 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
1567 ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
1568 }
1569 }
1570 //
1571 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1572 //
1573 if (ConsoleIn->Ctrled) {
1574 if (ConsoleIn->Key.UnicodeChar >= 'a' && ConsoleIn->Key.UnicodeChar <= 'z') {
1575 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'a' + 1);
1576 } else if (ConsoleIn->Key.UnicodeChar >= 'A' && ConsoleIn->Key.UnicodeChar <= 'Z') {
1577 ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - 'A' + 1);
1578 }
1579 }
1580
1581 break;
1582 }
1583 }
1584
1585 //
1586 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1587 //
1588 if (ScanCode >= 0x47 && ScanCode <= 0x53) {
1589
1590 if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {
1591 ConsoleIn->Key.ScanCode = SCAN_NULL;
1592 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
1593 ConsoleIn->Key.UnicodeChar = 0x00;
1594 }
1595 }
1596 //
1597 // If the key can not be converted then just return.
1598 //
1599 if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {
1600 return EFI_NOT_READY;
1601 }
1602
1603 //
1604 // Save the Shift/Toggle state
1605 //
1606 if (ConsoleIn->Ctrl) {
1607 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;
1608 }
1609 if (ConsoleIn->Alt) {
1610 ConsoleIn->KeyState.KeyShiftState |= (Extended == TRUE) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;
1611 }
1612 if (ConsoleIn->LeftShift) {
1613 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;
1614 }
1615 if (ConsoleIn->RightShift) {
1616 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;
1617 }
1618 if (ConsoleIn->LeftLogo) {
1619 ConsoleIn->KeyState.KeyShiftState |= EFI_LEFT_LOGO_PRESSED;
1620 }
1621 if (ConsoleIn->RightLogo) {
1622 ConsoleIn->KeyState.KeyShiftState |= EFI_RIGHT_LOGO_PRESSED;
1623 }
1624 if (ConsoleIn->Menu) {
1625 ConsoleIn->KeyState.KeyShiftState |= EFI_MENU_KEY_PRESSED;
1626 }
1627 if (ConsoleIn->SysReq) {
1628 ConsoleIn->KeyState.KeyShiftState |= EFI_SYS_REQ_PRESSED;
1629 }
1630 if (ConsoleIn->CapsLock) {
1631 ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
1632 }
1633 if (ConsoleIn->NumLock) {
1634 ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
1635 }
1636 if (ConsoleIn->ScrollLock) {
1637 ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
1638 }
1639
1640 return EFI_SUCCESS;
1641 }
1642
1643 /**
1644 Perform 8042 controller and keyboard Initialization
1645 If ExtendedVerification is TRUE, do additional test for
1646 the keyboard interface
1647
1648 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1649 @param ExtendedVerification - indicates a thorough initialization
1650
1651 @retval EFI_DEVICE_ERROR Fail to init keyboard
1652 @retval EFI_SUCCESS Success to init keyboard
1653 **/
1654 EFI_STATUS
1655 InitKeyboard (
1656 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1657 IN BOOLEAN ExtendedVerification
1658 )
1659 {
1660 EFI_STATUS Status;
1661 EFI_STATUS Status1;
1662 UINT8 CommandByte;
1663 STATIC BOOLEAN EnableMouseInterface;
1664 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
1665
1666 Status = EFI_SUCCESS;
1667 EnableMouseInterface = TRUE;
1668
1669 //
1670 // Get Ps2 policy to set this
1671 //
1672 Status = gBS->LocateProtocol (
1673 &gEfiPs2PolicyProtocolGuid,
1674 NULL,
1675 (VOID **) &Ps2Policy
1676 );
1677
1678 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1679 EFI_PROGRESS_CODE,
1680 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
1681 ConsoleIn->DevicePath
1682 );
1683
1684 //
1685 // Perform a read to cleanup the Status Register's
1686 // output buffer full bits
1687 //
1688 while (!EFI_ERROR (Status)) {
1689 Status = KeyboardRead (ConsoleIn, &CommandByte);
1690 }
1691 //
1692 // We should disable mouse interface during the initialization process
1693 // since mouse device output could block keyboard device output in the
1694 // 60H port of 8042 controller.
1695 //
1696 // So if we are not initializing 8042 controller for the
1697 // first time, we have to remember the previous mouse interface
1698 // enabling state
1699 //
1700 // Test the system flag in to determine whether this is the first
1701 // time initialization
1702 //
1703 if ((KeyReadStatusRegister (ConsoleIn) & 0x04)) {
1704 //
1705 // 8042 controller is already setup (by myself or by mouse driver):
1706 // See whether mouse interface is already enabled
1707 // which determines whether we should enable it later
1708 //
1709 //
1710 // Read the command byte of 8042 controller
1711 //
1712 Status = KeyboardCommand (ConsoleIn, 0x20);
1713 if (EFI_ERROR (Status)) {
1714 KeyboardError (ConsoleIn, L"\n\r");
1715 goto Done;
1716 }
1717
1718 Status = KeyboardRead (ConsoleIn, &CommandByte);
1719 if (EFI_ERROR (Status)) {
1720 KeyboardError (ConsoleIn, L"\n\r");
1721 goto Done;
1722 }
1723 //
1724 // Test the mouse enabling bit
1725 //
1726 if (CommandByte & 0x20) {
1727 EnableMouseInterface = FALSE;
1728 } else {
1729 EnableMouseInterface = TRUE;
1730 }
1731
1732 } else {
1733 //
1734 // 8042 controller is not setup yet:
1735 // 8042 controller selftest;
1736 // Don't enable mouse interface later.
1737 //
1738 //
1739 // Disable keyboard and mouse interfaces
1740 //
1741 Status = KeyboardCommand (ConsoleIn, 0xad);
1742 if (EFI_ERROR (Status)) {
1743 KeyboardError (ConsoleIn, L"\n\r");
1744 goto Done;
1745 }
1746
1747 Status = KeyboardCommand (ConsoleIn, 0xa7);
1748 if (EFI_ERROR (Status)) {
1749 KeyboardError (ConsoleIn, L"\n\r");
1750 goto Done;
1751 }
1752
1753 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1754 EFI_PROGRESS_CODE,
1755 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
1756 ConsoleIn->DevicePath
1757 );
1758 //
1759 // 8042 Controller Self Test
1760 //
1761 Status = KeyboardCommand (ConsoleIn, 0xaa);
1762 if (EFI_ERROR (Status)) {
1763 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1764 goto Done;
1765 }
1766
1767 Status = KeyboardWaitForValue (ConsoleIn, 0x55);
1768 if (EFI_ERROR (Status)) {
1769 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
1770 goto Done;
1771 }
1772 //
1773 // Don't enable mouse interface later
1774 //
1775 EnableMouseInterface = FALSE;
1776
1777 }
1778
1779 if (Ps2Policy != NULL) {
1780 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
1781 }
1782 //
1783 // Write 8042 Command Byte, set System Flag
1784 // While at the same time:
1785 // 1. disable mouse interface,
1786 // 2. enable kbd interface,
1787 // 3. enable PC/XT kbd translation mode
1788 // 4. enable mouse and kbd interrupts
1789 //
1790 // ( Command Byte bits:
1791 // 7: Reserved
1792 // 6: PC/XT translation mode
1793 // 5: Disable Auxiliary device interface
1794 // 4: Disable keyboard interface
1795 // 3: Reserved
1796 // 2: System Flag
1797 // 1: Enable Auxiliary device interrupt
1798 // 0: Enable Keyboard interrupt )
1799 //
1800 Status = KeyboardCommand (ConsoleIn, 0x60);
1801 if (EFI_ERROR (Status)) {
1802 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1803 goto Done;
1804 }
1805
1806 Status = KeyboardWrite (ConsoleIn, 0x67);
1807 if (EFI_ERROR (Status)) {
1808 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1809 goto Done;
1810 }
1811
1812 //
1813 // Clear Memory Scancode Buffer
1814 //
1815 ConsoleIn->ScancodeBufStartPos = 0;
1816 ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1;
1817 ConsoleIn->ScancodeBufCount = 0;
1818 ConsoleIn->Ctrled = FALSE;
1819 ConsoleIn->Alted = FALSE;
1820
1821 //
1822 // Reset the status indicators
1823 //
1824 ConsoleIn->Ctrl = FALSE;
1825 ConsoleIn->Alt = FALSE;
1826 ConsoleIn->Shift = FALSE;
1827 ConsoleIn->CapsLock = FALSE;
1828 ConsoleIn->NumLock = FALSE;
1829 ConsoleIn->ScrollLock = FALSE;
1830 ConsoleIn->LeftShift = FALSE;
1831 ConsoleIn->RightShift = FALSE;
1832 ConsoleIn->LeftLogo = FALSE;
1833 ConsoleIn->RightLogo = FALSE;
1834 ConsoleIn->Menu = FALSE;
1835 ConsoleIn->SysReq = FALSE;
1836
1837 //
1838 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1839 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1840 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
1841 // and normally during booting an OS, it's skipped.
1842 //
1843 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
1844 //
1845 // Additional verifications for keyboard interface
1846 //
1847 //
1848 // Keyboard Interface Test
1849 //
1850 Status = KeyboardCommand (ConsoleIn, 0xab);
1851 if (EFI_ERROR (Status)) {
1852 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1853 goto Done;
1854 }
1855
1856 Status = KeyboardWaitForValue (ConsoleIn, 0x00);
1857 if (EFI_ERROR (Status)) {
1858 KeyboardError (
1859 ConsoleIn,
1860 L"Some specific value not aquired from 8042 controller!\n\r"
1861 );
1862 goto Done;
1863 }
1864 //
1865 // Keyboard reset with a BAT(Basic Assurance Test)
1866 //
1867 Status = KeyboardWrite (ConsoleIn, 0xff);
1868 if (EFI_ERROR (Status)) {
1869 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1870 goto Done;
1871 }
1872
1873 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
1874 if (EFI_ERROR (Status)) {
1875 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1876 goto Done;
1877 }
1878 //
1879 // wait for BAT completion code
1880 //
1881 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;
1882
1883 Status = KeyboardWaitForValue (ConsoleIn, 0xaa);
1884 if (EFI_ERROR (Status)) {
1885 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
1886 goto Done;
1887 }
1888
1889 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
1890
1891 //
1892 // Set Keyboard to use Scan Code Set 2
1893 //
1894 Status = KeyboardWrite (ConsoleIn, 0xf0);
1895 if (EFI_ERROR (Status)) {
1896 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1897 goto Done;
1898 }
1899
1900 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
1901 if (EFI_ERROR (Status)) {
1902 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1903 goto Done;
1904 }
1905
1906 Status = KeyboardWrite (ConsoleIn, 0x02);
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 //
1919 // Clear Keyboard Scancode Buffer
1920 //
1921 Status = KeyboardWrite (ConsoleIn, 0xf4);
1922 if (EFI_ERROR (Status)) {
1923 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1924 goto Done;
1925 }
1926
1927 Status = KeyboardWaitForValue (ConsoleIn, 0xfa);
1928 if (EFI_ERROR (Status)) {
1929 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1930 goto Done;
1931 }
1932 //
1933 if (Ps2Policy != NULL) {
1934 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
1935 ConsoleIn->CapsLock = TRUE;
1936 }
1937
1938 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
1939 ConsoleIn->NumLock = TRUE;
1940 }
1941
1942 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
1943 ConsoleIn->ScrollLock = TRUE;
1944 }
1945 }
1946 //
1947 // Update Keyboard Lights
1948 //
1949 Status = UpdateStatusLights (ConsoleIn);
1950 if (EFI_ERROR (Status)) {
1951 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
1952 goto Done;
1953 }
1954 }
1955 //
1956 // At last, we can now enable the mouse interface if appropriate
1957 //
1958 Done:
1959
1960 if (EnableMouseInterface) {
1961 //
1962 // Enable mouse interface
1963 //
1964 Status1 = KeyboardCommand (ConsoleIn, 0xa8);
1965 if (EFI_ERROR (Status1)) {
1966 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1967 return EFI_DEVICE_ERROR;
1968 }
1969 }
1970
1971 if (!EFI_ERROR (Status)) {
1972 return EFI_SUCCESS;
1973 } else {
1974 return EFI_DEVICE_ERROR;
1975 }
1976
1977 }
1978
1979 /**
1980 Disable the keyboard interface of the 8042 controller
1981
1982 @param ConsoleIn - the device instance
1983
1984 @return status of issuing disable command
1985
1986 **/
1987 EFI_STATUS
1988 DisableKeyboard (
1989 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1990 )
1991 {
1992 EFI_STATUS Status;
1993
1994 //
1995 // Disable keyboard interface
1996 //
1997 Status = KeyboardCommand (ConsoleIn, 0xad);
1998 if (EFI_ERROR (Status)) {
1999 KeyboardError (ConsoleIn, L"\n\r");
2000 return EFI_DEVICE_ERROR;
2001 }
2002
2003 return Status;
2004 }
2005
2006 /**
2007 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
2008 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
2009 should not be in system.
2010
2011 @param[in] BiosKeyboardPrivate Keyboard Private Data Structure
2012
2013 @retval TRUE Keyboard in System.
2014 @retval FALSE Keyboard not in System.
2015 **/
2016 BOOLEAN
2017 EFIAPI
2018 CheckKeyboardConnect (
2019 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
2020 )
2021 {
2022 EFI_STATUS Status;
2023 UINTN WaitForValueTimeOutBcakup;
2024
2025 Status = EFI_SUCCESS;
2026 //
2027 // enable keyboard itself and wait for its ack
2028 // If can't receive ack, Keyboard should not be connected.
2029 //
2030 Status = KeyboardWrite (
2031 ConsoleIn,
2032 KEYBOARD_KBEN
2033 );
2034
2035 if (EFI_ERROR (Status)) {
2036 return FALSE;
2037 }
2038 //
2039 // wait for 1s
2040 //
2041 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
2042 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
2043 Status = KeyboardWaitForValue (
2044 ConsoleIn,
2045 KEYBOARD_CMDECHO_ACK
2046 );
2047 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
2048
2049 if (EFI_ERROR (Status)) {
2050 return FALSE;
2051 }
2052
2053 return TRUE;
2054 }
2055