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