-/*++\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved. <BR>\r
-This software and associated documentation (if any) is furnished\r
-under a license and may only be used or copied in accordance\r
-with the terms of the license. Except as permitted by such\r
-license, no part of this software or documentation may be\r
-reproduced, stored in a retrieval system, or transmitted in any\r
-form or by any means without the express written consent of\r
-Intel Corporation.\r
-\r
-\r
-Module Name:\r
-\r
- Ps2Keyboard.c\r
-\r
-Abstract:\r
+/** @file\r
\r
PS/2 Keyboard driver. Routines that interacts with callers,\r
conforming to EFI driver model\r
\r
---*/\r
+Copyright (c) 2006 - 2018, 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
-//\r
-// Include common header file for this module.\r
-//\r
-#include "CommonHeader.h"\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_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_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
);\r
\r
+/**\r
+ Stop this driver on ControllerHandle. Support stopping 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_HANDLE *ChildHandleBuffer\r
);\r
\r
-//\r
-// Global variables\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
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_HANDLE Controller,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- ControllerDriver Protocol Method\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// GC_TODO: This - add argument and description to function comment\r
-// GC_TODO: Controller - add argument and description to function comment\r
-// GC_TODO: RemainingDevicePath - add argument and description to function comment\r
{\r
EFI_STATUS Status;\r
EFI_ISA_IO_PROTOCOL *IsaIo;\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_HANDLE Controller,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
-// GC_TODO: This - add argument and description to function comment\r
-// GC_TODO: Controller - add argument and description to function comment\r
-// GC_TODO: RemainingDevicePath - add argument and description to function comment\r
-// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
{\r
EFI_STATUS Status;\r
EFI_STATUS Status1;\r
ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;\r
ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;\r
ConsoleIn->IsaIo = IsaIo;\r
- ConsoleIn->ScancodeBufStartPos = 0;\r
- ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1;\r
- ConsoleIn->ScancodeBufCount = 0;\r
- ConsoleIn->Ctrled = FALSE;\r
- ConsoleIn->Alted = FALSE;\r
ConsoleIn->DevicePath = ParentDevicePath;\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
EVT_NOTIFY_WAIT,\r
TPL_NOTIFY,\r
KeyboardWaitForKey,\r
- &(ConsoleIn->ConIn),\r
+ ConsoleIn,\r
&((ConsoleIn->ConIn).WaitForKey)\r
);\r
if (EFI_ERROR (Status)) {\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
+\r
// Setup a periodic timer, used for reading keystrokes at a fixed interval\r
//\r
Status = gBS->CreateEvent (\r
goto ErrorExit;\r
}\r
\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ ConsoleIn,\r
+ &ConsoleIn->KeyNotifyProcessEvent\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
//\r
// Reset the keyboard device\r
//\r
- Status = ConsoleIn->ConIn.Reset (&ConsoleIn->ConIn, TRUE);\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
+ ParentDevicePath\r
+ );\r
+\r
ConsoleIn->ControllerNameTable = NULL;\r
- AddUnicodeString (\r
+ AddUnicodeString2 (\r
"eng",\r
gPs2KeyboardComponentName.SupportedLanguages,\r
&ConsoleIn->ControllerNameTable,\r
- L"PS/2 Keyboard Device"\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
&Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
&ConsoleIn->ConIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &ConsoleIn->ConInEx,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {\r
gBS->CloseEvent (ConsoleIn->TimerEvent);\r
}\r
-\r
+ if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {\r
+ gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
+ }\r
+ if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {\r
+ gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+ }\r
+ KbdFreeNotifyList (&ConsoleIn->NotifyList);\r
if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {\r
FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);\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
- Status1 = EFI_SUCCESS;\r
- while (!EFI_ERROR (Status1)) {\r
- Status1 = KeyboardRead (ConsoleIn, &Data);;\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
return Status;\r
}\r
\r
+/**\r
+ Stop this driver on ControllerHandle. Support stopping 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 UINTN NumberOfChildren,\r
IN EFI_HANDLE *ChildHandleBuffer\r
)\r
-/*++\r
-\r
- Routine Description:\r
-\r
- Arguments:\r
-\r
- Returns:\r
-\r
---*/\r
-// GC_TODO: This - add argument and description to function comment\r
-// GC_TODO: Controller - add argument and description to function comment\r
-// GC_TODO: NumberOfChildren - add argument and description to function comment\r
-// GC_TODO: ChildHandleBuffer - add argument and description to function comment\r
-// GC_TODO: EFI_SUCCESS - add return value to function comment\r
{\r
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;\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
ConsoleIn->DevicePath\r
);\r
\r
- if (ConsoleIn->TimerEvent) {\r
+ if (ConsoleIn->TimerEvent != NULL) {\r
gBS->CloseEvent (ConsoleIn->TimerEvent);\r
ConsoleIn->TimerEvent = NULL;\r
}\r
- //\r
- // Disable the keyboard interface\r
- //\r
- Status = DisableKeyboard (ConsoleIn);\r
\r
//\r
// Since there will be no timer handler for keyboard input any more,\r
Status = KeyboardRead (ConsoleIn, &Data);;\r
}\r
//\r
- // Uninstall the Simple TextIn Protocol\r
+ // Uninstall the SimpleTextIn and SimpleTextInEx protocols\r
//\r
- Status = gBS->UninstallProtocolInterface (\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
- &ConsoleIn->ConIn\r
+ &ConsoleIn->ConIn,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &ConsoleIn->ConInEx,\r
+ NULL\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
//\r
// Free other resources\r
//\r
- if ((ConsoleIn->ConIn).WaitForKey) {\r
+ if ((ConsoleIn->ConIn).WaitForKey != NULL) {\r
gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);\r
(ConsoleIn->ConIn).WaitForKey = NULL;\r
}\r
-\r
+ if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {\r
+ gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);\r
+ ConsoleIn->ConInEx.WaitForKeyEx = NULL;\r
+ }\r
+ if (ConsoleIn->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);\r
+ ConsoleIn->KeyNotifyProcessEvent = 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