Ejemplo n.º 1
0
/**
  Issue keyboard command.

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Data      The buff holding the command

  @retval EFI_TIMEOUT Keyboard is not ready to issuing
  @retval EFI_SUCCESS Success to issue keyboard command

**/
EFI_STATUS
KeyboardCommand (
    IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
    IN UINT8                   Data
)
{
    UINT32  TimeOut;
    UINT32  RegEmptied;

    TimeOut     = 0;
    RegEmptied  = 0;

    //
    // Wait For Input Buffer Empty
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
        if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
            RegEmptied = 1;
            break;
        }

        MicroSecondDelay (30);
    }

    if (RegEmptied == 0) {
        return EFI_TIMEOUT;
    }
    //
    // issue the command
    //
    KeyWriteCommandRegister (ConsoleIn, Data);

    //
    // Wait For Input Buffer Empty again
    //
    RegEmptied = 0;
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
        if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
            RegEmptied = 1;
            break;
        }

        MicroSecondDelay (30);
    }

    if (RegEmptied == 0) {
        return EFI_TIMEOUT;
    }

    return EFI_SUCCESS;
}
Ejemplo n.º 2
0
/**
  write key to keyboard

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Data      value wanted to be written

  @retval EFI_TIMEOUT   The input buffer register is full for putting new value util timeout
  @retval EFI_SUCCESS   The new value is sucess put into input buffer register.

**/
EFI_STATUS
KeyboardWrite (
    IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
    IN UINT8                   Data
)
{
    UINT32  TimeOut;
    UINT32  RegEmptied;

    TimeOut     = 0;
    RegEmptied  = 0;

    //
    // wait for input buffer empty
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
        if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
            RegEmptied = 1;
            break;
        }

        MicroSecondDelay (30);
    }

    if (RegEmptied == 0) {
        return EFI_TIMEOUT;
    }
    //
    // Write it
    //
    KeyWriteDataRegister (ConsoleIn, Data);

    return EFI_SUCCESS;
}
Ejemplo n.º 3
0
/**
  Read key value .

  @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Data      - Pointer to outof buffer for keeping key value

  @retval EFI_TIMEOUT Status resigter time out
  @retval EFI_SUCCESS Success to read keyboard

**/
EFI_STATUS
KeyboardRead (
    IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
    OUT UINT8                   *Data
)

