]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add Ps2KeyboardDxe driver.
authorRuiyu Ni <ruiyu.ni@intel.com>
Fri, 17 Jul 2015 09:39:00 +0000 (17:39 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Fri, 8 Apr 2016 09:45:54 +0000 (17:45 +0800)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/ComponentName.c [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdCtrller.c [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KbdTextIn.c [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.h [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.uni [new file with mode: 0644]
MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxeExtra.uni [new file with mode: 0644]
MdeModulePkg/Include/Protocol/Ps2Policy.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/MdeModulePkg.dsc

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