/** @file
IPMI FRB Driver.
Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
EFI_STATUS
EfiDisableFrb (
VOID
)
/*++
Routine Description:
This routine disables the specified FRB timer.
Arguments:
This - This pointer
FrbType - Type of FRB timer to get data on
Returns:
EFI_SUCCESS - FRB timer was disabled
EFI_ABORTED - Timer was already stopped
EFI_UNSUPPORTED - This type of FRB timer is not supported.
--*/
{
EFI_STATUS Status;
IPMI_SET_WATCHDOG_TIMER_REQUEST SetWatchdogTimer;
UINT8 CompletionCode;
IPMI_GET_WATCHDOG_TIMER_RESPONSE GetWatchdogTimer;
Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check if timer is still running, if not abort disable routine.
//
if (GetWatchdogTimer.TimerUse.Bits.TimerRunning == 0) {
return EFI_ABORTED;
}
ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer));
//
// Just flip the Timer Use bit. This should release the timer.
//
SetWatchdogTimer.TimerUse.Bits.TimerRunning = 0;
SetWatchdogTimer.TimerUse.Bits.TimerUse = IPMI_WATCHDOG_TIMER_BIOS_FRB2;
SetWatchdogTimer.TimerUseExpirationFlagsClear &= ~BIT2;
SetWatchdogTimer.TimerUseExpirationFlagsClear |= BIT1 | BIT4;
Status = IpmiSetWatchdogTimer (&SetWatchdogTimer, &CompletionCode);
return Status;
}
VOID
EFIAPI
DisableFRB2Handler (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Disables FRB2. This function gets called each time the
EFI_EVENT_SIGNAL_READY_TO_BOOT gets signaled
Arguments:
Standard event notification function arguments:
Event - the event that is signaled.
Context - not used here.
Returns:
--*/
{
DEBUG((DEBUG_ERROR, "!!! enter DisableFRB2Handler()!!!\n"));
EfiDisableFrb ();
}
EFI_STATUS
CheckForAndReportErrors(
VOID
)
/*++
Routine Description:
Check the Watchdog timer expiration flags and report the kind of watchdog
timeout occurred to the Error Manager.
Arguments:
Returns:
EFI_SUCCESS - Errors retrieved and reported
--*/
{
EFI_STATUS Status;
IPMI_GET_WATCHDOG_TIMER_RESPONSE GetWatchdogTimer;
IPMI_SET_WATCHDOG_TIMER_REQUEST SetWatchdogTimer;
UINT8 CompletionCode;
//
// Get the Watchdog timer info to find out what kind of timer expiration occurred.
//
Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
if (EFI_ERROR (Status)) {
return Status;
}
//
// If FRB2 Failure occurred, report it to the error manager and log a SEL.
//
if ((GetWatchdogTimer.TimerUseExpirationFlagsClear & BIT1) != 0) {
//
// Report the FRB2 time-out error
//
} else if ((GetWatchdogTimer.TimerUseExpirationFlagsClear & BIT3) != 0) {
//
// Report the OS Watchdog timer failure
//
}
//
// Need to clear Timer expiration flags after checking.
//
ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer));
SetWatchdogTimer.TimerUse = GetWatchdogTimer.TimerUse;
SetWatchdogTimer.TimerActions = GetWatchdogTimer.TimerActions;
SetWatchdogTimer.PretimeoutInterval = GetWatchdogTimer.PretimeoutInterval;
SetWatchdogTimer.TimerUseExpirationFlagsClear = GetWatchdogTimer.TimerUseExpirationFlagsClear;
SetWatchdogTimer.InitialCountdownValue = GetWatchdogTimer.InitialCountdownValue;
SetWatchdogTimer.TimerUse.Bits.TimerRunning = 1;
SetWatchdogTimer.TimerUseExpirationFlagsClear |= BIT1 | BIT2 | BIT3;
Status = IpmiSetWatchdogTimer (&SetWatchdogTimer, &CompletionCode);
return Status;
}
EFI_STATUS
ReportFrb2Status (
VOID
)
/*++
Routine Description:
This routine is built only when DEBUG_MODE is enabled. It is used
to report the status of FRB2 when the FRB2 driver is installed.
Arguments:
none
Returns:
EFI_SUCCESS: All info was retrieved and reported
EFI_ERROR: There was an error during info retrieval
--*/
{
EFI_STATUS Status;
IPMI_GET_WATCHDOG_TIMER_RESPONSE GetWatchdogTimer;
//
// Get the Watchdog timer info to find out what kind of timer expiration occurred.
//
Status = IpmiGetWatchdogTimer (&GetWatchdogTimer);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to get Watchdog Timer info from BMC.\n"));
return Status;
}
//
// Check if timer is running, report status to DEBUG_MODE output.
//
if (GetWatchdogTimer.TimerUse.Bits.TimerRunning == 1) {
DEBUG ((DEBUG_INFO, "FRB2 Timer is running.\n"));
} else {
DEBUG ((DEBUG_INFO, "FRB2 Timer is not running.\n"));
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
FrbDxeEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
This is the standard EFI driver point. This function intitializes
the private data required for creating FRB Driver.
Arguments:
ImageHandle - Handle for the image of this driver
SystemTable - Pointer to the EFI System Table
Returns:
EFI_SUCCESS - Protocol successfully started and installed
EFI_UNSUPPORTED - Protocol can't be started
--*/
{
EFI_EVENT ReadyToBootEvent;
EFI_STATUS Status;
CheckForAndReportErrors();
ReportFrb2Status ();
//
// Register the event to Disable FRB2 before Boot.
//
Status = EfiCreateEventReadyToBootEx (
TPL_NOTIFY,
DisableFRB2Handler,
NULL,
&ReadyToBootEvent
);
return Status;
}