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