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