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