{
    UINT32  TimeOut;
    UINT32  RegFilled;

    TimeOut   = 0;
    RegFilled = 0;

    //
    // wait till output buffer full then perform the read
    //
    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
        if (KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
            RegFilled = 1;
            *Data     = KeyReadDataRegister (ConsoleIn);
            break;
        }

        MicroSecondDelay (30);
    }

    if (RegFilled == 0) {
        return EFI_TIMEOUT;
    }

    return EFI_SUCCESS;
}
Ejemplo n.º 4
0
/**
  Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
  
  @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
  @param Controller   driver controller handle
  @param RemainingDevicePath Children's device path
  
  @retval whether success to create floppy control instance.
**/
EFI_STATUS
EFIAPI
KbdControllerDriverStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
{
  EFI_STATUS                                Status;
  EFI_STATUS                                Status1;
  EFI_ISA_IO_PROTOCOL                       *IsaIo;
  KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
  UINT8                                     Data;
  EFI_STATUS_CODE_VALUE                     StatusCode;
  EFI_DEVICE_PATH_PROTOCOL                  *ParentDevicePath;

  StatusCode = 0;

  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Report that the keyboard is being enabled
  //
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    EFI_PROGRESS_CODE,
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
    ParentDevicePath
    );

  //
  // Get the ISA I/O Protocol on Controller's handle
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiIsaIoProtocolGuid,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    gBS->CloseProtocol (
           Controller,
           &gEfiDevicePathProtocolGuid,
           This->DriverBindingHandle,
           Controller
           );
    return EFI_INVALID_PARAMETER;
  }
  //
  // Allocate private data
  //
  ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
  if (ConsoleIn == NULL) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
  //
  // Setup the device instance
  //
  ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
  ConsoleIn->Handle                 = Controller;
  (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
  (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
  ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
  ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
  ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
  ConsoleIn->IsaIo                  = IsaIo;
  ConsoleIn->DevicePath             = ParentDevicePath;

  ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
  ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
  ConsoleIn->ConInEx.SetState            = KeyboardSetState;
  ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
  ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;  
  
  InitializeListHead (&ConsoleIn->NotifyList);

  //
  // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
  // When KBC decode (IO port 0x60/0x64 decode) is not enabled, 
  // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
  // So instead we read status register to detect after read if KBC decode is enabled.
  //
  
  //
  // Return code is ignored on purpose.
  //
  if (!PcdGetBool (PcdFastPS2Detection)) {
    KeyboardRead (ConsoleIn, &Data);
    if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
      //
      // If nobody decodes KBC I/O port, it will read back as 0xFF.
      // Check the Time-Out and Parity bit to see if it has an active KBC in system
      //
      Status      = EFI_DEVICE_ERROR;
      StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
      goto ErrorExit;
    }
  }
  
  //
  // Setup the WaitForKey event
  //
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_WAIT,
                  TPL_NOTIFY,
                  KeyboardWaitForKey,
                  ConsoleIn,
                  &((ConsoleIn->ConIn).WaitForKey)
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
  //
  // Setup the WaitForKeyEx event
  //  
  Status = gBS->CreateEvent (
                  EVT_NOTIFY_WAIT,
                  TPL_NOTIFY,
                  KeyboardWaitForKeyEx,
                  ConsoleIn,
                  &(ConsoleIn->ConInEx.WaitForKeyEx)
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
  // Setup a periodic timer, used for reading keystrokes at a fixed interval
  //
  Status = gBS->CreateEvent (
                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
                  TPL_NOTIFY,
                  KeyboardTimerHandler,
                  ConsoleIn,
                  &ConsoleIn->TimerEvent
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  Status = gBS->SetTimer (
                  ConsoleIn->TimerEvent,
                  TimerPeriodic,
                  KEYBOARD_TIMER_INTERVAL
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    EFI_PROGRESS_CODE,
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
    ParentDevicePath
    );

  //
  // Reset the keyboard device
  //
  Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));
  if (EFI_ERROR (Status)) {
    Status      = EFI_DEVICE_ERROR;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    goto ErrorExit;
  }

  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    EFI_PROGRESS_CODE,
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
    ParentDevicePath
    );

  ConsoleIn->ControllerNameTable = NULL;
  AddUnicodeString2 (
    "eng",
    gPs2KeyboardComponentName.SupportedLanguages,
    &ConsoleIn->ControllerNameTable,
    L"PS/2 Keyboard Device",
    TRUE
    );
  AddUnicodeString2 (
    "en",
    gPs2KeyboardComponentName2.SupportedLanguages,
    &ConsoleIn->ControllerNameTable,
    L"PS/2 Keyboard Device",
    FALSE
    );


  //
  // Install protocol interfaces for the keyboard device.
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Controller,
                  &gEfiSimpleTextInProtocolGuid,
                  &ConsoleIn->ConIn,
                  &gEfiSimpleTextInputExProtocolGuid,
                  &ConsoleIn->ConInEx,
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  return Status;

