/** Stop this driver on ControllerHandle. Support stoping any child handles created by this driver. @param This Protocol instance pointer. @param ControllerHandle Handle of device to stop driver on @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of children is zero stop the entire bus driver. @param ChildHandleBuffer List of Child Handles to Stop. @retval EFI_SUCCESS This driver is removed ControllerHandle @retval other This driver was not removed from this device **/ EFI_STATUS EFIAPI KbdControllerDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_STATUS Status; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; // // Disable Keyboard // Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInProtocolGuid, (VOID **) &ConIn, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInputExProtocolGuid, NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); // // Report that the keyboard is being disabled // REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE, ConsoleIn->DevicePath ); if (ConsoleIn->TimerEvent != NULL) { gBS->CloseEvent (ConsoleIn->TimerEvent); ConsoleIn->TimerEvent = NULL; } // // Since there will be no timer handler for keyboard input any more, // exhaust input data just in case there is still keyboard data left // Status = EFI_SUCCESS; while (!EFI_ERROR (Status)) { Status = KeyboardRead (ConsoleIn, &Data);; } // // Uninstall the SimpleTextIn and SimpleTextInEx protocols // Status = gBS->UninstallMultipleProtocolInterfaces ( Controller, &gEfiSimpleTextInProtocolGuid, &ConsoleIn->ConIn, &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, NULL ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); // // Free other resources // if ((ConsoleIn->ConIn).WaitForKey != NULL) { gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); (ConsoleIn->ConIn).WaitForKey = NULL; } if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); ConsoleIn->ConInEx.WaitForKeyEx = NULL; } KbdFreeNotifyList (&ConsoleIn->NotifyList); FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); gBS->FreePool (ConsoleIn); return EFI_SUCCESS; }
/** 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_ISA_IO_PROTOCOL *IsaIo; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; StatusCode = 0; Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); 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, ParentDevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, &gEfiIsaIoProtocolGuid, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_INVALID_PARAMETER; } // // 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->IsaIo = IsaIo; ConsoleIn->DevicePath = ParentDevicePath; ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; ConsoleIn->ConInEx.SetState = KeyboardSetState; ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; InitializeListHead (&ConsoleIn->NotifyList); // // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. // When KBC decode (IO port 0x60/0x64 decode) is not enabled, // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS. // So instead we read status register to detect after read if KBC decode is enabled. // // // Return code is ignored on purpose. // if (!PcdGetBool (PcdFastPS2Detection)) { KeyboardRead (ConsoleIn, &Data); if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) { // // If nobody decodes KBC I/O port, it will read back as 0xFF. // Check the Time-Out and Parity bit to see if it has an active KBC in system // Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } } // // Setup the WaitForKey event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKey, ConsoleIn, &((ConsoleIn->ConIn).WaitForKey) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // // Setup the WaitForKeyEx event // Status = gBS->CreateEvent ( EVT_NOTIFY_WAIT, TPL_NOTIFY, KeyboardWaitForKeyEx, ConsoleIn, &(ConsoleIn->ConInEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } // Setup a periodic timer, used for reading keystrokes at a fixed interval // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, KeyboardTimerHandler, ConsoleIn, &ConsoleIn->TimerEvent ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } Status = gBS->SetTimer ( ConsoleIn->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } REPORT_STATUS_CODE_WITH_DEVICE_PATH ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, ParentDevicePath ); // // 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, ParentDevicePath ); 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, ParentDevicePath ); } if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); } if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { gBS->CloseEvent (ConsoleIn->TimerEvent); } if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); } KbdFreeNotifyList (&ConsoleIn->NotifyList); if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { FreeUnicodeStringTable (ConsoleIn->ControllerNameTable); } // // Since there will be no timer handler for keyboard input any more, // exhaust input data just in case there is still keyboard data left // if (ConsoleIn != NULL) { Status1 = EFI_SUCCESS; while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { Status1 = KeyboardRead (ConsoleIn, &Data);; } } if (ConsoleIn != NULL) { gBS->FreePool (ConsoleIn); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, &gEfiIsaIoProtocolGuid, This->DriverBindingHandle, Controller ); return Status; }
EFI_STATUS EFIAPI KbdControllerDriverStart ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) /*++ Routine Description: Arguments: Returns: --*/ // GC_TODO: This - add argument and description to function comment // GC_TODO: Controller - add argument and description to function comment // GC_TODO: RemainingDevicePath - add argument and description to function comment // GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment { EFI_STATUS Status; EFI_STATUS Status1; EFI_INTERFACE_DEFINITION_FOR_ISA_IO *IsaIo; KEYBOARD_CONSOLE_IN_DEV *ConsoleIn; UINT8 Data; EFI_STATUS_CODE_VALUE StatusCode; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; StatusCode = 0; Status = gBS->OpenProtocol ( Controller, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { return Status; } // // Report that the keyboard is being enabled // ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Get the ISA I/O Protocol on Controller's handle // Status = gBS->OpenProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, (VOID **) &IsaIo, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); return EFI_INVALID_PARAMETER; } // // Allocate private data // ConsoleIn = EfiLibAllocateZeroPool (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->IsaIo = IsaIo; ConsoleIn->ScancodeBufStartPos = 0; ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1; ConsoleIn->ScancodeBufCount = 0; ConsoleIn->Ctrled = FALSE; ConsoleIn->Alted = FALSE; ConsoleIn->DevicePath = ParentDevicePath; #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx; ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx; ConsoleIn->ConInEx.SetState = KeyboardSetState; ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify; ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify; InitializeListHead (&ConsoleIn->NotifyList); #endif // DISABLE_CONSOLE_EX #endif // // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS. // 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 ( EFI_EVENT_NOTIFY_WAIT, EFI_TPL_NOTIFY, KeyboardWaitForKey, &(ConsoleIn->ConIn), &((ConsoleIn->ConIn).WaitForKey) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX // // Setup the WaitForKeyEx event // Status = gBS->CreateEvent ( EFI_EVENT_NOTIFY_WAIT, EFI_TPL_NOTIFY, KeyboardWaitForKeyEx, &(ConsoleIn->ConInEx), &(ConsoleIn->ConInEx.WaitForKeyEx) ); if (EFI_ERROR (Status)) { Status = EFI_OUT_OF_RESOURCES; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR; goto ErrorExit; } #endif // DISABLE_CONSOLE_EX #endif // // Setup a periodic timer, used for reading keystrokes at a fixed interval // Status = gBS->CreateEvent ( EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, EFI_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; } ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT, 0, &gEfiCallerIdGuid, ParentDevicePath ); // // Reset the keyboard device // Status = ConsoleIn->ConIn.Reset (&ConsoleIn->ConIn, TRUE); if (EFI_ERROR (Status)) { Status = EFI_DEVICE_ERROR; StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED; goto ErrorExit; } ConsoleIn->ControllerNameTable = NULL; EfiLibAddUnicodeString ( LANGUAGE_CODE_ENGLISH, gPs2KeyboardComponentName.SupportedLanguages, &ConsoleIn->ControllerNameTable, L"PS/2 Keyboard Device" ); // // Install protocol interfaces for the keyboard device. // Status = gBS->InstallMultipleProtocolInterfaces ( &Controller, &gEfiSimpleTextInProtocolGuid, &ConsoleIn->ConIn, #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, #endif // DISABLE_CONSOLE_EX #endif 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) { ReportStatusCodeWithDevicePath ( EFI_ERROR_CODE | EFI_ERROR_MINOR, StatusCode, 0, &gEfiCallerIdGuid, ParentDevicePath ); } if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) { gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey); } if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) { gBS->CloseEvent (ConsoleIn->TimerEvent); } #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); } KbdFreeNotifyList (&ConsoleIn->NotifyList); #endif // DISABLE_CONSOLE_EX #endif if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) { EfiLibFreeUnicodeStringTable (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 // Status1 = EFI_SUCCESS; while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) { Status1 = KeyboardRead (ConsoleIn, &Data);; } if (ConsoleIn != NULL) { gBS->FreePool (ConsoleIn); } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, This->DriverBindingHandle, Controller ); return Status; }
EFI_STATUS EFIAPI KbdControllerDriverStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) /*++ Routine Description: Arguments: Returns: --*/ // GC_TODO: This - add argument and description to function comment // GC_TODO: Controller - add argument and description to function comment // GC_TODO: NumberOfChildren - add argument and description to function comment // GC_TODO: ChildHandleBuffer - add argument and description to function comment // GC_TODO: EFI_SUCCESS - add return value to function comment { EFI_STATUS Status; EFI_SIMPLE_TEXT_IN_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; } #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX Status = gBS->OpenProtocol ( Controller, &gEfiSimpleTextInputExProtocolGuid, NULL, This->DriverBindingHandle, Controller, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { return Status; } #endif // DISABLE_CONSOLE_EX #endif ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn); // // Report that the keyboard is being disabled // ReportStatusCodeWithDevicePath ( EFI_PROGRESS_CODE, EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE, 0, &gEfiCallerIdGuid, ConsoleIn->DevicePath ); if (ConsoleIn->TimerEvent) { gBS->CloseEvent (ConsoleIn->TimerEvent); ConsoleIn->TimerEvent = NULL; } // // Disable the keyboard interface // Status = DisableKeyboard (ConsoleIn); // // 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, #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX &gEfiSimpleTextInputExProtocolGuid, &ConsoleIn->ConInEx, #endif // DISABLE_CONSOLE_EX #endif NULL ); if (EFI_ERROR (Status)) { return Status; } gBS->CloseProtocol ( Controller, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, Controller ); gBS->CloseProtocol ( Controller, EFI_ISA_IO_PROTOCOL_VERSION, This->DriverBindingHandle, Controller ); // // Free other resources // if ((ConsoleIn->ConIn).WaitForKey) { gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey); (ConsoleIn->ConIn).WaitForKey = NULL; } #if (EFI_SPECIFICATION_VERSION >= 0x0002000A) #ifndef DISABLE_CONSOLE_EX if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) { gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx); ConsoleIn->ConInEx.WaitForKeyEx = NULL; } KbdFreeNotifyList (&ConsoleIn->NotifyList); #endif // DISABLE_CONSOLE_EX #endif EfiLibFreeUnicodeStringTable (ConsoleIn->ControllerNameTable); gBS->FreePool (ConsoleIn); return EFI_SUCCESS; }
/** 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 // 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) { // // 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 { // // 8042 controller is not setup yet: // 8042 controller selftest; // Don't enable mouse interface later. // // // Disable keyboard and mouse interfaces // 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->ScancodeBufStartPos = 0; ConsoleIn->ScancodeBufEndPos = KEYBOARD_BUFFER_MAX_COUNT - 1; ConsoleIn->ScancodeBufCount = 0; ConsoleIn->Ctrled = FALSE; ConsoleIn->Alted = FALSE; // // Reset the status indicators // ConsoleIn->Ctrl = FALSE; ConsoleIn->Alt = FALSE; ConsoleIn->Shift = FALSE; ConsoleIn->CapsLock = FALSE; ConsoleIn->NumLock = FALSE; ConsoleIn->ScrollLock = FALSE; ConsoleIn->LeftShift = FALSE; ConsoleIn->RightShift = FALSE; ConsoleIn->LeftLogo = FALSE; ConsoleIn->RightLogo = FALSE; ConsoleIn->Menu = FALSE; ConsoleIn->SysReq = FALSE; // // For reseting keyboard is not mandatory before booting OS and sometimes keyboard responses very slow, // and to support KB hot plug, we need to let the InitKB succeed no matter whether there is a KB device connected // to system. So we only do the real reseting for keyboard when user asks and there is a real KB connected t system, // and normally during booting an OS, it's skipped. // if (ExtendedVerification && CheckKeyboardConnect (ConsoleIn)) { // // Additional verifications for keyboard interface // // // Keyboard Interface Test // Status = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_KEYBOARD_INTERFACE_SELF_TEST); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); goto Done; } Status = KeyboardWaitForValue (ConsoleIn, 0x00); if (EFI_ERROR (Status)) { KeyboardError ( ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r" ); goto Done; } // // Keyboard reset with a BAT(Basic Assurance Test) // Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_RESET); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); goto Done; } Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); goto Done; } // // wait for BAT completion code // mWaitForValueTimeOut = KEYBOARD_BAT_TIMEOUT; Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_BAT_SUCCESS); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Keyboard self test failed!\n\r"); goto Done; } mWaitForValueTimeOut = KEYBOARD_WAITFORVALUE_TIMEOUT; // // Set Keyboard to use Scan Code Set 2 // Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); goto Done; } Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); goto Done; } Status = KeyboardWrite (ConsoleIn, 0x02); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"8042 controller data write error!!\n\r"); goto Done; } Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); goto Done; } // // Clear Keyboard Scancode Buffer // Status = KeyboardWrite (ConsoleIn, KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"8042 controller data write error!\n\r"); goto Done; } Status = KeyboardWaitForValue (ConsoleIn, KEYBOARD_8048_RETURN_8042_ACK); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Some specific value not aquired from 8042 controller!\n\r"); goto Done; } // if (Ps2Policy != NULL) { if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_CAPSLOCK) == EFI_KEYBOARD_CAPSLOCK) { ConsoleIn->CapsLock = TRUE; } if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_NUMLOCK) == EFI_KEYBOARD_NUMLOCK) { ConsoleIn->NumLock = TRUE; } if ((Ps2Policy->KeyboardLight & EFI_KEYBOARD_SCROLLLOCK) == EFI_KEYBOARD_SCROLLLOCK) { ConsoleIn->ScrollLock = TRUE; } } // // Update Keyboard Lights // Status = UpdateStatusLights (ConsoleIn); if (EFI_ERROR (Status)) { KeyboardError (ConsoleIn, L"Update keyboard status lights error!\n\r"); goto Done; } } // // At last, we can now enable the mouse interface if appropriate // Done: if (mEnableMouseInterface) { // // Enable mouse interface // Status1 = KeyboardCommand (ConsoleIn, KEYBOARD_8042_COMMAND_ENABLE_MOUSE_INTERFACE); if (EFI_ERROR (Status1)) { KeyboardError (ConsoleIn, L"8042 controller command write error!\n\r"); return EFI_DEVICE_ERROR; } } if (!EFI_ERROR (Status)) { return EFI_SUCCESS; } else { return EFI_DEVICE_ERROR; } }