On Wed, May 26, 2021 at 17:06:56 +0700, Nhi Pham wrote: > The FailSafeDxe driver reverts the system's configuration to known good > values if the system fails to boot up multiple times. It also implements > the Watchdog Timer Architectural Protocol to reset the system if it > hangs. > > By default, when system starts, it configures the secure watchdog timer > with a default value of 5 minutes. If the system boots up cleanly to the > considered good stage, the counter is cleared as it indicates FailSafe > monitor (ATF) that has booted up successfully. If the timer expires, it > is considered a failed boot and system is rebooted. > > Cc: Thang Nguyen <th...@os.amperecomputing.com> > Cc: Chuong Tran <chu...@os.amperecomputing.com> > Cc: Phong Vo <ph...@os.amperecomputing.com> > Cc: Leif Lindholm <l...@nuviainc.com> > Cc: Michael D Kinney <michael.d.kin...@intel.com> > Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> > Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> > > Signed-off-by: Nhi Pham <n...@os.amperecomputing.com> > --- > Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 1 - > Platform/Ampere/JadePkg/Jade.dsc | 9 + > Platform/Ampere/JadePkg/Jade.fdf | 6 > +- > Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf | 54 > +++ > Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h | 20 > ++ > Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h | 29 > ++ > Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c | 184 > ++++++++++ > Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c | 357 > ++++++++++++++++++++ > 8 files changed, 658 insertions(+), 2 deletions(-) > > diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > index 0332473b59b0..6a6f72e995af 100755 > --- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > +++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc > @@ -585,7 +585,6 @@ [Components.common] > # Timer > # > ArmPkg/Drivers/TimerDxe/TimerDxe.inf > - MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
It's not clear from the commit message why this should happen. > > # > # ARM GIC Dxe > diff --git a/Platform/Ampere/JadePkg/Jade.dsc > b/Platform/Ampere/JadePkg/Jade.dsc > index f68af24a0d78..f92855af99ab 100755 > --- a/Platform/Ampere/JadePkg/Jade.dsc > +++ b/Platform/Ampere/JadePkg/Jade.dsc > @@ -75,6 +75,11 @@ [LibraryClasses] > # > > RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf > > + # > + # Library for FailSafe support > + # > + > FailSafeLib|Platform/Ampere/AmperePlatformPkg/Library/FailSafeLib/FailSafeLib.inf > + > > ################################################################################ > # > # Specific Platform Pcds > @@ -98,3 +103,7 @@ [PcdsFixedAtBuild.common] > # > > ################################################################################ > [Components.common] > + # > + # FailSafe and Watchdog Timer > + # > + Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf > diff --git a/Platform/Ampere/JadePkg/Jade.fdf > b/Platform/Ampere/JadePkg/Jade.fdf > index 905289844378..80a86d7c1156 100755 > --- a/Platform/Ampere/JadePkg/Jade.fdf > +++ b/Platform/Ampere/JadePkg/Jade.fdf > @@ -185,7 +185,11 @@ [FV.FvMain] > # Timer > # > INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf > - INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf It's not clear from the commit message why this should happen. / Leif > + > + # > + # FailSafe and Watchdog Timer > + # > + INF Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf > > # > # ARM GIC Dxe > diff --git > a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf > b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf > new file mode 100755 > index 000000000000..60de10c95c85 > --- /dev/null > +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.inf > @@ -0,0 +1,54 @@ > +## @file > +# > +# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x0001001B > + BASE_NAME = FailSafeDxe > + FILE_GUID = 7BC4F970-B1CF-11E6-80F5-76304DEC7EB7 > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = FailSafeDxeEntryPoint > + > +[Sources] > + FailSafe.h > + FailSafeDxe.c > + Watchdog.c > + Watchdog.h > + > +[Packages] > + ArmPkg/ArmPkg.dec > + ArmPlatformPkg/ArmPlatformPkg.dec > + EmbeddedPkg/EmbeddedPkg.dec > + MdeModulePkg/MdeModulePkg.dec > + MdePkg/MdePkg.dec > + Platform/Ampere/AmperePlatformPkg/AmperePlatformPkg.dec > + Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec > + Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec > + > +[LibraryClasses] > + ArmSmcLib > + DebugLib > + FailSafeLib > + NVParamLib > + PcdLib > + TimerLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiLib > + UefiRuntimeServicesTableLib > + > +[Pcd] > + gArmTokenSpaceGuid.PcdGenericWatchdogControlBase > + gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum > + > +[Protocols] > + gEfiWatchdogTimerArchProtocolGuid ## PRODUCES > + gHardwareInterrupt2ProtocolGuid ## CONSUMES > + > +[Depex] > + gHardwareInterrupt2ProtocolGuid > diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h > b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h > new file mode 100644 > index 000000000000..8bf3a98f1d8e > --- /dev/null > +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafe.h > @@ -0,0 +1,20 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef FAILSAFE_H_ > +#define FAILSAFE_H_ > + > +#include <Uefi.h> > + > +BOOLEAN > +EFIAPI > +IsFailSafeOff ( > + VOID > + ); > + > +#endif /* FAILSAFE_H_ */ > diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h > b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h > new file mode 100755 > index 000000000000..6c9106fdbea5 > --- /dev/null > +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.h > @@ -0,0 +1,29 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef GENERIC_WATCHDOG_H_ > +#define GENERIC_WATCHDOG_H_ > + > +#include <Protocol/WatchdogTimer.h> > + > +/* The number of 100ns periods (the unit of time passed to these functions) > + in a second */ > +#define TIME_UNITS_PER_SECOND 10000000 > + > +/** > + The function to install Watchdog timer protocol to the system > + > + @retval Return EFI_SUCCESS if install Watchdog timer protocol > successfully. > + **/ > +EFI_STATUS > +EFIAPI > +WatchdogTimerInstallProtocol ( > + EFI_WATCHDOG_TIMER_ARCH_PROTOCOL **WatchdogTimerProtocol > + ); > + > +#endif /* GENERIC_WATCHDOG_H_ */ > diff --git > a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c > b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c > new file mode 100644 > index 000000000000..1b8978b12ea7 > --- /dev/null > +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/FailSafeDxe.c > @@ -0,0 +1,184 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Uefi.h> > + > +#include <Guid/EventGroup.h> > +#include <Library/ArmSmcLib.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/FailSafeLib.h> > +#include <Library/NVParamLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > + > +#include "FailSafe.h" > +#include "Watchdog.h" > + > +STATIC UINTN gWatchdogOSTimeout; > +STATIC BOOLEAN gFailSafeOff; > +STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer; > + > +EFI_STATUS > +EFIAPI > +FailSafeTestBootFailure ( > + VOID > + ); > + > +STATIC VOID > +FailSafeTurnOff ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + > + if (IsFailSafeOff ()) { > + return; > + } > + > + Status = FailSafeBootSuccessfully (); > + ASSERT_EFI_ERROR (Status); > + > + gFailSafeOff = TRUE; > + > + /* Disable Watchdog timer */ > + gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, 0); > +} > + > +BOOLEAN > +EFIAPI > +IsFailSafeOff ( > + VOID > + ) > +{ > + return gFailSafeOff; > +} > + > +/** > + The function to disable Watchdog timer when enter Setup screen > + **/ > +VOID > +WdtTimerEnterSetupScreenCallback ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + /* Make sure FailSafe is turned off */ > + FailSafeTurnOff (); > +} > + > +/** > + The function to refresh Watchdog timer in the event before booting > + **/ > +VOID > +WdtTimerBeforeBootCallback ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + /* > + * At this point, the system is considered boot successfully to BIOS > + */ > + FailSafeTurnOff (); > + > + /* > + * It is BIOS's responsibility to setup Watchdog when load an EFI > application > + * after this step > + */ > +} > + > +/** > + The function to refresh Watchdog timer in the event before exiting boot > services > + **/ > +VOID > +WdtTimerExitBootServiceCallback ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + > + /* Enable Watchdog timer for OS booting */ > + if (gWatchdogOSTimeout != 0) { > + gWatchdogTimer->SetTimerPeriod ( > + gWatchdogTimer, > + gWatchdogOSTimeout * TIME_UNITS_PER_SECOND > + ); > + } else { > + /* Disable Watchdog timer */ > + gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, 0); > + } > +} > + > +/** > + This function is a hook called when user loads the manufacturing > + or optimal defaults. > + > + @param Defaults : (NVRAM_VARIABLE *)optimal or manufacturing > + @Data : Messagebox > + > + @retval VOID > +**/ > +VOID > +LoadNVRAMDefaultConfig ( > + IN VOID *Defaults, > + IN UINTN Data > + ) > +{ > + NVParamClrAll (); > +} > + > +/** > + Main entry for this driver. > + > + @param ImageHandle Image handle this driver. > + @param SystemTable Pointer to SystemTable. > + > + @retval EFI_SUCESS This function always complete successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +FailSafeDxeEntryPoint ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_EVENT ExitBootServicesEvent; > + EFI_STATUS Status; > + > + gFailSafeOff = FALSE; > + > + FailSafeTestBootFailure (); > + > + /* We need to setup non secure Watchdog to ensure that the system will > + * boot to OS successfully. > + * > + * The BIOS doesn't handle Watchdog interrupt so we expect WS1 asserted EL3 > + * when Watchdog timeout triggered > + */ > + > + Status = WatchdogTimerInstallProtocol (&gWatchdogTimer); > + ASSERT_EFI_ERROR (Status); > + > + // FIXME: We should register a callback function before entering to Setup > screen > + // rather than always call it at DXE phase. > + FailSafeTurnOff (); > + > + /* Register event before exit boot services */ > + Status = gBS->CreateEvent ( > + EVT_SIGNAL_EXIT_BOOT_SERVICES, > + TPL_NOTIFY, > + WdtTimerExitBootServiceCallback, > + NULL, > + &ExitBootServicesEvent > + ); > + ASSERT_EFI_ERROR (Status); > + > + return Status; > +} > diff --git a/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c > b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c > new file mode 100644 > index 000000000000..34329d04206a > --- /dev/null > +++ b/Platform/Ampere/AmperePlatformPkg/Drivers/FailSafeDxe/Watchdog.c > @@ -0,0 +1,357 @@ > +/** @file > + > + Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR> > + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include <Library/ArmGenericTimerCounterLib.h> > +#include <Library/ArmLib.h> > +#include <Library/BaseLib.h> > +#include <Library/DebugLib.h> > +#include <Library/IoLib.h> > +#include <Library/PcdLib.h> > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/UefiRuntimeServicesTableLib.h> > +#include <Protocol/HardwareInterrupt2.h> > + > +#include "FailSafe.h" > +#include "Watchdog.h" > + > +/* Watchdog timer controller registers */ > +#define WDT_CTRL_BASE_REG FixedPcdGet64 > (PcdGenericWatchdogControlBase) > +#define WDT_CTRL_WCS_OFF 0x0 > +#define WDT_CTRL_WCS_ENABLE_MASK 0x1 > +#define WDT_CTRL_WOR_OFF 0x8 > +#define WDT_CTRL_WCV_OFF 0x10 > +#define WS0_INTERRUPT_SOURCE FixedPcdGet32 > (PcdGenericWatchdogEl2IntrNum) > + > +STATIC UINT64 mNumTimerTicks; > +STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol; > +BOOLEAN mInterruptWS0Enabled; > + > +STATIC > +VOID > +WatchdogTimerWriteOffsetRegister ( > + UINT32 Value > + ) > +{ > + MmioWrite32 (WDT_CTRL_BASE_REG + WDT_CTRL_WOR_OFF, Value); > +} > + > +STATIC > +VOID > +WatchdogTimerWriteCompareRegister ( > + UINT64 Value > + ) > +{ > + MmioWrite64 (WDT_CTRL_BASE_REG + WDT_CTRL_WCV_OFF, Value); > +} > + > +STATIC > +EFI_STATUS > +WatchdogTimerEnable ( > + IN BOOLEAN Enable > + ) > +{ > + UINT32 Val = MmioRead32 ((UINTN)(WDT_CTRL_BASE_REG + WDT_CTRL_WCS_OFF)); > + > + if (Enable) { > + Val |= WDT_CTRL_WCS_ENABLE_MASK; > + } else { > + Val &= ~WDT_CTRL_WCS_ENABLE_MASK; > + } > + MmioWrite32 ((UINTN)(WDT_CTRL_BASE_REG + WDT_CTRL_WCS_OFF), Val); > + > + return EFI_SUCCESS; > +} > + > +STATIC > +EFI_STATUS > +WatchdogTimerSetup ( > + VOID > + ) > +{ > + EFI_STATUS Status; > + > + /* Disable Watchdog timer */ > + WatchdogTimerEnable (FALSE); > + > + if (!mInterruptWS0Enabled) { > + Status = mInterruptProtocol->EnableInterruptSource ( > + mInterruptProtocol, > + WS0_INTERRUPT_SOURCE > + ); > + ASSERT_EFI_ERROR (Status); > + > + mInterruptWS0Enabled = TRUE; > + } > + > + if (mNumTimerTicks == 0) { > + return EFI_SUCCESS; > + } > + > + /* If the number of required ticks is greater than the max the Watchdog's > + offset register (WOR) can hold, we need to manually compute and set > + the compare register (WCV) */ > + if (mNumTimerTicks > MAX_UINT32) { > + /* We need to enable the Watchdog *before* writing to the compare > register, > + because enabling the Watchdog causes an "explicit refresh", which > + clobbers the compare register (WCV). In order to make sure this > doesn't > + trigger an interrupt, set the offset to max. */ > + WatchdogTimerWriteOffsetRegister (MAX_UINT32); > + WatchdogTimerEnable (TRUE); > + WatchdogTimerWriteCompareRegister (ArmGenericTimerGetSystemCount () + > mNumTimerTicks); > + } else { > + WatchdogTimerWriteOffsetRegister ((UINT32)mNumTimerTicks); > + WatchdogTimerEnable (TRUE); > + } > + > + return EFI_SUCCESS; > +} > + > + > +/* This function is called when the Watchdog's first signal (WS0) goes high. > + It uses the ResetSystem Runtime Service to reset the board. > +*/ > +VOID > +EFIAPI > +WatchdogTimerInterruptHandler ( > + IN HARDWARE_INTERRUPT_SOURCE Source, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + STATIC CONST CHAR16 ResetString[]= L"The generic Watchdog timer ran out."; > + > + mInterruptProtocol->EndOfInterrupt (mInterruptProtocol, Source); > + > + if (!IsFailSafeOff ()) { > + /* Not handling interrupt as ATF is monitoring it */ > + return; > + } > + > + WatchdogTimerEnable (FALSE); > + > + gRT->ResetSystem ( > + EfiResetCold, > + EFI_TIMEOUT, > + StrSize (ResetString), > + (VOID *)&ResetString > + ); > + > + /* If we got here then the reset didn't work */ > + ASSERT (FALSE); > +} > + > +/** > + This function registers the handler NotifyFunction so it is called every > time > + the Watchdog timer expires. It also passes the amount of time since the > last > + handler call to the NotifyFunction. > + If NotifyFunction is not NULL and a handler is not already registered, > + then the new handler is registered and EFI_SUCCESS is returned. > + If NotifyFunction is NULL, and a handler is already registered, > + then that handler is unregistered. > + If an attempt is made to register a handler when a handler is already > + registered, then EFI_ALREADY_STARTED is returned. > + If an attempt is made to unregister a handler when a handler is not > + registered, then EFI_INVALID_PARAMETER is returned. > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param NotifyFunction The function to call when a timer interrupt fires. > + This function executes at TPL_HIGH_LEVEL. The DXE > + Core will register a handler for the timer > interrupt, > + so it can know how much time has passed. This > + information is used to signal timer based events. > + NULL will unregister the handler. > + > + @retval EFI_UNSUPPORTED The code does not support NotifyFunction. > + > +**/ > +EFI_STATUS > +EFIAPI > +WatchdogTimerRegisterHandler ( > + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, > + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction > + ) > +{ > + /* Not support. Watchdog will reset the board */ > + return EFI_UNSUPPORTED; > +} > + > +/** > + This function sets the amount of time to wait before firing the Watchdog > + timer to TimerPeriod 100ns units. If TimerPeriod is 0, then the Watchdog > + timer is disabled. > + > + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod The amount of time in 100ns units to wait before > + the Watchdog timer is fired. If TimerPeriod is > zero, > + then the Watchdog timer is disabled. > + > + @retval EFI_SUCCESS The Watchdog timer has been programmed to > fire > + in Time 100ns units. > + @retval EFI_DEVICE_ERROR A Watchdog timer could not be programmed due > + to a device error. > + > +**/ > +EFI_STATUS > +EFIAPI > +WatchdogTimerSetPeriod ( > + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, > + IN UINT64 TimerPeriod // In 100ns units > + ) > +{ > + mNumTimerTicks = (ArmGenericTimerGetTimerFreq () * TimerPeriod) / > TIME_UNITS_PER_SECOND; > + > + if (!IsFailSafeOff ()) { > + /* Not support Watchdog timer service until FailSafe is off as ATF is > monitoring it */ > + return EFI_SUCCESS; > + } > + > + return WatchdogTimerSetup (); > +} > + > +/** > + This function retrieves the period of timer interrupts in 100ns units, > + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod > + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is > + returned, then the timer is currently disabled. > + > + @param This The EFI_TIMER_ARCH_PROTOCOL instance. > + @param TimerPeriod A pointer to the timer period to retrieve in > + 100ns units. If 0 is returned, then the timer is > + currently disabled. > + > + > + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. > + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. > + > +**/ > +EFI_STATUS > +EFIAPI > +WatchdogTimerGetPeriod ( > + IN CONST EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, > + OUT UINT64 *TimerPeriod > + ) > +{ > + if (TimerPeriod == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *TimerPeriod = ((TIME_UNITS_PER_SECOND / ArmGenericTimerGetTimerFreq ()) * > mNumTimerTicks); > + > + return EFI_SUCCESS; > +} > + > +/** > + Interface structure for the Watchdog Architectural Protocol. > + > + @par Protocol Description: > + This protocol provides a service to set the amount of time to wait > + before firing the Watchdog timer, and it also provides a service to > + register a handler that is invoked when the Watchdog timer fires. > + > + @par When the Watchdog timer fires, control will be passed to a handler > + if one has been registered. If no handler has been registered, > + or the registered handler returns, then the system will be > + reset by calling the Runtime Service ResetSystem(). > + > + @param RegisterHandler > + Registers a handler that will be called each time the > + Watchdogtimer interrupt fires. TimerPeriod defines the minimum > + time between timer interrupts, so TimerPeriod will also > + be the minimum time between calls to the registered > + handler. > + NOTE: If the Watchdog resets the system in hardware, then > + this function will not have any chance of executing. > + > + @param SetTimerPeriod > + Sets the period of the timer interrupt in 100ns units. > + This function is optional, and may return EFI_UNSUPPORTED. > + If this function is supported, then the timer period will > + be rounded up to the nearest supported timer period. > + > + @param GetTimerPeriod > + Retrieves the period of the timer interrupt in 100ns units. > + > +**/ > +STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL gWatchdogTimer = { > + (EFI_WATCHDOG_TIMER_REGISTER_HANDLER)WatchdogTimerRegisterHandler, > + (EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD)WatchdogTimerSetPeriod, > + (EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD)WatchdogTimerGetPeriod > +}; > + > +EFI_STATUS > +EFIAPI > +WatchdogTimerInstallProtocol ( > + EFI_WATCHDOG_TIMER_ARCH_PROTOCOL **WatchdogTimerProtocol > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE Handle; > + EFI_TPL CurrentTpl; > + > + /* Make sure the Watchdog Timer Architectural Protocol has not been > installed > + in the system yet. > + This will avoid conflicts with the universal Watchdog */ > + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, > &gEfiWatchdogTimerArchProtocolGuid); > + > + ASSERT (ArmGenericTimerGetTimerFreq () != 0); > + > + /* Install interrupt handler */ > + Status = gBS->LocateProtocol ( > + &gHardwareInterrupt2ProtocolGuid, > + NULL, > + (VOID **)&mInterruptProtocol > + ); > + ASSERT_EFI_ERROR (Status); > + > + /* > + * We don't want to be interrupted while registering Watchdog interrupt > source as the interrupt > + * may be trigger in the middle because the interrupt line already enabled > in the EL3. > + */ > + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); > + > + Status = mInterruptProtocol->RegisterInterruptSource ( > + mInterruptProtocol, > + WS0_INTERRUPT_SOURCE, > + WatchdogTimerInterruptHandler > + ); > + ASSERT_EFI_ERROR (Status); > + > + /* Don't enable interrupt until FailSafe off */ > + mInterruptWS0Enabled = FALSE; > + Status = mInterruptProtocol->DisableInterruptSource ( > + mInterruptProtocol, > + WS0_INTERRUPT_SOURCE > + ); > + ASSERT_EFI_ERROR (Status); > + > + gBS->RestoreTPL (CurrentTpl); > + > + Status = mInterruptProtocol->SetTriggerType ( > + mInterruptProtocol, > + WS0_INTERRUPT_SOURCE, > + EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH > + ); > + ASSERT_EFI_ERROR (Status); > + > + /* Install the Timer Architectural Protocol onto a new handle */ > + Handle = NULL; > + Status = gBS->InstallMultipleProtocolInterfaces ( > + &Handle, > + &gEfiWatchdogTimerArchProtocolGuid, > + &gWatchdogTimer, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + > + mNumTimerTicks = 0; > + > + if (WatchdogTimerProtocol != NULL) { > + *WatchdogTimerProtocol = &gWatchdogTimer; > + } > + > + return Status; > +} > -- > 2.17.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#76085): https://edk2.groups.io/g/devel/message/76085 Mute This Topic: https://groups.io/mt/83097098/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-