EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c

Go to the documentation of this file.
00001 
00015 #include "Ps2Keyboard.h"
00016 
00017 struct {
00018   UINT8   ScanCode;             
00019   UINT16  EfiScanCode;
00020   CHAR16  UnicodeChar;
00021   CHAR16  ShiftUnicodeChar;
00022 }
00023 ConvertKeyboardScanCodeToEfiKey[] = {
00024 
00025   {
00026     0x01,  //   Escape
00027     SCAN_ESC,
00028     0x0000,
00029     0x0000
00030   },
00031   {
00032     0x02,
00033     SCAN_NULL,
00034     L'1',
00035     L'!'
00036   },
00037   {
00038     0x03,
00039     SCAN_NULL,
00040     L'2',
00041     L'@'
00042   },
00043   {
00044     0x04,
00045     SCAN_NULL,
00046     L'3',
00047     L'#'
00048   },
00049   {
00050     0x05,
00051     SCAN_NULL,
00052     L'4',
00053     L'$'
00054   },
00055   {
00056     0x06,
00057     SCAN_NULL,
00058     L'5',
00059     L'%'
00060   },
00061   {
00062     0x07,
00063     SCAN_NULL,
00064     L'6',
00065     L'^'
00066   },
00067   {
00068     0x08,
00069     SCAN_NULL,
00070     L'7',
00071     L'&'
00072   },
00073   {
00074     0x09,
00075     SCAN_NULL,
00076     L'8',
00077     L'*'
00078   },
00079   {
00080     0x0A,
00081     SCAN_NULL,
00082     L'9',
00083     L'('
00084   },
00085   {
00086     0x0B,
00087     SCAN_NULL,
00088     L'0',
00089     L')'
00090   },
00091   {
00092     0x0C,
00093     SCAN_NULL,
00094     L'-',
00095     L'_'
00096   },
00097   {
00098     0x0D,
00099     SCAN_NULL,
00100     L'=',
00101     L'+'
00102   },
00103   {
00104     0x0E, //  BackSpace
00105     SCAN_NULL,
00106     0x0008,
00107     0x0008
00108   },
00109   {
00110     0x0F, //  Tab
00111     SCAN_NULL,
00112     0x0009,
00113     0x0009
00114   },
00115   {
00116     0x10,
00117     SCAN_NULL,
00118     L'q',
00119     L'Q'
00120   },
00121   {
00122     0x11,
00123     SCAN_NULL,
00124     L'w',
00125     L'W'
00126   },
00127   {
00128     0x12,
00129     SCAN_NULL,
00130     L'e',
00131     L'E'
00132   },
00133   {
00134     0x13,
00135     SCAN_NULL,
00136     L'r',
00137     L'R'
00138   },
00139   {
00140     0x14,
00141     SCAN_NULL,
00142     L't',
00143     L'T'
00144   },
00145   {
00146     0x15,
00147     SCAN_NULL,
00148     L'y',
00149     L'Y'
00150   },
00151   {
00152     0x16,
00153     SCAN_NULL,
00154     L'u',
00155     L'U'
00156   },
00157   {
00158     0x17,
00159     SCAN_NULL,
00160     L'i',
00161     L'I'
00162   },
00163   {
00164     0x18,
00165     SCAN_NULL,
00166     L'o',
00167     L'O'
00168   },
00169   {
00170     0x19,
00171     SCAN_NULL,
00172     L'p',
00173     L'P'
00174   },
00175   {
00176     0x1a,
00177     SCAN_NULL,
00178     L'[',
00179     L'{'
00180   },
00181   {
00182     0x1b,
00183     SCAN_NULL,
00184     L']',
00185     L'}'
00186   },
00187   {
00188     0x1c, //   Enter
00189     SCAN_NULL,
00190     0x000d,
00191     0x000d
00192   },
00193   {
00194     0x1d,
00195     SCAN_NULL,
00196     0x0000,
00197     0x0000
00198   },
00199   {
00200     0x1e,
00201     SCAN_NULL,
00202     L'a',
00203     L'A'
00204   },
00205   {
00206     0x1f,
00207     SCAN_NULL,
00208     L's',
00209     L'S'
00210   },
00211   {
00212     0x20,
00213     SCAN_NULL,
00214     L'd',
00215     L'D'
00216   },
00217   {
00218     0x21,
00219     SCAN_NULL,
00220     L'f',
00221     L'F'
00222   },
00223   {
00224     0x22,
00225     SCAN_NULL,
00226     L'g',
00227     L'G'
00228   },
00229   {
00230     0x23,
00231     SCAN_NULL,
00232     L'h',
00233     L'H'
00234   },
00235   {
00236     0x24,
00237     SCAN_NULL,
00238     L'j',
00239     L'J'
00240   },
00241   {
00242     0x25,
00243     SCAN_NULL,
00244     L'k',
00245     L'K'
00246   },
00247   {
00248     0x26,
00249     SCAN_NULL,
00250     L'l',
00251     L'L'
00252   },
00253   {
00254     0x27,
00255     SCAN_NULL,
00256     L';',
00257     L':'
00258   },
00259   {
00260     0x28,
00261     SCAN_NULL,
00262     L'\'',
00263     L'"'
00264   },
00265   {
00266     0x29,
00267     SCAN_NULL,
00268     L'`',
00269     L'~'
00270   },
00271   {
00272     0x2a, //   Left Shift
00273     SCAN_NULL,
00274     0x0000,
00275     0x0000
00276   },
00277   {
00278     0x2b,
00279     SCAN_NULL,
00280     L'\\',
00281     L'|'
00282   },
00283   {
00284     0x2c,
00285     SCAN_NULL,
00286     L'z',
00287     L'Z'
00288   },
00289   {
00290     0x2d,
00291     SCAN_NULL,
00292     L'x',
00293     L'X'
00294   },
00295   {
00296     0x2e,
00297     SCAN_NULL,
00298     L'c',
00299     L'C'
00300   },
00301   {
00302     0x2f,
00303     SCAN_NULL,
00304     L'v',
00305     L'V'
00306   },
00307   {
00308     0x30,
00309     SCAN_NULL,
00310     L'b',
00311     L'B'
00312   },
00313   {
00314     0x31,
00315     SCAN_NULL,
00316     L'n',
00317     L'N'
00318   },
00319   {
00320     0x32,
00321     SCAN_NULL,
00322     L'm',
00323     L'M'
00324   },
00325   {
00326     0x33,
00327     SCAN_NULL,
00328     L',',
00329     L'<'
00330   },
00331   {
00332     0x34,
00333     SCAN_NULL,
00334     L'.',
00335     L'>'
00336   },
00337   {
00338     0x35,
00339     SCAN_NULL,
00340     L'/',
00341     L'?'
00342   },
00343   {
00344     0x36, //Right Shift
00345     SCAN_NULL,
00346     0x0000,
00347     0x0000
00348   },
00349   {
00350     0x37, // Numeric Keypad *
00351     SCAN_NULL,
00352     L'*',
00353     L'*'
00354   },
00355   {
00356     0x38,  //Left Alt/Extended Right Alt
00357     SCAN_NULL,
00358     0x0000,
00359     0x0000
00360   },
00361   {
00362     0x39,
00363     SCAN_NULL,
00364     L' ',
00365     L' '
00366   },
00367   {
00368     0x3A, //CapsLock
00369     SCAN_NULL,
00370     0x0000,
00371     0x0000
00372   },
00373   {
00374     0x3B,
00375     SCAN_F1,
00376     0x0000,
00377     0x0000
00378   },
00379   {
00380     0x3C,
00381     SCAN_F2,
00382     0x0000,
00383     0x0000
00384   },
00385   {
00386     0x3D,
00387     SCAN_F3,
00388     0x0000,
00389     0x0000
00390   },
00391   {
00392     0x3E,
00393     SCAN_F4,
00394     0x0000,
00395     0x0000
00396   },
00397   {
00398     0x3F,
00399     SCAN_F5,
00400     0x0000,
00401     0x0000
00402   },
00403   {
00404     0x40,
00405     SCAN_F6,
00406     0x0000,
00407     0x0000
00408   },
00409   {
00410     0x41,
00411     SCAN_F7,
00412     0x0000,
00413     0x0000
00414   },
00415   {
00416     0x42,
00417     SCAN_F8,
00418     0x0000,
00419     0x0000
00420   },
00421   {
00422     0x43,
00423     SCAN_F9,
00424     0x0000,
00425     0x0000
00426   },
00427   {
00428     0x44,
00429     SCAN_F10,
00430     0x0000,
00431     0x0000
00432   },
00433   {
00434     0x45, // NumLock
00435     SCAN_NULL,
00436     0x0000,
00437     0x0000
00438   },
00439   {
00440     0x46, //  ScrollLock
00441     SCAN_NULL,
00442     0x0000,
00443     0x0000
00444   },
00445   {
00446     0x47,
00447     SCAN_HOME,
00448     L'7',
00449     L'7'
00450   },
00451   {
00452     0x48,
00453     SCAN_UP,
00454     L'8',
00455     L'8'
00456   },
00457   {
00458     0x49,
00459     SCAN_PAGE_UP,
00460     L'9',
00461     L'9'
00462   },
00463   {
00464     0x4a,
00465     SCAN_NULL,
00466     L'-',
00467     L'-'
00468   },
00469   {
00470     0x4b,
00471     SCAN_LEFT,
00472     L'4',
00473     L'4'
00474   },
00475   {
00476     0x4c, //  Numeric Keypad 5
00477     SCAN_NULL,
00478     L'5',
00479     L'5'
00480   },
00481   {
00482     0x4d,
00483     SCAN_RIGHT,
00484     L'6',
00485     L'6'
00486   },
00487   {
00488     0x4e,
00489     SCAN_NULL,
00490     L'+',
00491     L'+'
00492   },
00493   {
00494     0x4f,
00495     SCAN_END,
00496     L'1',
00497     L'1'
00498   },
00499   {
00500     0x50,
00501     SCAN_DOWN,
00502     L'2',
00503     L'2'
00504   },
00505   {
00506     0x51,
00507     SCAN_PAGE_DOWN,
00508     L'3',
00509     L'3'
00510   },
00511   {
00512     0x52,
00513     SCAN_INSERT,
00514     L'0',
00515     L'0'
00516   },
00517   {
00518     0x53,
00519     SCAN_DELETE,
00520     L'.',
00521     L'.'
00522   },
00523   {
00524     0x57,
00525     SCAN_F11,
00526     0x0000,
00527     0x0000
00528   },
00529   {
00530     0x58,
00531     SCAN_F12,
00532     0x0000,
00533     0x0000
00534   },
00535   {
00536     0x5B,  //Left LOGO
00537     SCAN_NULL,
00538     0x0000,
00539     0x0000
00540   },
00541   {
00542     0x5C,  //Right LOGO
00543     SCAN_NULL,
00544     0x0000,
00545     0x0000
00546   },
00547   {
00548     0x5D,  //Menu key
00549     SCAN_NULL,
00550     0x0000,
00551     0x0000
00552   },
00553   {
00554     TABLE_END,
00555     TABLE_END,
00556     SCAN_NULL,
00557     SCAN_NULL
00558   },
00559 };
00560 
00561 //
00562 // The WaitForValue time out
00563 //
00564 UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
00565 
00566 BOOLEAN          mEnableMouseInterface;
00567 
00568 
00569 
00577 UINTN
00578 GetScancodeBufCount (
00579   IN SCAN_CODE_QUEUE       *Queue
00580   )
00581 {
00582   if (Queue->Head <= Queue->Tail) {
00583     return Queue->Tail - Queue->Head;
00584   } else {
00585     return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;
00586   }
00587 }
00588 
00601 EFI_STATUS
00602 GetScancodeBufHead (
00603   IN  SCAN_CODE_QUEUE        *Queue,
00604   IN  UINTN                  Count,
00605   OUT UINT8                  *Buf
00606   )
00607 {
00608   UINTN                      Index;
00609   UINTN                      Pos;
00610 
00611   //
00612   // check the valid range of parameter 'Count'
00613   //
00614   if (GetScancodeBufCount (Queue) < Count) {
00615     return EFI_NOT_READY;
00616   }
00617   //
00618   // retrieve the values
00619   //
00620   for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
00621     Buf[Index] = Queue->Buffer[Pos];
00622   }
00623 
00624   return EFI_SUCCESS;
00625 }
00626 
00639 EFI_STATUS
00640 PopScancodeBufHead (
00641   IN  SCAN_CODE_QUEUE       *Queue,
00642   IN  UINTN                 Count,
00643   OUT UINT8                 *Buf OPTIONAL
00644   )
00645 {
00646   UINTN                     Index;
00647 
00648   //
00649   // Check the valid range of parameter 'Count'
00650   //
00651   if (GetScancodeBufCount (Queue) < Count) {
00652     return EFI_NOT_READY;
00653   }
00654   //
00655   // Retrieve and remove the values
00656   //
00657   for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
00658     if (Buf != NULL) {
00659       Buf[Index] = Queue->Buffer[Queue->Head];
00660     }
00661   }
00662 
00663   return EFI_SUCCESS;
00664 }
00665 
00672 VOID
00673 PushScancodeBufTail (
00674   IN  SCAN_CODE_QUEUE       *Queue,
00675   IN  UINT8                 Scancode
00676   )
00677 {
00678   if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {
00679     PopScancodeBufHead (Queue, 1, NULL);
00680   }
00681 
00682   Queue->Buffer[Queue->Tail] = Scancode;
00683   Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;
00684 }
00685 
00694 UINT8
00695 KeyReadDataRegister (
00696   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
00697   )
00698 
00699 {
00700   EFI_ISA_IO_PROTOCOL                 *IsaIo;
00701   UINT8                               Data;
00702 
00703   //
00704   // Use IsaIo protocol to perform IO operations
00705   //
00706   IsaIo = ConsoleIn->IsaIo;
00707 
00708   IsaIo->Io.Read (
00709               IsaIo,
00710               EfiIsaIoWidthUint8,
00711               ConsoleIn->DataRegisterAddress,
00712               1,
00713               &Data
00714               );
00715 
00716   return Data;
00717 }
00718 
00726 VOID
00727 KeyWriteDataRegister (
00728   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
00729   IN UINT8                   Data
00730   )
00731 {
00732   ConsoleIn->IsaIo->Io.Write (
00733                          ConsoleIn->IsaIo,
00734                          EfiIsaIoWidthUint8,
00735                          ConsoleIn->DataRegisterAddress,
00736                          1,
00737                          &Data
00738                          );
00739 }
00740 
00749 UINT8
00750 KeyReadStatusRegister (
00751   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
00752   )
00753 {
00754   UINT8                               Data;
00755   ConsoleIn->IsaIo->Io.Read (
00756                          ConsoleIn->IsaIo,
00757                          EfiIsaIoWidthUint8,
00758                          ConsoleIn->StatusRegisterAddress,
00759                          1,
00760                          &Data
00761                          );
00762   return Data;
00763 }
00764 
00772 VOID
00773 KeyWriteCommandRegister (
00774   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
00775   IN UINT8                   Data
00776   )
00777 {
00778   ConsoleIn->IsaIo->Io.Write (
00779                          ConsoleIn->IsaIo,
00780                          EfiIsaIoWidthUint8,
00781                          ConsoleIn->CommandRegisterAddress,
00782                          1,
00783                          &Data
00784                          );
00785 }
00786 
00794 VOID
00795 KeyboardError (
00796   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
00797   IN CHAR16                  *ErrMsg
00798   )
00799 {
00800   ConsoleIn->KeyboardErr = TRUE;
00801 }
00802 
00814 VOID
00815 EFIAPI
00816 KeyboardTimerHandler (
00817   IN EFI_EVENT    Event,
00818   IN VOID         *Context
00819   )
00820 
00821 {
00822   UINT8                   Data;
00823   EFI_TPL                 OldTpl;
00824   KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
00825 
00826   ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
00827 
00828   //
00829   // Enter critical section
00830   //
00831   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
00832 
00833   if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
00834     //
00835     // Leave critical section and return
00836     //
00837     gBS->RestoreTPL (OldTpl);
00838     return ;
00839   }
00840 
00841   //
00842   // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
00843   // KB is not connected to system. If KB is not connected to system, driver will find there's something
00844   // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
00845   // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
00846   // Just skip the 'resend' process simply.
00847   //
00848 
00849   while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==
00850       KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA
00851      ) {
00852     //
00853     // Read one byte of the scan code and store it into the memory buffer
00854     //
00855     Data = KeyReadDataRegister (ConsoleIn);
00856     PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);
00857   }
00858   KeyGetchar (ConsoleIn);
00859 
00860   //
00861   // Leave critical section and return
00862   //
00863   gBS->RestoreTPL (OldTpl);
00864 }
00865 
00876 EFI_STATUS
00877 KeyboardRead (
00878   IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
00879   OUT UINT8                   *Data
00880   )
00881 
00882 {
00883   UINT32  TimeOut;
00884   UINT32  RegFilled;
00885 
00886   TimeOut   = 0;
00887   RegFilled = 0;
00888 
00889   //
00890   // wait till output buffer full then perform the read
00891   //
00892   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
00893     if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
00894       RegFilled = 1;
00895       *Data     = KeyReadDataRegister (ConsoleIn);
00896       break;
00897     }
00898 
00899     MicroSecondDelay (30);
00900   }
00901 
00902   if (RegFilled == 0) {
00903     return EFI_TIMEOUT;
00904   }
00905 
00906   return EFI_SUCCESS;
00907 }
00908 
00919 EFI_STATUS
00920 KeyboardWrite (
00921   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
00922   IN UINT8                   Data
00923   )
00924 {
00925   UINT32  TimeOut;
00926   UINT32  RegEmptied;
00927 
00928   TimeOut     = 0;
00929   RegEmptied  = 0;
00930 
00931   //
00932   // wait for input buffer empty
00933   //
00934   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
00935     if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
00936       RegEmptied = 1;
00937       break;
00938     }
00939 
00940     MicroSecondDelay (30);
00941   }
00942 
00943   if (RegEmptied == 0) {
00944     return EFI_TIMEOUT;
00945   }
00946   //
00947   // Write it
00948   //
00949   KeyWriteDataRegister (ConsoleIn, Data);
00950 
00951   return EFI_SUCCESS;
00952 }
00953 
00964 EFI_STATUS
00965 KeyboardCommand (
00966   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
00967   IN UINT8                   Data
00968   )
00969 {
00970   UINT32  TimeOut;
00971   UINT32  RegEmptied;
00972 
00973   TimeOut     = 0;
00974   RegEmptied  = 0;
00975 
00976   //
00977   // Wait For Input Buffer Empty
00978   //
00979   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
00980     if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
00981       RegEmptied = 1;
00982       break;
00983     }
00984 
00985     MicroSecondDelay (30);
00986   }
00987 
00988   if (RegEmptied == 0) {
00989     return EFI_TIMEOUT;
00990   }
00991   //
00992   // issue the command
00993   //
00994   KeyWriteCommandRegister (ConsoleIn, Data);
00995 
00996   //
00997   // Wait For Input Buffer Empty again
00998   //
00999   RegEmptied = 0;
01000   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
01001     if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
01002       RegEmptied = 1;
01003       break;
01004     }
01005 
01006     MicroSecondDelay (30);
01007   }
01008 
01009   if (RegEmptied == 0) {
01010     return EFI_TIMEOUT;
01011   }
01012 
01013   return EFI_SUCCESS;
01014 }
01015 
01028 EFI_STATUS
01029 KeyboardWaitForValue (
01030   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
01031   IN UINT8                   Value
01032   )
01033 {
01034   UINT8   Data;
01035   UINT32  TimeOut;
01036   UINT32  SumTimeOut;
01037   UINT32  GotIt;
01038 
01039   GotIt       = 0;
01040   TimeOut     = 0;
01041   SumTimeOut  = 0;
01042 
01043   //
01044   // Make sure the initial value of 'Data' is different from 'Value'
01045   //
01046   Data = 0;
01047   if (Data == Value) {
01048     Data = 1;
01049   }
01050   //
01051   // Read from 8042 (multiple times if needed)
01052   // until the expected value appears
01053   // use SumTimeOut to control the iteration
01054   //
01055   while (1) {
01056     //
01057     // Perform a read
01058     //
01059     for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
01060       if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
01061         Data = KeyReadDataRegister (ConsoleIn);
01062         break;
01063       }
01064 
01065       MicroSecondDelay (30);
01066     }
01067 
01068     SumTimeOut += TimeOut;
01069 
01070     if (Data == Value) {
01071       GotIt = 1;
01072       break;
01073     }
01074 
01075     if (SumTimeOut >= mWaitForValueTimeOut) {
01076       break;
01077     }
01078   }
01079   //
01080   // Check results
01081   //
01082   if (GotIt == 1) {
01083     return EFI_SUCCESS;
01084   } else {
01085     return EFI_TIMEOUT;
01086   }
01087 
01088 }
01089 
01099 EFI_STATUS
01100 UpdateStatusLights (
01101   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
01102   )
01103 {
01104   EFI_STATUS  Status;
01105   UINT8       Command;
01106 
01107   //
01108   // Send keyboard command
01109   //
01110   Status = KeyboardWrite (ConsoleIn, 0xed);
01111   if (EFI_ERROR (Status)) {
01112     return Status;
01113   }
01114 
01115   KeyboardWaitForValue (ConsoleIn, 0xfa);
01116 
01117   //
01118   // Light configuration
01119   //
01120   Command = 0;
01121   if (ConsoleIn->CapsLock) {
01122     Command |= 4;
01123   }
01124 
01125   if (ConsoleIn->NumLock) {
01126     Command |= 2;
01127   }
01128 
01129   if (ConsoleIn->ScrollLock) {
01130     Command |= 1;
01131   }
01132 
01133   Status = KeyboardWrite (ConsoleIn, Command);
01134 
01135   if (EFI_ERROR (Status)) {
01136     return Status;
01137   }
01138 
01139   KeyboardWaitForValue (ConsoleIn, 0xfa);
01140   return Status;
01141 }
01142 
01151 VOID
01152 KeyGetchar (
01153   IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
01154   )
01155 {
01156   EFI_STATUS                     Status;
01157   UINT16                         ScanCode;
01158   BOOLEAN                        Extend0;
01159   BOOLEAN                        Extend1;
01160   UINTN                          Index;
01161   EFI_KEY_DATA                   KeyData;
01162   LIST_ENTRY                     *Link;
01163   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
01164   //
01165   // 3 bytes most
01166   //
01167   UINT8                          ScancodeArr[3];
01168   UINT32                         ScancodeArrPos;
01169 
01170   //
01171   // Check if there are enough bytes of scancode representing a single key
01172   // available in the buffer
01173   //
01174   while (TRUE) {
01175     Extend0        = FALSE;
01176     Extend1        = FALSE;
01177     ScancodeArrPos = 0;
01178     Status  = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
01179     if (EFI_ERROR (Status)) {
01180       return ;
01181     }
01182 
01183     if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
01184       //
01185       // E0 to look ahead 2 bytes
01186       //
01187       Extend0 = TRUE;
01188       ScancodeArrPos = 1;
01189       Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
01190       if (EFI_ERROR (Status)) {
01191         return ;
01192       }
01193     } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
01194       //
01195       // E1 to look ahead 3 bytes
01196       //
01197       Extend1 = TRUE;
01198       ScancodeArrPos = 2;
01199       Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
01200       if (EFI_ERROR (Status)) {
01201         return ;
01202       }
01203     }
01204     //
01205     // if we reach this position, scancodes for a key is in buffer now,pop them
01206     //
01207     Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
01208     ASSERT_EFI_ERROR (Status);
01209 
01210     //
01211     // store the last available byte, this byte of scancode will be checked
01212     //
01213     ScanCode = ScancodeArr[ScancodeArrPos];
01214 
01215     if (!Extend1) {
01216       //
01217       // Check for special keys and update the driver state.
01218       //
01219       switch (ScanCode) {
01220 
01221       case SCANCODE_CTRL_MAKE:
01222         if (Extend0) {
01223           ConsoleIn->RightCtrl = TRUE;
01224         } else {
01225           ConsoleIn->LeftCtrl  = TRUE;
01226         }
01227         break;
01228       case SCANCODE_CTRL_BREAK:
01229         if (Extend0) {
01230           ConsoleIn->RightCtrl = FALSE;
01231         } else {
01232           ConsoleIn->LeftCtrl  = FALSE;
01233         }
01234         break;
01235 
01236       case SCANCODE_ALT_MAKE:
01237           if (Extend0) {
01238             ConsoleIn->RightAlt = TRUE;
01239           } else {
01240             ConsoleIn->LeftAlt  = TRUE;
01241           }
01242         break;
01243       case SCANCODE_ALT_BREAK:
01244           if (Extend0) {
01245             ConsoleIn->RightAlt = FALSE;
01246           } else {
01247             ConsoleIn->LeftAlt  = FALSE;
01248           }
01249         break;
01250 
01251       case SCANCODE_LEFT_SHIFT_MAKE:
01252         //
01253         // To avoid recognize PRNT_SCRN key as a L_SHIFT key
01254         // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.
01255         // If it the second byte of the PRNT_ScRN skip it.
01256         //
01257         if (!Extend0) {
01258           ConsoleIn->LeftShift  = TRUE;
01259           break;
01260         }
01261         continue;
01262 
01263       case SCANCODE_LEFT_SHIFT_BREAK:
01264         if (!Extend0) {
01265           ConsoleIn->LeftShift = FALSE;
01266         }
01267         break;
01268 
01269       case SCANCODE_RIGHT_SHIFT_MAKE:
01270         ConsoleIn->RightShift = TRUE;
01271         break;
01272       case SCANCODE_RIGHT_SHIFT_BREAK:
01273         ConsoleIn->RightShift = FALSE;
01274         break;
01275 
01276       case SCANCODE_LEFT_LOGO_MAKE:
01277         ConsoleIn->LeftLogo = TRUE;
01278         break;
01279       case SCANCODE_LEFT_LOGO_BREAK:
01280         ConsoleIn->LeftLogo = FALSE;
01281         break;
01282 
01283       case SCANCODE_RIGHT_LOGO_MAKE:
01284         ConsoleIn->RightLogo = TRUE;
01285         break;
01286       case SCANCODE_RIGHT_LOGO_BREAK:
01287         ConsoleIn->RightLogo = FALSE;
01288         break;
01289 
01290       case SCANCODE_MENU_MAKE:
01291         ConsoleIn->Menu = TRUE;
01292         break;
01293       case SCANCODE_MENU_BREAK:
01294         ConsoleIn->Menu = FALSE;
01295         break;
01296 
01297       case SCANCODE_SYS_REQ_MAKE:
01298         if (Extend0) {
01299           ConsoleIn->SysReq = TRUE;
01300         }
01301         break;
01302       case SCANCODE_SYS_REQ_BREAK:
01303         if (Extend0) {
01304           ConsoleIn->SysReq = FALSE;
01305         }
01306         break;
01307 
01308       case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
01309         ConsoleIn->SysReq = TRUE;
01310         break;
01311       case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
01312         ConsoleIn->SysReq = FALSE;
01313         break;
01314 
01315       case SCANCODE_CAPS_LOCK_MAKE:
01316         ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
01317         UpdateStatusLights (ConsoleIn);
01318         break;
01319       case SCANCODE_NUM_LOCK_MAKE:
01320         ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
01321         UpdateStatusLights (ConsoleIn);
01322         break;
01323       case SCANCODE_SCROLL_LOCK_MAKE:
01324         if (!Extend0) {
01325           ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
01326           UpdateStatusLights (ConsoleIn);
01327         }
01328         break;
01329       }
01330     }
01331 
01332     //
01333     // If this is above the valid range, ignore it
01334     //
01335     if (ScanCode >= SCANCODE_MAX_MAKE) {
01336       continue;
01337     } else {
01338       break;
01339     }
01340   }
01341 
01342   //
01343   // Handle Ctrl+Alt+Del hotkey
01344   //
01345   if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
01346       (ConsoleIn->LeftAlt  || ConsoleIn->RightAlt ) &&
01347       ScanCode == SCANCODE_DELETE_MAKE
01348      ) {
01349     gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
01350   }
01351 
01352   //
01353   // Save the Shift/Toggle state
01354   //
01355   KeyData.KeyState.KeyShiftState = (UINT32) (EFI_SHIFT_STATE_VALID
01356                                  | (ConsoleIn->LeftCtrl   ? EFI_LEFT_CONTROL_PRESSED  : 0)
01357                                  | (ConsoleIn->RightCtrl  ? EFI_RIGHT_CONTROL_PRESSED : 0)
01358                                  | (ConsoleIn->LeftAlt    ? EFI_LEFT_ALT_PRESSED      : 0)
01359                                  | (ConsoleIn->RightAlt   ? EFI_RIGHT_ALT_PRESSED     : 0)
01360                                  | (ConsoleIn->LeftShift  ? EFI_LEFT_SHIFT_PRESSED    : 0)
01361                                  | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED   : 0)
01362                                  | (ConsoleIn->LeftLogo   ? EFI_LEFT_LOGO_PRESSED     : 0)
01363                                  | (ConsoleIn->RightLogo  ? EFI_RIGHT_LOGO_PRESSED    : 0)
01364                                  | (ConsoleIn->Menu       ? EFI_MENU_KEY_PRESSED      : 0)
01365                                  | (ConsoleIn->SysReq     ? EFI_SYS_REQ_PRESSED       : 0)
01366                                  );
01367   KeyData.KeyState.KeyToggleState = (EFI_KEY_TOGGLE_STATE) (EFI_TOGGLE_STATE_VALID
01368                                   | (ConsoleIn->CapsLock   ? EFI_CAPS_LOCK_ACTIVE :   0)
01369                                   | (ConsoleIn->NumLock    ? EFI_NUM_LOCK_ACTIVE :    0)
01370                                   | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)
01371                                   | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0)
01372                                   );
01373 
01374   KeyData.Key.ScanCode            = SCAN_NULL;
01375   KeyData.Key.UnicodeChar         = CHAR_NULL;
01376 
01377   //
01378   // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix
01379   //
01380   if (Extend0 && ScanCode == 0x35) {
01381     KeyData.Key.UnicodeChar = L'/';
01382     KeyData.Key.ScanCode    = SCAN_NULL;
01383 
01384   //
01385   // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
01386   //
01387   } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
01388     KeyData.Key.UnicodeChar = CHAR_NULL;
01389     KeyData.Key.ScanCode    = SCAN_PAUSE;
01390 
01391   //
01392   // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix
01393   //
01394   } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
01395     KeyData.Key.UnicodeChar = CHAR_NULL;
01396     KeyData.Key.ScanCode    = SCAN_PAUSE;
01397 
01398   //
01399   // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix
01400   //
01401   } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
01402     KeyData.Key.UnicodeChar = CHAR_NULL;
01403     KeyData.Key.ScanCode    = SCAN_NULL;
01404 
01405   //
01406   // Except the above special case, all others can be handled by convert table
01407   //
01408   } else {
01409     for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {
01410       if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
01411         KeyData.Key.ScanCode    = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
01412         KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
01413 
01414         if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
01415             (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
01416           KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
01417           //
01418           // Need not return associated shift state if a class of printable characters that
01419           // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
01420           //
01421           KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
01422         }
01423         //
01424         // alphabetic key is affected by CapsLock State
01425         //
01426         if (ConsoleIn->CapsLock) {
01427           if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
01428             KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');
01429           } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
01430             KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');
01431           }
01432         }
01433         break;
01434       }
01435     }
01436   }
01437 
01438   //
01439   // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
01440   //
01441   if (ScanCode >= 0x47 && ScanCode <= 0x53) {
01442     if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {
01443       KeyData.Key.ScanCode = SCAN_NULL;
01444     } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
01445       KeyData.Key.UnicodeChar = CHAR_NULL;
01446     }
01447   }
01448 
01449   //
01450   // If the key can not be converted then just return.
01451   //
01452   if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
01453     if (!ConsoleIn->IsSupportPartialKey) {
01454       return ;
01455     }
01456   }
01457 
01458   //
01459   // Invoke notification functions if exist
01460   //
01461   for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {
01462     CurrentNotify = CR (
01463                       Link,
01464                       KEYBOARD_CONSOLE_IN_EX_NOTIFY,
01465                       NotifyEntry,
01466                       KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
01467                       );
01468     if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
01469       CurrentNotify->KeyNotificationFn (&KeyData);
01470     }
01471   }
01472 
01473   PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
01474 }
01475 
01487 EFI_STATUS
01488 InitKeyboard (
01489   IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
01490   IN BOOLEAN                     ExtendedVerification
01491   )
01492 {
01493   EFI_STATUS              Status;
01494   EFI_STATUS              Status1;
01495   UINT8                   CommandByte;
01496   EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
01497   UINT32                  TryTime;
01498 
01499   Status                 = EFI_SUCCESS;
01500   mEnableMouseInterface  = TRUE;
01501   TryTime                = 0;
01502 
01503   //
01504   // Get Ps2 policy to set this
01505   //
01506   gBS->LocateProtocol (
01507         &gEfiPs2PolicyProtocolGuid,
01508         NULL,
01509         (VOID **) &Ps2Policy
01510         );
01511 
01512   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
01513     EFI_PROGRESS_CODE,
01514     EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
01515     ConsoleIn->DevicePath
01516     );
01517 
01518   //
01519   // Perform a read to cleanup the Status Register's
01520   // output buffer full bits within MAX TRY times
01521   //
01522   while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
01523     Status = KeyboardRead (ConsoleIn, &CommandByte);
01524     TryTime ++;
01525   }
01526   //
01527   // Exceed the max try times. The device may be error.
01528   //
01529   if (TryTime == KEYBOARD_MAX_TRY) {
01530         Status = EFI_DEVICE_ERROR;
01531         goto Done;
01532   }
01533   //
01534   // We should disable mouse interface during the initialization process
01535   // since mouse device output could block keyboard device output in the
01536   // 60H port of 8042 controller.
01537   //
01538   // So if we are not initializing 8042 controller for the
01539   // first time, we have to remember the previous mouse interface
01540   // enabling state
01541   //
01542   // Test the system flag in to determine whether this is the first
01543   // time initialization
01544   //
01545   if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
01546     //
01547     // 8042 controller is already setup (by myself or by mouse driver):
01548     //   See whether mouse interface is already enabled
01549     //   which determines whether we should enable it later
01550     //
01551     //
01552     // Read the command byte of 8042 controller
01553     //
01554     Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
01555     if (EFI_ERROR (Status)) {
01556       KeyboardError (ConsoleIn, L"\n\r");
01557       goto Done;
01558     }
01559 
01560     Status = KeyboardRead (ConsoleIn, &CommandByte);
01561     if (EFI_ERROR (Status)) {
01562       KeyboardError (ConsoleIn, L"\n\r");
01563       goto Done;
01564     }
01565     //
01566     // Test the mouse enabling bit
01567     //
01568     if ((CommandByte & 0x20) != 0) {
01569       mEnableMouseInterface = FALSE;
01570     } else {
01571       mEnableMouseInterface = TRUE;
01572     }
01573 
01574   } else {
01575     //
01576     // 8042 controller is not setup yet:
01577     //   8042 controller selftest;
01578     //   Don't enable mouse interface later.
01579     //
01580     //
01581     // Disable keyboard and mouse interfaces
01582     //
01583     Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
01584     if (EFI_ERROR (Status)) {
01585       KeyboardError (ConsoleIn, L"\n\r");
01586       goto Done;
01587     }
01588 
01589     Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
01590     if (EFI_ERROR (Status)) {
01591       KeyboardError (ConsoleIn, L"\n\r");
01592       goto Done;
01593     }
01594 
01595     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
01596       EFI_PROGRESS_CODE,
01597       EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
01598       ConsoleIn->DevicePath
01599       );
01600     //
01601     // 8042 Controller Self Test
01602     //
01603     Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
01604     if (EFI_ERROR (Status)) {
01605       KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
01606       goto Done;
01607     }
01608 
01609     Status = KeyboardWaitForValue (ConsoleIn, 0x55);
01610     if (EFI_ERROR (Status)) {
01611       KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
01612       goto Done;
01613     }
01614     //
01615     // Don't enable mouse interface later
01616     //
01617     mEnableMouseInterface = FALSE;
01618 
01619   }
01620 
01621   if (Ps2Policy != NULL) {
01622     Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
01623   }
01624   //
01625   // Write 8042 Command Byte, set System Flag
01626   // While at the same time:
01627   //  1. disable mouse interface,
01628   //  2. enable kbd interface,
01629   //  3. enable PC/XT kbd translation mode
01630   //  4. enable mouse and kbd interrupts
01631   //
01632   //  ( Command Byte bits:
01633   //  7: Reserved
01634   //  6: PC/XT translation mode
01635   //  5: Disable Auxiliary device interface
01636   //  4: Disable keyboard interface
01637   //  3: Reserved
01638   //  2: System Flag
01639   //  1: Enable Auxiliary device interrupt
01640   //  0: Enable Keyboard interrupt )
01641   //
01642   Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
01643   if (EFI_ERROR (Status)) {
01644     KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
01645     goto Done;
01646   }
01647 
01648   Status = KeyboardWrite (ConsoleIn, 0x67);
01649   if (EFI_ERROR (Status)) {
01650     KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
01651     goto Done;
01652   }
01653 
01654   //
01655   // Clear Memory Scancode Buffer
01656   //
01657   ConsoleIn->ScancodeQueue.Head = 0;
01658   ConsoleIn->ScancodeQueue.Tail = 0;
01659   ConsoleIn->EfiKeyQueue.Head   = 0;
01660   ConsoleIn->EfiKeyQueue.Tail   = 0;
01661 
01662   //
01663   // Reset the status indicators
01664   //
01665   ConsoleIn->CapsLock   = FALSE;
01666   ConsoleIn->NumLock    = FALSE;
01667   ConsoleIn->ScrollLock = FALSE;
01668   ConsoleIn->LeftCtrl   = FALSE;
01669   ConsoleIn->RightCtrl  = FALSE;
01670   ConsoleIn->LeftAlt    = FALSE;
01671   ConsoleIn->RightAlt   = FALSE;
01672   ConsoleIn->LeftShift  = FALSE;
01673   ConsoleIn->RightShift = FALSE;
01674   ConsoleIn->LeftLogo   = FALSE;
01675   ConsoleIn->RightLogo  = FALSE;
01676   ConsoleIn->Menu       = FALSE;
01677   ConsoleIn->SysReq     = FALSE;
01678 
01679   ConsoleIn->IsSupportPartialKey = FALSE;
01680   //
01681   // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
01682   // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
01683   // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
01684   // and normally during booting an OS, it's skipped.
01685   //
01686   if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
01687     //
01688     // Additional verifications for keyboard interface
01689     //
01690     //
01691     // Keyboard Interface Test
01692     //
01693     Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
01694     if (EFI_ERROR (Status)) {
01695       KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
01696       goto Done;
01697     }
01698 
01699     Status = KeyboardWaitForValue (ConsoleIn, 0x00);
01700     if (EFI_ERROR (Status)) {
01701       KeyboardError (
01702         ConsoleIn,
01703         L"Some specific value not aquired from 8042 controller!\n\r"
01704         );
01705       goto Done;
01706     }
01707     //
01708     // Keyboard reset with a BAT(Basic Assurance Test)
01709     //
01710     Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
01711     if (EFI_ERROR (Status)) {
01712       KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
01713       goto Done;
01714     }
01715 
01716     Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
01717     if (EFI_ERROR (Status)) {
01718       KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
01719       goto Done;
01720     }
01721     //
01722     // wait for BAT completion code
01723     //
01724     mWaitForValueTimeOut  = KEYBOARD_BAT_TIMEOUT;
01725 
01726     Status                = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
01727     if (EFI_ERROR (Status)) {
01728       KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
01729       goto Done;
01730     }
01731 
01732     mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
01733 
01734     //
01735     // Set Keyboard to use Scan Code Set 2
01736     //
01737     Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
01738     if (EFI_ERROR (Status)) {
01739       KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
01740       goto Done;
01741     }
01742 
01743     Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
01744     if (EFI_ERROR (Status)) {
01745       KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
01746       goto Done;
01747     }
01748 
01749     Status = KeyboardWrite (ConsoleIn, 0x02);
01750     if (EFI_ERROR (Status)) {
01751       KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
01752       goto Done;
01753     }
01754 
01755     Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
01756     if (EFI_ERROR (Status)) {
01757       KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
01758       goto Done;
01759     }
01760 
01761   //
01762   // Clear Keyboard Scancode Buffer
01763   //
01764   Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
01765   if (EFI_ERROR (Status)) {
01766     KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
01767     goto Done;
01768   }
01769 
01770   Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
01771   if (EFI_ERROR (Status)) {
01772     KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
01773     goto Done;
01774   }
01775   //
01776   if (Ps2Policy != NULL) {
01777     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
01778       ConsoleIn->CapsLock = TRUE;
01779     }
01780 
01781     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
01782       ConsoleIn->NumLock = TRUE;
01783     }
01784 
01785     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
01786       ConsoleIn->ScrollLock = TRUE;
01787     }
01788   }
01789   //
01790   // Update Keyboard Lights
01791   //
01792   Status = UpdateStatusLights (ConsoleIn);
01793   if (EFI_ERROR (Status)) {
01794     KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
01795     goto Done;
01796     }
01797   }
01798   //
01799   // At last, we can now enable the mouse interface if appropriate
01800   //
01801 Done:
01802 
01803   if (mEnableMouseInterface) {
01804     //
01805     // Enable mouse interface
01806     //
01807     Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
01808     if (EFI_ERROR (Status1)) {
01809       KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
01810       return EFI_DEVICE_ERROR;
01811     }
01812   }
01813 
01814   if (!EFI_ERROR (Status)) {
01815     return EFI_SUCCESS;
01816   } else {
01817     return EFI_DEVICE_ERROR;
01818   }
01819 
01820 }
01821 
01830 EFI_STATUS
01831 DisableKeyboard (
01832   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
01833   )
01834 {
01835   EFI_STATUS  Status;
01836 
01837   //
01838   // Disable keyboard interface
01839   //
01840   Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
01841   if (EFI_ERROR (Status)) {
01842     KeyboardError (ConsoleIn, L"\n\r");
01843     return EFI_DEVICE_ERROR;
01844   }
01845 
01846   return Status;
01847 }
01848 
01859 BOOLEAN
01860 EFIAPI
01861 CheckKeyboardConnect (
01862   IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
01863   )
01864 {
01865   EFI_STATUS     Status;
01866   UINTN          WaitForValueTimeOutBcakup;
01867 
01868   Status = EFI_SUCCESS;
01869   //
01870   // enable keyboard itself and wait for its ack
01871   // If can't receive ack, Keyboard should not be connected.
01872   //
01873   Status = KeyboardWrite (
01874              ConsoleIn,
01875              KEYBOARD_KBEN
01876              );
01877 
01878   if (EFI_ERROR (Status)) {
01879     return FALSE;
01880   }
01881   //
01882   // wait for 1s
01883   //
01884   WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
01885   mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
01886   Status = KeyboardWaitForValue (
01887              ConsoleIn,
01888              KEYBOARD_CMDECHO_ACK
01889              );
01890   mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
01891 
01892   if (EFI_ERROR (Status)) {
01893     return FALSE;
01894   }
01895 
01896   return TRUE;
01897 }
01898 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines