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