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
15 Reads the next keystroke from the input device. The WaitForKey Event can
16 be used to test for existence of a keystroke via WaitForEvent () call.
18 @param TerminalDevice Terminal driver private structure
19 @param KeyData A pointer to a buffer that is filled in with the
20 keystroke state data for the key that was
23 @retval EFI_SUCCESS The keystroke information was returned.
24 @retval EFI_NOT_READY There was no keystroke data available.
25 @retval EFI_INVALID_PARAMETER KeyData is NULL.
30 IN TERMINAL_DEV
*TerminalDevice
,
31 OUT EFI_KEY_DATA
*KeyData
34 if (KeyData
== NULL
) {
35 return EFI_INVALID_PARAMETER
;
38 KeyData
->KeyState
.KeyShiftState
= 0;
39 KeyData
->KeyState
.KeyToggleState
= 0;
41 if (!EfiKeyFiFoRemoveOneKey (TerminalDevice
, &KeyData
->Key
)) {
50 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
51 This driver only perform dependent serial device reset regardless of
52 the value of ExtendeVerification
54 @param This Indicates the calling context.
55 @param ExtendedVerification Skip by this driver.
57 @retval EFI_SUCCESS The reset operation succeeds.
58 @retval EFI_DEVICE_ERROR The dependent serial port reset fails.
64 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
65 IN BOOLEAN ExtendedVerification
69 TERMINAL_DEV
*TerminalDevice
;
71 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
74 // Report progress code here
76 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
78 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
),
79 TerminalDevice
->DevicePath
82 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
85 // Make all the internal buffer empty for keys
87 TerminalDevice
->RawFiFo
->Head
= TerminalDevice
->RawFiFo
->Tail
;
88 TerminalDevice
->UnicodeFiFo
->Head
= TerminalDevice
->UnicodeFiFo
->Tail
;
89 TerminalDevice
->EfiKeyFiFo
->Head
= TerminalDevice
->EfiKeyFiFo
->Tail
;
90 TerminalDevice
->EfiKeyFiFoForNotify
->Head
= TerminalDevice
->EfiKeyFiFoForNotify
->Tail
;
92 if (EFI_ERROR (Status
)) {
93 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
94 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
95 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
),
96 TerminalDevice
->DevicePath
104 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
106 @param This Indicates the calling context.
107 @param Key A pointer to a buffer that is filled in with the
108 keystroke information for the key that was sent
111 @retval EFI_SUCCESS The keystroke information is returned successfully.
112 @retval EFI_NOT_READY There is no keystroke data available.
113 @retval EFI_DEVICE_ERROR The dependent serial device encounters error.
118 TerminalConInReadKeyStroke (
119 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
120 OUT EFI_INPUT_KEY
*Key
123 TERMINAL_DEV
*TerminalDevice
;
125 EFI_KEY_DATA KeyData
;
128 // get TERMINAL_DEV from "This" parameter.
130 TerminalDevice
= TERMINAL_CON_IN_DEV_FROM_THIS (This
);
132 Status
= ReadKeyStrokeWorker (TerminalDevice
, &KeyData
);
133 if (EFI_ERROR (Status
)) {
137 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
144 Check if the key already has been registered.
146 If both RegsiteredData and InputData is NULL, then ASSERT().
148 @param RegsiteredData A pointer to a buffer that is filled in with the
149 keystroke state data for the key that was
151 @param InputData A pointer to a buffer that is filled in with the
152 keystroke state data for the key that was
155 @retval TRUE Key be pressed matches a registered key.
156 @retval FALSE Match failed.
161 IN EFI_KEY_DATA
*RegsiteredData
,
162 IN EFI_KEY_DATA
*InputData
165 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
167 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
168 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
178 Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
179 Signal the event if there is key available
181 @param Event Indicates the event that invoke this function.
182 @param Context Indicates the calling context.
187 TerminalConInWaitForKeyEx (
192 TerminalConInWaitForKey (Event
, Context
);
196 // Simple Text Input Ex protocol functions
200 Reset the input device and optionally run diagnostics
202 @param This Protocol instance pointer.
203 @param ExtendedVerification Driver may perform diagnostics on reset.
205 @retval EFI_SUCCESS The device was reset.
206 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
212 TerminalConInResetEx (
213 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
214 IN BOOLEAN ExtendedVerification
218 TERMINAL_DEV
*TerminalDevice
;
220 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
222 Status
= TerminalDevice
->SimpleInput
.Reset (&TerminalDevice
->SimpleInput
, ExtendedVerification
);
223 if (EFI_ERROR (Status
)) {
224 return EFI_DEVICE_ERROR
;
233 Reads the next keystroke from the input device. The WaitForKey Event can
234 be used to test for existence of a keystroke via WaitForEvent () call.
236 @param This Protocol instance pointer.
237 @param KeyData A pointer to a buffer that is filled in with the
238 keystroke state data for the key that was
241 @retval EFI_SUCCESS The keystroke information was returned.
242 @retval EFI_NOT_READY There was no keystroke data available.
243 @retval EFI_DEVICE_ERROR The keystroke information was not returned due
245 @retval EFI_INVALID_PARAMETER KeyData is NULL.
250 TerminalConInReadKeyStrokeEx (
251 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
252 OUT EFI_KEY_DATA
*KeyData
255 TERMINAL_DEV
*TerminalDevice
;
257 if (KeyData
== NULL
) {
258 return EFI_INVALID_PARAMETER
;
261 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
263 return ReadKeyStrokeWorker (TerminalDevice
, KeyData
);
269 Set certain state for the input device.
271 @param This Protocol instance pointer.
272 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
273 state for the input device.
275 @retval EFI_SUCCESS The device state was set successfully.
276 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
277 could not have the setting adjusted.
278 @retval EFI_UNSUPPORTED The device does not have the ability to set its
280 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
285 TerminalConInSetState (
286 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
287 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
290 if (KeyToggleState
== NULL
) {
291 return EFI_INVALID_PARAMETER
;
294 if ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) {
295 return EFI_UNSUPPORTED
;
303 Register a notification function for a particular keystroke for the input device.
305 @param This Protocol instance pointer.
306 @param KeyData A pointer to a buffer that is filled in with
307 the keystroke information for the key that was
308 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
309 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
310 keystroke will trigger a notification of the KeyNotificationFunction.
311 @param KeyNotificationFunction Points to the function to be called when the key
312 sequence is typed specified by KeyData. This notification function
313 should be called at <=TPL_CALLBACK.
314 @param NotifyHandle Points to the unique handle assigned to the
315 registered notification.
317 @retval EFI_SUCCESS The notification function was registered
319 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
321 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
326 TerminalConInRegisterKeyNotify (
327 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
328 IN EFI_KEY_DATA
*KeyData
,
329 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
330 OUT VOID
**NotifyHandle
333 TERMINAL_DEV
*TerminalDevice
;
334 TERMINAL_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
336 LIST_ENTRY
*NotifyList
;
337 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
339 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
340 return EFI_INVALID_PARAMETER
;
343 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
346 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
348 NotifyList
= &TerminalDevice
->NotifyList
;
349 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
352 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
354 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
356 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
357 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
358 *NotifyHandle
= CurrentNotify
;
365 // Allocate resource to save the notification function
367 NewNotify
= (TERMINAL_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY
));
368 if (NewNotify
== NULL
) {
369 return EFI_OUT_OF_RESOURCES
;
372 NewNotify
->Signature
= TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
373 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
374 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
375 InsertTailList (&TerminalDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
377 *NotifyHandle
= NewNotify
;
384 Remove a registered notification function from a particular keystroke.
386 @param This Protocol instance pointer.
387 @param NotificationHandle The handle of the notification function being
390 @retval EFI_SUCCESS The notification function was unregistered
392 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
397 TerminalConInUnregisterKeyNotify (
398 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
399 IN VOID
*NotificationHandle
402 TERMINAL_DEV
*TerminalDevice
;
404 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
405 LIST_ENTRY
*NotifyList
;
407 if (NotificationHandle
== NULL
) {
408 return EFI_INVALID_PARAMETER
;
411 TerminalDevice
= TERMINAL_CON_IN_EX_DEV_FROM_THIS (This
);
413 NotifyList
= &TerminalDevice
->NotifyList
;
414 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
417 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
419 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
421 if (CurrentNotify
== NotificationHandle
) {
423 // Remove the notification function from NotifyList and free resources
425 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
427 gBS
->FreePool (CurrentNotify
);
433 // Can not find the matching entry in database.
435 return EFI_INVALID_PARAMETER
;
439 Translate raw data into Unicode (according to different encode), and
440 translate Unicode into key information. (according to different standard).
442 @param TerminalDevice Terminal driver private structure.
446 TranslateRawDataToEfiKey (
447 IN TERMINAL_DEV
*TerminalDevice
450 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
);
464 case TerminalTypeVtUtf8
:
466 // Process all the raw data in the RawFIFO,
467 // put the processed key into UnicodeFIFO.
469 VTUTF8RawDataToUnicode (TerminalDevice
);
472 // Translate all the Unicode data in the UnicodeFIFO to Efi key,
473 // then put into EfiKeyFIFO.
475 UnicodeToEfiKey (TerminalDevice
);
482 Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
483 Signal the event if there is key available
485 @param Event Indicates the event that invoke this function.
486 @param Context Indicates the calling context.
491 TerminalConInWaitForKey (
497 // Someone is waiting on the keystroke event, if there's
498 // a key pending, signal the event
500 if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV
*) Context
)) {
502 gBS
->SignalEvent (Event
);
507 Timer handler to poll the key from serial.
509 @param Event Indicates the event that invoke this function.
510 @param Context Indicates the calling context.
514 TerminalConInTimerHandler (
520 TERMINAL_DEV
*TerminalDevice
;
523 EFI_SERIAL_IO_MODE
*Mode
;
524 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
525 UINTN SerialInTimeOut
;
527 TerminalDevice
= (TERMINAL_DEV
*) Context
;
529 SerialIo
= TerminalDevice
->SerialIo
;
530 if (SerialIo
== NULL
) {
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.
538 Mode
= SerialIo
->Mode
;
539 if (Mode
->Timeout
!= TerminalDevice
->SerialInTimeOut
) {
542 if (Mode
->BaudRate
!= 0) {
544 // According to BAUD rate to calculate the timeout value.
546 SerialInTimeOut
= (1 + Mode
->DataBits
+ Mode
->StopBits
) * 2 * 1000000 / (UINTN
) Mode
->BaudRate
;
549 Status
= SerialIo
->SetAttributes (
552 Mode
->ReceiveFifoDepth
,
553 (UINT32
) SerialInTimeOut
,
554 (EFI_PARITY_TYPE
) (Mode
->Parity
),
555 (UINT8
) Mode
->DataBits
,
556 (EFI_STOP_BITS_TYPE
) (Mode
->StopBits
)
559 if (EFI_ERROR (Status
)) {
560 TerminalDevice
->SerialInTimeOut
= 0;
562 TerminalDevice
->SerialInTimeOut
= SerialInTimeOut
;
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.
570 Status
= SerialIo
->GetControl (SerialIo
, &Control
);
571 if (EFI_ERROR (Status
) || ((Control
& EFI_SERIAL_INPUT_BUFFER_EMPTY
) == 0)) {
573 // Fetch all the keys in the serial buffer,
574 // and insert the byte stream into RawFIFO.
576 while (!IsRawFiFoFull (TerminalDevice
)) {
578 Status
= GetOneKeyFromSerial (TerminalDevice
->SerialIo
, &Input
);
580 if (EFI_ERROR (Status
)) {
581 if (Status
== EFI_DEVICE_ERROR
) {
582 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
583 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
584 (EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_INPUT_ERROR
),
585 TerminalDevice
->DevicePath
591 RawFiFoInsertOneKey (TerminalDevice
, Input
);
596 // Translate all the raw data in RawFIFO into EFI Key,
597 // according to different terminal type supported.
599 TranslateRawDataToEfiKey (TerminalDevice
);
605 @param Event Indicates the event that invoke this function.
606 @param Context Indicates the calling context.
610 KeyNotifyProcessHandler (
616 TERMINAL_DEV
*TerminalDevice
;
618 EFI_KEY_DATA KeyData
;
620 LIST_ENTRY
*NotifyList
;
621 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
624 TerminalDevice
= (TERMINAL_DEV
*) Context
;
627 // Invoke notification functions.
629 NotifyList
= &TerminalDevice
->NotifyList
;
632 // Enter critical section
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;
640 // Leave critical section
642 gBS
->RestoreTPL (OldTpl
);
646 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
647 CurrentNotify
= CR (Link
, TERMINAL_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
648 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
649 CurrentNotify
->KeyNotificationFn (&KeyData
);
656 Get one key out of serial buffer.
658 @param SerialIo Serial I/O protocol attached to the serial device.
659 @param Output The fetched key.
661 @retval EFI_NOT_READY If serial buffer is empty.
662 @retval EFI_DEVICE_ERROR If reading serial buffer encounter error.
663 @retval EFI_SUCCESS If reading serial buffer successfully, put
664 the fetched key to the parameter output.
668 GetOneKeyFromSerial (
669 EFI_SERIAL_IO_PROTOCOL
*SerialIo
,
680 // Read one key from serial I/O device.
682 Status
= SerialIo
->Read (SerialIo
, &Size
, Output
);
684 if (EFI_ERROR (Status
)) {
686 if (Status
== EFI_TIMEOUT
) {
687 return EFI_NOT_READY
;
690 return EFI_DEVICE_ERROR
;
695 return EFI_NOT_READY
;
702 Insert one byte raw data into the Raw Data FIFO.
704 @param TerminalDevice Terminal driver private structure.
705 @param Input The key will be input.
707 @retval TRUE If insert successfully.
708 @retval FALSE If Raw Data buffer is full before key insertion,
713 RawFiFoInsertOneKey (
714 TERMINAL_DEV
*TerminalDevice
,
720 Tail
= TerminalDevice
->RawFiFo
->Tail
;
722 if (IsRawFiFoFull (TerminalDevice
)) {
729 TerminalDevice
->RawFiFo
->Data
[Tail
] = Input
;
731 TerminalDevice
->RawFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
737 Remove one pre-fetched key out of the Raw Data FIFO.
739 @param TerminalDevice Terminal driver private structure.
740 @param Output The key will be removed.
742 @retval TRUE If insert successfully.
743 @retval FALSE If Raw Data FIFO buffer is empty before remove operation.
747 RawFiFoRemoveOneKey (
748 TERMINAL_DEV
*TerminalDevice
,
754 Head
= TerminalDevice
->RawFiFo
->Head
;
756 if (IsRawFiFoEmpty (TerminalDevice
)) {
764 *Output
= TerminalDevice
->RawFiFo
->Data
[Head
];
766 TerminalDevice
->RawFiFo
->Head
= (UINT8
) ((Head
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1));
772 Clarify whether Raw Data FIFO buffer is empty.
774 @param TerminalDevice Terminal driver private structure
776 @retval TRUE If Raw Data FIFO buffer is empty.
777 @retval FALSE If Raw Data FIFO buffer is not empty.
782 TERMINAL_DEV
*TerminalDevice
785 if (TerminalDevice
->RawFiFo
->Head
== TerminalDevice
->RawFiFo
->Tail
) {
793 Clarify whether Raw Data FIFO buffer is full.
795 @param TerminalDevice Terminal driver private structure
797 @retval TRUE If Raw Data FIFO buffer is full.
798 @retval FALSE If Raw Data FIFO buffer is not full.
803 TERMINAL_DEV
*TerminalDevice
809 Tail
= TerminalDevice
->RawFiFo
->Tail
;
810 Head
= TerminalDevice
->RawFiFo
->Head
;
812 if (((Tail
+ 1) % (RAW_FIFO_MAX_NUMBER
+ 1)) == Head
) {
821 Insert one pre-fetched key into the FIFO buffer.
823 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
824 @param Input The key will be input.
826 @retval TRUE If insert successfully.
827 @retval FALSE If FIFO buffer is full before key insertion,
832 EfiKeyFiFoForNotifyInsertOneKey (
833 EFI_KEY_FIFO
*EfiKeyFiFo
,
839 Tail
= EfiKeyFiFo
->Tail
;
841 if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo
)) {
848 CopyMem (&EfiKeyFiFo
->Data
[Tail
], Input
, sizeof (EFI_INPUT_KEY
));
850 EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
856 Remove one pre-fetched key out of the FIFO buffer.
858 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
859 @param Output The key will be removed.
861 @retval TRUE If remove successfully.
862 @retval FALSE If FIFO buffer is empty before remove operation.
866 EfiKeyFiFoForNotifyRemoveOneKey (
867 EFI_KEY_FIFO
*EfiKeyFiFo
,
868 EFI_INPUT_KEY
*Output
873 Head
= EfiKeyFiFo
->Head
;
874 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
876 if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo
)) {
880 Output
->ScanCode
= SCAN_NULL
;
881 Output
->UnicodeChar
= 0;
885 CopyMem (Output
, &EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
887 EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
893 Clarify whether FIFO buffer is empty.
895 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
897 @retval TRUE If FIFO buffer is empty.
898 @retval FALSE If FIFO buffer is not empty.
902 IsEfiKeyFiFoForNotifyEmpty (
903 EFI_KEY_FIFO
*EfiKeyFiFo
906 if (EfiKeyFiFo
->Head
== EfiKeyFiFo
->Tail
) {
914 Clarify whether FIFO buffer is full.
916 @param EfiKeyFiFo Pointer to instance of EFI_KEY_FIFO.
918 @retval TRUE If FIFO buffer is full.
919 @retval FALSE If FIFO buffer is not full.
923 IsEfiKeyFiFoForNotifyFull (
924 EFI_KEY_FIFO
*EfiKeyFiFo
930 Tail
= EfiKeyFiFo
->Tail
;
931 Head
= EfiKeyFiFo
->Head
;
933 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
941 Insert one pre-fetched key into the FIFO buffer.
943 @param TerminalDevice Terminal driver private structure.
944 @param Key The key will be input.
946 @retval TRUE If insert successfully.
947 @retval FALSE If FIFO buffer is full before key insertion,
952 EfiKeyFiFoInsertOneKey (
953 TERMINAL_DEV
*TerminalDevice
,
959 LIST_ENTRY
*NotifyList
;
960 TERMINAL_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
961 EFI_KEY_DATA KeyData
;
963 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
965 CopyMem (&KeyData
.Key
, Key
, sizeof (EFI_INPUT_KEY
));
966 KeyData
.KeyState
.KeyShiftState
= 0;
967 KeyData
.KeyState
.KeyToggleState
= 0;
970 // Signal KeyNotify process event if this key pressed matches any key registered.
972 NotifyList
= &TerminalDevice
->NotifyList
;
973 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
,Link
); Link
= GetNextNode (NotifyList
,Link
)) {
976 TERMINAL_CONSOLE_IN_EX_NOTIFY
,
978 TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
980 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
982 // The key notification function needs to run at TPL_CALLBACK
983 // while current TPL is TPL_NOTIFY. It will be invoked in
984 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
986 EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice
->EfiKeyFiFoForNotify
, Key
);
987 gBS
->SignalEvent (TerminalDevice
->KeyNotifyProcessEvent
);
991 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
993 // Efi Key FIFO is full
998 CopyMem (&TerminalDevice
->EfiKeyFiFo
->Data
[Tail
], Key
, sizeof (EFI_INPUT_KEY
));
1000 TerminalDevice
->EfiKeyFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1006 Remove one pre-fetched key out of the FIFO buffer.
1008 @param TerminalDevice Terminal driver private structure.
1009 @param Output The key will be removed.
1011 @retval TRUE If insert successfully.
1012 @retval FALSE If FIFO buffer is empty before remove operation.
1016 EfiKeyFiFoRemoveOneKey (
1017 TERMINAL_DEV
*TerminalDevice
,
1018 EFI_INPUT_KEY
*Output
1023 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1024 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1026 if (IsEfiKeyFiFoEmpty (TerminalDevice
)) {
1030 Output
->ScanCode
= SCAN_NULL
;
1031 Output
->UnicodeChar
= 0;
1035 CopyMem (Output
, &TerminalDevice
->EfiKeyFiFo
->Data
[Head
], sizeof (EFI_INPUT_KEY
));
1037 TerminalDevice
->EfiKeyFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1043 Clarify whether FIFO buffer is empty.
1045 @param TerminalDevice Terminal driver private structure
1047 @retval TRUE If FIFO buffer is empty.
1048 @retval FALSE If FIFO buffer is not empty.
1053 TERMINAL_DEV
*TerminalDevice
1056 if (TerminalDevice
->EfiKeyFiFo
->Head
== TerminalDevice
->EfiKeyFiFo
->Tail
) {
1064 Clarify whether FIFO buffer is full.
1066 @param TerminalDevice Terminal driver private structure
1068 @retval TRUE If FIFO buffer is full.
1069 @retval FALSE If FIFO buffer is not full.
1074 TERMINAL_DEV
*TerminalDevice
1080 Tail
= TerminalDevice
->EfiKeyFiFo
->Tail
;
1081 Head
= TerminalDevice
->EfiKeyFiFo
->Head
;
1083 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1092 Insert one pre-fetched key into the Unicode FIFO buffer.
1094 @param TerminalDevice Terminal driver private structure.
1095 @param Input The key will be input.
1097 @retval TRUE If insert successfully.
1098 @retval FALSE If Unicode FIFO buffer is full before key insertion,
1099 and the key is lost.
1103 UnicodeFiFoInsertOneKey (
1104 TERMINAL_DEV
*TerminalDevice
,
1110 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1111 ASSERT (Tail
< FIFO_MAX_NUMBER
+ 1);
1114 if (IsUnicodeFiFoFull (TerminalDevice
)) {
1116 // Unicode FIFO is full
1121 TerminalDevice
->UnicodeFiFo
->Data
[Tail
] = Input
;
1123 TerminalDevice
->UnicodeFiFo
->Tail
= (UINT8
) ((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1129 Remove one pre-fetched key out of the Unicode FIFO buffer.
1130 The caller should guarantee that Unicode FIFO buffer is not empty
1131 by IsUnicodeFiFoEmpty ().
1133 @param TerminalDevice Terminal driver private structure.
1134 @param Output The key will be removed.
1138 UnicodeFiFoRemoveOneKey (
1139 TERMINAL_DEV
*TerminalDevice
,
1145 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1146 ASSERT (Head
< FIFO_MAX_NUMBER
+ 1);
1148 *Output
= TerminalDevice
->UnicodeFiFo
->Data
[Head
];
1150 TerminalDevice
->UnicodeFiFo
->Head
= (UINT8
) ((Head
+ 1) % (FIFO_MAX_NUMBER
+ 1));
1154 Clarify whether Unicode FIFO buffer is empty.
1156 @param TerminalDevice Terminal driver private structure
1158 @retval TRUE If Unicode FIFO buffer is empty.
1159 @retval FALSE If Unicode FIFO buffer is not empty.
1163 IsUnicodeFiFoEmpty (
1164 TERMINAL_DEV
*TerminalDevice
1167 if (TerminalDevice
->UnicodeFiFo
->Head
== TerminalDevice
->UnicodeFiFo
->Tail
) {
1175 Clarify whether Unicode FIFO buffer is full.
1177 @param TerminalDevice Terminal driver private structure
1179 @retval TRUE If Unicode FIFO buffer is full.
1180 @retval FALSE If Unicode FIFO buffer is not full.
1185 TERMINAL_DEV
*TerminalDevice
1191 Tail
= TerminalDevice
->UnicodeFiFo
->Tail
;
1192 Head
= TerminalDevice
->UnicodeFiFo
->Head
;
1194 if (((Tail
+ 1) % (FIFO_MAX_NUMBER
+ 1)) == Head
) {
1204 Update the Unicode characters from a terminal input device into EFI Keys FIFO.
1206 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1210 UnicodeToEfiKeyFlushState (
1211 IN TERMINAL_DEV
*TerminalDevice
1217 InputState
= TerminalDevice
->InputState
;
1219 if (IsEfiKeyFiFoFull (TerminalDevice
)) {
1223 if ((InputState
& INPUT_STATE_ESC
) != 0) {
1224 Key
.ScanCode
= SCAN_ESC
;
1225 Key
.UnicodeChar
= 0;
1226 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1229 if ((InputState
& INPUT_STATE_CSI
) != 0) {
1230 Key
.ScanCode
= SCAN_NULL
;
1231 Key
.UnicodeChar
= CSI
;
1232 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1235 if ((InputState
& INPUT_STATE_LEFTOPENBRACKET
) != 0) {
1236 Key
.ScanCode
= SCAN_NULL
;
1237 Key
.UnicodeChar
= LEFTOPENBRACKET
;
1238 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1241 if ((InputState
& INPUT_STATE_O
) != 0) {
1242 Key
.ScanCode
= SCAN_NULL
;
1243 Key
.UnicodeChar
= 'O';
1244 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1247 if ((InputState
& INPUT_STATE_2
) != 0) {
1248 Key
.ScanCode
= SCAN_NULL
;
1249 Key
.UnicodeChar
= '2';
1250 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1254 // Cancel the timer.
1257 TerminalDevice
->TwoSecondTimeOut
,
1262 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1267 Converts a stream of Unicode characters from a terminal input device into EFI Keys that
1268 can be read through the Simple Input Protocol.
1270 The table below shows the keyboard input mappings that this function supports.
1271 If the ESC sequence listed in one of the columns is presented, then it is translated
1272 into the corresponding EFI Scan Code. If a matching sequence is not found, then the raw
1273 key strokes are converted into EFI Keys.
1275 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not
1276 completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
1277 converted into EFI Keys.
1278 There is one special input sequence that will force the system to reset.
1279 This is ESC R ESC r ESC R.
1281 Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
1282 The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
1283 DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
1285 Symbols used in table below
1286 ===========================
1292 +=========+======+===========+==========+==========+
1293 | | EFI | UEFI 2.0 | | |
1294 | | Scan | | VT100+ | |
1295 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
1296 +=========+======+===========+==========+==========+
1297 | NULL | 0x00 | | | |
1298 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
1299 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
1300 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
1301 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
1302 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
1303 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
1304 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
1305 | | | ESC [ L | | ESC [ L |
1306 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
1307 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
1309 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
1311 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
1312 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
1313 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
1314 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
1315 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
1316 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
1317 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
1318 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
1319 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
1320 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
1321 | Escape | 0x17 | ESC | ESC | ESC |
1322 | F11 | 0x15 | | ESC ! | |
1323 | F12 | 0x16 | | ESC @ | |
1324 +=========+======+===========+==========+==========+
1326 Putty function key map:
1327 +=========+======+===========+=============+=============+=============+=========+
1329 | | Scan | | | Normal | | |
1330 | KEY | Code | VT100+ | Xterm R6 | VT400 | Linux | SCO |
1331 +=========+======+===========+=============+=============+=============+=========+
1332 | F1 | 0x0B | ESC O P | ESC O P | ESC [ 1 1 ~ | ESC [ [ A | ESC [ M |
1333 | F2 | 0x0C | ESC O Q | ESC O Q | ESC [ 1 2 ~ | ESC [ [ B | ESC [ N |
1334 | F3 | 0x0D | ESC O R | ESC O R | ESC [ 1 3 ~ | ESC [ [ C | ESC [ O |
1335 | F4 | 0x0E | ESC O S | ESC O S | ESC [ 1 4 ~ | ESC [ [ D | ESC [ P |
1336 | F5 | 0x0F | ESC O T | ESC [ 1 5 ~ | ESC [ 1 5 ~ | ESC [ [ E | ESC [ Q |
1337 | F6 | 0x10 | ESC O U | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ R |
1338 | F7 | 0x11 | ESC O V | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ S |
1339 | F8 | 0x12 | ESC O W | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ T |
1340 | F9 | 0x13 | ESC O X | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ U |
1341 | F10 | 0x14 | ESC O Y | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ V |
1342 | Escape | 0x17 | ESC | ESC | ESC | ESC | ESC |
1343 | F11 | 0x15 | ESC O Z | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ W |
1344 | F12 | 0x16 | ESC O [ | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ X |
1345 +=========+======+===========+=============+=============+=============+=========+
1349 ESC R ESC r ESC R = Reset System
1351 @param TerminalDevice The terminal device to use to translate raw input into EFI Keys
1356 IN TERMINAL_DEV
*TerminalDevice
1360 EFI_STATUS TimerStatus
;
1363 BOOLEAN SetDefaultResetState
;
1365 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1367 if (!EFI_ERROR (TimerStatus
)) {
1368 UnicodeToEfiKeyFlushState (TerminalDevice
);
1369 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1372 while (!IsUnicodeFiFoEmpty (TerminalDevice
) && !IsEfiKeyFiFoFull (TerminalDevice
)) {
1374 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
1376 // Check to see if the 2 seconds timer has expired
1378 TimerStatus
= gBS
->CheckEvent (TerminalDevice
->TwoSecondTimeOut
);
1379 if (!EFI_ERROR (TimerStatus
)) {
1380 UnicodeToEfiKeyFlushState (TerminalDevice
);
1381 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1386 // Fetch one Unicode character from the Unicode FIFO
1388 UnicodeFiFoRemoveOneKey (TerminalDevice
, &UnicodeChar
);
1390 SetDefaultResetState
= TRUE
;
1392 switch (TerminalDevice
->InputState
) {
1393 case INPUT_STATE_DEFAULT
:
1397 case INPUT_STATE_ESC
:
1399 if (UnicodeChar
== LEFTOPENBRACKET
) {
1400 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET
;
1401 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1405 if (UnicodeChar
== 'O' && (TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1406 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
||
1407 TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1408 TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
)) {
1409 TerminalDevice
->InputState
|= INPUT_STATE_O
;
1410 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1414 Key
.ScanCode
= SCAN_NULL
;
1416 if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1417 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
) {
1418 switch (UnicodeChar
) {
1420 Key
.ScanCode
= SCAN_F1
;
1423 Key
.ScanCode
= SCAN_F2
;
1426 Key
.ScanCode
= SCAN_F3
;
1429 Key
.ScanCode
= SCAN_F4
;
1432 Key
.ScanCode
= SCAN_F5
;
1435 Key
.ScanCode
= SCAN_F6
;
1438 Key
.ScanCode
= SCAN_F7
;
1441 Key
.ScanCode
= SCAN_F8
;
1444 Key
.ScanCode
= SCAN_F9
;
1447 Key
.ScanCode
= SCAN_F10
;
1450 Key
.ScanCode
= SCAN_F11
;
1453 Key
.ScanCode
= SCAN_F12
;
1456 Key
.ScanCode
= SCAN_HOME
;
1459 Key
.ScanCode
= SCAN_END
;
1462 Key
.ScanCode
= SCAN_INSERT
;
1465 Key
.ScanCode
= SCAN_DELETE
;
1468 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1471 Key
.ScanCode
= SCAN_PAGE_UP
;
1478 switch (UnicodeChar
) {
1480 if (TerminalDevice
->ResetState
== RESET_STATE_DEFAULT
) {
1481 TerminalDevice
->ResetState
= RESET_STATE_ESC_R
;
1482 SetDefaultResetState
= FALSE
;
1483 } else if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R_ESC_R
) {
1484 gRT
->ResetSystem (EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
1486 Key
.ScanCode
= SCAN_NULL
;
1489 if (TerminalDevice
->ResetState
== RESET_STATE_ESC_R
) {
1490 TerminalDevice
->ResetState
= RESET_STATE_ESC_R_ESC_R
;
1491 SetDefaultResetState
= FALSE
;
1493 Key
.ScanCode
= SCAN_NULL
;
1499 if (SetDefaultResetState
) {
1500 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1503 if (Key
.ScanCode
!= SCAN_NULL
) {
1504 Key
.UnicodeChar
= 0;
1505 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1506 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1507 UnicodeToEfiKeyFlushState (TerminalDevice
);
1511 UnicodeToEfiKeyFlushState (TerminalDevice
);
1515 case INPUT_STATE_ESC
| INPUT_STATE_O
:
1517 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1519 Key
.ScanCode
= SCAN_NULL
;
1521 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1522 switch (UnicodeChar
) {
1524 Key
.ScanCode
= SCAN_F1
;
1527 Key
.ScanCode
= SCAN_F2
;
1530 Key
.ScanCode
= SCAN_F3
;
1533 Key
.ScanCode
= SCAN_F4
;
1536 Key
.ScanCode
= SCAN_F5
;
1539 Key
.ScanCode
= SCAN_F6
;
1542 Key
.ScanCode
= SCAN_F7
;
1545 Key
.ScanCode
= SCAN_F8
;
1548 Key
.ScanCode
= SCAN_F9
;
1551 Key
.ScanCode
= SCAN_F10
;
1556 } else if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1557 /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
1558 switch (UnicodeChar
) {
1560 Key
.ScanCode
= SCAN_F1
;
1563 Key
.ScanCode
= SCAN_F2
;
1566 Key
.ScanCode
= SCAN_F3
;
1569 Key
.ScanCode
= SCAN_F4
;
1572 Key
.ScanCode
= SCAN_HOME
;
1575 Key
.ScanCode
= SCAN_END
;
1578 } else if (TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
) {
1579 switch (UnicodeChar
) {
1581 Key
.ScanCode
= SCAN_F1
;
1584 Key
.ScanCode
= SCAN_F2
;
1587 Key
.ScanCode
= SCAN_F3
;
1590 Key
.ScanCode
= SCAN_F4
;
1593 Key
.ScanCode
= SCAN_F5
;
1596 Key
.ScanCode
= SCAN_F6
;
1599 Key
.ScanCode
= SCAN_F7
;
1602 Key
.ScanCode
= SCAN_F8
;
1605 Key
.ScanCode
= SCAN_F9
;
1608 Key
.ScanCode
= SCAN_F10
;
1611 Key
.ScanCode
= SCAN_F11
;
1614 Key
.ScanCode
= SCAN_F12
;
1617 } else if (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
) {
1618 switch (UnicodeChar
) {
1620 Key
.ScanCode
= SCAN_F1
;
1623 Key
.ScanCode
= SCAN_F2
;
1626 Key
.ScanCode
= SCAN_F3
;
1629 Key
.ScanCode
= SCAN_F4
;
1634 if (Key
.ScanCode
!= SCAN_NULL
) {
1635 Key
.UnicodeChar
= 0;
1636 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1637 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1638 UnicodeToEfiKeyFlushState (TerminalDevice
);
1642 UnicodeToEfiKeyFlushState (TerminalDevice
);
1646 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
:
1648 if (UnicodeChar
== '1' && (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1649 TerminalDevice
->TerminalType
== TerminalTypeVt400
||
1650 TerminalDevice
->TerminalType
== TerminalTypeLinux
)) {
1651 TerminalDevice
->InputState
|= INPUT_STATE_1
;
1655 if (UnicodeChar
== '2' && (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1656 TerminalDevice
->TerminalType
== TerminalTypeVt400
||
1657 TerminalDevice
->TerminalType
== TerminalTypeLinux
)) {
1658 TerminalDevice
->InputState
|= INPUT_STATE_2
;
1662 if (UnicodeChar
== LEFTOPENBRACKET
&& TerminalDevice
->TerminalType
== TerminalTypeLinux
) {
1663 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_2ND
;
1667 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1669 Key
.ScanCode
= SCAN_NULL
;
1671 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1672 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1673 TerminalDevice
->TerminalType
== TerminalTypeVt100Plus
||
1674 TerminalDevice
->TerminalType
== TerminalTypeVtUtf8
||
1675 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
||
1676 TerminalDevice
->TerminalType
== TerminalTypeLinux
||
1677 TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1678 TerminalDevice
->TerminalType
== TerminalTypeVt400
||
1679 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1680 switch (UnicodeChar
) {
1682 Key
.ScanCode
= SCAN_UP
;
1685 Key
.ScanCode
= SCAN_DOWN
;
1688 Key
.ScanCode
= SCAN_RIGHT
;
1691 Key
.ScanCode
= SCAN_LEFT
;
1694 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1695 TerminalDevice
->TerminalType
== TerminalTypeVt100
||
1696 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1697 Key
.ScanCode
= SCAN_HOME
;
1701 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1702 TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1703 Key
.ScanCode
= SCAN_END
;
1707 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1708 Key
.ScanCode
= SCAN_END
;
1713 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1714 TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1715 Key
.ScanCode
= SCAN_INSERT
;
1719 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1720 Key
.ScanCode
= SCAN_DELETE
;
1721 } else if (TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1722 Key
.ScanCode
= SCAN_F12
;
1726 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1727 Key
.ScanCode
= SCAN_DELETE
;
1728 } else if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1729 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1730 Key
.ScanCode
= SCAN_F4
;
1734 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1735 Key
.ScanCode
= SCAN_PAGE_UP
;
1739 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1740 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1741 Key
.ScanCode
= SCAN_F10
;
1745 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1746 Key
.ScanCode
= SCAN_PAGE_UP
;
1750 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
) {
1751 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1755 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1756 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1757 Key
.ScanCode
= SCAN_F9
;
1761 if (TerminalDevice
->TerminalType
== TerminalTypeVt100
) {
1762 Key
.ScanCode
= SCAN_PAGE_DOWN
;
1766 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1767 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1768 Key
.ScanCode
= SCAN_F1
;
1772 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1773 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1774 Key
.ScanCode
= SCAN_F2
;
1778 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1779 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1780 Key
.ScanCode
= SCAN_F3
;
1784 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1785 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1786 Key
.ScanCode
= SCAN_F5
;
1790 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1791 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1792 Key
.ScanCode
= SCAN_F6
;
1796 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1797 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1798 Key
.ScanCode
= SCAN_F7
;
1802 if (TerminalDevice
->TerminalType
== TerminalTypePcAnsi
||
1803 TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1804 Key
.ScanCode
= SCAN_F8
;
1808 if (TerminalDevice
->TerminalType
== TerminalTypeSCO
) {
1809 Key
.ScanCode
= SCAN_F11
;
1818 * The VT220 escape codes that the TTY terminal accepts all have
1819 * numeric codes, and there are no ambiguous prefixes shared with
1820 * other terminal types.
1822 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
&&
1823 Key
.ScanCode
== SCAN_NULL
&&
1824 UnicodeChar
>= '0' &&
1825 UnicodeChar
<= '9') {
1826 TerminalDevice
->TtyEscapeStr
[0] = UnicodeChar
;
1827 TerminalDevice
->TtyEscapeIndex
= 1;
1828 TerminalDevice
->InputState
|= INPUT_STATE_LEFTOPENBRACKET_TTY
;
1832 if (Key
.ScanCode
!= SCAN_NULL
) {
1833 Key
.UnicodeChar
= 0;
1834 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1835 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1836 UnicodeToEfiKeyFlushState (TerminalDevice
);
1840 UnicodeToEfiKeyFlushState (TerminalDevice
);
1844 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_1
:
1846 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
1848 Key
.ScanCode
= SCAN_NULL
;
1850 if (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1851 TerminalDevice
->TerminalType
== TerminalTypeVt400
||
1852 TerminalDevice
->TerminalType
== TerminalTypeLinux
) {
1853 switch (UnicodeChar
) {
1855 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1856 Key
.ScanCode
= SCAN_F1
;
1860 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1861 Key
.ScanCode
= SCAN_F2
;
1865 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1866 Key
.ScanCode
= SCAN_F3
;
1870 if (TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1871 Key
.ScanCode
= SCAN_F4
;
1875 if (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1876 TerminalDevice
->TerminalType
== TerminalTypeVt400
) {
1877 Key
.ScanCode
= SCAN_F5
;
1881 Key
.ScanCode
= SCAN_F6
;
1884 Key
.ScanCode
= SCAN_F7
;
1887 Key
.ScanCode
= SCAN_F8
;
1892 if (Key
.ScanCode
!= SCAN_NULL
) {
1893 Key
.UnicodeChar
= 0;
1894 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1895 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1896 UnicodeToEfiKeyFlushState (TerminalDevice
);
1900 UnicodeToEfiKeyFlushState (TerminalDevice
);
1904 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_2
:
1906 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1907 Key
.ScanCode
= SCAN_NULL
;
1908 if (TerminalDevice
->TerminalType
== TerminalTypeXtermR6
||
1909 TerminalDevice
->TerminalType
== TerminalTypeVt400
||
1910 TerminalDevice
->TerminalType
== TerminalTypeLinux
) {
1911 switch (UnicodeChar
) {
1913 Key
.ScanCode
= SCAN_F9
;
1916 Key
.ScanCode
= SCAN_F10
;
1919 Key
.ScanCode
= SCAN_F11
;
1922 Key
.ScanCode
= SCAN_F12
;
1927 if (Key
.ScanCode
!= SCAN_NULL
) {
1928 Key
.UnicodeChar
= 0;
1929 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1930 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1931 UnicodeToEfiKeyFlushState (TerminalDevice
);
1935 UnicodeToEfiKeyFlushState (TerminalDevice
);
1939 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_2ND
:
1941 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1942 Key
.ScanCode
= SCAN_NULL
;
1944 if (TerminalDevice
->TerminalType
== TerminalTypeLinux
) {
1945 switch (UnicodeChar
) {
1947 Key
.ScanCode
= SCAN_F1
;
1950 Key
.ScanCode
= SCAN_F2
;
1953 Key
.ScanCode
= SCAN_F3
;
1956 Key
.ScanCode
= SCAN_F4
;
1959 Key
.ScanCode
= SCAN_F5
;
1964 if (Key
.ScanCode
!= SCAN_NULL
) {
1965 Key
.UnicodeChar
= 0;
1966 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
1967 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
1968 UnicodeToEfiKeyFlushState (TerminalDevice
);
1972 UnicodeToEfiKeyFlushState (TerminalDevice
);
1976 case INPUT_STATE_ESC
| INPUT_STATE_LEFTOPENBRACKET
| INPUT_STATE_LEFTOPENBRACKET_TTY
:
1978 * Here we handle the VT220 escape codes that we accept. This
1979 * state is only used by the TTY terminal type.
1981 Key
.ScanCode
= SCAN_NULL
;
1982 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
1984 if (UnicodeChar
== '~' && TerminalDevice
->TtyEscapeIndex
<= 2) {
1986 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
] = 0; /* Terminate string */
1987 EscCode
= (UINT16
) StrDecimalToUintn(TerminalDevice
->TtyEscapeStr
);
1990 Key
.ScanCode
= SCAN_INSERT
;
1993 Key
.ScanCode
= SCAN_DELETE
;
1996 Key
.ScanCode
= SCAN_PAGE_UP
;
1999 Key
.ScanCode
= SCAN_PAGE_DOWN
;
2006 Key
.ScanCode
= SCAN_F1
+ EscCode
- 11;
2013 Key
.ScanCode
= SCAN_F6
+ EscCode
- 17;
2017 Key
.ScanCode
= SCAN_F11
+ EscCode
- 23;
2022 } else if (TerminalDevice
->TtyEscapeIndex
== 1){
2023 /* 2 character escape code */
2024 TerminalDevice
->TtyEscapeStr
[TerminalDevice
->TtyEscapeIndex
++] = UnicodeChar
;
2028 DEBUG ((EFI_D_ERROR
, "Unexpected state in escape2\n"));
2031 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
2033 if (Key
.ScanCode
!= SCAN_NULL
) {
2034 Key
.UnicodeChar
= 0;
2035 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);
2036 TerminalDevice
->InputState
= INPUT_STATE_DEFAULT
;
2037 UnicodeToEfiKeyFlushState (TerminalDevice
);
2041 UnicodeToEfiKeyFlushState (TerminalDevice
);
2046 // Invalid state. This should never happen.
2050 UnicodeToEfiKeyFlushState (TerminalDevice
);
2055 if (UnicodeChar
== ESC
) {
2056 TerminalDevice
->InputState
= INPUT_STATE_ESC
;
2059 if (UnicodeChar
== CSI
) {
2060 TerminalDevice
->InputState
= INPUT_STATE_CSI
;
2063 if (TerminalDevice
->InputState
!= INPUT_STATE_DEFAULT
) {
2064 Status
= gBS
->SetTimer(
2065 TerminalDevice
->TwoSecondTimeOut
,
2069 ASSERT_EFI_ERROR (Status
);
2073 if (SetDefaultResetState
) {
2074 TerminalDevice
->ResetState
= RESET_STATE_DEFAULT
;
2077 if (UnicodeChar
== DEL
) {
2078 if (TerminalDevice
->TerminalType
== TerminalTypeTtyTerm
) {
2079 Key
.ScanCode
= SCAN_NULL
;
2080 Key
.UnicodeChar
= CHAR_BACKSPACE
;
2083 Key
.ScanCode
= SCAN_DELETE
;
2084 Key
.UnicodeChar
= 0;
2087 Key
.ScanCode
= SCAN_NULL
;
2088 Key
.UnicodeChar
= UnicodeChar
;
2091 EfiKeyFiFoInsertOneKey (TerminalDevice
, &Key
);