Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <[email protected]>
Cc: Feng Tian <[email protected]>
---
 .../Bus/Isa/Ps2KeyboardDxe/ComponentName.c         |  352 ++++
 .../Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c         | 1872 ++++++++++++++++++++
 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c |  683 +++++++
 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c  |  647 +++++++
 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h  |  551 ++++++
 .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf      |   84 +
 .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni      |   23 +
 .../Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni |   20 +
 MdeModulePkg/Include/Protocol/Ps2Policy.h          |   41 +
 MdeModulePkg/MdeModulePkg.dec                      |    8 +
 MdeModulePkg/MdeModulePkg.dsc                      |    1 +
 11 files changed, 4282 insertions(+)
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni
 create mode 100644 MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni
 create mode 100644 MdeModulePkg/Include/Protocol/Ps2Policy.h

diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c
new file mode 100644
index 0000000..e64e46b
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c
@@ -0,0 +1,352 @@
+/** @file
+  Routines related Component Name protocol.
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ps2Keyboard.h"
+
+//
+// EFI Component Name Functions
+//
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+Ps2KeyboardComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified 
by
+  Language, then a pointer to the controller name is returned in 
ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not 
currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter 
that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus 
drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name 
in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+Ps2KeyboardComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        
OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+
+//
+// EFI Component Name Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  
gPs2KeyboardComponentName = {
+  Ps2KeyboardComponentNameGetDriverName,
+  Ps2KeyboardComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL 
gPs2KeyboardComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) Ps2KeyboardComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) 
Ps2KeyboardComponentNameGetControllerName,
+  "en"
+};
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE 
mPs2KeyboardDriverNameTable[] = {
+  {
+    "eng;en",
+    L"PS/2 Keyboard Driver"
+  },
+  {
+    NULL,
+    NULL
+  }
+};
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+Ps2KeyboardComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mPs2KeyboardDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gPs2KeyboardComponentName)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified 
by
+  Language, then a pointer to the controller name is returned in 
ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not 
currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL 
or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter 
that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus 
drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name 
in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+Ps2KeyboardComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        
OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  EFI_STATUS                                  Status;
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL              *ConIn;
+  KEYBOARD_CONSOLE_IN_DEV                     *ConsoleIn;
+  //
+  // This is a device driver, so ChildHandle must be NULL.
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check Controller's handle
+  //
+  Status = EfiTestManagedDevice (ControllerHandle, 
gKeyboardControllerDriver.DriverBindingHandle, &gEfiSioProtocolGuid);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Get the device context
+  //
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiSimpleTextInProtocolGuid,
+                  (VOID **) &ConIn,
+                  gKeyboardControllerDriver.DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
+
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           ConsoleIn->ControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This == &gPs2KeyboardComponentName)
+           );
+}
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
new file mode 100644
index 0000000..4f064f7
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c
@@ -0,0 +1,1872 @@
+/** @file
+  Routines that access 8042 keyboard controller
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ps2Keyboard.h"
+
+struct {
+  UINT8   ScanCode;             ///< follows value defined in Scan Code Set1
+  UINT16  EfiScanCode;
+  CHAR16  UnicodeChar;
+  CHAR16  ShiftUnicodeChar;
+}
+ConvertKeyboardScanCodeToEfiKey[] = {
+
+  {
+    0x01,  //   Escape
+    SCAN_ESC,
+    0x0000,
+    0x0000
+  },
+  {
+    0x02,
+    SCAN_NULL,
+    L'1',
+    L'!'
+  },
+  {
+    0x03,
+    SCAN_NULL,
+    L'2',
+    L'@'
+  },
+  {
+    0x04,
+    SCAN_NULL,
+    L'3',
+    L'#'
+  },
+  {
+    0x05,
+    SCAN_NULL,
+    L'4',
+    L'$'
+  },
+  {
+    0x06,
+    SCAN_NULL,
+    L'5',
+    L'%'
+  },
+  {
+    0x07,
+    SCAN_NULL,
+    L'6',
+    L'^'
+  },
+  {
+    0x08,
+    SCAN_NULL,
+    L'7',
+    L'&'
+  },
+  {
+    0x09,
+    SCAN_NULL,
+    L'8',
+    L'*'
+  },
+  {
+    0x0A,
+    SCAN_NULL,
+    L'9',
+    L'('
+  },
+  {
+    0x0B,
+    SCAN_NULL,
+    L'0',
+    L')'
+  },
+  {
+    0x0C,
+    SCAN_NULL,
+    L'-',
+    L'_'
+  },
+  {
+    0x0D,
+    SCAN_NULL,
+    L'=',
+    L'+'
+  },
+  {
+    0x0E, //  BackSpace
+    SCAN_NULL,
+    0x0008,
+    0x0008
+  },
+  {
+    0x0F, //  Tab
+    SCAN_NULL,
+    0x0009,
+    0x0009
+  },
+  {
+    0x10,
+    SCAN_NULL,
+    L'q',
+    L'Q'
+  },
+  {
+    0x11,
+    SCAN_NULL,
+    L'w',
+    L'W'
+  },
+  {
+    0x12,
+    SCAN_NULL,
+    L'e',
+    L'E'
+  },
+  {
+    0x13,
+    SCAN_NULL,
+    L'r',
+    L'R'
+  },
+  {
+    0x14,
+    SCAN_NULL,
+    L't',
+    L'T'
+  },
+  {
+    0x15,
+    SCAN_NULL,
+    L'y',
+    L'Y'
+  },
+  {
+    0x16,
+    SCAN_NULL,
+    L'u',
+    L'U'
+  },
+  {
+    0x17,
+    SCAN_NULL,
+    L'i',
+    L'I'
+  },
+  {
+    0x18,
+    SCAN_NULL,
+    L'o',
+    L'O'
+  },
+  {
+    0x19,
+    SCAN_NULL,
+    L'p',
+    L'P'
+  },
+  {
+    0x1a,
+    SCAN_NULL,
+    L'[',
+    L'{'
+  },
+  {
+    0x1b,
+    SCAN_NULL,
+    L']',
+    L'}'
+  },
+  {
+    0x1c, //   Enter
+    SCAN_NULL,
+    0x000d,
+    0x000d
+  },
+  {
+    0x1d,
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x1e,
+    SCAN_NULL,
+    L'a',
+    L'A'
+  },
+  {
+    0x1f,
+    SCAN_NULL,
+    L's',
+    L'S'
+  },
+  {
+    0x20,
+    SCAN_NULL,
+    L'd',
+    L'D'
+  },
+  {
+    0x21,
+    SCAN_NULL,
+    L'f',
+    L'F'
+  },
+  {
+    0x22,
+    SCAN_NULL,
+    L'g',
+    L'G'
+  },
+  {
+    0x23,
+    SCAN_NULL,
+    L'h',
+    L'H'
+  },
+  {
+    0x24,
+    SCAN_NULL,
+    L'j',
+    L'J'
+  },
+  {
+    0x25,
+    SCAN_NULL,
+    L'k',
+    L'K'
+  },
+  {
+    0x26,
+    SCAN_NULL,
+    L'l',
+    L'L'
+  },
+  {
+    0x27,
+    SCAN_NULL,
+    L';',
+    L':'
+  },
+  {
+    0x28,
+    SCAN_NULL,
+    L'\'',
+    L'"'
+  },
+  {
+    0x29,
+    SCAN_NULL,
+    L'`',
+    L'~'
+  },
+  {
+    0x2a, //   Left Shift
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x2b,
+    SCAN_NULL,
+    L'\\',
+    L'|'
+  },
+  {
+    0x2c,
+    SCAN_NULL,
+    L'z',
+    L'Z'
+  },
+  {
+    0x2d,
+    SCAN_NULL,
+    L'x',
+    L'X'
+  },
+  {
+    0x2e,
+    SCAN_NULL,
+    L'c',
+    L'C'
+  },
+  {
+    0x2f,
+    SCAN_NULL,
+    L'v',
+    L'V'
+  },
+  {
+    0x30,
+    SCAN_NULL,
+    L'b',
+    L'B'
+  },
+  {
+    0x31,
+    SCAN_NULL,
+    L'n',
+    L'N'
+  },
+  {
+    0x32,
+    SCAN_NULL,
+    L'm',
+    L'M'
+  },
+  {
+    0x33,
+    SCAN_NULL,
+    L',',
+    L'<'
+  },
+  {
+    0x34,
+    SCAN_NULL,
+    L'.',
+    L'>'
+  },
+  {
+    0x35,
+    SCAN_NULL,
+    L'/',
+    L'?'
+  },
+  {
+    0x36, //Right Shift
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x37, // Numeric Keypad *
+    SCAN_NULL,
+    L'*',
+    L'*'
+  },
+  {
+    0x38,  //Left Alt/Extended Right Alt
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x39,
+    SCAN_NULL,
+    L' ',
+    L' '
+  },
+  {
+    0x3A, //CapsLock
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x3B,
+    SCAN_F1,
+    0x0000,
+    0x0000
+  },
+  {
+    0x3C,
+    SCAN_F2,
+    0x0000,
+    0x0000
+  },
+  {
+    0x3D,
+    SCAN_F3,
+    0x0000,
+    0x0000
+  },
+  {
+    0x3E,
+    SCAN_F4,
+    0x0000,
+    0x0000
+  },
+  {
+    0x3F,
+    SCAN_F5,
+    0x0000,
+    0x0000
+  },
+  {
+    0x40,
+    SCAN_F6,
+    0x0000,
+    0x0000
+  },
+  {
+    0x41,
+    SCAN_F7,
+    0x0000,
+    0x0000
+  },
+  {
+    0x42,
+    SCAN_F8,
+    0x0000,
+    0x0000
+  },
+  {
+    0x43,
+    SCAN_F9,
+    0x0000,
+    0x0000
+  },
+  {
+    0x44,
+    SCAN_F10,
+    0x0000,
+    0x0000
+  },
+  {
+    0x45, // NumLock
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x46, //  ScrollLock
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x47,
+    SCAN_HOME,
+    L'7',
+    L'7'
+  },
+  {
+    0x48,
+    SCAN_UP,
+    L'8',
+    L'8'
+  },
+  {
+    0x49,
+    SCAN_PAGE_UP,
+    L'9',
+    L'9'
+  },
+  {
+    0x4a,
+    SCAN_NULL,
+    L'-',
+    L'-'
+  },
+  {
+    0x4b,
+    SCAN_LEFT,
+    L'4',
+    L'4'
+  },
+  {
+    0x4c, //  Numeric Keypad 5
+    SCAN_NULL,
+    L'5',
+    L'5'
+  },
+  {
+    0x4d,
+    SCAN_RIGHT,
+    L'6',
+    L'6'
+  },
+  {
+    0x4e,
+    SCAN_NULL,
+    L'+',
+    L'+'
+  },
+  {
+    0x4f,
+    SCAN_END,
+    L'1',
+    L'1'
+  },
+  {
+    0x50,
+    SCAN_DOWN,
+    L'2',
+    L'2'
+  },
+  {
+    0x51,
+    SCAN_PAGE_DOWN,
+    L'3',
+    L'3'
+  },
+  {
+    0x52,
+    SCAN_INSERT,
+    L'0',
+    L'0'
+  },
+  {
+    0x53,
+    SCAN_DELETE,
+    L'.',
+    L'.'
+  },
+  {
+    0x57,
+    SCAN_F11,
+    0x0000,
+    0x0000
+  },
+  {
+    0x58,
+    SCAN_F12,
+    0x0000,
+    0x0000
+  },
+  {
+    0x5B,  //Left LOGO
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x5C,  //Right LOGO
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    0x5D,  //Menu key
+    SCAN_NULL,
+    0x0000,
+    0x0000
+  },
+  {
+    TABLE_END,
+    TABLE_END,
+    SCAN_NULL,
+    SCAN_NULL
+  },
+};
+
+//
+// The WaitForValue time out
+//
+UINTN  mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
+
+BOOLEAN          mEnableMouseInterface;
+
+
+
+/**
+  Return the count of scancode in the queue.
+
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
+
+  @return          Count of the scancode.
+**/
+UINTN
+GetScancodeBufCount (
+  IN SCAN_CODE_QUEUE       *Queue
+  )
+{
+  if (Queue->Head <= Queue->Tail) {
+    return Queue->Tail - Queue->Head;
+  } else {
+    return Queue->Tail + KEYBOARD_SCAN_CODE_MAX_COUNT - Queue->Head;
+  }
+}
+
+/**
+  Read several bytes from the scancode buffer without removing them.
+  This function is called to see if there are enough bytes of scancode
+  representing a single key.
+
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
+  @param Count     Number of bytes to be read
+  @param Buf       Store the results
+
+  @retval EFI_SUCCESS   success to scan the keyboard code
+  @retval EFI_NOT_READY invalid parameter
+**/
+EFI_STATUS
+GetScancodeBufHead (
+  IN  SCAN_CODE_QUEUE        *Queue,
+  IN  UINTN                  Count,
+  OUT UINT8                  *Buf
+  )
+{
+  UINTN                      Index;
+  UINTN                      Pos;
+
+  //
+  // check the valid range of parameter 'Count'
+  //
+  if (GetScancodeBufCount (Queue) < Count) {
+    return EFI_NOT_READY;
+  }
+  //
+  // retrieve the values
+  //
+  for (Index = 0, Pos = Queue->Head; Index < Count; Index++, Pos = (Pos + 1) % 
KEYBOARD_SCAN_CODE_MAX_COUNT) {
+    Buf[Index] = Queue->Buffer[Pos];
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+
+  Read & remove several bytes from the scancode buffer.
+  This function is usually called after GetScancodeBufHead()
+
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
+  @param Count     Number of bytes to be read
+  @param Buf       Store the results
+
+  @retval EFI_SUCCESS success to scan the keyboard code
+  @retval EFI_NOT_READY invalid parameter
+**/
+EFI_STATUS
+PopScancodeBufHead (
+  IN  SCAN_CODE_QUEUE       *Queue,
+  IN  UINTN                 Count,
+  OUT UINT8                 *Buf OPTIONAL
+  )
+{
+  UINTN                     Index;
+
+  //
+  // Check the valid range of parameter 'Count'
+  //
+  if (GetScancodeBufCount (Queue) < Count) {
+    return EFI_NOT_READY;
+  }
+  //
+  // Retrieve and remove the values
+  //
+  for (Index = 0; Index < Count; Index++, Queue->Head = (Queue->Head + 1) % 
KEYBOARD_SCAN_CODE_MAX_COUNT) {
+    if (Buf != NULL) {
+      Buf[Index] = Queue->Buffer[Queue->Head];
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Push one byte to the scancode buffer.
+
+  @param Queue     Pointer to instance of SCAN_CODE_QUEUE.
+  @param Scancode  The byte to push.
+**/
+VOID
+PushScancodeBufTail (
+  IN  SCAN_CODE_QUEUE       *Queue,
+  IN  UINT8                 Scancode
+  )
+{
+  if (GetScancodeBufCount (Queue) == KEYBOARD_SCAN_CODE_MAX_COUNT - 1) {
+    PopScancodeBufHead (Queue, 1, NULL);
+  }
+
+  Queue->Buffer[Queue->Tail] = Scancode;
+  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_SCAN_CODE_MAX_COUNT;
+}
+
+/**
+  Read data register .
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @return return the value
+
+**/
+UINT8
+KeyReadDataRegister (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+
+{
+  return IoRead8 (ConsoleIn->DataRegisterAddress);
+}
+
+/**
+  Write data register.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      value wanted to be written
+
+**/
+VOID
+KeyWriteDataRegister (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN UINT8                   Data
+  )
+{
+  IoWrite8 (ConsoleIn->DataRegisterAddress, Data);
+}
+
+/**
+  Read status register.
+
+  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @return value in status register
+
+**/
+UINT8
+KeyReadStatusRegister (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+{
+  return IoRead8 (ConsoleIn->StatusRegisterAddress);
+}
+
+/**
+  Write command register .
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      The value wanted to be written
+
+**/
+VOID
+KeyWriteCommandRegister (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN UINT8                   Data
+  )
+{
+  IoWrite8 (ConsoleIn->CommandRegisterAddress, Data);
+}
+
+/**
+  Display error message.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param ErrMsg    Unicode string of error message
+
+**/
+VOID
+KeyboardError (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN CHAR16                  *ErrMsg
+  )
+{
+  ConsoleIn->KeyboardErr = TRUE;
+}
+
+/**
+  Timer event handler: read a series of scancodes from 8042
+  and put them into memory scancode buffer.
+  it read as much scancodes to either fill
+  the memory buffer or empty the keyboard buffer.
+  It is registered as running under TPL_NOTIFY
+
+  @param Event       The timer event
+  @param Context     A KEYBOARD_CONSOLE_IN_DEV pointer
+
+**/
+VOID
+EFIAPI
+KeyboardTimerHandler (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  )
+
+{
+  UINT8                   Data;
+  EFI_TPL                 OldTpl;
+  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
+
+  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  if (((KEYBOARD_CONSOLE_IN_DEV *) Context)->KeyboardErr) {
+    //
+    // Leave critical section and return
+    //
+    gBS->RestoreTPL (OldTpl);
+    return ;
+  }
+
+  //
+  // To let KB driver support Hot plug, here should skip the 'resend' command  
for the case that
+  // KB is not connected to system. If KB is not connected to system, driver 
will find there's something
+  // error in the following code and wait for the input buffer empty, this 
waiting time shoulb be short enough since
+  // this is a NOTIFY TPL period function, or the system performance will 
degrade hardly when KB is not connected.
+  // Just skip the 'resend' process simply.
+  //
+
+  while ((KeyReadStatusRegister (ConsoleIn) & 
(KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT|KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA))
 ==
+      KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA
+     ) {
+    //
+    // Read one byte of the scan code and store it into the memory buffer
+    //
+    Data = KeyReadDataRegister (ConsoleIn);
+    PushScancodeBufTail (&ConsoleIn->ScancodeQueue, Data);
+  }
+  KeyGetchar (ConsoleIn);
+
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+}
+
+/**
+  Read key value .
+
+  @param ConsoleIn - Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      - Pointer to outof buffer for keeping key value
+
+  @retval EFI_TIMEOUT Status resigter time out
+  @retval EFI_SUCCESS Success to read keyboard
+
+**/
+EFI_STATUS
+KeyboardRead (
+  IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
+  OUT UINT8                   *Data
+  )
+
+{
+  UINT32  TimeOut;
+  UINT32  RegFilled;
+
+  TimeOut   = 0;
+  RegFilled = 0;
+
+  //
+  // wait till output buffer full then perform the read
+  //
+  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+    if (KeyReadStatusRegister (ConsoleIn) & 
KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
+      RegFilled = 1;
+      *Data     = KeyReadDataRegister (ConsoleIn);
+      break;
+    }
+
+    MicroSecondDelay (30);
+  }
+
+  if (RegFilled == 0) {
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  write key to keyboard
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      value wanted to be written
+
+  @retval EFI_TIMEOUT   The input buffer register is full for putting new 
value util timeout
+  @retval EFI_SUCCESS   The new value is sucess put into input buffer register.
+
+**/
+EFI_STATUS
+KeyboardWrite (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN UINT8                   Data
+  )
+{
+  UINT32  TimeOut;
+  UINT32  RegEmptied;
+
+  TimeOut     = 0;
+  RegEmptied  = 0;
+
+  //
+  // wait for input buffer empty
+  //
+  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
+      RegEmptied = 1;
+      break;
+    }
+
+    MicroSecondDelay (30);
+  }
+
+  if (RegEmptied == 0) {
+    return EFI_TIMEOUT;
+  }
+  //
+  // Write it
+  //
+  KeyWriteDataRegister (ConsoleIn, Data);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Issue keyboard command.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      The buff holding the command
+
+  @retval EFI_TIMEOUT Keyboard is not ready to issuing
+  @retval EFI_SUCCESS Success to issue keyboard command
+
+**/
+EFI_STATUS
+KeyboardCommand (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN UINT8                   Data
+  )
+{
+  UINT32  TimeOut;
+  UINT32  RegEmptied;
+
+  TimeOut     = 0;
+  RegEmptied  = 0;
+
+  //
+  // Wait For Input Buffer Empty
+  //
+  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
+      RegEmptied = 1;
+      break;
+    }
+
+    MicroSecondDelay (30);
+  }
+
+  if (RegEmptied == 0) {
+    return EFI_TIMEOUT;
+  }
+  //
+  // issue the command
+  //
+  KeyWriteCommandRegister (ConsoleIn, Data);
+
+  //
+  // Wait For Input Buffer Empty again
+  //
+  RegEmptied = 0;
+  for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+    if ((KeyReadStatusRegister (ConsoleIn) & 0x02) == 0) {
+      RegEmptied = 1;
+      break;
+    }
+
+    MicroSecondDelay (30);
+  }
+
+  if (RegEmptied == 0) {
+    return EFI_TIMEOUT;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  wait for a specific value to be presented on
+  8042 Data register by keyboard and then read it,
+  used in keyboard commands ack
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Value     the value wanted to be waited.
+
+  @retval EFI_TIMEOUT Fail to get specific value in given time
+  @retval EFI_SUCCESS Success to get specific value in given time.
+
+**/
+EFI_STATUS
+KeyboardWaitForValue (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN UINT8                   Value
+  )
+{
+  UINT8   Data;
+  UINT32  TimeOut;
+  UINT32  SumTimeOut;
+  UINT32  GotIt;
+
+  GotIt       = 0;
+  TimeOut     = 0;
+  SumTimeOut  = 0;
+
+  //
+  // Make sure the initial value of 'Data' is different from 'Value'
+  //
+  Data = 0;
+  if (Data == Value) {
+    Data = 1;
+  }
+  //
+  // Read from 8042 (multiple times if needed)
+  // until the expected value appears
+  // use SumTimeOut to control the iteration
+  //
+  while (1) {
+    //
+    // Perform a read
+    //
+    for (TimeOut = 0; TimeOut < KEYBOARD_TIMEOUT; TimeOut += 30) {
+      if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
+        Data = KeyReadDataRegister (ConsoleIn);
+        break;
+      }
+
+      MicroSecondDelay (30);
+    }
+
+    SumTimeOut += TimeOut;
+
+    if (Data == Value) {
+      GotIt = 1;
+      break;
+    }
+
+    if (SumTimeOut >= mWaitForValueTimeOut) {
+      break;
+    }
+  }
+  //
+  // Check results
+  //
+  if (GotIt == 1) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_TIMEOUT;
+  }
+
+}
+
+/**
+  Show keyboard status lights according to
+  indicators in ConsoleIn.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @return status of updating keyboard register
+
+**/
+EFI_STATUS
+UpdateStatusLights (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+{
+  EFI_STATUS  Status;
+  UINT8       Command;
+
+  //
+  // Send keyboard command
+  //
+  Status = KeyboardWrite (ConsoleIn, 0xed);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  KeyboardWaitForValue (ConsoleIn, 0xfa);
+
+  //
+  // Light configuration
+  //
+  Command = 0;
+  if (ConsoleIn->CapsLock) {
+    Command |= 4;
+  }
+
+  if (ConsoleIn->NumLock) {
+    Command |= 2;
+  }
+
+  if (ConsoleIn->ScrollLock) {
+    Command |= 1;
+  }
+
+  Status = KeyboardWrite (ConsoleIn, Command);
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  KeyboardWaitForValue (ConsoleIn, 0xfa);
+  return Status;
+}
+
+/**
+  Get scancode from scancode buffer and translate into EFI-scancode and 
unicode defined by EFI spec.
+
+  The function is always called in TPL_NOTIFY.
+
+  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
+
+**/
+VOID
+KeyGetchar (
+  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+{
+  EFI_STATUS                     Status;
+  UINT16                         ScanCode;
+  BOOLEAN                        Extend0;
+  BOOLEAN                        Extend1;
+  UINTN                          Index;
+  EFI_KEY_DATA                   KeyData;
+  LIST_ENTRY                     *Link;
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
+  //
+  // 3 bytes most
+  //
+  UINT8                          ScancodeArr[3];
+  UINT32                         ScancodeArrPos;
+
+  //
+  // Check if there are enough bytes of scancode representing a single key
+  // available in the buffer
+  //
+  while (TRUE) {
+    Extend0        = FALSE;
+    Extend1        = FALSE;
+    ScancodeArrPos = 0;
+    Status  = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 
1, ScancodeArr);
+    if (EFI_ERROR (Status)) {
+      return ;
+    }
+
+    if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED0) {
+      //
+      // E0 to look ahead 2 bytes
+      //
+      Extend0 = TRUE;
+      ScancodeArrPos = 1;
+      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 
ScancodeArrPos + 1, ScancodeArr);
+      if (EFI_ERROR (Status)) {
+        return ;
+      }
+    } else if (ScancodeArr[ScancodeArrPos] == SCANCODE_EXTENDED1) {
+      //
+      // E1 to look ahead 3 bytes
+      //
+      Extend1 = TRUE;
+      ScancodeArrPos = 2;
+      Status         = GetScancodeBufHead (&ConsoleIn->ScancodeQueue, 
ScancodeArrPos + 1, ScancodeArr);
+      if (EFI_ERROR (Status)) {
+        return ;
+      }
+    }
+    //
+    // if we reach this position, scancodes for a key is in buffer now,pop them
+    //
+    Status = PopScancodeBufHead (&ConsoleIn->ScancodeQueue, ScancodeArrPos + 
1, ScancodeArr);
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // store the last available byte, this byte of scancode will be checked
+    //
+    ScanCode = ScancodeArr[ScancodeArrPos];
+
+    if (!Extend1) {
+      //
+      // Check for special keys and update the driver state.
+      //
+      switch (ScanCode) {
+
+      case SCANCODE_CTRL_MAKE:
+        if (Extend0) {
+          ConsoleIn->RightCtrl = TRUE;
+        } else {
+          ConsoleIn->LeftCtrl  = TRUE;
+        }
+        break;
+      case SCANCODE_CTRL_BREAK:
+        if (Extend0) {
+          ConsoleIn->RightCtrl = FALSE;
+        } else {
+          ConsoleIn->LeftCtrl  = FALSE;
+        }
+        break;
+
+      case SCANCODE_ALT_MAKE:
+          if (Extend0) {
+            ConsoleIn->RightAlt = TRUE;
+          } else {
+            ConsoleIn->LeftAlt  = TRUE;
+          }
+        break;
+      case SCANCODE_ALT_BREAK:
+          if (Extend0) {
+            ConsoleIn->RightAlt = FALSE;
+          } else {
+            ConsoleIn->LeftAlt  = FALSE;
+          }
+        break;
+
+      case SCANCODE_LEFT_SHIFT_MAKE:
+        //
+        // To avoid recognize PRNT_SCRN key as a L_SHIFT key
+        // because PRNT_SCRN key generates E0 followed by L_SHIFT scan code.
+        // If it the second byte of the PRNT_ScRN skip it.
+        //
+        if (!Extend0) {
+          ConsoleIn->LeftShift  = TRUE;
+          break;
+        }
+        continue;
+
+      case SCANCODE_LEFT_SHIFT_BREAK:
+        if (!Extend0) {
+          ConsoleIn->LeftShift = FALSE;
+        }
+        break;
+
+      case SCANCODE_RIGHT_SHIFT_MAKE:
+        ConsoleIn->RightShift = TRUE;
+        break;
+      case SCANCODE_RIGHT_SHIFT_BREAK:
+        ConsoleIn->RightShift = FALSE;
+        break;
+
+      case SCANCODE_LEFT_LOGO_MAKE:
+        ConsoleIn->LeftLogo = TRUE;
+        break;
+      case SCANCODE_LEFT_LOGO_BREAK:
+        ConsoleIn->LeftLogo = FALSE;
+        break;
+
+      case SCANCODE_RIGHT_LOGO_MAKE:
+        ConsoleIn->RightLogo = TRUE;
+        break;
+      case SCANCODE_RIGHT_LOGO_BREAK:
+        ConsoleIn->RightLogo = FALSE;
+        break;
+
+      case SCANCODE_MENU_MAKE:
+        ConsoleIn->Menu = TRUE;
+        break;
+      case SCANCODE_MENU_BREAK:
+        ConsoleIn->Menu = FALSE;
+        break;
+
+      case SCANCODE_SYS_REQ_MAKE:
+        if (Extend0) {
+          ConsoleIn->SysReq = TRUE;
+        }
+        break;
+      case SCANCODE_SYS_REQ_BREAK:
+        if (Extend0) {
+          ConsoleIn->SysReq = FALSE;
+        }
+        break;
+
+      case SCANCODE_SYS_REQ_MAKE_WITH_ALT:
+        ConsoleIn->SysReq = TRUE;
+        break;
+      case SCANCODE_SYS_REQ_BREAK_WITH_ALT:
+        ConsoleIn->SysReq = FALSE;
+        break;
+
+      case SCANCODE_CAPS_LOCK_MAKE:
+        ConsoleIn->CapsLock = (BOOLEAN)!ConsoleIn->CapsLock;
+        UpdateStatusLights (ConsoleIn);
+        break;
+      case SCANCODE_NUM_LOCK_MAKE:
+        ConsoleIn->NumLock = (BOOLEAN)!ConsoleIn->NumLock;
+        UpdateStatusLights (ConsoleIn);
+        break;
+      case SCANCODE_SCROLL_LOCK_MAKE:
+        if (!Extend0) {
+          ConsoleIn->ScrollLock = (BOOLEAN)!ConsoleIn->ScrollLock;
+          UpdateStatusLights (ConsoleIn);
+        }
+        break;
+      }
+    }
+
+    //
+    // If this is above the valid range, ignore it
+    //
+    if (ScanCode >= SCANCODE_MAX_MAKE) {
+      continue;
+    } else {
+      break;
+    }
+  }
+
+  //
+  // Handle Ctrl+Alt+Del hotkey
+  //
+  if ((ConsoleIn->LeftCtrl || ConsoleIn->RightCtrl) &&
+      (ConsoleIn->LeftAlt  || ConsoleIn->RightAlt ) &&
+      ScanCode == SCANCODE_DELETE_MAKE
+     ) {
+    gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL);
+  }
+
+  //
+  // Save the Shift/Toggle state
+  //
+  KeyData.KeyState.KeyShiftState = (UINT32) (EFI_SHIFT_STATE_VALID
+                                 | (ConsoleIn->LeftCtrl   ? 
EFI_LEFT_CONTROL_PRESSED  : 0)
+                                 | (ConsoleIn->RightCtrl  ? 
EFI_RIGHT_CONTROL_PRESSED : 0)
+                                 | (ConsoleIn->LeftAlt    ? 
EFI_LEFT_ALT_PRESSED      : 0)
+                                 | (ConsoleIn->RightAlt   ? 
EFI_RIGHT_ALT_PRESSED     : 0)
+                                 | (ConsoleIn->LeftShift  ? 
EFI_LEFT_SHIFT_PRESSED    : 0)
+                                 | (ConsoleIn->RightShift ? 
EFI_RIGHT_SHIFT_PRESSED   : 0)
+                                 | (ConsoleIn->LeftLogo   ? 
EFI_LEFT_LOGO_PRESSED     : 0)
+                                 | (ConsoleIn->RightLogo  ? 
EFI_RIGHT_LOGO_PRESSED    : 0)
+                                 | (ConsoleIn->Menu       ? 
EFI_MENU_KEY_PRESSED      : 0)
+                                 | (ConsoleIn->SysReq     ? 
EFI_SYS_REQ_PRESSED       : 0)
+                                 );
+  KeyData.KeyState.KeyToggleState = (EFI_KEY_TOGGLE_STATE) 
(EFI_TOGGLE_STATE_VALID
+                                  | (ConsoleIn->CapsLock   ? 
EFI_CAPS_LOCK_ACTIVE :   0)
+                                  | (ConsoleIn->NumLock    ? 
EFI_NUM_LOCK_ACTIVE :    0)
+                                  | (ConsoleIn->ScrollLock ? 
EFI_SCROLL_LOCK_ACTIVE : 0)
+                                  | (ConsoleIn->IsSupportPartialKey ? 
EFI_KEY_STATE_EXPOSED : 0)
+                                  );
+
+  KeyData.Key.ScanCode            = SCAN_NULL;
+  KeyData.Key.UnicodeChar         = CHAR_NULL;
+
+  //
+  // Key Pad "/" shares the same scancode as that of "/" except Key Pad "/" 
has E0 prefix
+  //
+  if (Extend0 && ScanCode == 0x35) {
+    KeyData.Key.UnicodeChar = L'/';
+    KeyData.Key.ScanCode    = SCAN_NULL;
+
+  //
+  // PAUSE shares the same scancode as that of NUM except PAUSE has E1 prefix
+  //
+  } else if (Extend1 && ScanCode == SCANCODE_NUM_LOCK_MAKE) {
+    KeyData.Key.UnicodeChar = CHAR_NULL;
+    KeyData.Key.ScanCode    = SCAN_PAUSE;
+
+  //
+  // PAUSE shares the same scancode as that of SCROLL except PAUSE (CTRL 
pressed) has E0 prefix
+  //
+  } else if (Extend0 && ScanCode == SCANCODE_SCROLL_LOCK_MAKE) {
+    KeyData.Key.UnicodeChar = CHAR_NULL;
+    KeyData.Key.ScanCode    = SCAN_PAUSE;
+
+  //
+  // PRNT_SCRN shares the same scancode as that of Key Pad "*" except 
PRNT_SCRN has E0 prefix
+  //
+  } else if (Extend0 && ScanCode == SCANCODE_SYS_REQ_MAKE) {
+    KeyData.Key.UnicodeChar = CHAR_NULL;
+    KeyData.Key.ScanCode    = SCAN_NULL;
+
+  //
+  // Except the above special case, all others can be handled by convert table
+  //
+  } else {
+    for (Index = 0; ConvertKeyboardScanCodeToEfiKey[Index].ScanCode != 
TABLE_END; Index++) {
+      if (ScanCode == ConvertKeyboardScanCodeToEfiKey[Index].ScanCode) {
+        KeyData.Key.ScanCode    = 
ConvertKeyboardScanCodeToEfiKey[Index].EfiScanCode;
+        KeyData.Key.UnicodeChar = 
ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar;
+
+        if ((ConsoleIn->LeftShift || ConsoleIn->RightShift) &&
+            (ConvertKeyboardScanCodeToEfiKey[Index].UnicodeChar != 
ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar)) {
+          KeyData.Key.UnicodeChar = 
ConvertKeyboardScanCodeToEfiKey[Index].ShiftUnicodeChar;
+          //
+          // Need not return associated shift state if a class of printable 
characters that
+          // are normally adjusted by shift modifiers. e.g. Shift Key + 'f' 
key = 'F'
+          //
+          KeyData.KeyState.KeyShiftState &= ~(EFI_LEFT_SHIFT_PRESSED | 
EFI_RIGHT_SHIFT_PRESSED);
+        }
+        //
+        // alphabetic key is affected by CapsLock State
+        //
+        if (ConsoleIn->CapsLock) {
+          if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= 
L'z') {
+            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'a' 
+ L'A');
+          } else if (KeyData.Key.UnicodeChar >= L'A' && 
KeyData.Key.UnicodeChar <= L'Z') {
+            KeyData.Key.UnicodeChar = (UINT16) (KeyData.Key.UnicodeChar - L'A' 
+ L'a');
+          }
+        }
+        break;
+      }
+    }
+  }
+
+  //
+  // distinguish numeric key pad keys' 'up symbol' and 'down symbol'
+  //
+  if (ScanCode >= 0x47 && ScanCode <= 0x53) {
+    if (ConsoleIn->NumLock && !(ConsoleIn->LeftShift || ConsoleIn->RightShift) 
&& !Extend0) {
+      KeyData.Key.ScanCode = SCAN_NULL;
+    } else if (ScanCode != 0x4a && ScanCode != 0x4e) {
+      KeyData.Key.UnicodeChar = CHAR_NULL;
+    }
+  }
+
+  //
+  // If the key can not be converted then just return.
+  //
+  if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == 
CHAR_NULL) {
+    if (!ConsoleIn->IsSupportPartialKey) {
+      return ;
+    }
+  }
+
+  //
+  // Invoke notification functions if exist
+  //
+  for (Link = GetFirstNode (&ConsoleIn->NotifyList); !IsNull 
(&ConsoleIn->NotifyList, Link); Link = GetNextNode (&ConsoleIn->NotifyList, 
Link)) {
+    CurrentNotify = CR (
+                      Link,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
+      CurrentNotify->KeyNotificationFn (&KeyData);
+    }
+  }
+
+  PushEfikeyBufTail (&ConsoleIn->EfiKeyQueue, &KeyData);
+}
+
+/**
+  Perform 8042 controller and keyboard Initialization.
+  If ExtendedVerification is TRUE, do additional test for
+  the keyboard interface
+
+  @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
+  @param ExtendedVerification - indicates a thorough initialization
+
+  @retval EFI_DEVICE_ERROR Fail to init keyboard
+  @retval EFI_SUCCESS      Success to init keyboard
+**/
+EFI_STATUS
+InitKeyboard (
+  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN BOOLEAN                     ExtendedVerification
+  )
+{
+  EFI_STATUS              Status;
+  EFI_STATUS              Status1;
+  UINT8                   CommandByte;
+  EFI_PS2_POLICY_PROTOCOL *Ps2Policy;
+  UINT32                  TryTime;
+
+  Status                 = EFI_SUCCESS;
+  mEnableMouseInterface  = TRUE;
+  TryTime                = 0;
+
+  //
+  // Get Ps2 policy to set this
+  //
+  gBS->LocateProtocol (
+        &gEfiPs2PolicyProtocolGuid,
+        NULL,
+        (VOID **) &Ps2Policy
+        );
+
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER,
+    ConsoleIn->DevicePath
+    );
+
+  //
+  // Perform a read to cleanup the Status Register's
+  // output buffer full bits within MAX TRY times
+  //
+  if ((KeyReadStatusRegister (ConsoleIn) & 
KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
+    while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
+      Status = KeyboardRead (ConsoleIn, &CommandByte);
+      TryTime ++;
+    }
+    //
+    // Exceed the max try times. The device may be error.
+    //
+    if (TryTime == KEYBOARD_MAX_TRY) {
+      Status = EFI_DEVICE_ERROR;
+      goto Done;
+    }
+  }
+  //
+  // We should disable mouse interface during the initialization process
+  // since mouse device output could block keyboard device output in the
+  // 60H port of 8042 controller.
+  //
+  // So if we are not initializing 8042 controller for the
+  // first time, we have to remember the previous mouse interface
+  // enabling state
+  //
+  // Test the system flag in to determine whether this is the first
+  // time initialization
+  //
+  if ((KeyReadStatusRegister (ConsoleIn) & 
KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG) != 0) {
+    if (!PcdGetBool (PcdFastPS2Detection)) {
+      //
+      // 8042 controller is already setup (by myself or by mouse driver):
+      //   See whether mouse interface is already enabled
+      //   which determines whether we should enable it later
+      //
+      //
+      // Read the command byte of 8042 controller
+      //
+      Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_READ);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"\n\r");
+        goto Done;
+      }
+
+      Status = KeyboardRead (ConsoleIn, &CommandByte);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"\n\r");
+        goto Done;
+      }
+      //
+      // Test the mouse enabling bit
+      //
+      if ((CommandByte & 0x20) != 0) {
+        mEnableMouseInterface = FALSE;
+      } else {
+        mEnableMouseInterface = TRUE;
+      }
+    } else {
+      mEnableMouseInterface = FALSE;
+    }
+  } else {
+    //
+    // 8042 controller is not setup yet:
+    //   8042 controller selftest;
+    //   Don't enable mouse interface later.
+    //
+    //
+    // Disable keyboard and mouse interfaces
+    //
+    if (!PcdGetBool (PcdFastPS2Detection)) {
+      Status = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"\n\r");
+        goto Done;
+      }
+
+      Status = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"\n\r");
+        goto Done;
+      }
+
+      REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+        EFI_PROGRESS_CODE,
+        EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST,
+        ConsoleIn->DevicePath
+        );
+      //
+      // 8042 Controller Self Test
+      //
+      Status = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
+        goto Done;
+      }
+
+      Status = KeyboardWaitForValue (ConsoleIn, 0x55);
+      if (EFI_ERROR (Status)) {
+        KeyboardError (ConsoleIn, L"8042 controller self test failed!\n\r");
+        goto Done;
+      }
+    }
+    //
+    // Don't enable mouse interface later
+    //
+    mEnableMouseInterface = FALSE;
+
+  }
+
+  if (Ps2Policy != NULL) {
+    Ps2Policy->Ps2InitHardware (ConsoleIn->Handle);
+  }
+  //
+  // Write 8042 Command Byte, set System Flag
+  // While at the same time:
+  //  1. disable mouse interface,
+  //  2. enable kbd interface,
+  //  3. enable PC/XT kbd translation mode
+  //  4. enable mouse and kbd interrupts
+  //
+  //  ( Command Byte bits:
+  //  7: Reserved
+  //  6: PC/XT translation mode
+  //  5: Disable Auxiliary device interface
+  //  4: Disable keyboard interface
+  //  3: Reserved
+  //  2: System Flag
+  //  1: Enable Auxiliary device interrupt
+  //  0: Enable Keyboard interrupt )
+  //
+  Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_WRITE);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
+    goto Done;
+  }
+
+  Status = KeyboardWrite (ConsoleIn, 0x67);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
+    goto Done;
+  }
+
+  //
+  // Clear Memory Scancode Buffer
+  //
+  ConsoleIn->ScancodeQueue.Head = 0;
+  ConsoleIn->ScancodeQueue.Tail = 0;
+  ConsoleIn->EfiKeyQueue.Head   = 0;
+  ConsoleIn->EfiKeyQueue.Tail   = 0;
+
+  //
+  // Reset the status indicators
+  //
+  ConsoleIn->CapsLock   = FALSE;
+  ConsoleIn->NumLock    = FALSE;
+  ConsoleIn->ScrollLock = FALSE;
+  ConsoleIn->LeftCtrl   = FALSE;
+  ConsoleIn->RightCtrl  = FALSE;
+  ConsoleIn->LeftAlt    = FALSE;
+  ConsoleIn->RightAlt   = FALSE;
+  ConsoleIn->LeftShift  = FALSE;
+  ConsoleIn->RightShift = FALSE;
+  ConsoleIn->LeftLogo   = FALSE;
+  ConsoleIn->RightLogo  = FALSE;
+  ConsoleIn->Menu       = FALSE;
+  ConsoleIn->SysReq     = FALSE;
+
+  ConsoleIn->IsSupportPartialKey = FALSE;
+  //
+  // For reseting keyboard is not mandatory before booting OS and sometimes 
keyboard responses very slow,
+  // and to support KB hot plug, we need to let the InitKB succeed no matter 
whether there is a KB device connected
+  // to system. So we only do the real reseting for keyboard when user asks 
and there is a real KB connected t system,
+  // and normally during booting an OS, it's skipped.
+  //
+  if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) {
+    //
+    // Additional verifications for keyboard interface
+    //
+    //
+    // Keyboard Interface Test
+    //
+    Status = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
+      goto Done;
+    }
+
+    Status = KeyboardWaitForValue (ConsoleIn, 0x00);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (
+        ConsoleIn,
+        L"Some specific value not aquired from 8042 controller!\n\r"
+        );
+      goto Done;
+    }
+    //
+    // Keyboard reset with a BAT(Basic Assurance Test)
+    //
+    Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
+      goto Done;
+    }
+
+    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 
controller!\n\r");
+      goto Done;
+    }
+    //
+    // wait for BAT completion code
+    //
+    mWaitForValueTimeOut  = KEYBOARD_BAT_TIMEOUT;
+
+    Status                = KeyboardWaitForValue (ConsoleIn, 
KEYBOARD_8048_RETURN_8042_BAT_SUCCESS);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r");
+      goto Done;
+    }
+
+    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
+
+    //
+    // Set Keyboard to use Scan Code Set 2
+    //
+    Status = KeyboardWrite (ConsoleIn, 
KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
+      goto Done;
+    }
+
+    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 
controller!\n\r");
+      goto Done;
+    }
+
+    Status = KeyboardWrite (ConsoleIn, 0x02);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r");
+      goto Done;
+    }
+
+    Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
+    if (EFI_ERROR (Status)) {
+      KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 
controller!\n\r");
+      goto Done;
+    }
+
+  //
+  // Clear Keyboard Scancode Buffer
+  //
+  Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r");
+    goto Done;
+  }
+
+  Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 
controller!\n\r");
+    goto Done;
+  }
+  //
+  if (Ps2Policy != NULL) {
+    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == 
EFI_KEYBOARD_CAPSLOCK) {
+      ConsoleIn->CapsLock = TRUE;
+    }
+
+    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == 
EFI_KEYBOARD_NUMLOCK) {
+      ConsoleIn->NumLock = TRUE;
+    }
+
+    if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == 
EFI_KEYBOARD_SCROLLLOCK) {
+      ConsoleIn->ScrollLock = TRUE;
+    }
+  }
+  //
+  // Update Keyboard Lights
+  //
+  Status = UpdateStatusLights (ConsoleIn);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r");
+    goto Done;
+    }
+  }
+  //
+  // At last, we can now enable the mouse interface if appropriate
+  //
+Done:
+
+  if (mEnableMouseInterface) {
+    //
+    // Enable mouse interface
+    //
+    Status1 = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE);
+    if (EFI_ERROR (Status1)) {
+      KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r");
+      return EFI_DEVICE_ERROR;
+    }
+  }
+
+  if (!EFI_ERROR (Status)) {
+    return EFI_SUCCESS;
+  } else {
+    return EFI_DEVICE_ERROR;
+  }
+
+}
+
+/**
+  Disable the keyboard interface of the 8042 controller.
+
+  @param ConsoleIn   The device instance
+
+  @return status of issuing disable command
+
+**/
+EFI_STATUS
+DisableKeyboard (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Disable keyboard interface
+  //
+  Status = KeyboardCommand (ConsoleIn, 
KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
+  if (EFI_ERROR (Status)) {
+    KeyboardError (ConsoleIn, L"\n\r");
+    return EFI_DEVICE_ERROR;
+  }
+
+  return Status;
+}
+
+/**
+  Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard 
Command
+  If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't 
respond, the device
+  should not be in system.
+
+  @param[in]  ConsoleIn             Keyboard Private Data Structure
+
+  @retval     TRUE                  Keyboard in System.
+  @retval     FALSE                 Keyboard not in System.
+**/
+BOOLEAN
+EFIAPI
+CheckKeyboardConnect (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  )
+{
+  EFI_STATUS     Status;
+  UINTN          WaitForValueTimeOutBcakup;
+
+  //
+  // enable keyboard itself and wait for its ack
+  // If can't receive ack, Keyboard should not be connected.
+  //
+  if (!PcdGetBool (PcdFastPS2Detection)) {
+    Status = KeyboardWrite (
+               ConsoleIn,
+               KEYBOARD_KBEN
+               );
+
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+    //
+    // wait for 1s
+    //
+    WaitForValueTimeOutBcakup = mWaitForValueTimeOut;
+    mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT;
+    Status = KeyboardWaitForValue (
+               ConsoleIn,
+               KEYBOARD_CMDECHO_ACK
+               );
+    mWaitForValueTimeOut = WaitForValueTimeOutBcakup;
+
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+
+    return TRUE;
+  } else {
+    return TRUE;
+  }
+}
+
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
new file mode 100644
index 0000000..f6ccd95
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c
@@ -0,0 +1,683 @@
+/** @file
+  Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 
interfaces
+  provided by Ps2KbdCtrller.c.
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "Ps2Keyboard.h"
+
+/**
+  Check whether the EFI key buffer is empty.
+
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
+
+  @retval TRUE    The EFI key buffer is empty.
+  @retval FALSE   The EFI key buffer isn't empty.
+**/
+BOOLEAN
+IsEfikeyBufEmpty (
+  IN  EFI_KEY_QUEUE         *Queue
+  )
+{
+  return (BOOLEAN) (Queue->Head == Queue->Tail);
+}
+
+/**
+  Read & remove one key data from the EFI key buffer.
+
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
+  @param KeyData   Receive the key data.
+
+  @retval EFI_SUCCESS   The key data is popped successfully.
+  @retval EFI_NOT_READY There is no key data available.
+**/
+EFI_STATUS
+PopEfikeyBufHead (
+  IN  EFI_KEY_QUEUE         *Queue,
+  OUT EFI_KEY_DATA          *KeyData OPTIONAL
+  )
+{
+  if (IsEfikeyBufEmpty (Queue)) {
+    return EFI_NOT_READY;
+  }
+  //
+  // Retrieve and remove the values
+  //
+  if (KeyData != NULL) {
+    CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));
+  }
+  Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
+  return EFI_SUCCESS;
+}
+
+/**
+  Push one key data to the EFI key buffer.
+
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
+  @param KeyData   The key data to push.
+**/
+VOID
+PushEfikeyBufTail (
+  IN  EFI_KEY_QUEUE         *Queue,
+  IN  EFI_KEY_DATA          *KeyData
+  )
+{
+  if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {
+    //
+    // If Queue is full, pop the one from head.
+    //
+    PopEfikeyBufHead (Queue, NULL);
+  }
+  CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));
+  Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
+}
+
+/**
+  Judge whether is a registed key
+
+  @param RegsiteredData       A pointer to a buffer that is filled in with the 
keystroke
+                              state data for the key that was registered.
+  @param InputData            A pointer to a buffer that is filled in with the 
keystroke
+                              state data for the key that was pressed.
+
+  @retval TRUE                Key be pressed matches a registered key.
+  @retval FLASE               Match failed.
+
+**/
+BOOLEAN
+IsKeyRegistered (
+  IN EFI_KEY_DATA  *RegsiteredData,
+  IN EFI_KEY_DATA  *InputData
+  )
+
+{
+  ASSERT (RegsiteredData != NULL && InputData != NULL);
+
+  if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
+      (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
+    return FALSE;
+  }
+
+  //
+  // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means 
these state could be ignored.
+  //
+  if (RegsiteredData->KeyState.KeyShiftState != 0 &&
+      RegsiteredData->KeyState.KeyShiftState != 
InputData->KeyState.KeyShiftState) {
+    return FALSE;
+  }
+  if (RegsiteredData->KeyState.KeyToggleState != 0 &&
+      RegsiteredData->KeyState.KeyToggleState != 
InputData->KeyState.KeyToggleState) {
+    return FALSE;
+  }
+
+  return TRUE;
+
+}
+
+/**
+    Reads the next keystroke from the input device. The WaitForKey Event can
+    be used to test for existance of a keystroke via WaitForEvent () call.
+
+    @param ConsoleInDev          Ps2 Keyboard private structure
+    @param KeyData               A pointer to a buffer that is filled in with 
the keystroke
+                                 state data for the key that was pressed.
+
+
+    @retval EFI_SUCCESS             The keystroke information was returned.
+    @retval EFI_NOT_READY           There was no keystroke data availiable.
+    @retval EFI_DEVICE_ERROR        The keystroke information was not returned 
due to
+                                    hardware errors.
+    @retval EFI_INVALID_PARAMETER   KeyData is NULL.
+
+**/
+EFI_STATUS
+KeyboardReadKeyStrokeWorker (
+  IN  KEYBOARD_CONSOLE_IN_DEV           *ConsoleInDev,
+  OUT EFI_KEY_DATA                      *KeyData
+  )
+
+{
+  EFI_STATUS                            Status;
+  EFI_TPL                               OldTpl;
+
+  if (KeyData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  KeyboardTimerHandler (NULL, ConsoleInDev);
+
+  if (ConsoleInDev->KeyboardErr) {
+    Status = EFI_DEVICE_ERROR;
+  } else {
+    Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Perform 8042 controller and keyboard initialization which implement 
SIMPLE_TEXT_IN.Reset()
+
+  @param This                 Pointer to instance of 
EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+  @param ExtendedVerification Indicate that the driver may perform a more
+                              exhaustive verification operation of the device 
during
+                              reset, now this par is ignored in this driver
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardEfiReset (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  IN  BOOLEAN                         ExtendedVerification
+  )
+{
+  EFI_STATUS              Status;
+  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
+  EFI_TPL                 OldTpl;
+
+  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+  if (ConsoleIn->KeyboardErr) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
+    ConsoleIn->DevicePath
+    );
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  //
+  // Call InitKeyboard to initialize the keyboard
+  //
+  Status = InitKeyboard (ConsoleIn, ExtendedVerification);
+  if (EFI_ERROR (Status)) {
+    //
+    // Leave critical section and return
+    //
+    gBS->RestoreTPL (OldTpl);
+    return EFI_DEVICE_ERROR;
+  }
+
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  //
+  // Report the status If a stuck key was detected
+  //
+  if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,
+      ConsoleIn->DevicePath
+      );
+  }
+  //
+  // Report the status If keyboard is locked
+  //
+  if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,
+      ConsoleIn->DevicePath
+      );
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Retrieve key values for driver user which implement 
SIMPLE_TEXT_IN.ReadKeyStroke().
+
+  @param This    Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+  @param Key     The output buffer for key value
+
+  @retval EFI_SUCCESS success to read key stroke
+**/
+EFI_STATUS
+EFIAPI
+KeyboardReadKeyStroke (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  OUT EFI_INPUT_KEY                   *Key
+  )
+{
+  EFI_STATUS              Status;
+  KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
+  EFI_KEY_DATA            KeyData;
+
+  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+
+  //
+  // Considering if the partial keystroke is enabled, there maybe a partial
+  // keystroke in the queue, so here skip the partial keystroke and get the
+  // next key from the queue
+  //
+  while (1) {
+    //
+    // If there is no pending key, then return.
+    //
+    Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    //
+    // If it is partial keystroke, skip it.
+    //
+    if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == 
CHAR_NULL) {
+      continue;
+    }
+    //
+    // Translate the CTRL-Alpha characters to their corresponding control value
+    // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
+    //
+    if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | 
EFI_RIGHT_CONTROL_PRESSED)) != 0) {
+      if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {
+        KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 
1);
+      } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= 
L'Z') {
+        KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 
1);
+      }
+    }
+
+    CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Event notification function for SIMPLE_TEXT_IN.WaitForKey event
+  Signal the event if there is key available
+
+  @param Event    the event object
+  @param Context  waitting context
+
+**/
+VOID
+EFIAPI
+KeyboardWaitForKey (
+  IN  EFI_EVENT               Event,
+  IN  VOID                    *Context
+  )
+{
+  EFI_TPL                     OldTpl;
+  KEYBOARD_CONSOLE_IN_DEV     *ConsoleIn;
+  EFI_KEY_DATA                KeyData;
+
+  ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  KeyboardTimerHandler (NULL, ConsoleIn);
+
+  if (!ConsoleIn->KeyboardErr) {
+    //
+    // WaitforKey doesn't suppor the partial key.
+    // Considering if the partial keystroke is enabled, there maybe a partial
+    // keystroke in the queue, so here skip the partial keystroke and get the
+    // next key from the queue
+    //
+    while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {
+      CopyMem (
+        &KeyData,
+        &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),
+        sizeof (EFI_KEY_DATA)
+        );
+      if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == 
CHAR_NULL) {
+        PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);
+        continue;
+      }
+      //
+      // if there is pending value key, signal the event.
+      //
+      gBS->SignalEvent (Event);
+      break;
+    }
+  }
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+}
+
+/**
+  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx 
event
+  Signal the event if there is key available
+
+  @param Event    event object
+  @param Context  waiting context
+
+**/
+VOID
+EFIAPI
+KeyboardWaitForKeyEx (
+  IN  EFI_EVENT               Event,
+  IN  VOID                    *Context
+  )
+
+{
+  KeyboardWaitForKey (Event, Context);
+}
+
+/**
+  Reset the input device and optionaly run diagnostics
+
+  @param This                     Protocol instance pointer.
+  @param ExtendedVerification     Driver may perform diagnostics on reset.
+
+  @retval EFI_SUCCESS             The device was reset.
+  @retval EFI_DEVICE_ERROR        The device is not functioning properly and 
could
+                                  not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardEfiResetEx (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN BOOLEAN                            ExtendedVerification
+  )
+
+{
+  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
+
+  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+
+  return ConsoleInDev->ConIn.Reset (
+                               &ConsoleInDev->ConIn,
+                               ExtendedVerification
+                               );
+}
+
+/**
+    Reads the next keystroke from the input device. The WaitForKey Event can
+    be used to test for existance of a keystroke via WaitForEvent () call.
+
+
+    @param This         Protocol instance pointer.
+    @param KeyData      A pointer to a buffer that is filled in with the 
keystroke
+                        state data for the key that was pressed.
+
+    @retval EFI_SUCCESS           The keystroke information was returned.
+    @retval EFI_NOT_READY         There was no keystroke data availiable.
+    @retval EFI_DEVICE_ERROR      The keystroke information was not returned 
due to
+                                  hardware errors.
+    @retval EFI_INVALID_PARAMETER KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardReadKeyStrokeEx (
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+  OUT EFI_KEY_DATA                      *KeyData
+  )
+
+{
+  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
+
+  if (KeyData == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+  return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);
+}
+
+/**
+  Set certain state for the input device.
+
+  @param This               Protocol instance pointer.
+  @param KeyToggleState     A pointer to the EFI_KEY_TOGGLE_STATE to set the
+                            state for the input device.
+
+  @retval EFI_SUCCESS           The device state was set successfully.
+  @retval EFI_DEVICE_ERROR      The device is not functioning correctly and 
could
+                                not have the setting adjusted.
+  @retval EFI_UNSUPPORTED       The device does not have the ability to set 
its state.
+  @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardSetState (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
+  )
+
+{
+  EFI_STATUS                            Status;
+  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
+  EFI_TPL                               OldTpl;
+
+  if (KeyToggleState == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  if (ConsoleInDev->KeyboardErr) {
+    Status = EFI_DEVICE_ERROR;
+    goto Exit;
+  }
+
+  if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
+    Status = EFI_UNSUPPORTED;
+    goto Exit;
+  }
+
+  //
+  // Update the status light
+  //
+  ConsoleInDev->ScrollLock          = FALSE;
+  ConsoleInDev->NumLock             = FALSE;
+  ConsoleInDev->CapsLock            = FALSE;
+  ConsoleInDev->IsSupportPartialKey = FALSE;
+
+  if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
+    ConsoleInDev->ScrollLock = TRUE;
+  }
+  if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
+    ConsoleInDev->NumLock = TRUE;
+  }
+  if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
+    ConsoleInDev->CapsLock = TRUE;
+  }
+  if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
+    ConsoleInDev->IsSupportPartialKey = TRUE;
+  }
+
+  Status = UpdateStatusLights (ConsoleInDev);
+  if (EFI_ERROR (Status)) {
+    Status = EFI_DEVICE_ERROR;
+  }
+
+Exit:
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+
+  return Status;
+
+}
+
+/**
+    Register a notification function for a particular keystroke for the input 
device.
+
+    @param This                       Protocol instance pointer.
+    @param KeyData                    A pointer to a buffer that is filled in 
with the keystroke
+                                      information data for the key that was 
pressed.
+    @param KeyNotificationFunction    Points to the function to be called when 
the key
+                                      sequence is typed specified by KeyData.
+    @param NotifyHandle               Points to the unique handle assigned to 
the registered notification.
+
+    @retval EFI_SUCCESS               The notification function was registered 
successfully.
+    @retval EFI_OUT_OF_RESOURCES      Unable to allocate resources for 
necesssary data structures.
+    @retval EFI_INVALID_PARAMETER     KeyData or NotifyHandle or 
KeyNotificationFunction is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardRegisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_DATA                       *KeyData,
+  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
+  OUT VOID                              **NotifyHandle
+  )
+{
+  EFI_STATUS                            Status;
+  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
+  EFI_TPL                               OldTpl;
+  LIST_ENTRY                            *Link;
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *NewNotify;
+
+  if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == 
NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  //
+  // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already 
registered.
+  //
+  for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != 
&ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
+    CurrentNotify = CR (
+                      Link,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
+      if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
+        *NotifyHandle = CurrentNotify;
+        Status = EFI_SUCCESS;
+        goto Exit;
+      }
+    }
+  }
+
+  //
+  // Allocate resource to save the notification function
+  //
+  NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof 
(KEYBOARD_CONSOLE_IN_EX_NOTIFY));
+  if (NewNotify == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Exit;
+  }
+
+  NewNotify->Signature         = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
+  NewNotify->KeyNotificationFn = KeyNotificationFunction;
+  CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
+  InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
+
+  *NotifyHandle                = NewNotify;
+  Status                       = EFI_SUCCESS;
+
+Exit:
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+
+}
+
+/**
+    Remove a registered notification function from a particular keystroke.
+
+    @param This                       Protocol instance pointer.
+    @param NotificationHandle         The handle of the notification function 
being unregistered.
+
+
+    @retval EFI_SUCCESS               The notification function was 
unregistered successfully.
+    @retval EFI_INVALID_PARAMETER     The NotificationHandle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardUnregisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN VOID                               *NotificationHandle
+  )
+{
+  EFI_STATUS                            Status;
+  KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
+  EFI_TPL                               OldTpl;
+  LIST_ENTRY                            *Link;
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;
+
+  if (NotificationHandle == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
+
+  //
+  // Enter critical section
+  //
+  OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+  for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != 
&ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
+    CurrentNotify = CR (
+                      Link,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+                      NotifyEntry,
+                      KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                      );
+    if (CurrentNotify == NotificationHandle) {
+      //
+      // Remove the notification function from NotifyList and free resources
+      //
+      RemoveEntryList (&CurrentNotify->NotifyEntry);
+
+      gBS->FreePool (CurrentNotify);
+      Status = EFI_SUCCESS;
+      goto Exit;
+    }
+  }
+
+  //
+  // Can not find the specified Notification Handle
+  //
+  Status = EFI_INVALID_PARAMETER;
+Exit:
+  //
+  // Leave critical section and return
+  //
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
new file mode 100644
index 0000000..4384935
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
@@ -0,0 +1,647 @@
+/** @file
+
+  PS/2 Keyboard driver. Routines that interacts with callers,
+  conforming to EFI driver model
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Ps2Keyboard.h"
+
+//
+// Function prototypes
+//
+/**
+  Test controller is a keyboard Controller.
+
+  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
+  @param Controller           driver's controller
+  @param RemainingDevicePath  children device path
+
+  @retval EFI_UNSUPPORTED controller is not floppy disk
+  @retval EFI_SUCCESS     controller is floppy disk
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+/**
+  Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
+
+  @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
+  @param Controller   driver controller handle
+  @param RemainingDevicePath Children's device path
+
+  @retval whether success to create floppy control instance.
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  );
+
+/**
+  Stop this driver on ControllerHandle. Support stoping any child handles
+  created by this driver.
+
+  @param  This              Protocol instance pointer.
+  @param  ControllerHandle  Handle of device to stop driver on
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number 
of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle
+  @retval other             This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN  EFI_HANDLE                     Controller,
+  IN  UINTN                          NumberOfChildren,
+  IN  EFI_HANDLE                     *ChildHandleBuffer
+  );
+
+/**
+  Free the waiting key notify list.
+
+  @param ListHead  Pointer to list head
+
+  @retval EFI_INVALID_PARAMETER  ListHead is NULL
+  @retval EFI_SUCCESS            Sucess to free NotifyList
+**/
+EFI_STATUS
+KbdFreeNotifyList (
+  IN OUT LIST_ENTRY           *ListHead
+  );
+
+//
+// DriverBinding Protocol Instance
+//
+EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
+  KbdControllerDriverSupported,
+  KbdControllerDriverStart,
+  KbdControllerDriverStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+/**
+  Test controller is a keyboard Controller.
+
+  @param This                 Pointer of EFI_DRIVER_BINDING_PROTOCOL
+  @param Controller           driver's controller
+  @param RemainingDevicePath  children device path
+
+  @retval EFI_UNSUPPORTED controller is not floppy disk
+  @retval EFI_SUCCESS     controller is floppy disk
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                                 Status;
+  EFI_SIO_PROTOCOL                           *Sio;
+  EFI_DEVICE_PATH_PROTOCOL                   *DevicePath;
+  ACPI_HID_DEVICE_PATH                       *Acpi;
+
+  //
+  // Check whether the controller is keyboard.
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &DevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  do {
+    Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
+    DevicePath = NextDevicePathNode (DevicePath);
+  } while (!IsDevicePathEnd (DevicePath));
+
+  if (DevicePathType (Acpi) != ACPI_DEVICE_PATH ||
+      (DevicePathSubType (Acpi) != ACPI_DP && DevicePathSubType (Acpi) != 
ACPI_EXTENDED_DP)) {
+    return EFI_UNSUPPORTED;
+  }
+
+  if (Acpi->HID != EISA_PNP_ID (0x303) || Acpi->UID != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Open the IO Abstraction(s) needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiSioProtocolGuid,
+                  (VOID **) &Sio,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Close the I/O Abstraction(s) used to perform the supported test
+  //
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiSioProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  return Status;
+}
+
+/**
+  Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
+
+  @param This         Pointer of EFI_DRIVER_BINDING_PROTOCOL
+  @param Controller   driver controller handle
+  @param RemainingDevicePath Children's device path
+
+  @retval whether success to create floppy control instance.
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN EFI_HANDLE                     Controller,
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
+  )
+{
+  EFI_STATUS                                Status;
+  EFI_STATUS                                Status1;
+  EFI_SIO_PROTOCOL                          *Sio;
+  KEYBOARD_CONSOLE_IN_DEV                   *ConsoleIn;
+  UINT8                                     Data;
+  EFI_STATUS_CODE_VALUE                     StatusCode;
+  EFI_DEVICE_PATH_PROTOCOL                  *DevicePath;
+
+  StatusCode = 0;
+
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &DevicePath,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Report that the keyboard is being enabled
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
+    DevicePath
+    );
+
+  //
+  // Get the ISA I/O Protocol on Controller's handle
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiSioProtocolGuid,
+                  (VOID **) &Sio,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  //
+  // Allocate private data
+  //
+  ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
+  if (ConsoleIn == NULL) {
+    Status      = EFI_OUT_OF_RESOURCES;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+  //
+  // Setup the device instance
+  //
+  ConsoleIn->Signature              = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
+  ConsoleIn->Handle                 = Controller;
+  (ConsoleIn->ConIn).Reset          = KeyboardEfiReset;
+  (ConsoleIn->ConIn).ReadKeyStroke  = KeyboardReadKeyStroke;
+  ConsoleIn->DataRegisterAddress    = KEYBOARD_8042_DATA_REGISTER;
+  ConsoleIn->StatusRegisterAddress  = KEYBOARD_8042_STATUS_REGISTER;
+  ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
+  ConsoleIn->DevicePath             = DevicePath;
+
+  ConsoleIn->ConInEx.Reset               = KeyboardEfiResetEx;
+  ConsoleIn->ConInEx.ReadKeyStrokeEx     = KeyboardReadKeyStrokeEx;
+  ConsoleIn->ConInEx.SetState            = KeyboardSetState;
+  ConsoleIn->ConInEx.RegisterKeyNotify   = KeyboardRegisterKeyNotify;
+  ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;
+
+  InitializeListHead (&ConsoleIn->NotifyList);
+
+  //
+  // Fix for random hangs in System waiting for the Key if no KBC is present 
in BIOS.
+  // When KBC decode (IO port 0x60/0x64 decode) is not enabled,
+  // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
+  // So instead we read status register to detect after read if KBC decode is 
enabled.
+  //
+
+  //
+  // Return code is ignored on purpose.
+  //
+  if (!PcdGetBool (PcdFastPS2Detection)) {
+    KeyboardRead (ConsoleIn, &Data);
+    if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == 
(KBC_PARE | KBC_TIM)) {
+      //
+      // If nobody decodes KBC I/O port, it will read back as 0xFF.
+      // Check the Time-Out and Parity bit to see if it has an active KBC in 
system
+      //
+      Status      = EFI_DEVICE_ERROR;
+      StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
+      goto ErrorExit;
+    }
+  }
+
+  //
+  // Setup the WaitForKey event
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_WAIT,
+                  TPL_NOTIFY,
+                  KeyboardWaitForKey,
+                  ConsoleIn,
+                  &((ConsoleIn->ConIn).WaitForKey)
+                  );
+  if (EFI_ERROR (Status)) {
+    Status      = EFI_OUT_OF_RESOURCES;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+  //
+  // Setup the WaitForKeyEx event
+  //
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_WAIT,
+                  TPL_NOTIFY,
+                  KeyboardWaitForKeyEx,
+                  ConsoleIn,
+                  &(ConsoleIn->ConInEx.WaitForKeyEx)
+                  );
+  if (EFI_ERROR (Status)) {
+    Status      = EFI_OUT_OF_RESOURCES;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+  // Setup a periodic timer, used for reading keystrokes at a fixed interval
+  //
+  Status = gBS->CreateEvent (
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                  TPL_NOTIFY,
+                  KeyboardTimerHandler,
+                  ConsoleIn,
+                  &ConsoleIn->TimerEvent
+                  );
+  if (EFI_ERROR (Status)) {
+    Status      = EFI_OUT_OF_RESOURCES;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+
+  Status = gBS->SetTimer (
+                  ConsoleIn->TimerEvent,
+                  TimerPeriodic,
+                  KEYBOARD_TIMER_INTERVAL
+                  );
+  if (EFI_ERROR (Status)) {
+    Status      = EFI_OUT_OF_RESOURCES;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
+    DevicePath
+    );
+
+  //
+  // Reset the keyboard device
+  //
+  Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet 
(PcdPs2KbdExtendedVerification));
+  if (EFI_ERROR (Status)) {
+    Status      = EFI_DEVICE_ERROR;
+    StatusCode  = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
+    goto ErrorExit;
+  }
+
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
+    DevicePath
+    );
+
+  ConsoleIn->ControllerNameTable = NULL;
+  AddUnicodeString2 (
+    "eng",
+    gPs2KeyboardComponentName.SupportedLanguages,
+    &ConsoleIn->ControllerNameTable,
+    L"PS/2 Keyboard Device",
+    TRUE
+    );
+  AddUnicodeString2 (
+    "en",
+    gPs2KeyboardComponentName2.SupportedLanguages,
+    &ConsoleIn->ControllerNameTable,
+    L"PS/2 Keyboard Device",
+    FALSE
+    );
+
+
+  //
+  // Install protocol interfaces for the keyboard device.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Controller,
+                  &gEfiSimpleTextInProtocolGuid,
+                  &ConsoleIn->ConIn,
+                  &gEfiSimpleTextInputExProtocolGuid,
+                  &ConsoleIn->ConInEx,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
+    goto ErrorExit;
+  }
+
+  return Status;
+
+ErrorExit:
+  //
+  // Report error code
+  //
+  if (StatusCode != 0) {
+    REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,
+      StatusCode,
+      DevicePath
+      );
+  }
+
+  if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
+    gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
+  }
+
+  if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
+    gBS->CloseEvent (ConsoleIn->TimerEvent);
+  }
+  if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
+    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
+  }
+  KbdFreeNotifyList (&ConsoleIn->NotifyList);
+  if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
+    FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
+  }
+  //
+  // Since there will be no timer handler for keyboard input any more,
+  // exhaust input data just in case there is still keyboard data left
+  //
+  if (ConsoleIn != NULL) {
+    Status1 = EFI_SUCCESS;
+    while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
+      Status1 = KeyboardRead (ConsoleIn, &Data);;
+    }
+  }
+
+  if (ConsoleIn != NULL) {
+    gBS->FreePool (ConsoleIn);
+  }
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiSioProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  return Status;
+}
+
+/**
+  Stop this driver on ControllerHandle. Support stoping any child handles
+  created by this driver.
+
+  @param  This              Protocol instance pointer.
+  @param  ControllerHandle  Handle of device to stop driver on
+  @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number 
of
+                            children is zero stop the entire bus driver.
+  @param  ChildHandleBuffer List of Child Handles to Stop.
+
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle
+  @retval other             This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+KbdControllerDriverStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
+  IN  EFI_HANDLE                     Controller,
+  IN  UINTN                          NumberOfChildren,
+  IN  EFI_HANDLE                     *ChildHandleBuffer
+  )
+{
+  EFI_STATUS                     Status;
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+  KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
+  UINT8                          Data;
+
+  //
+  // Disable Keyboard
+  //
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiSimpleTextInProtocolGuid,
+                  (VOID **) &ConIn,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  Status = gBS->OpenProtocol (
+                  Controller,
+                  &gEfiSimpleTextInputExProtocolGuid,
+                  NULL,
+                  This->DriverBindingHandle,
+                  Controller,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
+
+  //
+  // Report that the keyboard is being disabled
+  //
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (
+    EFI_PROGRESS_CODE,
+    EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
+    ConsoleIn->DevicePath
+    );
+
+  if (ConsoleIn->TimerEvent != NULL) {
+    gBS->CloseEvent (ConsoleIn->TimerEvent);
+    ConsoleIn->TimerEvent = NULL;
+  }
+
+  //
+  // Since there will be no timer handler for keyboard input any more,
+  // exhaust input data just in case there is still keyboard data left
+  //
+  Status = EFI_SUCCESS;
+  while (!EFI_ERROR (Status)) {
+    Status = KeyboardRead (ConsoleIn, &Data);;
+  }
+  //
+  // Uninstall the SimpleTextIn and SimpleTextInEx protocols
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Controller,
+                  &gEfiSimpleTextInProtocolGuid,
+                  &ConsoleIn->ConIn,
+                  &gEfiSimpleTextInputExProtocolGuid,
+                  &ConsoleIn->ConInEx,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  gBS->CloseProtocol (
+         Controller,
+         &gEfiSioProtocolGuid,
+         This->DriverBindingHandle,
+         Controller
+         );
+
+  //
+  // Free other resources
+  //
+  if ((ConsoleIn->ConIn).WaitForKey != NULL) {
+    gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
+    (ConsoleIn->ConIn).WaitForKey = NULL;
+  }
+  if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
+    gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
+    ConsoleIn->ConInEx.WaitForKeyEx = NULL;
+  }
+  KbdFreeNotifyList (&ConsoleIn->NotifyList);
+  FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
+  gBS->FreePool (ConsoleIn);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Free the waiting key notify list.
+
+  @param ListHead  Pointer to list head
+
+  @retval EFI_INVALID_PARAMETER  ListHead is NULL
+  @retval EFI_SUCCESS            Sucess to free NotifyList
+**/
+EFI_STATUS
+KbdFreeNotifyList (
+  IN OUT LIST_ENTRY           *ListHead
+  )
+{
+  KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
+
+  if (ListHead == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  while (!IsListEmpty (ListHead)) {
+    NotifyNode = CR (
+                   ListHead->ForwardLink,
+                   KEYBOARD_CONSOLE_IN_EX_NOTIFY,
+                   NotifyEntry,
+                   KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
+                   );
+    RemoveEntryList (ListHead->ForwardLink);
+    gBS->FreePool (NotifyNode);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  The module Entry Point for module Ps2Keyboard.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePs2Keyboard(
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+
+  //
+  // Install driver model protocol(s).
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gKeyboardControllerDriver,
+             ImageHandle,
+             &gPs2KeyboardComponentName,
+             &gPs2KeyboardComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+
+  return Status;
+}
+
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h
new file mode 100644
index 0000000..d0aecfb
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h
@@ -0,0 +1,551 @@
+/** @file
+  PS/2 keyboard driver header file
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD 
License
+which accompanies this distribution.  The full text of the license may be 
found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PS2KEYBOARD_H_
+#define _PS2KEYBOARD_H_
+
+#include <Uefi.h>
+
+#include <Protocol/SuperIo.h>
+#include <Protocol/SimpleTextIn.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/Ps2Policy.h>
+
+#include <Library/IoLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
+
+//
+// Global Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL   gKeyboardControllerDriver;
+extern EFI_COMPONENT_NAME_PROTOCOL   gPs2KeyboardComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gPs2KeyboardComponentName2;
+
+//
+// Driver Private Data
+//
+#define KEYBOARD_CONSOLE_IN_DEV_SIGNATURE       SIGNATURE_32 ('k', 'k', 'e', 
'y')
+#define KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('k', 'c', 'e', 
'n')
+
+typedef struct _KEYBOARD_CONSOLE_IN_EX_NOTIFY {
+  UINTN                               Signature;
+  EFI_KEY_DATA                        KeyData;
+  EFI_KEY_NOTIFY_FUNCTION             KeyNotificationFn;
+  LIST_ENTRY                          NotifyEntry;
+} KEYBOARD_CONSOLE_IN_EX_NOTIFY;
+
+#define KEYBOARD_SCAN_CODE_MAX_COUNT  32
+typedef struct {
+  UINT8                               Buffer[KEYBOARD_SCAN_CODE_MAX_COUNT];
+  UINTN                               Head;
+  UINTN                               Tail;
+} SCAN_CODE_QUEUE;
+
+#define KEYBOARD_EFI_KEY_MAX_COUNT    256
+typedef struct {
+  EFI_KEY_DATA                        Buffer[KEYBOARD_EFI_KEY_MAX_COUNT];
+  UINTN                               Head;
+  UINTN                               Tail;
+} EFI_KEY_QUEUE;
+
+typedef struct {
+  UINTN                               Signature;
+
+  EFI_HANDLE                          Handle;
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL      ConIn;
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL   ConInEx;
+
+  EFI_EVENT                           TimerEvent;
+
+  UINT32                              DataRegisterAddress;
+  UINT32                              StatusRegisterAddress;
+  UINT32                              CommandRegisterAddress;
+
+  BOOLEAN                             LeftCtrl;
+  BOOLEAN                             RightCtrl;
+  BOOLEAN                             LeftAlt;
+  BOOLEAN                             RightAlt;
+  BOOLEAN                             LeftShift;
+  BOOLEAN                             RightShift;
+  BOOLEAN                             LeftLogo;
+  BOOLEAN                             RightLogo;
+  BOOLEAN                             Menu;
+  BOOLEAN                             SysReq;
+
+  BOOLEAN                             CapsLock;
+  BOOLEAN                             NumLock;
+  BOOLEAN                             ScrollLock;
+
+  BOOLEAN                             IsSupportPartialKey;
+  //
+  // Queue storing key scancodes
+  //
+  SCAN_CODE_QUEUE                     ScancodeQueue;
+  EFI_KEY_QUEUE                       EfiKeyQueue;
+
+  //
+  // Error state
+  //
+  BOOLEAN                             KeyboardErr;
+
+  EFI_UNICODE_STRING_TABLE            *ControllerNameTable;
+
+  EFI_DEVICE_PATH_PROTOCOL            *DevicePath;
+  //
+  // Notification Function List
+  //
+  LIST_ENTRY                          NotifyList;
+} KEYBOARD_CONSOLE_IN_DEV;
+
+#define KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a)  CR (a, KEYBOARD_CONSOLE_IN_DEV, 
ConIn, KEYBOARD_CONSOLE_IN_DEV_SIGNATURE)
+#define TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS(a) \
+  CR (a, \
+      KEYBOARD_CONSOLE_IN_DEV, \
+      ConInEx, \
+      KEYBOARD_CONSOLE_IN_DEV_SIGNATURE \
+      )
+
+#define TABLE_END 0x0
+
+//
+// Driver entry point
+//
+/**
+  The user Entry Point for module Ps2Keyboard. The user code starts with this 
function.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InstallPs2KeyboardDriver (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  );
+
+#define KEYBOARD_8042_DATA_REGISTER     0x60
+#define KEYBOARD_8042_STATUS_REGISTER   0x64
+#define KEYBOARD_8042_COMMAND_REGISTER  0x64
+
+#define KEYBOARD_KBEN                   0xF4
+#define KEYBOARD_CMDECHO_ACK            0xFA
+
+#define KEYBOARD_MAX_TRY                256     // 256
+#define KEYBOARD_TIMEOUT                65536   // 0.07s
+#define KEYBOARD_WAITFORVALUE_TIMEOUT   1000000 // 1s
+#define KEYBOARD_BAT_TIMEOUT            4000000 // 4s
+#define KEYBOARD_TIMER_INTERVAL         200000  // 0.02s
+#define SCANCODE_EXTENDED0              0xE0
+#define SCANCODE_EXTENDED1              0xE1
+#define SCANCODE_CTRL_MAKE              0x1D
+#define SCANCODE_CTRL_BREAK             0x9D
+#define SCANCODE_ALT_MAKE               0x38
+#define SCANCODE_ALT_BREAK              0xB8
+#define SCANCODE_LEFT_SHIFT_MAKE        0x2A
+#define SCANCODE_LEFT_SHIFT_BREAK       0xAA
+#define SCANCODE_RIGHT_SHIFT_MAKE       0x36
+#define SCANCODE_RIGHT_SHIFT_BREAK      0xB6
+#define SCANCODE_CAPS_LOCK_MAKE         0x3A
+#define SCANCODE_NUM_LOCK_MAKE          0x45
+#define SCANCODE_SCROLL_LOCK_MAKE       0x46
+#define SCANCODE_DELETE_MAKE            0x53
+#define SCANCODE_LEFT_LOGO_MAKE         0x5B //GUI key defined in Keyboard 
scan code
+#define SCANCODE_LEFT_LOGO_BREAK        0xDB
+#define SCANCODE_RIGHT_LOGO_MAKE        0x5C
+#define SCANCODE_RIGHT_LOGO_BREAK       0xDC
+#define SCANCODE_MENU_MAKE              0x5D //APPS key defined in Keyboard 
scan code
+#define SCANCODE_MENU_BREAK             0xDD
+#define SCANCODE_SYS_REQ_MAKE           0x37
+#define SCANCODE_SYS_REQ_BREAK          0xB7
+#define SCANCODE_SYS_REQ_MAKE_WITH_ALT  0x54
+#define SCANCODE_SYS_REQ_BREAK_WITH_ALT 0xD4
+
+#define SCANCODE_MAX_MAKE               0x60
+
+
+#define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA     BIT0        ///< 0 - 
Output register has no data; 1 - Output register has data
+#define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA      BIT1        ///< 0 - 
Input register has no data;  1 - Input register has data
+#define KEYBOARD_STATUS_REGISTER_SYSTEM_FLAG         BIT2        ///< Set to 0 
after power on reset
+#define KEYBOARD_STATUS_REGISTER_INPUT_DATA_TYPE     BIT3        ///< 0 - Data 
in input register is data; 1 - Data in input register is command
+#define KEYBOARD_STATUS_REGISTER_ENABLE_FLAG         BIT4        ///< 0 - 
Keyboard is disable; 1 - Keyboard is enable
+#define KEYBOARD_STATUS_REGISTER_TRANSMIT_TIMEOUT    BIT5        ///< 0 - 
Transmit is complete without timeout; 1 - Transmit is timeout without complete
+#define KEYBOARD_STATUS_REGISTER_RECEIVE_TIMEOUT     BIT6        ///< 0 - 
Receive is complete without timeout; 1 - Receive is timeout without complete
+#define KEYBOARD_STATUS_REGISTER_PARITY              BIT7        ///< 0 - Odd 
parity; 1 - Even parity
+
+#define KEYBOARD_8042_COMMAND_READ                          0x20
+#define KEYBOARD_8042_COMMAND_WRITE                         0x60
+#define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE       0xA7
+#define KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE        0xA8
+#define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST          0xAA
+#define KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST  0xAB
+#define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE    0xAD
+
+#define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA             0xF4
+#define KEYBOARD_8048_COMMAND_RESET                         0xFF
+#define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET          0xF0
+
+#define KEYBOARD_8048_RETURN_8042_BAT_SUCCESS               0xAA
+#define KEYBOARD_8048_RETURN_8042_BAT_ERROR                 0xFC
+#define KEYBOARD_8048_RETURN_8042_ACK                       0xFA
+
+
+//
+// Keyboard Controller Status
+//
+#define KBC_PARE  0x80  // Parity Error
+#define KBC_TIM   0x40  // General Time Out
+
+//
+// Other functions that are used among .c files
+//
+/**
+  Show keyboard status lights according to
+  indicators in ConsoleIn.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @return status
+
+**/
+EFI_STATUS
+UpdateStatusLights (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  );
+
+/**
+  write key to keyboard.
+
+  @param ConsoleIn Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+  @param Data      value wanted to be written
+
+  @retval EFI_TIMEOUT - GC_TODO: Add description for return value
+  @retval EFI_SUCCESS - GC_TODO: Add description for return value
+
+**/
+EFI_STATUS
+KeyboardRead (
+  IN KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn,
+  OUT UINT8                   *Data
+  );
+
+/**
+  Get scancode from scancode buffer and translate into EFI-scancode and 
unicode defined by EFI spec.
+
+  The function is always called in TPL_NOTIFY.
+
+  @param ConsoleIn KEYBOARD_CONSOLE_IN_DEV instance pointer
+
+**/
+VOID
+KeyGetchar (
+  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  );
+
+/**
+  Perform 8042 controller and keyboard Initialization.
+  If ExtendedVerification is TRUE, do additional test for
+  the keyboard interface
+
+  @param ConsoleIn - KEYBOARD_CONSOLE_IN_DEV instance pointer
+  @param ExtendedVerification - indicates a thorough initialization
+
+  @retval EFI_DEVICE_ERROR Fail to init keyboard
+  @retval EFI_SUCCESS      Success to init keyboard
+**/
+EFI_STATUS
+InitKeyboard (
+  IN OUT KEYBOARD_CONSOLE_IN_DEV *ConsoleIn,
+  IN BOOLEAN                     ExtendedVerification
+  );
+
+/**
+  Disable the keyboard interface of the 8042 controller.
+
+  @param ConsoleIn   - the device instance
+
+  @return status of issuing disable command
+
+**/
+EFI_STATUS
+DisableKeyboard (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  );
+
+/**
+  Timer event handler: read a series of scancodes from 8042
+  and put them into memory scancode buffer.
+  it read as much scancodes to either fill
+  the memory buffer or empty the keyboard buffer.
+  It is registered as running under TPL_NOTIFY
+
+  @param Event - The timer event
+  @param Context - A KEYBOARD_CONSOLE_IN_DEV pointer
+
+**/
+VOID
+EFIAPI
+KeyboardTimerHandler (
+  IN EFI_EVENT    Event,
+  IN VOID         *Context
+  );
+
+/**
+  logic reset keyboard
+  Implement SIMPLE_TEXT_IN.Reset()
+  Perform 8042 controller and keyboard initialization
+
+  @param This    Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+  @param ExtendedVerification Indicate that the driver may perform a more
+                              exhaustive verification operation of the device 
during
+                              reset, now this par is ignored in this driver
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardEfiReset (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  IN  BOOLEAN                         ExtendedVerification
+  );
+
+/**
+  Implement SIMPLE_TEXT_IN.ReadKeyStroke().
+  Retrieve key values for driver user.
+
+  @param This    Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+  @param Key     The output buffer for key value
+
+  @retval EFI_SUCCESS success to read key stroke
+**/
+EFI_STATUS
+EFIAPI
+KeyboardReadKeyStroke (
+  IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
+  OUT EFI_INPUT_KEY                   *Key
+  );
+
+/**
+  Event notification function for SIMPLE_TEXT_IN.WaitForKey event
+  Signal the event if there is key available
+
+  @param Event    the event object
+  @param Context  waitting context
+
+**/
+VOID
+EFIAPI
+KeyboardWaitForKey (
+  IN  EFI_EVENT               Event,
+  IN  VOID                    *Context
+  );
+
+/**
+  Read status register.
+
+  @param ConsoleIn  Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @return value in status register
+
+**/
+UINT8
+KeyReadStatusRegister (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  );
+
+/**
+  Check whether there is Ps/2 Keyboard device in system by 0xF4 Keyboard 
Command
+  If Keyboard receives 0xF4, it will respond with 'ACK'. If it doesn't 
respond, the device
+  should not be in system.
+
+  @param[in]  ConsoleIn   Pointer to instance of KEYBOARD_CONSOLE_IN_DEV
+
+  @retval     TRUE                  Keyboard in System.
+  @retval     FALSE                 Keyboard not in System.
+**/
+BOOLEAN
+EFIAPI
+CheckKeyboardConnect (
+  IN KEYBOARD_CONSOLE_IN_DEV *ConsoleIn
+  );
+
+/**
+  Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx 
event
+  Signal the event if there is key available
+
+  @param Event    event object
+  @param Context  waiting context
+
+**/
+VOID
+EFIAPI
+KeyboardWaitForKeyEx (
+  IN  EFI_EVENT               Event,
+  IN  VOID                    *Context
+  );
+
+//
+// Simple Text Input Ex protocol function prototypes
+//
+
+/**
+  Reset the input device and optionaly run diagnostics
+
+  @param This                 - Protocol instance pointer.
+  @param ExtendedVerification - Driver may perform diagnostics on reset.
+
+  @retval EFI_SUCCESS           - The device was reset.
+  @retval EFI_DEVICE_ERROR      - The device is not functioning properly and 
could
+                                  not be reset.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardEfiResetEx (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN BOOLEAN                            ExtendedVerification
+  );
+
+/**
+    Reads the next keystroke from the input device. The WaitForKey Event can
+    be used to test for existance of a keystroke via WaitForEvent () call.
+
+
+    @param This       - Protocol instance pointer.
+    @param KeyData    - A pointer to a buffer that is filled in with the 
keystroke
+                 state data for the key that was pressed.
+
+    @retval EFI_SUCCESS           - The keystroke information was returned.
+    @retval EFI_NOT_READY         - There was no keystroke data availiable.
+    @retval EFI_DEVICE_ERROR      - The keystroke information was not returned 
due to
+                            hardware errors.
+    @retval EFI_INVALID_PARAMETER - KeyData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardReadKeyStrokeEx (
+  IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
+  OUT EFI_KEY_DATA                      *KeyData
+  );
+
+/**
+  Set certain state for the input device.
+
+  @param This              - Protocol instance pointer.
+  @param KeyToggleState    - A pointer to the EFI_KEY_TOGGLE_STATE to set the
+                        state for the input device.
+
+  @retval EFI_SUCCESS           - The device state was set successfully.
+  @retval EFI_DEVICE_ERROR      - The device is not functioning correctly and 
could
+                            not have the setting adjusted.
+  @retval EFI_UNSUPPORTED       - The device does not have the ability to set 
its state.
+  @retval EFI_INVALID_PARAMETER - KeyToggleState is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardSetState (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
+  );
+
+/**
+    Register a notification function for a particular keystroke for the input 
device.
+
+    @param This                    - Protocol instance pointer.
+    @param KeyData                 - A pointer to a buffer that is filled in 
with the keystroke
+                              information data for the key that was pressed.
+    @param KeyNotificationFunction - Points to the function to be called when 
the key
+                              sequence is typed specified by KeyData.
+    @param NotifyHandle            - Points to the unique handle assigned to 
the registered notification.
+
+    @retval EFI_SUCCESS             - The notification function was registered 
successfully.
+    @retval EFI_OUT_OF_RESOURCES    - Unable to allocate resources for 
necesssary data structures.
+    @retval EFI_INVALID_PARAMETER   - KeyData or NotifyHandle is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardRegisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN EFI_KEY_DATA                       *KeyData,
+  IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
+  OUT VOID                              **NotifyHandle
+  );
+
+/**
+    Remove a registered notification function from a particular keystroke.
+
+    @param This                    - Protocol instance pointer.
+    @param NotificationHandle      - The handle of the notification function 
being unregistered.
+
+
+    @retval EFI_SUCCESS             - The notification function was 
unregistered successfully.
+    @retval EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.
+    @retval EFI_NOT_FOUND           - Can not find the matching entry in 
database.
+
+**/
+EFI_STATUS
+EFIAPI
+KeyboardUnregisterKeyNotify (
+  IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
+  IN VOID                               *NotificationHandle
+  );
+
+/**
+  Push one key data to the EFI key buffer.
+
+  @param Queue     Pointer to instance of EFI_KEY_QUEUE.
+  @param KeyData   The key data to push.
+**/
+VOID
+PushEfikeyBufTail (
+  IN  EFI_KEY_QUEUE         *Queue,
+  IN  EFI_KEY_DATA          *KeyData
+  );
+
+/**
+  Judge whether is a registed key
+
+  @param RegsiteredData       A pointer to a buffer that is filled in with the 
keystroke
+                              state data for the key that was registered.
+  @param InputData            A pointer to a buffer that is filled in with the 
keystroke
+                              state data for the key that was pressed.
+
+  @retval TRUE                Key be pressed matches a registered key.
+  @retval FLASE               Match failed.
+
+**/
+BOOLEAN
+IsKeyRegistered (
+  IN EFI_KEY_DATA  *RegsiteredData,
+  IN EFI_KEY_DATA  *InputData
+  );
+
+#endif
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
new file mode 100644
index 0000000..81a31e0
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
@@ -0,0 +1,84 @@
+## @file
+# Ps2 Keyboard Driver.
+#
+# Ps2 Keyboard Driver for UEFI. The keyboard type implemented follows IBM
+# compatible PS2 protocol using Scan Code Set 1.
+#
+# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD 
License
+# which accompanies this distribution.  The full text of the license may be 
found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = Ps2KeyboardDxe
+  MODULE_UNI_FILE                = Ps2KeyboardDxe.uni
+  FILE_GUID                      = 3DC82376-637B-40a6-A8FC-A565417F2C38
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializePs2Keyboard
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#  DRIVER_BINDING                = gKeyboardControllerDriver;
+#  COMPONENT_NAME                = gPs2KeyboardComponentName;
+#  COMPONENT_NAME2               = gPs2KeyboardComponentName2;
+#
+
+[Sources]
+  ComponentName.c
+  Ps2Keyboard.h
+  Ps2KbdCtrller.c
+  Ps2KbdTextIn.c
+  Ps2Keyboard.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  MemoryAllocationLib
+  UefiRuntimeServicesTableLib
+  DebugLib
+  ReportStatusCodeLib
+  UefiBootServicesTableLib
+  UefiLib
+  UefiDriverEntryPoint
+  BaseLib
+  BaseMemoryLib
+  TimerLib
+  PcdLib
+  IoLib
+
+[Protocols]
+  gEfiSimpleTextInProtocolGuid                  ## BY_START
+  gEfiSimpleTextInputExProtocolGuid             ## BY_START
+  gEfiPs2PolicyProtocolGuid                     ## SOMETIMES_CONSUMES
+  gEfiSioProtocolGuid                           ## TO_START
+  gEfiDevicePathProtocolGuid                    ## TO_START
+
+[FeaturePcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification   ## CONSUMES
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFastPS2Detection             ## 
SOMETIMES_CONSUMES
+
+#
+# [Event]
+#
+#   ##
+#   # Timer event used to read key strokes at a regular interval.
+#   #
+#   EVENT_TYPE_PERIODIC_TIMER   ## CONSUMES
+#
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  Ps2KeyboardDxeExtra.uni
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni
new file mode 100644
index 0000000..358cc63
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni
@@ -0,0 +1,23 @@
+// /** @file
+// Ps2 Keyboard Driver.
+//
+// Ps2 Keyboard Driver for UEFI. The keyboard type implemented follows IBM
+// compatible PS2 protocol using Scan Code Set 1.
+//
+// Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution.  The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Ps2 Keyboard Driver"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Ps2 Keyboard Driver 
for UEFI. The keyboard type implemented follows IBM compatible PS2 protocol 
using Scan Code Set 1."
+
diff --git a/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni 
b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni
new file mode 100644
index 0000000..7bca518
--- /dev/null
+++ b/MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// Ps2KeyboardDxe Localized Strings and Content
+//
+// Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD 
License
+// which accompanies this distribution.  The full text of the license may be 
found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR 
IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"PS2 Keyboard DXE Driver"
+
+
diff --git a/MdeModulePkg/Include/Protocol/Ps2Policy.h 
b/MdeModulePkg/Include/Protocol/Ps2Policy.h
new file mode 100644
index 0000000..14346ee
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/Ps2Policy.h
@@ -0,0 +1,41 @@
+/** @file
+  PS/2 policy protocol abstracts the specific platform initialization and 
settings.
+
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available 
under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _PS2_POLICY_PROTOCOL_H_
+#define _PS2_POLICY_PROTOCOL_H_
+
+#define EFI_PS2_POLICY_PROTOCOL_GUID \
+  { \
+    0x4df19259, 0xdc71, 0x4d46, {0xbe, 0xf1, 0x35, 0x7b, 0xb5, 0x78, 0xc4, 
0x18 } \
+  }
+
+#define EFI_KEYBOARD_CAPSLOCK   0x0004
+#define EFI_KEYBOARD_NUMLOCK    0x0002
+#define EFI_KEYBOARD_SCROLLLOCK 0x0001
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_PS2_INIT_HARDWARE) (
+  IN  EFI_HANDLE              Handle
+  );
+
+typedef struct {
+  UINT8                 KeyboardLight;
+  EFI_PS2_INIT_HARDWARE Ps2InitHardware;
+} EFI_PS2_POLICY_PROTOCOL;
+
+extern EFI_GUID gEfiPs2PolicyProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index aa9e806..0221651 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -709,6 +709,14 @@
   # @Prompt Enable S3 performance data support.
   
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwarePerformanceDataTableS3Support|TRUE|BOOLEAN|0x00010064
 
+  ## Indicates if PS2 keyboard does a extended verification during start.
+  #  Add this PCD mainly consider the use case of simulator. This PCD maybe 
set to FALSE for
+  #  Extended verification will take some performance. It can be set to FALSE 
for boot performance.<BR><BR>
+  #   TRUE  - Turn on PS2 keyboard extended verification.<BR>
+  #   FALSE - Turn off PS2 keyboard extended verification.<BR>
+  # @Prompt Turn on PS2 Keyboard Extended Verification
+  
gEfiMdeModulePkgTokenSpaceGuid.PcdPs2KbdExtendedVerification|TRUE|BOOLEAN|0x00010072
+
   ## Indicates if Serial device uses half hand shake.<BR><BR>
   #   TRUE  - Serial device uses half hand shake.<BR>
   #   FALSE - Serial device doesn't use half hand shake.<BR>
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index b1ece7b..f1d7a14 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -247,6 +247,7 @@
   MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf
   MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf
   MdeModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
+  MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
 
   MdeModulePkg/Core/Dxe/DxeMain.inf {
     <LibraryClasses>
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to