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