2 Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
6 Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
14 Reads the next keystroke from the input device. The WaitForKey Event can
15 be used to test for existence of a keystroke via WaitForEvent () call.
17 @param TerminalDevice Terminal driver private structure
18 @param KeyData A pointer to a buffer that is filled in with the
19 keystroke state data for the key that was
22 @retval EFI_SUCCESS The keystroke information was returned.
23 @retval EFI_NOT_READY There was no keystroke data available.
24 @retval EFI_INVALID_PARAMETER KeyData is NULL.
29 IN TERMINAL_DEV
*TerminalDevice
,
30 OUT EFI_KEY_DATA
*KeyData
33 if (KeyData
== NULL
) {
34 return EFI_INVALID_PARAMETER
;
37 KeyData
->KeyState
.KeyShiftState
= 0;
38 KeyData
->KeyState
.KeyToggleState
= 0;
40 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
48 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
49 This driver only perform dependent serial device reset regardless of
50 the value of ExtendeVerification
52 @param This Indicates the calling context.
53 @param ExtendedVerification Skip by this driver.
55 @retval EFI_SUCCESS The reset operation succeeds.
56 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
62 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
63 IN BOOLEAN ExtendedVerification
67 TERMINAL_DEV
*TerminalDevice
;
69 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
72 // Report progress code here
74 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
76 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
77 TerminalDevice
->DevicePath
80 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
83 // Make all the internal buffer empty for keys
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
;
90 if (EFI_ERROR (Status
)) {
91 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
92 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
93 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
94 TerminalDevice
->DevicePath
102 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
104 @param This Indicates the calling context.
105 @param Key A pointer to a buffer that is filled in with the
106 keystroke information for the key that was sent
109 @retval EFI_SUCCESS The keystroke information is returned successfully.
110 @retval EFI_NOT_READY There is no keystroke data available.
111 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
116 TerminalConInReadKeyStroke (
117 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
118 OUT EFI_INPUT_KEY
*Key
121 TERMINAL_DEV
*TerminalDevice
;
123 EFI_KEY_DATA KeyData
;
126 // get TERMINAL_DEV from "This" parameter.
128 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
130 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
131 if (EFI_ERROR (Status
)) {
135 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
141 Check if the key already has been registered.
143 If both RegsiteredData and InputData is NULL, then ASSERT().
145 @param RegsiteredData A pointer to a buffer that is filled in with the
146 keystroke state data for the key that was
148 @param InputData A pointer to a buffer that is filled in with the
149 keystroke state data for the key that was
152 @retval TRUE Key be pressed matches a registered key.
153 @retval FALSE Match failed.
158 IN EFI_KEY_DATA
*RegsiteredData
,
159 IN EFI_KEY_DATA
*InputData
162 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
164 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
165 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
))
174 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
175 Signal the event if there is key available
177 @param Event Indicates the event that invoke this function.
178 @param Context Indicates the calling context.
183 TerminalConInWaitForKeyEx (
188 TerminalConInWaitForKey (Event
, Context
);
192 // Simple Text Input Ex protocol functions
196 Reset the input device and optionally run diagnostics
198 @param This Protocol instance pointer.
199 @param ExtendedVerification Driver may perform diagnostics on reset.
201 @retval EFI_SUCCESS The device was reset.
202 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
208 TerminalConInResetEx (
209 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
210 IN BOOLEAN ExtendedVerification
214 TERMINAL_DEV
*TerminalDevice
;
216 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
218 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
219 if (EFI_ERROR (Status
)) {
220 return EFI_DEVICE_ERROR
;
227 Reads the next keystroke from the input device. The WaitForKey Event can
228 be used to test for existence of a keystroke via WaitForEvent () call.
230 @param This Protocol instance pointer.
231 @param KeyData A pointer to a buffer that is filled in with the
232 keystroke state data for the key that was
235 @retval EFI_SUCCESS The keystroke information was returned.
236 @retval EFI_NOT_READY There was no keystroke data available.
237 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
239 @retval EFI_INVALID_PARAMETER KeyData is NULL.
244 TerminalConInReadKeyStrokeEx (
245 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
246 OUT EFI_KEY_DATA
*KeyData
249 TERMINAL_DEV
*TerminalDevice
;
251 if (KeyData
== NULL
) {
252 return EFI_INVALID_PARAMETER
;
255 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
257 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
261 Set certain state for the input device.
263 @param This Protocol instance pointer.
264 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
265 state for the input device.
267 @retval EFI_SUCCESS The device state was set successfully.
268 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
269 could not have the setting adjusted.
270 @retval EFI_UNSUPPORTED The device does not have the ability to set its
272 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
277 TerminalConInSetState (
278 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
279 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
282 if (KeyToggleState
== NULL
) {
283 return EFI_INVALID_PARAMETER
;
286 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
287 return EFI_UNSUPPORTED
;
294 Register a notification function for a particular keystroke for the input device.
296 @param This Protocol instance pointer.
297 @param KeyData A pointer to a buffer that is filled in with
298 the keystroke information for the key that was
299 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
300 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
301 keystroke will trigger a notification of the KeyNotificationFunction.
302 @param KeyNotificationFunction Points to the function to be called when the key
303 sequence is typed specified by KeyData. This notification function
304 should be called at <=TPL_CALLBACK.
305 @param NotifyHandle Points to the unique handle assigned to the
306 registered notification.
308 @retval EFI_SUCCESS The notification function was registered
310 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
312 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
317 TerminalConInRegisterKeyNotify (
318 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
319 IN EFI_KEY_DATA
*KeyData
,
320 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
321 OUT VOID
**NotifyHandle
324 TERMINAL_DEV
*TerminalDevice
;
325 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
327 LIST_ENTRY
*NotifyList
;
328 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
330 if ((KeyData
== NULL
) || (NotifyHandle
== NULL
) || (KeyNotificationFunction
== NULL
)) {
331 return EFI_INVALID_PARAMETER
;
334 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
337 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
339 NotifyList
= &TerminalDevice
->NotifyList
;
340 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
343 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
345 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
347 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
348 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
349 *NotifyHandle
= CurrentNotify
;
356 // Allocate resource to save the notification function
358 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*)AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
359 if (NewNotify
== NULL
) {
360 return EFI_OUT_OF_RESOURCES
;
363 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
364 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
365 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
366 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
368 *NotifyHandle
= NewNotify
;
374 Remove a registered notification function from a particular keystroke.
376 @param This Protocol instance pointer.
377 @param NotificationHandle The handle of the notification function being
380 @retval EFI_SUCCESS The notification function was unregistered
382 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
387 TerminalConInUnregisterKeyNotify (
388 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
389 IN VOID
*NotificationHandle
392 TERMINAL_DEV
*TerminalDevice
;
394 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
395 LIST_ENTRY
*NotifyList
;
397 if (NotificationHandle
== NULL
) {
398 return EFI_INVALID_PARAMETER
;
401 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
403 NotifyList
= &TerminalDevice
->NotifyList
;
404 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
407 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
409 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
411 if (CurrentNotify
== NotificationHandle
) {
413 // Remove the notification function from NotifyList and free resources
415 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
417 gBS
->FreePool (CurrentNotify
);
423 // Can not find the matching entry in database.
425 return EFI_INVALID_PARAMETER
;
429 Translate raw data into Unicode (according to different encode), and
430 translate Unicode into key information. (according to different standard).
432 @param TerminalDevice Terminal driver private structure.
436 TranslateRawDataToEfiKey (
437 IN TERMINAL_DEV
*TerminalDevice
440 switch (TerminalDevice
->TerminalType
) {
441 case TerminalTypePcAnsi
:
442 case TerminalTypeVt100
:
443 case TerminalTypeVt100Plus
:
444 case TerminalTypeTtyTerm
:
445 case TerminalTypeLinux
:
446 case TerminalTypeXtermR6
:
447 case TerminalTypeVt400
:
448 case TerminalTypeSCO
:
449 AnsiRawDataToUnicode (TerminalDevice
);
450 UnicodeToEfiKey (TerminalDevice
);
453 case TerminalTypeVtUtf8
:
455 // Process all the raw data in the RawFIFO,
456 // put the processed key into UnicodeFIFO.
458 VTUTF8RawDataToUnicode (TerminalDevice
);
461 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
462 // then put into EfiKeyFIFO.
464 UnicodeToEfiKey (TerminalDevice
);
471 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
472 Signal the event if there is key available
474 @param Event Indicates the event that invoke this function.
475 @param Context Indicates the calling context.
480 TerminalConInWaitForKey (
486 // Someone is waiting on the keystroke event, if there's
487 // a key pending, signal the event
489 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*)Context
)) {
490 gBS
->SignalEvent (Event
);
495 Timer handler to poll the key from serial.
497 @param Event Indicates the event that invoke this function.
498 @param Context Indicates the calling context.
502 TerminalConInTimerHandler (
508 TERMINAL_DEV
*TerminalDevice
;
511 EFI_SERIAL_IO_MODE
*Mode
;
512 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
513 UINTN SerialInTimeOut
;
515 TerminalDevice
= (TERMINAL_DEV
*)Context
;
517 SerialIo
= TerminalDevice
->SerialIo
;
518 if (SerialIo
== NULL
) {
523 // if current timeout value for serial device is not identical with
524 // the value saved in TERMINAL_DEV structure, then recalculate the
525 // timeout value again and set serial attribute according to this value.
527 Mode
= SerialIo
->Mode
;
528 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
530 if (Mode
->BaudRate
!= 0) {
532 // According to BAUD rate to calculate the timeout value.
534 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
)Mode
->BaudRate
;
537 Status
= SerialIo
->SetAttributes (
540 Mode
->ReceiveFifoDepth
,
541 (UINT32
)SerialInTimeOut
,
542 (EFI_PARITY_TYPE
)(Mode
->Parity
),
543 (UINT8
)Mode
->DataBits
,
544 (EFI_STOP_BITS_TYPE
)(Mode
->StopBits
)
547 if (EFI_ERROR (Status
)) {
548 TerminalDevice
->SerialInTimeOut
= 0;
550 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
555 // Check whether serial buffer is empty.
556 // Skip the key transfer loop only if the SerialIo protocol instance
557 // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
559 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
560 if (EFI_ERROR (Status
) || ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0)) {
562 // Fetch all the keys in the serial buffer,
563 // and insert the byte stream into RawFIFO.
565 while (!IsRawFiFoFull (TerminalDevice
)) {
566 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
568 if (EFI_ERROR (Status
)) {
569 if (Status
== EFI_DEVICE_ERROR
) {
570 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
571 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
572 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
573 TerminalDevice
->DevicePath
580 RawFiFoInsertOneKey (TerminalDevice
, Input
);
585 // Translate all the raw data in RawFIFO into EFI Key,
586 // according to different terminal type supported.
588 TranslateRawDataToEfiKey (TerminalDevice
);
594 @param Event Indicates the event that invoke this function.
595 @param Context Indicates the calling context.
599 KeyNotifyProcessHandler (
605 TERMINAL_DEV
*TerminalDevice
;
607 EFI_KEY_DATA KeyData
;
609 LIST_ENTRY
*NotifyList
;
610 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
613 TerminalDevice
= (TERMINAL_DEV
*)Context
;
616 // Invoke notification functions.
618 NotifyList
= &TerminalDevice
->NotifyList
;
621 // Enter critical section
623 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
624 HasKey
= EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, &Key
);
625 CopyMem (&KeyData
.Key
, &Key
, sizeof (EFI_INPUT_KEY
));
626 KeyData
.KeyState
.KeyShiftState
= 0;
627 KeyData
.KeyState
.KeyToggleState
= 0;
629 // Leave critical section
631 gBS
->RestoreTPL (OldTpl
);
636 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
637 CurrentNotify
= CR (Link
, TERMINAL_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
638 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
639 CurrentNotify
->KeyNotificationFn (&KeyData
);
646 Get one key out of serial buffer.
648 @param SerialIo Serial I/O protocol attached to the serial device.
649 @param Output The fetched key.
651 @retval EFI_NOT_READY If serial buffer is empty.
652 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
653 @retval EFI_SUCCESS If reading serial buffer successfully, put
654 the fetched key to the parameter output.
658 GetOneKeyFromSerial (
659 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
670 // Read one key from serial I/O device.
672 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
674 if (EFI_ERROR (Status
)) {
675 if (Status
== EFI_TIMEOUT
) {
676 return EFI_NOT_READY
;
679 return EFI_DEVICE_ERROR
;
683 return EFI_NOT_READY
;
690 Insert one byte raw data into the Raw Data FIFO.
692 @param TerminalDevice Terminal driver private structure.
693 @param Input The key will be input.
695 @retval TRUE If insert successfully.
696 @retval FALSE If Raw Data buffer is full before key insertion,
701 RawFiFoInsertOneKey (
702 TERMINAL_DEV
*TerminalDevice
,
708 Tail
= TerminalDevice
->RawFiFo
->Tail
;
710 if (IsRawFiFoFull (TerminalDevice
)) {
717 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
719 TerminalDevice
->RawFiFo
->Tail
= (UINT8
)((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
725 Remove one pre-fetched key out of the Raw Data FIFO.
727 @param TerminalDevice Terminal driver private structure.
728 @param Output The key will be removed.
730 @retval TRUE If insert successfully.
731 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
735 RawFiFoRemoveOneKey (
736 TERMINAL_DEV
*TerminalDevice
,
742 Head
= TerminalDevice
->RawFiFo
->Head
;
744 if (IsRawFiFoEmpty (TerminalDevice
)) {
752 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
754 TerminalDevice
->RawFiFo
->Head
= (UINT8
)((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
760 Clarify whether Raw Data FIFO buffer is empty.
762 @param TerminalDevice Terminal driver private structure
764 @retval TRUE If Raw Data FIFO buffer is empty.
765 @retval FALSE If Raw Data FIFO buffer is not empty.
770 TERMINAL_DEV
*TerminalDevice
773 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
781 Clarify whether Raw Data FIFO buffer is full.
783 @param TerminalDevice Terminal driver private structure
785 @retval TRUE If Raw Data FIFO buffer is full.
786 @retval FALSE If Raw Data FIFO buffer is not full.
791 TERMINAL_DEV
*TerminalDevice
797 Tail
= TerminalDevice
->RawFiFo
->Tail
;
798 Head
= TerminalDevice
->RawFiFo
->Head
;
800 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
808 Insert one pre-fetched key into the FIFO buffer.
810 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
811 @param Input The key will be input.
813 @retval TRUE If insert successfully.
814 @retval FALSE If FIFO buffer is full before key insertion,
819 EfiKeyFiFoForNotifyInsertOneKey (
820 EFI_KEY_FIFO
*EfiKeyFiFo
,
826 Tail
= EfiKeyFiFo
->Tail
;
828 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo
)) {
835 CopyMem (&EfiKeyFiFo
->Data
[Tail
], Input
, sizeof (EFI_INPUT_KEY
));
837 EfiKeyFiFo
->Tail
= (UINT8
)((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
843 Remove one pre-fetched key out of the FIFO buffer.
845 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
846 @param Output The key will be removed.
848 @retval TRUE If remove successfully.
849 @retval FALSE If FIFO buffer is empty before remove operation.
853 EfiKeyFiFoForNotifyRemoveOneKey (
854 EFI_KEY_FIFO
*EfiKeyFiFo
,
855 EFI_INPUT_KEY
*Output
860 Head
= EfiKeyFiFo
->Head
;
861 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
863 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo
)) {
867 Output
->ScanCode
= SCAN_NULL
;
868 Output
->UnicodeChar
= 0;
872 CopyMem (Output
, &EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
874 EfiKeyFiFo
->Head
= (UINT8
)((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
880 Clarify whether FIFO buffer is empty.
882 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
884 @retval TRUE If FIFO buffer is empty.
885 @retval FALSE If FIFO buffer is not empty.
889 IsEfiKeyFiFoForNotifyEmpty (
890 EFI_KEY_FIFO
*EfiKeyFiFo
893 if (EfiKeyFiFo
->Head
== EfiKeyFiFo
->Tail
) {
901 Clarify whether FIFO buffer is full.
903 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
905 @retval TRUE If FIFO buffer is full.
906 @retval FALSE If FIFO buffer is not full.
910 IsEfiKeyFiFoForNotifyFull (
911 EFI_KEY_FIFO
*EfiKeyFiFo
917 Tail
= EfiKeyFiFo
->Tail
;
918 Head
= EfiKeyFiFo
->Head
;
920 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
928 Insert one pre-fetched key into the FIFO buffer.
930 @param TerminalDevice Terminal driver private structure.
931 @param Key The key will be input.
933 @retval TRUE If insert successfully.
934 @retval FALSE If FIFO buffer is full before key insertion,
939 EfiKeyFiFoInsertOneKey (
940 TERMINAL_DEV
*TerminalDevice
,
946 LIST_ENTRY
*NotifyList
;
947 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
948 EFI_KEY_DATA KeyData
;
950 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
952 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
953 KeyData
.KeyState
.KeyShiftState
= 0;
954 KeyData
.KeyState
.KeyToggleState
= 0;
957 // Signal KeyNotify process event if this key pressed matches any key registered.
959 NotifyList
= &TerminalDevice
->NotifyList
;
960 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
963 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
965 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
967 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
969 // The key notification function needs to run at TPL_CALLBACK
970 // while current TPL is TPL_NOTIFY. It will be invoked in
971 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
973 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, Key
);
974 gBS
->SignalEvent (TerminalDevice
->KeyNotifyProcessEvent
);
979 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
981 // Efi Key FIFO is full
986 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
988 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
)((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
994 Remove one pre-fetched key out of the FIFO buffer.
996 @param TerminalDevice Terminal driver private structure.
997 @param Output The key will be removed.
999 @retval TRUE If insert successfully.
1000 @retval FALSE If FIFO buffer is empty before remove operation.
1004 EfiKeyFiFoRemoveOneKey (
1005 TERMINAL_DEV
*TerminalDevice
,
1006 EFI_INPUT_KEY
*Output
1011 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1012 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1014 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
1018 Output
->ScanCode
= SCAN_NULL
;
1019 Output
->UnicodeChar
= 0;
1023 CopyMem (Output
, &TerminalDevice
->EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
1025 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
)((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1031 Clarify whether FIFO buffer is empty.
1033 @param TerminalDevice Terminal driver private structure
1035 @retval TRUE If FIFO buffer is empty.
1036 @retval FALSE If FIFO buffer is not empty.
1041 TERMINAL_DEV
*TerminalDevice
1044 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
1052 Clarify whether FIFO buffer is full.
1054 @param TerminalDevice Terminal driver private structure
1056 @retval TRUE If FIFO buffer is full.
1057 @retval FALSE If FIFO buffer is not full.
1062 TERMINAL_DEV
*TerminalDevice
1068 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
1069 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1071 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1079 Insert one pre-fetched key into the Unicode FIFO buffer.
1081 @param TerminalDevice Terminal driver private structure.
1082 @param Input The key will be input.
1084 @retval TRUE If insert successfully.
1085 @retval FALSE If Unicode FIFO buffer is full before key insertion,
1086 and the key is lost.
1090 UnicodeFiFoInsertOneKey (
1091 TERMINAL_DEV
*TerminalDevice
,
1097 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1098 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
1100 if (IsUnicodeFiFoFull (TerminalDevice
)) {
1102 // Unicode FIFO is full
1107 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1109 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
)((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1115 Remove one pre-fetched key out of the Unicode FIFO buffer.
1116 The caller should guarantee that Unicode FIFO buffer is not empty
1117 by IsUnicodeFiFoEmpty ().
1119 @param TerminalDevice Terminal driver private structure.
1120 @param Output The key will be removed.
1124 UnicodeFiFoRemoveOneKey (
1125 TERMINAL_DEV
*TerminalDevice
,
1131 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1132 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1134 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1136 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
)((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1140 Clarify whether Unicode FIFO buffer is empty.
1142 @param TerminalDevice Terminal driver private structure
1144 @retval TRUE If Unicode FIFO buffer is empty.
1145 @retval FALSE If Unicode FIFO buffer is not empty.
1149 IsUnicodeFiFoEmpty (
1150 TERMINAL_DEV
*TerminalDevice
1153 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1161 Clarify whether Unicode FIFO buffer is full.
1163 @param TerminalDevice Terminal driver private structure
1165 @retval TRUE If Unicode FIFO buffer is full.
1166 @retval FALSE If Unicode FIFO buffer is not full.
1171 TERMINAL_DEV
*TerminalDevice
1177 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1178 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1180 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1188 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1190 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1194 UnicodeToEfiKeyFlushState (
1195 IN TERMINAL_DEV
*TerminalDevice
1201 InputState
= TerminalDevice
->InputState
;
1203 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1207 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1208 Key
.ScanCode
= SCAN_ESC
;
1209 Key
.UnicodeChar
= 0;
1210 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1213 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1214 Key
.ScanCode
= SCAN_NULL
;
1215 Key
.UnicodeChar
= CSI
;
1216 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1219 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1220 Key
.ScanCode
= SCAN_NULL
;
1221 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1222 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1225 if ((InputState
& INPUT_STATE_O
) != 0) {
1226 Key
.ScanCode
= SCAN_NULL
;
1227 Key
.UnicodeChar
= 'O';
1228 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1231 if ((InputState
& INPUT_STATE_2
) != 0) {
1232 Key
.ScanCode
= SCAN_NULL
;
1233 Key
.UnicodeChar
= '2';
1234 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1238 // Cancel the timer.
1241 TerminalDevice
->TwoSecondTimeOut
,
1246 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1250 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1251 can be read through the Simple Input Protocol.
1253 The table below shows the keyboard input mappings that this function supports.
1254 If the ESC sequence listed in one of the columns is presented, then it is translated
1255 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1256 key strokes are converted into EFI Keys.
1258 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1259 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1260 converted into EFI Keys.
1261 There is one special input sequence that will force the system to reset.
1262 This is ESC R ESC r ESC R.
1264 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1265 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1266 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1268 Symbols used in table below
1269 ===========================
1275 +=========+======+===========+==========+==========+
1276 | | EFI | UEFI 2.0 | | |
1277 | | Scan | | VT100+ | |
1278 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1279 +=========+======+===========+==========+==========+
1280 | NULL | 0x00 | | | |
1281 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1282 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1283 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1284 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1285 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1286 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1287 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1288 | | | ESC [ L | | ESC [ L |
1289 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1290 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1292 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1294 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1295 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1296 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1297 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1298 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1299 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1300 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1301 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1302 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1303 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1304 | Escape | 0x17 | ESC | ESC | ESC |
1305 | F11 | 0x15 | | ESC ! | |
1306 | F12 | 0x16 | | ESC @ | |
1307 +=========+======+===========+==========+==========+
1309 Putty function key map:
1310 +=========+======+===========+=============+=============+=============+=========+
1312 | | Scan | | | Normal | | |
1313 | KEY | Code | VT100+ | Xterm R6 | VT400 | Linux | SCO |
1314 +=========+======+===========+=============+=============+=============+=========+
1315 | F1 | 0x0B | ESC O P | ESC O P | ESC [ 1 1 ~ | ESC [ [ A | ESC [ M |
1316 | F2 | 0x0C | ESC O Q | ESC O Q | ESC [ 1 2 ~ | ESC [ [ B | ESC [ N |
1317 | F3 | 0x0D | ESC O R | ESC O R | ESC [ 1 3 ~ | ESC [ [ C | ESC [ O |
1318 | F4 | 0x0E | ESC O S | ESC O S | ESC [ 1 4 ~ | ESC [ [ D | ESC [ P |
1319 | F5 | 0x0F | ESC O T | ESC [ 1 5 ~ | ESC [ 1 5 ~ | ESC [ [ E | ESC [ Q |
1320 | F6 | 0x10 | ESC O U | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ R |
1321 | F7 | 0x11 | ESC O V | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ S |
1322 | F8 | 0x12 | ESC O W | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ T |
1323 | F9 | 0x13 | ESC O X | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ U |
1324 | F10 | 0x14 | ESC O Y | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ V |
1325 | Escape | 0x17 | ESC | ESC | ESC | ESC | ESC |
1326 | F11 | 0x15 | ESC O Z | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ W |
1327 | F12 | 0x16 | ESC O [ | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ X |
1328 +=========+======+===========+=============+=============+=============+=========+
1332 ESC R ESC r ESC R = Reset System
1334 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1339 IN TERMINAL_DEV
*TerminalDevice
1343 EFI_STATUS TimerStatus
;
1346 BOOLEAN SetDefaultResetState
;
1348 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1350 if (!EFI_ERROR (TimerStatus
)) {
1351 UnicodeToEfiKeyFlushState (TerminalDevice
);
1352 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1355 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1356 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1358 // Check to see if the 2 seconds timer has expired
1360 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1361 if (!EFI_ERROR (TimerStatus
)) {
1362 UnicodeToEfiKeyFlushState (TerminalDevice
);
1363 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1368 // Fetch one Unicode character from the Unicode FIFO
1370 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1372 SetDefaultResetState
= TRUE
;
1374 switch (TerminalDevice
->InputState
) {
1375 case INPUT_STATE_DEFAULT
:
1379 case INPUT_STATE_ESC
:
1381 if (UnicodeChar
== LEFTOPENBRACKET
) {
1382 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1383 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1387 if ((UnicodeChar
== 'O') && ((TerminalDevice
->TerminalType
== TerminalTypeVt100
) ||
1388 (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) ||
1389 (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1390 (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
)))
1392 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1393 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1397 Key
.ScanCode
= SCAN_NULL
;
1399 if ((TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
) ||
1400 (TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
))
1402 switch (UnicodeChar
) {
1404 Key
.ScanCode
= SCAN_F1
;
1407 Key
.ScanCode
= SCAN_F2
;
1410 Key
.ScanCode
= SCAN_F3
;
1413 Key
.ScanCode
= SCAN_F4
;
1416 Key
.ScanCode
= SCAN_F5
;
1419 Key
.ScanCode
= SCAN_F6
;
1422 Key
.ScanCode
= SCAN_F7
;
1425 Key
.ScanCode
= SCAN_F8
;
1428 Key
.ScanCode
= SCAN_F9
;
1431 Key
.ScanCode
= SCAN_F10
;
1434 Key
.ScanCode
= SCAN_F11
;
1437 Key
.ScanCode
= SCAN_F12
;
1440 Key
.ScanCode
= SCAN_HOME
;
1443 Key
.ScanCode
= SCAN_END
;
1446 Key
.ScanCode
= SCAN_INSERT
;
1449 Key
.ScanCode
= SCAN_DELETE
;
1452 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1455 Key
.ScanCode
= SCAN_PAGE_UP
;
1462 switch (UnicodeChar
) {
1464 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1465 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1466 SetDefaultResetState
= FALSE
;
1467 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1468 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1471 Key
.ScanCode
= SCAN_NULL
;
1474 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1475 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1476 SetDefaultResetState
= FALSE
;
1479 Key
.ScanCode
= SCAN_NULL
;
1485 if (SetDefaultResetState
) {
1486 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1489 if (Key
.ScanCode
!= SCAN_NULL
) {
1490 Key
.UnicodeChar
= 0;
1491 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1492 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1493 UnicodeToEfiKeyFlushState (TerminalDevice
);
1497 UnicodeToEfiKeyFlushState (TerminalDevice
);
1501 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1503 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1505 Key
.ScanCode
= SCAN_NULL
;
1507 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1508 switch (UnicodeChar
) {
1510 Key
.ScanCode
= SCAN_F1
;
1513 Key
.ScanCode
= SCAN_F2
;
1516 Key
.ScanCode
= SCAN_F3
;
1519 Key
.ScanCode
= SCAN_F4
;
1522 Key
.ScanCode
= SCAN_F5
;
1525 Key
.ScanCode
= SCAN_F6
;
1528 Key
.ScanCode
= SCAN_F7
;
1531 Key
.ScanCode
= SCAN_F8
;
1534 Key
.ScanCode
= SCAN_F9
;
1537 Key
.ScanCode
= SCAN_F10
;
1542 } else if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1543 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1544 switch (UnicodeChar
) {
1546 Key
.ScanCode
= SCAN_F1
;
1549 Key
.ScanCode
= SCAN_F2
;
1552 Key
.ScanCode
= SCAN_F3
;
1555 Key
.ScanCode
= SCAN_F4
;
1558 Key
.ScanCode
= SCAN_HOME
;
1561 Key
.ScanCode
= SCAN_END
;
1564 } else if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
) {
1565 switch (UnicodeChar
) {
1567 Key
.ScanCode
= SCAN_F1
;
1570 Key
.ScanCode
= SCAN_F2
;
1573 Key
.ScanCode
= SCAN_F3
;
1576 Key
.ScanCode
= SCAN_F4
;
1579 Key
.ScanCode
= SCAN_F5
;
1582 Key
.ScanCode
= SCAN_F6
;
1585 Key
.ScanCode
= SCAN_F7
;
1588 Key
.ScanCode
= SCAN_F8
;
1591 Key
.ScanCode
= SCAN_F9
;
1594 Key
.ScanCode
= SCAN_F10
;
1597 Key
.ScanCode
= SCAN_F11
;
1600 Key
.ScanCode
= SCAN_F12
;
1603 } else if (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) {
1604 switch (UnicodeChar
) {
1606 Key
.ScanCode
= SCAN_F1
;
1609 Key
.ScanCode
= SCAN_F2
;
1612 Key
.ScanCode
= SCAN_F3
;
1615 Key
.ScanCode
= SCAN_F4
;
1620 if (Key
.ScanCode
!= SCAN_NULL
) {
1621 Key
.UnicodeChar
= 0;
1622 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1623 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1624 UnicodeToEfiKeyFlushState (TerminalDevice
);
1628 UnicodeToEfiKeyFlushState (TerminalDevice
);
1632 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1634 if ((UnicodeChar
== '1') && ((TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1635 (TerminalDevice
->TerminalType
== TerminalTypeVt400
) ||
1636 (TerminalDevice
->TerminalType
== TerminalTypeLinux
)))
1638 TerminalDevice
->InputState
|= INPUT_STATE_1
;
1642 if ((UnicodeChar
== '2') && ((TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1643 (TerminalDevice
->TerminalType
== TerminalTypeVt400
) ||
1644 (TerminalDevice
->TerminalType
== TerminalTypeLinux
)))
1646 TerminalDevice
->InputState
|= INPUT_STATE_2
;
1650 if ((UnicodeChar
== LEFTOPENBRACKET
) && (TerminalDevice
->TerminalType
== TerminalTypeLinux
)) {
1651 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_2ND
;
1655 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1657 Key
.ScanCode
= SCAN_NULL
;
1659 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1660 (TerminalDevice
->TerminalType
== TerminalTypeVt100
) ||
1661 (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
) ||
1662 (TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
) ||
1663 (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) ||
1664 (TerminalDevice
->TerminalType
== TerminalTypeLinux
) ||
1665 (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1666 (TerminalDevice
->TerminalType
== TerminalTypeVt400
) ||
1667 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1669 switch (UnicodeChar
) {
1671 Key
.ScanCode
= SCAN_UP
;
1674 Key
.ScanCode
= SCAN_DOWN
;
1677 Key
.ScanCode
= SCAN_RIGHT
;
1680 Key
.ScanCode
= SCAN_LEFT
;
1683 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1684 (TerminalDevice
->TerminalType
== TerminalTypeVt100
) ||
1685 (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
))
1687 Key
.ScanCode
= SCAN_HOME
;
1692 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1693 (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
))
1695 Key
.ScanCode
= SCAN_END
;
1700 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1701 Key
.ScanCode
= SCAN_END
;
1707 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1708 (TerminalDevice
->TerminalType
== TerminalTypeVt100
))
1710 Key
.ScanCode
= SCAN_INSERT
;
1715 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1716 Key
.ScanCode
= SCAN_DELETE
;
1717 } else if (TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1718 Key
.ScanCode
= SCAN_F12
;
1723 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1724 Key
.ScanCode
= SCAN_DELETE
;
1725 } else if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1726 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1728 Key
.ScanCode
= SCAN_F4
;
1733 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1734 Key
.ScanCode
= SCAN_PAGE_UP
;
1739 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1740 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1742 Key
.ScanCode
= SCAN_F10
;
1747 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1748 Key
.ScanCode
= SCAN_PAGE_UP
;
1753 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1754 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1759 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1760 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1762 Key
.ScanCode
= SCAN_F9
;
1767 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1768 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1773 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1774 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1776 Key
.ScanCode
= SCAN_F1
;
1781 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1782 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1784 Key
.ScanCode
= SCAN_F2
;
1789 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1790 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1792 Key
.ScanCode
= SCAN_F3
;
1797 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1798 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1800 Key
.ScanCode
= SCAN_F5
;
1805 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1806 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1808 Key
.ScanCode
= SCAN_F6
;
1813 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1814 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1816 Key
.ScanCode
= SCAN_F7
;
1821 if ((TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) ||
1822 (TerminalDevice
->TerminalType
== TerminalTypeSCO
))
1824 Key
.ScanCode
= SCAN_F8
;
1829 if (TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1830 Key
.ScanCode
= SCAN_F11
;
1840 * The VT220 escape codes that the TTY terminal accepts all have
1841 * numeric codes, and there are no ambiguous prefixes shared with
1842 * other terminal types.
1844 if ((TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) &&
1845 (Key
.ScanCode
== SCAN_NULL
) &&
1846 (UnicodeChar
>= '0') &&
1847 (UnicodeChar
<= '9'))
1849 TerminalDevice
->TtyEscapeStr
[0] = UnicodeChar
;
1850 TerminalDevice
->TtyEscapeIndex
= 1;
1851 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_TTY
;
1855 if (Key
.ScanCode
!= SCAN_NULL
) {
1856 Key
.UnicodeChar
= 0;
1857 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1858 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1859 UnicodeToEfiKeyFlushState (TerminalDevice
);
1863 UnicodeToEfiKeyFlushState (TerminalDevice
);
1867 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_1
:
1869 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1871 Key
.ScanCode
= SCAN_NULL
;
1873 if ((TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1874 (TerminalDevice
->TerminalType
== TerminalTypeVt400
) ||
1875 (TerminalDevice
->TerminalType
== TerminalTypeLinux
))
1877 switch (UnicodeChar
) {
1879 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1880 Key
.ScanCode
= SCAN_F1
;
1885 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1886 Key
.ScanCode
= SCAN_F2
;
1891 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1892 Key
.ScanCode
= SCAN_F3
;
1897 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1898 Key
.ScanCode
= SCAN_F4
;
1903 if ((TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1904 (TerminalDevice
->TerminalType
== TerminalTypeVt400
))
1906 Key
.ScanCode
= SCAN_F5
;
1911 Key
.ScanCode
= SCAN_F6
;
1914 Key
.ScanCode
= SCAN_F7
;
1917 Key
.ScanCode
= SCAN_F8
;
1922 if (Key
.ScanCode
!= SCAN_NULL
) {
1923 Key
.UnicodeChar
= 0;
1924 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1925 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1926 UnicodeToEfiKeyFlushState (TerminalDevice
);
1930 UnicodeToEfiKeyFlushState (TerminalDevice
);
1934 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_2
:
1936 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1937 Key
.ScanCode
= SCAN_NULL
;
1938 if ((TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) ||
1939 (TerminalDevice
->TerminalType
== TerminalTypeVt400
) ||
1940 (TerminalDevice
->TerminalType
== TerminalTypeLinux
))
1942 switch (UnicodeChar
) {
1944 Key
.ScanCode
= SCAN_F9
;
1947 Key
.ScanCode
= SCAN_F10
;
1950 Key
.ScanCode
= SCAN_F11
;
1953 Key
.ScanCode
= SCAN_F12
;
1958 if (Key
.ScanCode
!= SCAN_NULL
) {
1959 Key
.UnicodeChar
= 0;
1960 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1961 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1962 UnicodeToEfiKeyFlushState (TerminalDevice
);
1966 UnicodeToEfiKeyFlushState (TerminalDevice
);
1970 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_2ND
:
1972 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1973 Key
.ScanCode
= SCAN_NULL
;
1975 if (TerminalDevice
->TerminalType
== TerminalTypeLinux
) {
1976 switch (UnicodeChar
) {
1978 Key
.ScanCode
= SCAN_F1
;
1981 Key
.ScanCode
= SCAN_F2
;
1984 Key
.ScanCode
= SCAN_F3
;
1987 Key
.ScanCode
= SCAN_F4
;
1990 Key
.ScanCode
= SCAN_F5
;
1995 if (Key
.ScanCode
!= SCAN_NULL
) {
1996 Key
.UnicodeChar
= 0;
1997 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1998 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1999 UnicodeToEfiKeyFlushState (TerminalDevice
);
2003 UnicodeToEfiKeyFlushState (TerminalDevice
);
2007 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_TTY
:
2009 * Here we handle the VT220 escape codes that we accept. This
2010 * state is only used by the TTY terminal type.
2012 Key
.ScanCode
= SCAN_NULL
;
2013 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
2014 if ((UnicodeChar
== '~') && (TerminalDevice
->TtyEscapeIndex
<= 2)) {
2016 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
] = 0; /* Terminate string */
2017 EscCode
= (UINT16
)StrDecimalToUintn (TerminalDevice
->TtyEscapeStr
);
2020 Key
.ScanCode
= SCAN_INSERT
;
2023 Key
.ScanCode
= SCAN_DELETE
;
2026 Key
.ScanCode
= SCAN_PAGE_UP
;
2029 Key
.ScanCode
= SCAN_PAGE_DOWN
;
2036 Key
.ScanCode
= SCAN_F1
+ EscCode
- 11;
2043 Key
.ScanCode
= SCAN_F6
+ EscCode
- 17;
2047 Key
.ScanCode
= SCAN_F11
+ EscCode
- 23;
2052 } else if (TerminalDevice
->TtyEscapeIndex
== 1) {
2053 /* 2 character escape code */
2054 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
++] = UnicodeChar
;
2057 DEBUG ((DEBUG_ERROR
, "Unexpected state in escape2\n"));
2061 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
2063 if (Key
.ScanCode
!= SCAN_NULL
) {
2064 Key
.UnicodeChar
= 0;
2065 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
2066 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
2067 UnicodeToEfiKeyFlushState (TerminalDevice
);
2071 UnicodeToEfiKeyFlushState (TerminalDevice
);
2076 // Invalid state. This should never happen.
2080 UnicodeToEfiKeyFlushState (TerminalDevice
);
2085 if (UnicodeChar
== ESC
) {
2086 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
2089 if (UnicodeChar
== CSI
) {
2090 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
2093 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
2094 Status
= gBS
->SetTimer (
2095 TerminalDevice
->TwoSecondTimeOut
,
2099 ASSERT_EFI_ERROR (Status
);
2103 if (SetDefaultResetState
) {
2104 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
2107 if (UnicodeChar
== DEL
) {
2108 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
2109 Key
.ScanCode
= SCAN_NULL
;
2110 Key
.UnicodeChar
= CHAR_BACKSPACE
;
2112 Key
.ScanCode
= SCAN_DELETE
;
2113 Key
.UnicodeChar
= 0;
2116 Key
.ScanCode
= SCAN_NULL
;
2117 Key
.UnicodeChar
= UnicodeChar
;
2120 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);