123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863 |
- /** @file
- Routines that access 8042 keyboard controller
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "Ps2Keyboard.h"
- struct {
- UINT8 ScanCode; ///< follows value defined in Scan Code Set1
- UINT16 EfiScanCode;
- CHAR16 UnicodeChar;
- CHAR16 ShiftUnicodeChar;
- }
- ConvertKeyboardScanCodeToEfiKey[] = {
- {
- 0x01, // Escape
- SCAN_ESC,
- 0x0000,
- 0x0000
- },
- {
- 0x02,
- SCAN_NULL,
- L'1',
- L'!'
- },
- {
- 0x03,
- SCAN_NULL,
- L'2',
- L'@'
- },
- {
- 0x04,
- SCAN_NULL,
- L'3',
- L'#'
- },
- {
- 0x05,
- SCAN_NULL,
- L'4',
- L'$'
- },
- {
- 0x06,
- SCAN_NULL,
- L'5',
- L'%'
- },
- {
- 0x07,
- SCAN_NULL,
- L'6',
- L'^'
- },
- {
- 0x08,
- SCAN_NULL,
- L'7',
- L'&'
- },
- {
- 0x09,
- SCAN_NULL,
- L'8',
- L'*'
- },
- {
- 0x0A,
- SCAN_NULL,
- L'9',
- L'('
- },
- {
- 0x0B,
- SCAN_NULL,
- L'0',
- L')'
- },
- {
- 0x0C,
- SCAN_NULL,
- L'-',
- L'_'
- },
- {
- 0x0D,
- SCAN_NULL,
- L'=',
- L'+'
- },
- {
- 0x0E, // BackSpace
- SCAN_NULL,
- 0x0008,
- 0x0008
- },
- {
- 0x0F, // Tab
- SCAN_NULL,
- 0x0009,
- 0x0009
- },
- {
- 0x10,
- SCAN_NULL,
- L'q',
- L'Q'
- },
- {
- 0x11,
- SCAN_NULL,
- L'w',
- L'W'
- },
- {
- 0x12,
- SCAN_NULL,
- L'e',
- L'E'
- },
- {
- 0x13,
- SCAN_NULL,
- L'r',
- L'R'
- },
- {
- 0x14,
- SCAN_NULL,
- L't',
- L'T'
- },
- {
- 0x15,
- SCAN_NULL,
- L'y',
- L'Y'
- },
- {
- 0x16,
- SCAN_NULL,
- L'u',
- L'U'
- },
- {
- 0x17,
- SCAN_NULL,
- L'i',
- L'I'
- },
- {
- 0x18,
- SCAN_NULL,
- L'o',
- L'O'
- },
- {
- 0x19,
- SCAN_NULL,
- L'p',
- L'P'
- },
- {
- 0x1a,
- SCAN_NULL,
- L'[',
- L'{'
- },
- {
- 0x1b,
- SCAN_NULL,
- L']',
- L'}'
- },
- {
- 0x1c, // Enter
- SCAN_NULL,
- 0x000d,
- 0x000d
- },
- {
- 0x1d,
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x1e,
- SCAN_NULL,
- L'a',
- L'A'
- },
- {
- 0x1f,
- SCAN_NULL,
- L's',
- L'S'
- },
- {
- 0x20,
- SCAN_NULL,
- L'd',
- L'D'
- },
- {
- 0x21,
- SCAN_NULL,
- L'f',
- L'F'
- },
- {
- 0x22,
- SCAN_NULL,
- L'g',
- L'G'
- },
- {
- 0x23,
- SCAN_NULL,
- L'h',
- L'H'
- },
- {
- 0x24,
- SCAN_NULL,
- L'j',
- L'J'
- },
- {
- 0x25,
- SCAN_NULL,
- L'k',
- L'K'
- },
- {
- 0x26,
- SCAN_NULL,
- L'l',
- L'L'
- },
- {
- 0x27,
- SCAN_NULL,
- L';',
- L':'
- },
- {
- 0x28,
- SCAN_NULL,
- L'\'',
- L'"'
- },
- {
- 0x29,
- SCAN_NULL,
- L'`',
- L'~'
- },
- {
- 0x2a, // Left Shift
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x2b,
- SCAN_NULL,
- L'\\',
- L'|'
- },
- {
- 0x2c,
- SCAN_NULL,
- L'z',
- L'Z'
- },
- {
- 0x2d,
- SCAN_NULL,
- L'x',
- L'X'
- },
- {
- 0x2e,
- SCAN_NULL,
- L'c',
- L'C'
- },
- {
- 0x2f,
- SCAN_NULL,
- L'v',
- L'V'
- },
- {
- 0x30,
- SCAN_NULL,
- L'b',
- L'B'
- },
- {
- 0x31,
- SCAN_NULL,
- L'n',
- L'N'
- },
- {
- 0x32,
- SCAN_NULL,
- L'm',
- L'M'
- },
- {
- 0x33,
- SCAN_NULL,
- L',',
- L'<'
- },
- {
- 0x34,
- SCAN_NULL,
- L'.',
- L'>'
- },
- {
- 0x35,
- SCAN_NULL,
- L'/',
- L'?'
- },
- {
- 0x36, //Right Shift
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x37, // Numeric Keypad *
- SCAN_NULL,
- L'*',
- L'*'
- },
- {
- 0x38, //Left Alt/Extended Right Alt
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x39,
- SCAN_NULL,
- L' ',
- L' '
- },
- {
- 0x3A, //CapsLock
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x3B,
- SCAN_F1,
- 0x0000,
- 0x0000
- },
- {
- 0x3C,
- SCAN_F2,
- 0x0000,
- 0x0000
- },
- {
- 0x3D,
- SCAN_F3,
- 0x0000,
- 0x0000
- },
- {
- 0x3E,
- SCAN_F4,
- 0x0000,
- 0x0000
- },
- {
- 0x3F,
- SCAN_F5,
- 0x0000,
- 0x0000
- },
- {
- 0x40,
- SCAN_F6,
- 0x0000,
- 0x0000
- },
- {
- 0x41,
- SCAN_F7,
- 0x0000,
- 0x0000
- },
- {
- 0x42,
- SCAN_F8,
- 0x0000,
- 0x0000
- },
- {
- 0x43,
- SCAN_F9,
- 0x0000,
- 0x0000
- },
- {
- 0x44,
- SCAN_F10,
- 0x0000,
- 0x0000
- },
- {
- 0x45, // NumLock
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x46, // ScrollLock
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x47,
- SCAN_HOME,
- L'7',
- L'7'
- },
- {
- 0x48,
- SCAN_UP,
- L'8',
- L'8'
- },
- {
- 0x49,
- SCAN_PAGE_UP,
- L'9',
- L'9'
- },
- {
- 0x4a,
- SCAN_NULL,
- L'-',
- L'-'
- },
- {
- 0x4b,
- SCAN_LEFT,
- L'4',
- L'4'
- },
- {
- 0x4c, // Numeric Keypad 5
- SCAN_NULL,
- L'5',
- L'5'
- },
- {
- 0x4d,
- SCAN_RIGHT,
- L'6',
- L'6'
- },
- {
- 0x4e,
- SCAN_NULL,
- L'+',
- L'+'
- },
- {
- 0x4f,
- SCAN_END,
- L'1',
- L'1'
- },
- {
- 0x50,
- SCAN_DOWN,
- L'2',
- L'2'
- },
- {
- 0x51,
- SCAN_PAGE_DOWN,
- L'3',
- L'3'
- },
- {
- 0x52,
- SCAN_INSERT,
- L'0',
- L'0'
- },
- {
- 0x53,
- SCAN_DELETE,
- L'.',
- L'.'
- },
- {
- 0x57,
- SCAN_F11,
- 0x0000,
- 0x0000
- },
- {
- 0x58,
- SCAN_F12,
- 0x0000,
- 0x0000
- },
- {
- 0x5B, //Left LOGO
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x5C, //Right LOGO
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- 0x5D, //Menu key
- SCAN_NULL,
- 0x0000,
- 0x0000
- },
- {
- TABLE_END,
- TABLE_END,
- SCAN_NULL,
- SCAN_NULL
- },
- };
- //
- // The WaitForValue time out
- //
- UINTN mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
- BOOLEAN mEnableMouseInterface;
- /**
- Return the count of scancode in the queue.
- @param Queue Pointer to instance of SCAN_CODE_QUEUE.
- @return Count of the scancode.
- **/
- UINTN
- GetScancodeBufCount (
- IN SCAN_CODE_QUEUE *Queue
- )
- {
- if (Queue->Head <= Queue->Tail) {
- return Queue->Tail - Queue->Head;
- } else {
- return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;
- }
- }
- /**
- Read several bytes from the scancode buffer without removing them.
- This function is called to see if there are enough bytes of scancode
- representing a single key.
- @param Queue Pointer to instance of SCAN_CODE_QUEUE.
- @param Count Number of bytes to be read
- @param Buf Store the results
- @retval EFI_SUCCESS success to scan the keyboard code
- @retval EFI_NOT_READY invalid parameter
- **/
- EFI_STATUS
- GetScancodeBufHead (
- IN SCAN_CODE_QUEUE *Queue,
- IN UINTN Count,
- OUT UINT8 *Buf
- )
- {
- UINTN Index;
- UINTN Pos;
- //
- // check the valid range of parameter 'Count'
- //
- if (GetScancodeBufCount (Queue) < Count) {
- return EFI_NOT_READY;
- }
- //
- // retrieve the values
- //
- for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
- Buf[Index] = Queue->Buffer[Pos];
- }
- return EFI_SUCCESS;
- }
- /**
- Read & remove several bytes from the scancode buffer.
- This function is usually called after GetScancodeBufHead()
- @param Queue Pointer to instance of SCAN_CODE_QUEUE.
- @param Count Number of bytes to be read
- @param Buf Store the results
- @retval EFI_SUCCESS success to scan the keyboard code
- @retval EFI_NOT_READY invalid parameter
- **/
- EFI_STATUS
- PopScancodeBufHead (
- IN SCAN_CODE_QUEUE *Queue,
- IN UINTN Count,
- OUT UINT8 *Buf OPTIONAL
- )
- {
- UINTN Index;
- //
- // Check the valid range of parameter 'Count'
- //
- if (GetScancodeBufCount (Queue) < Count) {
- return EFI_NOT_READY;
- }
- //
- // Retrieve and remove the values
- //
- for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT) {
- if (Buf != NULL) {
- Buf[Index] = Queue->Buffer[Queue->Head];
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Push one byte to the scancode buffer.
- @param Queue Pointer to instance of SCAN_CODE_QUEUE.
- @param Scancode The byte to push.
- **/
- VOID
- PushScancodeBufTail (
- IN SCAN_CODE_QUEUE *Queue,
- IN UINT8 Scancode
- )
- {
- if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {
- PopScancodeBufHead (Queue, 1, NULL);
- }
- Queue->Buffer[Queue->Tail] = Scancode;
- Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;
- }
- /**
- Read data register .
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @return return the value
- **/
- UINT8
- KeyReadDataRegister (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
- )
- {
- return IoRead8 (ConsoleIn->DataRegisterAddress);
- }
- /**
- Write data register.
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Data value wanted to be written
- **/
- VOID
- KeyWriteDataRegister (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN UINT8 Data
- )
- {
- IoWrite8 (ConsoleIn->DataRegisterAddress, Data);
- }
- /**
- Read status register.
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @return value in status register
- **/
- UINT8
- KeyReadStatusRegister (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
- )
- {
- return IoRead8 (ConsoleIn->StatusRegisterAddress);
- }
- /**
- Write command register .
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Data The value wanted to be written
- **/
- VOID
- KeyWriteCommandRegister (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN UINT8 Data
- )
- {
- IoWrite8 (ConsoleIn->CommandRegisterAddress, Data);
- }
- /**
- Display error message.
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param ErrMsg Unicode string of error message
- **/
- VOID
- KeyboardError (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN CHAR16 *ErrMsg
- )
- {
- ConsoleIn->KeyboardErr = TRUE;
- }
- /**
- Timer event handler: read a series of scancodes from 8042
- and put them into memory scancode buffer.
- it read as much scancodes to either fill
- the memory buffer or empty the keyboard buffer.
- It is registered as running under TPL_NOTIFY
- @param Event The timer event
- @param Context A KEYBOARD_CONSOLE_IN_DEV pointer
- **/
- VOID
- EFIAPI
- KeyboardTimerHandler (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UINT8 Data;
- EFI_TPL OldTpl;
- KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
- ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
- //
- // Enter critical section
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
- //
- // Leave critical section and return
- //
- gBS->RestoreTPL (OldTpl);
- return ;
- }
- //
- // To let KB driver support Hot plug, here should skip the 'resend' command for the case that
- // KB is not connected to system. If KB is not connected to system, driver will find there's something
- // error in the following code and wait for the input buffer empty, this waiting time shoulb be short enough since
- // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
- // Just skip the 'resend' process simply.
- //
- while ((KeyReadStatusRegister (ConsoleIn) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) ==
- KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA
- ) {
- //
- // Read one byte of the scan code and store it into the memory buffer
- //
- Data = KeyReadDataRegister (ConsoleIn);
- PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);
- }
- KeyGetchar (ConsoleIn);
- //
- // Leave critical section and return
- //
- gBS->RestoreTPL (OldTpl);
- }
- /**
- Read key value .
- @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Data - Pointer to outof buffer for keeping key value
- @retval EFI_TIMEOUT Status resigter time out
- @retval EFI_SUCCESS Success to read keyboard
- **/
- EFI_STATUS
- KeyboardRead (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- OUT UINT8 *Data
- )
- {
- UINT32 TimeOut;
- UINT32 RegFilled;
- TimeOut = 0;
- RegFilled = 0;
- //
- // wait till output buffer full then perform the read
- //
- for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
- if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
- RegFilled = 1;
- *Data = KeyReadDataRegister (ConsoleIn);
- break;
- }
- MicroSecondDelay (30);
- }
- if (RegFilled == 0) {
- return EFI_TIMEOUT;
- }
- return EFI_SUCCESS;
- }
- /**
- write key to keyboard
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Data value wanted to be written
- @retval EFI_TIMEOUT The input buffer register is full for putting new value util timeout
- @retval EFI_SUCCESS The new value is sucess put into input buffer register.
- **/
- EFI_STATUS
- KeyboardWrite (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN UINT8 Data
- )
- {
- UINT32 TimeOut;
- UINT32 RegEmptied;
- TimeOut = 0;
- RegEmptied = 0;
- //
- // wait for input buffer empty
- //
- for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
- if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
- RegEmptied = 1;
- break;
- }
- MicroSecondDelay (30);
- }
- if (RegEmptied == 0) {
- return EFI_TIMEOUT;
- }
- //
- // Write it
- //
- KeyWriteDataRegister (ConsoleIn, Data);
- return EFI_SUCCESS;
- }
- /**
- Issue keyboard command.
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Data The buff holding the command
- @retval EFI_TIMEOUT Keyboard is not ready to issuing
- @retval EFI_SUCCESS Success to issue keyboard command
- **/
- EFI_STATUS
- KeyboardCommand (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN UINT8 Data
- )
- {
- UINT32 TimeOut;
- UINT32 RegEmptied;
- TimeOut = 0;
- RegEmptied = 0;
- //
- // Wait For Input Buffer Empty
- //
- for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
- if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
- RegEmptied = 1;
- break;
- }
- MicroSecondDelay (30);
- }
- if (RegEmptied == 0) {
- return EFI_TIMEOUT;
- }
- //
- // issue the command
- //
- KeyWriteCommandRegister (ConsoleIn, Data);
- //
- // Wait For Input Buffer Empty again
- //
- RegEmptied = 0;
- for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
- if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
- RegEmptied = 1;
- break;
- }
- MicroSecondDelay (30);
- }
- if (RegEmptied == 0) {
- return EFI_TIMEOUT;
- }
- return EFI_SUCCESS;
- }
- /**
- wait for a specific value to be presented on
- 8042 Data register by keyboard and then read it,
- used in keyboard commands ack
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @param Value the value wanted to be waited.
- @retval EFI_TIMEOUT Fail to get specific value in given time
- @retval EFI_SUCCESS Success to get specific value in given time.
- **/
- EFI_STATUS
- KeyboardWaitForValue (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN UINT8 Value
- )
- {
- UINT8 Data;
- UINT32 TimeOut;
- UINT32 SumTimeOut;
- UINT32 GotIt;
- GotIt = 0;
- TimeOut = 0;
- SumTimeOut = 0;
- //
- // Make sure the initial value of 'Data' is different from 'Value'
- //
- Data = 0;
- if (Data == Value) {
- Data = 1;
- }
- //
- // Read from 8042 (multiple times if needed)
- // until the expected value appears
- // use SumTimeOut to control the iteration
- //
- while (1) {
- //
- // Perform a read
- //
- for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
- if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
- Data = KeyReadDataRegister (ConsoleIn);
- break;
- }
- MicroSecondDelay (30);
- }
- SumTimeOut += TimeOut;
- if (Data == Value) {
- GotIt = 1;
- break;
- }
- if (SumTimeOut >= mWaitForValueTimeOut) {
- break;
- }
- }
- //
- // Check results
- //
- if (GotIt == 1) {
- return EFI_SUCCESS;
- } else {
- return EFI_TIMEOUT;
- }
- }
- /**
- Show keyboard status lights according to
- indicators in ConsoleIn.
- @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
- @return status of updating keyboard register
- **/
- EFI_STATUS
- UpdateStatusLights (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
- )
- {
- EFI_STATUS Status;
- UINT8 Command;
- //
- // Send keyboard command
- //
- Status = KeyboardWrite (ConsoleIn, 0xed);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- KeyboardWaitForValue (ConsoleIn, 0xfa);
- //
- // Light configuration
- //
- Command = 0;
- if (ConsoleIn->CapsLock) {
- Command |= 4;
- }
- if (ConsoleIn->NumLock) {
- Command |= 2;
- }
- if (ConsoleIn->ScrollLock) {
- Command |= 1;
- }
- Status = KeyboardWrite (ConsoleIn, Command);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- KeyboardWaitForValue (ConsoleIn, 0xfa);
- return Status;
- }
- /**
- Initialize the key state.
- @param ConsoleIn The KEYBOARD_CONSOLE_IN_DEV instance.
- @param KeyState A pointer to receive the key state information.
- **/
- VOID
- InitializeKeyState (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- OUT EFI_KEY_STATE *KeyState
- )
- {
- KeyState->KeyShiftState = EFI_SHIFT_STATE_VALID
- | (ConsoleIn->LeftCtrl ? EFI_LEFT_CONTROL_PRESSED : 0)
- | (ConsoleIn->RightCtrl ? EFI_RIGHT_CONTROL_PRESSED : 0)
- | (ConsoleIn->LeftAlt ? EFI_LEFT_ALT_PRESSED : 0)
- | (ConsoleIn->RightAlt ? EFI_RIGHT_ALT_PRESSED : 0)
- | (ConsoleIn->LeftShift ? EFI_LEFT_SHIFT_PRESSED : 0)
- | (ConsoleIn->RightShift ? EFI_RIGHT_SHIFT_PRESSED : 0)
- | (ConsoleIn->LeftLogo ? EFI_LEFT_LOGO_PRESSED : 0)
- | (ConsoleIn->RightLogo ? EFI_RIGHT_LOGO_PRESSED : 0)
- | (ConsoleIn->Menu ? EFI_MENU_KEY_PRESSED : 0)
- | (ConsoleIn->SysReq ? EFI_SYS_REQ_PRESSED : 0)
- ;
- KeyState->KeyToggleState = EFI_TOGGLE_STATE_VALID
- | (ConsoleIn->CapsLock ? EFI_CAPS_LOCK_ACTIVE : 0)
- | (ConsoleIn->NumLock ? EFI_NUM_LOCK_ACTIVE : 0)
- | (ConsoleIn->ScrollLock ? EFI_SCROLL_LOCK_ACTIVE : 0)
- | (ConsoleIn->IsSupportPartialKey ? EFI_KEY_STATE_EXPOSED : 0)
- ;
- }
- /**
- Get scancode from scancode buffer and translate into EFI-scancode and unicode defined by EFI spec.
- The function is always called in TPL_NOTIFY.
- @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
- **/
- VOID
- KeyGetchar (
- IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
- )
- {
- EFI_STATUS Status;
- UINT16 ScanCode;
- BOOLEAN Extend0;
- BOOLEAN Extend1;
- UINTN Index;
- EFI_KEY_DATA KeyData;
- LIST_ENTRY *Link;
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
- //
- // 3 bytes most
- //
- UINT8 ScancodeArr[3];
- UINT32 ScancodeArrPos;
- //
- // Check if there are enough bytes of scancode representing a single key
- // available in the buffer
- //
- while (TRUE) {
- Extend0 = FALSE;
- Extend1 = FALSE;
- ScancodeArrPos = 0;
- Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
- if (EFI_ERROR (Status)) {
- return ;
- }
- if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
- //
- // E0 to look ahead 2 bytes
- //
- Extend0 = TRUE;
- ScancodeArrPos = 1;
- Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
- if (EFI_ERROR (Status)) {
- return ;
- }
- } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
- //
- // E1 to look ahead 3 bytes
- //
- Extend1 = TRUE;
- ScancodeArrPos = 2;
- Status = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
- if (EFI_ERROR (Status)) {
- return ;
- }
- }
- //
- // if we reach this position, scancodes for a key is in buffer now,pop them
- //
- Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 1, ScancodeArr);
- ASSERT_EFI_ERROR (Status);
- //
- // store the last available byte, this byte of scancode will be checked
- //
- ScanCode = ScancodeArr[ScancodeArrPos];
- if (!Extend1) {
- //
- // Check for special keys and update the driver state.
- //
- switch (ScanCode) {
- case SCANCODE_CTRL_MAKE:
- if (Extend0) {
- ConsoleIn->RightCtrl = TRUE;
- } else {
- ConsoleIn->LeftCtrl = TRUE;
- }
- break;
- case SCANCODE_CTRL_BREAK:
- if (Extend0) {
- ConsoleIn->RightCtrl = FALSE;
- } else {
- ConsoleIn->LeftCtrl = FALSE;
- }
- break;
- case SCANCODE_ALT_MAKE:
- if (Extend0) {
- ConsoleIn->RightAlt = TRUE;
- } else {
- ConsoleIn->LeftAlt = TRUE;
- }
- break;
- case SCANCODE_ALT_BREAK:
- if (Extend0) {
- ConsoleIn->RightAlt = FALSE;
- } else {
- ConsoleIn->LeftAlt = FALSE;
- }
- break;
- case SCANCODE_LEFT_SHIFT_MAKE:
- //
- // To avoid recognize PRNT_SCRN key as a L_SHIFT key
- // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.
- // If it the second byte of the PRNT_ScRN skip it.
- //
- if (!Extend0) {
- ConsoleIn->LeftShift = TRUE;
- break;
- }
- continue;
- case SCANCODE_LEFT_SHIFT_BREAK:
- if (!Extend0) {
- ConsoleIn->LeftShift = FALSE;
- }
- break;
- case SCANCODE_RIGHT_SHIFT_MAKE:
- ConsoleIn->RightShift = TRUE;
- break;
- case SCANCODE_RIGHT_SHIFT_BREAK:
- ConsoleIn->RightShift = FALSE;
- break;
- case SCANCODE_LEFT_LOGO_MAKE:
- ConsoleIn->LeftLogo = TRUE;
- break;
- case SCANCODE_LEFT_LOGO_BREAK:
- ConsoleIn->LeftLogo = FALSE;
- break;
- case SCANCODE_RIGHT_LOGO_MAKE:
- ConsoleIn->RightLogo = TRUE;
- break;
- case SCANCODE_RIGHT_LOGO_BREAK:
- ConsoleIn->RightLogo = FALSE;
- break;
- case SCANCODE_MENU_MAKE:
- ConsoleIn->Menu = TRUE;
- break;
- case SCANCODE_MENU_BREAK:
- ConsoleIn->Menu = FALSE;
- break;
- case SCANCODE_SYS_REQ_MAKE:
- if (Extend0) {
- ConsoleIn->SysReq = TRUE;
- }
- break;
- case SCANCODE_SYS_REQ_BREAK:
- if (Extend0) {
- ConsoleIn->SysReq = FALSE;
- }
- break;
- case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
- ConsoleIn->SysReq = TRUE;
- break;
- case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
- ConsoleIn->SysReq = FALSE;
- break;
- case SCANCODE_CAPS_LOCK_MAKE:
- ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
- UpdateStatusLights (ConsoleIn);
- break;
- case SCANCODE_NUM_LOCK_MAKE:
- ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
- UpdateStatusLights (ConsoleIn);
- break;
- case SCANCODE_SCROLL_LOCK_MAKE:
- if (!Extend0) {
- ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
- UpdateStatusLights (ConsoleIn);
- }
- break;
- }
- }
- //
- // If this is above the valid range, ignore it
- //
- if (ScanCode >= SCANCODE_MAX_MAKE) {
- continue;
- } else {
- break;
- }
- }
- //
- // Handle Ctrl+Alt+Del hotkey
- //
- if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
- (ConsoleIn->LeftAlt || ConsoleIn->RightAlt ) &&
- ScanCode == SCANCODE_DELETE_MAKE
- ) {
- gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
- }
- //
- // Save the Shift/Toggle state
- //
- InitializeKeyState (ConsoleIn, &KeyData.KeyState);
- KeyData.Key.ScanCode = SCAN_NULL;
- KeyData.Key.UnicodeChar = CHAR_NULL;
- //
- // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" has E0 prefix
- //
- if (Extend0 && ScanCode == 0x35) {
- KeyData.Key.UnicodeChar = L'/';
- KeyData.Key.ScanCode = SCAN_NULL;
- //
- // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
- //
- } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
- KeyData.Key.UnicodeChar = CHAR_NULL;
- KeyData.Key.ScanCode = SCAN_PAUSE;
- //
- // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL pressed) has E0 prefix
- //
- } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
- KeyData.Key.UnicodeChar = CHAR_NULL;
- KeyData.Key.ScanCode = SCAN_PAUSE;
- //
- // PRNT_SCRN shares the same scancode as that of Key Pad "*" except PRNT_SCRN has E0 prefix
- //
- } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
- KeyData.Key.UnicodeChar = CHAR_NULL;
- KeyData.Key.ScanCode = SCAN_NULL;
- //
- // Except the above special case, all others can be handled by convert table
- //
- } else {
- for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index++) {
- if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
- KeyData.Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
- KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
- if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
- (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
- KeyData.Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
- //
- // Need not return associated shift state if a class of printable characters that
- // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
- //
- KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
- }
- //
- // alphabetic key is affected by CapsLock State
- //
- if (ConsoleIn->CapsLock) {
- if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
- KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' + L'A');
- } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
- KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' + L'a');
- }
- }
- break;
- }
- }
- }
- //
- // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
- //
- if (ScanCode >= 0x47 && ScanCode <= 0x53) {
- if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) && !Extend0) {
- KeyData.Key.ScanCode = SCAN_NULL;
- } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
- KeyData.Key.UnicodeChar = CHAR_NULL;
- }
- }
- //
- // If the key can not be converted then just return.
- //
- if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
- if (!ConsoleIn->IsSupportPartialKey) {
- return ;
- }
- }
- //
- // Signal KeyNotify process event if this key pressed matches any key registered.
- //
- for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull (&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, Link)) {
- CurrentNotify = CR (
- Link,
- KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
- //
- // The key notification function needs to run at TPL_CALLBACK
- // while current TPL is TPL_NOTIFY. It will be invoked in
- // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
- //
- PushEfikeyBufTail (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
- gBS->SignalEvent (ConsoleIn->KeyNotifyProcessEvent);
- break;
- }
- }
- PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
- }
- /**
- Perform 8042 controller and keyboard Initialization.
- If ExtendedVerification is TRUE, do additional test for
- the keyboard interface
- @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
- @param ExtendedVerification - indicates a thorough initialization
- @retval EFI_DEVICE_ERROR Fail to init keyboard
- @retval EFI_SUCCESS Success to init keyboard
- **/
- EFI_STATUS
- InitKeyboard (
- IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
- IN BOOLEAN ExtendedVerification
- )
- {
- EFI_STATUS Status;
- EFI_STATUS Status1;
- UINT8 CommandByte;
- EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
- UINT32 TryTime;
- Status = EFI_SUCCESS;
- mEnableMouseInterface = TRUE;
- TryTime = 0;
- //
- // Get Ps2 policy to set this
- //
- gBS->LocateProtocol (
- &gEfiPs2PolicyProtocolGuid,
- NULL,
- (VOID **) &Ps2Policy
- );
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
- ConsoleIn->DevicePath
- );
- //
- // Perform a read to cleanup the Status Register's
- // output buffer full bits within MAX TRY times
- //
- if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
- while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
- Status = KeyboardRead (ConsoleIn, &CommandByte);
- TryTime ++;
- }
- //
- // Exceed the max try times. The device may be error.
- //
- if (TryTime == KEYBOARD_MAX_TRY) {
- Status = EFI_DEVICE_ERROR;
- goto Done;
- }
- }
- //
- // We should disable mouse interface during the initialization process
- // since mouse device output could block keyboard device output in the
- // 60H port of 8042 controller.
- //
- // So if we are not initializing 8042 controller for the
- // first time, we have to remember the previous mouse interface
- // enabling state
- //
- // Test the system flag in to determine whether this is the first
- // time initialization
- //
- if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
- if (!PcdGetBool (PcdFastPS2Detection)) {
- //
- // 8042 controller is already setup (by myself or by mouse driver):
- // See whether mouse interface is already enabled
- // which determines whether we should enable it later
- //
- //
- // Read the command byte of 8042 controller
- //
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"\n\r");
- goto Done;
- }
- Status = KeyboardRead (ConsoleIn, &CommandByte);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"\n\r");
- goto Done;
- }
- //
- // Test the mouse enabling bit
- //
- if ((CommandByte & 0x20) != 0) {
- mEnableMouseInterface = FALSE;
- } else {
- mEnableMouseInterface = TRUE;
- }
- } else {
- mEnableMouseInterface = FALSE;
- }
- } else {
- //
- // 8042 controller is not setup yet:
- // 8042 controller selftest;
- // Don't enable mouse interface later.
- //
- //
- // Disable keyboard and mouse interfaces
- //
- if (!PcdGetBool (PcdFastPS2Detection)) {
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"\n\r");
- goto Done;
- }
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"\n\r");
- goto Done;
- }
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
- ConsoleIn->DevicePath
- );
- //
- // 8042 Controller Self Test
- //
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, 0x55);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
- goto Done;
- }
- }
- //
- // Don't enable mouse interface later
- //
- mEnableMouseInterface = FALSE;
- }
- if (Ps2Policy != NULL) {
- Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
- }
- //
- // Write 8042 Command Byte, set System Flag
- // While at the same time:
- // 1. disable mouse interface,
- // 2. enable kbd interface,
- // 3. enable PC/XT kbd translation mode
- // 4. enable mouse and kbd interrupts
- //
- // ( Command Byte bits:
- // 7: Reserved
- // 6: PC/XT translation mode
- // 5: Disable Auxiliary device interface
- // 4: Disable keyboard interface
- // 3: Reserved
- // 2: System Flag
- // 1: Enable Auxiliary device interrupt
- // 0: Enable Keyboard interrupt )
- //
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
- goto Done;
- }
- Status = KeyboardWrite (ConsoleIn, 0x67);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
- goto Done;
- }
- //
- // Clear Memory Scancode Buffer
- //
- ConsoleIn->ScancodeQueue.Head = 0;
- ConsoleIn->ScancodeQueue.Tail = 0;
- ConsoleIn->EfiKeyQueue.Head = 0;
- ConsoleIn->EfiKeyQueue.Tail = 0;
- ConsoleIn->EfiKeyQueueForNotify.Head = 0;
- ConsoleIn->EfiKeyQueueForNotify.Tail = 0;
- //
- // Reset the status indicators
- //
- ConsoleIn->CapsLock = FALSE;
- ConsoleIn->NumLock = FALSE;
- ConsoleIn->ScrollLock = FALSE;
- ConsoleIn->LeftCtrl = FALSE;
- ConsoleIn->RightCtrl = FALSE;
- ConsoleIn->LeftAlt = FALSE;
- ConsoleIn->RightAlt = FALSE;
- ConsoleIn->LeftShift = FALSE;
- ConsoleIn->RightShift = FALSE;
- ConsoleIn->LeftLogo = FALSE;
- ConsoleIn->RightLogo = FALSE;
- ConsoleIn->Menu = FALSE;
- ConsoleIn->SysReq = FALSE;
- ConsoleIn->IsSupportPartialKey = FALSE;
- //
- // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
- // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
- // to system. So we only do the real resetting for keyboard when user asks and there is a real KB connected t system,
- // and normally during booting an OS, it's skipped.
- //
- if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
- //
- // Additional verifications for keyboard interface
- //
- //
- // Keyboard Interface Test
- //
- Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, 0x00);
- if (EFI_ERROR (Status)) {
- KeyboardError (
- ConsoleIn,
- L"Some specific value not aquired from 8042 controller!\n\r"
- );
- goto Done;
- }
- //
- // Keyboard reset with a BAT(Basic Assurance Test)
- //
- Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
- goto Done;
- }
- //
- // wait for BAT completion code
- //
- mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT;
- Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
- goto Done;
- }
- mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
- //
- // Set Keyboard to use Scan Code Set 2
- //
- Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
- goto Done;
- }
- Status = KeyboardWrite (ConsoleIn, 0x02);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
- goto Done;
- }
- //
- // Clear Keyboard Scancode Buffer
- //
- Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
- goto Done;
- }
- Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
- goto Done;
- }
- //
- if (Ps2Policy != NULL) {
- if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
- ConsoleIn->CapsLock = TRUE;
- }
- if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
- ConsoleIn->NumLock = TRUE;
- }
- if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
- ConsoleIn->ScrollLock = TRUE;
- }
- }
- //
- // Update Keyboard Lights
- //
- Status = UpdateStatusLights (ConsoleIn);
- if (EFI_ERROR (Status)) {
- KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
- goto Done;
- }
- }
- //
- // At last, we can now enable the mouse interface if appropriate
- //
- Done:
- if (mEnableMouseInterface) {
- //
- // Enable mouse interface
- //
- Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
- if (EFI_ERROR (Status1)) {
- KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
- return EFI_DEVICE_ERROR;
- }
- }
- if (!EFI_ERROR (Status)) {
- return EFI_SUCCESS;
- } else {
- return EFI_DEVICE_ERROR;
- }
- }
- /**
- Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
- If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
- should not be in system.
- @param[in] ConsoleIn Keyboard Private Data Structure
- @retval TRUE Keyboard in System.
- @retval FALSE Keyboard not in System.
- **/
- BOOLEAN
- EFIAPI
- CheckKeyboardConnect (
- IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
- )
- {
- EFI_STATUS Status;
- UINTN WaitForValueTimeOutBcakup;
- //
- // enable keyboard itself and wait for its ack
- // If can't receive ack, Keyboard should not be connected.
- //
- if (!PcdGetBool (PcdFastPS2Detection)) {
- Status = KeyboardWrite (
- ConsoleIn,
- KEYBOARD_KBEN
- );
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- //
- // wait for 1s
- //
- WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
- mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
- Status = KeyboardWaitForValue (
- ConsoleIn,
- KEYBOARD_CMDECHO_ACK
- );
- mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
- if (EFI_ERROR (Status)) {
- return FALSE;
- }
- return TRUE;
- } else {
- return TRUE;
- }
- }
|