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