ErrorExit:
  //
  // Report error code
  //
  if (StatusCode != 0) {
    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
      StatusCode,
      ParentDevicePath
      );
  }

  if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
    gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
  }

  if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
    gBS->CloseEvent (ConsoleIn->TimerEvent);
  }
  if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
  }
  KbdFreeNotifyList (&ConsoleIn->NotifyList);
  if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
    FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
  }
  //
  // Since there will be no timer handler for keyboard input any more,
  // exhaust input data just in case there is still keyboard data left
  //
  if (ConsoleIn != NULL) {
    Status1 = EFI_SUCCESS;
    while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
      Status1 = KeyboardRead (ConsoleIn, &Data);;
    }
  }
  
  if (ConsoleIn != NULL) {
    gBS->FreePool (ConsoleIn);
  }

  gBS->CloseProtocol (
         Controller,
         &gEfiDevicePathProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  gBS->CloseProtocol (
         Controller,
         &gEfiIsaIoProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
Ejemplo n.º 5
0
/**
  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;
  }
  //
  // Clear the status of ConsoleIn.Key
  //
  ConsoleIn->Key.ScanCode     = SCAN_NULL;
  ConsoleIn->Key.UnicodeChar  = 0x0000;

  //
  // 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;
}
Ejemplo n.º 6
0
EFI_STATUS
EFIAPI
KbdControllerDriverStart (
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
  IN EFI_HANDLE                     Controller,
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
  )
/*++

Routine Description:

Arguments:

Returns:

--*/
// GC_TODO:    This - add argument and description to function comment
// GC_TODO:    Controller - add argument and description to function comment
// GC_TODO:    RemainingDevicePath - add argument and description to function comment
// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment
{
  EFI_STATUS                                Status;
  EFI_STATUS                                Status1;
  EFI_INTERFACE_DEFINITION_FOR_ISA_IO       *IsaIo;
  KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
  UINT8                                     Data;
  EFI_STATUS_CODE_VALUE                     StatusCode;
  EFI_DEVICE_PATH_PROTOCOL                  *ParentDevicePath;

  StatusCode = 0;

  Status = gBS->OpenProtocol (
                  Controller,
                  &gEfiDevicePathProtocolGuid,
                  (VOID **) &ParentDevicePath,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return Status;
  }
  //
  // Report that the keyboard is being enabled
  //
  ReportStatusCodeWithDevicePath (
    EFI_PROGRESS_CODE,
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
    0,
    &gEfiCallerIdGuid,
    ParentDevicePath
    );

  //
  // Get the ISA I/O Protocol on Controller's handle
  //
  Status = gBS->OpenProtocol (
                  Controller,
                  EFI_ISA_IO_PROTOCOL_VERSION,
                  (VOID **) &IsaIo,
                  This->DriverBindingHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    gBS->CloseProtocol (
           Controller,
           &gEfiDevicePathProtocolGuid,
           This->DriverBindingHandle,
           Controller
           );
    return EFI_INVALID_PARAMETER;
  }
  //
  // Allocate private data
  //
  ConsoleIn = EfiLibAllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
  if (ConsoleIn == NULL) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
  //
  // Setup the device instance
  //
  ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
  ConsoleIn->Handle                 = Controller;
  (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
  (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
  ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
  ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
  ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
  ConsoleIn->IsaIo                  = IsaIo;
  ConsoleIn->ScancodeBufStartPos    = 0;
  ConsoleIn->ScancodeBufEndPos      = KEYBOARD_BUFFER_MAX_COUNT - 1;
  ConsoleIn->ScancodeBufCount       = 0;
  ConsoleIn->Ctrled                 = FALSE;
  ConsoleIn->Alted                  = FALSE;
  ConsoleIn->DevicePath             = ParentDevicePath;

#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
#ifndef DISABLE_CONSOLE_EX
  ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
  ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
  ConsoleIn->ConInEx.SetState            = KeyboardSetState;
  ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
  ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;  
  
  InitializeListHead (&ConsoleIn->NotifyList);
#endif  // DISABLE_CONSOLE_EX
#endif

  //
  // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
  //
  KeyboardRead (ConsoleIn, &Data);
  if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
    //
    // If nobody decodes KBC I/O port, it will read back as 0xFF.
    // Check the Time-Out and Parity bit to see if it has an active KBC in system
    //
    Status      = EFI_DEVICE_ERROR;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    goto ErrorExit;
  }

  //
  // Setup the WaitForKey event
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_WAIT,
                  EFI_TPL_NOTIFY,
                  KeyboardWaitForKey,
                  &(ConsoleIn->ConIn),
                  &((ConsoleIn->ConIn).WaitForKey)
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
#ifndef DISABLE_CONSOLE_EX  
  //
  // Setup the WaitForKeyEx event
  //  
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_WAIT,
                  EFI_TPL_NOTIFY,
                  KeyboardWaitForKeyEx,
                  &(ConsoleIn->ConInEx),
                  &(ConsoleIn->ConInEx.WaitForKeyEx)
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }
#endif  // DISABLE_CONSOLE_EX
#endif
  //
  // Setup a periodic timer, used for reading keystrokes at a fixed interval
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_NOTIFY,
                  KeyboardTimerHandler,
                  ConsoleIn,
                  &ConsoleIn->TimerEvent
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  Status = gBS->SetTimer (
                  ConsoleIn->TimerEvent,
                  TimerPeriodic,
                  KEYBOARD_TIMER_INTERVAL
                  );
  if (EFI_ERROR (Status)) {
    Status      = EFI_OUT_OF_RESOURCES;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  ReportStatusCodeWithDevicePath (
    EFI_PROGRESS_CODE,
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
    0,
    &gEfiCallerIdGuid,
    ParentDevicePath
    );

  //
  // Reset the keyboard device
  //
  Status = ConsoleIn->ConIn.Reset (&ConsoleIn->ConIn, TRUE);
  if (EFI_ERROR (Status)) {
    Status      = EFI_DEVICE_ERROR;
    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    goto ErrorExit;
  }

  ConsoleIn->ControllerNameTable = NULL;
  EfiLibAddUnicodeString (
    LANGUAGE_CODE_ENGLISH,
    gPs2KeyboardComponentName.SupportedLanguages,
    &ConsoleIn->ControllerNameTable,
    L"PS/2 Keyboard Device"
    );

  //
  // Install protocol interfaces for the keyboard device.
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &Controller,
                  &gEfiSimpleTextInProtocolGuid,
                  &ConsoleIn->ConIn,
#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
#ifndef DISABLE_CONSOLE_EX  
                  &gEfiSimpleTextInputExProtocolGuid,
                  &ConsoleIn->ConInEx,
#endif  // DISABLE_CONSOLE_EX
#endif
                  NULL
                  );
  if (EFI_ERROR (Status)) {
    StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    goto ErrorExit;
  }

  return Status;

ErrorExit:
  //
  // Report error code
  //
  if (StatusCode != 0) {
    ReportStatusCodeWithDevicePath (
      EFI_ERROR_CODE | EFI_ERROR_MINOR,
      StatusCode,
      0,
      &gEfiCallerIdGuid,
      ParentDevicePath
      );
  }

  if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
    gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
  }

  if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
    gBS->CloseEvent (ConsoleIn->TimerEvent);
  }
#if (EFI_SPECIFICATION_VERSION >= 0x0002000A)
#ifndef DISABLE_CONSOLE_EX  
  if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
  }
  KbdFreeNotifyList (&ConsoleIn->NotifyList);
