From 923863e826faf98bf5755be50c533b2ea80f4a38 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Sun, 4 Mar 2018 22:08:25 +0800 Subject: Add IPMI support. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao --- .../Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c | 243 +++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c (limited to 'Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c') diff --git a/Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c b/Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c new file mode 100644 index 0000000000..42fc6fc2ec --- /dev/null +++ b/Platform/Intel/AdvancedFeaturePkg/Ipmi/Frb/FrbDxe.c @@ -0,0 +1,243 @@ +/** @file + IPMI FRB Driver. + +Copyright (c) 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under +the terms and conditions of the BSD License that accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php. + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#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.TimerRunning == 0) { + return EFI_ABORTED; + } + + ZeroMem (&SetWatchdogTimer, sizeof(SetWatchdogTimer)); + // + // Just flip the Timer Use bit. This should release the timer. + // + SetWatchdogTimer.TimerUse.TimerRunning = 0; + SetWatchdogTimer.TimerUse.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((EFI_D_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.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.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; +} -- cgit v1.2.3