]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
Fix Ps2KeyboardDxe driver to return correct key data when Shift/Ctrl/Alt and PrtSc...
[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 UINT16 ScanCode;
1156 BOOLEAN Extend0;
1157 BOOLEAN Extend1;
1158 UINTN Index;
1159 EFI_KEY_DATA KeyData;
1160 LIST_ENTRY *Link;
1161 KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
1162 //
1163 // 3 bytes most
1164 //
1165 UINT8 ScancodeArr[3];
1166 UINT32 ScancodeArrPos;
1167
1168 //
1169 // Check if there are enough bytes of scancode representing a single key
1170 // available in the buffer
1171 //
1172 while (TRUE) {
1173 Extend0 = FALSE;
1174 Extend1 = FALSE;
1175 ScancodeArrPos = 0;
1176 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1177 if (EFI_ERROR (Status)) {
1178 return ;
1179 }
1180
1181 if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
1182 //
1183 // E0 to look ahead 2 bytes
1184 //
1185 Extend0 = TRUE;
1186 ScancodeArrPos = 1;
1187 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1188 if (EFI_ERROR (Status)) {
1189 return ;
1190 }
1191 } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
1192 //
1193 // E1 to look ahead 3 bytes
1194 //
1195 Extend1 = TRUE;
1196 ScancodeArrPos = 2;
1197 Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1198 if (EFI_ERROR (Status)) {
1199 return ;
1200 }
1201 }
1202 //
1203 // if we reach this position, scancodes for a key is in buffer now,pop them
1204 //
1205 Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
1206 ASSERT_EFI_ERROR (Status);
1207
1208 //
1209 // store the last available byte, this byte of scancode will be checked
1210 //
1211 ScanCode = ScancodeArr[ScancodeArrPos];
1212
1213 if (!Extend1) {
1214 //
1215 // Check for special keys and update the driver state.
1216 //
1217 switch (ScanCode) {
1218
1219 case SCANCODE_CTRL_MAKE:
1220 if (Extend0) {
1221 ConsoleIn->RightCtrl = TRUE;
1222 } else {
1223 ConsoleIn->LeftCtrl = TRUE;
1224 }
1225 break;
1226 case SCANCODE_CTRL_BREAK:
1227 if (Extend0) {
1228 ConsoleIn->RightCtrl = FALSE;
1229 } else {
1230 ConsoleIn->LeftCtrl = FALSE;
1231 }
1232 break;
1233
1234 case SCANCODE_ALT_MAKE:
1235 if (Extend0) {
1236 ConsoleIn->RightAlt = TRUE;
1237 } else {
1238 ConsoleIn->LeftAlt = TRUE;
1239 }
1240 break;
1241 case SCANCODE_ALT_BREAK:
1242 if (Extend0) {
1243 ConsoleIn->RightAlt = FALSE;
1244 } else {
1245 ConsoleIn->LeftAlt = FALSE;
1246 }
1247 break;
1248
1249 case SCANCODE_LEFT_SHIFT_MAKE:
1250 //
1251 // To avoid recognize PRNT_SCRN key as a L_SHIFT key
1252 // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code
1253 //
1254 if (!Extend0) {
1255 ConsoleIn->LeftShift = TRUE;
1256 }
1257 break;
1258 case SCANCODE_LEFT_SHIFT_BREAK:
1259 if (!Extend0) {
1260 ConsoleIn->LeftShift = FALSE;
1261 }
1262 break;
1263
1264 case SCANCODE_RIGHT_SHIFT_MAKE:
1265 ConsoleIn->RightShift = TRUE;
1266 break;
1267 case SCANCODE_RIGHT_SHIFT_BREAK:
1268 ConsoleIn->RightShift = FALSE;
1269 break;
1270
1271 case SCANCODE_LEFT_LOGO_MAKE:
1272 ConsoleIn->LeftLogo = TRUE;
1273 break;
1274 case SCANCODE_LEFT_LOGO_BREAK:
1275 ConsoleIn->LeftLogo = FALSE;
1276 break;
1277
1278 case SCANCODE_RIGHT_LOGO_MAKE:
1279 ConsoleIn->RightLogo = TRUE;
1280 break;
1281 case SCANCODE_RIGHT_LOGO_BREAK:
1282 ConsoleIn->RightLogo = FALSE;
1283 break;
1284
1285 case SCANCODE_MENU_MAKE:
1286 ConsoleIn->Menu = TRUE;
1287 break;
1288 case SCANCODE_MENU_BREAK:
1289 ConsoleIn->Menu = FALSE;
1290 break;
1291
1292 case SCANCODE_SYS_REQ_MAKE:
1293 if (Extend0) {
1294 ConsoleIn->SysReq = TRUE;
1295 }
1296 break;
1297 case SCANCODE_SYS_REQ_BREAK:
1298 if (Extend0) {
1299 ConsoleIn->SysReq = FALSE;
1300 }
1301 break;
1302
1303 case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
1304 ConsoleIn->SysReq = TRUE;
1305 break;
1306 case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
1307 ConsoleIn->SysReq = FALSE;
1308 break;
1309
1310 case SCANCODE_CAPS_LOCK_MAKE:
1311 ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
1312 UpdateStatusLights (ConsoleIn);
1313 break;
1314 case SCANCODE_NUM_LOCK_MAKE:
1315 ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
1316 UpdateStatusLights (ConsoleIn);
1317 break;
1318 case SCANCODE_SCROLL_LOCK_MAKE:
1319 if (!Extend0) {
1320 ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
1321 UpdateStatusLights (ConsoleIn);
1322 }
1323 break;
1324 }
1325 }
1326
1327 //
1328 // If this is above the valid range, ignore it
1329 //
1330 if (ScanCode >= SCANCODE_MAX_MAKE) {
1331 continue;
1332 } else {
1333 break;
1334 }
1335 }
1336
1337 //
1338 // Handle Ctrl+Alt+Del hotkey
1339 //
1340 if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
1341 (ConsoleIn->LeftAlt || ConsoleIn->RightAlt ) &&
1342 ScanCode == SCANCODE_DELETE_MAKE
1343 ) {
1344 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1345 }
1346
1347 //
1348 // Save the Shift/Toggle state
1349 //
1350 KeyData.KeyState.KeyShiftState = (UINT32) (EFI_SHIFT_STATE_VALID
1351 | (ConsoleIn->LeftCtrl ? EFI_LEFT_CONTROL_PRESSED : 0)
1352 | (ConsoleIn->RightCtrl ? EFI_RIGHT_CONTROL_PRESSED : 0)
1353 | (ConsoleIn->LeftAlt ? EFI_LEFT_ALT_PRESSED : 0)
1354 | (ConsoleIn->RightAlt ? EFI_RIGHT_ALT_PRESSED : 0)
1355 | (ConsoleIn->LeftShift ? EFI_LEFT_SHIFT_PRESSED : 0)
1356 | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED : 0)
1357 | (ConsoleIn->LeftLogo ? EFI_LEFT_LOGO_PRESSED : 0)
1358 | (ConsoleIn->RightLogo ? EFI_RIGHT_LOGO_PRESSED : 0)
1359 | (ConsoleIn->Menu ? EFI_MENU_KEY_PRESSED : 0)
1360 | (ConsoleIn->SysReq ? EFI_SYS_REQ_PRESSED : 0)
1361 )
1362 ;
1363 KeyData.KeyState.KeyToggleState = (EFI_KEY_TOGGLE_STATE) (EFI_TOGGLE_STATE_VALID
1364 | (ConsoleIn->CapsLock ? EFI_CAPS_LOCK_ACTIVE : 0)
1365 | (ConsoleIn->NumLock ? EFI_NUM_LOCK_ACTIVE : 0)
1366 | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)
1367 )
1368 ;
1369 KeyData.Key.ScanCode = SCAN_NULL;
1370 KeyData.Key.UnicodeChar = CHAR_NULL;
1371
1372 //
1373 // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix
1374 //
1375 if (Extend0 && ScanCode == 0x35) {
1376 KeyData.Key.UnicodeChar = L'/';
1377 KeyData.Key.ScanCode = SCAN_NULL;
1378
1379 //
1380 // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
1381 //
1382 } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
1383 KeyData.Key.UnicodeChar = CHAR_NULL;
1384 KeyData.Key.ScanCode = SCAN_PAUSE;
1385
1386 //
1387 // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix
1388 //
1389 } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
1390 KeyData.Key.UnicodeChar = CHAR_NULL;
1391 KeyData.Key.ScanCode = SCAN_PAUSE;
1392
1393 //
1394 // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix
1395 //
1396 } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
1397 KeyData.Key.UnicodeChar = CHAR_NULL;
1398 KeyData.Key.ScanCode = SCAN_NULL;
1399
1400 //
1401 // Except the above special case, all others can be handled by convert table
1402 //
1403 } else {
1404 for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {
1405 if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
1406 KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
1407 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
1408
1409 if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
1410 (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
1411 KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
1412 //
1413 // Need not return associated shift state if a class of printable characters that
1414 // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
1415 //
1416 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
1417 }
1418 //
1419 // alphabetic key is affected by CapsLock State
1420 //
1421 if (ConsoleIn->CapsLock) {
1422 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
1423 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');
1424 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
1425 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');
1426 }
1427 }
1428 break;
1429 }
1430 }
1431 }
1432
1433 //
1434 // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
1435 //
1436 if (ScanCode >= 0x47 && ScanCode <= 0x53) {
1437 if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {
1438 KeyData.Key.ScanCode = SCAN_NULL;
1439 } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
1440 KeyData.Key.UnicodeChar = CHAR_NULL;
1441 }
1442 }
1443 //
1444 // If the key can not be converted then just return.
1445 //
1446 if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
1447 return ;
1448 }
1449
1450 //
1451 // Invoke notification functions if exist
1452 //
1453 for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {
1454 CurrentNotify = CR (
1455 Link,
1456 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
1457 NotifyEntry,
1458 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1459 );
1460 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
1461 CurrentNotify->KeyNotificationFn (&KeyData);
1462 }
1463 }
1464
1465 //
1466 // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
1467 //
1468 if (ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) {
1469 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
1470 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + 1);
1471 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
1472 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + 1);
1473 }
1474 }
1475
1476 PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
1477 }
1478
1479 /**
1480 Perform 8042 controller and keyboard Initialization.
1481 If ExtendedVerification is TRUE, do additional test for
1482 the keyboard interface
1483
1484 @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
1485 @param ExtendedVerification - indicates a thorough initialization
1486
1487 @retval EFI_DEVICE_ERROR Fail to init keyboard
1488 @retval EFI_SUCCESS Success to init keyboard
1489 **/
1490 EFI_STATUS
1491 InitKeyboard (
1492 IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
1493 IN BOOLEAN ExtendedVerification
1494 )
1495 {
1496 EFI_STATUS Status;
1497 EFI_STATUS Status1;
1498 UINT8 CommandByte;
1499 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
1500 UINT32 TryTime;
1501
1502 Status = EFI_SUCCESS;
1503 mEnableMouseInterface = TRUE;
1504 TryTime = 0;
1505
1506 //
1507 // Get Ps2 policy to set this
1508 //
1509 gBS->LocateProtocol (
1510 &gEfiPs2PolicyProtocolGuid,
1511 NULL,
1512 (VOID **) &Ps2Policy
1513 );
1514
1515 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1516 EFI_PROGRESS_CODE,
1517 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
1518 ConsoleIn->DevicePath
1519 );
1520
1521 //
1522 // Perform a read to cleanup the Status Register's
1523 // output buffer full bits within MAX TRY times
1524 //
1525 while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
1526 Status = KeyboardRead (ConsoleIn, &CommandByte);
1527 TryTime ++;
1528 }
1529 //
1530 // Exceed the max try times. The device may be error.
1531 //
1532 if (TryTime == KEYBOARD_MAX_TRY) {
1533 Status = EFI_DEVICE_ERROR;
1534 goto Done;
1535 }
1536 //
1537 // We should disable mouse interface during the initialization process
1538 // since mouse device output could block keyboard device output in the
1539 // 60H port of 8042 controller.
1540 //
1541 // So if we are not initializing 8042 controller for the
1542 // first time, we have to remember the previous mouse interface
1543 // enabling state
1544 //
1545 // Test the system flag in to determine whether this is the first
1546 // time initialization
1547 //
1548 if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
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
1577 } else {
1578 //
1579 // 8042 controller is not setup yet:
1580 // 8042 controller selftest;
1581 // Don't enable mouse interface later.
1582 //
1583 //
1584 // Disable keyboard and mouse interfaces
1585 //
1586 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
1587 if (EFI_ERROR (Status)) {
1588 KeyboardError (ConsoleIn, L"\n\r");
1589 goto Done;
1590 }
1591
1592 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
1593 if (EFI_ERROR (Status)) {
1594 KeyboardError (ConsoleIn, L"\n\r");
1595 goto Done;
1596 }
1597
1598 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1599 EFI_PROGRESS_CODE,
1600 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
1601 ConsoleIn->DevicePath
1602 );
1603 //
1604 // 8042 Controller Self Test
1605 //
1606 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
1607 if (EFI_ERROR (Status)) {
1608 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1609 goto Done;
1610 }
1611
1612 Status = KeyboardWaitForValue (ConsoleIn, 0x55);
1613 if (EFI_ERROR (Status)) {
1614 KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
1615 goto Done;
1616 }
1617 //
1618 // Don't enable mouse interface later
1619 //
1620 mEnableMouseInterface = FALSE;
1621
1622 }
1623
1624 if (Ps2Policy != NULL) {
1625 Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
1626 }
1627 //
1628 // Write 8042 Command Byte, set System Flag
1629 // While at the same time:
1630 // 1. disable mouse interface,
1631 // 2. enable kbd interface,
1632 // 3. enable PC/XT kbd translation mode
1633 // 4. enable mouse and kbd interrupts
1634 //
1635 // ( Command Byte bits:
1636 // 7: Reserved
1637 // 6: PC/XT translation mode
1638 // 5: Disable Auxiliary device interface
1639 // 4: Disable keyboard interface
1640 // 3: Reserved
1641 // 2: System Flag
1642 // 1: Enable Auxiliary device interrupt
1643 // 0: Enable Keyboard interrupt )
1644 //
1645 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
1646 if (EFI_ERROR (Status)) {
1647 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1648 goto Done;
1649 }
1650
1651 Status = KeyboardWrite (ConsoleIn, 0x67);
1652 if (EFI_ERROR (Status)) {
1653 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1654 goto Done;
1655 }
1656
1657 //
1658 // Clear Memory Scancode Buffer
1659 //
1660 ConsoleIn->ScancodeQueue.Head = 0;
1661 ConsoleIn->ScancodeQueue.Tail = 0;
1662 ConsoleIn->EfiKeyQueue.Head = 0;
1663 ConsoleIn->EfiKeyQueue.Tail = 0;
1664
1665 //
1666 // Reset the status indicators
1667 //
1668 ConsoleIn->CapsLock = FALSE;
1669 ConsoleIn->NumLock = FALSE;
1670 ConsoleIn->ScrollLock = FALSE;
1671 ConsoleIn->LeftCtrl = FALSE;
1672 ConsoleIn->RightCtrl = FALSE;
1673 ConsoleIn->LeftAlt = FALSE;
1674 ConsoleIn->RightAlt = FALSE;
1675 ConsoleIn->LeftShift = FALSE;
1676 ConsoleIn->RightShift = FALSE;
1677 ConsoleIn->LeftLogo = FALSE;
1678 ConsoleIn->RightLogo = FALSE;
1679 ConsoleIn->Menu = FALSE;
1680 ConsoleIn->SysReq = FALSE;
1681
1682 //
1683 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
1684 // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
1685 // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
1686 // and normally during booting an OS, it's skipped.
1687 //
1688 if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
1689 //
1690 // Additional verifications for keyboard interface
1691 //
1692 //
1693 // Keyboard Interface Test
1694 //
1695 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
1696 if (EFI_ERROR (Status)) {
1697 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1698 goto Done;
1699 }
1700
1701 Status = KeyboardWaitForValue (ConsoleIn, 0x00);
1702 if (EFI_ERROR (Status)) {
1703 KeyboardError (
1704 ConsoleIn,
1705 L"Some specific value not aquired from 8042 controller!\n\r"
1706 );
1707 goto Done;
1708 }
1709 //
1710 // Keyboard reset with a BAT(Basic Assurance Test)
1711 //
1712 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
1713 if (EFI_ERROR (Status)) {
1714 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1715 goto Done;
1716 }
1717
1718 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1719 if (EFI_ERROR (Status)) {
1720 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1721 goto Done;
1722 }
1723 //
1724 // wait for BAT completion code
1725 //
1726 mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;
1727
1728 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
1729 if (EFI_ERROR (Status)) {
1730 KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
1731 goto Done;
1732 }
1733
1734 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
1735
1736 //
1737 // Set Keyboard to use Scan Code Set 2
1738 //
1739 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
1740 if (EFI_ERROR (Status)) {
1741 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1742 goto Done;
1743 }
1744
1745 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1746 if (EFI_ERROR (Status)) {
1747 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1748 goto Done;
1749 }
1750
1751 Status = KeyboardWrite (ConsoleIn, 0x02);
1752 if (EFI_ERROR (Status)) {
1753 KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
1754 goto Done;
1755 }
1756
1757 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1758 if (EFI_ERROR (Status)) {
1759 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1760 goto Done;
1761 }
1762
1763 //
1764 // Clear Keyboard Scancode Buffer
1765 //
1766 Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
1767 if (EFI_ERROR (Status)) {
1768 KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
1769 goto Done;
1770 }
1771
1772 Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
1773 if (EFI_ERROR (Status)) {
1774 KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
1775 goto Done;
1776 }
1777 //
1778 if (Ps2Policy != NULL) {
1779 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
1780 ConsoleIn->CapsLock = TRUE;
1781 }
1782
1783 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
1784 ConsoleIn->NumLock = TRUE;
1785 }
1786
1787 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
1788 ConsoleIn->ScrollLock = TRUE;
1789 }
1790 }
1791 //
1792 // Update Keyboard Lights
1793 //
1794 Status = UpdateStatusLights (ConsoleIn);
1795 if (EFI_ERROR (Status)) {
1796 KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
1797 goto Done;
1798 }
1799 }
1800 //
1801 // At last, we can now enable the mouse interface if appropriate
1802 //
1803 Done:
1804
1805 if (mEnableMouseInterface) {
1806 //
1807 // Enable mouse interface
1808 //
1809 Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
1810 if (EFI_ERROR (Status1)) {
1811 KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
1812 return EFI_DEVICE_ERROR;
1813 }
1814 }
1815
1816 if (!EFI_ERROR (Status)) {
1817 return EFI_SUCCESS;
1818 } else {
1819 return EFI_DEVICE_ERROR;
1820 }
1821
1822 }
1823
1824 /**
1825 Disable the keyboard interface of the 8042 controller.
1826
1827 @param ConsoleIn The device instance
1828
1829 @return status of issuing disable command
1830
1831 **/
1832 EFI_STATUS
1833 DisableKeyboard (
1834 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1835 )
1836 {
1837 EFI_STATUS Status;
1838
1839 //
1840 // Disable keyboard interface
1841 //
1842 Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
1843 if (EFI_ERROR (Status)) {
1844 KeyboardError (ConsoleIn, L"\n\r");
1845 return EFI_DEVICE_ERROR;
1846 }
1847
1848 return Status;
1849 }
1850
1851 /**
1852 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
1853 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
1854 should not be in system.
1855
1856 @param[in] ConsoleIn Keyboard Private Data Structure
1857
1858 @retval TRUE Keyboard in System.
1859 @retval FALSE Keyboard not in System.
1860 **/
1861 BOOLEAN
1862 EFIAPI
1863 CheckKeyboardConnect (
1864 IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
1865 )
1866 {
1867 EFI_STATUS Status;
1868 UINTN WaitForValueTimeOutBcakup;
1869
1870 Status = EFI_SUCCESS;
1871 //
1872 // enable keyboard itself and wait for its ack
1873 // If can't receive ack, Keyboard should not be connected.
1874 //
1875 Status = KeyboardWrite (
1876 ConsoleIn,
1877 KEYBOARD_KBEN
1878 );
1879
1880 if (EFI_ERROR (Status)) {
1881 return FALSE;
1882 }
1883 //
1884 // wait for 1s
1885 //
1886 WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
1887 mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
1888 Status = KeyboardWaitForValue (
1889 ConsoleIn,
1890 KEYBOARD_CMDECHO_ACK
1891 );
1892 mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
1893
1894 if (EFI_ERROR (Status)) {
1895 return FALSE;
1896 }
1897
1898 return TRUE;
1899 }
1900