Home | History | Annotate | Download | only in KeyboardDxe
      1 /** @file
      2   ConsoleOut Routines that speak VGA.
      3 
      4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      5 
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions
      8 of the BSD License which accompanies this distribution.  The
      9 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 "BiosKeyboard.h"
     18 
     19 //
     20 // EFI Driver Binding Protocol Instance
     21 //
     22 EFI_DRIVER_BINDING_PROTOCOL gBiosKeyboardDriverBinding = {
     23   BiosKeyboardDriverBindingSupported,
     24   BiosKeyboardDriverBindingStart,
     25   BiosKeyboardDriverBindingStop,
     26   0x3,
     27   NULL,
     28   NULL
     29 };
     30 
     31 
     32 /**
     33   Enqueue the key.
     34 
     35   @param  Queue                 The queue to be enqueued.
     36   @param  KeyData               The key data to be enqueued.
     37 
     38   @retval EFI_NOT_READY         The queue is full.
     39   @retval EFI_SUCCESS           Successfully enqueued the key data.
     40 
     41 **/
     42 EFI_STATUS
     43 Enqueue (
     44   IN SIMPLE_QUEUE         *Queue,
     45   IN EFI_KEY_DATA         *KeyData
     46   )
     47 {
     48   if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {
     49     return EFI_NOT_READY;
     50   }
     51 
     52   CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
     53   Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;
     54 
     55   return EFI_SUCCESS;
     56 }
     57 
     58 
     59 /**
     60   Dequeue the key.
     61 
     62   @param  Queue                 The queue to be dequeued.
     63   @param  KeyData               The key data to be dequeued.
     64 
     65   @retval EFI_NOT_READY         The queue is empty.
     66   @retval EFI_SUCCESS           Successfully dequeued the key data.
     67 
     68 **/
     69 EFI_STATUS
     70 Dequeue (
     71   IN SIMPLE_QUEUE         *Queue,
     72   IN EFI_KEY_DATA         *KeyData
     73   )
     74 {
     75   if (Queue->Front == Queue->Rear) {
     76     return EFI_NOT_READY;
     77   }
     78 
     79   CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));
     80   Queue->Front  = (Queue->Front + 1) % QUEUE_MAX_COUNT;
     81 
     82   return EFI_SUCCESS;
     83 }
     84 
     85 
     86 /**
     87   Check whether the queue is empty.
     88 
     89   @param  Queue                 The queue to be checked.
     90 
     91   @retval EFI_NOT_READY         The queue is empty.
     92   @retval EFI_SUCCESS           The queue is not empty.
     93 
     94 **/
     95 EFI_STATUS
     96 CheckQueue (
     97   IN SIMPLE_QUEUE         *Queue
     98   )
     99 {
    100   if (Queue->Front == Queue->Rear) {
    101     return EFI_NOT_READY;
    102   }
    103 
    104   return EFI_SUCCESS;
    105 }
    106 
    107 //
    108 // EFI Driver Binding Protocol Functions
    109 //
    110 
    111 /**
    112   Check whether the driver supports this device.
    113 
    114   @param  This                   The Udriver binding protocol.
    115   @param  Controller             The controller handle to check.
    116   @param  RemainingDevicePath    The remaining device path.
    117 
    118   @retval EFI_SUCCESS            The driver supports this controller.
    119   @retval other                  This device isn't supported.
    120 
    121 **/
    122 EFI_STATUS
    123 EFIAPI
    124 BiosKeyboardDriverBindingSupported (
    125   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    126   IN EFI_HANDLE                   Controller,
    127   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    128   )
    129 {
    130   EFI_STATUS                                Status;
    131   EFI_LEGACY_BIOS_PROTOCOL                  *LegacyBios;
    132   EFI_ISA_IO_PROTOCOL                       *IsaIo;
    133 
    134   //
    135   // See if the Legacy BIOS Protocol is available
    136   //
    137   Status = gBS->LocateProtocol (
    138                   &gEfiLegacyBiosProtocolGuid,
    139                   NULL,
    140                   (VOID **) &LegacyBios
    141                   );
    142 
    143   if (EFI_ERROR (Status)) {
    144     return Status;
    145   }
    146   //
    147   // Open the IO Abstraction(s) needed to perform the supported test
    148   //
    149   Status = gBS->OpenProtocol (
    150                   Controller,
    151                   &gEfiIsaIoProtocolGuid,
    152                   (VOID **) &IsaIo,
    153                   This->DriverBindingHandle,
    154                   Controller,
    155                   EFI_OPEN_PROTOCOL_BY_DRIVER
    156                   );
    157 
    158   if (EFI_ERROR (Status)) {
    159     return Status;
    160   }
    161   //
    162   // Use the ISA I/O Protocol to see if Controller is the Keyboard controller
    163   //
    164   if (IsaIo->ResourceList->Device.HID != EISA_PNP_ID (0x303) || IsaIo->ResourceList->Device.UID != 0) {
    165     Status = EFI_UNSUPPORTED;
    166   }
    167 
    168   gBS->CloseProtocol (
    169          Controller,
    170          &gEfiIsaIoProtocolGuid,
    171          This->DriverBindingHandle,
    172          Controller
    173          );
    174 
    175   return Status;
    176 }
    177 
    178 /**
    179   Starts the device with this driver.
    180 
    181   @param  This                   The driver binding instance.
    182   @param  Controller             Handle of device to bind driver to.
    183   @param  RemainingDevicePath    Optional parameter use to pick a specific child
    184                                  device to start.
    185 
    186   @retval EFI_SUCCESS            The controller is controlled by the driver.
    187   @retval Other                  This controller cannot be started.
    188 
    189 **/
    190 EFI_STATUS
    191 EFIAPI
    192 BiosKeyboardDriverBindingStart (
    193   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    194   IN EFI_HANDLE                   Controller,
    195   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    196   )
    197 {
    198   EFI_STATUS                                Status;
    199   EFI_LEGACY_BIOS_PROTOCOL                  *LegacyBios;
    200   EFI_ISA_IO_PROTOCOL                       *IsaIo;
    201   BIOS_KEYBOARD_DEV                         *BiosKeyboardPrivate;
    202   EFI_IA32_REGISTER_SET                     Regs;
    203   BOOLEAN                                   CarryFlag;
    204   EFI_PS2_POLICY_PROTOCOL                   *Ps2Policy;
    205   UINT8                                     Command;
    206   EFI_STATUS_CODE_VALUE                     StatusCode;
    207 
    208   BiosKeyboardPrivate = NULL;
    209   IsaIo = NULL;
    210   StatusCode          = 0;
    211 
    212   //
    213   // Get Ps2 policy to set. Will be use if present.
    214   //
    215   gBS->LocateProtocol (
    216         &gEfiPs2PolicyProtocolGuid,
    217         NULL,
    218         (VOID **) &Ps2Policy
    219         );
    220 
    221   //
    222   // See if the Legacy BIOS Protocol is available
    223   //
    224   Status = gBS->LocateProtocol (
    225                   &gEfiLegacyBiosProtocolGuid,
    226                   NULL,
    227                   (VOID **) &LegacyBios
    228                   );
    229 
    230   if (EFI_ERROR (Status)) {
    231     return Status;
    232   }
    233   //
    234   // Open the IO Abstraction(s) needed
    235   //
    236   Status = gBS->OpenProtocol (
    237                   Controller,
    238                   &gEfiIsaIoProtocolGuid,
    239                   (VOID **) &IsaIo,
    240                   This->DriverBindingHandle,
    241                   Controller,
    242                   EFI_OPEN_PROTOCOL_BY_DRIVER
    243                   );
    244   if (EFI_ERROR (Status)) {
    245     return Status;
    246   }
    247 
    248   //
    249   // Allocate the private device structure
    250   //
    251     BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_DEV));
    252   if (NULL == BiosKeyboardPrivate) {
    253     Status = EFI_OUT_OF_RESOURCES;
    254     goto Done;
    255   }
    256 
    257   //
    258   // Initialize the private device structure
    259   //
    260   BiosKeyboardPrivate->Signature                  = BIOS_KEYBOARD_DEV_SIGNATURE;
    261   BiosKeyboardPrivate->Handle                     = Controller;
    262   BiosKeyboardPrivate->LegacyBios                 = LegacyBios;
    263   BiosKeyboardPrivate->IsaIo                      = IsaIo;
    264 
    265   BiosKeyboardPrivate->SimpleTextIn.Reset         = BiosKeyboardReset;
    266   BiosKeyboardPrivate->SimpleTextIn.ReadKeyStroke = BiosKeyboardReadKeyStroke;
    267 
    268   BiosKeyboardPrivate->DataRegisterAddress        = KEYBOARD_8042_DATA_REGISTER;
    269   BiosKeyboardPrivate->StatusRegisterAddress      = KEYBOARD_8042_STATUS_REGISTER;
    270   BiosKeyboardPrivate->CommandRegisterAddress     = KEYBOARD_8042_COMMAND_REGISTER;
    271   BiosKeyboardPrivate->ExtendedKeyboard           = TRUE;
    272 
    273   BiosKeyboardPrivate->Queue.Front                = 0;
    274   BiosKeyboardPrivate->Queue.Rear                 = 0;
    275   BiosKeyboardPrivate->QueueForNotify.Front       = 0;
    276   BiosKeyboardPrivate->QueueForNotify.Rear        = 0;
    277   BiosKeyboardPrivate->SimpleTextInputEx.Reset               = BiosKeyboardResetEx;
    278   BiosKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx     = BiosKeyboardReadKeyStrokeEx;
    279   BiosKeyboardPrivate->SimpleTextInputEx.SetState            = BiosKeyboardSetState;
    280   BiosKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify   = BiosKeyboardRegisterKeyNotify;
    281   BiosKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = BiosKeyboardUnregisterKeyNotify;
    282   InitializeListHead (&BiosKeyboardPrivate->NotifyList);
    283 
    284   //
    285   // Report that the keyboard is being enabled
    286   //
    287   REPORT_STATUS_CODE (
    288     EFI_PROGRESS_CODE,
    289     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE
    290     );
    291 
    292   //
    293   // Setup the WaitForKey event
    294   //
    295   Status = gBS->CreateEvent (
    296                   EVT_NOTIFY_WAIT,
    297                   TPL_NOTIFY,
    298                   BiosKeyboardWaitForKey,
    299                   &(BiosKeyboardPrivate->SimpleTextIn),
    300                   &((BiosKeyboardPrivate->SimpleTextIn).WaitForKey)
    301                   );
    302   if (EFI_ERROR (Status)) {
    303     (BiosKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;
    304     goto Done;
    305   }
    306   Status = gBS->CreateEvent (
    307                   EVT_NOTIFY_WAIT,
    308                   TPL_NOTIFY,
    309                   BiosKeyboardWaitForKeyEx,
    310                   &(BiosKeyboardPrivate->SimpleTextInputEx),
    311                   &(BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)
    312                   );
    313   if (EFI_ERROR (Status)) {
    314     BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;
    315     goto Done;
    316   }
    317 
    318   //
    319   // Setup a periodic timer, used for reading keystrokes at a fixed interval
    320   //
    321   Status = gBS->CreateEvent (
    322                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    323                   TPL_NOTIFY,
    324                   BiosKeyboardTimerHandler,
    325                   BiosKeyboardPrivate,
    326                   &BiosKeyboardPrivate->TimerEvent
    327                   );
    328   if (EFI_ERROR (Status)) {
    329     Status      = EFI_OUT_OF_RESOURCES;
    330     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    331     goto Done;
    332   }
    333 
    334   Status = gBS->SetTimer (
    335                   BiosKeyboardPrivate->TimerEvent,
    336                   TimerPeriodic,
    337                   KEYBOARD_TIMER_INTERVAL
    338                   );
    339   if (EFI_ERROR (Status)) {
    340     Status      = EFI_OUT_OF_RESOURCES;
    341     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    342     goto Done;
    343   }
    344 
    345   Status = gBS->CreateEvent (
    346                   EVT_NOTIFY_SIGNAL,
    347                   TPL_CALLBACK,
    348                   KeyNotifyProcessHandler,
    349                   BiosKeyboardPrivate,
    350                   &BiosKeyboardPrivate->KeyNotifyProcessEvent
    351                   );
    352   if (EFI_ERROR (Status)) {
    353     Status      = EFI_OUT_OF_RESOURCES;
    354     StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
    355     goto Done;
    356   }
    357 
    358   //
    359   // Report a Progress Code for an attempt to detect the precense of the keyboard device in the system
    360   //
    361   REPORT_STATUS_CODE (
    362     EFI_PROGRESS_CODE,
    363     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT
    364     );
    365 
    366   //
    367   // Reset the keyboard device
    368   //
    369   Status = BiosKeyboardPrivate->SimpleTextInputEx.Reset (
    370                                                     &BiosKeyboardPrivate->SimpleTextInputEx,
    371                                                     FeaturePcdGet (PcdPs2KbdExtendedVerification)
    372                                                     );
    373   if (EFI_ERROR (Status)) {
    374     DEBUG ((EFI_D_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));
    375     StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
    376     goto Done;
    377   }
    378   //
    379   // Do platform specific policy like port swapping and keyboard light default
    380   //
    381   if (Ps2Policy != NULL) {
    382 
    383     Ps2Policy->Ps2InitHardware (Controller);
    384 
    385     Command = 0;
    386     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) {
    387       Command |= 4;
    388     }
    389 
    390     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) {
    391       Command |= 2;
    392     }
    393 
    394     if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) {
    395       Command |= 1;
    396     }
    397 
    398     KeyboardWrite (BiosKeyboardPrivate, 0xed);
    399     KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);
    400     KeyboardWrite (BiosKeyboardPrivate, Command);
    401     //
    402     // Call Legacy BIOS Protocol to set whatever is necessary
    403     //
    404     LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
    405   }
    406   //
    407   // Get Configuration
    408   //
    409   Regs.H.AH = 0xc0;
    410   CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
    411                                                  BiosKeyboardPrivate->LegacyBios,
    412                                                  0x15,
    413                                                  &Regs
    414                                                  );
    415 
    416   if (!CarryFlag) {
    417     //
    418     // Check bit 6 of Feature Byte 2.
    419     // If it is set, then Int 16 Func 09 is supported
    420     //
    421     if (*(UINT8 *)(UINTN) ((Regs.X.ES << 4) + Regs.X.BX + 0x06) & 0x40) {
    422       //
    423       // Get Keyboard Functionality
    424       //
    425       Regs.H.AH = 0x09;
    426       CarryFlag = BiosKeyboardPrivate->LegacyBios->Int86 (
    427                                                      BiosKeyboardPrivate->LegacyBios,
    428                                                      0x16,
    429                                                      &Regs
    430                                                      );
    431 
    432       if (!CarryFlag) {
    433         //
    434         // Check bit 5 of AH.
    435         // If it is set, then INT 16 Finc 10-12 are supported.
    436         //
    437         if ((Regs.H.AL & 0x40) != 0) {
    438           //
    439           // Set the flag to use INT 16 Func 10-12
    440           //
    441           BiosKeyboardPrivate->ExtendedKeyboard = TRUE;
    442         }
    443       }
    444     }
    445   }
    446   DEBUG ((EFI_D_INFO, "[KBD]Extended keystrokes supported by CSM16 - %02x\n", (UINTN)BiosKeyboardPrivate->ExtendedKeyboard));
    447   //
    448   // Install protocol interfaces for the keyboard device.
    449   //
    450   Status = gBS->InstallMultipleProtocolInterfaces (
    451                   &Controller,
    452                   &gEfiSimpleTextInProtocolGuid,
    453                   &BiosKeyboardPrivate->SimpleTextIn,
    454                   &gEfiSimpleTextInputExProtocolGuid,
    455                   &BiosKeyboardPrivate->SimpleTextInputEx,
    456                   NULL
    457                   );
    458 
    459 Done:
    460   if (StatusCode != 0) {
    461     //
    462     // Report an Error Code for failing to start the keyboard device
    463     //
    464     REPORT_STATUS_CODE (
    465       EFI_ERROR_CODE | EFI_ERROR_MINOR,
    466       StatusCode
    467       );
    468   }
    469 
    470   if (EFI_ERROR (Status)) {
    471 
    472     if (BiosKeyboardPrivate != NULL) {
    473       if ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {
    474         gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);
    475       }
    476 
    477       if ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {
    478         gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx);
    479       }
    480 
    481       if (BiosKeyboardPrivate->KeyNotifyProcessEvent != NULL) {
    482         gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
    483       }
    484 
    485       BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
    486 
    487       if (BiosKeyboardPrivate->TimerEvent != NULL) {
    488         gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);
    489       }
    490 
    491       FreePool (BiosKeyboardPrivate);
    492     }
    493 
    494     if (IsaIo != NULL) {
    495       gBS->CloseProtocol (
    496              Controller,
    497              &gEfiIsaIoProtocolGuid,
    498              This->DriverBindingHandle,
    499              Controller
    500              );
    501     }
    502   }
    503 
    504   return Status;
    505 }
    506 
    507 /**
    508   Stop the device handled by this driver.
    509 
    510   @param  This                   The driver binding protocol.
    511   @param  Controller             The controller to release.
    512   @param  NumberOfChildren       The number of handles in ChildHandleBuffer.
    513   @param  ChildHandleBuffer      The array of child handle.
    514 
    515   @retval EFI_SUCCESS            The device was stopped.
    516   @retval EFI_DEVICE_ERROR       The device could not be stopped due to a device error.
    517   @retval Others                 Fail to uninstall protocols attached on the device.
    518 
    519 **/
    520 EFI_STATUS
    521 EFIAPI
    522 BiosKeyboardDriverBindingStop (
    523   IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
    524   IN  EFI_HANDLE                      Controller,
    525   IN  UINTN                           NumberOfChildren,
    526   IN  EFI_HANDLE                      *ChildHandleBuffer
    527   )
    528 {
    529   EFI_STATUS                     Status;
    530   EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;
    531   BIOS_KEYBOARD_DEV              *BiosKeyboardPrivate;
    532 
    533   //
    534   // Disable Keyboard
    535   //
    536   Status = gBS->OpenProtocol (
    537                   Controller,
    538                   &gEfiSimpleTextInProtocolGuid,
    539                   (VOID **) &SimpleTextIn,
    540                   This->DriverBindingHandle,
    541                   Controller,
    542                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    543                   );
    544   if (EFI_ERROR (Status)) {
    545     return Status;
    546   }
    547 
    548   Status = gBS->OpenProtocol (
    549                   Controller,
    550                   &gEfiSimpleTextInputExProtocolGuid,
    551                   NULL,
    552                   This->DriverBindingHandle,
    553                   Controller,
    554                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    555                   );
    556   if (EFI_ERROR (Status)) {
    557     return Status;
    558   }
    559 
    560   BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (SimpleTextIn);
    561 
    562   Status = gBS->UninstallMultipleProtocolInterfaces (
    563                   Controller,
    564                   &gEfiSimpleTextInProtocolGuid,
    565                   &BiosKeyboardPrivate->SimpleTextIn,
    566                   &gEfiSimpleTextInputExProtocolGuid,
    567                   &BiosKeyboardPrivate->SimpleTextInputEx,
    568                   NULL
    569                   );
    570   if (EFI_ERROR (Status)) {
    571     return Status;
    572   }
    573   //
    574   // Release the IsaIo protocol on the controller handle
    575   //
    576   gBS->CloseProtocol (
    577          Controller,
    578          &gEfiIsaIoProtocolGuid,
    579          This->DriverBindingHandle,
    580          Controller
    581          );
    582 
    583   //
    584   // Free other resources
    585   //
    586   gBS->CloseEvent ((BiosKeyboardPrivate->SimpleTextIn).WaitForKey);
    587   gBS->CloseEvent (BiosKeyboardPrivate->TimerEvent);
    588   gBS->CloseEvent (BiosKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx);
    589   gBS->CloseEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
    590   BiosKeyboardFreeNotifyList (&BiosKeyboardPrivate->NotifyList);
    591 
    592   FreePool (BiosKeyboardPrivate);
    593 
    594   return EFI_SUCCESS;
    595 }
    596 
    597 /**
    598   Read data byte from output buffer of Keyboard Controller without delay and waiting for buffer-empty state.
    599 
    600   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    601 
    602   @return  The data byte read from output buffer of Keyboard Controller from data port which often is port 60H.
    603 
    604 **/
    605 UINT8
    606 KeyReadDataRegister (
    607   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate
    608   )
    609 {
    610   UINT8 Data;
    611 
    612   //
    613   // Use IsaIo protocol to perform IO operations
    614   //
    615   BiosKeyboardPrivate->IsaIo->Io.Read (
    616                                    BiosKeyboardPrivate->IsaIo,
    617                                    EfiIsaIoWidthUint8,
    618                                    BiosKeyboardPrivate->DataRegisterAddress,
    619                                    1,
    620                                    &Data
    621                                    );
    622 
    623   return Data;
    624 }
    625 
    626 /**
    627   Read status byte from status register of Keyboard Controller without delay and waiting for buffer-empty state.
    628 
    629   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    630 
    631   @return  The status byte read from status register of Keyboard Controller from command port which often is port 64H.
    632 
    633 **/
    634 UINT8
    635 KeyReadStatusRegister (
    636   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate
    637   )
    638 {
    639   UINT8 Data;
    640 
    641   //
    642   // Use IsaIo protocol to perform IO operations
    643   //
    644   BiosKeyboardPrivate->IsaIo->Io.Read (
    645                                    BiosKeyboardPrivate->IsaIo,
    646                                    EfiIsaIoWidthUint8,
    647                                    BiosKeyboardPrivate->StatusRegisterAddress,
    648                                    1,
    649                                    &Data
    650                                    );
    651 
    652   return Data;
    653 }
    654 
    655 /**
    656   Write command byte to control register of Keyboard Controller without delay and waiting for buffer-empty state.
    657 
    658   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    659   @param   Data                 Data byte to write.
    660 
    661 **/
    662 VOID
    663 KeyWriteCommandRegister (
    664   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    665   IN UINT8              Data
    666   )
    667 {
    668   //
    669   // Use IsaIo protocol to perform IO operations
    670   //
    671   BiosKeyboardPrivate->IsaIo->Io.Write (
    672                                    BiosKeyboardPrivate->IsaIo,
    673                                    EfiIsaIoWidthUint8,
    674                                    BiosKeyboardPrivate->CommandRegisterAddress,
    675                                    1,
    676                                    &Data
    677                                    );
    678 }
    679 
    680 /**
    681   Write data byte to input buffer or input/output ports of Keyboard Controller without delay and waiting for buffer-empty state.
    682 
    683   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    684   @param   Data                 Data byte to write.
    685 
    686 **/
    687 VOID
    688 KeyWriteDataRegister (
    689   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    690   IN UINT8              Data
    691   )
    692 {
    693   //
    694   // Use IsaIo protocol to perform IO operations
    695   //
    696   BiosKeyboardPrivate->IsaIo->Io.Write (
    697                                    BiosKeyboardPrivate->IsaIo,
    698                                    EfiIsaIoWidthUint8,
    699                                    BiosKeyboardPrivate->DataRegisterAddress,
    700                                    1,
    701                                    &Data
    702                                    );
    703 }
    704 
    705 /**
    706   Read data byte from output buffer of Keyboard Controller with delay and waiting for buffer-empty state.
    707 
    708   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    709   @param   Data                 The pointer for data that being read out.
    710 
    711   @retval  EFI_SUCCESS          The data byte read out successfully.
    712   @retval  EFI_TIMEOUT          Timeout occurred during reading out data byte.
    713 
    714 **/
    715 EFI_STATUS
    716 KeyboardRead (
    717   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    718   OUT UINT8             *Data
    719   )
    720 {
    721   UINT32  TimeOut;
    722   UINT32  RegFilled;
    723 
    724   TimeOut   = 0;
    725   RegFilled = 0;
    726 
    727   //
    728   // wait till output buffer full then perform the read
    729   //
    730   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    731     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {
    732       RegFilled = 1;
    733       *Data     = KeyReadDataRegister (BiosKeyboardPrivate);
    734       break;
    735     }
    736 
    737     gBS->Stall (30);
    738   }
    739 
    740   if (RegFilled == 0) {
    741     return EFI_TIMEOUT;
    742   }
    743 
    744   return EFI_SUCCESS;
    745 }
    746 
    747 /**
    748   Write data byte to input buffer or input/output ports of Keyboard Controller with delay and waiting for buffer-empty state.
    749 
    750   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    751   @param   Data                 Data byte to write.
    752 
    753   @retval  EFI_SUCCESS          The data byte is written successfully.
    754   @retval  EFI_TIMEOUT          Timeout occurred during writing.
    755 
    756 **/
    757 EFI_STATUS
    758 KeyboardWrite (
    759   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    760   IN UINT8              Data
    761   )
    762 {
    763   UINT32  TimeOut;
    764   UINT32  RegEmptied;
    765 
    766   TimeOut     = 0;
    767   RegEmptied  = 0;
    768 
    769   //
    770   // wait for input buffer empty
    771   //
    772   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    773     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
    774       RegEmptied = 1;
    775       break;
    776     }
    777 
    778     gBS->Stall (30);
    779   }
    780 
    781   if (RegEmptied == 0) {
    782     return EFI_TIMEOUT;
    783   }
    784   //
    785   // Write it
    786   //
    787   KeyWriteDataRegister (BiosKeyboardPrivate, Data);
    788 
    789   return EFI_SUCCESS;
    790 }
    791 
    792 /**
    793   Write command byte to control register of Keyboard Controller with delay and waiting for buffer-empty state.
    794 
    795   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    796   @param   Data                 Command byte to write.
    797 
    798   @retval  EFI_SUCCESS          The command byte is written successfully.
    799   @retval  EFI_TIMEOUT          Timeout occurred during writing.
    800 
    801 **/
    802 EFI_STATUS
    803 KeyboardCommand (
    804   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    805   IN UINT8              Data
    806   )
    807 {
    808   UINT32  TimeOut;
    809   UINT32  RegEmptied;
    810 
    811   TimeOut     = 0;
    812   RegEmptied  = 0;
    813 
    814   //
    815   // Wait For Input Buffer Empty
    816   //
    817   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    818     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
    819       RegEmptied = 1;
    820       break;
    821     }
    822 
    823     gBS->Stall (30);
    824   }
    825 
    826   if (RegEmptied == 0) {
    827     return EFI_TIMEOUT;
    828   }
    829   //
    830   // issue the command
    831   //
    832   KeyWriteCommandRegister (BiosKeyboardPrivate, Data);
    833 
    834   //
    835   // Wait For Input Buffer Empty again
    836   //
    837   RegEmptied = 0;
    838   for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    839     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_INPB) == 0) {
    840       RegEmptied = 1;
    841       break;
    842     }
    843 
    844     gBS->Stall (30);
    845   }
    846 
    847   if (RegEmptied == 0) {
    848     return EFI_TIMEOUT;
    849   }
    850 
    851   return EFI_SUCCESS;
    852 }
    853 
    854 /**
    855   Wait for a specific value to be presented in
    856   Data register of Keyboard Controller by keyboard and then read it,
    857   used in keyboard commands ack
    858 
    859   @param   BiosKeyboardPrivate  Keyboard instance pointer.
    860   @param   Value                The value to be waited for
    861   @param   WaitForValueTimeOut  The limit of microseconds for timeout
    862 
    863   @retval  EFI_SUCCESS          The command byte is written successfully.
    864   @retval  EFI_TIMEOUT          Timeout occurred during writing.
    865 
    866 **/
    867 EFI_STATUS
    868 KeyboardWaitForValue (
    869   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    870   IN UINT8              Value,
    871   IN UINTN              WaitForValueTimeOut
    872   )
    873 {
    874   UINT8   Data;
    875   UINT32  TimeOut;
    876   UINT32  SumTimeOut;
    877   UINT32  GotIt;
    878 
    879   GotIt       = 0;
    880   TimeOut     = 0;
    881   SumTimeOut  = 0;
    882 
    883   //
    884   // Make sure the initial value of 'Data' is different from 'Value'
    885   //
    886   Data = 0;
    887   if (Data == Value) {
    888     Data = 1;
    889   }
    890   //
    891   // Read from 8042 (multiple times if needed)
    892   // until the expected value appears
    893   // use SumTimeOut to control the iteration
    894   //
    895   while (1) {
    896     //
    897     // Perform a read
    898     //
    899     for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
    900       if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_OUTB) != 0) {
    901         Data = KeyReadDataRegister (BiosKeyboardPrivate);
    902         break;
    903       }
    904 
    905       gBS->Stall (30);
    906     }
    907 
    908     SumTimeOut += TimeOut;
    909 
    910     if (Data == Value) {
    911       GotIt = 1;
    912       break;
    913     }
    914 
    915     if (SumTimeOut >= WaitForValueTimeOut) {
    916       break;
    917     }
    918   }
    919   //
    920   // Check results
    921   //
    922   if (GotIt != 0) {
    923     return EFI_SUCCESS;
    924   } else {
    925     return EFI_TIMEOUT;
    926   }
    927 
    928 }
    929 
    930 /**
    931   Reads the next keystroke from the input device. The WaitForKey Event can
    932   be used to test for existance of a keystroke via WaitForEvent () call.
    933 
    934   @param  BiosKeyboardPrivate   Bioskeyboard driver private structure.
    935   @param  KeyData               A pointer to a buffer that is filled in with the keystroke
    936                                 state data for the key that was pressed.
    937 
    938   @retval EFI_SUCCESS           The keystroke information was returned.
    939   @retval EFI_NOT_READY         There was no keystroke data availiable.
    940   @retval EFI_DEVICE_ERROR      The keystroke information was not returned due to
    941                                 hardware errors.
    942   @retval EFI_INVALID_PARAMETER KeyData is NULL.
    943 
    944 **/
    945 EFI_STATUS
    946 KeyboardReadKeyStrokeWorker (
    947   IN BIOS_KEYBOARD_DEV  *BiosKeyboardPrivate,
    948   OUT EFI_KEY_DATA      *KeyData
    949   )
    950 {
    951   EFI_STATUS                            Status;
    952   EFI_TPL                               OldTpl;
    953   if (KeyData == NULL) {
    954     return EFI_INVALID_PARAMETER;
    955   }
    956 
    957   //
    958   // Use TimerEvent callback function to check whether there's any key pressed
    959   //
    960 
    961   //
    962   // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
    963   // Csm will be used to check whether there is a key pending, but the csm will disable all
    964   // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
    965   // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
    966   // e.g. OS loader, other drivers which are driven by timer event will have a bad performance during this period,
    967   // e.g. usb keyboard driver.
    968   // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
    969   // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
    970   //
    971   gBS->Stall (1000);
    972 
    973   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    974 
    975   BiosKeyboardTimerHandler (NULL, BiosKeyboardPrivate);
    976   //
    977   // If there's no key, just return
    978   //
    979   Status = CheckQueue (&BiosKeyboardPrivate->Queue);
    980   if (EFI_ERROR (Status)) {
    981     gBS->RestoreTPL (OldTpl);
    982     return EFI_NOT_READY;
    983   }
    984 
    985   Status = Dequeue (&BiosKeyboardPrivate->Queue, KeyData);
    986 
    987   gBS->RestoreTPL (OldTpl);
    988 
    989   return EFI_SUCCESS;
    990 }
    991 
    992 //
    993 // EFI Simple Text In Protocol Functions
    994 //
    995 /**
    996   Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE) then do some extra keyboard validations.
    997 
    998   @param  This                  Pointer of simple text Protocol.
    999   @param  ExtendedVerification  Whether perform the extra validation of keyboard. True: perform; FALSE: skip.
   1000 
   1001   @retval EFI_SUCCESS           The command byte is written successfully.
   1002   @retval EFI_DEVICE_ERROR      Errors occurred during resetting keyboard.
   1003 
   1004 **/
   1005 EFI_STATUS
   1006 EFIAPI
   1007 BiosKeyboardReset (
   1008   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
   1009   IN  BOOLEAN                         ExtendedVerification
   1010   )
   1011 {
   1012   BIOS_KEYBOARD_DEV *BiosKeyboardPrivate;
   1013   EFI_STATUS        Status;
   1014   EFI_TPL           OldTpl;
   1015   UINT8             CommandByte;
   1016   BOOLEAN           MouseEnable;
   1017   EFI_INPUT_KEY     Key;
   1018 
   1019   MouseEnable         = FALSE;
   1020   BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
   1021 
   1022   //
   1023   // 1
   1024   // Report reset progress code
   1025   //
   1026   REPORT_STATUS_CODE (
   1027     EFI_PROGRESS_CODE,
   1028     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET
   1029     );
   1030 
   1031   //
   1032   // Report a Progress Code for clearing the keyboard buffer
   1033   //
   1034   REPORT_STATUS_CODE (
   1035     EFI_PROGRESS_CODE,
   1036     EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER
   1037     );
   1038 
   1039   //
   1040   // 2
   1041   // Raise TPL to avoid mouse operation impact
   1042   //
   1043   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   1044 
   1045   //
   1046   //
   1047   // Exhaust output buffer data
   1048   //
   1049   do {
   1050     Status = BiosKeyboardReadKeyStroke (
   1051                This,
   1052                &Key
   1053                );
   1054   } while (!EFI_ERROR (Status));
   1055   //
   1056   // 3
   1057   // check for KBC itself firstly for setted-up already or not by reading SYSF (bit2) of status register via 64H
   1058   // if not skip step 4&5 and jump to step 6 to selftest KBC and report this
   1059   // else   go step 4
   1060   //
   1061   if (!PcdGetBool (PcdFastPS2Detection)) {
   1062     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & KBC_STSREG_VIA64_SYSF) != 0) {
   1063       //
   1064       // 4
   1065       // CheckMouseStatus to decide enable it later or not
   1066       //
   1067       //
   1068       // Read the command byte of KBC
   1069       //
   1070       Status = KeyboardCommand (
   1071                  BiosKeyboardPrivate,
   1072                  KBC_CMDREG_VIA64_CMDBYTE_R
   1073                  );
   1074 
   1075       if (EFI_ERROR (Status)) {
   1076         Status    = EFI_DEVICE_ERROR;
   1077         goto Exit;
   1078       }
   1079 
   1080       Status = KeyboardRead (
   1081                  BiosKeyboardPrivate,
   1082                  &CommandByte
   1083                  );
   1084 
   1085       if (EFI_ERROR (Status)) {
   1086         Status    = EFI_DEVICE_ERROR;
   1087         goto Exit;
   1088       }
   1089       //
   1090       // Check mouse enabled or not before
   1091       //
   1092       if ((CommandByte & KB_CMMBYTE_DISABLE_AUX) != 0) {
   1093         MouseEnable = FALSE;
   1094       } else {
   1095         MouseEnable = TRUE;
   1096       }
   1097       //
   1098       // 5
   1099       // disable mouse (via KBC) and Keyborad device
   1100       //
   1101       Status = KeyboardCommand (
   1102                  BiosKeyboardPrivate,
   1103                  KBC_CMDREG_VIA64_AUX_DISABLE
   1104                  );
   1105 
   1106       if (EFI_ERROR (Status)) {
   1107         Status    = EFI_DEVICE_ERROR;
   1108         goto Exit;
   1109       }
   1110 
   1111       Status = KeyboardCommand (
   1112                  BiosKeyboardPrivate,
   1113                  KBC_CMDREG_VIA64_KB_DISABLE
   1114                  );
   1115 
   1116       if (EFI_ERROR (Status)) {
   1117         Status    = EFI_DEVICE_ERROR;
   1118         goto Exit;
   1119       }
   1120     } else {
   1121       //
   1122       // 6
   1123       // KBC Self Test
   1124       //
   1125       //
   1126       // Report a Progress Code for performing a self test on the keyboard controller
   1127       //
   1128       REPORT_STATUS_CODE (
   1129         EFI_PROGRESS_CODE,
   1130         EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST
   1131         );
   1132 
   1133       Status = KeyboardCommand (
   1134                  BiosKeyboardPrivate,
   1135                  KBC_CMDREG_VIA64_KBC_SLFTEST
   1136                  );
   1137       if (EFI_ERROR (Status)) {
   1138         Status    = EFI_DEVICE_ERROR;
   1139         goto Exit;
   1140       }
   1141 
   1142       Status = KeyboardWaitForValue (
   1143                  BiosKeyboardPrivate,
   1144                  KBC_CMDECHO_KBCSLFTEST_OK,
   1145                  KEYBOARD_WAITFORVALUE_TIMEOUT
   1146                  );
   1147       if (EFI_ERROR (Status)) {
   1148         Status    = EFI_DEVICE_ERROR;
   1149         goto Exit;
   1150       }
   1151     }
   1152   }
   1153   //
   1154   // 7
   1155   // Disable  Mouse interface, enable  Keyboard interface and declare selftest success
   1156   //
   1157   // Mouse device will block keyboard interface before it be configured, so we should disable mouse first.
   1158   //
   1159   Status = KeyboardCommand (
   1160              BiosKeyboardPrivate,
   1161              KBC_CMDREG_VIA64_CMDBYTE_W
   1162              );
   1163 
   1164   if (EFI_ERROR (Status)) {
   1165     Status    = EFI_DEVICE_ERROR;
   1166     goto Exit;
   1167   }
   1168 
   1169   //
   1170   // Write 8042 Command Byte, set System Flag
   1171   // While at the same time:
   1172   //  1. disable mouse interface,
   1173   //  2. enable kbd interface,
   1174   //  3. enable PC/XT kbd translation mode
   1175   //  4. enable mouse and kbd interrupts
   1176   //
   1177   //Command Byte bits:
   1178   //  7: Reserved
   1179   //  6: PC/XT translation mode
   1180   //  5: Disable Auxiliary device interface
   1181   //  4: Disable keyboard interface
   1182   //  3: Reserved
   1183   //  2: System Flag
   1184   //  1: Enable Auxiliary device interrupt
   1185   //  0: Enable Keyboard interrupt
   1186   //
   1187   CommandByte = 0;
   1188   Status = KeyboardWrite (
   1189              BiosKeyboardPrivate,
   1190              (UINT8) ((CommandByte &
   1191               (~KB_CMMBYTE_DISABLE_KB)) |
   1192               KB_CMMBYTE_KSCAN2UNI_COV |
   1193               KB_CMMBYTE_ENABLE_AUXINT |
   1194               KB_CMMBYTE_ENABLE_KBINT  |
   1195               KB_CMMBYTE_SLFTEST_SUCC  |
   1196               KB_CMMBYTE_DISABLE_AUX)
   1197              );
   1198 
   1199   //
   1200   // For resetting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow,
   1201   // so we only do the real resetting for keyboard when user asks, and normally during booting an OS, it's skipped.
   1202   // Call CheckKeyboardConnect() to check whether keyboard is connected, if it is not connected,
   1203   // Real reset will not do.
   1204   //
   1205   if (ExtendedVerification && CheckKeyboardConnect (BiosKeyboardPrivate)) {
   1206     //
   1207     // 8
   1208     // Send keyboard reset command then read ACK
   1209     //
   1210     Status = KeyboardWrite (
   1211                BiosKeyboardPrivate,
   1212                KBC_INPBUF_VIA60_KBRESET
   1213                );
   1214 
   1215     if (EFI_ERROR (Status)) {
   1216       Status    = EFI_DEVICE_ERROR;
   1217       goto Exit;
   1218     }
   1219 
   1220     Status = KeyboardWaitForValue (
   1221                BiosKeyboardPrivate,
   1222                KBC_CMDECHO_ACK,
   1223                KEYBOARD_WAITFORVALUE_TIMEOUT
   1224                );
   1225 
   1226     if (EFI_ERROR (Status)) {
   1227       Status    = EFI_DEVICE_ERROR;
   1228       goto Exit;
   1229     }
   1230     //
   1231     // 9
   1232     // Wait for keyboard return test OK.
   1233     //
   1234     Status = KeyboardWaitForValue (
   1235                BiosKeyboardPrivate,
   1236                KBC_CMDECHO_BATTEST_OK,
   1237                KEYBOARD_WAITFORVALUE_TIMEOUT
   1238                );
   1239 
   1240     if (EFI_ERROR (Status)) {
   1241       Status    = EFI_DEVICE_ERROR;
   1242       goto Exit;
   1243     }
   1244     //
   1245     // 10
   1246     // set keyboard scan code set = 02 (standard configuration)
   1247     //
   1248     Status = KeyboardWrite (
   1249                BiosKeyboardPrivate,
   1250                KBC_INPBUF_VIA60_KBSCODE
   1251                );
   1252     if (EFI_ERROR (Status)) {
   1253       Status    = EFI_DEVICE_ERROR;
   1254       goto Exit;
   1255     }
   1256 
   1257     Status = KeyboardWaitForValue (
   1258                BiosKeyboardPrivate,
   1259                KBC_CMDECHO_ACK,
   1260                KEYBOARD_WAITFORVALUE_TIMEOUT
   1261                );
   1262 
   1263     if (EFI_ERROR (Status)) {
   1264       Status    = EFI_DEVICE_ERROR;
   1265       goto Exit;
   1266     }
   1267 
   1268     Status = KeyboardWrite (
   1269                BiosKeyboardPrivate,
   1270                KBC_INPBUF_VIA60_SCODESET2
   1271                );
   1272     if (EFI_ERROR (Status)) {
   1273       Status    = EFI_DEVICE_ERROR;
   1274       goto Exit;
   1275     }
   1276 
   1277     Status = KeyboardWaitForValue (
   1278                BiosKeyboardPrivate,
   1279                KBC_CMDECHO_ACK,
   1280                KEYBOARD_WAITFORVALUE_TIMEOUT
   1281                );
   1282 
   1283     if (EFI_ERROR (Status)) {
   1284       Status    = EFI_DEVICE_ERROR;
   1285       goto Exit;
   1286     }
   1287     //
   1288     // 11
   1289     // enable keyboard itself (not via KBC) by writing CMD F4 via 60H
   1290     //
   1291     Status = KeyboardWrite (
   1292                BiosKeyboardPrivate,
   1293                KBC_INPBUF_VIA60_KBEN
   1294                );
   1295     if (EFI_ERROR (Status)) {
   1296       Status    = EFI_DEVICE_ERROR;
   1297       goto Exit;
   1298     }
   1299 
   1300     Status = KeyboardWaitForValue (
   1301                BiosKeyboardPrivate,
   1302                KBC_CMDECHO_ACK,
   1303                KEYBOARD_WAITFORVALUE_TIMEOUT
   1304                );
   1305 
   1306     if (EFI_ERROR (Status)) {
   1307       Status    = EFI_DEVICE_ERROR;
   1308       goto Exit;
   1309     }
   1310     //
   1311     // 12
   1312     // Additional validation, do it as follow:
   1313     // 1). check for status register of PARE && TIM via 64H
   1314     // 2). perform KB checking by writing ABh via 64H
   1315     //
   1316     if ((KeyReadStatusRegister (BiosKeyboardPrivate) & (KBC_STSREG_VIA64_PARE | KBC_STSREG_VIA64_TIM)) != 0) {
   1317       Status    = EFI_DEVICE_ERROR;
   1318       goto Exit;
   1319     }
   1320 
   1321     Status = KeyboardCommand (
   1322                BiosKeyboardPrivate,
   1323                KBC_CMDREG_VIA64_KB_CKECK
   1324                );
   1325     if (EFI_ERROR (Status)) {
   1326       Status    = EFI_DEVICE_ERROR;
   1327       goto Exit;
   1328     }
   1329 
   1330     Status = KeyboardWaitForValue (
   1331                BiosKeyboardPrivate,
   1332                KBC_CMDECHO_KBCHECK_OK,
   1333                KEYBOARD_WAITFORVALUE_TIMEOUT
   1334                );
   1335 
   1336     if (EFI_ERROR (Status)) {
   1337       Status    = EFI_DEVICE_ERROR;
   1338       goto Exit;
   1339     }
   1340   }
   1341   //
   1342   // 13
   1343   // Done for validating keyboard. Enable keyboard (via KBC)
   1344   // and recover the command byte to proper value
   1345   //
   1346   if (!PcdGetBool (PcdFastPS2Detection)) {
   1347     Status = KeyboardCommand (
   1348                BiosKeyboardPrivate,
   1349                KBC_CMDREG_VIA64_KB_ENABLE
   1350                );
   1351 
   1352     if (EFI_ERROR (Status)) {
   1353       Status    = EFI_DEVICE_ERROR;
   1354       goto Exit;
   1355     }
   1356   }
   1357 
   1358   //
   1359   // 14
   1360   // conditionally enable mouse (via KBC)
   1361   //
   1362   if (MouseEnable) {
   1363     Status = KeyboardCommand (
   1364                BiosKeyboardPrivate,
   1365                KBC_CMDREG_VIA64_AUX_ENABLE
   1366                );
   1367 
   1368     if (EFI_ERROR (Status)) {
   1369       Status    = EFI_DEVICE_ERROR;
   1370 
   1371     }
   1372   }
   1373 
   1374 Exit:
   1375   //
   1376   // 15
   1377   // resume priority of task level
   1378   //
   1379   gBS->RestoreTPL (OldTpl);
   1380 
   1381   return Status;
   1382 
   1383 }
   1384 
   1385 /**
   1386   Read out the scan code of the key that has just been stroked.
   1387 
   1388   @param  This        Pointer of simple text Protocol.
   1389   @param  Key         Pointer for store the key that read out.
   1390 
   1391   @retval EFI_SUCCESS The key is read out successfully.
   1392   @retval other       The key reading failed.
   1393 
   1394 **/
   1395 EFI_STATUS
   1396 EFIAPI
   1397 BiosKeyboardReadKeyStroke (
   1398   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
   1399   OUT EFI_INPUT_KEY                   *Key
   1400   )
   1401 {
   1402   BIOS_KEYBOARD_DEV     *BiosKeyboardPrivate;
   1403   EFI_STATUS            Status;
   1404   EFI_KEY_DATA          KeyData;
   1405 
   1406   BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
   1407 
   1408   Status = KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, &KeyData);
   1409   if (EFI_ERROR (Status)) {
   1410     return Status;
   1411   }
   1412 
   1413   //
   1414   // Convert the Ctrl+[a-z] to Ctrl+[1-26]
   1415   //
   1416   if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
   1417     if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
   1418       KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
   1419     } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {
   1420       KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
   1421     }
   1422   }
   1423 
   1424   CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
   1425 
   1426   return EFI_SUCCESS;
   1427 }
   1428 
   1429 /**
   1430   Waiting on the keyboard event, if there's any key pressed by the user, signal the event
   1431 
   1432   @param  Event       The event that be siganlled when any key has been stroked.
   1433   @param  Context     Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
   1434 
   1435 **/
   1436 VOID
   1437 EFIAPI
   1438 BiosKeyboardWaitForKey (
   1439   IN  EFI_EVENT  Event,
   1440   IN  VOID       *Context
   1441   )
   1442 {
   1443   //
   1444   // Stall 1ms to give a chance to let other driver interrupt this routine for their timer event.
   1445   // Csm will be used to check whether there is a key pending, but the csm will disable all
   1446   // interrupt before switch to compatibility16, which mean all the efiCompatibility timer
   1447   // event will stop work during the compatibility16. And If a caller recursivly invoke this function,
   1448   // e.g. UI setup or Shell, other drivers which are driven by timer event will have a bad performance during this period,
   1449   // e.g. usb keyboard driver.
   1450   // Add a stall period can greatly increate other driver performance during the WaitForKey is recursivly invoked.
   1451   // 1ms delay will make little impact to the thunk keyboard driver, and user can not feel the delay at all when input.
   1452   //
   1453   gBS->Stall (1000);
   1454   //
   1455   // Use TimerEvent callback function to check whether there's any key pressed
   1456   //
   1457   BiosKeyboardTimerHandler (NULL, BIOS_KEYBOARD_DEV_FROM_THIS (Context));
   1458 
   1459   if (!EFI_ERROR (BiosKeyboardCheckForKey (Context))) {
   1460     gBS->SignalEvent (Event);
   1461   }
   1462 }
   1463 
   1464 /**
   1465   Check key buffer to get the key stroke status.
   1466 
   1467   @param  This         Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
   1468 
   1469   @retval EFI_SUCCESS  A key is being pressed now.
   1470   @retval Other        No key is now pressed.
   1471 
   1472 **/
   1473 EFI_STATUS
   1474 EFIAPI
   1475 BiosKeyboardCheckForKey (
   1476   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This
   1477   )
   1478 {
   1479   BIOS_KEYBOARD_DEV     *BiosKeyboardPrivate;
   1480 
   1481   BiosKeyboardPrivate = BIOS_KEYBOARD_DEV_FROM_THIS (This);
   1482 
   1483   return CheckQueue (&BiosKeyboardPrivate->Queue);
   1484 }
   1485 //
   1486 // Private worker functions
   1487 //
   1488 #define TABLE_END 0x0
   1489 
   1490 typedef struct _CONVERT_TABLE_ENTRY {
   1491   UINT16  ScanCode;
   1492   UINT16  EfiScanCode;
   1493 } CONVERT_TABLE_ENTRY;
   1494 
   1495 CONVERT_TABLE_ENTRY mConvertTable[] = {
   1496   {
   1497     0x47,
   1498     SCAN_HOME
   1499   },
   1500   {
   1501     0x48,
   1502     SCAN_UP
   1503   },
   1504   {
   1505     0x49,
   1506     SCAN_PAGE_UP
   1507   },
   1508   {
   1509     0x4b,
   1510     SCAN_LEFT
   1511   },
   1512   {
   1513     0x4d,
   1514     SCAN_RIGHT
   1515   },
   1516   {
   1517     0x4f,
   1518     SCAN_END
   1519   },
   1520   {
   1521     0x50,
   1522     SCAN_DOWN
   1523   },
   1524   {
   1525     0x51,
   1526     SCAN_PAGE_DOWN
   1527   },
   1528   {
   1529     0x52,
   1530     SCAN_INSERT
   1531   },
   1532   {
   1533     0x53,
   1534     SCAN_DELETE
   1535   },
   1536   //
   1537   // Function Keys are only valid if KeyChar == 0x00
   1538   //  This function does not require KeyChar to be 0x00
   1539   //
   1540   {
   1541     0x3b,
   1542     SCAN_F1
   1543   },
   1544   {
   1545     0x3c,
   1546     SCAN_F2
   1547   },
   1548   {
   1549     0x3d,
   1550     SCAN_F3
   1551   },
   1552   {
   1553     0x3e,
   1554     SCAN_F4
   1555   },
   1556   {
   1557     0x3f,
   1558     SCAN_F5
   1559   },
   1560   {
   1561     0x40,
   1562     SCAN_F6
   1563   },
   1564   {
   1565     0x41,
   1566     SCAN_F7
   1567   },
   1568   {
   1569     0x42,
   1570     SCAN_F8
   1571   },
   1572   {
   1573     0x43,
   1574     SCAN_F9
   1575   },
   1576   {
   1577     0x44,
   1578     SCAN_F10
   1579   },
   1580   {
   1581     0x85,
   1582     SCAN_F11
   1583   },
   1584   {
   1585     0x86,
   1586     SCAN_F12
   1587   },
   1588   //
   1589   // Convert ALT + Fn keys
   1590   //
   1591   {
   1592     0x68,
   1593     SCAN_F1
   1594   },
   1595   {
   1596     0x69,
   1597     SCAN_F2
   1598   },
   1599   {
   1600     0x6a,
   1601     SCAN_F3
   1602   },
   1603   {
   1604     0x6b,
   1605     SCAN_F4
   1606   },
   1607   {
   1608     0x6c,
   1609     SCAN_F5
   1610   },
   1611   {
   1612     0x6d,
   1613     SCAN_F6
   1614   },
   1615   {
   1616     0x6e,
   1617     SCAN_F7
   1618   },
   1619   {
   1620     0x6f,
   1621     SCAN_F8
   1622   },
   1623   {
   1624     0x70,
   1625     SCAN_F9
   1626   },
   1627   {
   1628     0x71,
   1629     SCAN_F10
   1630   },
   1631   {
   1632     TABLE_END,
   1633     SCAN_NULL
   1634   },
   1635 };
   1636 
   1637 /**
   1638   Convert unicode combined with scan code of key to the counterpart of EFIScancode of it.
   1639 
   1640   @param  KeyChar      Unicode of key.
   1641   @param  ScanCode     Scan code of key.
   1642 
   1643   @return The value of EFI Scancode for the key.
   1644   @retval SCAN_NULL   No corresponding value in the EFI convert table is found for the key.
   1645 
   1646 **/
   1647 UINT16
   1648 ConvertToEFIScanCode (
   1649   IN  CHAR16  KeyChar,
   1650   IN  UINT16  ScanCode
   1651   )
   1652 {
   1653   UINT16  EfiScanCode;
   1654   UINT16  Index;
   1655 
   1656   if (KeyChar == CHAR_ESC) {
   1657     EfiScanCode = SCAN_ESC;
   1658   } else if (KeyChar == 0x00 || KeyChar == 0xe0) {
   1659     //
   1660     // Movement & Function Keys
   1661     //
   1662     for (Index = 0; (Index < sizeof (mConvertTable) / sizeof (CONVERT_TABLE_ENTRY)) && (mConvertTable[Index].ScanCode != TABLE_END); Index += 1) {
   1663       if (ScanCode == mConvertTable[Index].ScanCode) {
   1664         return mConvertTable[Index].EfiScanCode;
   1665       }
   1666     }
   1667     //
   1668     // Reach Table end, return default value
   1669     //
   1670     return SCAN_NULL;
   1671   } else {
   1672     return SCAN_NULL;
   1673   }
   1674 
   1675   return EfiScanCode;
   1676 }
   1677 
   1678 /**
   1679   Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard Command
   1680   If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't respond, the device
   1681   should not be in system.
   1682 
   1683   @param  BiosKeyboardPrivate  Keyboard Private Data Struture
   1684 
   1685   @retval TRUE  Keyboard in System.
   1686   @retval FALSE Keyboard not in System.
   1687 
   1688 **/
   1689 BOOLEAN
   1690 CheckKeyboardConnect (
   1691   IN  BIOS_KEYBOARD_DEV     *BiosKeyboardPrivate
   1692   )
   1693 {
   1694   EFI_STATUS     Status;
   1695 
   1696   Status         = EFI_SUCCESS;
   1697   //
   1698   // enable keyboard itself and wait for its ack
   1699   // If can't receive ack, Keyboard should not be connected.
   1700   //
   1701   if (!PcdGetBool (PcdFastPS2Detection)) {
   1702     Status = KeyboardWrite (
   1703                BiosKeyboardPrivate,
   1704                KBC_INPBUF_VIA60_KBEN
   1705                );
   1706     if (EFI_ERROR (Status)) {
   1707       DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Keyboard enable failed!\n"));
   1708       REPORT_STATUS_CODE (
   1709         EFI_ERROR_CODE | EFI_ERROR_MINOR,
   1710         EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
   1711         );
   1712       return FALSE;
   1713     }
   1714 
   1715     Status = KeyboardWaitForValue (
   1716                BiosKeyboardPrivate,
   1717                KBC_CMDECHO_ACK,
   1718                KEYBOARD_WAITFORVALUE_TIMEOUT
   1719                );
   1720 
   1721     if (EFI_ERROR (Status)) {
   1722       DEBUG ((EFI_D_ERROR, "[KBD]CheckKeyboardConnect - Timeout!\n"));
   1723       REPORT_STATUS_CODE (
   1724         EFI_ERROR_CODE | EFI_ERROR_MINOR,
   1725         EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR
   1726         );
   1727       return FALSE;
   1728     }
   1729     return TRUE;
   1730   } else {
   1731     return TRUE;
   1732   }
   1733 }
   1734 
   1735 /**
   1736   Timer event handler: read a series of key stroke from 8042
   1737   and put them into memory key buffer.
   1738   It is registered as running under TPL_NOTIFY
   1739 
   1740   @param  Event   The timer event
   1741   @param  Context A BIOS_KEYBOARD_DEV pointer
   1742 
   1743 **/
   1744 VOID
   1745 EFIAPI
   1746 BiosKeyboardTimerHandler (
   1747   IN EFI_EVENT    Event,
   1748   IN VOID         *Context
   1749   )
   1750 {
   1751   EFI_TPL                            OldTpl;
   1752   BIOS_KEYBOARD_DEV                  *BiosKeyboardPrivate;
   1753   EFI_IA32_REGISTER_SET              Regs;
   1754   UINT8                              KbFlag1;  // 0040h:0017h - KEYBOARD - STATUS FLAGS 1
   1755   UINT8                              KbFlag2;  // 0040h:0018h - KEYBOARD - STATUS FLAGS 2
   1756   EFI_KEY_DATA                       KeyData;
   1757   LIST_ENTRY                         *Link;
   1758   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
   1759 
   1760   BiosKeyboardPrivate = Context;
   1761 
   1762   //
   1763   // Enter critical section
   1764   //
   1765   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   1766 
   1767   //
   1768   // if there is no key present, just return
   1769   //
   1770   if (BiosKeyboardPrivate->ExtendedKeyboard) {
   1771     Regs.H.AH = 0x11;
   1772   } else {
   1773     Regs.H.AH = 0x01;
   1774   }
   1775 
   1776   BiosKeyboardPrivate->LegacyBios->Int86 (
   1777                                      BiosKeyboardPrivate->LegacyBios,
   1778                                      0x16,
   1779                                      &Regs
   1780                                      );
   1781   if (Regs.X.Flags.ZF != 0) {
   1782     gBS->RestoreTPL (OldTpl);
   1783     return;
   1784   }
   1785 
   1786   //
   1787   // Read the key
   1788   //
   1789   if (BiosKeyboardPrivate->ExtendedKeyboard) {
   1790     Regs.H.AH = 0x10;
   1791   } else {
   1792     Regs.H.AH = 0x00;
   1793   }
   1794 
   1795   BiosKeyboardPrivate->LegacyBios->Int86 (
   1796                                      BiosKeyboardPrivate->LegacyBios,
   1797                                      0x16,
   1798                                      &Regs
   1799                                      );
   1800 
   1801   KeyData.Key.ScanCode            = (UINT16) Regs.H.AH;
   1802   KeyData.Key.UnicodeChar         = (UINT16) Regs.H.AL;
   1803   DEBUG ((
   1804     EFI_D_INFO,
   1805     "[KBD]INT16 returns EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
   1806     KeyData.Key.ScanCode,
   1807     KeyData.Key.UnicodeChar
   1808     ));
   1809 
   1810   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;
   1811   KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
   1812   //
   1813   // Leagcy Bios use Int 9 which is IRQ1 interrupt handler to get keystroke scancode to KB  buffer in BDA (BIOS DATE AREA),  then
   1814   // Int 16 depend  KB buffer and some key bits in BDA to translate the scancode to ASCII code, and  return both the scancode and ASCII
   1815   // code to Int 16 caller. This translation process works well if the Int 9  could response user input in time. But in Tiano enviorment,  the Int 9
   1816   // will be disabled after the thunk call finish, which means if user crazy input during int 9 being disabled, some keystrokes will be lost when
   1817   // KB device own hardware buffer overflows. And if the lost keystroke code is CTRL or ALT or SHIFT release code, these function key flags bit
   1818   // in BDA will not be updated. So the Int 16 will believe the CTRL or ALT or SHIFT is still pressed, and Int 16 will translate later scancode
   1819   // to wrong ASCII code. We can increase the Thunk frequence to let Int 9 response in time, but this way will much hurt other drivers
   1820   // performance, like USB.
   1821   //
   1822   // 1. If CTRL or ALT release code is missed,  all later input keys will be translated to wrong ASCII codes which the Tiano cannot support. In
   1823   //     this case, the KB input seems fail to work, and user input is blocked. To solve the problem, we can help to clear the CTRL or ALT flag in BDA
   1824   //    after every Int 16 finish. Thus persist to press CTRL or ALT has same effection as only press one time. It is Ok, since user not often use the
   1825   //    CTRL and ALT.
   1826   //
   1827   // 2. If SHIFT release code is missed, all later lowercase input will become capital. This is ugly, but not block user input. If user press the lost
   1828   //     SHIFT again,  the lowercase will come back to normal. Since user often use the SHIFT, it is not reasonable to help to clear the SHIFT flag in BDA,
   1829   //     which will let persist to press SHIFT has same effection as only press one time.
   1830   //
   1831   //0040h:0017h - KEYBOARD - STATUS FLAGS 1
   1832   //   7 INSert active
   1833   //   6 Caps Lock active
   1834   //   5 Num Lock active
   1835   //   4 Scroll Lock active
   1836   //   3 either Alt pressed
   1837   //   2 either Ctrl pressed
   1838   //   1 Left Shift pressed
   1839   //   0 Right Shift pressed
   1840 
   1841 
   1842   //
   1843   // Clear the CTRL and ALT BDA flag
   1844   //
   1845   KbFlag1 = *((UINT8 *) (UINTN) 0x417);  // read the STATUS FLAGS 1
   1846   KbFlag2 = *((UINT8 *) (UINTN) 0x418); // read STATUS FLAGS 2
   1847 
   1848   DEBUG_CODE (
   1849     {
   1850       if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {
   1851         DEBUG ((EFI_D_INFO, "[KBD]Caps Lock Key is pressed.\n"));
   1852       }
   1853       if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {
   1854         DEBUG ((EFI_D_INFO, "[KBD]Num Lock Key is pressed.\n"));
   1855       }
   1856       if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {
   1857         DEBUG ((EFI_D_INFO, "[KBD]Scroll Lock Key is pressed.\n"));
   1858       }
   1859       if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {
   1860         if ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) {
   1861           DEBUG ((EFI_D_INFO, "[KBD]Left Alt Key is pressed.\n"));
   1862         } else {
   1863           DEBUG ((EFI_D_INFO, "[KBD]Right Alt Key is pressed.\n"));
   1864         }
   1865       }
   1866       if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {
   1867         if ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) {
   1868           DEBUG ((EFI_D_INFO, "[KBD]Left Ctrl Key is pressed.\n"));
   1869         } else {
   1870           DEBUG ((EFI_D_INFO, "[KBD]Right Ctrl Key is pressed.\n"));
   1871         }
   1872       }
   1873       if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {
   1874         DEBUG ((EFI_D_INFO, "[KBD]Left Shift Key is pressed.\n"));
   1875       }
   1876       if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {
   1877         DEBUG ((EFI_D_INFO, "[KBD]Right Shift Key is pressed.\n"));
   1878       }
   1879     }
   1880   );
   1881 
   1882   //
   1883   // Record toggle state
   1884   //
   1885   if ((KbFlag1 & KB_CAPS_LOCK_BIT) == KB_CAPS_LOCK_BIT) {
   1886     KeyData.KeyState.KeyToggleState |= EFI_CAPS_LOCK_ACTIVE;
   1887   }
   1888   if ((KbFlag1 & KB_NUM_LOCK_BIT) == KB_NUM_LOCK_BIT) {
   1889     KeyData.KeyState.KeyToggleState |= EFI_NUM_LOCK_ACTIVE;
   1890   }
   1891   if ((KbFlag1 & KB_SCROLL_LOCK_BIT) == KB_SCROLL_LOCK_BIT) {
   1892     KeyData.KeyState.KeyToggleState |= EFI_SCROLL_LOCK_ACTIVE;
   1893   }
   1894   //
   1895   // Record shift state
   1896   // BUGBUG: Need add Menu key and Left/Right Logo key state in the future
   1897   //
   1898   if ((KbFlag1 & KB_ALT_PRESSED) == KB_ALT_PRESSED) {
   1899     KeyData.KeyState.KeyShiftState  |= ((KbFlag2 & KB_LEFT_ALT_PRESSED) == KB_LEFT_ALT_PRESSED) ? EFI_LEFT_ALT_PRESSED : EFI_RIGHT_ALT_PRESSED;
   1900   }
   1901   if ((KbFlag1 & KB_CTRL_PRESSED) == KB_CTRL_PRESSED) {
   1902     KeyData.KeyState.KeyShiftState  |= ((KbFlag2 & KB_LEFT_CTRL_PRESSED) == KB_LEFT_CTRL_PRESSED) ? EFI_LEFT_CONTROL_PRESSED : EFI_RIGHT_CONTROL_PRESSED;
   1903   }
   1904   if ((KbFlag1 & KB_LEFT_SHIFT_PRESSED) == KB_LEFT_SHIFT_PRESSED) {
   1905     KeyData.KeyState.KeyShiftState  |= EFI_LEFT_SHIFT_PRESSED;
   1906   }
   1907   if ((KbFlag1 & KB_RIGHT_SHIFT_PRESSED) == KB_RIGHT_SHIFT_PRESSED) {
   1908     KeyData.KeyState.KeyShiftState  |= EFI_RIGHT_SHIFT_PRESSED;
   1909   }
   1910 
   1911   //
   1912   // Clear left alt and left ctrl BDA flag
   1913   //
   1914   KbFlag2 &= ~(KB_LEFT_ALT_PRESSED | KB_LEFT_CTRL_PRESSED);
   1915   *((UINT8 *) (UINTN) 0x418) = KbFlag2;
   1916   KbFlag1 &= ~0x0C;
   1917   *((UINT8 *) (UINTN) 0x417) = KbFlag1;
   1918 
   1919 
   1920   //
   1921   // Output EFI input key and shift/toggle state
   1922   //
   1923   if (KeyData.Key.UnicodeChar == CHAR_NULL || KeyData.Key.UnicodeChar == CHAR_SCANCODE || KeyData.Key.UnicodeChar == CHAR_ESC) {
   1924     KeyData.Key.ScanCode     = ConvertToEFIScanCode (KeyData.Key.UnicodeChar, KeyData.Key.ScanCode);
   1925     KeyData.Key.UnicodeChar  = CHAR_NULL;
   1926   } else {
   1927     KeyData.Key.ScanCode     = SCAN_NULL;
   1928   }
   1929 
   1930   //
   1931   // CSM16 has converted the Ctrl+[a-z] to [1-26], converted it back.
   1932   //
   1933   if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
   1934     if (KeyData.Key.UnicodeChar >= 1 && KeyData.Key.UnicodeChar <= 26) {
   1935       if (((KeyData.KeyState.KeyShiftState & (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)) != 0) ==
   1936           ((KeyData.KeyState.KeyToggleState & EFI_CAPS_LOCK_ACTIVE) != 0)
   1937           ) {
   1938         KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'a' - 1);
   1939       } else {
   1940         KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar + L'A' - 1);
   1941       }
   1942     }
   1943   }
   1944 
   1945   DEBUG ((
   1946     EFI_D_INFO,
   1947     "[KBD]Convert to EFI Scan Code, EFI_INPUT_KEY.ScanCode - %x, EFI_INPUT_KEY.UnicodeChar - %x\n",
   1948     KeyData.Key.ScanCode,
   1949     KeyData.Key.UnicodeChar
   1950     ));
   1951 
   1952   //
   1953   // Need not return associated shift state if a class of printable characters that
   1954   // are normally adjusted by shift modifiers.
   1955   // e.g. Shift Key + 'f' key = 'F'; Shift Key + 'F' key = 'f'.
   1956   //
   1957   if ((KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') ||
   1958       (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z')
   1959      ) {
   1960     DEBUG ((EFI_D_INFO, "[KBD]Shift key with a~z are pressed, remove shift state in EFI_KEY_STATE.\n"));
   1961     KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED);
   1962   }
   1963 
   1964   //
   1965   // Signal KeyNotify process event if this key pressed matches any key registered.
   1966   //
   1967   for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
   1968     CurrentNotify = CR (
   1969                       Link,
   1970                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
   1971                       NotifyEntry,
   1972                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
   1973                       );
   1974     if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
   1975       //
   1976       // The key notification function needs to run at TPL_CALLBACK
   1977       // while current TPL is TPL_NOTIFY. It will be invoked in
   1978       // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
   1979       //
   1980       Enqueue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);
   1981       gBS->SignalEvent (BiosKeyboardPrivate->KeyNotifyProcessEvent);
   1982     }
   1983   }
   1984 
   1985   Enqueue (&BiosKeyboardPrivate->Queue, &KeyData);
   1986   //
   1987   // Leave critical section and return
   1988   //
   1989   gBS->RestoreTPL (OldTpl);
   1990 
   1991   return ;
   1992 }
   1993 
   1994 /**
   1995   Process key notify.
   1996 
   1997   @param  Event                 Indicates the event that invoke this function.
   1998   @param  Context               Indicates the calling context.
   1999 **/
   2000 VOID
   2001 EFIAPI
   2002 KeyNotifyProcessHandler (
   2003   IN  EFI_EVENT                 Event,
   2004   IN  VOID                      *Context
   2005   )
   2006 {
   2007   EFI_STATUS                            Status;
   2008   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2009   EFI_KEY_DATA                          KeyData;
   2010   LIST_ENTRY                            *Link;
   2011   LIST_ENTRY                            *NotifyList;
   2012   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;
   2013   EFI_TPL                               OldTpl;
   2014 
   2015   BiosKeyboardPrivate = (BIOS_KEYBOARD_DEV *) Context;
   2016 
   2017   //
   2018   // Invoke notification functions.
   2019   //
   2020   NotifyList = &BiosKeyboardPrivate->NotifyList;
   2021   while (TRUE) {
   2022     //
   2023     // Enter critical section
   2024     //
   2025     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   2026     Status = Dequeue (&BiosKeyboardPrivate->QueueForNotify, &KeyData);
   2027     //
   2028     // Leave critical section
   2029     //
   2030     gBS->RestoreTPL (OldTpl);
   2031     if (EFI_ERROR (Status)) {
   2032       break;
   2033     }
   2034     for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
   2035       CurrentNotify = CR (Link, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
   2036       if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
   2037         CurrentNotify->KeyNotificationFn (&KeyData);
   2038       }
   2039     }
   2040   }
   2041 }
   2042 
   2043 /**
   2044   Free keyboard notify list.
   2045 
   2046   @param  ListHead   The list head
   2047 
   2048   @retval EFI_SUCCESS           Free the notify list successfully
   2049   @retval EFI_INVALID_PARAMETER ListHead is invalid.
   2050 
   2051 **/
   2052 EFI_STATUS
   2053 BiosKeyboardFreeNotifyList (
   2054   IN OUT LIST_ENTRY           *ListHead
   2055   )
   2056 {
   2057   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
   2058 
   2059   if (ListHead == NULL) {
   2060     return EFI_INVALID_PARAMETER;
   2061   }
   2062   while (!IsListEmpty (ListHead)) {
   2063     NotifyNode = CR (
   2064                    ListHead->ForwardLink,
   2065                    BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
   2066                    NotifyEntry,
   2067                    BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
   2068                    );
   2069     RemoveEntryList (ListHead->ForwardLink);
   2070     gBS->FreePool (NotifyNode);
   2071   }
   2072 
   2073   return EFI_SUCCESS;
   2074 }
   2075 
   2076 /**
   2077   Check if key is registered.
   2078 
   2079   @param  RegsiteredData    A pointer to a buffer that is filled in with the keystroke
   2080                             state data for the key that was registered.
   2081   @param  InputData         A pointer to a buffer that is filled in with the keystroke
   2082                             state data for the key that was pressed.
   2083 
   2084   @retval TRUE              Key be pressed matches a registered key.
   2085   @retval FLASE             Match failed.
   2086 
   2087 **/
   2088 BOOLEAN
   2089 IsKeyRegistered (
   2090   IN EFI_KEY_DATA  *RegsiteredData,
   2091   IN EFI_KEY_DATA  *InputData
   2092   )
   2093 {
   2094   ASSERT (RegsiteredData != NULL && InputData != NULL);
   2095 
   2096   if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
   2097       (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
   2098     return FALSE;
   2099   }
   2100 
   2101   //
   2102   // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
   2103   //
   2104   if (RegsiteredData->KeyState.KeyShiftState != 0 &&
   2105       RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
   2106     return FALSE;
   2107   }
   2108   if (RegsiteredData->KeyState.KeyToggleState != 0 &&
   2109       RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
   2110     return FALSE;
   2111   }
   2112 
   2113   return TRUE;
   2114 
   2115 }
   2116 
   2117 /**
   2118   Waiting on the keyboard event, if there's any key pressed by the user, signal the event
   2119 
   2120   @param  Event    The event that be siganlled when any key has been stroked.
   2121   @param  Context  Pointer of the protocol EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
   2122 
   2123 **/
   2124 VOID
   2125 EFIAPI
   2126 BiosKeyboardWaitForKeyEx (
   2127   IN  EFI_EVENT  Event,
   2128   IN  VOID       *Context
   2129   )
   2130 {
   2131   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2132 
   2133   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (Context);
   2134   BiosKeyboardWaitForKey (Event, &BiosKeyboardPrivate->SimpleTextIn);
   2135 
   2136 }
   2137 
   2138 /**
   2139   Reset the input device and optionaly run diagnostics
   2140 
   2141   @param  This                  Protocol instance pointer.
   2142   @param  ExtendedVerification  Driver may perform diagnostics on reset.
   2143 
   2144   @retval EFI_SUCCESS           The device was reset.
   2145   @retval EFI_DEVICE_ERROR      The device is not functioning properly and could
   2146                                 not be reset.
   2147 
   2148 **/
   2149 EFI_STATUS
   2150 EFIAPI
   2151 BiosKeyboardResetEx (
   2152   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
   2153   IN BOOLEAN                            ExtendedVerification
   2154   )
   2155 {
   2156   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2157   EFI_STATUS                            Status;
   2158   EFI_TPL                               OldTpl;
   2159 
   2160   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
   2161 
   2162   Status = BiosKeyboardPrivate->SimpleTextIn.Reset (
   2163                                                &BiosKeyboardPrivate->SimpleTextIn,
   2164                                                ExtendedVerification
   2165                                                );
   2166   if (EFI_ERROR (Status)) {
   2167     return EFI_DEVICE_ERROR;
   2168   }
   2169 
   2170   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   2171 
   2172   gBS->RestoreTPL (OldTpl);
   2173 
   2174   return EFI_SUCCESS;
   2175 
   2176 }
   2177 
   2178 /**
   2179   Reads the next keystroke from the input device. The WaitForKey Event can
   2180   be used to test for existance of a keystroke via WaitForEvent () call.
   2181 
   2182   @param  This         Protocol instance pointer.
   2183   @param  KeyData      A pointer to a buffer that is filled in with the keystroke
   2184                        state data for the key that was pressed.
   2185 
   2186   @retval  EFI_SUCCESS           The keystroke information was returned.
   2187   @retval  EFI_NOT_READY         There was no keystroke data availiable.
   2188   @retval  EFI_DEVICE_ERROR      The keystroke information was not returned due to
   2189                                  hardware errors.
   2190   @retval  EFI_INVALID_PARAMETER KeyData is NULL.
   2191 
   2192 **/
   2193 EFI_STATUS
   2194 EFIAPI
   2195 BiosKeyboardReadKeyStrokeEx (
   2196   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
   2197   OUT EFI_KEY_DATA                      *KeyData
   2198   )
   2199 {
   2200   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2201 
   2202   if (KeyData == NULL) {
   2203     return EFI_INVALID_PARAMETER;
   2204   }
   2205 
   2206   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
   2207 
   2208   return KeyboardReadKeyStrokeWorker (BiosKeyboardPrivate, KeyData);
   2209 
   2210 }
   2211 
   2212 /**
   2213   Set certain state for the input device.
   2214 
   2215   @param  This              Protocol instance pointer.
   2216   @param  KeyToggleState    A pointer to the EFI_KEY_TOGGLE_STATE to set the
   2217                             state for the input device.
   2218 
   2219   @retval EFI_SUCCESS           The device state was set successfully.
   2220   @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could
   2221                                 not have the setting adjusted.
   2222   @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.
   2223   @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
   2224 
   2225 **/
   2226 EFI_STATUS
   2227 EFIAPI
   2228 BiosKeyboardSetState (
   2229   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
   2230   IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
   2231   )
   2232 {
   2233   EFI_STATUS                            Status;
   2234   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2235   EFI_TPL                               OldTpl;
   2236   EFI_LEGACY_BIOS_PROTOCOL              *LegacyBios;
   2237   UINT8                                 Command;
   2238 
   2239   if (KeyToggleState == NULL) {
   2240     return EFI_INVALID_PARAMETER;
   2241   }
   2242 
   2243   //
   2244   // Thunk keyboard driver doesn't support partial keystroke.
   2245   //
   2246   if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID ||
   2247       (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED
   2248       ) {
   2249     return EFI_UNSUPPORTED;
   2250   }
   2251 
   2252   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
   2253   //
   2254   // See if the Legacy BIOS Protocol is available
   2255   //
   2256   Status = gBS->LocateProtocol (
   2257                   &gEfiLegacyBiosProtocolGuid,
   2258                   NULL,
   2259                   (VOID **) &LegacyBios
   2260                   );
   2261 
   2262   ASSERT_EFI_ERROR (Status);
   2263   //
   2264   // Enter critical section
   2265   //
   2266   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   2267 
   2268   Command = 0;
   2269   if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
   2270     Command |= 4;
   2271   }
   2272   if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
   2273     Command |= 2;
   2274   }
   2275   if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
   2276     Command |= 1;
   2277   }
   2278 
   2279   Status = KeyboardWrite (BiosKeyboardPrivate, 0xed);
   2280   if (EFI_ERROR (Status)) {
   2281     Status = EFI_DEVICE_ERROR;
   2282     goto Exit;
   2283   }
   2284   Status = KeyboardWaitForValue (BiosKeyboardPrivate, 0xfa, KEYBOARD_WAITFORVALUE_TIMEOUT);
   2285   if (EFI_ERROR (Status)) {
   2286     Status = EFI_DEVICE_ERROR;
   2287     goto Exit;
   2288   }
   2289   Status = KeyboardWrite (BiosKeyboardPrivate, Command);
   2290   if (EFI_ERROR (Status)) {
   2291     Status = EFI_DEVICE_ERROR;
   2292     goto Exit;
   2293   }
   2294   //
   2295   // Call Legacy BIOS Protocol to set whatever is necessary
   2296   //
   2297   LegacyBios->UpdateKeyboardLedStatus (LegacyBios, Command);
   2298 
   2299   Status = EFI_SUCCESS;
   2300 
   2301 Exit:
   2302   //
   2303   // Leave critical section and return
   2304   //
   2305   gBS->RestoreTPL (OldTpl);
   2306 
   2307   return Status;
   2308 
   2309 }
   2310 
   2311 /**
   2312   Register a notification function for a particular keystroke for the input device.
   2313 
   2314   @param  This                    Protocol instance pointer.
   2315   @param  KeyData                 A pointer to a buffer that is filled in with the keystroke
   2316                                   information data for the key that was pressed.
   2317   @param  KeyNotificationFunction Points to the function to be called when the key
   2318                                   sequence is typed specified by KeyData.
   2319   @param  NotifyHandle            Points to the unique handle assigned to the registered notification.
   2320 
   2321 
   2322   @retval EFI_SUCCESS             The notification function was registered successfully.
   2323   @retval EFI_OUT_OF_RESOURCES    Unable to allocate resources for necesssary data structures.
   2324   @retval EFI_INVALID_PARAMETER   KeyData or NotifyHandle is NULL.
   2325 
   2326 **/
   2327 EFI_STATUS
   2328 EFIAPI
   2329 BiosKeyboardRegisterKeyNotify (
   2330   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
   2331   IN EFI_KEY_DATA                       *KeyData,
   2332   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
   2333   OUT VOID                              **NotifyHandle
   2334   )
   2335 {
   2336   EFI_STATUS                            Status;
   2337   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2338   EFI_TPL                               OldTpl;
   2339   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *NewNotify;
   2340   LIST_ENTRY                            *Link;
   2341   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;
   2342 
   2343   if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {
   2344     return EFI_INVALID_PARAMETER;
   2345   }
   2346 
   2347   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
   2348 
   2349   //
   2350   // Enter critical section
   2351   //
   2352   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   2353 
   2354   //
   2355   // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
   2356   //
   2357   for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
   2358     CurrentNotify = CR (
   2359                       Link,
   2360                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
   2361                       NotifyEntry,
   2362                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
   2363                       );
   2364     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
   2365       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
   2366         *NotifyHandle = CurrentNotify;
   2367         Status = EFI_SUCCESS;
   2368         goto Exit;
   2369       }
   2370     }
   2371   }
   2372 
   2373   //
   2374   // Allocate resource to save the notification function
   2375   //
   2376 
   2377   NewNotify = (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY));
   2378   if (NewNotify == NULL) {
   2379     Status = EFI_OUT_OF_RESOURCES;
   2380     goto Exit;
   2381   }
   2382 
   2383   NewNotify->Signature         = BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
   2384   NewNotify->KeyNotificationFn = KeyNotificationFunction;
   2385   CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
   2386   InsertTailList (&BiosKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);
   2387 
   2388   *NotifyHandle                = NewNotify;
   2389   Status                       = EFI_SUCCESS;
   2390 
   2391 Exit:
   2392   //
   2393   // Leave critical section and return
   2394   //
   2395   gBS->RestoreTPL (OldTpl);
   2396   return Status;
   2397 }
   2398 
   2399 /**
   2400   Remove a registered notification function from a particular keystroke.
   2401 
   2402   @param  This                 Protocol instance pointer.
   2403   @param  NotificationHandle   The handle of the notification function being unregistered.
   2404 
   2405   @retval EFI_SUCCESS             The notification function was unregistered successfully.
   2406   @retval EFI_INVALID_PARAMETER   The NotificationHandle is invalid.
   2407 
   2408 **/
   2409 EFI_STATUS
   2410 EFIAPI
   2411 BiosKeyboardUnregisterKeyNotify (
   2412   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
   2413   IN VOID                               *NotificationHandle
   2414   )
   2415 {
   2416   EFI_STATUS                            Status;
   2417   BIOS_KEYBOARD_DEV                     *BiosKeyboardPrivate;
   2418   EFI_TPL                               OldTpl;
   2419   LIST_ENTRY                            *Link;
   2420   BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY    *CurrentNotify;
   2421 
   2422   //
   2423   // Check incoming notification handle
   2424   //
   2425   if (NotificationHandle == NULL) {
   2426     return EFI_INVALID_PARAMETER;
   2427   }
   2428 
   2429   if (((BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
   2430     return EFI_INVALID_PARAMETER;
   2431   }
   2432 
   2433   BiosKeyboardPrivate = TEXT_INPUT_EX_BIOS_KEYBOARD_DEV_FROM_THIS (This);
   2434 
   2435   //
   2436   // Enter critical section
   2437   //
   2438   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   2439 
   2440   for (Link = BiosKeyboardPrivate->NotifyList.ForwardLink; Link != &BiosKeyboardPrivate->NotifyList; Link = Link->ForwardLink) {
   2441     CurrentNotify = CR (
   2442                       Link,
   2443                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
   2444                       NotifyEntry,
   2445                       BIOS_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
   2446                       );
   2447     if (CurrentNotify == NotificationHandle) {
   2448       //
   2449       // Remove the notification function from NotifyList and free resources
   2450       //
   2451       RemoveEntryList (&CurrentNotify->NotifyEntry);
   2452 
   2453       Status = EFI_SUCCESS;
   2454       goto Exit;
   2455     }
   2456   }
   2457 
   2458   //
   2459   // Can not find the specified Notification Handle
   2460   //
   2461   Status = EFI_INVALID_PARAMETER;
   2462 
   2463 Exit:
   2464   //
   2465   // Leave critical section and return
   2466   //
   2467   gBS->RestoreTPL (OldTpl);
   2468   return Status;
   2469 }
   2470 
   2471 /**
   2472   The user Entry Point for module BiosKeyboard. The user code starts with this function.
   2473 
   2474   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   2475   @param[in] SystemTable    A pointer to the EFI System Table.
   2476 
   2477   @retval EFI_SUCCESS       The entry point is executed successfully.
   2478   @retval other             Some error occurs when executing this entry point.
   2479 
   2480 **/
   2481 EFI_STATUS
   2482 EFIAPI
   2483 InitializeBiosKeyboard(
   2484   IN EFI_HANDLE           ImageHandle,
   2485   IN EFI_SYSTEM_TABLE     *SystemTable
   2486   )
   2487 {
   2488   EFI_STATUS              Status;
   2489 
   2490   //
   2491   // Install driver model protocol(s).
   2492   //
   2493   Status = EfiLibInstallDriverBindingComponentName2 (
   2494              ImageHandle,
   2495              SystemTable,
   2496              &gBiosKeyboardDriverBinding,
   2497              ImageHandle,
   2498              &gBiosKeyboardComponentName,
   2499              &gBiosKeyboardComponentName2
   2500              );
   2501   ASSERT_EFI_ERROR (Status);
   2502 
   2503   return Status;
   2504 }
   2505