]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
Apply WriteUnaligned64() to write DevicePath structure.
[mirror_edk2.git] / MdeModulePkg / Universal / Console / TerminalDxe / TerminalConIn.c
CommitLineData
e49ef433 1/** @file\r
66aa04e4 2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.\r
fb0b259e 3\r
e49ef433 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
fb0b259e 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
95276127 12\r
13**/\r
14\r
95276127 15#include "Terminal.h"\r
16\r
95276127 17\r
e49ef433 18/**\r
19 Reads the next keystroke from the input device. The WaitForKey Event can\r
11baadb6 20 be used to test for existence of a keystroke via WaitForEvent () call.\r
e49ef433 21\r
22 @param TerminalDevice Terminal driver private structure\r
23 @param KeyData A pointer to a buffer that is filled in with the\r
24 keystroke state data for the key that was\r
25 pressed.\r
26\r
27 @retval EFI_SUCCESS The keystroke information was returned.\r
11baadb6 28 @retval EFI_NOT_READY There was no keystroke data available.\r
e49ef433 29 @retval EFI_DEVICE_ERROR The keystroke information was not returned due\r
30 to hardware errors.\r
31 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
32\r
33**/\r
66aa04e4 34EFI_STATUS\r
35ReadKeyStrokeWorker (\r
36 IN TERMINAL_DEV *TerminalDevice,\r
37 OUT EFI_KEY_DATA *KeyData\r
38 )\r
66aa04e4 39{\r
40 EFI_STATUS Status;\r
41 LIST_ENTRY *Link;\r
11baadb6 42 LIST_ENTRY *NotifyList;\r
66aa04e4 43 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
44\r
45 if (KeyData == NULL) {\r
46 return EFI_INVALID_PARAMETER;\r
fb0b259e 47 }\r
66aa04e4 48\r
49 //\r
50 // Initialize *Key to nonsense value.\r
51 //\r
52 KeyData->Key.ScanCode = SCAN_NULL;\r
53 KeyData->Key.UnicodeChar = 0;\r
54\r
55 Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);\r
56 if (EFI_ERROR (Status)) {\r
57 return EFI_NOT_READY;\r
58 }\r
59\r
60 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {\r
61 return EFI_NOT_READY;\r
62 }\r
63\r
64 KeyData->KeyState.KeyShiftState = 0;\r
65 KeyData->KeyState.KeyToggleState = 0;\r
66\r
67 //\r
68 // Invoke notification functions if exist\r
69 //\r
11baadb6 70 NotifyList = &TerminalDevice->NotifyList;\r
71 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
66aa04e4 72 CurrentNotify = CR (\r
fb0b259e 73 Link,\r
74 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
75 NotifyEntry,\r
66aa04e4 76 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
77 );\r
fb0b259e 78 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 79 CurrentNotify->KeyNotificationFn (KeyData);\r
80 }\r
81 }\r
82\r
83 return EFI_SUCCESS;\r
84\r
85}\r
86\r
e49ef433 87/**\r
88 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().\r
89 This driver only perform dependent serial device reset regardless of\r
90 the value of ExtendeVerification\r
66aa04e4 91\r
e49ef433 92 @param This Indicates the calling context.\r
93 @param ExtendedVerification Skip by this driver.\r
94\r
00bfdbe1 95 @retval EFI_SUCCESS The reset operation succeeds.\r
96 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.\r
e49ef433 97\r
98**/\r
95276127 99EFI_STATUS\r
100EFIAPI\r
101TerminalConInReset (\r
102 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
103 IN BOOLEAN ExtendedVerification\r
104 )\r
95276127 105{\r
106 EFI_STATUS Status;\r
107 TERMINAL_DEV *TerminalDevice;\r
108\r
109 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
110\r
111 //\r
112 // Report progress code here\r
113 //\r
114 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
115 EFI_PROGRESS_CODE,\r
97a079ed 116 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset),\r
95276127 117 TerminalDevice->DevicePath\r
118 );\r
119\r
120 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);\r
121\r
122 //\r
5c998646 123 // Make all the internal buffer empty for keys\r
95276127 124 //\r
5c998646 125 TerminalDevice->RawFiFo->Head = TerminalDevice->RawFiFo->Tail;\r
126 TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;\r
127 TerminalDevice->EfiKeyFiFo->Head = TerminalDevice->EfiKeyFiFo->Tail;\r
95276127 128\r
129 if (EFI_ERROR (Status)) {\r
130 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
131 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
97a079ed 132 PcdGet32 (PcdStatusCodeValueRemoteConsoleError),\r
95276127 133 TerminalDevice->DevicePath\r
134 );\r
135 }\r
136\r
137 return Status;\r
138}\r
139\r
e49ef433 140/**\r
141 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().\r
142\r
8fd98315 143 @param This Indicates the calling context.\r
144 @param Key A pointer to a buffer that is filled in with the\r
145 keystroke information for the key that was sent\r
146 from terminal.\r
e49ef433 147\r
00bfdbe1 148 @retval EFI_SUCCESS The keystroke information is returned successfully.\r
149 @retval EFI_NOT_READY There is no keystroke data available.\r
150 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.\r
e49ef433 151\r
152**/\r
95276127 153EFI_STATUS\r
154EFIAPI\r
155TerminalConInReadKeyStroke (\r
156 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
157 OUT EFI_INPUT_KEY *Key\r
158 )\r
95276127 159{\r
160 TERMINAL_DEV *TerminalDevice;\r
161 EFI_STATUS Status;\r
66aa04e4 162 EFI_KEY_DATA KeyData;\r
95276127 163\r
95276127 164 //\r
165 // get TERMINAL_DEV from "This" parameter.\r
166 //\r
167 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
168\r
66aa04e4 169 Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);\r
95276127 170 if (EFI_ERROR (Status)) {\r
66aa04e4 171 return Status;\r
172 }\r
173\r
174 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
175\r
176 return EFI_SUCCESS;\r
177\r
178}\r
179\r
e49ef433 180/**\r
8fd98315 181 Check if the key already has been registered.\r
5c998646 182\r
11baadb6 183 If both RegsiteredData and InputData is NULL, then ASSERT().\r
e49ef433 184\r
185 @param RegsiteredData A pointer to a buffer that is filled in with the\r
186 keystroke state data for the key that was\r
187 registered.\r
188 @param InputData A pointer to a buffer that is filled in with the\r
189 keystroke state data for the key that was\r
190 pressed.\r
191\r
192 @retval TRUE Key be pressed matches a registered key.\r
193 @retval FLASE Match failed.\r
194\r
195**/\r
66aa04e4 196BOOLEAN\r
197IsKeyRegistered (\r
198 IN EFI_KEY_DATA *RegsiteredData,\r
199 IN EFI_KEY_DATA *InputData\r
200 )\r
66aa04e4 201{\r
202 ASSERT (RegsiteredData != NULL && InputData != NULL);\r
fb0b259e 203\r
66aa04e4 204 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
205 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
fb0b259e 206 return FALSE;\r
207 }\r
208\r
66aa04e4 209 return TRUE;\r
210}\r
211\r
212\r
e49ef433 213\r
214/**\r
215 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event\r
216 Signal the event if there is key available\r
217\r
218 @param Event Indicates the event that invoke this function.\r
219 @param Context Indicates the calling context.\r
220\r
e49ef433 221**/\r
66aa04e4 222VOID\r
223EFIAPI\r
224TerminalConInWaitForKeyEx (\r
225 IN EFI_EVENT Event,\r
226 IN VOID *Context\r
227 )\r
66aa04e4 228{\r
229 TERMINAL_DEV *TerminalDevice;\r
fb0b259e 230\r
66aa04e4 231 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);\r
232\r
233 TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);\r
234\r
235}\r
236\r
237//\r
238// Simple Text Input Ex protocol functions\r
239//\r
240\r
e49ef433 241/**\r
11baadb6 242 Reset the input device and optionally run diagnostics\r
e49ef433 243\r
244 @param This Protocol instance pointer.\r
245 @param ExtendedVerification Driver may perform diagnostics on reset.\r
246\r
247 @retval EFI_SUCCESS The device was reset.\r
248 @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
249 not be reset.\r
250\r
251**/\r
66aa04e4 252EFI_STATUS\r
253EFIAPI\r
254TerminalConInResetEx (\r
255 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
256 IN BOOLEAN ExtendedVerification\r
257 )\r
66aa04e4 258{\r
259 EFI_STATUS Status;\r
260 TERMINAL_DEV *TerminalDevice;\r
261\r
262 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
263\r
264 Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);\r
265 if (EFI_ERROR (Status)) {\r
266 return EFI_DEVICE_ERROR;\r
95276127 267 }\r
268\r
66aa04e4 269 return EFI_SUCCESS;\r
fb0b259e 270\r
66aa04e4 271}\r
272\r
e49ef433 273\r
274/**\r
275 Reads the next keystroke from the input device. The WaitForKey Event can\r
11baadb6 276 be used to test for existence of a keystroke via WaitForEvent () call.\r
e49ef433 277\r
278 @param This Protocol instance pointer.\r
279 @param KeyData A pointer to a buffer that is filled in with the\r
280 keystroke state data for the key that was\r
281 pressed.\r
282\r
283 @retval EFI_SUCCESS The keystroke information was returned.\r
11baadb6 284 @retval EFI_NOT_READY There was no keystroke data available.\r
e49ef433 285 @retval EFI_DEVICE_ERROR The keystroke information was not returned due\r
286 to hardware errors.\r
287 @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
288\r
289**/\r
66aa04e4 290EFI_STATUS\r
291EFIAPI\r
292TerminalConInReadKeyStrokeEx (\r
293 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
294 OUT EFI_KEY_DATA *KeyData\r
295 )\r
66aa04e4 296{\r
297 TERMINAL_DEV *TerminalDevice;\r
298\r
299 if (KeyData == NULL) {\r
300 return EFI_INVALID_PARAMETER;\r
fb0b259e 301 }\r
66aa04e4 302\r
303 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
304\r
305 return ReadKeyStrokeWorker (TerminalDevice, KeyData);\r
306\r
307}\r
308\r
e49ef433 309\r
310/**\r
311 Set certain state for the input device.\r
312\r
313 @param This Protocol instance pointer.\r
314 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
315 state for the input device.\r
316\r
317 @retval EFI_SUCCESS The device state was set successfully.\r
318 @retval EFI_DEVICE_ERROR The device is not functioning correctly and\r
319 could not have the setting adjusted.\r
320 @retval EFI_UNSUPPORTED The device does not have the ability to set its\r
321 state.\r
322 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
323\r
324**/\r
66aa04e4 325EFI_STATUS\r
326EFIAPI\r
327TerminalConInSetState (\r
328 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
329 IN EFI_KEY_TOGGLE_STATE *KeyToggleState\r
330 )\r
66aa04e4 331{\r
332 if (KeyToggleState == NULL) {\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
95276127 335\r
336 return EFI_SUCCESS;\r
66aa04e4 337}\r
95276127 338\r
e49ef433 339\r
340/**\r
341 Register a notification function for a particular keystroke for the input device.\r
342\r
343 @param This Protocol instance pointer.\r
344 @param KeyData A pointer to a buffer that is filled in with the\r
345 keystroke information data for the key that was\r
346 pressed.\r
347 @param KeyNotificationFunction Points to the function to be called when the key\r
348 sequence is typed specified by KeyData.\r
349 @param NotifyHandle Points to the unique handle assigned to the\r
350 registered notification.\r
351\r
352 @retval EFI_SUCCESS The notification function was registered\r
353 successfully.\r
11baadb6 354 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data\r
e49ef433 355 structures.\r
356 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
357\r
358**/\r
66aa04e4 359EFI_STATUS\r
360EFIAPI\r
361TerminalConInRegisterKeyNotify (\r
362 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
363 IN EFI_KEY_DATA *KeyData,\r
364 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
365 OUT EFI_HANDLE *NotifyHandle\r
366 )\r
66aa04e4 367{\r
66aa04e4 368 TERMINAL_DEV *TerminalDevice;\r
369 TERMINAL_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
370 LIST_ENTRY *Link;\r
11baadb6 371 LIST_ENTRY *NotifyList;\r
fb0b259e 372 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
66aa04e4 373\r
374 if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
375 return EFI_INVALID_PARAMETER;\r
376 }\r
377\r
378 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
379\r
380 //\r
381 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
382 //\r
11baadb6 383 NotifyList = &TerminalDevice->NotifyList;\r
384 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
66aa04e4 385 CurrentNotify = CR (\r
fb0b259e 386 Link,\r
387 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
388 NotifyEntry,\r
66aa04e4 389 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
390 );\r
fb0b259e 391 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
66aa04e4 392 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
fb0b259e 393 *NotifyHandle = CurrentNotify->NotifyHandle;\r
66aa04e4 394 return EFI_SUCCESS;\r
395 }\r
396 }\r
397 }\r
398\r
399 //\r
400 // Allocate resource to save the notification function\r
fb0b259e 401 //\r
66aa04e4 402 NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));\r
403 if (NewNotify == NULL) {\r
404 return EFI_OUT_OF_RESOURCES;\r
fb0b259e 405 }\r
66aa04e4 406\r
fb0b259e 407 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
66aa04e4 408 NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
7fc80d44 409 NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
66aa04e4 410 CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
411 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);\r
7fc80d44 412\r
fb0b259e 413 *NotifyHandle = NewNotify->NotifyHandle;\r
66aa04e4 414\r
415 return EFI_SUCCESS;\r
95276127 416}\r
417\r
e49ef433 418\r
419/**\r
420 Remove a registered notification function from a particular keystroke.\r
421\r
422 @param This Protocol instance pointer.\r
423 @param NotificationHandle The handle of the notification function being\r
424 unregistered.\r
425\r
426 @retval EFI_SUCCESS The notification function was unregistered\r
427 successfully.\r
428 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
429 @retval EFI_NOT_FOUND Can not find the matching entry in database.\r
430\r
431**/\r
66aa04e4 432EFI_STATUS\r
433EFIAPI\r
434TerminalConInUnregisterKeyNotify (\r
435 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
436 IN EFI_HANDLE NotificationHandle\r
437 )\r
66aa04e4 438{\r
66aa04e4 439 TERMINAL_DEV *TerminalDevice;\r
440 LIST_ENTRY *Link;\r
441 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
11baadb6 442 LIST_ENTRY *NotifyList;\r
5c998646 443\r
66aa04e4 444 if (NotificationHandle == NULL) {\r
445 return EFI_INVALID_PARAMETER;\r
fb0b259e 446 }\r
447\r
0dc99784 448 if (((TERMINAL_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {\r
449 return EFI_INVALID_PARAMETER;\r
450 } \r
451 \r
66aa04e4 452 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);\r
453\r
11baadb6 454 NotifyList = &TerminalDevice->NotifyList;\r
455 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {\r
66aa04e4 456 CurrentNotify = CR (\r
fb0b259e 457 Link,\r
458 TERMINAL_CONSOLE_IN_EX_NOTIFY,\r
459 NotifyEntry,\r
66aa04e4 460 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
461 );\r
462 if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
463 //\r
464 // Remove the notification function from NotifyList and free resources\r
465 //\r
fb0b259e 466 RemoveEntryList (&CurrentNotify->NotifyEntry);\r
7fc80d44 467\r
fb0b259e 468 gBS->FreePool (CurrentNotify);\r
66aa04e4 469 return EFI_SUCCESS;\r
470 }\r
471 }\r
fb0b259e 472\r
473 return EFI_NOT_FOUND;\r
66aa04e4 474}\r
475\r
e49ef433 476/**\r
5c998646 477 Translate raw data into Unicode (according to different encode), and\r
478 translate Unicode into key information. (according to different standard).\r
66aa04e4 479\r
e49ef433 480 @param TerminalDevice Terminal driver private structure.\r
481\r
e49ef433 482**/\r
95276127 483VOID\r
484TranslateRawDataToEfiKey (\r
485 IN TERMINAL_DEV *TerminalDevice\r
486 )\r
95276127 487{\r
488 switch (TerminalDevice->TerminalType) {\r
489\r
e49ef433 490 case PCANSITYPE:\r
491 case VT100TYPE:\r
492 case VT100PLUSTYPE:\r
95276127 493 AnsiRawDataToUnicode (TerminalDevice);\r
494 UnicodeToEfiKey (TerminalDevice);\r
495 break;\r
496\r
e49ef433 497 case VTUTF8TYPE:\r
95276127 498 //\r
499 // Process all the raw data in the RawFIFO,\r
500 // put the processed key into UnicodeFIFO.\r
501 //\r
502 VTUTF8RawDataToUnicode (TerminalDevice);\r
503\r
504 //\r
505 // Translate all the Unicode data in the UnicodeFIFO to Efi key,\r
506 // then put into EfiKeyFIFO.\r
507 //\r
508 UnicodeToEfiKey (TerminalDevice);\r
509\r
510 break;\r
511 }\r
512}\r
513\r
e49ef433 514/**\r
515 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event\r
516 Signal the event if there is key available\r
517\r
518 @param Event Indicates the event that invoke this function.\r
519 @param Context Indicates the calling context.\r
520\r
e49ef433 521**/\r
95276127 522VOID\r
523EFIAPI\r
524TerminalConInWaitForKey (\r
525 IN EFI_EVENT Event,\r
526 IN VOID *Context\r
527 )\r
95276127 528{\r
529 //\r
530 // Someone is waiting on the keystroke event, if there's\r
531 // a key pending, signal the event\r
532 //\r
533 // Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
534 //\r
535 if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {\r
536\r
537 gBS->SignalEvent (Event);\r
538 }\r
539}\r
540\r
fb0b259e 541\r
e49ef433 542/**\r
543 Check for a pending key in the Efi Key FIFO or Serial device buffer.\r
fb0b259e 544\r
e49ef433 545 @param This Indicates the calling context.\r
fb0b259e 546\r
8fd98315 547 @retval EFI_SUCCESS There is key pending.\r
548 @retval EFI_NOT_READY There is no key pending.\r
11baadb6 549 @retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.\r
fb0b259e 550\r
e49ef433 551**/\r
552EFI_STATUS\r
553TerminalConInCheckForKey (\r
554 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
555 )\r
95276127 556{\r
557 EFI_STATUS Status;\r
558 TERMINAL_DEV *TerminalDevice;\r
559 UINT32 Control;\r
560 UINT8 Input;\r
561 EFI_SERIAL_IO_MODE *Mode;\r
562 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
563 UINTN SerialInTimeOut;\r
564\r
565 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);\r
566\r
567 SerialIo = TerminalDevice->SerialIo;\r
568 if (SerialIo == NULL) {\r
569 return EFI_DEVICE_ERROR;\r
570 }\r
571 //\r
572 // if current timeout value for serial device is not identical with\r
573 // the value saved in TERMINAL_DEV structure, then recalculate the\r
574 // timeout value again and set serial attribute according to this value.\r
575 //\r
576 Mode = SerialIo->Mode;\r
577 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {\r
578\r
579 SerialInTimeOut = 0;\r
580 if (Mode->BaudRate != 0) {\r
ab76200c 581 //\r
582 // According to BAUD rate to calculate the timeout value.\r
583 //\r
95276127 584 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate;\r
585 }\r
586\r
587 Status = SerialIo->SetAttributes (\r
588 SerialIo,\r
589 Mode->BaudRate,\r
590 Mode->ReceiveFifoDepth,\r
591 (UINT32) SerialInTimeOut,\r
592 (EFI_PARITY_TYPE) (Mode->Parity),\r
593 (UINT8) Mode->DataBits,\r
594 (EFI_STOP_BITS_TYPE) (Mode->StopBits)\r
595 );\r
596\r
597 if (EFI_ERROR (Status)) {\r
598 TerminalDevice->SerialInTimeOut = 0;\r
599 } else {\r
600 TerminalDevice->SerialInTimeOut = SerialInTimeOut;\r
601 }\r
602 }\r
603 //\r
ab76200c 604 // Check whether serial buffer is empty.\r
95276127 605 //\r
606 Status = SerialIo->GetControl (SerialIo, &Control);\r
607\r
ab76200c 608 if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {\r
95276127 609 //\r
610 // Translate all the raw data in RawFIFO into EFI Key,\r
611 // according to different terminal type supported.\r
612 //\r
613 TranslateRawDataToEfiKey (TerminalDevice);\r
614\r
615 //\r
616 // if there is pre-fetched Efi Key in EfiKeyFIFO buffer,\r
617 // return directly.\r
618 //\r
619 if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
620 return EFI_SUCCESS;\r
621 } else {\r
622 return EFI_NOT_READY;\r
623 }\r
624 }\r
625 //\r
626 // Fetch all the keys in the serial buffer,\r
627 // and insert the byte stream into RawFIFO.\r
628 //\r
629 do {\r
630\r
631 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);\r
632\r
633 if (EFI_ERROR (Status)) {\r
634 if (Status == EFI_DEVICE_ERROR) {\r
635 REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
636 EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
97a079ed 637 PcdGet32 (PcdStatusCodeValueRemoteConsoleInputError),\r
95276127 638 TerminalDevice->DevicePath\r
639 );\r
640 }\r
641 break;\r
642 }\r
643\r
644 RawFiFoInsertOneKey (TerminalDevice, Input);\r
645 } while (TRUE);\r
646\r
647 //\r
648 // Translate all the raw data in RawFIFO into EFI Key,\r
649 // according to different terminal type supported.\r
650 //\r
651 TranslateRawDataToEfiKey (TerminalDevice);\r
652\r
653 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
654 return EFI_NOT_READY;\r
655 }\r
656\r
657 return EFI_SUCCESS;\r
658}\r
659\r
e49ef433 660/**\r
661 Get one key out of serial buffer.\r
662\r
11baadb6 663 @param SerialIo Serial I/O protocol attached to the serial device.\r
e49ef433 664 @param Output The fetched key.\r
665\r
00bfdbe1 666 @retval EFI_NOT_READY If serial buffer is empty.\r
667 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.\r
668 @retval EFI_SUCCESS If reading serial buffer successfully, put\r
e49ef433 669 the fetched key to the parameter output.\r
670\r
671**/\r
95276127 672EFI_STATUS\r
673GetOneKeyFromSerial (\r
674 EFI_SERIAL_IO_PROTOCOL *SerialIo,\r
e49ef433 675 UINT8 *Output\r
95276127 676 )\r
95276127 677{\r
678 EFI_STATUS Status;\r
679 UINTN Size;\r
680\r
681 Size = 1;\r
e49ef433 682 *Output = 0;\r
95276127 683\r
ab76200c 684 //\r
685 // Read one key from serial I/O device.\r
686 //\r
e49ef433 687 Status = SerialIo->Read (SerialIo, &Size, Output);\r
95276127 688\r
689 if (EFI_ERROR (Status)) {\r
690\r
691 if (Status == EFI_TIMEOUT) {\r
692 return EFI_NOT_READY;\r
693 }\r
694\r
695 return EFI_DEVICE_ERROR;\r
696\r
697 }\r
698\r
e49ef433 699 if (*Output == 0) {\r
95276127 700 return EFI_NOT_READY;\r
701 }\r
702\r
703 return EFI_SUCCESS;\r
704}\r
705\r
e49ef433 706/**\r
707 Insert one byte raw data into the Raw Data FIFO.\r
708\r
709 @param TerminalDevice Terminal driver private structure.\r
710 @param Input The key will be input.\r
711\r
00bfdbe1 712 @retval TRUE If insert successfully.\r
713 @retval FLASE If Raw Data buffer is full before key insertion,\r
e49ef433 714 and the key is lost.\r
715\r
716**/\r
95276127 717BOOLEAN\r
718RawFiFoInsertOneKey (\r
719 TERMINAL_DEV *TerminalDevice,\r
720 UINT8 Input\r
721 )\r
95276127 722{\r
723 UINT8 Tail;\r
724\r
5c998646 725 Tail = TerminalDevice->RawFiFo->Tail;\r
95276127 726\r
727 if (IsRawFiFoFull (TerminalDevice)) {\r
728 //\r
729 // Raw FIFO is full\r
730 //\r
731 return FALSE;\r
732 }\r
733\r
5c998646 734 TerminalDevice->RawFiFo->Data[Tail] = Input;\r
95276127 735\r
5c998646 736 TerminalDevice->RawFiFo->Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
95276127 737\r
738 return TRUE;\r
739}\r
740\r
e49ef433 741/**\r
742 Remove one pre-fetched key out of the Raw Data FIFO.\r
743\r
744 @param TerminalDevice Terminal driver private structure.\r
745 @param Output The key will be removed.\r
746\r
00bfdbe1 747 @retval TRUE If insert successfully.\r
748 @retval FLASE If Raw Data FIFO buffer is empty before remove operation.\r
e49ef433 749\r
750**/\r
95276127 751BOOLEAN\r
752RawFiFoRemoveOneKey (\r
753 TERMINAL_DEV *TerminalDevice,\r
754 UINT8 *Output\r
755 )\r
95276127 756{\r
757 UINT8 Head;\r
758\r
5c998646 759 Head = TerminalDevice->RawFiFo->Head;\r
95276127 760\r
761 if (IsRawFiFoEmpty (TerminalDevice)) {\r
762 //\r
763 // FIFO is empty\r
764 //\r
765 *Output = 0;\r
766 return FALSE;\r
767 }\r
768\r
5c998646 769 *Output = TerminalDevice->RawFiFo->Data[Head];\r
95276127 770\r
5c998646 771 TerminalDevice->RawFiFo->Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));\r
95276127 772\r
773 return TRUE;\r
774}\r
775\r
e49ef433 776/**\r
777 Clarify whether Raw Data FIFO buffer is empty.\r
778\r
779 @param TerminalDevice Terminal driver private structure\r
780\r
00bfdbe1 781 @retval TRUE If Raw Data FIFO buffer is empty.\r
782 @retval FLASE If Raw Data FIFO buffer is not empty.\r
e49ef433 783\r
784**/\r
95276127 785BOOLEAN\r
786IsRawFiFoEmpty (\r
787 TERMINAL_DEV *TerminalDevice\r
788 )\r
95276127 789{\r
5c998646 790 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {\r
95276127 791 return TRUE;\r
792 } else {\r
793 return FALSE;\r
794 }\r
795}\r
796\r
e49ef433 797/**\r
798 Clarify whether Raw Data FIFO buffer is full.\r
799\r
800 @param TerminalDevice Terminal driver private structure\r
801\r
00bfdbe1 802 @retval TRUE If Raw Data FIFO buffer is full.\r
803 @retval FLASE If Raw Data FIFO buffer is not full.\r
e49ef433 804\r
805**/\r
95276127 806BOOLEAN\r
807IsRawFiFoFull (\r
808 TERMINAL_DEV *TerminalDevice\r
809 )\r
95276127 810{\r
811 UINT8 Tail;\r
812 UINT8 Head;\r
813\r
5c998646 814 Tail = TerminalDevice->RawFiFo->Tail;\r
815 Head = TerminalDevice->RawFiFo->Head;\r
95276127 816\r
817 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {\r
818\r
819 return TRUE;\r
820 }\r
821\r
822 return FALSE;\r
823}\r
824\r
e49ef433 825/**\r
826 Insert one pre-fetched key into the FIFO buffer.\r
827\r
828 @param TerminalDevice Terminal driver private structure.\r
829 @param Key The key will be input.\r
830\r
00bfdbe1 831 @retval TRUE If insert successfully.\r
832 @retval FLASE If FIFO buffer is full before key insertion,\r
e49ef433 833 and the key is lost.\r
834\r
835**/\r
95276127 836BOOLEAN\r
837EfiKeyFiFoInsertOneKey (\r
838 TERMINAL_DEV *TerminalDevice,\r
839 EFI_INPUT_KEY Key\r
840 )\r
95276127 841{\r
842 UINT8 Tail;\r
843\r
5c998646 844 Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
df80a83c 845 ASSERT (Tail < FIFO_MAX_NUMBER + 1);\r
95276127 846\r
847 if (IsEfiKeyFiFoFull (TerminalDevice)) {\r
848 //\r
849 // Efi Key FIFO is full\r
850 //\r
851 return FALSE;\r
852 }\r
853\r
5c998646 854 TerminalDevice->EfiKeyFiFo->Data[Tail] = Key;\r
95276127 855\r
5c998646 856 TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 857\r
858 return TRUE;\r
859}\r
860\r
e49ef433 861/**\r
862 Remove one pre-fetched key out of the FIFO buffer.\r
863\r
864 @param TerminalDevice Terminal driver private structure.\r
865 @param Output The key will be removed.\r
866\r
00bfdbe1 867 @retval TRUE If insert successfully.\r
868 @retval FLASE If FIFO buffer is empty before remove operation.\r
e49ef433 869\r
870**/\r
95276127 871BOOLEAN\r
872EfiKeyFiFoRemoveOneKey (\r
873 TERMINAL_DEV *TerminalDevice,\r
874 EFI_INPUT_KEY *Output\r
875 )\r
95276127 876{\r
877 UINT8 Head;\r
878\r
5c998646 879 Head = TerminalDevice->EfiKeyFiFo->Head;\r
df80a83c 880 ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
95276127 881\r
882 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {\r
883 //\r
884 // FIFO is empty\r
885 //\r
886 Output->ScanCode = SCAN_NULL;\r
887 Output->UnicodeChar = 0;\r
888 return FALSE;\r
889 }\r
890\r
5c998646 891 *Output = TerminalDevice->EfiKeyFiFo->Data[Head];\r
95276127 892\r
5c998646 893 TerminalDevice->EfiKeyFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 894\r
895 return TRUE;\r
896}\r
897\r
e49ef433 898/**\r
899 Clarify whether FIFO buffer is empty.\r
900\r
901 @param TerminalDevice Terminal driver private structure\r
902\r
00bfdbe1 903 @retval TRUE If FIFO buffer is empty.\r
904 @retval FLASE If FIFO buffer is not empty.\r
e49ef433 905\r
906**/\r
95276127 907BOOLEAN\r
908IsEfiKeyFiFoEmpty (\r
909 TERMINAL_DEV *TerminalDevice\r
910 )\r
95276127 911{\r
5c998646 912 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {\r
95276127 913 return TRUE;\r
914 } else {\r
915 return FALSE;\r
916 }\r
917}\r
918\r
e49ef433 919/**\r
920 Clarify whether FIFO buffer is full.\r
921\r
922 @param TerminalDevice Terminal driver private structure\r
923\r
00bfdbe1 924 @retval TRUE If FIFO buffer is full.\r
925 @retval FLASE If FIFO buffer is not full.\r
e49ef433 926\r
927**/\r
95276127 928BOOLEAN\r
929IsEfiKeyFiFoFull (\r
930 TERMINAL_DEV *TerminalDevice\r
931 )\r
95276127 932{\r
933 UINT8 Tail;\r
934 UINT8 Head;\r
935\r
5c998646 936 Tail = TerminalDevice->EfiKeyFiFo->Tail;\r
937 Head = TerminalDevice->EfiKeyFiFo->Head;\r
95276127 938\r
939 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
940\r
941 return TRUE;\r
942 }\r
943\r
944 return FALSE;\r
945}\r
946\r
e49ef433 947/**\r
948 Insert one pre-fetched key into the Unicode FIFO buffer.\r
949\r
950 @param TerminalDevice Terminal driver private structure.\r
951 @param Input The key will be input.\r
952\r
00bfdbe1 953 @retval TRUE If insert successfully.\r
954 @retval FLASE If Unicode FIFO buffer is full before key insertion,\r
e49ef433 955 and the key is lost.\r
956\r
957**/\r
95276127 958BOOLEAN\r
959UnicodeFiFoInsertOneKey (\r
960 TERMINAL_DEV *TerminalDevice,\r
961 UINT16 Input\r
962 )\r
95276127 963{\r
964 UINT8 Tail;\r
965\r
5c998646 966 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
df80a83c 967 ASSERT (Tail < FIFO_MAX_NUMBER + 1);\r
968\r
95276127 969\r
970 if (IsUnicodeFiFoFull (TerminalDevice)) {\r
971 //\r
972 // Unicode FIFO is full\r
973 //\r
974 return FALSE;\r
975 }\r
976\r
5c998646 977 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;\r
95276127 978\r
5c998646 979 TerminalDevice->UnicodeFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 980\r
981 return TRUE;\r
982}\r
983\r
e49ef433 984/**\r
985 Remove one pre-fetched key out of the Unicode FIFO buffer.\r
986\r
987 @param TerminalDevice Terminal driver private structure.\r
988 @param Output The key will be removed.\r
989\r
00bfdbe1 990 @retval TRUE If insert successfully.\r
991 @retval FLASE If Unicode FIFO buffer is empty before remove operation.\r
e49ef433 992\r
993**/\r
95276127 994BOOLEAN\r
995UnicodeFiFoRemoveOneKey (\r
996 TERMINAL_DEV *TerminalDevice,\r
997 UINT16 *Output\r
998 )\r
95276127 999{\r
1000 UINT8 Head;\r
1001\r
5c998646 1002 Head = TerminalDevice->UnicodeFiFo->Head;\r
df80a83c 1003 ASSERT (Head < FIFO_MAX_NUMBER + 1);\r
95276127 1004\r
1005 if (IsUnicodeFiFoEmpty (TerminalDevice)) {\r
1006 //\r
1007 // FIFO is empty\r
1008 //\r
1009 Output = NULL;\r
1010 return FALSE;\r
1011 }\r
1012\r
5c998646 1013 *Output = TerminalDevice->UnicodeFiFo->Data[Head];\r
95276127 1014\r
5c998646 1015 TerminalDevice->UnicodeFiFo->Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1));\r
95276127 1016\r
1017 return TRUE;\r
1018}\r
1019\r
e49ef433 1020/**\r
1021 Clarify whether Unicode FIFO buffer is empty.\r
1022\r
1023 @param TerminalDevice Terminal driver private structure\r
1024\r
00bfdbe1 1025 @retval TRUE If Unicode FIFO buffer is empty.\r
1026 @retval FLASE If Unicode FIFO buffer is not empty.\r
e49ef433 1027\r
1028**/\r
95276127 1029BOOLEAN\r
1030IsUnicodeFiFoEmpty (\r
1031 TERMINAL_DEV *TerminalDevice\r
1032 )\r
95276127 1033{\r
5c998646 1034 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {\r
95276127 1035 return TRUE;\r
1036 } else {\r
1037 return FALSE;\r
1038 }\r
1039}\r
1040\r
e49ef433 1041/**\r
1042 Clarify whether Unicode FIFO buffer is full.\r
1043\r
1044 @param TerminalDevice Terminal driver private structure\r
1045\r
00bfdbe1 1046 @retval TRUE If Unicode FIFO buffer is full.\r
1047 @retval FLASE If Unicode FIFO buffer is not full.\r
e49ef433 1048\r
1049**/\r
95276127 1050BOOLEAN\r
1051IsUnicodeFiFoFull (\r
1052 TERMINAL_DEV *TerminalDevice\r
1053 )\r
95276127 1054{\r
1055 UINT8 Tail;\r
1056 UINT8 Head;\r
1057\r
5c998646 1058 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1059 Head = TerminalDevice->UnicodeFiFo->Head;\r
95276127 1060\r
1061 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {\r
1062\r
1063 return TRUE;\r
1064 }\r
1065\r
1066 return FALSE;\r
1067}\r
1068\r
8fd98315 1069/**\r
1070 Count Unicode FIFO buffer.\r
1071\r
1072 @param TerminalDevice Terminal driver private structure\r
1073\r
1074 @return The count in bytes of Unicode FIFO.\r
1075\r
1076**/\r
95276127 1077UINT8\r
1078UnicodeFiFoGetKeyCount (\r
1079 TERMINAL_DEV *TerminalDevice\r
1080 )\r
1081{\r
1082 UINT8 Tail;\r
1083 UINT8 Head;\r
1084\r
5c998646 1085 Tail = TerminalDevice->UnicodeFiFo->Tail;\r
1086 Head = TerminalDevice->UnicodeFiFo->Head;\r
95276127 1087\r
1088 if (Tail >= Head) {\r
1089 return (UINT8) (Tail - Head);\r
1090 } else {\r
1091 return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head);\r
1092 }\r
1093}\r
1094\r
8fd98315 1095/**\r
1096 Update the Unicode characters from a terminal input device into EFI Keys FIFO.\r
5c998646 1097\r
8fd98315 1098 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1099\r
8fd98315 1100**/\r
95276127 1101VOID\r
1102UnicodeToEfiKeyFlushState (\r
1103 IN TERMINAL_DEV *TerminalDevice\r
1104 )\r
1105{\r
1106 EFI_INPUT_KEY Key;\r
11baadb6 1107 UINT32 InputState;\r
5c998646 1108\r
11baadb6 1109 InputState = TerminalDevice->InputState;\r
5c998646 1110\r
11baadb6 1111 if ((InputState & INPUT_STATE_ESC) != 0) {\r
95276127 1112 Key.ScanCode = SCAN_ESC;\r
1113 Key.UnicodeChar = 0;\r
1114 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1115 }\r
1116\r
11baadb6 1117 if ((InputState & INPUT_STATE_CSI) != 0) {\r
95276127 1118 Key.ScanCode = SCAN_NULL;\r
1119 Key.UnicodeChar = CSI;\r
1120 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1121 }\r
1122\r
11baadb6 1123 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {\r
95276127 1124 Key.ScanCode = SCAN_NULL;\r
1125 Key.UnicodeChar = LEFTOPENBRACKET;\r
1126 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1127 }\r
1128\r
11baadb6 1129 if ((InputState & INPUT_STATE_O) != 0) {\r
95276127 1130 Key.ScanCode = SCAN_NULL;\r
1131 Key.UnicodeChar = 'O';\r
1132 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1133 }\r
1134\r
11baadb6 1135 if ((InputState & INPUT_STATE_2) != 0) {\r
95276127 1136 Key.ScanCode = SCAN_NULL;\r
1137 Key.UnicodeChar = '2';\r
1138 EfiKeyFiFoInsertOneKey (TerminalDevice, Key);\r
1139 }\r
1140\r
ab76200c 1141 //\r
1142 // Cancel the timer.\r
1143 //\r
95276127 1144 gBS->SetTimer (\r
1145 TerminalDevice->TwoSecondTimeOut,\r
1146 TimerCancel,\r
1147 0\r
1148 );\r
1149\r
1150 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1151}\r
1152\r
e49ef433 1153\r
1154/**\r
1155 Converts a stream of Unicode characters from a terminal input device into EFI Keys that\r
5c998646 1156 can be read through the Simple Input Protocol.\r
1157\r
8fd98315 1158 The table below shows the keyboard input mappings that this function supports.\r
1159 If the ESC sequence listed in one of the columns is presented, then it is translated\r
11baadb6 1160 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw\r
8fd98315 1161 key strokes are converted into EFI Keys.\r
1162\r
e49ef433 1163 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not\r
1164 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are\r
1165 converted into EFI Keys.\r
1166 There is one special input sequence that will force the system to reset.\r
1167 This is ESC R ESC r ESC R.\r
1168\r
1169 Symbols used in table below\r
1170 ===========================\r
1171 ESC = 0x1B\r
1172 CSI = 0x9B\r
1173 DEL = 0x7f\r
1174 ^ = CTRL\r
8fd98315 1175\r
e49ef433 1176 +=========+======+===========+==========+==========+\r
1177 | | EFI | UEFI 2.0 | | |\r
1178 | | Scan | | VT100+ | |\r
1179 | KEY | Code | PC ANSI | VTUTF8 | VT100 |\r
1180 +=========+======+===========+==========+==========+\r
1181 | NULL | 0x00 | | | |\r
1182 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |\r
1183 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |\r
1184 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |\r
1185 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |\r
1186 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |\r
1187 | END | 0x06 | ESC [ F | ESC k | ESC [ K |\r
1188 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |\r
1189 | | | ESC [ L | | ESC [ L |\r
1190 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |\r
1191 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |\r
1192 | | | | | ESC [ ? |\r
1193 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |\r
1194 | | | | | ESC [ / |\r
1195 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |\r
1196 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |\r
1197 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |\r
1198 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |\r
1199 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |\r
1200 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |\r
1201 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |\r
1202 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |\r
1203 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |\r
1204 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |\r
1205 | Escape | 0x17 | ESC | ESC | ESC |\r
1206 | F11 | 0x15 | | ESC ! | |\r
1207 | F12 | 0x16 | | ESC @ | |\r
1208 +=========+======+===========+==========+==========+\r
8fd98315 1209\r
e49ef433 1210 Special Mappings\r
1211 ================\r
1212 ESC R ESC r ESC R = Reset System\r
1213\r
e49ef433 1214 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys\r
1215\r
e49ef433 1216**/\r
95276127 1217VOID\r
1218UnicodeToEfiKey (\r
1219 IN TERMINAL_DEV *TerminalDevice\r
1220 )\r
95276127 1221{\r
1222 EFI_STATUS Status;\r
1223 EFI_STATUS TimerStatus;\r
1224 UINT16 UnicodeChar;\r
1225 EFI_INPUT_KEY Key;\r
1226 BOOLEAN SetDefaultResetState;\r
fb0b259e 1227\r
95276127 1228 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1229\r
1230 if (!EFI_ERROR (TimerStatus)) {\r
1231 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1232 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1233 }\r
1234\r
1235 while (!IsUnicodeFiFoEmpty(TerminalDevice)) {\r
fb0b259e 1236\r
95276127 1237 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1238 //\r
05b1c414 1239 // Check to see if the 2 seconds timer has expired\r
95276127 1240 //\r
1241 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);\r
1242 if (!EFI_ERROR (TimerStatus)) {\r
1243 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1244 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1245 }\r
1246 }\r
1247\r
1248 //\r
1249 // Fetch one Unicode character from the Unicode FIFO\r
1250 //\r
8fd98315 1251 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);\r
95276127 1252\r
1253 SetDefaultResetState = TRUE;\r
1254\r
1255 switch (TerminalDevice->InputState) {\r
1256 case INPUT_STATE_DEFAULT:\r
1257\r
1258 break;\r
1259\r
1260 case INPUT_STATE_ESC:\r
1261\r
1262 if (UnicodeChar == LEFTOPENBRACKET) {\r
1263 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;\r
1264 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1265 continue;\r
1266 }\r
1267\r
e49ef433 1268 if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100TYPE) {\r
95276127 1269 TerminalDevice->InputState |= INPUT_STATE_O;\r
1270 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1271 continue;\r
1272 }\r
1273\r
1274 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1275\r
e49ef433 1276 if (TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1277 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
95276127 1278 switch (UnicodeChar) {\r
fb0b259e 1279 case '1':\r
1280 Key.ScanCode = SCAN_F1;\r
95276127 1281 break;\r
fb0b259e 1282 case '2':\r
1283 Key.ScanCode = SCAN_F2;\r
95276127 1284 break;\r
fb0b259e 1285 case '3':\r
1286 Key.ScanCode = SCAN_F3;\r
95276127 1287 break;\r
fb0b259e 1288 case '4':\r
1289 Key.ScanCode = SCAN_F4;\r
95276127 1290 break;\r
fb0b259e 1291 case '5':\r
1292 Key.ScanCode = SCAN_F5;\r
95276127 1293 break;\r
fb0b259e 1294 case '6':\r
1295 Key.ScanCode = SCAN_F6;\r
95276127 1296 break;\r
fb0b259e 1297 case '7':\r
1298 Key.ScanCode = SCAN_F7;\r
95276127 1299 break;\r
fb0b259e 1300 case '8':\r
1301 Key.ScanCode = SCAN_F8;\r
95276127 1302 break;\r
fb0b259e 1303 case '9':\r
1304 Key.ScanCode = SCAN_F9;\r
95276127 1305 break;\r
fb0b259e 1306 case '0':\r
1307 Key.ScanCode = SCAN_F10;\r
95276127 1308 break;\r
66aa04e4 1309 case '!':\r
1310 Key.ScanCode = SCAN_F11;\r
1311 break;\r
1312 case '@':\r
1313 Key.ScanCode = SCAN_F12;\r
95276127 1314 break;\r
fb0b259e 1315 case 'h':\r
1316 Key.ScanCode = SCAN_HOME;\r
95276127 1317 break;\r
fb0b259e 1318 case 'k':\r
1319 Key.ScanCode = SCAN_END;\r
95276127 1320 break;\r
fb0b259e 1321 case '+':\r
1322 Key.ScanCode = SCAN_INSERT;\r
95276127 1323 break;\r
fb0b259e 1324 case '-':\r
1325 Key.ScanCode = SCAN_DELETE;\r
95276127 1326 break;\r
fb0b259e 1327 case '/':\r
1328 Key.ScanCode = SCAN_PAGE_DOWN;\r
1329 break;\r
1330 case '?':\r
1331 Key.ScanCode = SCAN_PAGE_UP;\r
1332 break;\r
1333 default :\r
95276127 1334 break;\r
1335 }\r
1336 }\r
fb0b259e 1337\r
95276127 1338 switch (UnicodeChar) {\r
fb0b259e 1339 case 'R':\r
95276127 1340 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {\r
1341 TerminalDevice->ResetState = RESET_STATE_ESC_R;\r
1342 SetDefaultResetState = FALSE;\r
1343 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) {\r
1344 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);\r
1345 }\r
1346 Key.ScanCode = SCAN_NULL;\r
1347 break;\r
fb0b259e 1348 case 'r':\r
95276127 1349 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {\r
1350 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r;\r
1351 SetDefaultResetState = FALSE;\r
1352 }\r
1353 Key.ScanCode = SCAN_NULL;\r
1354 break;\r
fb0b259e 1355 default :\r
95276127 1356 break;\r
1357 }\r
1358\r
1359 if (SetDefaultResetState) {\r
1360 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1361 }\r
1362\r
1363 if (Key.ScanCode != SCAN_NULL) {\r
1364 Key.UnicodeChar = 0;\r
1365 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1366 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1367 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1368 continue;\r
1369 }\r
1370\r
1371 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1372\r
1373 break;\r
1374\r
1375 case INPUT_STATE_ESC | INPUT_STATE_O:\r
1376\r
1377 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1378\r
1379 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1380\r
e49ef433 1381 if (TerminalDevice->TerminalType == VT100TYPE) {\r
95276127 1382 switch (UnicodeChar) {\r
fb0b259e 1383 case 'P':\r
1384 Key.ScanCode = SCAN_F1;\r
95276127 1385 break;\r
fb0b259e 1386 case 'Q':\r
1387 Key.ScanCode = SCAN_F2;\r
95276127 1388 break;\r
fb0b259e 1389 case 'w':\r
1390 Key.ScanCode = SCAN_F3;\r
95276127 1391 break;\r
fb0b259e 1392 case 'x':\r
1393 Key.ScanCode = SCAN_F4;\r
95276127 1394 break;\r
fb0b259e 1395 case 't':\r
1396 Key.ScanCode = SCAN_F5;\r
95276127 1397 break;\r
fb0b259e 1398 case 'u':\r
1399 Key.ScanCode = SCAN_F6;\r
95276127 1400 break;\r
fb0b259e 1401 case 'q':\r
1402 Key.ScanCode = SCAN_F7;\r
95276127 1403 break;\r
fb0b259e 1404 case 'r':\r
1405 Key.ScanCode = SCAN_F8;\r
95276127 1406 break;\r
fb0b259e 1407 case 'p':\r
1408 Key.ScanCode = SCAN_F9;\r
95276127 1409 break;\r
fb0b259e 1410 case 'M':\r
1411 Key.ScanCode = SCAN_F10;\r
95276127 1412 break;\r
fb0b259e 1413 default :\r
95276127 1414 break;\r
1415 }\r
1416 }\r
1417\r
1418 if (Key.ScanCode != SCAN_NULL) {\r
1419 Key.UnicodeChar = 0;\r
1420 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1421 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1422 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1423 continue;\r
1424 }\r
1425\r
1426 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1427\r
1428 break;\r
1429\r
1430 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:\r
fb0b259e 1431\r
95276127 1432 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
fb0b259e 1433\r
95276127 1434 Key.ScanCode = SCAN_NULL;\r
fb0b259e 1435\r
e49ef433 1436 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1437 TerminalDevice->TerminalType == VT100TYPE ||\r
1438 TerminalDevice->TerminalType == VT100PLUSTYPE ||\r
1439 TerminalDevice->TerminalType == VTUTF8TYPE) {\r
95276127 1440 switch (UnicodeChar) {\r
fb0b259e 1441 case 'A':\r
1442 Key.ScanCode = SCAN_UP;\r
95276127 1443 break;\r
fb0b259e 1444 case 'B':\r
1445 Key.ScanCode = SCAN_DOWN;\r
95276127 1446 break;\r
fb0b259e 1447 case 'C':\r
1448 Key.ScanCode = SCAN_RIGHT;\r
95276127 1449 break;\r
fb0b259e 1450 case 'D':\r
1451 Key.ScanCode = SCAN_LEFT;\r
95276127 1452 break;\r
fb0b259e 1453 case 'H':\r
e49ef433 1454 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1455 TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1456 Key.ScanCode = SCAN_HOME;\r
95276127 1457 }\r
1458 break;\r
fb0b259e 1459 case 'F':\r
e49ef433 1460 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1461 Key.ScanCode = SCAN_END;\r
1462 }\r
1463 break;\r
fb0b259e 1464 case 'K':\r
e49ef433 1465 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1466 Key.ScanCode = SCAN_END;\r
95276127 1467 }\r
1468 break;\r
fb0b259e 1469 case 'L':\r
1470 case '@':\r
e49ef433 1471 if (TerminalDevice->TerminalType == PCANSITYPE ||\r
1472 TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1473 Key.ScanCode = SCAN_INSERT;\r
95276127 1474 }\r
1475 break;\r
fb0b259e 1476 case 'X':\r
e49ef433 1477 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1478 Key.ScanCode = SCAN_DELETE;\r
1479 }\r
1480 break;\r
fb0b259e 1481 case 'P':\r
e49ef433 1482 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1483 Key.ScanCode = SCAN_DELETE;\r
e49ef433 1484 } else if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1485 Key.ScanCode = SCAN_F4;\r
1486 }\r
1487 break;\r
fb0b259e 1488 case 'I':\r
e49ef433 1489 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1490 Key.ScanCode = SCAN_PAGE_UP;\r
1491 }\r
fb0b259e 1492 break;\r
1493 case 'V':\r
e49ef433 1494 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1495 Key.ScanCode = SCAN_F10;\r
fb0b259e 1496 }\r
1497 case '?':\r
e49ef433 1498 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1499 Key.ScanCode = SCAN_PAGE_UP;\r
95276127 1500 }\r
1501 break;\r
fb0b259e 1502 case 'G':\r
e49ef433 1503 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1504 Key.ScanCode = SCAN_PAGE_DOWN;\r
1505 }\r
fb0b259e 1506 break;\r
1507 case 'U':\r
e49ef433 1508 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1509 Key.ScanCode = SCAN_F9;\r
1510 }\r
fb0b259e 1511 case '/':\r
e49ef433 1512 if (TerminalDevice->TerminalType == VT100TYPE) {\r
fb0b259e 1513 Key.ScanCode = SCAN_PAGE_DOWN;\r
95276127 1514 }\r
1515 break;\r
fb0b259e 1516 case 'M':\r
e49ef433 1517 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1518 Key.ScanCode = SCAN_F1;\r
1519 }\r
fb0b259e 1520 break;\r
1521 case 'N':\r
e49ef433 1522 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1523 Key.ScanCode = SCAN_F2;\r
1524 }\r
fb0b259e 1525 break;\r
1526 case 'O':\r
e49ef433 1527 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1528 Key.ScanCode = SCAN_F3;\r
1529 }\r
fb0b259e 1530 break;\r
1531 case 'Q':\r
e49ef433 1532 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1533 Key.ScanCode = SCAN_F5;\r
1534 }\r
fb0b259e 1535 break;\r
1536 case 'R':\r
e49ef433 1537 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1538 Key.ScanCode = SCAN_F6;\r
1539 }\r
fb0b259e 1540 break;\r
1541 case 'S':\r
e49ef433 1542 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1543 Key.ScanCode = SCAN_F7;\r
1544 }\r
fb0b259e 1545 break;\r
1546 case 'T':\r
e49ef433 1547 if (TerminalDevice->TerminalType == PCANSITYPE) {\r
95276127 1548 Key.ScanCode = SCAN_F8;\r
1549 }\r
fb0b259e 1550 break;\r
1551 default :\r
95276127 1552 break;\r
1553 }\r
1554 }\r
1555\r
1556 if (Key.ScanCode != SCAN_NULL) {\r
1557 Key.UnicodeChar = 0;\r
1558 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1559 TerminalDevice->InputState = INPUT_STATE_DEFAULT;\r
1560 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1561 continue;\r
1562 }\r
1563\r
1564 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1565\r
1566 break;\r
1567\r
fb0b259e 1568\r
95276127 1569 default:\r
1570 //\r
1571 // Invalid state. This should never happen.\r
1572 //\r
1573 ASSERT (FALSE);\r
1574\r
1575 UnicodeToEfiKeyFlushState (TerminalDevice);\r
1576\r
1577 break;\r
1578 }\r
1579\r
1580 if (UnicodeChar == ESC) {\r
1581 TerminalDevice->InputState = INPUT_STATE_ESC;\r
1582 }\r
66aa04e4 1583\r
1584 if (UnicodeChar == CSI) {\r
1585 TerminalDevice->InputState = INPUT_STATE_CSI;\r
1586 }\r
fb0b259e 1587\r
95276127 1588 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {\r
1589 Status = gBS->SetTimer(\r
1590 TerminalDevice->TwoSecondTimeOut,\r
1591 TimerRelative,\r
1592 (UINT64)20000000\r
1593 );\r
1594 ASSERT_EFI_ERROR (Status);\r
1595 continue;\r
1596 }\r
1597\r
1598 if (SetDefaultResetState) {\r
1599 TerminalDevice->ResetState = RESET_STATE_DEFAULT;\r
1600 }\r
1601\r
1602 if (UnicodeChar == DEL) {\r
1603 Key.ScanCode = SCAN_DELETE;\r
1604 Key.UnicodeChar = 0;\r
1605 } else {\r
1606 Key.ScanCode = SCAN_NULL;\r
1607 Key.UnicodeChar = UnicodeChar;\r
1608 }\r
1609\r
1610 EfiKeyFiFoInsertOneKey (TerminalDevice,Key);\r
1611 }\r
1612}\r