Fix various typos in documentation, comments and debug strings. Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Ray Ni <ray.ni@intel.com> Signed-off-by: Antoine Coeur <coeur@gmx.fr> Reviewed-by: Philippe Mathieu-Daude <philmd@redhat.com> Acked-by: Liming Gao <liming.gao@intel.com> Signed-off-by: Philippe Mathieu-Daude <philmd@redhat.com> Message-Id: <20200207010831.9046-14-philmd@redhat.com>
		
			
				
	
	
		
			734 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			734 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
 | 
						|
  provided by Ps2KbdCtrller.c.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
 | 
						|
#include "Ps2Keyboard.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether the EFI key buffer is empty.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | 
						|
 | 
						|
  @retval TRUE    The EFI key buffer is empty.
 | 
						|
  @retval FALSE   The EFI key buffer isn't empty.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsEfikeyBufEmpty (
 | 
						|
  IN  EFI_KEY_QUEUE         *Queue
 | 
						|
  )
 | 
						|
{
 | 
						|
  return (BOOLEAN) (Queue->Head == Queue->Tail);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Read & remove one key data from the EFI key buffer.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | 
						|
  @param KeyData   Receive the key data.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   The key data is popped successfully.
 | 
						|
  @retval EFI_NOT_READY There is no key data available.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PopEfikeyBufHead (
 | 
						|
  IN  EFI_KEY_QUEUE         *Queue,
 | 
						|
  OUT EFI_KEY_DATA          *KeyData OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (IsEfikeyBufEmpty (Queue)) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Retrieve and remove the values
 | 
						|
  //
 | 
						|
  if (KeyData != NULL) {
 | 
						|
    CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));
 | 
						|
  }
 | 
						|
  Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Push one key data to the EFI key buffer.
 | 
						|
 | 
						|
  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | 
						|
  @param KeyData   The key data to push.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PushEfikeyBufTail (
 | 
						|
  IN  EFI_KEY_QUEUE         *Queue,
 | 
						|
  IN  EFI_KEY_DATA          *KeyData
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {
 | 
						|
    //
 | 
						|
    // If Queue is full, pop the one from head.
 | 
						|
    //
 | 
						|
    PopEfikeyBufHead (Queue, NULL);
 | 
						|
  }
 | 
						|
  CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));
 | 
						|
  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Judge whether is a registered key
 | 
						|
 | 
						|
  @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;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
 | 
						|
  //
 | 
						|
  if (RegsiteredData->KeyState.KeyShiftState != 0 &&
 | 
						|
      RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
  if (RegsiteredData->KeyState.KeyToggleState != 0 &&
 | 
						|
      RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
    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 ConsoleInDev          Ps2 Keyboard 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_DEVICE_ERROR        The keystroke information was not returned due to
 | 
						|
                                    hardware errors.
 | 
						|
    @retval EFI_INVALID_PARAMETER   KeyData is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KeyboardReadKeyStrokeWorker (
 | 
						|
  IN  KEYBOARD_CONSOLE_IN_DEV           *ConsoleInDev,
 | 
						|
  OUT EFI_KEY_DATA                      *KeyData
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  EFI_TPL                               OldTpl;
 | 
						|
 | 
						|
  if (KeyData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  KeyboardTimerHandler (NULL, ConsoleInDev);
 | 
						|
 | 
						|
  if (ConsoleInDev->KeyboardErr) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  } else {
 | 
						|
    Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);
 | 
						|
    if (Status == EFI_NOT_READY) {
 | 
						|
      ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
 | 
						|
      InitializeKeyState (ConsoleInDev, &KeyData->KeyState);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
 | 
						|
 | 
						|
  @param This                 Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
 | 
						|
  @param ExtendedVerification Indicate that the driver may perform a more
 | 
						|
                              exhaustive verification operation of the device during
 | 
						|
                              reset, now this par is ignored in this driver
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KeyboardEfiReset (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | 
						|
  IN  BOOLEAN                         ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | 
						|
  EFI_TPL                 OldTpl;
 | 
						|
 | 
						|
  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
  if (ConsoleIn->KeyboardErr) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
 | 
						|
    ConsoleIn->DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  //
 | 
						|
  // Call InitKeyboard to initialize the keyboard
 | 
						|
  //
 | 
						|
  Status = InitKeyboard (ConsoleIn, ExtendedVerification);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Leave critical section and return
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  //
 | 
						|
  // Report the status If a stuck key was detected
 | 
						|
  //
 | 
						|
  if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,
 | 
						|
      ConsoleIn->DevicePath
 | 
						|
      );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Report the status If keyboard is locked
 | 
						|
  //
 | 
						|
  if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {
 | 
						|
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | 
						|
      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,
 | 
						|
      ConsoleIn->DevicePath
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
 | 
						|
 | 
						|
  @param This    Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
 | 
						|
  @param Key     The output buffer for key value
 | 
						|
 | 
						|
  @retval EFI_SUCCESS success to read key stroke
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KeyboardReadKeyStroke (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | 
						|
  OUT EFI_INPUT_KEY                   *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | 
						|
  EFI_KEY_DATA            KeyData;
 | 
						|
 | 
						|
  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Considering if the partial keystroke is enabled, there maybe a partial
 | 
						|
  // keystroke in the queue, so here skip the partial keystroke and get the
 | 
						|
  // next key from the queue
 | 
						|
  //
 | 
						|
  while (1) {
 | 
						|
    //
 | 
						|
    // If there is no pending key, then return.
 | 
						|
    //
 | 
						|
    Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // If it is partial keystroke, skip it.
 | 
						|
    //
 | 
						|
    if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Translate the CTRL-Alpha characters to their corresponding control value
 | 
						|
    // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
 | 
						|
    //
 | 
						|
    if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
 | 
						|
      if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
 | 
						|
        KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
 | 
						|
      } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
 | 
						|
        KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification function for SIMPLE_TEXT_IN.WaitForKey event
 | 
						|
  Signal the event if there is key available
 | 
						|
 | 
						|
  @param Event    the event object
 | 
						|
  @param Context  waiting context
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KeyboardWaitForKey (
 | 
						|
  IN  EFI_EVENT               Event,
 | 
						|
  IN  VOID                    *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_TPL                     OldTpl;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV     *ConsoleIn;
 | 
						|
  EFI_KEY_DATA                KeyData;
 | 
						|
 | 
						|
  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  KeyboardTimerHandler (NULL, ConsoleIn);
 | 
						|
 | 
						|
  if (!ConsoleIn->KeyboardErr) {
 | 
						|
    //
 | 
						|
    // WaitforKey doesn't support the partial key.
 | 
						|
    // Considering if the partial keystroke is enabled, there maybe a partial
 | 
						|
    // keystroke in the queue, so here skip the partial keystroke and get the
 | 
						|
    // next key from the queue
 | 
						|
    //
 | 
						|
    while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {
 | 
						|
      CopyMem (
 | 
						|
        &KeyData,
 | 
						|
        &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),
 | 
						|
        sizeof (EFI_KEY_DATA)
 | 
						|
        );
 | 
						|
      if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {
 | 
						|
        PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // if there is pending value key, signal the event.
 | 
						|
      //
 | 
						|
      gBS->SignalEvent (Event);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
 | 
						|
  Signal the event if there is key available
 | 
						|
 | 
						|
  @param Event    event object
 | 
						|
  @param Context  waiting context
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
KeyboardWaitForKeyEx (
 | 
						|
  IN  EFI_EVENT               Event,
 | 
						|
  IN  VOID                    *Context
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  KeyboardWaitForKey (Event, Context);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
KeyboardEfiResetEx (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                            ExtendedVerification
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | 
						|
 | 
						|
  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  return ConsoleInDev->ConIn.Reset (
 | 
						|
                               &ConsoleInDev->ConIn,
 | 
						|
                               ExtendedVerification
 | 
						|
                               );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
    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
 | 
						|
KeyboardReadKeyStrokeEx (
 | 
						|
  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
 | 
						|
  OUT EFI_KEY_DATA                      *KeyData
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | 
						|
 | 
						|
  if (KeyData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
  return KeyboardReadKeyStrokeWorker (ConsoleInDev, 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
 | 
						|
KeyboardSetState (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
 | 
						|
  )
 | 
						|
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | 
						|
  EFI_TPL                               OldTpl;
 | 
						|
 | 
						|
  if (KeyToggleState == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  if (ConsoleInDev->KeyboardErr) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update the status light
 | 
						|
  //
 | 
						|
  ConsoleInDev->ScrollLock          = FALSE;
 | 
						|
  ConsoleInDev->NumLock             = FALSE;
 | 
						|
  ConsoleInDev->CapsLock            = FALSE;
 | 
						|
  ConsoleInDev->IsSupportPartialKey = FALSE;
 | 
						|
 | 
						|
  if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
 | 
						|
    ConsoleInDev->ScrollLock = TRUE;
 | 
						|
  }
 | 
						|
  if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
 | 
						|
    ConsoleInDev->NumLock = TRUE;
 | 
						|
  }
 | 
						|
  if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
 | 
						|
    ConsoleInDev->CapsLock = TRUE;
 | 
						|
  }
 | 
						|
  if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
 | 
						|
    ConsoleInDev->IsSupportPartialKey = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = UpdateStatusLights (ConsoleInDev);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
Exit:
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return Status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
    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 data 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 or KeyNotificationFunction is NULL.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KeyboardRegisterKeyNotify (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN EFI_KEY_DATA                       *KeyData,
 | 
						|
  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
 | 
						|
  OUT VOID                              **NotifyHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | 
						|
  EFI_TPL                               OldTpl;
 | 
						|
  LIST_ENTRY                            *Link;
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *NewNotify;
 | 
						|
 | 
						|
  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  //
 | 
						|
  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
 | 
						|
  //
 | 
						|
  for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
 | 
						|
      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
 | 
						|
        *NotifyHandle = CurrentNotify;
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
        goto Exit;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate resource to save the notification function
 | 
						|
  //
 | 
						|
  NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
 | 
						|
  if (NewNotify == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
 | 
						|
  NewNotify->Signature         = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
 | 
						|
  NewNotify->KeyNotificationFn = KeyNotificationFunction;
 | 
						|
  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
 | 
						|
  InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
 | 
						|
 | 
						|
  *NotifyHandle                = NewNotify;
 | 
						|
  Status                       = EFI_SUCCESS;
 | 
						|
 | 
						|
Exit:
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
  return Status;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
    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
 | 
						|
KeyboardUnregisterKeyNotify (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | 
						|
  IN VOID                               *NotificationHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | 
						|
  EFI_TPL                               OldTpl;
 | 
						|
  LIST_ENTRY                            *Link;
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;
 | 
						|
 | 
						|
  if (NotificationHandle == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Enter critical section
 | 
						|
  //
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
 | 
						|
  for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
 | 
						|
    CurrentNotify = CR (
 | 
						|
                      Link,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                      NotifyEntry,
 | 
						|
                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                      );
 | 
						|
    if (CurrentNotify == NotificationHandle) {
 | 
						|
      //
 | 
						|
      // Remove the notification function from NotifyList and free resources
 | 
						|
      //
 | 
						|
      RemoveEntryList (&CurrentNotify->NotifyEntry);
 | 
						|
 | 
						|
      gBS->FreePool (CurrentNotify);
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      goto Exit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Can not find the specified Notification Handle
 | 
						|
  //
 | 
						|
  Status = EFI_INVALID_PARAMETER;
 | 
						|
Exit:
 | 
						|
  //
 | 
						|
  // Leave critical section and return
 | 
						|
  //
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV       *ConsoleIn;
 | 
						|
  EFI_KEY_DATA                  KeyData;
 | 
						|
  LIST_ENTRY                    *Link;
 | 
						|
  LIST_ENTRY                    *NotifyList;
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
 | 
						|
  EFI_TPL                       OldTpl;
 | 
						|
 | 
						|
  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
 | 
						|
 | 
						|
  //
 | 
						|
  // Invoke notification functions.
 | 
						|
  //
 | 
						|
  NotifyList = &ConsoleIn->NotifyList;
 | 
						|
  while (TRUE) {
 | 
						|
    //
 | 
						|
    // Enter critical section
 | 
						|
    //
 | 
						|
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | 
						|
    Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
 | 
						|
    //
 | 
						|
    // Leave critical section
 | 
						|
    //
 | 
						|
    gBS->RestoreTPL (OldTpl);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | 
						|
      CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
 | 
						|
      if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
 | 
						|
        CurrentNotify->KeyNotificationFn (&KeyData);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 |