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