ArmPkg/GenericWatchdogDxe: implement RegisterHandler() method
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 18 Dec 2018 13:10:14 +0000 (14:10 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Thu, 20 Dec 2018 11:41:21 +0000 (12:41 +0100)
Even though UEFI does not appear to use it, let's implement the
complete PI watchdog protocol, including handler registration,
which will be invoked before the ResetSystem() runtime service
when the watchdog timer expires.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c

index 285727f..a1ef036 100644 (file)
@@ -42,6 +42,7 @@ STATIC UINTN mTimerFrequencyHz = 0;
 STATIC UINT64 mNumTimerTicks = 0;\r
 \r
 STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol;\r
+STATIC EFI_WATCHDOG_TIMER_NOTIFY        mWatchdogNotify;\r
 \r
 STATIC\r
 VOID\r
@@ -107,17 +108,25 @@ WatchdogInterruptHandler (
   )\r
 {\r
   STATIC CONST CHAR16 ResetString[]= L"The generic watchdog timer ran out.";\r
+  UINT64              TimerPeriod;\r
 \r
   WatchdogDisable ();\r
 \r
   mInterruptProtocol->EndOfInterrupt (mInterruptProtocol, Source);\r
 \r
-  gRT->ResetSystem (\r
-         EfiResetCold,\r
-         EFI_TIMEOUT,\r
-         StrSize (ResetString),\r
-         (VOID *) &ResetString\r
-         );\r
+  //\r
+  // The notify function should be called with the elapsed number of ticks\r
+  // since the watchdog was armed, which should exceed the timer period.\r
+  // We don't actually know the elapsed number of ticks, so let's return\r
+  // the timer period plus 1.\r
+  //\r
+  if (mWatchdogNotify != NULL) {\r
+    TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks);\r
+    mWatchdogNotify (TimerPeriod + 1);\r
+  }\r
+\r
+  gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, StrSize (ResetString),\r
+         (CHAR16 *)ResetString);\r
 \r
   // If we got here then the reset didn't work\r
   ASSERT (FALSE);\r
@@ -155,9 +164,16 @@ WatchdogRegisterHandler (
   IN EFI_WATCHDOG_TIMER_NOTIFY                NotifyFunction\r
   )\r
 {\r
-  // ERROR: This function is not supported.\r
-  // The watchdog will reset the board\r
-  return EFI_UNSUPPORTED;\r
+  if (mWatchdogNotify == NULL && NotifyFunction == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (mWatchdogNotify != NULL && NotifyFunction != NULL) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  mWatchdogNotify = NotifyFunction;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r