Ps2KbdCtrller.c 41 KB

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