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