]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Csm/BiosThunk/KeyboardDxe/BiosKeyboard.c
Fix some typo and coding style issues in BaseCryptLib instances.
[mirror_edk2.git] / IntelFrameworkModulePkg / Csm / BiosThunk / KeyboardDxe / BiosKeyboard.c
CommitLineData
bcecde14 1/** @file\r
2 ConsoleOut Routines that speak VGA.\r
3\r
4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5\r
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions\r
8of the BSD License which accompanies this distribution. The\r
9full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "BiosKeyboard.h"\r
18\r
19//\r
20// EFI Driver Binding Protocol Instance\r
21//\r
22EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = {\r
23 BiosKeyboardDriverBindingSupported,\r
24 BiosKeyboardDriverBindingStart,\r
25 BiosKeyboardDriverBindingStop,\r
26 0x3,\r
27 NULL,\r
28 NULL\r
29};\r
30\r
31\r
32/**\r
33 Enqueue the key.\r
34\r
35 @param Queue The queue to be enqueued.\r
36 @param KeyData The key data to be enqueued.\r
37\r
38 @retval EFI_NOT_READY The queue is full.\r
39 @retval EFI_SUCCESS Successfully enqueued the key data.\r
40\r
41**/\r
42EFI_STATUS\r
43Enqueue (\r
44 IN SIMPLE_QUEUE *Queue,\r
45 IN EFI_KEY_DATA *KeyData\r
46 )\r
47{\r
48 if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {\r
49 return EFI_NOT_READY;\r
50 }\r
51\r
52 CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));\r
53 Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;\r
54\r
55 return EFI_SUCCESS;\r
56}\r
57\r
58\r
59/**\r
60 Dequeue the key.\r
61 \r
62 @param Queue The queue to be dequeued.\r
63 @param KeyData The key data to be dequeued.\r
64\r
65 @retval EFI_NOT_READY The queue is empty.\r
66 @retval EFI_SUCCESS Successfully dequeued the key data.\r
67\r
68**/\r
69EFI_STATUS\r
70Dequeue (\r
71 IN SIMPLE_QUEUE *Queue,\r
72 IN EFI_KEY_DATA *KeyData\r
73 )\r
74{\r
75 if (Queue->Front == Queue->Rear) {\r
76 return EFI_NOT_READY;\r
77 }\r
78\r
79 CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));\r
80 Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT;\r
81\r
82 return EFI_SUCCESS;\r
83}\r
84\r
85\r
86/**\r
87 Check whether the queue is empty.\r
88 \r
89 @param Queue The queue to be checked.\r
90\r
91 @retval EFI_NOT_READY The queue is empty.\r
92 @retval EFI_SUCCESS The queue is not empty.\r
93\r
94**/\r
95EFI_STATUS\r
96CheckQueue (\r
97 IN SIMPLE_QUEUE *Queue\r
98 )\r
99{\r
100 if (Queue->Front == Queue->Rear) {\r
101 return EFI_NOT_READY;\r
102 }\r
103\r
104 return EFI_SUCCESS;\r
105}\r
106\r
107//\r
108// EFI Driver Binding Protocol Functions\r
109//\r
110\r
111/**\r
112 Check whether the driver supports this device.\r
113\r
114 @param This The Udriver binding protocol.\r
115 @param Controller The controller handle to check.\r
116 @param RemainingDevicePath The remaining device path.\r
117\r
118 @retval EFI_SUCCESS The driver supports this controller.\r
119 @retval other This device isn't supported.\r
120\r
121**/\r
122EFI_STATUS\r
123EFIAPI\r
124BiosKeyboardDriverBindingSupported (\r
125 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
126 IN EFI_HANDLE Controller,\r
127 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
128 )\r
129{\r
130 EFI_STATUS Status;\r
131 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
132 EFI_ISA_IO_PROTOCOL *IsaIo;\r
133\r
134 //\r
135 // See if the Legacy BIOS Protocol is available\r
136 //\r
137 Status = gBS->LocateProtocol (\r
138 &gEfiLegacyBiosProtocolGuid,\r
139 NULL,\r
140 (VOID **) &LegacyBios\r
141 );\r
142\r
143 if (EFI_ERROR (Status)) {\r
144 return Status;\r
145 }\r
146 //\r
147 // Open the IO Abstraction(s) needed to perform the supported test\r
148 //\r
149 Status = gBS->OpenProtocol (\r
150 Controller,\r
151 &gEfiIsaIoProtocolGuid,\r
152 (VOID **) &IsaIo,\r
153 This->DriverBindingHandle,\r
154 Controller,\r
155 EFI_OPEN_PROTOCOL_BY_DRIVER\r
156 );\r
157\r
158 if (EFI_ERROR (Status)) {\r
159 return Status;\r
160 }\r
161 //\r
162 // Use the ISA I/O Protocol to see if Controller is the Keyboard controller\r
163 //\r
164 if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {\r
165 Status = EFI_UNSUPPORTED;\r
166 }\r
167\r
168 gBS->CloseProtocol (\r
169 Controller,\r
170 &gEfiIsaIoProtocolGuid,\r
171 This->DriverBindingHandle,\r
172 Controller\r
173 );\r
174\r
175 return Status;\r
176}\r
177\r
178/**\r
179 Starts the device with this driver.\r
180\r
181 @param This The driver binding instance.\r
182 @param Controller Handle of device to bind driver to.\r
183 @param RemainingDevicePath Optional parameter use to pick a specific child\r
184 device to start.\r
185\r
186 @retval EFI_SUCCESS The controller is controlled by the driver.\r
187 @retval Other This controller cannot be started.\r
188\r
189**/\r
190EFI_STATUS\r
191EFIAPI\r
192BiosKeyboardDriverBindingStart (\r
193 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
194 IN EFI_HANDLE Controller,\r
195 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
196 )\r
197{\r
198 EFI_STATUS Status;\r
199 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
200 EFI_ISA_IO_PROTOCOL *IsaIo;\r
201 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
202 EFI_IA32_REGISTER_SET Regs;\r
203 BOOLEAN CarryFlag;\r
204 EFI_PS2_POLICY_PROTOCOL *Ps2Policy;\r
205 UINT8 Command;\r
206 EFI_STATUS_CODE_VALUE StatusCode;\r
207\r
208 BiosKeyboardPrivate = NULL;\r
209 IsaIo = NULL;\r
210 StatusCode = 0;\r
211\r
212 //\r
213 // Get Ps2 policy to set. Will be use if present.\r
214 //\r
215 gBS->LocateProtocol (\r
216 &gEfiPs2PolicyProtocolGuid,\r
217 NULL,\r
218 (VOID **) &Ps2Policy\r
219 );\r
220\r
221 //\r
222 // See if the Legacy BIOS Protocol is available\r
223 //\r
224 Status = gBS->LocateProtocol (\r
225 &gEfiLegacyBiosProtocolGuid,\r
226 NULL,\r
227 (VOID **) &LegacyBios\r
228 );\r
229\r
230 if (EFI_ERROR (Status)) {\r
231 return Status;\r
232 }\r
233 //\r
234 // Open the IO Abstraction(s) needed\r
235 //\r
236 Status = gBS->OpenProtocol (\r
237 Controller,\r
238 &gEfiIsaIoProtocolGuid,\r
239 (VOID **) &IsaIo,\r
240 This->DriverBindingHandle,\r
241 Controller,\r
242 EFI_OPEN_PROTOCOL_BY_DRIVER\r
243 );\r
244 if (EFI_ERROR (Status)) {\r
245 return Status;\r
246 }\r
247\r
248 //\r
249 // Allocate the private device structure\r
250 //\r
251 BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));\r
252 if (NULL == BiosKeyboardPrivate) {\r
253 Status = EFI_OUT_OF_RESOURCES;\r
254 goto Done;\r
255 }\r
256\r
257 //\r
258 // Initialize the private device structure\r
259 //\r
260 BiosKeyboardPrivate->Signature = BIOS_KEYBOARD_DEV_SIGNATURE;\r
261 BiosKeyboardPrivate->Handle = Controller;\r
262 BiosKeyboardPrivate->LegacyBios = LegacyBios;\r
263 BiosKeyboardPrivate->IsaIo = IsaIo;\r
264\r
265 BiosKeyboardPrivate->SimpleTextIn.Reset = BiosKeyboardReset;\r
266 BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke;\r
267\r
268 BiosKeyboardPrivate->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER;\r
269 BiosKeyboardPrivate->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;\r
270 BiosKeyboardPrivate->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;\r
271 BiosKeyboardPrivate->ExtendedKeyboard = TRUE;\r
272 \r
273 BiosKeyboardPrivate->Queue.Front = 0;\r
274 BiosKeyboardPrivate->Queue.Rear = 0;\r
275 BiosKeyboardPrivate->SimpleTextInputEx.Reset = BiosKeyboardResetEx;\r
276 BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = BiosKeyboardReadKeyStrokeEx;\r
277 BiosKeyboardPrivate->SimpleTextInputEx.SetState = BiosKeyboardSetState;\r
278 BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = BiosKeyboardRegisterKeyNotify; \r
279 BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify; \r
280 InitializeListHead (&BiosKeyboardPrivate->NotifyList);\r
281\r
bcecde14 282 //\r
283 // Report that the keyboard is being enabled\r
284 //\r
55d4edfb 285 REPORT_STATUS_CODE (\r
bcecde14 286 EFI_PROGRESS_CODE,\r
55d4edfb 287 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE\r
bcecde14 288 );\r
289\r
290 //\r
291 // Setup the WaitForKey event\r
292 //\r
293 Status = gBS->CreateEvent (\r
294 EVT_NOTIFY_WAIT,\r
295 TPL_NOTIFY,\r
296 BiosKeyboardWaitForKey,\r
297 &(BiosKeyboardPrivate->SimpleTextIn),\r
298 &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey)\r
299 );\r
300 if (EFI_ERROR (Status)) {\r
301 (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;\r
302 goto Done;\r
303 }\r
304 Status = gBS->CreateEvent (\r
305 EVT_NOTIFY_WAIT,\r
306 TPL_NOTIFY,\r
307 BiosKeyboardWaitForKeyEx,\r
308 &(BiosKeyboardPrivate->SimpleTextInputEx),\r
309 &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)\r
310 );\r
311 if (EFI_ERROR (Status)) {\r
312 BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;\r
313 goto Done;\r
314 } \r
315\r
316 //\r
317 // Setup a periodic timer, used for reading keystrokes at a fixed interval\r
318 //\r
319 Status = gBS->CreateEvent (\r
320 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
321 TPL_NOTIFY,\r
322 BiosKeyboardTimerHandler,\r
323 BiosKeyboardPrivate,\r
324 &BiosKeyboardPrivate->TimerEvent\r
325 );\r
326 if (EFI_ERROR (Status)) {\r
327 Status = EFI_OUT_OF_RESOURCES;\r
328 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
329 goto Done;\r
330 }\r
331\r
332 Status = gBS->SetTimer (\r
333 BiosKeyboardPrivate->TimerEvent,\r
334 TimerPeriodic,\r
335 KEYBOARD_TIMER_INTERVAL\r
336 );\r
337 if (EFI_ERROR (Status)) {\r
338 Status = EFI_OUT_OF_RESOURCES;\r
339 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;\r
340 goto Done;\r
341 }\r
342 \r
343 //\r
344 // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system\r
345 //\r
55d4edfb 346 REPORT_STATUS_CODE (\r
bcecde14 347 EFI_PROGRESS_CODE,\r
55d4edfb 348 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT\r
bcecde14 349 );\r
350\r
351 //\r
352 // Reset the keyboard device\r
353 //\r
354 Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (\r
355 &BiosKeyboardPrivate->SimpleTextInputEx,\r
f6c014fb 356 FeaturePcdGet (PcdPs2KbdExtendedVerification)\r
bcecde14 357 );\r
bcecde14 358 if (EFI_ERROR (Status)) {\r
f6c014fb 359 DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status)); \r
bcecde14 360 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;\r
361 goto Done;\r
362 }\r
363 //\r
364 // Do platform specific policy like port swapping and keyboard light default\r
365 //\r
366 if (Ps2Policy != NULL) {\r
367\r
368 Ps2Policy->Ps2InitHardware (Controller);\r
369\r
370 Command = 0;\r
371 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {\r
372 Command |= 4;\r
373 }\r
374\r
375 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {\r
376 Command |= 2;\r
377 }\r
378\r
379 if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {\r
380 Command |= 1;\r
381 }\r
382\r
383 KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
384 KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
385 KeyboardWrite (BiosKeyboardPrivate, Command);\r
386 //\r
387 // Call Legacy BIOS Protocol to set whatever is necessary\r
388 //\r
389 LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);\r
390 }\r
391 //\r
392 // Get Configuration\r
393 //\r
394 Regs.H.AH = 0xc0;\r
395 CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (\r
396 BiosKeyboardPrivate->LegacyBios,\r
397 0x15,\r
398 &Regs\r
399 );\r
400\r
401 if (!CarryFlag) {\r
402 //\r
403 // Check bit 6 of Feature Byte 2.\r
404 // If it is set, then Int 16 Func 09 is supported\r
405 //\r
406 if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {\r
407 //\r
408 // Get Keyboard Functionality\r
409 //\r
410 Regs.H.AH = 0x09;\r
411 CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (\r
412 BiosKeyboardPrivate->LegacyBios,\r
413 0x16,\r
414 &Regs\r
415 );\r
416\r
417 if (!CarryFlag) {\r
418 //\r
419 // Check bit 5 of AH.\r
420 // If it is set, then INT 16 Finc 10-12 are supported.\r
421 //\r
422 if ((Regs.H.AL & 0x40) != 0) {\r
423 //\r
424 // Set the flag to use INT 16 Func 10-12\r
425 //\r
426 BiosKeyboardPrivate->ExtendedKeyboard = TRUE;\r
427 }\r
428 }\r
429 }\r
430 }\r
f6c014fb 431 DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard));\r
bcecde14 432 //\r
433 // Install protocol interfaces for the keyboard device.\r
434 //\r
435 Status = gBS->InstallMultipleProtocolInterfaces (\r
436 &Controller,\r
437 &gEfiSimpleTextInProtocolGuid,\r
438 &BiosKeyboardPrivate->SimpleTextIn,\r
439 &gEfiSimpleTextInputExProtocolGuid,\r
440 &BiosKeyboardPrivate->SimpleTextInputEx,\r
441 NULL\r
442 );\r
443\r
444Done:\r
445 if (StatusCode != 0) {\r
446 //\r
447 // Report an Error Code for failing to start the keyboard device\r
448 //\r
55d4edfb 449 REPORT_STATUS_CODE (\r
bcecde14 450 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
55d4edfb 451 StatusCode\r
bcecde14 452 );\r
453 }\r
454\r
455 if (EFI_ERROR (Status)) {\r
456\r
457 if (BiosKeyboardPrivate != NULL) { \r
458 if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {\r
459 gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
460 }\r
461\r
462 if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {\r
463 gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx); \r
464 }\r
465 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
466\r
467 if (BiosKeyboardPrivate->TimerEvent != NULL) {\r
468 gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent); \r
469 }\r
470\r
471 FreePool (BiosKeyboardPrivate);\r
472 }\r
473\r
474 if (IsaIo != NULL) {\r
475 gBS->CloseProtocol (\r
476 Controller,\r
477 &gEfiIsaIoProtocolGuid,\r
478 This->DriverBindingHandle,\r
479 Controller\r
480 );\r
481 }\r
482 }\r
483\r
484 return Status;\r
485}\r
486\r
487/**\r
488 Stop the device handled by this driver.\r
489\r
490 @param This The driver binding protocol.\r
491 @param Controller The controller to release.\r
492 @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
493 @param ChildHandleBuffer The array of child handle.\r
494\r
495 @retval EFI_SUCCESS The device was stopped.\r
496 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
497 @retval Others Fail to uninstall protocols attached on the device.\r
498\r
499**/\r
500EFI_STATUS\r
501EFIAPI\r
502BiosKeyboardDriverBindingStop (\r
503 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
504 IN EFI_HANDLE Controller,\r
505 IN UINTN NumberOfChildren,\r
506 IN EFI_HANDLE *ChildHandleBuffer\r
507 )\r
508{\r
509 EFI_STATUS Status;\r
510 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;\r
511 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
512\r
513 //\r
514 // Disable Keyboard\r
515 //\r
516 Status = gBS->OpenProtocol (\r
517 Controller,\r
518 &gEfiSimpleTextInProtocolGuid,\r
519 (VOID **) &SimpleTextIn,\r
520 This->DriverBindingHandle,\r
521 Controller,\r
522 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
523 );\r
524 if (EFI_ERROR (Status)) {\r
525 return Status;\r
526 }\r
527\r
528 Status = gBS->OpenProtocol (\r
529 Controller,\r
530 &gEfiSimpleTextInputExProtocolGuid,\r
531 NULL,\r
532 This->DriverBindingHandle,\r
533 Controller,\r
534 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
535 );\r
536 if (EFI_ERROR (Status)) {\r
537 return Status;\r
538 }\r
539 \r
540 BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn);\r
541\r
542 Status = gBS->UninstallMultipleProtocolInterfaces (\r
543 Controller,\r
544 &gEfiSimpleTextInProtocolGuid,\r
545 &BiosKeyboardPrivate->SimpleTextIn,\r
546 &gEfiSimpleTextInputExProtocolGuid,\r
547 &BiosKeyboardPrivate->SimpleTextInputEx,\r
548 NULL\r
549 );\r
550 if (EFI_ERROR (Status)) {\r
551 return Status;\r
552 }\r
553 //\r
554 // Release the IsaIo protocol on the controller handle\r
555 //\r
556 gBS->CloseProtocol (\r
557 Controller,\r
558 &gEfiIsaIoProtocolGuid,\r
559 This->DriverBindingHandle,\r
560 Controller\r
561 );\r
562\r
563 //\r
564 // Free other resources\r
565 //\r
566 gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);\r
567 gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);\r
568 gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);\r
569 BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);\r
570\r
571 FreePool (BiosKeyboardPrivate);\r
572\r
573 return EFI_SUCCESS;\r
574}\r
575\r
576/**\r
577 Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.\r
578\r
579 @param BiosKeyboardPrivate Keyboard instance pointer.\r
580\r
581 @return The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.\r
582\r
583**/\r
584UINT8\r
585KeyReadDataRegister (\r
586 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
587 )\r
588{\r
589 UINT8 Data;\r
590\r
591 //\r
592 // Use IsaIo protocol to perform IO operations\r
593 //\r
594 BiosKeyboardPrivate->IsaIo->Io.Read (\r
595 BiosKeyboardPrivate->IsaIo,\r
596 EfiIsaIoWidthUint8,\r
597 BiosKeyboardPrivate->DataRegisterAddress,\r
598 1,\r
599 &Data\r
600 );\r
601\r
602 return Data;\r
603}\r
604\r
605/**\r
606 Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.\r
607\r
608 @param BiosKeyboardPrivate Keyboard instance pointer.\r
609\r
610 @return The status byte read from status register of Keyboard Controller from command port which often is port 64H.\r
611\r
612**/\r
613UINT8\r
614KeyReadStatusRegister (\r
615 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
616 )\r
617{\r
618 UINT8 Data;\r
619\r
620 //\r
621 // Use IsaIo protocol to perform IO operations\r
622 //\r
623 BiosKeyboardPrivate->IsaIo->Io.Read (\r
624 BiosKeyboardPrivate->IsaIo,\r
625 EfiIsaIoWidthUint8,\r
626 BiosKeyboardPrivate->StatusRegisterAddress,\r
627 1,\r
628 &Data\r
629 );\r
630\r
631 return Data;\r
632}\r
633\r
634/**\r
635 Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.\r
636\r
637 @param BiosKeyboardPrivate Keyboard instance pointer.\r
638 @param Data Data byte to write.\r
639\r
640**/\r
641VOID\r
642KeyWriteCommandRegister (\r
643 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
644 IN UINT8 Data\r
645 )\r
646{\r
647 //\r
648 // Use IsaIo protocol to perform IO operations\r
649 //\r
650 BiosKeyboardPrivate->IsaIo->Io.Write (\r
651 BiosKeyboardPrivate->IsaIo,\r
652 EfiIsaIoWidthUint8,\r
653 BiosKeyboardPrivate->CommandRegisterAddress,\r
654 1,\r
655 &Data\r
656 );\r
657}\r
658\r
659/**\r
660 Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.\r
661\r
662 @param BiosKeyboardPrivate Keyboard instance pointer.\r
663 @param Data Data byte to write.\r
664\r
665**/\r
666VOID\r
667KeyWriteDataRegister (\r
668 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
669 IN UINT8 Data\r
670 )\r
671{\r
672 //\r
673 // Use IsaIo protocol to perform IO operations\r
674 //\r
675 BiosKeyboardPrivate->IsaIo->Io.Write (\r
676 BiosKeyboardPrivate->IsaIo,\r
677 EfiIsaIoWidthUint8,\r
678 BiosKeyboardPrivate->DataRegisterAddress,\r
679 1,\r
680 &Data\r
681 );\r
682}\r
683\r
684/**\r
685 Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.\r
686\r
687 @param BiosKeyboardPrivate Keyboard instance pointer.\r
688 @param Data The pointer for data that being read out.\r
689\r
690 @retval EFI_SUCCESS The data byte read out successfully.\r
691 @retval EFI_TIMEOUT Timeout occurred during reading out data byte.\r
692\r
693**/\r
694EFI_STATUS\r
695KeyboardRead (\r
696 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
697 OUT UINT8 *Data\r
698 )\r
699{\r
700 UINT32 TimeOut;\r
701 UINT32 RegFilled;\r
702\r
703 TimeOut = 0;\r
704 RegFilled = 0;\r
705\r
706 //\r
707 // wait till output buffer full then perform the read\r
708 //\r
709 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
710 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {\r
711 RegFilled = 1;\r
712 *Data = KeyReadDataRegister (BiosKeyboardPrivate);\r
713 break;\r
714 }\r
715\r
716 gBS->Stall (30);\r
717 }\r
718\r
719 if (RegFilled == 0) {\r
720 return EFI_TIMEOUT;\r
721 }\r
722\r
723 return EFI_SUCCESS;\r
724}\r
725\r
726/**\r
727 Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.\r
728\r
729 @param BiosKeyboardPrivate Keyboard instance pointer.\r
730 @param Data Data byte to write.\r
731\r
732 @retval EFI_SUCCESS The data byte is written successfully.\r
733 @retval EFI_TIMEOUT Timeout occurred during writing.\r
734\r
735**/\r
736EFI_STATUS\r
737KeyboardWrite (\r
738 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
739 IN UINT8 Data\r
740 )\r
741{\r
742 UINT32 TimeOut;\r
743 UINT32 RegEmptied;\r
744\r
745 TimeOut = 0;\r
746 RegEmptied = 0;\r
747\r
748 //\r
749 // wait for input buffer empty\r
750 //\r
751 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
752 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
753 RegEmptied = 1;\r
754 break;\r
755 }\r
756\r
757 gBS->Stall (30);\r
758 }\r
759\r
760 if (RegEmptied == 0) {\r
761 return EFI_TIMEOUT;\r
762 }\r
763 //\r
764 // Write it\r
765 //\r
766 KeyWriteDataRegister (BiosKeyboardPrivate, Data);\r
767\r
768 return EFI_SUCCESS;\r
769}\r
770\r
771/**\r
772 Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.\r
773\r
774 @param BiosKeyboardPrivate Keyboard instance pointer.\r
775 @param Data Command byte to write.\r
776\r
777 @retval EFI_SUCCESS The command byte is written successfully.\r
778 @retval EFI_TIMEOUT Timeout occurred during writing.\r
779\r
780**/\r
781EFI_STATUS\r
782KeyboardCommand (\r
783 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
784 IN UINT8 Data\r
785 )\r
786{\r
787 UINT32 TimeOut;\r
788 UINT32 RegEmptied;\r
789\r
790 TimeOut = 0;\r
791 RegEmptied = 0;\r
792\r
793 //\r
794 // Wait For Input Buffer Empty\r
795 //\r
796 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
797 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
798 RegEmptied = 1;\r
799 break;\r
800 }\r
801\r
802 gBS->Stall (30);\r
803 }\r
804\r
805 if (RegEmptied == 0) {\r
806 return EFI_TIMEOUT;\r
807 }\r
808 //\r
809 // issue the command\r
810 //\r
811 KeyWriteCommandRegister (BiosKeyboardPrivate, Data);\r
812\r
813 //\r
814 // Wait For Input Buffer Empty again\r
815 //\r
816 RegEmptied = 0;\r
817 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
818 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {\r
819 RegEmptied = 1;\r
820 break;\r
821 }\r
822\r
823 gBS->Stall (30);\r
824 }\r
825\r
826 if (RegEmptied == 0) {\r
827 return EFI_TIMEOUT;\r
828 }\r
829\r
830 return EFI_SUCCESS;\r
831}\r
832\r
833/**\r
834 Wait for a specific value to be presented in\r
835 Data register of Keyboard Controller by keyboard and then read it,\r
836 used in keyboard commands ack\r
837\r
838 @param BiosKeyboardPrivate Keyboard instance pointer.\r
839 @param Value The value to be waited for\r
840 @param WaitForValueTimeOut The limit of microseconds for timeout\r
841\r
842 @retval EFI_SUCCESS The command byte is written successfully.\r
843 @retval EFI_TIMEOUT Timeout occurred during writing.\r
844\r
845**/\r
846EFI_STATUS\r
847KeyboardWaitForValue (\r
848 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
849 IN UINT8 Value,\r
850 IN UINTN WaitForValueTimeOut\r
851 )\r
852{\r
853 UINT8 Data;\r
854 UINT32 TimeOut;\r
855 UINT32 SumTimeOut;\r
856 UINT32 GotIt;\r
857\r
858 GotIt = 0;\r
859 TimeOut = 0;\r
860 SumTimeOut = 0;\r
861\r
862 //\r
863 // Make sure the initial value of 'Data' is different from 'Value'\r
864 //\r
865 Data = 0;\r
866 if (Data == Value) {\r
867 Data = 1;\r
868 }\r
869 //\r
870 // Read from 8042 (multiple times if needed)\r
871 // until the expected value appears\r
872 // use SumTimeOut to control the iteration\r
873 //\r
874 while (1) {\r
875 //\r
876 // Perform a read\r
877 //\r
878 for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {\r
879 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {\r
880 Data = KeyReadDataRegister (BiosKeyboardPrivate);\r
881 break;\r
882 }\r
883\r
884 gBS->Stall (30);\r
885 }\r
886\r
887 SumTimeOut += TimeOut;\r
888\r
889 if (Data == Value) {\r
890 GotIt = 1;\r
891 break;\r
892 }\r
893\r
894 if (SumTimeOut >= WaitForValueTimeOut) {\r
895 break;\r
896 }\r
897 }\r
898 //\r
899 // Check results\r
900 //\r
901 if (GotIt != 0) {\r
902 return EFI_SUCCESS;\r
903 } else {\r
904 return EFI_TIMEOUT;\r
905 }\r
906\r
907}\r
908\r
909/**\r
910 Reads the next keystroke from the input device. The WaitForKey Event can \r
911 be used to test for existance of a keystroke via WaitForEvent () call.\r
912\r
913 @param BiosKeyboardPrivate Bioskeyboard driver private structure.\r
914 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
915 state data for the key that was pressed.\r
916\r
917 @retval EFI_SUCCESS The keystroke information was returned.\r
918 @retval EFI_NOT_READY There was no keystroke data availiable.\r
919 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
920 hardware errors.\r
921 @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
922 \r
923**/\r
924EFI_STATUS\r
925KeyboardReadKeyStrokeWorker (\r
926 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate,\r
927 OUT EFI_KEY_DATA *KeyData\r
928 )\r
929{\r
930 EFI_STATUS Status;\r
931 EFI_TPL OldTpl;\r
932 if (KeyData == NULL) {\r
933 return EFI_INVALID_PARAMETER;\r
934 }\r
935\r
936 //\r
937 // Use TimerEvent callback funciton to check whether there's any key pressed\r
938 //\r
939 \r
940 //\r
941 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.\r
942 // Csm will be used to check whether there is a key pending, but the csm will disable all \r
943 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer\r
944 // event will stop work during the compatibility16. And If a caller recursivly invoke this function, \r
945 // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period, \r
946 // e.g. usb keyboard driver. \r
947 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.\r
948 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.\r
949 //\r
950 gBS->Stall (1000);\r
951\r
952 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
953\r
954 BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate);\r
955 //\r
956 // If there's no key, just return\r
957 //\r
958 Status = CheckQueue (&BiosKeyboardPrivate->Queue);\r
959 if (EFI_ERROR (Status)) {\r
960 gBS->RestoreTPL (OldTpl);\r
961 return EFI_NOT_READY;\r
962 }\r
963\r
964 Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData);\r
965\r
966 gBS->RestoreTPL (OldTpl);\r
967\r
968 return EFI_SUCCESS;\r
969}\r
970\r
971//\r
972// EFI Simple Text In Protocol Functions\r
973//\r
974/**\r
975 Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.\r
976\r
977 @param This Pointer of simple text Protocol.\r
978 @param ExtendedVerification Whether perform the extra validation of keyboard. True: perform; FALSE: skip.\r
979\r
980 @retval EFI_SUCCESS The command byte is written successfully.\r
981 @retval EFI_DEVICE_ERROR Errors occurred during reseting keyboard.\r
982\r
983**/\r
984EFI_STATUS\r
985EFIAPI\r
986BiosKeyboardReset (\r
987 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
988 IN BOOLEAN ExtendedVerification\r
989 )\r
990{\r
991 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
992 EFI_STATUS Status;\r
993 EFI_TPL OldTpl;\r
994 UINT8 CommandByte;\r
995 BOOLEAN MouseEnable;\r
996 EFI_INPUT_KEY Key;\r
997\r
998 MouseEnable = FALSE;\r
999 BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
1000\r
1001 //\r
1002 // 1\r
1003 // Report reset progress code\r
1004 //\r
55d4edfb 1005 REPORT_STATUS_CODE (\r
bcecde14 1006 EFI_PROGRESS_CODE,\r
55d4edfb 1007 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET\r
bcecde14 1008 );\r
1009\r
1010 //\r
1011 // Report a Progress Code for clearing the keyboard buffer\r
1012 //\r
55d4edfb 1013 REPORT_STATUS_CODE (\r
bcecde14 1014 EFI_PROGRESS_CODE,\r
55d4edfb 1015 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER\r
bcecde14 1016 );\r
1017\r
1018 //\r
1019 // 2\r
1020 // Raise TPL to avoid mouse operation impact\r
1021 //\r
1022 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1023\r
1024 //\r
1025 //\r
1026 // Exhaust output buffer data\r
1027 //\r
1028 do {\r
1029 Status = BiosKeyboardReadKeyStroke (\r
1030 This,\r
1031 &Key\r
1032 );\r
1033 } while (!EFI_ERROR (Status));\r
1034 //\r
1035 // 3\r
1036 // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H\r
1037 // if not skip step 4&5 and jump to step 6 to selftest KBC and report this\r
1038 // else go step 4\r
1039 //\r
1040 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {\r
1041 //\r
1042 // 4\r
1043 // CheckMouseStatus to decide enable it later or not\r
1044 //\r
1045 //\r
1046 // Read the command byte of KBC\r
1047 //\r
1048 Status = KeyboardCommand (\r
1049 BiosKeyboardPrivate,\r
1050 KBC_CMDREG_VIA64_CMDBYTE_R\r
1051 );\r
1052\r
1053 if (EFI_ERROR (Status)) {\r
1054 Status = EFI_DEVICE_ERROR;\r
1055 goto Exit;\r
1056 }\r
1057\r
1058 Status = KeyboardRead (\r
1059 BiosKeyboardPrivate,\r
1060 &CommandByte\r
1061 );\r
1062\r
1063 if (EFI_ERROR (Status)) {\r
1064 Status = EFI_DEVICE_ERROR;\r
1065 goto Exit;\r
1066 }\r
1067 //\r
1068 // Check mouse enabled or not before\r
1069 //\r
1070 if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {\r
1071 MouseEnable = FALSE;\r
1072 } else {\r
1073 MouseEnable = TRUE;\r
1074 }\r
1075 //\r
1076 // 5\r
1077 // disable mouse (via KBC) and Keyborad device\r
1078 //\r
1079 Status = KeyboardCommand (\r
1080 BiosKeyboardPrivate,\r
1081 KBC_CMDREG_VIA64_AUX_DISABLE\r
1082 );\r
1083\r
1084 if (EFI_ERROR (Status)) {\r
1085 Status = EFI_DEVICE_ERROR;\r
1086 goto Exit;\r
1087 }\r
1088\r
1089 Status = KeyboardCommand (\r
1090 BiosKeyboardPrivate,\r
1091 KBC_CMDREG_VIA64_KB_DISABLE\r
1092 );\r
1093\r
1094 if (EFI_ERROR (Status)) {\r
1095 Status = EFI_DEVICE_ERROR;\r
1096 goto Exit;\r
1097 }\r
1098\r
1099 } else {\r
1100 //\r
1101 // 6\r
1102 // KBC Self Test\r
1103 //\r
1104 //\r
1105 // Report a Progress Code for performing a self test on the keyboard controller\r
1106 //\r
55d4edfb 1107 REPORT_STATUS_CODE (\r
bcecde14 1108 EFI_PROGRESS_CODE,\r
55d4edfb 1109 EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST\r
bcecde14 1110 );\r
1111\r
1112 Status = KeyboardCommand (\r
1113 BiosKeyboardPrivate,\r
1114 KBC_CMDREG_VIA64_KBC_SLFTEST\r
1115 );\r
1116 if (EFI_ERROR (Status)) {\r
1117 Status = EFI_DEVICE_ERROR;\r
1118 goto Exit;\r
1119 }\r
1120\r
1121 Status = KeyboardWaitForValue (\r
1122 BiosKeyboardPrivate,\r
1123 KBC_CMDECHO_KBCSLFTEST_OK,\r
1124 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1125 );\r
1126 if (EFI_ERROR (Status)) {\r
1127 Status = EFI_DEVICE_ERROR;\r
1128 goto Exit;\r
1129 }\r
1130 }\r
1131 //\r
1132 // 7\r
1133 // Disable Mouse interface, enable Keyboard interface and declare selftest success\r
1134 //\r
1135 // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.\r
1136 //\r
1137 Status = KeyboardCommand (\r
1138 BiosKeyboardPrivate,\r
1139 KBC_CMDREG_VIA64_CMDBYTE_W\r
1140 );\r
1141\r
1142 if (EFI_ERROR (Status)) {\r
1143 Status = EFI_DEVICE_ERROR;\r
1144 goto Exit;\r
1145 }\r
1146\r
1147 //\r
1148 // Write 8042 Command Byte, set System Flag\r
1149 // While at the same time:\r
1150 // 1. disable mouse interface,\r
1151 // 2. enable kbd interface,\r
1152 // 3. enable PC/XT kbd translation mode\r
1153 // 4. enable mouse and kbd interrupts\r
1154 //\r
1155 //Command Byte bits:\r
1156 // 7: Reserved\r
1157 // 6: PC/XT translation mode\r
1158 // 5: Disable Auxiliary device interface\r
1159 // 4: Disable keyboard interface\r
1160 // 3: Reserved\r
1161 // 2: System Flag\r
1162 // 1: Enable Auxiliary device interrupt\r
1163 // 0: Enable Keyboard interrupt\r
1164 //\r
1165 CommandByte = 0;\r
1166 Status = KeyboardWrite (\r
1167 BiosKeyboardPrivate,\r
1168 (UINT8) ((CommandByte &\r
1169 (~KB_CMMBYTE_DISABLE_KB)) |\r
1170 KB_CMMBYTE_KSCAN2UNI_COV |\r
1171 KB_CMMBYTE_ENABLE_AUXINT |\r
1172 KB_CMMBYTE_ENABLE_KBINT |\r
1173 KB_CMMBYTE_SLFTEST_SUCC |\r
1174 KB_CMMBYTE_DISABLE_AUX)\r
1175 );\r
1176\r
1177 //\r
1178 // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,\r
1179 // so we only do the real reseting for keyboard when user asks, and normally during booting an OS, it's skipped.\r
1180 // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,\r
1181 // Real reset will not do.\r
1182 //\r
1183 if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) {\r
1184 //\r
1185 // 8\r
1186 // Send keyboard reset command then read ACK\r
1187 //\r
1188 Status = KeyboardWrite (\r
1189 BiosKeyboardPrivate,\r
1190 KBC_INPBUF_VIA60_KBRESET\r
1191 );\r
1192\r
1193 if (EFI_ERROR (Status)) {\r
1194 Status = EFI_DEVICE_ERROR;\r
1195 goto Exit;\r
1196 }\r
1197\r
1198 Status = KeyboardWaitForValue (\r
1199 BiosKeyboardPrivate,\r
1200 KBC_CMDECHO_ACK,\r
1201 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1202 );\r
1203\r
1204 if (EFI_ERROR (Status)) {\r
1205 Status = EFI_DEVICE_ERROR;\r
1206 goto Exit;\r
1207 }\r
1208 //\r
1209 // 9\r
1210 // Wait for keyboard return test OK.\r
1211 //\r
1212 Status = KeyboardWaitForValue (\r
1213 BiosKeyboardPrivate,\r
1214 KBC_CMDECHO_BATTEST_OK,\r
1215 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1216 );\r
1217\r
1218 if (EFI_ERROR (Status)) {\r
1219 Status = EFI_DEVICE_ERROR;\r
1220 goto Exit;\r
1221 }\r
1222 //\r
1223 // 10\r
1224 // set keyboard scan code set = 02 (standard configuration)\r
1225 //\r
1226 Status = KeyboardWrite (\r
1227 BiosKeyboardPrivate,\r
1228 KBC_INPBUF_VIA60_KBSCODE\r
1229 );\r
1230 if (EFI_ERROR (Status)) {\r
1231 Status = EFI_DEVICE_ERROR;\r
1232 goto Exit;\r
1233 }\r
1234\r
1235 Status = KeyboardWaitForValue (\r
1236 BiosKeyboardPrivate,\r
1237 KBC_CMDECHO_ACK,\r
1238 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1239 );\r
1240\r
1241 if (EFI_ERROR (Status)) {\r
1242 Status = EFI_DEVICE_ERROR;\r
1243 goto Exit;\r
1244 }\r
1245\r
1246 Status = KeyboardWrite (\r
1247 BiosKeyboardPrivate,\r
1248 KBC_INPBUF_VIA60_SCODESET2\r
1249 );\r
1250 if (EFI_ERROR (Status)) {\r
1251 Status = EFI_DEVICE_ERROR;\r
1252 goto Exit;\r
1253 }\r
1254\r
1255 Status = KeyboardWaitForValue (\r
1256 BiosKeyboardPrivate,\r
1257 KBC_CMDECHO_ACK,\r
1258 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1259 );\r
1260\r
1261 if (EFI_ERROR (Status)) {\r
1262 Status = EFI_DEVICE_ERROR;\r
1263 goto Exit;\r
1264 }\r
1265 //\r
1266 // 11\r
1267 // enable keyboard itself (not via KBC) by writing CMD F4 via 60H\r
1268 //\r
1269 Status = KeyboardWrite (\r
1270 BiosKeyboardPrivate,\r
1271 KBC_INPBUF_VIA60_KBEN\r
1272 );\r
1273 if (EFI_ERROR (Status)) {\r
1274 Status = EFI_DEVICE_ERROR;\r
1275 goto Exit;\r
1276 }\r
1277\r
1278 Status = KeyboardWaitForValue (\r
1279 BiosKeyboardPrivate,\r
1280 KBC_CMDECHO_ACK,\r
1281 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1282 );\r
1283\r
1284 if (EFI_ERROR (Status)) {\r
1285 Status = EFI_DEVICE_ERROR;\r
1286 goto Exit;\r
1287 }\r
1288 //\r
1289 // 12\r
1290 // Additional validation, do it as follow:\r
1291 // 1). check for status register of PARE && TIM via 64H\r
1292 // 2). perform KB checking by writing ABh via 64H\r
1293 //\r
1294 if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) {\r
1295 Status = EFI_DEVICE_ERROR;\r
1296 goto Exit;\r
1297 }\r
1298\r
1299 Status = KeyboardCommand (\r
1300 BiosKeyboardPrivate,\r
1301 KBC_CMDREG_VIA64_KB_CKECK\r
1302 );\r
1303 if (EFI_ERROR (Status)) {\r
1304 Status = EFI_DEVICE_ERROR;\r
1305 goto Exit;\r
1306 }\r
1307\r
1308 Status = KeyboardWaitForValue (\r
1309 BiosKeyboardPrivate,\r
1310 KBC_CMDECHO_KBCHECK_OK,\r
1311 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1312 );\r
1313\r
1314 if (EFI_ERROR (Status)) {\r
1315 Status = EFI_DEVICE_ERROR;\r
1316 goto Exit;\r
1317 }\r
1318 }\r
1319 //\r
1320 // 13\r
1321 // Done for validating keyboard. Enable keyboard (via KBC)\r
1322 // and recover the command byte to proper value\r
1323 //\r
1324 Status = KeyboardCommand (\r
1325 BiosKeyboardPrivate,\r
1326 KBC_CMDREG_VIA64_KB_ENABLE\r
1327 );\r
1328\r
1329 if (EFI_ERROR (Status)) {\r
1330 Status = EFI_DEVICE_ERROR;\r
1331 goto Exit;\r
1332 }\r
1333\r
1334 //\r
1335 // 14\r
1336 // conditionally enable mouse (via KBC)\r
1337 //\r
1338 if (MouseEnable) {\r
1339 Status = KeyboardCommand (\r
1340 BiosKeyboardPrivate,\r
1341 KBC_CMDREG_VIA64_AUX_ENABLE\r
1342 );\r
1343\r
1344 if (EFI_ERROR (Status)) {\r
1345 Status = EFI_DEVICE_ERROR;\r
1346\r
1347 }\r
1348 }\r
1349\r
1350Exit:\r
1351 //\r
1352 // 15\r
1353 // resume priority of task level\r
1354 //\r
1355 gBS->RestoreTPL (OldTpl);\r
1356\r
1357 return Status;\r
1358\r
1359}\r
1360\r
1361/**\r
1362 Read out the scan code of the key that has just been stroked.\r
1363\r
1364 @param This Pointer of simple text Protocol.\r
1365 @param Key Pointer for store the key that read out.\r
1366\r
1367 @retval EFI_SUCCESS The key is read out successfully.\r
1368 @retval other The key reading failed.\r
1369\r
1370**/\r
1371EFI_STATUS\r
1372EFIAPI\r
1373BiosKeyboardReadKeyStroke (\r
1374 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
1375 OUT EFI_INPUT_KEY *Key\r
1376 )\r
1377{\r
1378 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
1379 EFI_STATUS Status;\r
1380 EFI_KEY_DATA KeyData;\r
1381\r
1382 BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
1383\r
1384 Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData);\r
1385 if (EFI_ERROR (Status)) {\r
1386 return Status;\r
1387 }\r
1388\r
9891f791
RN
1389 //\r
1390 // Convert the Ctrl+[a-z] to Ctrl+[1-26]\r
1391 //\r
1392 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
1393 if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
1394 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
1395 } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
1396 KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
1397 }\r
1398 }\r
1399\r
bcecde14 1400 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY)); \r
1401\r
1402 return EFI_SUCCESS;\r
1403}\r
1404\r
1405/**\r
1406 Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
1407\r
1408 @param Event The event that be siganlled when any key has been stroked.\r
1409 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
1410\r
1411**/\r
1412VOID\r
1413EFIAPI\r
1414BiosKeyboardWaitForKey (\r
1415 IN EFI_EVENT Event,\r
1416 IN VOID *Context\r
1417 )\r
1418{\r
1419 //\r
1420 // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.\r
1421 // Csm will be used to check whether there is a key pending, but the csm will disable all\r
1422 // interrupt before switch to compatibility16, which mean all the efiCompatibility timer\r
1423 // event will stop work during the compatibility16. And If a caller recursivly invoke this function,\r
1424 // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,\r
1425 // e.g. usb keyboard driver.\r
1426 // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.\r
1427 // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.\r
1428 //\r
1429 gBS->Stall (1000);\r
1430 //\r
1431 // Use TimerEvent callback funciton to check whether there's any key pressed\r
1432 //\r
1433 BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));\r
1434\r
1435 if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) {\r
1436 gBS->SignalEvent (Event);\r
1437 }\r
1438}\r
1439\r
1440/**\r
1441 Check key buffer to get the key stroke status.\r
1442\r
1443 @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.\r
1444 \r
1445 @retval EFI_SUCCESS A key is being pressed now.\r
1446 @retval Other No key is now pressed.\r
1447\r
1448**/\r
1449EFI_STATUS\r
1450EFIAPI\r
1451BiosKeyboardCheckForKey (\r
1452 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
1453 )\r
1454{\r
1455 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
1456\r
1457 BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
1458\r
1459 return CheckQueue (&BiosKeyboardPrivate->Queue);\r
1460}\r
1461//\r
1462// Private worker functions\r
1463//\r
1464#define TABLE_END 0x0\r
1465\r
1466typedef struct _CONVERT_TABLE_ENTRY {\r
1467 UINT16 ScanCode;\r
1468 UINT16 EfiScanCode;\r
1469} CONVERT_TABLE_ENTRY;\r
1470\r
1471CONVERT_TABLE_ENTRY mConvertTable[] = {\r
1472 {\r
1473 0x47,\r
1474 SCAN_HOME\r
1475 },\r
1476 {\r
1477 0x48,\r
1478 SCAN_UP\r
1479 },\r
1480 {\r
1481 0x49,\r
1482 SCAN_PAGE_UP\r
1483 },\r
1484 {\r
1485 0x4b,\r
1486 SCAN_LEFT\r
1487 },\r
1488 {\r
1489 0x4d,\r
1490 SCAN_RIGHT\r
1491 },\r
1492 {\r
1493 0x4f,\r
1494 SCAN_END\r
1495 },\r
1496 {\r
1497 0x50,\r
1498 SCAN_DOWN\r
1499 },\r
1500 {\r
1501 0x51,\r
1502 SCAN_PAGE_DOWN\r
1503 },\r
1504 {\r
1505 0x52,\r
1506 SCAN_INSERT\r
1507 },\r
1508 {\r
1509 0x53,\r
1510 SCAN_DELETE\r
1511 },\r
1512 //\r
1513 // Function Keys are only valid if KeyChar == 0x00\r
1514 // This function does not require KeyChar to be 0x00\r
1515 //\r
1516 {\r
1517 0x3b,\r
1518 SCAN_F1\r
1519 },\r
1520 {\r
1521 0x3c,\r
1522 SCAN_F2\r
1523 },\r
1524 {\r
1525 0x3d,\r
1526 SCAN_F3\r
1527 },\r
1528 {\r
1529 0x3e,\r
1530 SCAN_F4\r
1531 },\r
1532 {\r
1533 0x3f,\r
1534 SCAN_F5\r
1535 },\r
1536 {\r
1537 0x40,\r
1538 SCAN_F6\r
1539 },\r
1540 {\r
1541 0x41,\r
1542 SCAN_F7\r
1543 },\r
1544 {\r
1545 0x42,\r
1546 SCAN_F8\r
1547 },\r
1548 {\r
1549 0x43,\r
1550 SCAN_F9\r
1551 },\r
1552 {\r
1553 0x44,\r
1554 SCAN_F10\r
1555 },\r
1556 {\r
1557 0x85,\r
1558 SCAN_F11\r
1559 },\r
1560 {\r
1561 0x86,\r
1562 SCAN_F12\r
1563 },\r
1564 //\r
1565 // Convert ALT + Fn keys\r
1566 //\r
1567 {\r
1568 0x68,\r
1569 SCAN_F1\r
1570 },\r
1571 {\r
1572 0x69,\r
1573 SCAN_F2\r
1574 },\r
1575 {\r
1576 0x6a,\r
1577 SCAN_F3\r
1578 },\r
1579 {\r
1580 0x6b,\r
1581 SCAN_F4\r
1582 },\r
1583 {\r
1584 0x6c,\r
1585 SCAN_F5\r
1586 },\r
1587 {\r
1588 0x6d,\r
1589 SCAN_F6\r
1590 },\r
1591 {\r
1592 0x6e,\r
1593 SCAN_F7\r
1594 },\r
1595 {\r
1596 0x6f,\r
1597 SCAN_F8\r
1598 },\r
1599 {\r
1600 0x70,\r
1601 SCAN_F9\r
1602 },\r
1603 {\r
1604 0x71,\r
1605 SCAN_F10\r
1606 },\r
1607 {\r
1608 TABLE_END,\r
1609 SCAN_NULL\r
1610 },\r
1611};\r
1612\r
1613/**\r
1614 Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.\r
1615\r
1616 @param KeyChar Unicode of key.\r
1617 @param ScanCode Scan code of key.\r
1618\r
1619 @return The value of EFI Scancode for the key. \r
1620 @retval SCAN_NULL No corresponding value in the EFI convert table is found for the key.\r
1621\r
1622**/\r
1623UINT16\r
1624ConvertToEFIScanCode (\r
1625 IN CHAR16 KeyChar,\r
1626 IN UINT16 ScanCode\r
1627 )\r
1628{\r
1629 UINT16 EfiScanCode;\r
1630 UINT16 Index;\r
1631\r
1632 if (KeyChar == CHAR_ESC) {\r
1633 EfiScanCode = SCAN_ESC;\r
1634 } else if (KeyChar == 0x00 || KeyChar == 0xe0) {\r
1635 //\r
1636 // Movement & Function Keys\r
1637 //\r
1638 for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) {\r
1639 if (ScanCode == mConvertTable[Index].ScanCode) {\r
1640 return mConvertTable[Index].EfiScanCode;\r
1641 }\r
1642 }\r
1643 //\r
1644 // Reach Table end, return default value\r
1645 //\r
1646 return SCAN_NULL;\r
1647 } else {\r
1648 return SCAN_NULL;\r
1649 }\r
1650\r
1651 return EfiScanCode;\r
1652}\r
1653\r
1654/**\r
1655 Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command\r
1656 If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device\r
1657 should not be in system. \r
1658\r
1659 @param BiosKeyboardPrivate Keyboard Private Data Struture\r
1660\r
1661 @retval TRUE Keyboard in System.\r
1662 @retval FALSE Keyboard not in System.\r
1663\r
1664**/\r
1665BOOLEAN\r
1666CheckKeyboardConnect (\r
1667 IN BIOS_KEYBOARD_DEV *BiosKeyboardPrivate\r
1668 )\r
1669{\r
1670 EFI_STATUS Status;\r
1671\r
1672 Status = EFI_SUCCESS;\r
1673 //\r
1674 // enable keyboard itself and wait for its ack\r
1675 // If can't receive ack, Keyboard should not be connected.\r
1676 //\r
1677 Status = KeyboardWrite (\r
1678 BiosKeyboardPrivate,\r
1679 KBC_INPBUF_VIA60_KBEN\r
1680 );\r
1681 if (EFI_ERROR (Status)) {\r
f6c014fb 1682 DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));\r
55d4edfb 1683 REPORT_STATUS_CODE (\r
f6c014fb 1684 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
55d4edfb 1685 EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR\r
f6c014fb 1686 );\r
bcecde14 1687 return FALSE;\r
1688 }\r
1689\r
1690 Status = KeyboardWaitForValue (\r
1691 BiosKeyboardPrivate,\r
1692 KBC_CMDECHO_ACK,\r
1693 KEYBOARD_WAITFORVALUE_TIMEOUT\r
1694 );\r
1695\r
1696 if (EFI_ERROR (Status)) {\r
f6c014fb 1697 DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n"));\r
55d4edfb 1698 REPORT_STATUS_CODE (\r
f6c014fb 1699 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
55d4edfb 1700 EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR\r
f6c014fb 1701 );\r
bcecde14 1702 return FALSE;\r
1703 }\r
1704\r
1705 return TRUE;\r
1706}\r
1707\r
1708/**\r
1709 Timer event handler: read a series of key stroke from 8042\r
1710 and put them into memory key buffer. \r
1711 It is registered as running under TPL_NOTIFY\r
1712 \r
1713 @param Event The timer event\r
1714 @param Context A BIOS_KEYBOARD_DEV pointer\r
1715\r
1716**/\r
1717VOID\r
1718EFIAPI\r
1719BiosKeyboardTimerHandler (\r
1720 IN EFI_EVENT Event,\r
1721 IN VOID *Context\r
1722 )\r
1723{\r
1724 EFI_TPL OldTpl;\r
1725 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
1726 EFI_IA32_REGISTER_SET Regs;\r
1727 UINT8 KbFlag1; // 0040h:0017h - KEYBOARD - STATUS FLAGS 1\r
1728 UINT8 KbFlag2; // 0040h:0018h - KEYBOARD - STATUS FLAGS 2\r
1729 EFI_KEY_DATA KeyData;\r
1730 LIST_ENTRY *Link;\r
1731 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
1732\r
1733 BiosKeyboardPrivate = Context;\r
1734\r
1735 //\r
1736 // Enter critical section\r
1737 //\r
1738 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
1739\r
1740 //\r
1741 // if there is no key present, just return\r
1742 //\r
1743 if (BiosKeyboardPrivate->ExtendedKeyboard) {\r
1744 Regs.H.AH = 0x11;\r
1745 } else {\r
1746 Regs.H.AH = 0x01;\r
1747 }\r
1748\r
1749 BiosKeyboardPrivate->LegacyBios->Int86 (\r
1750 BiosKeyboardPrivate->LegacyBios,\r
1751 0x16,\r
1752 &Regs\r
1753 );\r
1754 if (Regs.X.Flags.ZF != 0) {\r
1755 gBS->RestoreTPL (OldTpl);\r
1756 return;\r
1757 } \r
1758\r
1759 //\r
1760 // Read the key\r
1761 //\r
1762 if (BiosKeyboardPrivate->ExtendedKeyboard) {\r
1763 Regs.H.AH = 0x10;\r
1764 } else {\r
1765 Regs.H.AH = 0x00;\r
1766 }\r
1767\r
1768 BiosKeyboardPrivate->LegacyBios->Int86 (\r
1769 BiosKeyboardPrivate->LegacyBios,\r
1770 0x16,\r
1771 &Regs\r
1772 );\r
1773\r
1774 KeyData.Key.ScanCode = (UINT16) Regs.H.AH;\r
1775 KeyData.Key.UnicodeChar = (UINT16) Regs.H.AL;\r
f6c014fb 1776 DEBUG ((\r
1777 EFI_D_INFO,\r
1778 "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",\r
1779 KeyData.Key.ScanCode,\r
1780 KeyData.Key.UnicodeChar\r
1781 ));\r
1782 \r
bcecde14 1783 KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
1784 KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
1785 //\r
1786 // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB buffer in BDA (BIOS DATE AREA), then \r
1787 // Int 16 depend KB buffer and some key bits in BDA to translate the scancode to ASCII code, and return both the scancode and ASCII \r
1788 // code to Int 16 caller. This translation process works well if the Int 9 could response user input in time. But in Tiano enviorment, the Int 9 \r
1789 // will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when \r
1790 // KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit \r
1791 // in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode \r
1792 // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other dirvers \r
1793 // performance, like USB.\r
1794 //\r
1795 // 1. If CTRL or ALT release code is missed, all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In \r
1796 // this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA \r
1797 // after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the \r
1798 // CTRL and ALT.\r
1799 //\r
1800 // 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost \r
1801 // SHIFT again, the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA,\r
1802 // which will let persist to press SHIFT has same effection as only press one time. \r
1803 //\r
1804 //0040h:0017h - KEYBOARD - STATUS FLAGS 1\r
1805 // 7 INSert active\r
1806 // 6 Caps Lock active\r
1807 // 5 Num Lock active\r
1808 // 4 Scroll Lock active\r
1809 // 3 either Alt pressed\r
1810 // 2 either Ctrl pressed\r
1811 // 1 Left Shift pressed\r
1812 // 0 Right Shift pressed\r
1813\r
1814\r
1815 //\r
1816 // Clear the CTRL and ALT BDA flag\r
1817 //\r
1818 KbFlag1 = *((UINT8 *) (UINTN) 0x417); // read the STATUS FLAGS 1\r
1819 KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2\r
1820\r
f6c014fb 1821 DEBUG_CODE (\r
1822 {\r
1823 if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {\r
1824 DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n"));\r
1825 }\r
1826 if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {\r
1827 DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n"));\r
1828 }\r
1829 if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {\r
1830 DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n"));\r
1831 } \r
1832 if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {\r
1833 if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) {\r
1834 DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n"));\r
1835 } else {\r
1836 DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n"));\r
1837 }\r
1838 } \r
1839 if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {\r
1840 if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) {\r
1841 DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n"));\r
1842 } else {\r
1843 DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n"));\r
1844 }\r
1845 } \r
1846 if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {\r
1847 DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n"));\r
1848 }\r
1849 if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {\r
1850 DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n"));\r
1851 }\r
1852 }\r
1853 );\r
1854\r
bcecde14 1855 //\r
1856 // Record toggle state\r
1857 //\r
1858 if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {\r
1859 KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;\r
1860 }\r
1861 if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {\r
1862 KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;\r
1863 }\r
1864 if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {\r
1865 KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;\r
1866 }\r
1867 //\r
1868 // Record shift state\r
1869 // BUGBUG: Need add Menu key and Left/Right Logo key state in the future\r
1870 // \r
1871 if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {\r
1872 KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED;\r
1873 } \r
1874 if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {\r
1875 KeyData.KeyState.KeyShiftState |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED;\r
1876 } \r
1877 if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {\r
1878 KeyData.KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED;\r
1879 }\r
1880 if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {\r
1881 KeyData.KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED;\r
1882 }\r
1883\r
1884 //\r
1885 // Clear left alt and left ctrl BDA flag\r
1886 //\r
1887 KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);\r
1888 *((UINT8 *) (UINTN) 0x418) = KbFlag2;\r
1889 KbFlag1 &= ~0x0C; \r
1890 *((UINT8 *) (UINTN) 0x417) = KbFlag1; \r
1891\r
1892 \r
1893 //\r
1894 // Output EFI input key and shift/toggle state\r
1895 //\r
1896 if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) {\r
1897 KeyData.Key.ScanCode = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode);\r
1898 KeyData.Key.UnicodeChar = CHAR_NULL;\r
1899 } else {\r
1900 KeyData.Key.ScanCode = SCAN_NULL;\r
1901 }\r
1902\r
1903 //\r
1904 // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.\r
1905 //\r
1906 if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
1907 if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) {\r
1908 if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ==\r
1909 ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0)\r
1910 ) {\r
1911 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1);\r
1912 } else {\r
1913 KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1);\r
1914 }\r
1915 }\r
1916 }\r
1917\r
f6c014fb 1918 DEBUG ((\r
1919 EFI_D_INFO,\r
1920 "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",\r
1921 KeyData.Key.ScanCode,\r
1922 KeyData.Key.UnicodeChar\r
1923 ));\r
1924\r
bcecde14 1925 //\r
1926 // Need not return associated shift state if a class of printable characters that\r
1927 // are normally adjusted by shift modifiers.\r
1928 // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.\r
1929 //\r
1930 if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||\r
1931 (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')\r
1932 ) {\r
f6c014fb 1933 DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));\r
bcecde14 1934 KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);\r
1935 }\r
1936\r
1937 //\r
1938 // Invoke notification functions if exist\r
1939 //\r
1940 for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
1941 CurrentNotify = CR (\r
1942 Link, \r
1943 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1944 NotifyEntry, \r
1945 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1946 );\r
1947 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) { \r
1948 CurrentNotify->KeyNotificationFn (&KeyData);\r
1949 }\r
1950 }\r
1951\r
bcecde14 1952 Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);\r
1953 //\r
1954 // Leave critical section and return\r
1955 //\r
1956 gBS->RestoreTPL (OldTpl);\r
1957\r
1958 return ; \r
1959}\r
1960\r
1961/**\r
1962 Free keyboard notify list.\r
1963\r
1964 @param ListHead The list head\r
1965\r
1966 @retval EFI_SUCCESS Free the notify list successfully\r
1967 @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
1968\r
1969**/\r
1970EFI_STATUS\r
1971BiosKeyboardFreeNotifyList (\r
1972 IN OUT LIST_ENTRY *ListHead\r
1973 )\r
1974{\r
1975 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
1976\r
1977 if (ListHead == NULL) {\r
1978 return EFI_INVALID_PARAMETER;\r
1979 }\r
1980 while (!IsListEmpty (ListHead)) {\r
1981 NotifyNode = CR (\r
1982 ListHead->ForwardLink, \r
1983 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
1984 NotifyEntry, \r
1985 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
1986 );\r
1987 RemoveEntryList (ListHead->ForwardLink);\r
1988 gBS->FreePool (NotifyNode);\r
1989 }\r
1990\r
1991 return EFI_SUCCESS;\r
1992}\r
1993\r
1994/**\r
1995 Check if key is registered.\r
1996\r
1997 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke \r
1998 state data for the key that was registered.\r
1999 @param InputData A pointer to a buffer that is filled in with the keystroke \r
2000 state data for the key that was pressed.\r
2001\r
2002 @retval TRUE Key be pressed matches a registered key.\r
2003 @retval FLASE Match failed. \r
2004 \r
2005**/\r
2006BOOLEAN\r
2007IsKeyRegistered (\r
2008 IN EFI_KEY_DATA *RegsiteredData,\r
2009 IN EFI_KEY_DATA *InputData\r
2010 )\r
2011{\r
2012 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
2013 \r
2014 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
2015 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
2016 return FALSE; \r
2017 } \r
2018 \r
2019 //\r
2020 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
2021 //\r
2022 if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
2023 RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
2024 return FALSE; \r
2025 } \r
2026 if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
2027 RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
2028 return FALSE; \r
2029 } \r
2030 \r
2031 return TRUE;\r
2032\r
2033}\r
2034\r
2035/**\r
2036 Waiting on the keyboard event, if there's any key pressed by the user, signal the event\r
2037\r
2038 @param Event The event that be siganlled when any key has been stroked.\r
2039 @param Context Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.\r
2040 \r
2041**/\r
2042VOID\r
2043EFIAPI\r
2044BiosKeyboardWaitForKeyEx (\r
2045 IN EFI_EVENT Event,\r
2046 IN VOID *Context\r
2047 )\r
2048{ \r
2049 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2050 \r
2051 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context); \r
2052 BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn);\r
2053\r
2054}\r
2055\r
2056/**\r
2057 Reset the input device and optionaly run diagnostics\r
2058 \r
2059 @param This Protocol instance pointer.\r
2060 @param ExtendedVerification Driver may perform diagnostics on reset.\r
2061\r
2062 @retval EFI_SUCCESS The device was reset.\r
2063 @retval EFI_DEVICE_ERROR The device is not functioning properly and could \r
2064 not be reset.\r
2065\r
2066**/\r
2067EFI_STATUS\r
2068EFIAPI\r
2069BiosKeyboardResetEx (\r
2070 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2071 IN BOOLEAN ExtendedVerification\r
2072 )\r
2073{\r
2074 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2075 EFI_STATUS Status;\r
2076 EFI_TPL OldTpl;\r
2077 \r
2078 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This); \r
2079\r
2080 Status = BiosKeyboardPrivate->SimpleTextIn.Reset (\r
2081 &BiosKeyboardPrivate->SimpleTextIn, \r
2082 ExtendedVerification\r
2083 );\r
2084 if (EFI_ERROR (Status)) {\r
2085 return EFI_DEVICE_ERROR;\r
2086 }\r
2087\r
2088 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
2089\r
2090 gBS->RestoreTPL (OldTpl);\r
2091 \r
2092 return EFI_SUCCESS;\r
2093\r
2094}\r
2095\r
2096/**\r
2097 Reads the next keystroke from the input device. The WaitForKey Event can \r
2098 be used to test for existance of a keystroke via WaitForEvent () call.\r
2099\r
2100 @param This Protocol instance pointer.\r
2101 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
2102 state data for the key that was pressed.\r
2103 \r
2104 @retval EFI_SUCCESS The keystroke information was returned.\r
2105 @retval EFI_NOT_READY There was no keystroke data availiable.\r
2106 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to \r
2107 hardware errors.\r
2108 @retval EFI_INVALID_PARAMETER KeyData is NULL. \r
2109 \r
2110**/\r
2111EFI_STATUS\r
2112EFIAPI\r
2113BiosKeyboardReadKeyStrokeEx (\r
2114 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2115 OUT EFI_KEY_DATA *KeyData\r
2116 )\r
2117{\r
2118 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2119\r
2120 if (KeyData == NULL) {\r
2121 return EFI_INVALID_PARAMETER;\r
2122 }\r
2123 \r
2124 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
2125\r
2126 return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, KeyData);\r
2127 \r
2128}\r
2129\r
2130/**\r
2131 Set certain state for the input device.\r
2132\r
2133 @param This Protocol instance pointer.\r
2134 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
2135 state for the input device.\r
2136\r
2137 @retval EFI_SUCCESS The device state was set successfully.\r
2138 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could \r
2139 not have the setting adjusted.\r
2140 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
2141 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL. \r
2142\r
2143**/ \r
2144EFI_STATUS\r
2145EFIAPI\r
2146BiosKeyboardSetState (\r
2147 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2148 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
2149 )\r
2150{\r
2151 EFI_STATUS Status;\r
2152 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2153 EFI_TPL OldTpl;\r
2154 EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;\r
2155 UINT8 Command;\r
2156\r
2157 if (KeyToggleState == NULL) {\r
2158 return EFI_INVALID_PARAMETER;\r
2159 }\r
2160\r
5829afe3 2161 //\r
2162 // Thunk keyboard driver doesn't support partial keystroke.\r
2163 //\r
2164 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||\r
2165 (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED\r
2166 ) {\r
bcecde14 2167 return EFI_UNSUPPORTED;\r
2168 }\r
2169\r
2170 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
2171 //\r
2172 // See if the Legacy BIOS Protocol is available\r
2173 //\r
2174 Status = gBS->LocateProtocol (\r
2175 &gEfiLegacyBiosProtocolGuid,\r
2176 NULL,\r
2177 (VOID **) &LegacyBios\r
2178 );\r
2179\r
2180 ASSERT_EFI_ERROR (Status);\r
2181 //\r
2182 // Enter critical section\r
2183 //\r
2184 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
2185\r
2186 Command = 0;\r
2187 if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
2188 Command |= 4;\r
2189 }\r
2190 if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
2191 Command |= 2;\r
2192 }\r
2193 if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
2194 Command |= 1;\r
2195 }\r
2196\r
2197 Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);\r
2198 if (EFI_ERROR (Status)) {\r
2199 return EFI_DEVICE_ERROR;\r
2200 } \r
2201 Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);\r
2202 if (EFI_ERROR (Status)) {\r
2203 return EFI_DEVICE_ERROR;\r
2204 }\r
2205 Status = KeyboardWrite (BiosKeyboardPrivate, Command);\r
2206 if (EFI_ERROR (Status)) {\r
2207 return EFI_DEVICE_ERROR;\r
2208 } \r
2209 //\r
2210 // Call Legacy BIOS Protocol to set whatever is necessary\r
2211 //\r
2212 LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);\r
2213\r
2214 Status = EFI_SUCCESS;\r
2215\r
2216 //\r
2217 // Leave critical section and return\r
2218 //\r
2219 gBS->RestoreTPL (OldTpl);\r
2220\r
2221 return Status;\r
2222\r
2223}\r
2224\r
2225/**\r
2226 Register a notification function for a particular keystroke for the input device.\r
2227\r
2228 @param This Protocol instance pointer.\r
2229 @param KeyData A pointer to a buffer that is filled in with the keystroke \r
2230 information data for the key that was pressed.\r
2231 @param KeyNotificationFunction Points to the function to be called when the key \r
2232 sequence is typed specified by KeyData. \r
2233 @param NotifyHandle Points to the unique handle assigned to the registered notification. \r
2234\r
2235 \r
2236 @retval EFI_SUCCESS The notification function was registered successfully.\r
2237 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
2238 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
2239 \r
2240**/ \r
2241EFI_STATUS\r
2242EFIAPI\r
2243BiosKeyboardRegisterKeyNotify (\r
2244 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2245 IN EFI_KEY_DATA *KeyData,\r
2246 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
2247 OUT EFI_HANDLE *NotifyHandle\r
2248 )\r
2249{\r
2250 EFI_STATUS Status;\r
2251 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2252 EFI_TPL OldTpl;\r
2253 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
2254 LIST_ENTRY *Link;\r
2255 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
2256\r
2257 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
2258 return EFI_INVALID_PARAMETER;\r
2259 }\r
2260\r
2261 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
2262\r
2263 //\r
2264 // Enter critical section\r
2265 //\r
2266 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
2267\r
2268 //\r
2269 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
2270 //\r
2271 for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
2272 CurrentNotify = CR (\r
2273 Link, \r
2274 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
2275 NotifyEntry, \r
2276 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
2277 );\r
2278 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
2279 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
2280 *NotifyHandle = CurrentNotify->NotifyHandle; \r
2281 Status = EFI_SUCCESS;\r
2282 goto Exit;\r
2283 }\r
2284 } \r
2285 }\r
2286\r
2287 //\r
2288 // Allocate resource to save the notification function\r
2289 //\r
2290 \r
2291 NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
2292 if (NewNotify == NULL) {\r
2293 Status = EFI_OUT_OF_RESOURCES;\r
2294 goto Exit;\r
2295 }\r
2296\r
2297 NewNotify->Signature = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
2298 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
2299 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
2300 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
2301 InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);\r
2302\r
2303 *NotifyHandle = NewNotify->NotifyHandle; \r
2304 Status = EFI_SUCCESS;\r
2305 \r
2306Exit:\r
2307 //\r
2308 // Leave critical section and return\r
2309 //\r
2310 gBS->RestoreTPL (OldTpl);\r
2311 return Status; \r
2312}\r
2313\r
2314/**\r
2315 Remove a registered notification function from a particular keystroke.\r
2316\r
2317 @param This Protocol instance pointer. \r
2318 @param NotificationHandle The handle of the notification function being unregistered.\r
2319 \r
2320 @retval EFI_SUCCESS The notification function was unregistered successfully.\r
2321 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
2322 \r
2323**/ \r
2324EFI_STATUS\r
2325EFIAPI\r
2326BiosKeyboardUnregisterKeyNotify (\r
2327 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
2328 IN EFI_HANDLE NotificationHandle\r
2329 )\r
2330{\r
2331 EFI_STATUS Status;\r
2332 BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;\r
2333 EFI_TPL OldTpl;\r
2334 LIST_ENTRY *Link;\r
2335 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
2336\r
2337 //\r
2338 // Check incoming notification handle\r
2339 //\r
2340 if (NotificationHandle == NULL) {\r
2341 return EFI_INVALID_PARAMETER;\r
2342 }\r
2343\r
2344 if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
2345 return EFI_INVALID_PARAMETER;\r
2346 } \r
2347 \r
2348 BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);\r
2349 \r
2350 //\r
2351 // Enter critical section\r
2352 //\r
2353 OldTpl = gBS->RaiseTPL (TPL_NOTIFY); \r
2354\r
2355 for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {\r
2356 CurrentNotify = CR (\r
2357 Link, \r
2358 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
2359 NotifyEntry, \r
2360 BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
2361 ); \r
2362 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
2363 //\r
2364 // Remove the notification function from NotifyList and free resources\r
2365 //\r
2366 RemoveEntryList (&CurrentNotify->NotifyEntry); \r
2367\r
2368 Status = EFI_SUCCESS;\r
2369 goto Exit;\r
2370 }\r
2371 }\r
2372 \r
2373 //\r
2374 // Can not find the specified Notification Handle\r
2375 //\r
2376 Status = EFI_INVALID_PARAMETER;\r
2377\r
2378Exit:\r
2379 //\r
2380 // Leave critical section and return\r
2381 //\r
2382 gBS->RestoreTPL (OldTpl);\r
2383 return Status;\r
2384}\r
2385\r
2386/**\r
2387 The user Entry Point for module BiosKeyboard. The user code starts with this function.\r
2388\r
2389 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
2390 @param[in] SystemTable A pointer to the EFI System Table.\r
2391\r
2392 @retval EFI_SUCCESS The entry point is executed successfully.\r
2393 @retval other Some error occurs when executing this entry point.\r
2394\r
2395**/\r
2396EFI_STATUS\r
2397EFIAPI\r
2398InitializeBiosKeyboard(\r
2399 IN EFI_HANDLE ImageHandle,\r
2400 IN EFI_SYSTEM_TABLE *SystemTable\r
2401 )\r
2402{\r
2403 EFI_STATUS Status;\r
2404\r
2405 //\r
2406 // Install driver model protocol(s).\r
2407 //\r
2408 Status = EfiLibInstallDriverBindingComponentName2 (\r
2409 ImageHandle,\r
2410 SystemTable,\r
2411 &gBiosKeyboardDriverBinding,\r
2412 ImageHandle,\r
2413 &gBiosKeyboardComponentName,\r
2414 &gBiosKeyboardComponentName2\r
2415 );\r
2416 ASSERT_EFI_ERROR (Status);\r
2417\r
2418 return Status;\r
2419}\r