Home | History | Annotate | Download | only in Ps2KeyboardDxe
      1 /** @file
      2 
      3   PS/2 Keyboard driver. Routines that interacts with callers,
      4   conforming to EFI driver model
      5 
      6 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions of the BSD License
      9 which accompanies this distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "Ps2Keyboard.h"
     18 
     19 //
     20 // Function prototypes
     21 //
     22 /**
     23   Test controller is a keyboard Controller.
     24 
     25   @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
     26   @param Controller           driver's controller
     27   @param RemainingDevicePath  children device path
     28 
     29   @retval EFI_UNSUPPORTED controller is not floppy disk
     30   @retval EFI_SUCCESS     controller is floppy disk
     31 **/
     32 EFI_STATUS
     33 EFIAPI
     34 KbdControllerDriverSupported (
     35   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
     36   IN EFI_HANDLE                     Controller,
     37   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
     38   );
     39 
     40 /**
     41   Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
     42 
     43   @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
     44   @param Controller   driver controller handle
     45   @param RemainingDevicePath Children's device path
     46 
     47   @retval whether success to create floppy control instance.
     48 **/
     49 EFI_STATUS
     50 EFIAPI
     51 KbdControllerDriverStart (
     52   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
     53   IN EFI_HANDLE                     Controller,
     54   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
     55   );
     56 
     57 /**
     58   Stop this driver on ControllerHandle. Support stopping any child handles
     59   created by this driver.
     60 
     61   @param  This              Protocol instance pointer.
     62   @param  ControllerHandle  Handle of device to stop driver on
     63   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
     64                             children is zero stop the entire bus driver.
     65   @param  ChildHandleBuffer List of Child Handles to Stop.
     66 
     67   @retval EFI_SUCCESS       This driver is removed ControllerHandle
     68   @retval other             This driver was not removed from this device
     69 
     70 **/
     71 EFI_STATUS
     72 EFIAPI
     73 KbdControllerDriverStop (
     74   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
     75   IN  EFI_HANDLE                     Controller,
     76   IN  UINTN                          NumberOfChildren,
     77   IN  EFI_HANDLE                     *ChildHandleBuffer
     78   );
     79 
     80 /**
     81   Free the waiting key notify list.
     82 
     83   @param ListHead  Pointer to list head
     84 
     85   @retval EFI_INVALID_PARAMETER  ListHead is NULL
     86   @retval EFI_SUCCESS            Sucess to free NotifyList
     87 **/
     88 EFI_STATUS
     89 KbdFreeNotifyList (
     90   IN OUT LIST_ENTRY           *ListHead
     91   );
     92 
     93 //
     94 // DriverBinding Protocol Instance
     95 //
     96 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
     97   KbdControllerDriverSupported,
     98   KbdControllerDriverStart,
     99   KbdControllerDriverStop,
    100   0xa,
    101   NULL,
    102   NULL
    103 };
    104 
    105 /**
    106   Test controller is a keyboard Controller.
    107 
    108   @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
    109   @param Controller           driver's controller
    110   @param RemainingDevicePath  children device path
    111 
    112   @retval EFI_UNSUPPORTED controller is not floppy disk
    113   @retval EFI_SUCCESS     controller is floppy disk
    114 **/
    115 EFI_STATUS
    116 EFIAPI
    117 KbdControllerDriverSupported (
    118   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    119   IN EFI_HANDLE                     Controller,
    120   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
    121   )
    122 {
    123   EFI_STATUS                                 Status;
    124   EFI_SIO_PROTOCOL                           *Sio;
    125   EFI_DEVICE_PATH_PROTOCOL                   *DevicePath;
    126   ACPI_HID_DEVICE_PATH                       *Acpi;
    127 
    128   //
    129   // Check whether the controller is keyboard.
    130   //
    131   Status = gBS->OpenProtocol (
    132                   Controller,
    133                   &gEfiDevicePathProtocolGuid,
    134                   (VOID **) &DevicePath,
    135                   This->DriverBindingHandle,
    136                   Controller,
    137                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    138                   );
    139   if (EFI_ERROR (Status)) {
    140     return Status;
    141   }
    142 
    143   do {
    144     Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
    145     DevicePath = NextDevicePathNode (DevicePath);
    146   } while (!IsDevicePathEnd (DevicePath));
    147 
    148   if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
    149       (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)) {
    150     return EFI_UNSUPPORTED;
    151   }
    152 
    153   if (Acpi->HID != EISA_PNP_ID (0x303) || Acpi->UID != 0) {
    154     return EFI_UNSUPPORTED;
    155   }
    156 
    157   //
    158   // Open the IO Abstraction(s) needed to perform the supported test
    159   //
    160   Status = gBS->OpenProtocol (
    161                   Controller,
    162                   &gEfiSioProtocolGuid,
    163                   (VOID **) &Sio,
    164                   This->DriverBindingHandle,
    165                   Controller,
    166                   EFI_OPEN_PROTOCOL_BY_DRIVER
    167                   );
    168   if (EFI_ERROR (Status)) {
    169     return Status;
    170   }
    171 
    172   //
    173   // Close the I/O Abstraction(s) used to perform the supported test
    174   //
    175   gBS->CloseProtocol (
    176          Controller,
    177          &gEfiSioProtocolGuid,
    178          This->DriverBindingHandle,
    179          Controller
    180          );
    181 
    182   return Status;
    183 }
    184 
    185 /**
    186   Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
    187 
    188   @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
    189   @param Controller   driver controller handle
    190   @param RemainingDevicePath Children's device path
    191 
    192   @retval whether success to create floppy control instance.
    193 **/
    194 EFI_STATUS
    195 EFIAPI
    196 KbdControllerDriverStart (
    197   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
    198   IN EFI_HANDLE                     Controller,
    199   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
    200   )
    201 {
    202   EFI_STATUS                                Status;
    203   EFI_STATUS                                Status1;
    204   EFI_SIO_PROTOCOL                          *Sio;
    205   KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
    206   UINT8                                     Data;
    207   EFI_STATUS_CODE_VALUE                     StatusCode;
    208   EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
    209 
    210   StatusCode = 0;
    211 
    212   Status = gBS->OpenProtocol (
    213                   Controller,
    214                   &gEfiDevicePathProtocolGuid,
    215                   (VOID **) &DevicePath,
    216                   This->DriverBindingHandle,
    217                   Controller,
    218                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    219                   );
    220   if (EFI_ERROR (Status)) {
    221     return Status;
    222   }
    223   //
    224   // Report that the keyboard is being enabled
    225   //
    226   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    227     EFI_PROGRESS_CODE,
    228     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
    229     DevicePath
    230     );
    231 
    232   //
    233   // Get the ISA I/O Protocol on Controller's handle
    234   //
    235   Status = gBS->OpenProtocol (
    236                   Controller,
    237                   &gEfiSioProtocolGuid,
    238                   (VOID **) &Sio,
    239                   This->DriverBindingHandle,
    240                   Controller,
    241                   EFI_OPEN_PROTOCOL_BY_DRIVER
    242                   );
    243   if (EFI_ERROR (Status)) {
    244     return Status;
    245   }
    246   //
    247   // Allocate private data
    248   //
    249   ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
    250   if (ConsoleIn == NULL) {
    251     Status      = EFI_OUT_OF_RESOURCES;
    252     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    253     goto ErrorExit;
    254   }
    255   //
    256   // Setup the device instance
    257   //
    258   ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
    259   ConsoleIn->Handle                 = Controller;
    260   (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
    261   (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
    262   ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
    263   ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
    264   ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
    265   ConsoleIn->DevicePath             = DevicePath;
    266 
    267   ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
    268   ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
    269   ConsoleIn->ConInEx.SetState            = KeyboardSetState;
    270   ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
    271   ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;
    272 
    273   InitializeListHead (&ConsoleIn->NotifyList);
    274 
    275   //
    276   // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
    277   // When KBC decode (IO port 0x60/0x64 decode) is not enabled,
    278   // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
    279   // So instead we read status register to detect after read if KBC decode is enabled.
    280   //
    281 
    282   //
    283   // Return code is ignored on purpose.
    284   //
    285   if (!PcdGetBool (PcdFastPS2Detection)) {
    286     KeyboardRead (ConsoleIn, &Data);
    287     if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
    288       //
    289       // If nobody decodes KBC I/O port, it will read back as 0xFF.
    290       // Check the Time-Out and Parity bit to see if it has an active KBC in system
    291       //
    292       Status      = EFI_DEVICE_ERROR;
    293       StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    294       goto ErrorExit;
    295     }
    296   }
    297 
    298   //
    299   // Setup the WaitForKey event
    300   //
    301   Status = gBS->CreateEvent (
    302                   EVT_NOTIFY_WAIT,
    303                   TPL_NOTIFY,
    304                   KeyboardWaitForKey,
    305                   ConsoleIn,
    306                   &((ConsoleIn->ConIn).WaitForKey)
    307                   );
    308   if (EFI_ERROR (Status)) {
    309     Status      = EFI_OUT_OF_RESOURCES;
    310     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    311     goto ErrorExit;
    312   }
    313   //
    314   // Setup the WaitForKeyEx event
    315   //
    316   Status = gBS->CreateEvent (
    317                   EVT_NOTIFY_WAIT,
    318                   TPL_NOTIFY,
    319                   KeyboardWaitForKeyEx,
    320                   ConsoleIn,
    321                   &(ConsoleIn->ConInEx.WaitForKeyEx)
    322                   );
    323   if (EFI_ERROR (Status)) {
    324     Status      = EFI_OUT_OF_RESOURCES;
    325     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    326     goto ErrorExit;
    327   }
    328   // Setup a periodic timer, used for reading keystrokes at a fixed interval
    329   //
    330   Status = gBS->CreateEvent (
    331                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    332                   TPL_NOTIFY,
    333                   KeyboardTimerHandler,
    334                   ConsoleIn,
    335                   &ConsoleIn->TimerEvent
    336                   );
    337   if (EFI_ERROR (Status)) {
    338     Status      = EFI_OUT_OF_RESOURCES;
    339     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    340     goto ErrorExit;
    341   }
    342 
    343   Status = gBS->SetTimer (
    344                   ConsoleIn->TimerEvent,
    345                   TimerPeriodic,
    346                   KEYBOARD_TIMER_INTERVAL
    347                   );
    348   if (EFI_ERROR (Status)) {
    349     Status      = EFI_OUT_OF_RESOURCES;
    350     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    351     goto ErrorExit;
    352   }
    353 
    354   Status = gBS->CreateEvent (
    355                   EVT_NOTIFY_SIGNAL,
    356                   TPL_CALLBACK,
    357                   KeyNotifyProcessHandler,
    358                   ConsoleIn,
    359                   &ConsoleIn->KeyNotifyProcessEvent
    360                   );
    361   if (EFI_ERROR (Status)) {
    362     Status      = EFI_OUT_OF_RESOURCES;
    363     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    364     goto ErrorExit;
    365   }
    366 
    367   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    368     EFI_PROGRESS_CODE,
    369     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
    370     DevicePath
    371     );
    372 
    373   //
    374   // Reset the keyboard device
    375   //
    376   Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));
    377   if (EFI_ERROR (Status)) {
    378     Status      = EFI_DEVICE_ERROR;
    379     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    380     goto ErrorExit;
    381   }
    382 
    383   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    384     EFI_PROGRESS_CODE,
    385     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
    386     DevicePath
    387     );
    388 
    389   ConsoleIn->ControllerNameTable = NULL;
    390   AddUnicodeString2 (
    391     "eng",
    392     gPs2KeyboardComponentName.SupportedLanguages,
    393     &ConsoleIn->ControllerNameTable,
    394     L"PS/2 Keyboard Device",
    395     TRUE
    396     );
    397   AddUnicodeString2 (
    398     "en",
    399     gPs2KeyboardComponentName2.SupportedLanguages,
    400     &ConsoleIn->ControllerNameTable,
    401     L"PS/2 Keyboard Device",
    402     FALSE
    403     );
    404 
    405 
    406   //
    407   // Install protocol interfaces for the keyboard device.
    408   //
    409   Status = gBS->InstallMultipleProtocolInterfaces (
    410                   &Controller,
    411                   &gEfiSimpleTextInProtocolGuid,
    412                   &ConsoleIn->ConIn,
    413                   &gEfiSimpleTextInputExProtocolGuid,
    414                   &ConsoleIn->ConInEx,
    415                   NULL
    416                   );
    417   if (EFI_ERROR (Status)) {
    418     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    419     goto ErrorExit;
    420   }
    421 
    422   return Status;
    423 
    424 ErrorExit:
    425   //
    426   // Report error code
    427   //
    428   if (StatusCode != 0) {
    429     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    430       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    431       StatusCode,
    432       DevicePath
    433       );
    434   }
    435 
    436   if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
    437     gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
    438   }
    439 
    440   if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
    441     gBS->CloseEvent (ConsoleIn->TimerEvent);
    442   }
    443   if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
    444     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
    445   }
    446   if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {
    447     gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
    448   }
    449   KbdFreeNotifyList (&ConsoleIn->NotifyList);
    450   if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
    451     FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
    452   }
    453   //
    454   // Since there will be no timer handler for keyboard input any more,
    455   // exhaust input data just in case there is still keyboard data left
    456   //
    457   if (ConsoleIn != NULL) {
    458     Status1 = EFI_SUCCESS;
    459     while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
    460       Status1 = KeyboardRead (ConsoleIn, &Data);;
    461     }
    462   }
    463 
    464   if (ConsoleIn != NULL) {
    465     gBS->FreePool (ConsoleIn);
    466   }
    467 
    468   gBS->CloseProtocol (
    469          Controller,
    470          &gEfiSioProtocolGuid,
    471          This->DriverBindingHandle,
    472          Controller
    473          );
    474 
    475   return Status;
    476 }
    477 
    478 /**
    479   Stop this driver on ControllerHandle. Support stopping any child handles
    480   created by this driver.
    481 
    482   @param  This              Protocol instance pointer.
    483   @param  ControllerHandle  Handle of device to stop driver on
    484   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    485                             children is zero stop the entire bus driver.
    486   @param  ChildHandleBuffer List of Child Handles to Stop.
    487 
    488   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    489   @retval other             This driver was not removed from this device
    490 
    491 **/
    492 EFI_STATUS
    493 EFIAPI
    494 KbdControllerDriverStop (
    495   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
    496   IN  EFI_HANDLE                     Controller,
    497   IN  UINTN                          NumberOfChildren,
    498   IN  EFI_HANDLE                     *ChildHandleBuffer
    499   )
    500 {
    501   EFI_STATUS                     Status;
    502   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
    503   KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
    504   UINT8                          Data;
    505 
    506   //
    507   // Disable Keyboard
    508   //
    509   Status = gBS->OpenProtocol (
    510                   Controller,
    511                   &gEfiSimpleTextInProtocolGuid,
    512                   (VOID **) &ConIn,
    513                   This->DriverBindingHandle,
    514                   Controller,
    515                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    516                   );
    517   if (EFI_ERROR (Status)) {
    518     return Status;
    519   }
    520   Status = gBS->OpenProtocol (
    521                   Controller,
    522                   &gEfiSimpleTextInputExProtocolGuid,
    523                   NULL,
    524                   This->DriverBindingHandle,
    525                   Controller,
    526                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    527                   );
    528   if (EFI_ERROR (Status)) {
    529     return Status;
    530   }
    531 
    532   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
    533 
    534   //
    535   // Report that the keyboard is being disabled
    536   //
    537   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
    538     EFI_PROGRESS_CODE,
    539     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
    540     ConsoleIn->DevicePath
    541     );
    542 
    543   if (ConsoleIn->TimerEvent != NULL) {
    544     gBS->CloseEvent (ConsoleIn->TimerEvent);
    545     ConsoleIn->TimerEvent = NULL;
    546   }
    547 
    548   //
    549   // Since there will be no timer handler for keyboard input any more,
    550   // exhaust input data just in case there is still keyboard data left
    551   //
    552   Status = EFI_SUCCESS;
    553   while (!EFI_ERROR (Status)) {
    554     Status = KeyboardRead (ConsoleIn, &Data);;
    555   }
    556   //
    557   // Uninstall the SimpleTextIn and SimpleTextInEx protocols
    558   //
    559   Status = gBS->UninstallMultipleProtocolInterfaces (
    560                   Controller,
    561                   &gEfiSimpleTextInProtocolGuid,
    562                   &ConsoleIn->ConIn,
    563                   &gEfiSimpleTextInputExProtocolGuid,
    564                   &ConsoleIn->ConInEx,
    565                   NULL
    566                   );
    567   if (EFI_ERROR (Status)) {
    568     return Status;
    569   }
    570 
    571   gBS->CloseProtocol (
    572          Controller,
    573          &gEfiSioProtocolGuid,
    574          This->DriverBindingHandle,
    575          Controller
    576          );
    577 
    578   //
    579   // Free other resources
    580   //
    581   if ((ConsoleIn->ConIn).WaitForKey != NULL) {
    582     gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
    583     (ConsoleIn->ConIn).WaitForKey = NULL;
    584   }
    585   if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
    586     gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
    587     ConsoleIn->ConInEx.WaitForKeyEx = NULL;
    588   }
    589   if (ConsoleIn->KeyNotifyProcessEvent != NULL) {
    590     gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
    591     ConsoleIn->KeyNotifyProcessEvent = NULL;
    592   }
    593   KbdFreeNotifyList (&ConsoleIn->NotifyList);
    594   FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
    595   gBS->FreePool (ConsoleIn);
    596 
    597   return EFI_SUCCESS;
    598 }
    599 
    600 /**
    601   Free the waiting key notify list.
    602 
    603   @param ListHead  Pointer to list head
    604 
    605   @retval EFI_INVALID_PARAMETER  ListHead is NULL
    606   @retval EFI_SUCCESS            Sucess to free NotifyList
    607 **/
    608 EFI_STATUS
    609 KbdFreeNotifyList (
    610   IN OUT LIST_ENTRY           *ListHead
    611   )
    612 {
    613   KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
    614 
    615   if (ListHead == NULL) {
    616     return EFI_INVALID_PARAMETER;
    617   }
    618   while (!IsListEmpty (ListHead)) {
    619     NotifyNode = CR (
    620                    ListHead->ForwardLink,
    621                    KEYBOARD_CONSOLE_IN_EX_NOTIFY,
    622                    NotifyEntry,
    623                    KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
    624                    );
    625     RemoveEntryList (ListHead->ForwardLink);
    626     gBS->FreePool (NotifyNode);
    627   }
    628 
    629   return EFI_SUCCESS;
    630 }
    631 
    632 /**
    633   The module Entry Point for module Ps2Keyboard.
    634 
    635   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
    636   @param[in] SystemTable    A pointer to the EFI System Table.
    637 
    638   @retval EFI_SUCCESS       The entry point is executed successfully.
    639   @retval other             Some error occurs when executing this entry point.
    640 
    641 **/
    642 EFI_STATUS
    643 EFIAPI
    644 InitializePs2Keyboard(
    645   IN EFI_HANDLE           ImageHandle,
    646   IN EFI_SYSTEM_TABLE     *SystemTable
    647   )
    648 {
    649   EFI_STATUS              Status;
    650 
    651   //
    652   // Install driver model protocol(s).
    653   //
    654   Status = EfiLibInstallDriverBindingComponentName2 (
    655              ImageHandle,
    656              SystemTable,
    657              &gKeyboardControllerDriver,
    658              ImageHandle,
    659              &gPs2KeyboardComponentName,
    660              &gPs2KeyboardComponentName2
    661              );
    662   ASSERT_EFI_ERROR (Status);
    663 
    664 
    665   return Status;
    666 }
    667 
    668