1/** @file
2  Routines that access 8042 keyboard controller
3
4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "Ps2Keyboard.h"
16
17struct {
18  UINT8   ScanCode;             ///< follows value defined in Scan Code Set1
19  UINT16  EfiScanCode;
20  CHAR16  UnicodeChar;
21  CHAR16  ShiftUnicodeChar;
22}
23ConvertKeyboardScanCodeToEfiKey[] = {
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//
564UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
565
566BOOLEAN          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**/
577UINTN
578GetScancodeBufCount (
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**/
601EFI_STATUS
602GetScancodeBufHead (
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**/
639EFI_STATUS
640PopScancodeBufHead (
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**/
672VOID
673PushScancodeBufTail (
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**/
694UINT8
695KeyReadDataRegister (
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**/
726VOID
727KeyWriteDataRegister (
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**/
749UINT8
750KeyReadStatusRegister (
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**/
772VOID
773KeyWriteCommandRegister (
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**/
794VOID
795KeyboardError (
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**/
814VOID
815EFIAPI
816KeyboardTimerHandler (
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**/
876EFI_STATUS
877KeyboardRead (
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**/
919EFI_STATUS
920KeyboardWrite (
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**/
964EFI_STATUS
965KeyboardCommand (
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**/
1028EFI_STATUS
1029KeyboardWaitForValue (
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**/
1099EFI_STATUS
1100UpdateStatusLights (
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**/
1151VOID
1152KeyGetchar (
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**/
1493EFI_STATUS
1494InitKeyboard (
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  //
1816Done:
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**/
1845EFI_STATUS
1846DisableKeyboard (
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**/
1874BOOLEAN
1875EFIAPI
1876CheckKeyboardConnect (
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