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