REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			2123 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2123 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
 | 
						|
 | 
						|
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 | 
						|
Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Terminal.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Reads the next keystroke from the input device. The WaitForKey Event can
 | 
						|
  be used to test for existence of a keystroke via WaitForEvent () call.
 | 
						|
 | 
						|
  @param  TerminalDevice           Terminal driver private structure
 | 
						|
  @param  KeyData                  A pointer to a buffer that is filled in with the
 | 
						|
                                   keystroke state data for the key that was
 | 
						|
                                   pressed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The keystroke information was returned.
 | 
						|
  @retval EFI_NOT_READY            There was no keystroke data available.
 | 
						|
  @retval EFI_INVALID_PARAMETER    KeyData is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ReadKeyStrokeWorker (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice,
 | 
						|
  OUT EFI_KEY_DATA  *KeyData
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (KeyData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  KeyData->KeyState.KeyShiftState  = 0;
 | 
						|
  KeyData->KeyState.KeyToggleState = 0;
 | 
						|
 | 
						|
  if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.Reset().
 | 
						|
  This driver only perform dependent serial device reset regardless of
 | 
						|
  the value of ExtendeVerification
 | 
						|
 | 
						|
  @param  This                     Indicates the calling context.
 | 
						|
  @param  ExtendedVerification     Skip by this driver.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The reset operation succeeds.
 | 
						|
  @retval EFI_DEVICE_ERROR         The dependent serial port reset fails.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInReset (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | 
						|
  IN  BOOLEAN                         ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  TERMINAL_DEV  *TerminalDevice;
 | 
						|
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Report progress code here
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
 | 
						|
    TerminalDevice->DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
 | 
						|
 | 
						|
  //
 | 
						|
  // Make all the internal buffer empty for keys
 | 
						|
  //
 | 
						|
  TerminalDevice->RawFiFo->Head             = TerminalDevice->RawFiFo->Tail;
 | 
						|
  TerminalDevice->UnicodeFiFo->Head         = TerminalDevice->UnicodeFiFo->Tail;
 | 
						|
  TerminalDevice->EfiKeyFiFo->Head          = TerminalDevice->EfiKeyFiFo->Tail;
 | 
						|
  TerminalDevice->EfiKeyFiFoForNotify->Head = TerminalDevice->EfiKeyFiFoForNotify->Tail;
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
 | 
						|
      TerminalDevice->DevicePath
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke().
 | 
						|
 | 
						|
  @param  This                Indicates the calling context.
 | 
						|
  @param  Key                 A pointer to a buffer that is filled in with the
 | 
						|
                              keystroke information for the key that was sent
 | 
						|
                              from terminal.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         The keystroke information is returned successfully.
 | 
						|
  @retval EFI_NOT_READY       There is no keystroke data available.
 | 
						|
  @retval EFI_DEVICE_ERROR    The dependent serial device encounters error.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInReadKeyStroke (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | 
						|
  OUT EFI_INPUT_KEY                   *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  TERMINAL_DEV  *TerminalDevice;
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  EFI_KEY_DATA  KeyData;
 | 
						|
 | 
						|
  //
 | 
						|
  //  get TERMINAL_DEV from "This" parameter.
 | 
						|
  //
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  Status = ReadKeyStrokeWorker (TerminalDevice, &KeyData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if the key already has been registered.
 | 
						|
 | 
						|
  If both RegsiteredData and InputData is NULL, then ASSERT().
 | 
						|
 | 
						|
  @param  RegsiteredData           A pointer to a buffer that is filled in with the
 | 
						|
                                   keystroke state data for the key that was
 | 
						|
                                   registered.
 | 
						|
  @param  InputData                A pointer to a buffer that is filled in with the
 | 
						|
                                   keystroke state data for the key that was
 | 
						|
                                   pressed.
 | 
						|
 | 
						|
  @retval TRUE                     Key be pressed matches a registered key.
 | 
						|
  @retval FALSE                    Match failed.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsKeyRegistered (
 | 
						|
  IN EFI_KEY_DATA  *RegsiteredData,
 | 
						|
  IN EFI_KEY_DATA  *InputData
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (RegsiteredData != NULL && InputData != NULL);
 | 
						|
 | 
						|
  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
 | 
						|
      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar))
 | 
						|
  {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification function for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
 | 
						|
  Signal the event if there is key available
 | 
						|
 | 
						|
  @param  Event                    Indicates the event that invoke this function.
 | 
						|
  @param  Context                  Indicates the calling context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
TerminalConInWaitForKeyEx (
 | 
						|
  IN  EFI_EVENT  Event,
 | 
						|
  IN  VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  TerminalConInWaitForKey (Event, Context);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Simple Text Input Ex protocol functions
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Reset the input device and optionally run diagnostics
 | 
						|
 | 
						|
  @param  This                     Protocol instance pointer.
 | 
						|
  @param  ExtendedVerification     Driver may perform diagnostics on reset.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The device was reset.
 | 
						|
  @retval EFI_DEVICE_ERROR         The device is not functioning properly and could
 | 
						|
                                   not be reset.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInResetEx (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                            ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  TERMINAL_DEV  *TerminalDevice;
 | 
						|
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  Status = TerminalDevice->SimpleInput.Reset (&TerminalDevice->SimpleInput, ExtendedVerification);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Reads the next keystroke from the input device. The WaitForKey Event can
 | 
						|
  be used to test for existence of a keystroke via WaitForEvent () call.
 | 
						|
 | 
						|
  @param  This                     Protocol instance pointer.
 | 
						|
  @param  KeyData                  A pointer to a buffer that is filled in with the
 | 
						|
                                   keystroke state data for the key that was
 | 
						|
                                   pressed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The keystroke information was returned.
 | 
						|
  @retval EFI_NOT_READY            There was no keystroke data available.
 | 
						|
  @retval EFI_DEVICE_ERROR         The keystroke information was not returned due
 | 
						|
                                   to hardware errors.
 | 
						|
  @retval EFI_INVALID_PARAMETER    KeyData is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInReadKeyStrokeEx (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  OUT EFI_KEY_DATA                       *KeyData
 | 
						|
  )
 | 
						|
{
 | 
						|
  TERMINAL_DEV  *TerminalDevice;
 | 
						|
 | 
						|
  if (KeyData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  return ReadKeyStrokeWorker (TerminalDevice, KeyData);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set certain state for the input device.
 | 
						|
 | 
						|
  @param  This                     Protocol instance pointer.
 | 
						|
  @param  KeyToggleState           A pointer to the EFI_KEY_TOGGLE_STATE to set the
 | 
						|
                                   state for the input device.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The device state was set successfully.
 | 
						|
  @retval EFI_DEVICE_ERROR         The device is not functioning correctly and
 | 
						|
                                   could not have the setting adjusted.
 | 
						|
  @retval EFI_UNSUPPORTED          The device does not have the ability to set its
 | 
						|
                                   state.
 | 
						|
  @retval EFI_INVALID_PARAMETER    KeyToggleState is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInSetState (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (KeyToggleState == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Register a notification function for a particular keystroke for the input device.
 | 
						|
 | 
						|
  @param  This                     Protocol instance pointer.
 | 
						|
  @param  KeyData                  A pointer to a buffer that is filled in with
 | 
						|
                                   the keystroke information for the key that was
 | 
						|
                                   pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
 | 
						|
                                   and KeyData.KeyState.KeyShiftState are 0, then any incomplete
 | 
						|
                                   keystroke will trigger a notification of the KeyNotificationFunction.
 | 
						|
  @param  KeyNotificationFunction  Points to the function to be called when the key
 | 
						|
                                   sequence is typed specified by KeyData. This notification function
 | 
						|
                                   should be called at <=TPL_CALLBACK.
 | 
						|
  @param  NotifyHandle             Points to the unique handle assigned to the
 | 
						|
                                   registered notification.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The notification function was registered
 | 
						|
                                   successfully.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES     Unable to allocate resources for necessary data
 | 
						|
                                   structures.
 | 
						|
  @retval EFI_INVALID_PARAMETER    KeyData or NotifyHandle is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInRegisterKeyNotify (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN EFI_KEY_DATA                       *KeyData,
 | 
						|
  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
 | 
						|
  OUT VOID                              **NotifyHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  TERMINAL_DEV                   *TerminalDevice;
 | 
						|
  TERMINAL_CONSOLE_IN_EX_NOTIFY  *NewNotify;
 | 
						|
  LIST_ENTRY                     *Link;
 | 
						|
  LIST_ENTRY                     *NotifyList;
 | 
						|
  TERMINAL_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | 
						|
 | 
						|
  if ((KeyData == NULL) || (NotifyHandle == NULL) || (KeyNotificationFunction == NULL)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
 | 
						|
  //
 | 
						|
  NotifyList = &TerminalDevice->NotifyList;
 | 
						|
  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
 | 
						|
      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
 | 
						|
        *NotifyHandle = CurrentNotify;
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate resource to save the notification function
 | 
						|
  //
 | 
						|
  NewNotify = (TERMINAL_CONSOLE_IN_EX_NOTIFY *)AllocateZeroPool (sizeof (TERMINAL_CONSOLE_IN_EX_NOTIFY));
 | 
						|
  if (NewNotify == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  NewNotify->Signature         = TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
 | 
						|
  NewNotify->KeyNotificationFn = KeyNotificationFunction;
 | 
						|
  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
 | 
						|
  InsertTailList (&TerminalDevice->NotifyList, &NewNotify->NotifyEntry);
 | 
						|
 | 
						|
  *NotifyHandle = NewNotify;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove a registered notification function from a particular keystroke.
 | 
						|
 | 
						|
  @param  This                     Protocol instance pointer.
 | 
						|
  @param  NotificationHandle       The handle of the notification function being
 | 
						|
                                   unregistered.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS              The notification function was unregistered
 | 
						|
                                   successfully.
 | 
						|
  @retval EFI_INVALID_PARAMETER    The NotificationHandle is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TerminalConInUnregisterKeyNotify (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN VOID                               *NotificationHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  TERMINAL_DEV                   *TerminalDevice;
 | 
						|
  LIST_ENTRY                     *Link;
 | 
						|
  TERMINAL_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | 
						|
  LIST_ENTRY                     *NotifyList;
 | 
						|
 | 
						|
  if (NotificationHandle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  NotifyList = &TerminalDevice->NotifyList;
 | 
						|
  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (CurrentNotify == NotificationHandle) {
 | 
						|
      //
 | 
						|
      // Remove the notification function from NotifyList and free resources
 | 
						|
      //
 | 
						|
      RemoveEntryList (&CurrentNotify->NotifyEntry);
 | 
						|
 | 
						|
      gBS->FreePool (CurrentNotify);
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Can not find the matching entry in database.
 | 
						|
  //
 | 
						|
  return EFI_INVALID_PARAMETER;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Translate raw data into Unicode (according to different encode), and
 | 
						|
  translate Unicode into key information. (according to different standard).
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
TranslateRawDataToEfiKey (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  switch (TerminalDevice->TerminalType) {
 | 
						|
    case TerminalTypePcAnsi:
 | 
						|
    case TerminalTypeVt100:
 | 
						|
    case TerminalTypeVt100Plus:
 | 
						|
    case TerminalTypeTtyTerm:
 | 
						|
    case TerminalTypeLinux:
 | 
						|
    case TerminalTypeXtermR6:
 | 
						|
    case TerminalTypeVt400:
 | 
						|
    case TerminalTypeSCO:
 | 
						|
      AnsiRawDataToUnicode (TerminalDevice);
 | 
						|
      UnicodeToEfiKey (TerminalDevice);
 | 
						|
      break;
 | 
						|
 | 
						|
    case TerminalTypeVtUtf8:
 | 
						|
      //
 | 
						|
      // Process all the raw data in the RawFIFO,
 | 
						|
      // put the processed key into UnicodeFIFO.
 | 
						|
      //
 | 
						|
      VTUTF8RawDataToUnicode (TerminalDevice);
 | 
						|
 | 
						|
      //
 | 
						|
      // Translate all the Unicode data in the UnicodeFIFO to Efi key,
 | 
						|
      // then put into EfiKeyFIFO.
 | 
						|
      //
 | 
						|
      UnicodeToEfiKey (TerminalDevice);
 | 
						|
 | 
						|
      break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
 | 
						|
  Signal the event if there is key available
 | 
						|
 | 
						|
  @param  Event                    Indicates the event that invoke this function.
 | 
						|
  @param  Context                  Indicates the calling context.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
TerminalConInWaitForKey (
 | 
						|
  IN  EFI_EVENT  Event,
 | 
						|
  IN  VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Someone is waiting on the keystroke event, if there's
 | 
						|
  // a key pending, signal the event
 | 
						|
  //
 | 
						|
  if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *)Context)) {
 | 
						|
    gBS->SignalEvent (Event);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Timer handler to poll the key from serial.
 | 
						|
 | 
						|
  @param  Event                    Indicates the event that invoke this function.
 | 
						|
  @param  Context                  Indicates the calling context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
TerminalConInTimerHandler (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  TERMINAL_DEV            *TerminalDevice;
 | 
						|
  UINT32                  Control;
 | 
						|
  UINT8                   Input;
 | 
						|
  EFI_SERIAL_IO_MODE      *Mode;
 | 
						|
  EFI_SERIAL_IO_PROTOCOL  *SerialIo;
 | 
						|
  UINTN                   SerialInTimeOut;
 | 
						|
 | 
						|
  TerminalDevice = (TERMINAL_DEV *)Context;
 | 
						|
 | 
						|
  SerialIo = TerminalDevice->SerialIo;
 | 
						|
  if (SerialIo == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  //  if current timeout value for serial device is not identical with
 | 
						|
  //  the value saved in TERMINAL_DEV structure, then recalculate the
 | 
						|
  //  timeout value again and set serial attribute according to this value.
 | 
						|
  //
 | 
						|
  Mode = SerialIo->Mode;
 | 
						|
  if (Mode->Timeout != TerminalDevice->SerialInTimeOut) {
 | 
						|
    SerialInTimeOut = 0;
 | 
						|
    if (Mode->BaudRate != 0) {
 | 
						|
      //
 | 
						|
      // According to BAUD rate to calculate the timeout value.
 | 
						|
      //
 | 
						|
      SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN)Mode->BaudRate;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = SerialIo->SetAttributes (
 | 
						|
                         SerialIo,
 | 
						|
                         Mode->BaudRate,
 | 
						|
                         Mode->ReceiveFifoDepth,
 | 
						|
                         (UINT32)SerialInTimeOut,
 | 
						|
                         (EFI_PARITY_TYPE)(Mode->Parity),
 | 
						|
                         (UINT8)Mode->DataBits,
 | 
						|
                         (EFI_STOP_BITS_TYPE)(Mode->StopBits)
 | 
						|
                         );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      TerminalDevice->SerialInTimeOut = 0;
 | 
						|
    } else {
 | 
						|
      TerminalDevice->SerialInTimeOut = SerialInTimeOut;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether serial buffer is empty.
 | 
						|
  // Skip the key transfer loop only if the SerialIo protocol instance
 | 
						|
  // successfully reports EFI_SERIAL_INPUT_BUFFER_EMPTY.
 | 
						|
  //
 | 
						|
  Status = SerialIo->GetControl (SerialIo, &Control);
 | 
						|
  if (EFI_ERROR (Status) || ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) == 0)) {
 | 
						|
    //
 | 
						|
    // Fetch all the keys in the serial buffer,
 | 
						|
    // and insert the byte stream into RawFIFO.
 | 
						|
    //
 | 
						|
    while (!IsRawFiFoFull (TerminalDevice)) {
 | 
						|
      Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input);
 | 
						|
 | 
						|
      if (EFI_ERROR (Status)) {
 | 
						|
        if (Status == EFI_DEVICE_ERROR) {
 | 
						|
          REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
            EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
            (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR),
 | 
						|
            TerminalDevice->DevicePath
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      RawFiFoInsertOneKey (TerminalDevice, Input);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Translate all the raw data in RawFIFO into EFI Key,
 | 
						|
  // according to different terminal type supported.
 | 
						|
  //
 | 
						|
  TranslateRawDataToEfiKey (TerminalDevice);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process key notify.
 | 
						|
 | 
						|
  @param  Event                 Indicates the event that invoke this function.
 | 
						|
  @param  Context               Indicates the calling context.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KeyNotifyProcessHandler (
 | 
						|
  IN  EFI_EVENT  Event,
 | 
						|
  IN  VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN                        HasKey;
 | 
						|
  TERMINAL_DEV                   *TerminalDevice;
 | 
						|
  EFI_INPUT_KEY                  Key;
 | 
						|
  EFI_KEY_DATA                   KeyData;
 | 
						|
  LIST_ENTRY                     *Link;
 | 
						|
  LIST_ENTRY                     *NotifyList;
 | 
						|
  TERMINAL_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | 
						|
  EFI_TPL                        OldTpl;
 | 
						|
 | 
						|
  TerminalDevice = (TERMINAL_DEV *)Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Invoke notification functions.
 | 
						|
  //
 | 
						|
  NotifyList = &TerminalDevice->NotifyList;
 | 
						|
  while (TRUE) {
 | 
						|
    //
 | 
						|
    // Enter critical section
 | 
						|
    //
 | 
						|
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
    HasKey = EfiKeyFiFoForNotifyRemoveOneKey (TerminalDevice->EfiKeyFiFoForNotify, &Key);
 | 
						|
    CopyMem (&KeyData.Key, &Key, sizeof (EFI_INPUT_KEY));
 | 
						|
    KeyData.KeyState.KeyShiftState  = 0;
 | 
						|
    KeyData.KeyState.KeyToggleState = 0;
 | 
						|
    //
 | 
						|
    // Leave critical section
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
    if (!HasKey) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | 
						|
      CurrentNotify = CR (Link, TERMINAL_CONSOLE_IN_EX_NOTIFY, NotifyEntry, TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
 | 
						|
      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
 | 
						|
        CurrentNotify->KeyNotificationFn (&KeyData);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get one key out of serial buffer.
 | 
						|
 | 
						|
  @param  SerialIo           Serial I/O protocol attached to the serial device.
 | 
						|
  @param  Output             The fetched key.
 | 
						|
 | 
						|
  @retval EFI_NOT_READY      If serial buffer is empty.
 | 
						|
  @retval EFI_DEVICE_ERROR   If reading serial buffer encounter error.
 | 
						|
  @retval EFI_SUCCESS        If reading serial buffer successfully, put
 | 
						|
                             the fetched key to the parameter output.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetOneKeyFromSerial (
 | 
						|
  EFI_SERIAL_IO_PROTOCOL  *SerialIo,
 | 
						|
  UINT8                   *Output
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       Size;
 | 
						|
 | 
						|
  Size    = 1;
 | 
						|
  *Output = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Read one key from serial I/O device.
 | 
						|
  //
 | 
						|
  Status = SerialIo->Read (SerialIo, &Size, Output);
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    if (Status == EFI_TIMEOUT) {
 | 
						|
      return EFI_NOT_READY;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (*Output == 0) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert one byte raw data into the Raw Data FIFO.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Input                The key will be input.
 | 
						|
 | 
						|
  @retval TRUE                 If insert successfully.
 | 
						|
  @retval FALSE                If Raw Data buffer is full before key insertion,
 | 
						|
                               and the key is lost.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
RawFiFoInsertOneKey (
 | 
						|
  TERMINAL_DEV  *TerminalDevice,
 | 
						|
  UINT8         Input
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
 | 
						|
  Tail = TerminalDevice->RawFiFo->Tail;
 | 
						|
 | 
						|
  if (IsRawFiFoFull (TerminalDevice)) {
 | 
						|
    //
 | 
						|
    // Raw FIFO is full
 | 
						|
    //
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  TerminalDevice->RawFiFo->Data[Tail] = Input;
 | 
						|
 | 
						|
  TerminalDevice->RawFiFo->Tail = (UINT8)((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove one pre-fetched key out of the Raw Data FIFO.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Output               The key will be removed.
 | 
						|
 | 
						|
  @retval TRUE                 If insert successfully.
 | 
						|
  @retval FALSE                If Raw Data FIFO buffer is empty before remove operation.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
RawFiFoRemoveOneKey (
 | 
						|
  TERMINAL_DEV  *TerminalDevice,
 | 
						|
  UINT8         *Output
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Head = TerminalDevice->RawFiFo->Head;
 | 
						|
 | 
						|
  if (IsRawFiFoEmpty (TerminalDevice)) {
 | 
						|
    //
 | 
						|
    //  FIFO is empty
 | 
						|
    //
 | 
						|
    *Output = 0;
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  *Output = TerminalDevice->RawFiFo->Data[Head];
 | 
						|
 | 
						|
  TerminalDevice->RawFiFo->Head = (UINT8)((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether Raw Data FIFO buffer is empty.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If Raw Data FIFO buffer is empty.
 | 
						|
  @retval FALSE                If Raw Data FIFO buffer is not empty.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsRawFiFoEmpty (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (TerminalDevice->RawFiFo->Head == TerminalDevice->RawFiFo->Tail) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether Raw Data FIFO buffer is full.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If Raw Data FIFO buffer is full.
 | 
						|
  @retval FALSE                If Raw Data FIFO buffer is not full.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsRawFiFoFull (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Tail = TerminalDevice->RawFiFo->Tail;
 | 
						|
  Head = TerminalDevice->RawFiFo->Head;
 | 
						|
 | 
						|
  if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert one pre-fetched key into the FIFO buffer.
 | 
						|
 | 
						|
  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
 | 
						|
  @param  Input                 The key will be input.
 | 
						|
 | 
						|
  @retval TRUE                  If insert successfully.
 | 
						|
  @retval FALSE                 If FIFO buffer is full before key insertion,
 | 
						|
                                and the key is lost.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiKeyFiFoForNotifyInsertOneKey (
 | 
						|
  EFI_KEY_FIFO   *EfiKeyFiFo,
 | 
						|
  EFI_INPUT_KEY  *Input
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
 | 
						|
  Tail = EfiKeyFiFo->Tail;
 | 
						|
 | 
						|
  if (IsEfiKeyFiFoForNotifyFull (EfiKeyFiFo)) {
 | 
						|
    //
 | 
						|
    // FIFO is full
 | 
						|
    //
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (&EfiKeyFiFo->Data[Tail], Input, sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  EfiKeyFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove one pre-fetched key out of the FIFO buffer.
 | 
						|
 | 
						|
  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
 | 
						|
  @param  Output                The key will be removed.
 | 
						|
 | 
						|
  @retval TRUE                  If remove successfully.
 | 
						|
  @retval FALSE                 If FIFO buffer is empty before remove operation.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiKeyFiFoForNotifyRemoveOneKey (
 | 
						|
  EFI_KEY_FIFO   *EfiKeyFiFo,
 | 
						|
  EFI_INPUT_KEY  *Output
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Head = EfiKeyFiFo->Head;
 | 
						|
  ASSERT (Head < FIFO_MAX_NUMBER + 1);
 | 
						|
 | 
						|
  if (IsEfiKeyFiFoForNotifyEmpty (EfiKeyFiFo)) {
 | 
						|
    //
 | 
						|
    // FIFO is empty
 | 
						|
    //
 | 
						|
    Output->ScanCode    = SCAN_NULL;
 | 
						|
    Output->UnicodeChar = 0;
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Output, &EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  EfiKeyFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether FIFO buffer is empty.
 | 
						|
 | 
						|
  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
 | 
						|
 | 
						|
  @retval TRUE                  If FIFO buffer is empty.
 | 
						|
  @retval FALSE                 If FIFO buffer is not empty.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsEfiKeyFiFoForNotifyEmpty (
 | 
						|
  EFI_KEY_FIFO  *EfiKeyFiFo
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (EfiKeyFiFo->Head == EfiKeyFiFo->Tail) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether FIFO buffer is full.
 | 
						|
 | 
						|
  @param  EfiKeyFiFo            Pointer to instance of EFI_KEY_FIFO.
 | 
						|
 | 
						|
  @retval TRUE                  If FIFO buffer is full.
 | 
						|
  @retval FALSE                 If FIFO buffer is not full.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsEfiKeyFiFoForNotifyFull (
 | 
						|
  EFI_KEY_FIFO  *EfiKeyFiFo
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Tail = EfiKeyFiFo->Tail;
 | 
						|
  Head = EfiKeyFiFo->Head;
 | 
						|
 | 
						|
  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert one pre-fetched key into the FIFO buffer.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Key                  The key will be input.
 | 
						|
 | 
						|
  @retval TRUE                 If insert successfully.
 | 
						|
  @retval FALSE                If FIFO buffer is full before key insertion,
 | 
						|
                               and the key is lost.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiKeyFiFoInsertOneKey (
 | 
						|
  TERMINAL_DEV   *TerminalDevice,
 | 
						|
  EFI_INPUT_KEY  *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8                          Tail;
 | 
						|
  LIST_ENTRY                     *Link;
 | 
						|
  LIST_ENTRY                     *NotifyList;
 | 
						|
  TERMINAL_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | 
						|
  EFI_KEY_DATA                   KeyData;
 | 
						|
 | 
						|
  Tail = TerminalDevice->EfiKeyFiFo->Tail;
 | 
						|
 | 
						|
  CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));
 | 
						|
  KeyData.KeyState.KeyShiftState  = 0;
 | 
						|
  KeyData.KeyState.KeyToggleState = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Signal KeyNotify process event if this key pressed matches any key registered.
 | 
						|
  //
 | 
						|
  NotifyList = &TerminalDevice->NotifyList;
 | 
						|
  for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
 | 
						|
      //
 | 
						|
      // The key notification function needs to run at TPL_CALLBACK
 | 
						|
      // while current TPL is TPL_NOTIFY. It will be invoked in
 | 
						|
      // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
 | 
						|
      //
 | 
						|
      EfiKeyFiFoForNotifyInsertOneKey (TerminalDevice->EfiKeyFiFoForNotify, Key);
 | 
						|
      gBS->SignalEvent (TerminalDevice->KeyNotifyProcessEvent);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsEfiKeyFiFoFull (TerminalDevice)) {
 | 
						|
    //
 | 
						|
    // Efi Key FIFO is full
 | 
						|
    //
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  TerminalDevice->EfiKeyFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove one pre-fetched key out of the FIFO buffer.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Output               The key will be removed.
 | 
						|
 | 
						|
  @retval TRUE                 If insert successfully.
 | 
						|
  @retval FALSE                If FIFO buffer is empty before remove operation.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiKeyFiFoRemoveOneKey (
 | 
						|
  TERMINAL_DEV   *TerminalDevice,
 | 
						|
  EFI_INPUT_KEY  *Output
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Head = TerminalDevice->EfiKeyFiFo->Head;
 | 
						|
  ASSERT (Head < FIFO_MAX_NUMBER + 1);
 | 
						|
 | 
						|
  if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
 | 
						|
    //
 | 
						|
    //  FIFO is empty
 | 
						|
    //
 | 
						|
    Output->ScanCode    = SCAN_NULL;
 | 
						|
    Output->UnicodeChar = 0;
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (Output, &TerminalDevice->EfiKeyFiFo->Data[Head], sizeof (EFI_INPUT_KEY));
 | 
						|
 | 
						|
  TerminalDevice->EfiKeyFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether FIFO buffer is empty.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If FIFO buffer is empty.
 | 
						|
  @retval FALSE                If FIFO buffer is not empty.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsEfiKeyFiFoEmpty (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (TerminalDevice->EfiKeyFiFo->Head == TerminalDevice->EfiKeyFiFo->Tail) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether FIFO buffer is full.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If FIFO buffer is full.
 | 
						|
  @retval FALSE                If FIFO buffer is not full.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsEfiKeyFiFoFull (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Tail = TerminalDevice->EfiKeyFiFo->Tail;
 | 
						|
  Head = TerminalDevice->EfiKeyFiFo->Head;
 | 
						|
 | 
						|
  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert one pre-fetched key into the Unicode FIFO buffer.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Input                The key will be input.
 | 
						|
 | 
						|
  @retval TRUE                 If insert successfully.
 | 
						|
  @retval FALSE                If Unicode FIFO buffer is full before key insertion,
 | 
						|
                               and the key is lost.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
UnicodeFiFoInsertOneKey (
 | 
						|
  TERMINAL_DEV  *TerminalDevice,
 | 
						|
  UINT16        Input
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
 | 
						|
  Tail = TerminalDevice->UnicodeFiFo->Tail;
 | 
						|
  ASSERT (Tail < FIFO_MAX_NUMBER + 1);
 | 
						|
 | 
						|
  if (IsUnicodeFiFoFull (TerminalDevice)) {
 | 
						|
    //
 | 
						|
    // Unicode FIFO is full
 | 
						|
    //
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  TerminalDevice->UnicodeFiFo->Data[Tail] = Input;
 | 
						|
 | 
						|
  TerminalDevice->UnicodeFiFo->Tail = (UINT8)((Tail + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Remove one pre-fetched key out of the Unicode FIFO buffer.
 | 
						|
  The caller should guarantee that Unicode FIFO buffer is not empty
 | 
						|
  by IsUnicodeFiFoEmpty ().
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure.
 | 
						|
  @param  Output               The key will be removed.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnicodeFiFoRemoveOneKey (
 | 
						|
  TERMINAL_DEV  *TerminalDevice,
 | 
						|
  UINT16        *Output
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Head = TerminalDevice->UnicodeFiFo->Head;
 | 
						|
  ASSERT (Head < FIFO_MAX_NUMBER + 1);
 | 
						|
 | 
						|
  *Output = TerminalDevice->UnicodeFiFo->Data[Head];
 | 
						|
 | 
						|
  TerminalDevice->UnicodeFiFo->Head = (UINT8)((Head + 1) % (FIFO_MAX_NUMBER + 1));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether Unicode FIFO buffer is empty.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If Unicode FIFO buffer is empty.
 | 
						|
  @retval FALSE                If Unicode FIFO buffer is not empty.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsUnicodeFiFoEmpty (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (TerminalDevice->UnicodeFiFo->Head == TerminalDevice->UnicodeFiFo->Tail) {
 | 
						|
    return TRUE;
 | 
						|
  } else {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Clarify whether Unicode FIFO buffer is full.
 | 
						|
 | 
						|
  @param  TerminalDevice       Terminal driver private structure
 | 
						|
 | 
						|
  @retval TRUE                 If Unicode FIFO buffer is full.
 | 
						|
  @retval FALSE                If Unicode FIFO buffer is not full.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsUnicodeFiFoFull (
 | 
						|
  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT8  Tail;
 | 
						|
  UINT8  Head;
 | 
						|
 | 
						|
  Tail = TerminalDevice->UnicodeFiFo->Tail;
 | 
						|
  Head = TerminalDevice->UnicodeFiFo->Head;
 | 
						|
 | 
						|
  if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update the Unicode characters from a terminal input device into EFI Keys FIFO.
 | 
						|
 | 
						|
  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnicodeToEfiKeyFlushState (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_INPUT_KEY  Key;
 | 
						|
  UINT32         InputState;
 | 
						|
 | 
						|
  InputState = TerminalDevice->InputState;
 | 
						|
 | 
						|
  if (IsEfiKeyFiFoFull (TerminalDevice)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InputState & INPUT_STATE_ESC) != 0) {
 | 
						|
    Key.ScanCode    = SCAN_ESC;
 | 
						|
    Key.UnicodeChar = 0;
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InputState & INPUT_STATE_CSI) != 0) {
 | 
						|
    Key.ScanCode    = SCAN_NULL;
 | 
						|
    Key.UnicodeChar = CSI;
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
 | 
						|
    Key.ScanCode    = SCAN_NULL;
 | 
						|
    Key.UnicodeChar = LEFTOPENBRACKET;
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InputState & INPUT_STATE_O) != 0) {
 | 
						|
    Key.ScanCode    = SCAN_NULL;
 | 
						|
    Key.UnicodeChar = 'O';
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
 | 
						|
  if ((InputState & INPUT_STATE_2) != 0) {
 | 
						|
    Key.ScanCode    = SCAN_NULL;
 | 
						|
    Key.UnicodeChar = '2';
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Cancel the timer.
 | 
						|
  //
 | 
						|
  gBS->SetTimer (
 | 
						|
         TerminalDevice->TwoSecondTimeOut,
 | 
						|
         TimerCancel,
 | 
						|
         0
 | 
						|
         );
 | 
						|
 | 
						|
  TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Converts a stream of Unicode characters from a terminal input device into EFI Keys that
 | 
						|
  can be read through the Simple Input Protocol.
 | 
						|
 | 
						|
  The table below shows the keyboard input mappings that this function supports.
 | 
						|
  If the ESC sequence listed in one of the columns is presented, then it is translated
 | 
						|
  into the corresponding EFI Scan Code.  If a matching sequence is not found, then the raw
 | 
						|
  key strokes are converted into EFI Keys.
 | 
						|
 | 
						|
  2 seconds are allowed for an ESC sequence to be completed.  If the ESC sequence is not
 | 
						|
  completed in 2 seconds, then the raw key strokes of the partial ESC sequence are
 | 
						|
  converted into EFI Keys.
 | 
						|
  There is one special input sequence that will force the system to reset.
 | 
						|
  This is ESC R ESC r ESC R.
 | 
						|
 | 
						|
  Note: current implementation support terminal types include: PC ANSI, VT100+/VTUTF8, VT100.
 | 
						|
        The table below is not same with UEFI Spec 2.3 Appendix B Table 201(not support ANSI X3.64 /
 | 
						|
        DEC VT200-500 and extra support PC ANSI, VT100)since UEFI Table 201 is just an example.
 | 
						|
 | 
						|
  Symbols used in table below
 | 
						|
  ===========================
 | 
						|
    ESC = 0x1B
 | 
						|
    CSI = 0x9B
 | 
						|
    DEL = 0x7f
 | 
						|
    ^   = CTRL
 | 
						|
 | 
						|
  +=========+======+===========+==========+==========+
 | 
						|
  |         | EFI  | UEFI 2.0  |          |          |
 | 
						|
  |         | Scan |           |  VT100+  |          |
 | 
						|
  |   KEY   | Code |  PC ANSI  |  VTUTF8  |   VT100  |
 | 
						|
  +=========+======+===========+==========+==========+
 | 
						|
  | NULL    | 0x00 |           |          |          |
 | 
						|
  | UP      | 0x01 | ESC [ A   | ESC [ A  | ESC [ A  |
 | 
						|
  | DOWN    | 0x02 | ESC [ B   | ESC [ B  | ESC [ B  |
 | 
						|
  | RIGHT   | 0x03 | ESC [ C   | ESC [ C  | ESC [ C  |
 | 
						|
  | LEFT    | 0x04 | ESC [ D   | ESC [ D  | ESC [ D  |
 | 
						|
  | HOME    | 0x05 | ESC [ H   | ESC h    | ESC [ H  |
 | 
						|
  | END     | 0x06 | ESC [ F   | ESC k    | ESC [ K  |
 | 
						|
  | INSERT  | 0x07 | ESC [ @   | ESC +    | ESC [ @  |
 | 
						|
  |         |      | ESC [ L   |          | ESC [ L  |
 | 
						|
  | DELETE  | 0x08 | ESC [ X   | ESC -    | ESC [ P  |
 | 
						|
  | PG UP   | 0x09 | ESC [ I   | ESC ?    | ESC [ V  |
 | 
						|
  |         |      |           |          | ESC [ ?  |
 | 
						|
  | PG DOWN | 0x0A | ESC [ G   | ESC /    | ESC [ U  |
 | 
						|
  |         |      |           |          | ESC [ /  |
 | 
						|
  | F1      | 0x0B | ESC [ M   | ESC 1    | ESC O P  |
 | 
						|
  | F2      | 0x0C | ESC [ N   | ESC 2    | ESC O Q  |
 | 
						|
  | F3      | 0x0D | ESC [ O   | ESC 3    | ESC O w  |
 | 
						|
  | F4      | 0x0E | ESC [ P   | ESC 4    | ESC O x  |
 | 
						|
  | F5      | 0x0F | ESC [ Q   | ESC 5    | ESC O t  |
 | 
						|
  | F6      | 0x10 | ESC [ R   | ESC 6    | ESC O u  |
 | 
						|
  | F7      | 0x11 | ESC [ S   | ESC 7    | ESC O q  |
 | 
						|
  | F8      | 0x12 | ESC [ T   | ESC 8    | ESC O r  |
 | 
						|
  | F9      | 0x13 | ESC [ U   | ESC 9    | ESC O p  |
 | 
						|
  | F10     | 0x14 | ESC [ V   | ESC 0    | ESC O M  |
 | 
						|
  | Escape  | 0x17 | ESC       | ESC      | ESC      |
 | 
						|
  | F11     | 0x15 |           | ESC !    |          |
 | 
						|
  | F12     | 0x16 |           | ESC @    |          |
 | 
						|
  +=========+======+===========+==========+==========+
 | 
						|
 | 
						|
Putty function key map:
 | 
						|
  +=========+======+===========+=============+=============+=============+=========+
 | 
						|
  |         | EFI  |           |             |             |             |         |
 | 
						|
  |         | Scan |           |             |  Normal     |             |         |
 | 
						|
  |   KEY   | Code |  VT100+   | Xterm R6    |  VT400      | Linux       | SCO     |
 | 
						|
  +=========+======+===========+=============+=============+=============+=========+
 | 
						|
  | F1      | 0x0B | ESC O P   | ESC O P     | ESC [ 1 1 ~ | ESC [ [ A   | ESC [ M |
 | 
						|
  | F2      | 0x0C | ESC O Q   | ESC O Q     | ESC [ 1 2 ~ | ESC [ [ B   | ESC [ N |
 | 
						|
  | F3      | 0x0D | ESC O R   | ESC O R     | ESC [ 1 3 ~ | ESC [ [ C   | ESC [ O |
 | 
						|
  | F4      | 0x0E | ESC O S   | ESC O S     | ESC [ 1 4 ~ | ESC [ [ D   | ESC [ P |
 | 
						|
  | F5      | 0x0F | ESC O T   | ESC [ 1 5 ~ | ESC [ 1 5 ~ | ESC [ [ E   | ESC [ Q |
 | 
						|
  | F6      | 0x10 | ESC O U   | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ 1 7 ~ | ESC [ R |
 | 
						|
  | F7      | 0x11 | ESC O V   | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ 1 8 ~ | ESC [ S |
 | 
						|
  | F8      | 0x12 | ESC O W   | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ 1 9 ~ | ESC [ T |
 | 
						|
  | F9      | 0x13 | ESC O X   | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ 2 0 ~ | ESC [ U |
 | 
						|
  | F10     | 0x14 | ESC O Y   | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ 2 1 ~ | ESC [ V |
 | 
						|
  | Escape  | 0x17 | ESC       | ESC         | ESC         | ESC         | ESC     |
 | 
						|
  | F11     | 0x15 | ESC O Z   | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ 2 3 ~ | ESC [ W |
 | 
						|
  | F12     | 0x16 | ESC O [   | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ 2 4 ~ | ESC [ X |
 | 
						|
  +=========+======+===========+=============+=============+=============+=========+
 | 
						|
 | 
						|
  Special Mappings
 | 
						|
  ================
 | 
						|
  ESC R ESC r ESC R = Reset System
 | 
						|
 | 
						|
  @param TerminalDevice   The terminal device to use to translate raw input into EFI Keys
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
UnicodeToEfiKey (
 | 
						|
  IN  TERMINAL_DEV  *TerminalDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS     Status;
 | 
						|
  EFI_STATUS     TimerStatus;
 | 
						|
  UINT16         UnicodeChar;
 | 
						|
  EFI_INPUT_KEY  Key;
 | 
						|
  BOOLEAN        SetDefaultResetState;
 | 
						|
 | 
						|
  TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
 | 
						|
 | 
						|
  if (!EFI_ERROR (TimerStatus)) {
 | 
						|
    UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
    TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
  }
 | 
						|
 | 
						|
  while (!IsUnicodeFiFoEmpty (TerminalDevice) && !IsEfiKeyFiFoFull (TerminalDevice)) {
 | 
						|
    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
 | 
						|
      //
 | 
						|
      // Check to see if the 2 seconds timer has expired
 | 
						|
      //
 | 
						|
      TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut);
 | 
						|
      if (!EFI_ERROR (TimerStatus)) {
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Fetch one Unicode character from the Unicode FIFO
 | 
						|
    //
 | 
						|
    UnicodeFiFoRemoveOneKey (TerminalDevice, &UnicodeChar);
 | 
						|
 | 
						|
    SetDefaultResetState = TRUE;
 | 
						|
 | 
						|
    switch (TerminalDevice->InputState) {
 | 
						|
      case INPUT_STATE_DEFAULT:
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC:
 | 
						|
 | 
						|
        if (UnicodeChar == LEFTOPENBRACKET) {
 | 
						|
          TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET;
 | 
						|
          TerminalDevice->ResetState  = RESET_STATE_DEFAULT;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((UnicodeChar == 'O') && ((TerminalDevice->TerminalType == TerminalTypeVt100) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeTtyTerm) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeVt100Plus)))
 | 
						|
        {
 | 
						|
          TerminalDevice->InputState |= INPUT_STATE_O;
 | 
						|
          TerminalDevice->ResetState  = RESET_STATE_DEFAULT;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        Key.ScanCode = SCAN_NULL;
 | 
						|
 | 
						|
        if ((TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVtUtf8))
 | 
						|
        {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case '1':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case '2':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case '3':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case '4':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
            case '5':
 | 
						|
              Key.ScanCode = SCAN_F5;
 | 
						|
              break;
 | 
						|
            case '6':
 | 
						|
              Key.ScanCode = SCAN_F6;
 | 
						|
              break;
 | 
						|
            case '7':
 | 
						|
              Key.ScanCode = SCAN_F7;
 | 
						|
              break;
 | 
						|
            case '8':
 | 
						|
              Key.ScanCode = SCAN_F8;
 | 
						|
              break;
 | 
						|
            case '9':
 | 
						|
              Key.ScanCode = SCAN_F9;
 | 
						|
              break;
 | 
						|
            case '0':
 | 
						|
              Key.ScanCode = SCAN_F10;
 | 
						|
              break;
 | 
						|
            case '!':
 | 
						|
              Key.ScanCode = SCAN_F11;
 | 
						|
              break;
 | 
						|
            case '@':
 | 
						|
              Key.ScanCode = SCAN_F12;
 | 
						|
              break;
 | 
						|
            case 'h':
 | 
						|
              Key.ScanCode = SCAN_HOME;
 | 
						|
              break;
 | 
						|
            case 'k':
 | 
						|
              Key.ScanCode = SCAN_END;
 | 
						|
              break;
 | 
						|
            case '+':
 | 
						|
              Key.ScanCode = SCAN_INSERT;
 | 
						|
              break;
 | 
						|
            case '-':
 | 
						|
              Key.ScanCode = SCAN_DELETE;
 | 
						|
              break;
 | 
						|
            case '/':
 | 
						|
              Key.ScanCode = SCAN_PAGE_DOWN;
 | 
						|
              break;
 | 
						|
            case '?':
 | 
						|
              Key.ScanCode = SCAN_PAGE_UP;
 | 
						|
              break;
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        switch (UnicodeChar) {
 | 
						|
          case 'R':
 | 
						|
            if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) {
 | 
						|
              TerminalDevice->ResetState = RESET_STATE_ESC_R;
 | 
						|
              SetDefaultResetState       = FALSE;
 | 
						|
            } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_R) {
 | 
						|
              gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
 | 
						|
            }
 | 
						|
 | 
						|
            Key.ScanCode = SCAN_NULL;
 | 
						|
            break;
 | 
						|
          case 'r':
 | 
						|
            if (TerminalDevice->ResetState == RESET_STATE_ESC_R) {
 | 
						|
              TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_R;
 | 
						|
              SetDefaultResetState       = FALSE;
 | 
						|
            }
 | 
						|
 | 
						|
            Key.ScanCode = SCAN_NULL;
 | 
						|
            break;
 | 
						|
          default:
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (SetDefaultResetState) {
 | 
						|
          TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_O:
 | 
						|
 | 
						|
        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
 | 
						|
        Key.ScanCode = SCAN_NULL;
 | 
						|
 | 
						|
        if (TerminalDevice->TerminalType == TerminalTypeVt100) {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'P':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case 'Q':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case 'w':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case 'x':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
            case 't':
 | 
						|
              Key.ScanCode = SCAN_F5;
 | 
						|
              break;
 | 
						|
            case 'u':
 | 
						|
              Key.ScanCode = SCAN_F6;
 | 
						|
              break;
 | 
						|
            case 'q':
 | 
						|
              Key.ScanCode = SCAN_F7;
 | 
						|
              break;
 | 
						|
            case 'r':
 | 
						|
              Key.ScanCode = SCAN_F8;
 | 
						|
              break;
 | 
						|
            case 'p':
 | 
						|
              Key.ScanCode = SCAN_F9;
 | 
						|
              break;
 | 
						|
            case 'M':
 | 
						|
              Key.ScanCode = SCAN_F10;
 | 
						|
              break;
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        } else if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
 | 
						|
          /* Also accept VT100 escape codes for F1-F4, HOME and END for TTY term */
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'P':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case 'Q':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case 'R':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case 'S':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
            case 'H':
 | 
						|
              Key.ScanCode = SCAN_HOME;
 | 
						|
              break;
 | 
						|
            case 'F':
 | 
						|
              Key.ScanCode = SCAN_END;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        } else if (TerminalDevice->TerminalType == TerminalTypeVt100Plus) {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'P':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case 'Q':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case 'R':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case 'S':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
            case 'T':
 | 
						|
              Key.ScanCode = SCAN_F5;
 | 
						|
              break;
 | 
						|
            case 'U':
 | 
						|
              Key.ScanCode = SCAN_F6;
 | 
						|
              break;
 | 
						|
            case 'V':
 | 
						|
              Key.ScanCode = SCAN_F7;
 | 
						|
              break;
 | 
						|
            case 'W':
 | 
						|
              Key.ScanCode = SCAN_F8;
 | 
						|
              break;
 | 
						|
            case 'X':
 | 
						|
              Key.ScanCode = SCAN_F9;
 | 
						|
              break;
 | 
						|
            case 'Y':
 | 
						|
              Key.ScanCode = SCAN_F10;
 | 
						|
              break;
 | 
						|
            case 'Z':
 | 
						|
              Key.ScanCode = SCAN_F11;
 | 
						|
              break;
 | 
						|
            case '[':
 | 
						|
              Key.ScanCode = SCAN_F12;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        } else if (TerminalDevice->TerminalType == TerminalTypeXtermR6) {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'P':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case 'Q':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case 'R':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case 'S':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET:
 | 
						|
 | 
						|
        if ((UnicodeChar == '1') && ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeVt400) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeLinux)))
 | 
						|
        {
 | 
						|
          TerminalDevice->InputState |= INPUT_STATE_1;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((UnicodeChar == '2') && ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeVt400) ||
 | 
						|
                                     (TerminalDevice->TerminalType == TerminalTypeLinux)))
 | 
						|
        {
 | 
						|
          TerminalDevice->InputState |= INPUT_STATE_2;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((UnicodeChar == LEFTOPENBRACKET) && (TerminalDevice->TerminalType == TerminalTypeLinux)) {
 | 
						|
          TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET_2ND;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
 | 
						|
        Key.ScanCode = SCAN_NULL;
 | 
						|
 | 
						|
        if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVt100) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVtUtf8) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeTtyTerm) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeLinux) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVt400) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
        {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'A':
 | 
						|
              Key.ScanCode = SCAN_UP;
 | 
						|
              break;
 | 
						|
            case 'B':
 | 
						|
              Key.ScanCode = SCAN_DOWN;
 | 
						|
              break;
 | 
						|
            case 'C':
 | 
						|
              Key.ScanCode = SCAN_RIGHT;
 | 
						|
              break;
 | 
						|
            case 'D':
 | 
						|
              Key.ScanCode = SCAN_LEFT;
 | 
						|
              break;
 | 
						|
            case 'H':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeVt100) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeTtyTerm))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_HOME;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'F':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeTtyTerm))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_END;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'K':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt100) {
 | 
						|
                Key.ScanCode = SCAN_END;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'L':
 | 
						|
            case '@':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeVt100))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_INSERT;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'X':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
 | 
						|
                Key.ScanCode = SCAN_DELETE;
 | 
						|
              } else if (TerminalDevice->TerminalType == TerminalTypeSCO) {
 | 
						|
                Key.ScanCode = SCAN_F12;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'P':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt100) {
 | 
						|
                Key.ScanCode = SCAN_DELETE;
 | 
						|
              } else if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                         (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F4;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'I':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
 | 
						|
                Key.ScanCode = SCAN_PAGE_UP;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'V':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F10;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '?':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt100) {
 | 
						|
                Key.ScanCode = SCAN_PAGE_UP;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'G':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypePcAnsi) {
 | 
						|
                Key.ScanCode = SCAN_PAGE_DOWN;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'U':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F9;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '/':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt100) {
 | 
						|
                Key.ScanCode = SCAN_PAGE_DOWN;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'M':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F1;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'N':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F2;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'O':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F3;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'Q':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F5;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'R':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F6;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'S':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F7;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'T':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypePcAnsi) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeSCO))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F8;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case 'W':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeSCO) {
 | 
						|
                Key.ScanCode = SCAN_F11;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            default:
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        /*
 | 
						|
         * The VT220 escape codes that the TTY terminal accepts all have
 | 
						|
         * numeric codes, and there are no ambiguous prefixes shared with
 | 
						|
         * other terminal types.
 | 
						|
         */
 | 
						|
        if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) &&
 | 
						|
            (Key.ScanCode == SCAN_NULL) &&
 | 
						|
            (UnicodeChar >= '0') &&
 | 
						|
            (UnicodeChar <= '9'))
 | 
						|
        {
 | 
						|
          TerminalDevice->TtyEscapeStr[0] = UnicodeChar;
 | 
						|
          TerminalDevice->TtyEscapeIndex  = 1;
 | 
						|
          TerminalDevice->InputState     |= INPUT_STATE_LEFTOPENBRACKET_TTY;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_1:
 | 
						|
 | 
						|
        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
 | 
						|
        Key.ScanCode = SCAN_NULL;
 | 
						|
 | 
						|
        if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVt400) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeLinux))
 | 
						|
        {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case '1':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt400) {
 | 
						|
                Key.ScanCode = SCAN_F1;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '2':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt400) {
 | 
						|
                Key.ScanCode = SCAN_F2;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '3':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt400) {
 | 
						|
                Key.ScanCode = SCAN_F3;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '4':
 | 
						|
              if (TerminalDevice->TerminalType == TerminalTypeVt400) {
 | 
						|
                Key.ScanCode = SCAN_F4;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '5':
 | 
						|
              if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
                  (TerminalDevice->TerminalType == TerminalTypeVt400))
 | 
						|
              {
 | 
						|
                Key.ScanCode = SCAN_F5;
 | 
						|
              }
 | 
						|
 | 
						|
              break;
 | 
						|
            case '7':
 | 
						|
              Key.ScanCode = SCAN_F6;
 | 
						|
              break;
 | 
						|
            case '8':
 | 
						|
              Key.ScanCode = SCAN_F7;
 | 
						|
              break;
 | 
						|
            case '9':
 | 
						|
              Key.ScanCode = SCAN_F8;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_2:
 | 
						|
 | 
						|
        TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
        Key.ScanCode               = SCAN_NULL;
 | 
						|
        if ((TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeVt400) ||
 | 
						|
            (TerminalDevice->TerminalType == TerminalTypeLinux))
 | 
						|
        {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case '0':
 | 
						|
              Key.ScanCode = SCAN_F9;
 | 
						|
              break;
 | 
						|
            case '1':
 | 
						|
              Key.ScanCode = SCAN_F10;
 | 
						|
              break;
 | 
						|
            case '3':
 | 
						|
              Key.ScanCode = SCAN_F11;
 | 
						|
              break;
 | 
						|
            case '4':
 | 
						|
              Key.ScanCode = SCAN_F12;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_LEFTOPENBRACKET_2ND:
 | 
						|
 | 
						|
        TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
        Key.ScanCode               = SCAN_NULL;
 | 
						|
 | 
						|
        if (TerminalDevice->TerminalType == TerminalTypeLinux) {
 | 
						|
          switch (UnicodeChar) {
 | 
						|
            case 'A':
 | 
						|
              Key.ScanCode = SCAN_F1;
 | 
						|
              break;
 | 
						|
            case 'B':
 | 
						|
              Key.ScanCode = SCAN_F2;
 | 
						|
              break;
 | 
						|
            case 'C':
 | 
						|
              Key.ScanCode = SCAN_F3;
 | 
						|
              break;
 | 
						|
            case 'D':
 | 
						|
              Key.ScanCode = SCAN_F4;
 | 
						|
              break;
 | 
						|
            case 'E':
 | 
						|
              Key.ScanCode = SCAN_F5;
 | 
						|
              break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET | INPUT_STATE_LEFTOPENBRACKET_TTY:
 | 
						|
        /*
 | 
						|
         * Here we handle the VT220 escape codes that we accept.  This
 | 
						|
         * state is only used by the TTY terminal type.
 | 
						|
         */
 | 
						|
        Key.ScanCode = SCAN_NULL;
 | 
						|
        if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
 | 
						|
          if ((UnicodeChar == '~') && (TerminalDevice->TtyEscapeIndex <= 2)) {
 | 
						|
            UINT16  EscCode;
 | 
						|
            TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex] = 0; /* Terminate string */
 | 
						|
            EscCode                                                      = (UINT16)StrDecimalToUintn (TerminalDevice->TtyEscapeStr);
 | 
						|
            switch (EscCode) {
 | 
						|
              case 2:
 | 
						|
                Key.ScanCode = SCAN_INSERT;
 | 
						|
                break;
 | 
						|
              case 3:
 | 
						|
                Key.ScanCode = SCAN_DELETE;
 | 
						|
                break;
 | 
						|
              case 5:
 | 
						|
                Key.ScanCode = SCAN_PAGE_UP;
 | 
						|
                break;
 | 
						|
              case 6:
 | 
						|
                Key.ScanCode = SCAN_PAGE_DOWN;
 | 
						|
                break;
 | 
						|
              case 11:
 | 
						|
              case 12:
 | 
						|
              case 13:
 | 
						|
              case 14:
 | 
						|
              case 15:
 | 
						|
                Key.ScanCode = SCAN_F1 + EscCode - 11;
 | 
						|
                break;
 | 
						|
              case 17:
 | 
						|
              case 18:
 | 
						|
              case 19:
 | 
						|
              case 20:
 | 
						|
              case 21:
 | 
						|
                Key.ScanCode = SCAN_F6 + EscCode - 17;
 | 
						|
                break;
 | 
						|
              case 23:
 | 
						|
              case 24:
 | 
						|
                Key.ScanCode = SCAN_F11 + EscCode - 23;
 | 
						|
                break;
 | 
						|
              default:
 | 
						|
                break;
 | 
						|
            }
 | 
						|
          } else if (TerminalDevice->TtyEscapeIndex == 1) {
 | 
						|
            /* 2 character escape code   */
 | 
						|
            TerminalDevice->TtyEscapeStr[TerminalDevice->TtyEscapeIndex++] = UnicodeChar;
 | 
						|
            continue;
 | 
						|
          } else {
 | 
						|
            DEBUG ((DEBUG_ERROR, "Unexpected state in escape2\n"));
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
 | 
						|
        if (Key.ScanCode != SCAN_NULL) {
 | 
						|
          Key.UnicodeChar = 0;
 | 
						|
          EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
          TerminalDevice->InputState = INPUT_STATE_DEFAULT;
 | 
						|
          UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        //
 | 
						|
        // Invalid state. This should never happen.
 | 
						|
        //
 | 
						|
        ASSERT (FALSE);
 | 
						|
 | 
						|
        UnicodeToEfiKeyFlushState (TerminalDevice);
 | 
						|
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UnicodeChar == ESC) {
 | 
						|
      TerminalDevice->InputState = INPUT_STATE_ESC;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UnicodeChar == CSI) {
 | 
						|
      TerminalDevice->InputState = INPUT_STATE_CSI;
 | 
						|
    }
 | 
						|
 | 
						|
    if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) {
 | 
						|
      Status = gBS->SetTimer (
 | 
						|
                      TerminalDevice->TwoSecondTimeOut,
 | 
						|
                      TimerRelative,
 | 
						|
                      (UINT64)20000000
 | 
						|
                      );
 | 
						|
      ASSERT_EFI_ERROR (Status);
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SetDefaultResetState) {
 | 
						|
      TerminalDevice->ResetState = RESET_STATE_DEFAULT;
 | 
						|
    }
 | 
						|
 | 
						|
    if (UnicodeChar == DEL) {
 | 
						|
      if (TerminalDevice->TerminalType == TerminalTypeTtyTerm) {
 | 
						|
        Key.ScanCode    = SCAN_NULL;
 | 
						|
        Key.UnicodeChar = CHAR_BACKSPACE;
 | 
						|
      } else {
 | 
						|
        Key.ScanCode    = SCAN_DELETE;
 | 
						|
        Key.UnicodeChar = 0;
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      Key.ScanCode    = SCAN_NULL;
 | 
						|
      Key.UnicodeChar = UnicodeChar;
 | 
						|
    }
 | 
						|
 | 
						|
    EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
 | 
						|
  }
 | 
						|
}
 |