#endif  // DISABLE_CONSOLE_EX
#endif
  if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
    EfiLibFreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
  }
  //
  // Since there will be no timer handler for keyboard input any more,
  // exhaust input data just in case there is still keyboard data left
  //
  Status1 = EFI_SUCCESS;
  while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
    Status1 = KeyboardRead (ConsoleIn, &Data);;
  }

  if (ConsoleIn != NULL) {
    gBS->FreePool (ConsoleIn);
  }

  gBS->CloseProtocol (
         Controller,
         &gEfiDevicePathProtocolGuid,
         This->DriverBindingHandle,
         Controller
         );

  gBS->CloseProtocol (
         Controller,
         EFI_ISA_IO_PROTOCOL_VERSION,
         This->DriverBindingHandle,
         Controller
         );

  return Status;
}
Ejemplo n.º 7
0
/**
  Timer event handler: read a series of scancodes from 8042
  and put them into memory scancode buffer.
  it read as much scancodes to either fill
  the memory buffer or empty the keyboard buffer.
  It is registered as running under TPL_NOTIFY

  @param Event       The timer event
  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer

**/
VOID
EFIAPI
KeyboardTimerHandler (
    IN EFI_EVENT    Event,
    IN VOID         *Context
)

{
    UINT8                   Data;
    EFI_TPL                 OldTpl;
    KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;

    ConsoleIn = Context;

    //
    // Enter critical section
    //
    OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

    if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
        //
        // Leave critical section and return
        //
        gBS->RestoreTPL (OldTpl);
        return ;
    }

    //
    // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
    // KB is not connected to system. If KB is not connected to system, driver will find there's  something
    // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since
    // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
    // Just skip the 'resend' process simply.
    //

    Data = 0;

    //
    // if there is no key present, just return
    //
    if ((KeyReadStatusRegister (Context) & (KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA)) != KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
        //
        // Leave critical section and return
        //
        gBS->RestoreTPL (OldTpl);

        return ;
    }
    //
    // Read one byte of the scan code and store it into the memory buffer
    //
    if (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT) {

        Data = KeyReadDataRegister (Context);
        //
        // put the scancode into the memory scancode buffer
        //
        ConsoleIn->ScancodeBufCount++;
        ConsoleIn->ScancodeBufEndPos++;
        if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
            ConsoleIn->ScancodeBufEndPos = 0;
        }

        ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Data;

        //
        // Handle Alt+Ctrl+Del Key combination
        //
        switch (Data) {
        case SCANCODE_CTRL_MAKE:
            ConsoleIn->Ctrled = TRUE;
            break;

        case SCANCODE_CTRL_BREAK:
            ConsoleIn->Ctrled = FALSE;
            break;

        case SCANCODE_ALT_MAKE:
            ConsoleIn->Alted = TRUE;
            break;

        case SCANCODE_ALT_BREAK:
            ConsoleIn->Alted = FALSE;
            break;
        }
        //
        // if Alt+Ctrl+Del, Reboot the System
        //
        if (ConsoleIn->Ctrled && ConsoleIn->Alted && Data == 0x53) {
            gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
        }
    }
    //
    // Leave critical section and return
    //
    gBS->RestoreTPL (OldTpl);

    return ;
}
Ejemplo n.º 8
0
/**
  Perform 8042 controller and keyboard Initialization.
  If ExtendedVerification is TRUE, do additional test for
  the keyboard interface

  @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
  @param ExtendedVerification - indicates a thorough initialization

  @retval EFI_DEVICE_ERROR Fail to init keyboard
  @retval EFI_SUCCESS      Success to init keyboard
**/
EFI_STATUS
InitKeyboard (
    IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
    IN BOOLEAN                     ExtendedVerification
)
{
    EFI_STATUS              Status;
    EFI_STATUS              Status1;
    UINT8                   CommandByte;
    EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
    UINT32                  TryTime;

    Status                 = EFI_SUCCESS;
    mEnableMouseInterface  = TRUE;
    TryTime                = 0;

    //
    // Get Ps2 policy to set this
    //
    gBS->LocateProtocol (
        &gEfiPs2PolicyProtocolGuid,
        NULL,
        (VOID **) &Ps2Policy
    );

    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
        EFI_PROGRESS_CODE,
        EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
        ConsoleIn->DevicePath
    );

    //
    // Perform a read to cleanup the Status Register's
    // output buffer full bits within MAX TRY times
    //
    while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
        Status = KeyboardRead (ConsoleIn, &CommandByte);
        TryTime ++;
    }
    //
    // Exceed the max try times. The device may be error.
    //
    if (TryTime == KEYBOARD_MAX_TRY) {
        Status = EFI_DEVICE_ERROR;
        goto Done;
    }
    //
    // We should disable mouse interface during the initialization process
    // since mouse device output could block keyboard device output in the
    // 60H port of 8042 controller.
    //
    // So if we are not initializing 8042 controller for the
    // first time, we have to remember the previous mouse interface
    // enabling state
    //
    // Test the system flag in to determine whether this is the first
    // time initialization
    //
    if ((KeyReadStatusRegister (ConsoleIn) & KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
        //
        // 8042 controller is already setup (by myself or by mouse driver):
        //   See whether mouse interface is already enabled
        //   which determines whether we should enable it later
        //
        //
        // Read the command byte of 8042 controller
        //
        Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"\n\r");
            goto Done;
        }

        Status = KeyboardRead (ConsoleIn, &CommandByte);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"\n\r");
            goto Done;
        }
        //
        // Test the mouse enabling bit
        //
        if ((CommandByte & 0x20) != 0) {
            mEnableMouseInterface = FALSE;
        } else {
            mEnableMouseInterface = TRUE;
        }

    } else {
        //
        // 8042 controller is not setup yet:
        //   8042 controller selftest;
        //   Don't enable mouse interface later.
        //
        //
        // Disable keyboard and mouse interfaces
        //
        Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"\n\r");
            goto Done;
        }

        Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"\n\r");
            goto Done;
        }

        REPORT_STATUS_CODE_WITH_DEVICE_PATH (
            EFI_PROGRESS_CODE,
            EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
            ConsoleIn->DevicePath
        );
        //
        // 8042 Controller Self Test
        //
        Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, 0x55);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
            goto Done;
        }
        //
        // Don't enable mouse interface later
        //
        mEnableMouseInterface = FALSE;

    }

    if (Ps2Policy != NULL) {
        Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
    }
    //
    // Write 8042 Command Byte, set System Flag
    // While at the same time:
    //  1. disable mouse interface,
    //  2. enable kbd interface,
    //  3. enable PC/XT kbd translation mode
    //  4. enable mouse and kbd interrupts
    //
    //  ( Command Byte bits:
    //  7: Reserved
    //  6: PC/XT translation mode
    //  5: Disable Auxiliary device interface
    //  4: Disable keyboard interface
    //  3: Reserved
    //  2: System Flag
    //  1: Enable Auxiliary device interrupt
    //  0: Enable Keyboard interrupt )
    //
    Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
    if (EFI_ERROR (Status)) {
        KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
        goto Done;
    }

    Status = KeyboardWrite (ConsoleIn, 0x67);
    if (EFI_ERROR (Status)) {
        KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
        goto Done;
    }

    //
    // Clear Memory Scancode Buffer
    //
    ConsoleIn->ScancodeBufStartPos  = 0;
    ConsoleIn->ScancodeBufEndPos    = KEYBOARD_BUFFER_MAX_COUNT - 1;
    ConsoleIn->ScancodeBufCount     = 0;
    ConsoleIn->Ctrled               = FALSE;
    ConsoleIn->Alted                = FALSE;

    //
    // Reset the status indicators
    //
    ConsoleIn->Ctrl       = FALSE;
    ConsoleIn->Alt        = FALSE;
    ConsoleIn->Shift      = FALSE;
    ConsoleIn->CapsLock   = FALSE;
    ConsoleIn->NumLock    = FALSE;
    ConsoleIn->ScrollLock = FALSE;
    ConsoleIn->LeftShift  = FALSE;
    ConsoleIn->RightShift = FALSE;
    ConsoleIn->LeftLogo   = FALSE;
    ConsoleIn->RightLogo  = FALSE;
    ConsoleIn->Menu       = FALSE;
    ConsoleIn->SysReq     = FALSE;

    //
    // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
    // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected
    // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system,
    // and normally during booting an OS, it's skipped.
    //
    if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
        //
        // Additional verifications for keyboard interface
        //
        //
        // Keyboard Interface Test
        //
        Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, 0x00);
        if (EFI_ERROR (Status)) {
            KeyboardError (
                ConsoleIn,
                L"Some specific value not aquired from 8042 controller!\n\r"
            );
            goto Done;
        }
        //
        // Keyboard reset with a BAT(Basic Assurance Test)
        //
        Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
            goto Done;
        }
        //
        // wait for BAT completion code
        //
        mWaitForValueTimeOut  = KEYBOARD_BAT_TIMEOUT;

        Status                = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
            goto Done;
        }

        mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;

        //
        // Set Keyboard to use Scan Code Set 2
        //
        Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
            goto Done;
        }

        Status = KeyboardWrite (ConsoleIn, 0x02);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
            goto Done;
        }

        //
        // Clear Keyboard Scancode Buffer
        //
        Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
            goto Done;
        }

        Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r");
            goto Done;
        }
        //
        if (Ps2Policy != NULL) {
            if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
                ConsoleIn->CapsLock = TRUE;
            }

            if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
                ConsoleIn->NumLock = TRUE;
            }

            if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
                ConsoleIn->ScrollLock = TRUE;
            }
        }
        //
        // Update Keyboard Lights
        //
        Status = UpdateStatusLights (ConsoleIn);
        if (EFI_ERROR (Status)) {
            KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
            goto Done;
        }
    }
    //
    // At last, we can now enable the mouse interface if appropriate
    //
