/** @file | |
PS/2 Mouse 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 "Ps2Mouse.h" | |
#include "CommPs2.h" | |
/// | |
/// DriverBinding Protocol Instance | |
/// | |
EFI_DRIVER_BINDING_PROTOCOL gPS2MouseDriver = { | |
PS2MouseDriverSupported, | |
PS2MouseDriverStart, | |
PS2MouseDriverStop, | |
0xa, | |
NULL, | |
NULL | |
}; | |
/** | |
Test to see if this driver supports ControllerHandle. Any ControllerHandle | |
than contains a IsaIo protocol can be supported. | |
@param This Protocol instance pointer. | |
@param ControllerHandle Handle of device to test | |
@param RemainingDevicePath Optional parameter use to pick a specific child | |
device to start. | |
@retval EFI_SUCCESS This driver supports this device | |
@retval EFI_ALREADY_STARTED This driver is already running on this device | |
@retval other This driver does not support this device | |
**/ | |
EFI_STATUS | |
EFIAPI | |
PS2MouseDriverSupported ( | |
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; | |
} | |
switch (Acpi->HID) { | |
case EISA_PNP_ID (0xF03): | |
// | |
// Microsoft PS/2 style mouse | |
// | |
case EISA_PNP_ID (0xF13): | |
// | |
// PS/2 Port for PS/2-style Mice | |
// | |
break; | |
case EISA_PNP_ID (0x303): | |
// | |
// IBM Enhanced (101/102-key, PS/2 mouse support) | |
// | |
if (Acpi->UID == 1) { | |
break; | |
} | |
default: | |
return EFI_UNSUPPORTED; | |
break; | |
} | |
// | |
// 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; | |
} | |
/** | |
Start this driver on ControllerHandle by opening a Sio protocol, creating | |
PS2_MOUSE_DEV device and install gEfiSimplePointerProtocolGuid finally. | |
@param This Protocol instance pointer. | |
@param ControllerHandle Handle of device to bind driver to | |
@param RemainingDevicePath Optional parameter use to pick a specific child | |
device to start. | |
@retval EFI_SUCCESS This driver is added to ControllerHandle | |
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle | |
@retval other This driver does not support this device | |
**/ | |
EFI_STATUS | |
EFIAPI | |
PS2MouseDriverStart ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_STATUS EmptyStatus; | |
EFI_SIO_PROTOCOL *Sio; | |
PS2_MOUSE_DEV *MouseDev; | |
UINT8 Data; | |
EFI_TPL OldTpl; | |
EFI_STATUS_CODE_VALUE StatusCode; | |
EFI_DEVICE_PATH_PROTOCOL *DevicePath; | |
StatusCode = 0; | |
// | |
// Open the device path protocol | |
// | |
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_MOUSE | 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; | |
} | |
// | |
// Raise TPL to avoid keyboard operation impact | |
// | |
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
// | |
// Allocate private data | |
// | |
MouseDev = AllocateZeroPool (sizeof (PS2_MOUSE_DEV)); | |
if (MouseDev == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ErrorExit; | |
} | |
// | |
// Setup the device instance | |
// | |
MouseDev->Signature = PS2_MOUSE_DEV_SIGNATURE; | |
MouseDev->Handle = Controller; | |
MouseDev->SampleRate = SampleRate20; | |
MouseDev->Resolution = MouseResolution4; | |
MouseDev->Scaling = Scaling1; | |
MouseDev->DataPackageSize = 3; | |
MouseDev->DevicePath = DevicePath; | |
// | |
// Resolution = 4 counts/mm | |
// | |
MouseDev->Mode.ResolutionX = 4; | |
MouseDev->Mode.ResolutionY = 4; | |
MouseDev->Mode.LeftButton = TRUE; | |
MouseDev->Mode.RightButton = TRUE; | |
MouseDev->SimplePointerProtocol.Reset = MouseReset; | |
MouseDev->SimplePointerProtocol.GetState = MouseGetState; | |
MouseDev->SimplePointerProtocol.Mode = &(MouseDev->Mode); | |
// | |
// Initialize keyboard controller if necessary | |
// | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_PROGRESS_CODE, | |
EFI_PERIPHERAL_MOUSE | EFI_P_MOUSE_PC_SELF_TEST, | |
DevicePath | |
); | |
Data = IoRead8 (KBC_CMD_STS_PORT); | |
// | |
// Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. | |
// | |
if ((Data & (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_MOUSE | EFI_P_EC_NOT_DETECTED; | |
goto ErrorExit; | |
} | |
if ((Data & KBC_SYSF) != KBC_SYSF) { | |
Status = KbcSelfTest (); | |
if (EFI_ERROR (Status)) { | |
StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_CONTROLLER_ERROR; | |
goto ErrorExit; | |
} | |
} | |
KbcEnableAux (); | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_PROGRESS_CODE, | |
EFI_PERIPHERAL_MOUSE | EFI_P_PC_PRESENCE_DETECT, | |
DevicePath | |
); | |
// | |
// Reset the mouse | |
// | |
Status = MouseDev->SimplePointerProtocol.Reset ( | |
&MouseDev->SimplePointerProtocol, | |
FeaturePcdGet (PcdPs2MouseExtendedVerification) | |
); | |
if (EFI_ERROR (Status)) { | |
// | |
// mouse not connected | |
// | |
Status = EFI_SUCCESS; | |
StatusCode = EFI_PERIPHERAL_MOUSE | EFI_P_EC_NOT_DETECTED; | |
goto ErrorExit; | |
} | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_PROGRESS_CODE, | |
EFI_PERIPHERAL_MOUSE | EFI_P_PC_DETECTED, | |
DevicePath | |
); | |
// | |
// Setup the WaitForKey event | |
// | |
Status = gBS->CreateEvent ( | |
EVT_NOTIFY_WAIT, | |
TPL_NOTIFY, | |
MouseWaitForInput, | |
MouseDev, | |
&((MouseDev->SimplePointerProtocol).WaitForInput) | |
); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ErrorExit; | |
} | |
// | |
// Setup a periodic timer, used to poll mouse state | |
// | |
Status = gBS->CreateEvent ( | |
EVT_TIMER | EVT_NOTIFY_SIGNAL, | |
TPL_NOTIFY, | |
PollMouse, | |
MouseDev, | |
&MouseDev->TimerEvent | |
); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ErrorExit; | |
} | |
// | |
// Start timer to poll mouse (100 samples per second) | |
// | |
Status = gBS->SetTimer (MouseDev->TimerEvent, TimerPeriodic, 100000); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ErrorExit; | |
} | |
MouseDev->ControllerNameTable = NULL; | |
AddUnicodeString2 ( | |
"eng", | |
gPs2MouseComponentName.SupportedLanguages, | |
&MouseDev->ControllerNameTable, | |
L"PS/2 Mouse Device", | |
TRUE | |
); | |
AddUnicodeString2 ( | |
"en", | |
gPs2MouseComponentName2.SupportedLanguages, | |
&MouseDev->ControllerNameTable, | |
L"PS/2 Mouse Device", | |
FALSE | |
); | |
// | |
// Install protocol interfaces for the mouse device. | |
// | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&Controller, | |
&gEfiSimplePointerProtocolGuid, | |
&MouseDev->SimplePointerProtocol, | |
NULL | |
); | |
if (EFI_ERROR (Status)) { | |
goto ErrorExit; | |
} | |
gBS->RestoreTPL (OldTpl); | |
return Status; | |
ErrorExit: | |
if (Status != EFI_DEVICE_ERROR) { | |
KbcDisableAux (); | |
} | |
if (StatusCode != 0) { | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_ERROR_CODE | EFI_ERROR_MINOR, | |
StatusCode, | |
DevicePath | |
); | |
} | |
if ((MouseDev != NULL) && (MouseDev->SimplePointerProtocol.WaitForInput != NULL)) { | |
gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); | |
} | |
if ((MouseDev != NULL) && (MouseDev->TimerEvent != NULL)) { | |
gBS->CloseEvent (MouseDev->TimerEvent); | |
} | |
if ((MouseDev != NULL) && (MouseDev->ControllerNameTable != NULL)) { | |
FreeUnicodeStringTable (MouseDev->ControllerNameTable); | |
} | |
if (Status != EFI_DEVICE_ERROR) { | |
// | |
// Since there will be no timer handler for mouse input any more, | |
// exhaust input data just in case there is still mouse data left | |
// | |
EmptyStatus = EFI_SUCCESS; | |
while (!EFI_ERROR (EmptyStatus)) { | |
EmptyStatus = In8042Data (&Data); | |
} | |
} | |
if (MouseDev != NULL) { | |
FreePool (MouseDev); | |
} | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiDevicePathProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiSioProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
gBS->RestoreTPL (OldTpl); | |
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 | |
PS2MouseDriverStop ( | |
IN EFI_DRIVER_BINDING_PROTOCOL *This, | |
IN EFI_HANDLE Controller, | |
IN UINTN NumberOfChildren, | |
IN EFI_HANDLE *ChildHandleBuffer | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; | |
PS2_MOUSE_DEV *MouseDev; | |
UINT8 Data; | |
Status = gBS->OpenProtocol ( | |
Controller, | |
&gEfiSimplePointerProtocolGuid, | |
(VOID **)&SimplePointerProtocol, | |
This->DriverBindingHandle, | |
Controller, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
if (EFI_ERROR (Status)) { | |
return EFI_SUCCESS; | |
} | |
MouseDev = PS2_MOUSE_DEV_FROM_THIS (SimplePointerProtocol); | |
// | |
// Report that the keyboard is being disabled | |
// | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_PROGRESS_CODE, | |
EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE, | |
MouseDev->DevicePath | |
); | |
Status = gBS->UninstallProtocolInterface ( | |
Controller, | |
&gEfiSimplePointerProtocolGuid, | |
&MouseDev->SimplePointerProtocol | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Cancel mouse data polling timer, close timer event | |
// | |
gBS->SetTimer (MouseDev->TimerEvent, TimerCancel, 0); | |
gBS->CloseEvent (MouseDev->TimerEvent); | |
// | |
// Since there will be no timer handler for mouse input any more, | |
// exhaust input data just in case there is still mouse data left | |
// | |
Status = EFI_SUCCESS; | |
while (!EFI_ERROR (Status)) { | |
Status = In8042Data (&Data); | |
} | |
gBS->CloseEvent (MouseDev->SimplePointerProtocol.WaitForInput); | |
FreeUnicodeStringTable (MouseDev->ControllerNameTable); | |
FreePool (MouseDev); | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiDevicePathProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
gBS->CloseProtocol ( | |
Controller, | |
&gEfiSioProtocolGuid, | |
This->DriverBindingHandle, | |
Controller | |
); | |
return EFI_SUCCESS; | |
} | |
/** | |
Reset the Mouse and do BAT test for it, if ExtendedVerification is TRUE and | |
there is a mouse device connected to system. | |
@param This - Pointer of simple pointer Protocol. | |
@param ExtendedVerification - Whether configure mouse parameters. True: do; FALSE: skip. | |
@retval EFI_SUCCESS - The command byte is written successfully. | |
@retval EFI_DEVICE_ERROR - Errors occurred during resetting keyboard. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
MouseReset ( | |
IN EFI_SIMPLE_POINTER_PROTOCOL *This, | |
IN BOOLEAN ExtendedVerification | |
) | |
{ | |
EFI_STATUS Status; | |
PS2_MOUSE_DEV *MouseDev; | |
EFI_TPL OldTpl; | |
BOOLEAN KeyboardEnable; | |
UINT8 Data; | |
MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); | |
// | |
// Report reset progress code | |
// | |
REPORT_STATUS_CODE_WITH_DEVICE_PATH ( | |
EFI_PROGRESS_CODE, | |
EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET, | |
MouseDev->DevicePath | |
); | |
KeyboardEnable = FALSE; | |
// | |
// Raise TPL to avoid keyboard operation impact | |
// | |
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
ZeroMem (&MouseDev->State, sizeof (EFI_SIMPLE_POINTER_STATE)); | |
MouseDev->StateChanged = FALSE; | |
// | |
// Exhaust input data | |
// | |
Status = EFI_SUCCESS; | |
while (!EFI_ERROR (Status)) { | |
Status = In8042Data (&Data); | |
} | |
CheckKbStatus (&KeyboardEnable); | |
KbcDisableKb (); | |
// | |
// if there's data block on KBC data port, read it out | |
// | |
if ((IoRead8 (KBC_CMD_STS_PORT) & KBC_OUTB) == KBC_OUTB) { | |
IoRead8 (KBC_DATA_PORT); | |
} | |
Status = EFI_SUCCESS; | |
// | |
// The PS2 mouse driver reset behavior is always successfully return no matter whether or not there is mouse connected to system. | |
// This behavior is needed by performance speed. The following mouse command only successfully finish when mouse device is | |
// connected to system, so if PS2 mouse device not connect to system or user not ask for, we skip the mouse configuration and enabling | |
// | |
if (ExtendedVerification && CheckMouseConnect (MouseDev)) { | |
// | |
// Send mouse reset command and set mouse default configure | |
// | |
Status = PS2MouseReset (); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_DEVICE_ERROR; | |
goto Exit; | |
} | |
Status = PS2MouseSetSampleRate (MouseDev->SampleRate); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_DEVICE_ERROR; | |
goto Exit; | |
} | |
Status = PS2MouseSetResolution (MouseDev->Resolution); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_DEVICE_ERROR; | |
goto Exit; | |
} | |
Status = PS2MouseSetScaling (MouseDev->Scaling); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_DEVICE_ERROR; | |
goto Exit; | |
} | |
Status = PS2MouseEnable (); | |
if (EFI_ERROR (Status)) { | |
Status = EFI_DEVICE_ERROR; | |
goto Exit; | |
} | |
} | |
Exit: | |
gBS->RestoreTPL (OldTpl); | |
if (KeyboardEnable) { | |
KbcEnableKb (); | |
} | |
return Status; | |
} | |
/** | |
Check whether there is Ps/2 mouse device in system | |
@param MouseDev - Mouse Private Data Structure | |
@retval TRUE - Keyboard in System. | |
@retval FALSE - Keyboard not in System. | |
**/ | |
BOOLEAN | |
CheckMouseConnect ( | |
IN PS2_MOUSE_DEV *MouseDev | |
) | |
{ | |
EFI_STATUS Status; | |
Status = PS2MouseEnable (); | |
if (!EFI_ERROR (Status)) { | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/** | |
Get and Clear mouse status. | |
@param This - Pointer of simple pointer Protocol. | |
@param State - Output buffer holding status. | |
@retval EFI_INVALID_PARAMETER Output buffer is invalid. | |
@retval EFI_NOT_READY Mouse is not changed status yet. | |
@retval EFI_SUCCESS Mouse status is changed and get successful. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
MouseGetState ( | |
IN EFI_SIMPLE_POINTER_PROTOCOL *This, | |
IN OUT EFI_SIMPLE_POINTER_STATE *State | |
) | |
{ | |
PS2_MOUSE_DEV *MouseDev; | |
EFI_TPL OldTpl; | |
MouseDev = PS2_MOUSE_DEV_FROM_THIS (This); | |
if (State == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (!MouseDev->StateChanged) { | |
return EFI_NOT_READY; | |
} | |
OldTpl = gBS->RaiseTPL (TPL_NOTIFY); | |
CopyMem (State, &(MouseDev->State), sizeof (EFI_SIMPLE_POINTER_STATE)); | |
// | |
// clear mouse state | |
// | |
MouseDev->State.RelativeMovementX = 0; | |
MouseDev->State.RelativeMovementY = 0; | |
MouseDev->State.RelativeMovementZ = 0; | |
MouseDev->StateChanged = FALSE; | |
gBS->RestoreTPL (OldTpl); | |
return EFI_SUCCESS; | |
} | |
/** | |
Event notification function for SIMPLE_POINTER.WaitForInput event. | |
Signal the event if there is input from mouse. | |
@param Event event object | |
@param Context event context | |
**/ | |
VOID | |
EFIAPI | |
MouseWaitForInput ( | |
IN EFI_EVENT Event, | |
IN VOID *Context | |
) | |
{ | |
PS2_MOUSE_DEV *MouseDev; | |
MouseDev = (PS2_MOUSE_DEV *)Context; | |
// | |
// Someone is waiting on the mouse event, if there's | |
// input from mouse, signal the event | |
// | |
if (MouseDev->StateChanged) { | |
gBS->SignalEvent (Event); | |
} | |
} | |
/** | |
Event notification function for TimerEvent event. | |
If mouse device is connected to system, try to get the mouse packet data. | |
@param Event - TimerEvent in PS2_MOUSE_DEV | |
@param Context - Pointer to PS2_MOUSE_DEV structure | |
**/ | |
VOID | |
EFIAPI | |
PollMouse ( | |
IN EFI_EVENT Event, | |
IN VOID *Context | |
) | |
{ | |
PS2_MOUSE_DEV *MouseDev; | |
MouseDev = (PS2_MOUSE_DEV *)Context; | |
// | |
// Polling mouse packet data | |
// | |
PS2MouseGetPacket (MouseDev); | |
} | |
/** | |
The user Entry Point for module Ps2Mouse. 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 | |
InitializePs2Mouse ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
// | |
// Install driver model protocol(s). | |
// | |
Status = EfiLibInstallDriverBindingComponentName2 ( | |
ImageHandle, | |
SystemTable, | |
&gPS2MouseDriver, | |
ImageHandle, | |
&gPs2MouseComponentName, | |
&gPs2MouseComponentName2 | |
); | |
ASSERT_EFI_ERROR (Status); | |
return Status; | |
} |