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