mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 10:19:50 +00:00 
			
		
		
		
	1. Do not use tab characters 2. No trailing white space in one line 3. All files must end with CRLF Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com>
		
			
				
	
	
		
			664 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			664 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
  PS/2 Keyboard driver. Routines that interacts with callers,
 | 
						|
  conforming to EFI driver model
 | 
						|
 | 
						|
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions of the BSD License
 | 
						|
which accompanies this distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Ps2Keyboard.h"
 | 
						|
 | 
						|
//
 | 
						|
// Function prototypes
 | 
						|
//
 | 
						|
/**
 | 
						|
  Test controller is a keyboard Controller.
 | 
						|
 | 
						|
  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
 | 
						|
  @param Controller           driver's controller
 | 
						|
  @param RemainingDevicePath  children device path
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED controller is not floppy disk
 | 
						|
  @retval EFI_SUCCESS     controller is floppy disk
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KbdControllerDriverSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. Support stopping any child handles
 | 
						|
  created by this driver.
 | 
						|
 | 
						|
  @param  This              Protocol instance pointer.
 | 
						|
  @param  ControllerHandle  Handle of device to stop driver on
 | 
						|
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                            children is zero stop the entire bus driver.
 | 
						|
  @param  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       This driver is removed ControllerHandle
 | 
						|
  @retval other             This driver was not removed from this device
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KbdControllerDriverStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN  EFI_HANDLE                     Controller,
 | 
						|
  IN  UINTN                          NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                     *ChildHandleBuffer
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Free the waiting key notify list.
 | 
						|
 | 
						|
  @param ListHead  Pointer to list head
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  ListHead is NULL
 | 
						|
  @retval EFI_SUCCESS            Sucess to free NotifyList
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KbdFreeNotifyList (
 | 
						|
  IN OUT LIST_ENTRY           *ListHead
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// DriverBinding Protocol Instance
 | 
						|
//
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
 | 
						|
  KbdControllerDriverSupported,
 | 
						|
  KbdControllerDriverStart,
 | 
						|
  KbdControllerDriverStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Test controller is a keyboard Controller.
 | 
						|
 | 
						|
  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
 | 
						|
  @param Controller           driver's controller
 | 
						|
  @param RemainingDevicePath  children device path
 | 
						|
 | 
						|
  @retval EFI_UNSUPPORTED controller is not floppy disk
 | 
						|
  @retval EFI_SUCCESS     controller is floppy disk
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KbdControllerDriverSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN EFI_HANDLE                     Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_ISA_IO_PROTOCOL                 *IsaIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the IO Abstraction(s) needed to perform the supported test
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiIsaIoProtocolGuid,
 | 
						|
                  (VOID **) &IsaIo,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
 | 
						|
  //
 | 
						|
  if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Close the I/O Abstraction(s) used to perform the supported test
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiIsaIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_SIGNAL,
 | 
						|
                  TPL_CALLBACK,
 | 
						|
                  KeyNotifyProcessHandler,
 | 
						|
                  ConsoleIn,
 | 
						|
                  &ConsoleIn->KeyNotifyProcessEvent
 | 
						|
                  );
 | 
						|
  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);
 | 
						|
  }
 | 
						|
  if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {
 | 
						|
    gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
 | 
						|
  }
 | 
						|
  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;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. Support stopping any child handles
 | 
						|
  created by this driver.
 | 
						|
 | 
						|
  @param  This              Protocol instance pointer.
 | 
						|
  @param  ControllerHandle  Handle of device to stop driver on
 | 
						|
  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                            children is zero stop the entire bus driver.
 | 
						|
  @param  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       This driver is removed ControllerHandle
 | 
						|
  @retval other             This driver was not removed from this device
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
KbdControllerDriverStop (
 | 
						|
  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
 | 
						|
  IN  EFI_HANDLE                     Controller,
 | 
						|
  IN  UINTN                          NumberOfChildren,
 | 
						|
  IN  EFI_HANDLE                     *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                     Status;
 | 
						|
  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
 | 
						|
  KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
 | 
						|
  UINT8                          Data;
 | 
						|
 | 
						|
  //
 | 
						|
  // Disable Keyboard
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSimpleTextInProtocolGuid,
 | 
						|
                  (VOID **) &ConIn,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSimpleTextInputExProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
 | 
						|
 | 
						|
  //
 | 
						|
  // Report that the keyboard is being disabled
 | 
						|
  //
 | 
						|
  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | 
						|
    EFI_PROGRESS_CODE,
 | 
						|
    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
 | 
						|
    ConsoleIn->DevicePath
 | 
						|
    );
 | 
						|
 | 
						|
  if (ConsoleIn->TimerEvent != NULL) {
 | 
						|
    gBS->CloseEvent (ConsoleIn->TimerEvent);
 | 
						|
    ConsoleIn->TimerEvent = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Since there will be no timer handler for keyboard input any more,
 | 
						|
  // exhaust input data just in case there is still keyboard data left
 | 
						|
  //
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  while (!EFI_ERROR (Status)) {
 | 
						|
    Status = KeyboardRead (ConsoleIn, &Data);;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Uninstall the SimpleTextIn and SimpleTextInEx protocols
 | 
						|
  //
 | 
						|
  Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                  Controller,
 | 
						|
                  &gEfiSimpleTextInProtocolGuid,
 | 
						|
                  &ConsoleIn->ConIn,
 | 
						|
                  &gEfiSimpleTextInputExProtocolGuid,
 | 
						|
                  &ConsoleIn->ConInEx,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiDevicePathProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  gBS->CloseProtocol (
 | 
						|
         Controller,
 | 
						|
         &gEfiIsaIoProtocolGuid,
 | 
						|
         This->DriverBindingHandle,
 | 
						|
         Controller
 | 
						|
         );
 | 
						|
 | 
						|
  //
 | 
						|
  // Free other resources
 | 
						|
  //
 | 
						|
  if ((ConsoleIn->ConIn).WaitForKey != NULL) {
 | 
						|
    gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
 | 
						|
    (ConsoleIn->ConIn).WaitForKey = NULL;
 | 
						|
  }
 | 
						|
  if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
 | 
						|
    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
 | 
						|
    ConsoleIn->ConInEx.WaitForKeyEx = NULL;
 | 
						|
  }
 | 
						|
  if (ConsoleIn->KeyNotifyProcessEvent != NULL) {
 | 
						|
    gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
 | 
						|
    ConsoleIn->KeyNotifyProcessEvent = NULL;
 | 
						|
  }
 | 
						|
  KbdFreeNotifyList (&ConsoleIn->NotifyList);
 | 
						|
  FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
 | 
						|
  gBS->FreePool (ConsoleIn);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Free the waiting key notify list.
 | 
						|
 | 
						|
  @param ListHead  Pointer to list head
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  ListHead is NULL
 | 
						|
  @retval EFI_SUCCESS            Sucess to free NotifyList
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
KbdFreeNotifyList (
 | 
						|
  IN OUT LIST_ENTRY           *ListHead
 | 
						|
  )
 | 
						|
{
 | 
						|
  KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
 | 
						|
 | 
						|
  if (ListHead == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  while (!IsListEmpty (ListHead)) {
 | 
						|
    NotifyNode = CR (
 | 
						|
                   ListHead->ForwardLink,
 | 
						|
                   KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | 
						|
                   NotifyEntry,
 | 
						|
                   KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | 
						|
                   );
 | 
						|
    RemoveEntryList (ListHead->ForwardLink);
 | 
						|
    gBS->FreePool (NotifyNode);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  The module Entry Point for module Ps2Keyboard.
 | 
						|
 | 
						|
  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
 | 
						|
  @param[in] SystemTable    A pointer to the EFI System Table.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS       The entry point is executed successfully.
 | 
						|
  @retval other             Some error occurs when executing this entry point.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
InitializePs2Keyboard(
 | 
						|
  IN EFI_HANDLE           ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE     *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install driver model protocol(s).
 | 
						|
  //
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gKeyboardControllerDriver,
 | 
						|
             ImageHandle,
 | 
						|
             &gPs2KeyboardComponentName,
 | 
						|
             &gPs2KeyboardComponentName2
 | 
						|
             );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 |