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