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