Done:

    if (mEnableMouseInterface) {
        //
        // Enable mouse interface
        //
        Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
        if (EFI_ERROR (Status1)) {
            KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
            return EFI_DEVICE_ERROR;
        }
    }

    if (!EFI_ERROR (Status)) {
        return EFI_SUCCESS;
    } else {
        return EFI_DEVICE_ERROR;
    }

}
Ejemplo n.º 9
0
/**
  Get scancode from scancode buffer
  and translate into EFI-scancode and unicode defined by EFI spec
  The function is always called in TPL_NOTIFY

  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer

  @retval EFI_NOT_READY  Input from console not ready yet.
  @retval EFI_SUCCESS    Function executed successfully.

**/
EFI_STATUS
KeyGetchar (
    IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
)
{
    EFI_STATUS  Status;
    UINT8       ScanCode;
    UINT8       Readed;
    BOOLEAN     Extended;
    UINT8       ScancodeArr[4];
    UINTN       Index;
    //
    // 4 bytes most
    //
    UINT32      ScancodeArrPos;
    //
    // point to the current position in ScancodeArr
    //

    Readed          = 0;
    Extended        = FALSE;
    ScancodeArrPos  = 0;

    //
    // Read one byte of the scan code and store it into the memory buffer
    // This block of code is added to insert an action that is equivalent to
    // the timer event handling function, so as to increase the frequency of
    // detecting the availability of keys. Timer event has a max frequency of
    // 18Hz which is insufficient
    //
    //
    // To let KB driver support Hot plug, here should skip the 'resend' command  for the case that
    // KB is not connected to system. If KB is not connected to system, driver will find there's  something
    // error in the following code and wait for the input buffer empty, this waiting time shoulb be  short enough since
    // this is a NOTIFY TPL period function, or the system performance will degrade hardly when KB is not connected.
    // Just skip the 'resend' process simply.
    //


    if (((KeyReadStatusRegister (ConsoleIn) & 0x21) == 0x1) && (ConsoleIn->ScancodeBufCount < KEYBOARD_BUFFER_MAX_COUNT)) {

        Readed = KeyReadDataRegister (ConsoleIn);
        //
        // put the scancode into the memory scancode buffer
        //
        ConsoleIn->ScancodeBufCount++;
        ConsoleIn->ScancodeBufEndPos++;
        if (ConsoleIn->ScancodeBufEndPos >= KEYBOARD_BUFFER_MAX_COUNT) {
            ConsoleIn->ScancodeBufEndPos = 0;
        }

        ConsoleIn->ScancodeBuf[ConsoleIn->ScancodeBufEndPos] = Readed;

        //
        // Handle Alt+Ctrl+Del Key combination
        //
        switch (Readed) {

        case SCANCODE_CTRL_MAKE:
            ConsoleIn->Ctrled = TRUE;
            break;

        case SCANCODE_CTRL_BREAK:
            ConsoleIn->Ctrled = FALSE;
            break;

        case SCANCODE_ALT_MAKE:
            ConsoleIn->Alted = TRUE;
            break;

        case SCANCODE_ALT_BREAK:
            ConsoleIn->Alted = FALSE;
            break;
        }
        //
        // if Alt+Ctrl+Del, Reboot the System
        //
        if (ConsoleIn->Ctrled && ConsoleIn->Alted && Readed == 0x53) {
            gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
        }
    }
    //
    // Check if there are enough bytes of scancode representing a single key
    // available in the buffer
    //
    while (TRUE) {

        Status          = GetScancodeBufHead (ConsoleIn, 1, ScancodeArr);
        ScancodeArrPos  = 0;
        if (EFI_ERROR (Status)) {
            return EFI_NOT_READY;
        }

        if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED) {
            Extended        = TRUE;
            Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
            ScancodeArrPos  = 1;
            if (EFI_ERROR (Status)) {
                return EFI_NOT_READY;
            }
        }
        //
        // Checks for key scancode for PAUSE:E1-1D/45-E1/9D-C5
        // if present, ignore them
        //
        if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {

            Status          = GetScancodeBufHead (ConsoleIn, 2, ScancodeArr);
            ScancodeArrPos  = 1;

            if (EFI_ERROR (Status)) {
                return EFI_NOT_READY;
            }

            Status          = GetScancodeBufHead (ConsoleIn, 3, ScancodeArr);
            ScancodeArrPos  = 2;

            if (EFI_ERROR (Status)) {
                return EFI_NOT_READY;
            }

            PopScancodeBufHead (ConsoleIn, 3, ScancodeArr);
            return EFI_NOT_READY;
        }
        //
        // if we reach this position, scancodes for a key is in buffer now,pop them
        //
        Status = PopScancodeBufHead (ConsoleIn, ScancodeArrPos + 1, ScancodeArr);
        if (EFI_ERROR (Status)) {
            return EFI_NOT_READY;
        }
        //
        // store the last available byte, this byte of scancode will be checked
        //
        ScanCode = ScancodeArr[ScancodeArrPos];

        //
        // Check for special keys and update the driver state.
        //
        switch (ScanCode) {

        case SCANCODE_CTRL_MAKE:
            ConsoleIn->Ctrl = TRUE;
            break;

        case SCANCODE_CTRL_BREAK:
            ConsoleIn->Ctrl = FALSE;
            break;

        case SCANCODE_ALT_MAKE:
            ConsoleIn->Alt = TRUE;
            break;

        case SCANCODE_ALT_BREAK:
            ConsoleIn->Alt = FALSE;
            break;

        case SCANCODE_LEFT_SHIFT_MAKE:
            if (!Extended) {
                ConsoleIn->Shift     = TRUE;
                ConsoleIn->LeftShift = TRUE;
            }
            break;
        case SCANCODE_RIGHT_SHIFT_MAKE:
            if (!Extended) {
                ConsoleIn->Shift = TRUE;
                ConsoleIn->RightShift = TRUE;
            }
            break;

        case SCANCODE_LEFT_SHIFT_BREAK:
            if (!Extended) {
                ConsoleIn->Shift     = FALSE;
                ConsoleIn->LeftShift = FALSE;
            } else {
                ConsoleIn->SysReq    = FALSE;
            }
            break;
        case SCANCODE_RIGHT_SHIFT_BREAK:
            if (!Extended) {
                ConsoleIn->Shift = FALSE;
                ConsoleIn->RightShift = FALSE;
            }
            break;

        case SCANCODE_LEFT_LOGO_MAKE:
            ConsoleIn->LeftLogo = TRUE;
            break;
        case SCANCODE_LEFT_LOGO_BREAK:
            ConsoleIn->LeftLogo = FALSE;
            break;
        case SCANCODE_RIGHT_LOGO_MAKE:
            ConsoleIn->RightLogo = TRUE;
            break;
        case SCANCODE_RIGHT_LOGO_BREAK:
            ConsoleIn->RightLogo = FALSE;
            break;
        case SCANCODE_MENU_MAKE:
            ConsoleIn->Menu = TRUE;
            break;
        case SCANCODE_MENU_BREAK:
            ConsoleIn->Menu = FALSE;
            break;
        case SCANCODE_SYS_REQ_MAKE:
            if (Extended) {
                ConsoleIn->SysReq = TRUE;
            }
        case SCANCODE_CAPS_LOCK_MAKE:
            ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
            UpdateStatusLights (ConsoleIn);
            break;

        case SCANCODE_NUM_LOCK_MAKE:
            ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
            UpdateStatusLights (ConsoleIn);
            break;

        case SCANCODE_SCROLL_LOCK_MAKE:
            ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
            UpdateStatusLights (ConsoleIn);
            break;
        }
        //
        // If this is a BREAK Key or above the valid range, ignore it
        //
        if (ScanCode >= SCANCODE_MAX_MAKE) {
            continue;
        } else {
            break;
        }
    }
    //
    // Treat Numeric Key Pad "/" specially
    //
    if (Extended && ScanCode == 0x35) {
        ConsoleIn->Key.ScanCode     = SCAN_NULL;
        ConsoleIn->Key.UnicodeChar  = L'/';
        return EFI_SUCCESS;
    }
    //
    // Convert Keyboard ScanCode into an EFI Key
    //
    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != TABLE_END; Index += 1) {
        if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
            ConsoleIn->Key.ScanCode = ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
            if (ConsoleIn->Shift) {
                ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
                //
                // Need not return associated shift state if a class of printable characters that
                // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' key = 'F'
                //
                if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {
                    ConsoleIn->LeftShift  = FALSE;
                    ConsoleIn->RightShift = FALSE;
                }
            } else {
                ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
            }
            //
            // alphabetic key is affected by CapsLock State
            //
            if (ConsoleIn->CapsLock) {
                if (ConsoleIn->Key.UnicodeChar >= L'a' && ConsoleIn->Key.UnicodeChar <= L'z') {
                    ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
                } else if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {
                    ConsoleIn->Key.UnicodeChar = ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
                }
            }
            //
            // Translate the CTRL-Alpha characters to their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
            //
            if (ConsoleIn->Ctrled) {
                if (ConsoleIn->Key.UnicodeChar >= L'a' && ConsoleIn->Key.UnicodeChar <= L'z') {
                    ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - L'a' + 1);
                } else if (ConsoleIn->Key.UnicodeChar >= L'A' && ConsoleIn->Key.UnicodeChar <= L'Z') {
                    ConsoleIn->Key.UnicodeChar = (UINT16) (ConsoleIn->Key.UnicodeChar - L'A' + 1);
                }
            }

            break;
        }
    }

    //
    // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
    //
    if (ScanCode >= 0x47 && ScanCode <= 0x53) {

        if (ConsoleIn->NumLock && !ConsoleIn->Shift && !Extended) {
            ConsoleIn->Key.ScanCode = SCAN_NULL;
        } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
            ConsoleIn->Key.UnicodeChar = 0x0000;
        }
    }
    //
    // If the key can not be converted then just return.
    //
    if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x0000) {
        return EFI_NOT_READY;
    }

    //
    // Save the Shift/Toggle state
    //
    if (ConsoleIn->Ctrl) {
        ConsoleIn->KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_CONTROL_PRESSED : EFI_LEFT_CONTROL_PRESSED;
    }
    if (ConsoleIn->Alt) {
        ConsoleIn->KeyState.KeyShiftState  |= (Extended) ? EFI_RIGHT_ALT_PRESSED : EFI_LEFT_ALT_PRESSED;
    }
    if (ConsoleIn->LeftShift) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;
    }
    if (ConsoleIn->RightShift) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;
    }
    if (ConsoleIn->LeftLogo) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_LEFT_LOGO_PRESSED;
    }
    if (ConsoleIn->RightLogo) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_RIGHT_LOGO_PRESSED;
    }
    if (ConsoleIn->Menu) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_MENU_KEY_PRESSED;
    }
    if (ConsoleIn->SysReq) {
        ConsoleIn->KeyState.KeyShiftState  |= EFI_SYS_REQ_PRESSED;
    }
    if (ConsoleIn->CapsLock) {
        ConsoleIn->KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
    }
    if (ConsoleIn->NumLock) {
        ConsoleIn->KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
    }
    if (ConsoleIn->ScrollLock) {
        ConsoleIn->KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
    }

    return EFI_SUCCESS;
}
Ejemplo n.º 10
0
/**
  wait for a specific value to be presented on
  8042 Data register by keyboard and then read it,
  used in keyboard commands ack

  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
  @param Value     the value wanted to be waited.

  @retval EFI_TIMEOUT Fail to get specific value in given time
  @retval EFI_SUCCESS Success to get specific value in given time.

**/
EFI_STATUS
KeyboardWaitForValue (
    IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
    IN UINT8                   Value
)
{
    UINT8   Data;
    UINT32  TimeOut;
    UINT32  SumTimeOut;
    UINT32  GotIt;

    GotIt       = 0;
    TimeOut     = 0;
    SumTimeOut  = 0;

    //
    // Make sure the initial value of 'Data' is different from 'Value'
    //
    Data = 0;
    if (Data == Value) {
        Data = 1;
    }
    //
    // Read from 8042 (multiple times if needed)
    // until the expected value appears
    // use SumTimeOut to control the iteration
    //
    while (1) {
        //
        // Perform a read
        //
        for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
            if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
                Data = KeyReadDataRegister (ConsoleIn);
                break;
            }

            MicroSecondDelay (30);
        }

        SumTimeOut += TimeOut;

        if (Data == Value) {
            GotIt = 1;
            break;
        }

        if (SumTimeOut >= mWaitForValueTimeOut) {
            break;
        }
    }
    //
    // Check results
    //
    if (GotIt == 1) {
        return EFI_SUCCESS;
    } else {
        return EFI_TIMEOUT;
    }

}