TianoCore EDK2 master
Loading...
Searching...
No Matches
TerminalConIn.c
Go to the documentation of this file.
1
11#include "Terminal.h"
12
29 IN TERMINAL_DEV *TerminalDevice,
30 OUT EFI_KEY_DATA *KeyData
31 )
32{
33 if (KeyData == NULL) {
34 return EFI_INVALID_PARAMETER;
35 }
36
37 KeyData->KeyState.KeyShiftState = 0;
38 KeyData->KeyState.KeyToggleState = 0;
39
40 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
41 return EFI_NOT_READY;
42 }
43
44 return EFI_SUCCESS;
45}
46
60EFIAPI
63 IN BOOLEAN ExtendedVerification
64 )
65{
66 EFI_STATUS Status;
67 TERMINAL_DEV *TerminalDevice;
68
69 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
70
71 //
72 // Report progress code here
73 //
76 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
77 TerminalDevice->DevicePath
78 );
79
80 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
81
82 //
83 // Make all the internal buffer empty for keys
84 //
85 TerminalDevice->RawFiFo->Head = TerminalDevice->RawFiFo->Tail;
86 TerminalDevice->UnicodeFiFo->Head = TerminalDevice->UnicodeFiFo->Tail;
87 TerminalDevice->EfiKeyFiFo->Head = TerminalDevice->EfiKeyFiFo->Tail;
88 TerminalDevice->EfiKeyFiFoForNotify->Head = TerminalDevice->EfiKeyFiFoForNotify->Tail;
89
90 if (EFI_ERROR (Status)) {
92 EFI_ERROR_CODE | EFI_ERROR_MINOR,
93 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
94 TerminalDevice->DevicePath
95 );
96 }
97
98 if (!EFI_ERROR (Status)) {
99 Status = TerminalDevice->SerialIo->SetControl (TerminalDevice->SerialIo, EFI_SERIAL_DATA_TERMINAL_READY|EFI_SERIAL_REQUEST_TO_SEND);
100 if (Status == EFI_UNSUPPORTED) {
101 Status = EFI_SUCCESS;
102 }
103 }
104
105 return Status;
106}
107
124EFIAPI
127 OUT EFI_INPUT_KEY *Key
128 )
129{
130 TERMINAL_DEV *TerminalDevice;
131 EFI_STATUS Status;
132 EFI_KEY_DATA KeyData;
133
134 //
135 // get TERMINAL_DEV from "This" parameter.
136 //
137 TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
138
139 Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);
140 if (EFI_ERROR (Status)) {
141 return Status;
142 }
143
144 CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
145
146 return EFI_SUCCESS;
147}
148
165BOOLEAN
167 IN EFI_KEY_DATA *RegsiteredData,
168 IN EFI_KEY_DATA *InputData
169 )
170{
171 ASSERT (RegsiteredData != NULL && InputData != NULL);
172
173 if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||
174 (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar))
175 {
176 return FALSE;
177 }
178
179 return TRUE;
180}
181
190VOID
191EFIAPI
193 IN EFI_EVENT Event,
194 IN VOID *Context
195 )
196{
197 TerminalConInWaitForKey (Event, Context);
198}
199
200//
201// Simple Text Input Ex protocol functions
202//
203
216EFIAPI
219 IN BOOLEAN ExtendedVerification
220 )
221{
222 EFI_STATUS Status;
223 TERMINAL_DEV *TerminalDevice;
224
225 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
226
227 Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);
228 if (EFI_ERROR (Status)) {
229 return EFI_DEVICE_ERROR;
230 }
231
232 return EFI_SUCCESS;
233}
234
254EFIAPI
257 OUT EFI_KEY_DATA *KeyData
258 )
259{
260 TERMINAL_DEV *TerminalDevice;
261
262 if (KeyData == NULL) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
267
268 return ReadKeyStrokeWorker (TerminalDevice, KeyData);
269}
270
287EFIAPI
290 IN EFI_KEY_TOGGLE_STATE *KeyToggleState
291 )
292{
293 if (KeyToggleState == NULL) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
298 return EFI_UNSUPPORTED;
299 }
300
301 return EFI_SUCCESS;
302}
303
327EFIAPI
330 IN EFI_KEY_DATA *KeyData,
331 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
332 OUT VOID **NotifyHandle
333 )
334{
335 TERMINAL_DEV *TerminalDevice;
337 LIST_ENTRY *Link;
338 LIST_ENTRY *NotifyList;
339 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
340
341 if ((KeyData == NULL) || (NotifyHandle == NULL) || (KeyNotificationFunction == NULL)) {
342 return EFI_INVALID_PARAMETER;
343 }
344
345 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
346
347 //
348 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
349 //
350 NotifyList = &TerminalDevice->NotifyList;
351 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
352 CurrentNotify = CR (
353 Link,
355 NotifyEntry,
356 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
357 );
358 if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
359 if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
360 *NotifyHandle = CurrentNotify;
361 return EFI_SUCCESS;
362 }
363 }
364 }
365
366 //
367 // Allocate resource to save the notification function
368 //
370 if (NewNotify == NULL) {
371 return EFI_OUT_OF_RESOURCES;
372 }
373
374 NewNotify->Signature = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
375 NewNotify->KeyNotificationFn = KeyNotificationFunction;
376 CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
377 InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);
378
379 *NotifyHandle = NewNotify;
380
381 return EFI_SUCCESS;
382}
383
397EFIAPI
400 IN VOID *NotificationHandle
401 )
402{
403 TERMINAL_DEV *TerminalDevice;
404 LIST_ENTRY *Link;
405 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
406 LIST_ENTRY *NotifyList;
407
408 if (NotificationHandle == NULL) {
409 return EFI_INVALID_PARAMETER;
410 }
411
412 TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
413
414 NotifyList = &TerminalDevice->NotifyList;
415 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
416 CurrentNotify = CR (
417 Link,
419 NotifyEntry,
420 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
421 );
422 if (CurrentNotify == NotificationHandle) {
423 //
424 // Remove the notification function from NotifyList and free resources
425 //
426 RemoveEntryList (&CurrentNotify->NotifyEntry);
427
428 gBS->FreePool (CurrentNotify);
429 return EFI_SUCCESS;
430 }
431 }
432
433 //
434 // Can not find the matching entry in database.
435 //
436 return EFI_INVALID_PARAMETER;
437}
438
446VOID
448 IN TERMINAL_DEV *TerminalDevice
449 )
450{
451 switch (TerminalDevice->TerminalType) {
452 case TerminalTypePcAnsi:
453 case TerminalTypeVt100:
454 case TerminalTypeVt100Plus:
455 case TerminalTypeTtyTerm:
456 case TerminalTypeLinux:
457 case TerminalTypeXtermR6:
458 case TerminalTypeVt400:
459 case TerminalTypeSCO:
460 AnsiRawDataToUnicode (TerminalDevice);
461 UnicodeToEfiKey (TerminalDevice);
462 break;
463
464 case TerminalTypeVtUtf8:
465 //
466 // Process all the raw data in the RawFIFO,
467 // put the processed key into UnicodeFIFO.
468 //
469 VTUTF8RawDataToUnicode (TerminalDevice);
470
471 //
472 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
473 // then put into EfiKeyFIFO.
474 //
475 UnicodeToEfiKey (TerminalDevice);
476
477 break;
478 }
479}
480
489VOID
490EFIAPI
492 IN EFI_EVENT Event,
493 IN VOID *Context
494 )
495{
496 //
497 // Someone is waiting on the keystroke event, if there's
498 // a key pending, signal the event
499 //
500 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *)Context)) {
501 gBS->SignalEvent (Event);
502 }
503}
504
511VOID
512EFIAPI
514 IN EFI_EVENT Event,
515 IN VOID *Context
516 )
517{
518 EFI_STATUS Status;
519 TERMINAL_DEV *TerminalDevice;
520 UINT32 Control;
521 UINT8 Input;
522 EFI_SERIAL_IO_MODE *Mode;
523 EFI_SERIAL_IO_PROTOCOL *SerialIo;
524 UINTN SerialInTimeOut;
525
526 TerminalDevice = (TERMINAL_DEV *)Context;
527
528 SerialIo = TerminalDevice->SerialIo;
529 if (SerialIo == NULL) {
530 return;
531 }
532
533 //
534 // if current timeout value for serial device is not identical with
535 // the value saved in TERMINAL_DEV structure, then recalculate the
536 // timeout value again and set serial attribute according to this value.
537 //
538 Mode = SerialIo->Mode;
539 if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
540 SerialInTimeOut = 0;
541 if (Mode->BaudRate != 0) {
542 //
543 // According to BAUD rate to calculate the timeout value.
544 //
545 SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN)Mode->BaudRate;
546 }
547
548 Status = SerialIo->SetAttributes (
549 SerialIo,
550 Mode->BaudRate,
551 Mode->ReceiveFifoDepth,
552 (UINT32)SerialInTimeOut,
553 (EFI_PARITY_TYPE)(Mode->Parity),
554 (UINT8)Mode->DataBits,
555 (EFI_STOP_BITS_TYPE)(Mode->StopBits)
556 );
557
558 if (EFI_ERROR (Status)) {
559 TerminalDevice->SerialInTimeOut = 0;
560 } else {
561 TerminalDevice->SerialInTimeOut = SerialInTimeOut;
562 }
563 }
564
565 //
566 // Check whether serial buffer is empty.
567 // Skip the key transfer loop only if the SerialIo protocol instance
568 // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
569 //
570 Status = SerialIo->GetControl (SerialIo, &Control);
571 if (EFI_ERROR (Status) || ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0)) {
572 //
573 // Fetch all the keys in the serial buffer,
574 // and insert the byte stream into RawFIFO.
575 //
576 while (!IsRawFiFoFull (TerminalDevice)) {
577 Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
578
579 if (EFI_ERROR (Status)) {
580 if (Status == EFI_DEVICE_ERROR) {
582 EFI_ERROR_CODE | EFI_ERROR_MINOR,
583 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),
584 TerminalDevice->DevicePath
585 );
586 }
587
588 break;
589 }
590
591 RawFiFoInsertOneKey (TerminalDevice, Input);
592 }
593 }
594
595 //
596 // Translate all the raw data in RawFIFO into EFI Key,
597 // according to different terminal type supported.
598 //
599 TranslateRawDataToEfiKey (TerminalDevice);
600}
601
608VOID
609EFIAPI
611 IN EFI_EVENT Event,
612 IN VOID *Context
613 )
614{
615 BOOLEAN HasKey;
616 TERMINAL_DEV *TerminalDevice;
617 EFI_INPUT_KEY Key;
618 EFI_KEY_DATA KeyData;
619 LIST_ENTRY *Link;
620 LIST_ENTRY *NotifyList;
621 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
622 EFI_TPL OldTpl;
623
624 TerminalDevice = (TERMINAL_DEV *)Context;
625
626 //
627 // Invoke notification functions.
628 //
629 NotifyList = &TerminalDevice->NotifyList;
630 while (TRUE) {
631 //
632 // Enter critical section
633 //
634 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
635 HasKey = EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice->EfiKeyFiFoForNotify, &Key);
636 CopyMem (&KeyData.Key, &Key, sizeof (EFI_INPUT_KEY));
637 KeyData.KeyState.KeyShiftState = 0;
638 KeyData.KeyState.KeyToggleState = 0;
639 //
640 // Leave critical section
641 //
642 gBS->RestoreTPL (OldTpl);
643 if (!HasKey) {
644 break;
645 }
646
647 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
648 CurrentNotify = CR (Link, TERMINAL_CONSOLE_IN_EX_NOTIFY, NotifyEntry, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
649 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
650 CurrentNotify->KeyNotificationFn (&KeyData);
651 }
652 }
653 }
654}
655
670 EFI_SERIAL_IO_PROTOCOL *SerialIo,
671 UINT8 *Output
672 )
673{
674 EFI_STATUS Status;
675 UINTN Size;
676
677 Size = 1;
678 *Output = 0;
679
680 //
681 // Read one key from serial I/O device.
682 //
683 Status = SerialIo->Read (SerialIo, &Size, Output);
684
685 if (EFI_ERROR (Status)) {
686 if (Status == EFI_TIMEOUT) {
687 return EFI_NOT_READY;
688 }
689
690 return EFI_DEVICE_ERROR;
691 }
692
693 if (*Output == 0) {
694 return EFI_NOT_READY;
695 }
696
697 return EFI_SUCCESS;
698}
699
711BOOLEAN
713 TERMINAL_DEV *TerminalDevice,
714 UINT8 Input
715 )
716{
717 UINT8 Tail;
718
719 Tail = TerminalDevice->RawFiFo->Tail;
720
721 if (IsRawFiFoFull (TerminalDevice)) {
722 //
723 // Raw FIFO is full
724 //
725 return FALSE;
726 }
727
728 TerminalDevice->RawFiFo->Data[Tail] = Input;
729
730 TerminalDevice->RawFiFo->Tail = (UINT8)((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
731
732 return TRUE;
733}
734
745BOOLEAN
747 TERMINAL_DEV *TerminalDevice,
748 UINT8 *Output
749 )
750{
751 UINT8 Head;
752
753 Head = TerminalDevice->RawFiFo->Head;
754
755 if (IsRawFiFoEmpty (TerminalDevice)) {
756 //
757 // FIFO is empty
758 //
759 *Output = 0;
760 return FALSE;
761 }
762
763 *Output = TerminalDevice->RawFiFo->Data[Head];
764
765 TerminalDevice->RawFiFo->Head = (UINT8)((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
766
767 return TRUE;
768}
769
779BOOLEAN
781 TERMINAL_DEV *TerminalDevice
782 )
783{
784 if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {
785 return TRUE;
786 } else {
787 return FALSE;
788 }
789}
790
800BOOLEAN
802 TERMINAL_DEV *TerminalDevice
803 )
804{
805 UINT8 Tail;
806 UINT8 Head;
807
808 Tail = TerminalDevice->RawFiFo->Tail;
809 Head = TerminalDevice->RawFiFo->Head;
810
811 if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
812 return TRUE;
813 }
814
815 return FALSE;
816}
817
829BOOLEAN
831 EFI_KEY_FIFO *EfiKeyFiFo,
833 )
834{
835 UINT8 Tail;
836
837 Tail = EfiKeyFiFo->Tail;
838
839 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo)) {
840 //
841 // FIFO is full
842 //
843 return FALSE;
844 }
845
846 CopyMem (&EfiKeyFiFo->Data[Tail], Input, sizeof (EFI_INPUT_KEY));
847
848 EfiKeyFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
849
850 return TRUE;
851}
852
863BOOLEAN
865 EFI_KEY_FIFO *EfiKeyFiFo,
866 EFI_INPUT_KEY *Output
867 )
868{
869 UINT8 Head;
870
871 Head = EfiKeyFiFo->Head;
872 ASSERT (Head < FIFO_MAX_NUMBER + 1);
873
874 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo)) {
875 //
876 // FIFO is empty
877 //
878 Output->ScanCode = SCAN_NULL;
879 Output->UnicodeChar = 0;
880 return FALSE;
881 }
882
883 CopyMem (Output, &EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
884
885 EfiKeyFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
886
887 return TRUE;
888}
889
899BOOLEAN
901 EFI_KEY_FIFO *EfiKeyFiFo
902 )
903{
904 if (EfiKeyFiFo->Head == EfiKeyFiFo->Tail) {
905 return TRUE;
906 } else {
907 return FALSE;
908 }
909}
910
920BOOLEAN
922 EFI_KEY_FIFO *EfiKeyFiFo
923 )
924{
925 UINT8 Tail;
926 UINT8 Head;
927
928 Tail = EfiKeyFiFo->Tail;
929 Head = EfiKeyFiFo->Head;
930
931 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
932 return TRUE;
933 }
934
935 return FALSE;
936}
937
949BOOLEAN
951 TERMINAL_DEV *TerminalDevice,
952 EFI_INPUT_KEY *Key
953 )
954{
955 UINT8 Tail;
956 LIST_ENTRY *Link;
957 LIST_ENTRY *NotifyList;
958 TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
959 EFI_KEY_DATA KeyData;
960
961 Tail = TerminalDevice->EfiKeyFiFo->Tail;
962
963 CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));
964 KeyData.KeyState.KeyShiftState = 0;
965 KeyData.KeyState.KeyToggleState = 0;
966
967 //
968 // Signal KeyNotify process event if this key pressed matches any key registered.
969 //
970 NotifyList = &TerminalDevice->NotifyList;
971 for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
972 CurrentNotify = CR (
973 Link,
975 NotifyEntry,
976 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
977 );
978 if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
979 //
980 // The key notification function needs to run at TPL_CALLBACK
981 // while current TPL is TPL_NOTIFY. It will be invoked in
982 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
983 //
984 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice->EfiKeyFiFoForNotify, Key);
985 gBS->SignalEvent (TerminalDevice->KeyNotifyProcessEvent);
986 break;
987 }
988 }
989
990 if (IsEfiKeyFiFoFull (TerminalDevice)) {
991 //
992 // Efi Key FIFO is full
993 //
994 return FALSE;
995 }
996
997 CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));
998
999 TerminalDevice->EfiKeyFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
1000
1001 return TRUE;
1002}
1003
1014BOOLEAN
1016 TERMINAL_DEV *TerminalDevice,
1017 EFI_INPUT_KEY *Output
1018 )
1019{
1020 UINT8 Head;
1021
1022 Head = TerminalDevice->EfiKeyFiFo->Head;
1023 ASSERT (Head < FIFO_MAX_NUMBER + 1);
1024
1025 if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
1026 //
1027 // FIFO is empty
1028 //
1029 Output->ScanCode = SCAN_NULL;
1030 Output->UnicodeChar = 0;
1031 return FALSE;
1032 }
1033
1034 CopyMem (Output, &TerminalDevice->EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
1035
1036 TerminalDevice->EfiKeyFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
1037
1038 return TRUE;
1039}
1040
1050BOOLEAN
1052 TERMINAL_DEV *TerminalDevice
1053 )
1054{
1055 if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {
1056 return TRUE;
1057 } else {
1058 return FALSE;
1059 }
1060}
1061
1071BOOLEAN
1073 TERMINAL_DEV *TerminalDevice
1074 )
1075{
1076 UINT8 Tail;
1077 UINT8 Head;
1078
1079 Tail = TerminalDevice->EfiKeyFiFo->Tail;
1080 Head = TerminalDevice->EfiKeyFiFo->Head;
1081
1082 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
1083 return TRUE;
1084 }
1085
1086 return FALSE;
1087}
1088
1100BOOLEAN
1102 TERMINAL_DEV *TerminalDevice,
1103 UINT16 Input
1104 )
1105{
1106 UINT8 Tail;
1107
1108 Tail = TerminalDevice->UnicodeFiFo->Tail;
1109 ASSERT (Tail < FIFO_MAX_NUMBER + 1);
1110
1111 if (IsUnicodeFiFoFull (TerminalDevice)) {
1112 //
1113 // Unicode FIFO is full
1114 //
1115 return FALSE;
1116 }
1117
1118 TerminalDevice->UnicodeFiFo->Data[Tail] = Input;
1119
1120 TerminalDevice->UnicodeFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
1121
1122 return TRUE;
1123}
1124
1134VOID
1136 TERMINAL_DEV *TerminalDevice,
1137 UINT16 *Output
1138 )
1139{
1140 UINT8 Head;
1141
1142 Head = TerminalDevice->UnicodeFiFo->Head;
1143 ASSERT (Head < FIFO_MAX_NUMBER + 1);
1144
1145 *Output = TerminalDevice->UnicodeFiFo->Data[Head];
1146
1147 TerminalDevice->UnicodeFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
1148}
1149
1159BOOLEAN
1161 TERMINAL_DEV *TerminalDevice
1162 )
1163{
1164 if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {
1165 return TRUE;
1166 } else {
1167 return FALSE;
1168 }
1169}
1170
1180BOOLEAN
1182 TERMINAL_DEV *TerminalDevice
1183 )
1184{
1185 UINT8 Tail;
1186 UINT8 Head;
1187
1188 Tail = TerminalDevice->UnicodeFiFo->Tail;
1189 Head = TerminalDevice->UnicodeFiFo->Head;
1190
1191 if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
1192 return TRUE;
1193 }
1194
1195 return FALSE;
1196}
1197
1204VOID
1206 IN TERMINAL_DEV *TerminalDevice
1207 )
1208{
1209 EFI_INPUT_KEY Key;
1210 UINT32 InputState;
1211
1212 InputState = TerminalDevice->InputState;
1213
1214 if (IsEfiKeyFiFoFull (TerminalDevice)) {
1215 return;
1216 }
1217
1218 if ((InputState & INPUT_STATE_ESC) != 0) {
1219 Key.ScanCode = SCAN_ESC;
1220 Key.UnicodeChar = 0;
1221 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1222 }
1223
1224 if ((InputState & INPUT_STATE_CSI) != 0) {
1225 Key.ScanCode = SCAN_NULL;
1226 Key.UnicodeChar = CSI;
1227 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1228 }
1229
1230 if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
1231 Key.ScanCode = SCAN_NULL;
1232 Key.UnicodeChar = LEFTOPENBRACKET;
1233 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1234 }
1235
1236 if ((InputState & INPUT_STATE_O) != 0) {
1237 Key.ScanCode = SCAN_NULL;
1238 Key.UnicodeChar = 'O';
1239 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1240 }
1241
1242 if ((InputState & INPUT_STATE_2) != 0) {
1243 Key.ScanCode = SCAN_NULL;
1244 Key.UnicodeChar = '2';
1245 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1246 }
1247
1248 //
1249 // Cancel the timer.
1250 //
1251 gBS->SetTimer (
1252 TerminalDevice->TwoSecondTimeOut,
1254 0
1255 );
1256
1257 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1258}
1259
1348VOID
1350 IN TERMINAL_DEV *TerminalDevice
1351 )
1352{
1353 EFI_STATUS Status;
1354 EFI_STATUS TimerStatus;
1355 UINT16 UnicodeChar;
1356 EFI_INPUT_KEY Key;
1357 BOOLEAN SetDefaultResetState;
1358
1359 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1360
1361 if (!EFI_ERROR (TimerStatus)) {
1362 UnicodeToEfiKeyFlushState (TerminalDevice);
1363 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1364 }
1365
1366 while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) {
1367 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
1368 //
1369 // Check to see if the 2 seconds timer has expired
1370 //
1371 TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
1372 if (!EFI_ERROR (TimerStatus)) {
1373 UnicodeToEfiKeyFlushState (TerminalDevice);
1374 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1375 }
1376 }
1377
1378 //
1379 // Fetch one Unicode character from the Unicode FIFO
1380 //
1381 UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);
1382
1383 SetDefaultResetState = TRUE;
1384
1385 switch (TerminalDevice->InputState) {
1386 case INPUT_STATE_DEFAULT:
1387
1388 break;
1389
1390 case INPUT_STATE_ESC:
1391
1392 if (UnicodeChar == LEFTOPENBRACKET) {
1393 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
1394 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1395 continue;
1396 }
1397
1398 if ((UnicodeChar == 'O') && ((TerminalDevice->TerminalType == TerminalTypeVt100) ||
1399 (TerminalDevice->TerminalType == TerminalTypeTtyTerm) ||
1400 (TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1401 (TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
1402 (TerminalDevice->TerminalType == TerminalTypeVtUtf8)))
1403 {
1404 TerminalDevice->InputState |= INPUT_STATE_O;
1405 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1406 continue;
1407 }
1408
1409 Key.ScanCode = SCAN_NULL;
1410
1411 if ((TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
1412 (TerminalDevice->TerminalType == TerminalTypeVtUtf8))
1413 {
1414 switch (UnicodeChar) {
1415 case '1':
1416 Key.ScanCode = SCAN_F1;
1417 break;
1418 case '2':
1419 Key.ScanCode = SCAN_F2;
1420 break;
1421 case '3':
1422 Key.ScanCode = SCAN_F3;
1423 break;
1424 case '4':
1425 Key.ScanCode = SCAN_F4;
1426 break;
1427 case '5':
1428 Key.ScanCode = SCAN_F5;
1429 break;
1430 case '6':
1431 Key.ScanCode = SCAN_F6;
1432 break;
1433 case '7':
1434 Key.ScanCode = SCAN_F7;
1435 break;
1436 case '8':
1437 Key.ScanCode = SCAN_F8;
1438 break;
1439 case '9':
1440 Key.ScanCode = SCAN_F9;
1441 break;
1442 case '0':
1443 Key.ScanCode = SCAN_F10;
1444 break;
1445 case '!':
1446 Key.ScanCode = SCAN_F11;
1447 break;
1448 case '@':
1449 Key.ScanCode = SCAN_F12;
1450 break;
1451 case 'h':
1452 Key.ScanCode = SCAN_HOME;
1453 break;
1454 case 'k':
1455 Key.ScanCode = SCAN_END;
1456 break;
1457 case '+':
1458 Key.ScanCode = SCAN_INSERT;
1459 break;
1460 case '-':
1461 Key.ScanCode = SCAN_DELETE;
1462 break;
1463 case '/':
1464 Key.ScanCode = SCAN_PAGE_DOWN;
1465 break;
1466 case '?':
1467 Key.ScanCode = SCAN_PAGE_UP;
1468 break;
1469 default:
1470 break;
1471 }
1472 }
1473
1474 switch (UnicodeChar) {
1475 case 'R':
1476 if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
1477 TerminalDevice->ResetState = RESET_STATE_ESC_R;
1478 SetDefaultResetState = FALSE;
1479 } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {
1480 gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
1481 }
1482
1483 Key.ScanCode = SCAN_NULL;
1484 break;
1485 case 'r':
1486 if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
1487 TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;
1488 SetDefaultResetState = FALSE;
1489 }
1490
1491 Key.ScanCode = SCAN_NULL;
1492 break;
1493 default:
1494 break;
1495 }
1496
1497 if (SetDefaultResetState) {
1498 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1499 }
1500
1501 if (Key.ScanCode != SCAN_NULL) {
1502 Key.UnicodeChar = 0;
1503 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1504 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1505 UnicodeToEfiKeyFlushState (TerminalDevice);
1506 continue;
1507 }
1508
1509 UnicodeToEfiKeyFlushState (TerminalDevice);
1510
1511 break;
1512
1513 case INPUT_STATE_ESC | INPUT_STATE_O:
1514
1515 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1516
1517 Key.ScanCode = SCAN_NULL;
1518
1519 if (TerminalDevice->TerminalType == TerminalTypeVt100) {
1520 switch (UnicodeChar) {
1521 case 'P':
1522 Key.ScanCode = SCAN_F1;
1523 break;
1524 case 'Q':
1525 Key.ScanCode = SCAN_F2;
1526 break;
1527 case 'w':
1528 Key.ScanCode = SCAN_F3;
1529 break;
1530 case 'x':
1531 Key.ScanCode = SCAN_F4;
1532 break;
1533 case 't':
1534 Key.ScanCode = SCAN_F5;
1535 break;
1536 case 'u':
1537 Key.ScanCode = SCAN_F6;
1538 break;
1539 case 'q':
1540 Key.ScanCode = SCAN_F7;
1541 break;
1542 case 'r':
1543 Key.ScanCode = SCAN_F8;
1544 break;
1545 case 'p':
1546 Key.ScanCode = SCAN_F9;
1547 break;
1548 case 'M':
1549 Key.ScanCode = SCAN_F10;
1550 break;
1551 default:
1552 break;
1553 }
1554 } else if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
1555 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1556 switch (UnicodeChar) {
1557 case 'P':
1558 Key.ScanCode = SCAN_F1;
1559 break;
1560 case 'Q':
1561 Key.ScanCode = SCAN_F2;
1562 break;
1563 case 'R':
1564 Key.ScanCode = SCAN_F3;
1565 break;
1566 case 'S':
1567 Key.ScanCode = SCAN_F4;
1568 break;
1569 case 'H':
1570 Key.ScanCode = SCAN_HOME;
1571 break;
1572 case 'F':
1573 Key.ScanCode = SCAN_END;
1574 break;
1575 }
1576 } else if ((TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
1577 (TerminalDevice->TerminalType == TerminalTypeVtUtf8))
1578 {
1579 switch (UnicodeChar) {
1580 case 'P':
1581 Key.ScanCode = SCAN_F1;
1582 break;
1583 case 'Q':
1584 Key.ScanCode = SCAN_F2;
1585 break;
1586 case 'R':
1587 Key.ScanCode = SCAN_F3;
1588 break;
1589 case 'S':
1590 Key.ScanCode = SCAN_F4;
1591 break;
1592 case 'T':
1593 Key.ScanCode = SCAN_F5;
1594 break;
1595 case 'U':
1596 Key.ScanCode = SCAN_F6;
1597 break;
1598 case 'V':
1599 Key.ScanCode = SCAN_F7;
1600 break;
1601 case 'W':
1602 Key.ScanCode = SCAN_F8;
1603 break;
1604 case 'X':
1605 Key.ScanCode = SCAN_F9;
1606 break;
1607 case 'Y':
1608 Key.ScanCode = SCAN_F10;
1609 break;
1610 case 'Z':
1611 Key.ScanCode = SCAN_F11;
1612 break;
1613 case '[':
1614 Key.ScanCode = SCAN_F12;
1615 break;
1616 }
1617 } else if (TerminalDevice->TerminalType == TerminalTypeXtermR6) {
1618 switch (UnicodeChar) {
1619 case 'P':
1620 Key.ScanCode = SCAN_F1;
1621 break;
1622 case 'Q':
1623 Key.ScanCode = SCAN_F2;
1624 break;
1625 case 'R':
1626 Key.ScanCode = SCAN_F3;
1627 break;
1628 case 'S':
1629 Key.ScanCode = SCAN_F4;
1630 break;
1631 }
1632 }
1633
1634 if (Key.ScanCode != SCAN_NULL) {
1635 Key.UnicodeChar = 0;
1636 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1637 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1638 UnicodeToEfiKeyFlushState (TerminalDevice);
1639 continue;
1640 }
1641
1642 UnicodeToEfiKeyFlushState (TerminalDevice);
1643
1644 break;
1645
1646 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
1647
1648 if ((UnicodeChar == '1') && ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1649 (TerminalDevice->TerminalType == TerminalTypeVt400) ||
1650 (TerminalDevice->TerminalType == TerminalTypeLinux)))
1651 {
1652 TerminalDevice->InputState |= INPUT_STATE_1;
1653 continue;
1654 }
1655
1656 if ((UnicodeChar == '2') && ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1657 (TerminalDevice->TerminalType == TerminalTypeVt400) ||
1658 (TerminalDevice->TerminalType == TerminalTypeLinux)))
1659 {
1660 TerminalDevice->InputState |= INPUT_STATE_2;
1661 continue;
1662 }
1663
1664 if ((UnicodeChar == LEFTOPENBRACKET) && (TerminalDevice->TerminalType == TerminalTypeLinux)) {
1665 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET_2ND;
1666 continue;
1667 }
1668
1669 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1670
1671 Key.ScanCode = SCAN_NULL;
1672
1673 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1674 (TerminalDevice->TerminalType == TerminalTypeVt100) ||
1675 (TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
1676 (TerminalDevice->TerminalType == TerminalTypeVtUtf8) ||
1677 (TerminalDevice->TerminalType == TerminalTypeTtyTerm) ||
1678 (TerminalDevice->TerminalType == TerminalTypeLinux) ||
1679 (TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1680 (TerminalDevice->TerminalType == TerminalTypeVt400) ||
1681 (TerminalDevice->TerminalType == TerminalTypeSCO))
1682 {
1683 switch (UnicodeChar) {
1684 case 'A':
1685 Key.ScanCode = SCAN_UP;
1686 break;
1687 case 'B':
1688 Key.ScanCode = SCAN_DOWN;
1689 break;
1690 case 'C':
1691 Key.ScanCode = SCAN_RIGHT;
1692 break;
1693 case 'D':
1694 Key.ScanCode = SCAN_LEFT;
1695 break;
1696 case 'H':
1697 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1698 (TerminalDevice->TerminalType == TerminalTypeVt100) ||
1699 (TerminalDevice->TerminalType == TerminalTypeTtyTerm))
1700 {
1701 Key.ScanCode = SCAN_HOME;
1702 }
1703
1704 break;
1705 case 'F':
1706 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1707 (TerminalDevice->TerminalType == TerminalTypeTtyTerm))
1708 {
1709 Key.ScanCode = SCAN_END;
1710 }
1711
1712 break;
1713 case 'K':
1714 if (TerminalDevice->TerminalType == TerminalTypeVt100) {
1715 Key.ScanCode = SCAN_END;
1716 }
1717
1718 break;
1719 case 'L':
1720 case '@':
1721 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1722 (TerminalDevice->TerminalType == TerminalTypeVt100))
1723 {
1724 Key.ScanCode = SCAN_INSERT;
1725 }
1726
1727 break;
1728 case 'X':
1729 if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
1730 Key.ScanCode = SCAN_DELETE;
1731 } else if (TerminalDevice->TerminalType == TerminalTypeSCO) {
1732 Key.ScanCode = SCAN_F12;
1733 }
1734
1735 break;
1736 case 'P':
1737 if (TerminalDevice->TerminalType == TerminalTypeVt100) {
1738 Key.ScanCode = SCAN_DELETE;
1739 } else if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1740 (TerminalDevice->TerminalType == TerminalTypeSCO))
1741 {
1742 Key.ScanCode = SCAN_F4;
1743 }
1744
1745 break;
1746 case 'I':
1747 if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
1748 Key.ScanCode = SCAN_PAGE_UP;
1749 }
1750
1751 break;
1752 case 'V':
1753 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1754 (TerminalDevice->TerminalType == TerminalTypeSCO))
1755 {
1756 Key.ScanCode = SCAN_F10;
1757 }
1758
1759 break;
1760 case '?':
1761 if (TerminalDevice->TerminalType == TerminalTypeVt100) {
1762 Key.ScanCode = SCAN_PAGE_UP;
1763 }
1764
1765 break;
1766 case 'G':
1767 if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
1768 Key.ScanCode = SCAN_PAGE_DOWN;
1769 }
1770
1771 break;
1772 case 'U':
1773 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1774 (TerminalDevice->TerminalType == TerminalTypeSCO))
1775 {
1776 Key.ScanCode = SCAN_F9;
1777 }
1778
1779 break;
1780 case '/':
1781 if (TerminalDevice->TerminalType == TerminalTypeVt100) {
1782 Key.ScanCode = SCAN_PAGE_DOWN;
1783 }
1784
1785 break;
1786 case 'M':
1787 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1788 (TerminalDevice->TerminalType == TerminalTypeSCO))
1789 {
1790 Key.ScanCode = SCAN_F1;
1791 }
1792
1793 break;
1794 case 'N':
1795 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1796 (TerminalDevice->TerminalType == TerminalTypeSCO))
1797 {
1798 Key.ScanCode = SCAN_F2;
1799 }
1800
1801 break;
1802 case 'O':
1803 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1804 (TerminalDevice->TerminalType == TerminalTypeSCO))
1805 {
1806 Key.ScanCode = SCAN_F3;
1807 }
1808
1809 break;
1810 case 'Q':
1811 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1812 (TerminalDevice->TerminalType == TerminalTypeSCO))
1813 {
1814 Key.ScanCode = SCAN_F5;
1815 }
1816
1817 break;
1818 case 'R':
1819 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1820 (TerminalDevice->TerminalType == TerminalTypeSCO))
1821 {
1822 Key.ScanCode = SCAN_F6;
1823 }
1824
1825 break;
1826 case 'S':
1827 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1828 (TerminalDevice->TerminalType == TerminalTypeSCO))
1829 {
1830 Key.ScanCode = SCAN_F7;
1831 }
1832
1833 break;
1834 case 'T':
1835 if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
1836 (TerminalDevice->TerminalType == TerminalTypeSCO))
1837 {
1838 Key.ScanCode = SCAN_F8;
1839 }
1840
1841 break;
1842 case 'W':
1843 if (TerminalDevice->TerminalType == TerminalTypeSCO) {
1844 Key.ScanCode = SCAN_F11;
1845 }
1846
1847 break;
1848 default:
1849 break;
1850 }
1851 }
1852
1853 /*
1854 * The VT220 escape codes that the TTY terminal accepts all have
1855 * numeric codes, and there are no ambiguous prefixes shared with
1856 * other terminal types.
1857 */
1858 if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) &&
1859 (Key.ScanCode == SCAN_NULL) &&
1860 (UnicodeChar >= '0') &&
1861 (UnicodeChar <= '9'))
1862 {
1863 TerminalDevice->TtyEscapeStr[0] = UnicodeChar;
1864 TerminalDevice->TtyEscapeIndex = 1;
1865 TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET_TTY;
1866 continue;
1867 }
1868
1869 if (Key.ScanCode != SCAN_NULL) {
1870 Key.UnicodeChar = 0;
1871 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1872 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1873 UnicodeToEfiKeyFlushState (TerminalDevice);
1874 continue;
1875 }
1876
1877 UnicodeToEfiKeyFlushState (TerminalDevice);
1878
1879 break;
1880
1881 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_1:
1882
1883 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
1884
1885 Key.ScanCode = SCAN_NULL;
1886
1887 if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1888 (TerminalDevice->TerminalType == TerminalTypeVt400) ||
1889 (TerminalDevice->TerminalType == TerminalTypeLinux))
1890 {
1891 switch (UnicodeChar) {
1892 case '1':
1893 if (TerminalDevice->TerminalType == TerminalTypeVt400) {
1894 Key.ScanCode = SCAN_F1;
1895 }
1896
1897 break;
1898 case '2':
1899 if (TerminalDevice->TerminalType == TerminalTypeVt400) {
1900 Key.ScanCode = SCAN_F2;
1901 }
1902
1903 break;
1904 case '3':
1905 if (TerminalDevice->TerminalType == TerminalTypeVt400) {
1906 Key.ScanCode = SCAN_F3;
1907 }
1908
1909 break;
1910 case '4':
1911 if (TerminalDevice->TerminalType == TerminalTypeVt400) {
1912 Key.ScanCode = SCAN_F4;
1913 }
1914
1915 break;
1916 case '5':
1917 if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1918 (TerminalDevice->TerminalType == TerminalTypeVt400))
1919 {
1920 Key.ScanCode = SCAN_F5;
1921 }
1922
1923 break;
1924 case '7':
1925 Key.ScanCode = SCAN_F6;
1926 break;
1927 case '8':
1928 Key.ScanCode = SCAN_F7;
1929 break;
1930 case '9':
1931 Key.ScanCode = SCAN_F8;
1932 break;
1933 }
1934 }
1935
1936 if (Key.ScanCode != SCAN_NULL) {
1937 Key.UnicodeChar = 0;
1938 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1939 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1940 UnicodeToEfiKeyFlushState (TerminalDevice);
1941 continue;
1942 }
1943
1944 UnicodeToEfiKeyFlushState (TerminalDevice);
1945
1946 break;
1947
1948 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_2:
1949
1950 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1951 Key.ScanCode = SCAN_NULL;
1952 if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
1953 (TerminalDevice->TerminalType == TerminalTypeVt400) ||
1954 (TerminalDevice->TerminalType == TerminalTypeLinux))
1955 {
1956 switch (UnicodeChar) {
1957 case '0':
1958 Key.ScanCode = SCAN_F9;
1959 break;
1960 case '1':
1961 Key.ScanCode = SCAN_F10;
1962 break;
1963 case '3':
1964 Key.ScanCode = SCAN_F11;
1965 break;
1966 case '4':
1967 Key.ScanCode = SCAN_F12;
1968 break;
1969 }
1970 }
1971
1972 if (Key.ScanCode != SCAN_NULL) {
1973 Key.UnicodeChar = 0;
1974 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
1975 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1976 UnicodeToEfiKeyFlushState (TerminalDevice);
1977 continue;
1978 }
1979
1980 UnicodeToEfiKeyFlushState (TerminalDevice);
1981
1982 break;
1983
1984 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_LEFTOPENBRACKET_2ND:
1985
1986 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
1987 Key.ScanCode = SCAN_NULL;
1988
1989 if (TerminalDevice->TerminalType == TerminalTypeLinux) {
1990 switch (UnicodeChar) {
1991 case 'A':
1992 Key.ScanCode = SCAN_F1;
1993 break;
1994 case 'B':
1995 Key.ScanCode = SCAN_F2;
1996 break;
1997 case 'C':
1998 Key.ScanCode = SCAN_F3;
1999 break;
2000 case 'D':
2001 Key.ScanCode = SCAN_F4;
2002 break;
2003 case 'E':
2004 Key.ScanCode = SCAN_F5;
2005 break;
2006 }
2007 }
2008
2009 if (Key.ScanCode != SCAN_NULL) {
2010 Key.UnicodeChar = 0;
2011 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
2012 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
2013 UnicodeToEfiKeyFlushState (TerminalDevice);
2014 continue;
2015 }
2016
2017 UnicodeToEfiKeyFlushState (TerminalDevice);
2018
2019 break;
2020
2021 case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_LEFTOPENBRACKET_TTY:
2022 /*
2023 * Here we handle the VT220 escape codes that we accept. This
2024 * state is only used by the TTY terminal type.
2025 */
2026 Key.ScanCode = SCAN_NULL;
2027 if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
2028 if ((UnicodeChar == '~') && (TerminalDevice->TtyEscapeIndex <= 2)) {
2029 UINT16 EscCode;
2030 TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex] = 0; /* Terminate string */
2031 EscCode = (UINT16)StrDecimalToUintn (TerminalDevice->TtyEscapeStr);
2032 switch (EscCode) {
2033 case 2:
2034 Key.ScanCode = SCAN_INSERT;
2035 break;
2036 case 3:
2037 Key.ScanCode = SCAN_DELETE;
2038 break;
2039 case 5:
2040 Key.ScanCode = SCAN_PAGE_UP;
2041 break;
2042 case 6:
2043 Key.ScanCode = SCAN_PAGE_DOWN;
2044 break;
2045 case 11:
2046 case 12:
2047 case 13:
2048 case 14:
2049 case 15:
2050 Key.ScanCode = SCAN_F1 + EscCode - 11;
2051 break;
2052 case 17:
2053 case 18:
2054 case 19:
2055 case 20:
2056 case 21:
2057 Key.ScanCode = SCAN_F6 + EscCode - 17;
2058 break;
2059 case 23:
2060 case 24:
2061 Key.ScanCode = SCAN_F11 + EscCode - 23;
2062 break;
2063 default:
2064 break;
2065 }
2066 } else if (TerminalDevice->TtyEscapeIndex == 1) {
2067 /* 2 character escape code */
2068 TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex++] = UnicodeChar;
2069 continue;
2070 } else {
2071 DEBUG ((DEBUG_ERROR, "Unexpected state in escape2\n"));
2072 }
2073 }
2074
2075 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
2076
2077 if (Key.ScanCode != SCAN_NULL) {
2078 Key.UnicodeChar = 0;
2079 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
2080 TerminalDevice->InputState = INPUT_STATE_DEFAULT;
2081 UnicodeToEfiKeyFlushState (TerminalDevice);
2082 continue;
2083 }
2084
2085 UnicodeToEfiKeyFlushState (TerminalDevice);
2086 break;
2087
2088 default:
2089 //
2090 // Invalid state. This should never happen.
2091 //
2092 ASSERT (FALSE);
2093
2094 UnicodeToEfiKeyFlushState (TerminalDevice);
2095
2096 break;
2097 }
2098
2099 if (UnicodeChar == ESC) {
2100 TerminalDevice->InputState = INPUT_STATE_ESC;
2101 }
2102
2103 if (UnicodeChar == CSI) {
2104 TerminalDevice->InputState = INPUT_STATE_CSI;
2105 }
2106
2107 if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
2108 Status = gBS->SetTimer (
2109 TerminalDevice->TwoSecondTimeOut,
2111 (UINT64)20000000
2112 );
2113 ASSERT_EFI_ERROR (Status);
2114 continue;
2115 }
2116
2117 if (SetDefaultResetState) {
2118 TerminalDevice->ResetState = RESET_STATE_DEFAULT;
2119 }
2120
2121 if (UnicodeChar == DEL) {
2122 if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
2123 Key.ScanCode = SCAN_NULL;
2124 Key.UnicodeChar = CHAR_BACKSPACE;
2125 } else {
2126 Key.ScanCode = SCAN_DELETE;
2127 Key.UnicodeChar = 0;
2128 }
2129 } else {
2130 Key.ScanCode = SCAN_NULL;
2131 Key.UnicodeChar = UnicodeChar;
2132 }
2133
2134 EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
2135 }
2136}
UINT64 UINTN
VOID AnsiRawDataToUnicode(IN TERMINAL_DEV *TerminalDevice)
Definition: Ansi.c:19
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
UINTN EFIAPI StrDecimalToUintn(IN CONST CHAR16 *String)
Definition: String.c:405
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI Input(IN CHAR16 *Prompt OPTIONAL, OUT CHAR16 *InStr, IN UINTN StrLen)
Definition: EdbSupportUI.c:187
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
#define EFI_ERROR_MINOR
Definition: PiStatusCode.h:58
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
EFI_STOP_BITS_TYPE
Definition: SerialIo.h:53
EFI_PARITY_TYPE
Definition: SerialIo.h:41
UINT8 EFI_KEY_TOGGLE_STATE
EFI_STATUS(EFIAPI * EFI_KEY_NOTIFY_FUNCTION)(IN EFI_KEY_DATA *KeyData)
VOID VTUTF8RawDataToUnicode(IN TERMINAL_DEV *VtUtf8Device)
Definition: Vtutf8.c:19
EFI_STATUS EFIAPI TerminalConInReadKeyStrokeEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, OUT EFI_KEY_DATA *KeyData)
EFI_STATUS GetOneKeyFromSerial(EFI_SERIAL_IO_PROTOCOL *SerialIo, UINT8 *Output)
VOID EFIAPI TerminalConInTimerHandler(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI KeyNotifyProcessHandler(IN EFI_EVENT Event, IN VOID *Context)
VOID UnicodeToEfiKeyFlushState(IN TERMINAL_DEV *TerminalDevice)
BOOLEAN IsRawFiFoFull(TERMINAL_DEV *TerminalDevice)
EFI_STATUS EFIAPI TerminalConInReset(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
Definition: TerminalConIn.c:61
EFI_STATUS EFIAPI TerminalConInResetEx(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN BOOLEAN ExtendedVerification)
BOOLEAN IsEfiKeyFiFoFull(TERMINAL_DEV *TerminalDevice)
VOID EFIAPI TerminalConInWaitForKey(IN EFI_EVENT Event, IN VOID *Context)
BOOLEAN RawFiFoInsertOneKey(TERMINAL_DEV *TerminalDevice, UINT8 Input)
BOOLEAN EfiKeyFiFoForNotifyRemoveOneKey(EFI_KEY_FIFO *EfiKeyFiFo, EFI_INPUT_KEY *Output)
BOOLEAN EfiKeyFiFoInsertOneKey(TERMINAL_DEV *TerminalDevice, EFI_INPUT_KEY *Key)
EFI_STATUS EFIAPI TerminalConInUnregisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN VOID *NotificationHandle)
BOOLEAN IsEfiKeyFiFoForNotifyFull(EFI_KEY_FIFO *EfiKeyFiFo)
BOOLEAN EfiKeyFiFoForNotifyInsertOneKey(EFI_KEY_FIFO *EfiKeyFiFo, EFI_INPUT_KEY *Input)
BOOLEAN IsUnicodeFiFoEmpty(TERMINAL_DEV *TerminalDevice)
VOID UnicodeToEfiKey(IN TERMINAL_DEV *TerminalDevice)
EFI_STATUS ReadKeyStrokeWorker(IN TERMINAL_DEV *TerminalDevice, OUT EFI_KEY_DATA *KeyData)
Definition: TerminalConIn.c:28
BOOLEAN IsEfiKeyFiFoForNotifyEmpty(EFI_KEY_FIFO *EfiKeyFiFo)
BOOLEAN RawFiFoRemoveOneKey(TERMINAL_DEV *TerminalDevice, UINT8 *Output)
EFI_STATUS EFIAPI TerminalConInRegisterKeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_DATA *KeyData, IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, OUT VOID **NotifyHandle)
VOID UnicodeFiFoRemoveOneKey(TERMINAL_DEV *TerminalDevice, UINT16 *Output)
BOOLEAN IsUnicodeFiFoFull(TERMINAL_DEV *TerminalDevice)
EFI_STATUS EFIAPI TerminalConInReadKeyStroke(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, OUT EFI_INPUT_KEY *Key)
BOOLEAN IsEfiKeyFiFoEmpty(TERMINAL_DEV *TerminalDevice)
BOOLEAN UnicodeFiFoInsertOneKey(TERMINAL_DEV *TerminalDevice, UINT16 Input)
EFI_STATUS EFIAPI TerminalConInSetState(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, IN EFI_KEY_TOGGLE_STATE *KeyToggleState)
BOOLEAN IsRawFiFoEmpty(TERMINAL_DEV *TerminalDevice)
VOID EFIAPI TerminalConInWaitForKeyEx(IN EFI_EVENT Event, IN VOID *Context)
BOOLEAN IsKeyRegistered(IN EFI_KEY_DATA *RegsiteredData, IN EFI_KEY_DATA *InputData)
BOOLEAN EfiKeyFiFoRemoveOneKey(TERMINAL_DEV *TerminalDevice, EFI_INPUT_KEY *Output)
VOID TranslateRawDataToEfiKey(IN TERMINAL_DEV *TerminalDevice)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ EfiResetWarm
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerRelative
Definition: UefiSpec.h:539
EFI_KEY_TOGGLE_STATE KeyToggleState
UINT32 KeyShiftState
EFI_SERIAL_IO_MODE * Mode
Definition: SerialIo.h:295
EFI_INPUT_KEY Key
EFI_KEY_STATE KeyState