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