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