blob: 87ca6c5b0b73037b2c6556c71c3ad24cf1b2a75c [file] [log] [blame]
Tom Rinif739fcd2018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +02002/*
3 * EFI watchdog
4 *
5 * Copyright (c) 2017 Heinrich Schuchardt
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +02006 */
7
8#include <common.h>
9#include <efi_loader.h>
10
11/* Conversion factor from seconds to multiples of 100ns */
12#define EFI_SECONDS_TO_100NS 10000000ULL
13
14static struct efi_event *watchdog_timer_event;
15
Heinrich Schuchardt540faca2020-04-10 17:51:56 +020016/**
17 * efi_watchdog_timer_notify() - resets system upon watchdog event
18 *
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020019 * Reset the system when the watchdog event is notified.
20 *
21 * @event: the watchdog event
22 * @context: not used
23 */
24static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event,
25 void *context)
26{
27 EFI_ENTRY("%p, %p", event, context);
28
29 printf("\nEFI: Watchdog timeout\n");
Heinrich Schuchardtaec7c092021-09-09 07:47:05 +020030 do_reset(NULL, 0, 0, NULL);
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020031
32 EFI_EXIT(EFI_UNSUPPORTED);
33}
34
Heinrich Schuchardt540faca2020-04-10 17:51:56 +020035/**
36 * efi_set_watchdog() - resets the watchdog timer
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020037 *
38 * This function is used by the SetWatchdogTimer service.
39 *
40 * @timeout: seconds before reset by watchdog
Heinrich Schuchardt540faca2020-04-10 17:51:56 +020041 * Return: status code
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020042 */
43efi_status_t efi_set_watchdog(unsigned long timeout)
44{
45 efi_status_t r;
46
47 if (timeout)
48 /* Reset watchdog */
49 r = efi_set_timer(watchdog_timer_event, EFI_TIMER_RELATIVE,
50 EFI_SECONDS_TO_100NS * timeout);
51 else
52 /* Deactivate watchdog */
53 r = efi_set_timer(watchdog_timer_event, EFI_TIMER_STOP, 0);
54 return r;
55}
56
Heinrich Schuchardt540faca2020-04-10 17:51:56 +020057/**
58 * efi_watchdog_register() - initializes the EFI watchdog
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020059 *
Heinrich Schuchardt540faca2020-04-10 17:51:56 +020060 * This function is called by efi_init_obj_list().
61 *
62 * Return: status code
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020063 */
Heinrich Schuchardtd7b181d2018-03-03 15:28:57 +010064efi_status_t efi_watchdog_register(void)
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020065{
66 efi_status_t r;
67
68 /*
69 * Create a timer event.
70 */
71 r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
Heinrich Schuchardtb095f3c2018-02-18 15:17:52 +010072 efi_watchdog_timer_notify, NULL, NULL,
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020073 &watchdog_timer_event);
74 if (r != EFI_SUCCESS) {
75 printf("ERROR: Failed to register watchdog event\n");
76 return r;
77 }
78 /*
79 * The UEFI standard requires that the watchdog timer is set to five
80 * minutes when invoking an EFI boot option.
81 *
82 * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A
83 * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer
84 */
85 r = efi_set_watchdog(300);
86 if (r != EFI_SUCCESS) {
87 printf("ERROR: Failed to set watchdog timer\n");
88 return r;
89 }
Heinrich Schuchardtd7b181d2018-03-03 15:28:57 +010090 return EFI_SUCCESS;
Heinrich Schuchardtb3d60902017-10-18 18:13:04 +020091}