1// SPDX-License-Identifier: GPL-2.0+
2/*
3 *  EFI watchdog
4 *
5 *  Copyright (c) 2017 Heinrich Schuchardt
6 */
7
8#include <efi_loader.h>
9
10/* Conversion factor from seconds to multiples of 100ns */
11#define EFI_SECONDS_TO_100NS 10000000ULL
12
13static struct efi_event *watchdog_timer_event;
14
15/**
16 * efi_watchdog_timer_notify() - resets system upon watchdog event
17 *
18 * Reset the system when the watchdog event is notified.
19 *
20 * @event:	the watchdog event
21 * @context:	not used
22 */
23static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event,
24					     void *context)
25{
26	EFI_ENTRY("%p, %p", event, context);
27
28	printf("\nEFI: Watchdog timeout\n");
29	do_reset(NULL, 0, 0, NULL);
30
31	EFI_EXIT(EFI_UNSUPPORTED);
32}
33
34/**
35 * efi_set_watchdog() - resets the watchdog timer
36 *
37 * This function is used by the SetWatchdogTimer service.
38 *
39 * @timeout:		seconds before reset by watchdog
40 * Return:		status code
41 */
42efi_status_t efi_set_watchdog(unsigned long timeout)
43{
44	efi_status_t r;
45
46	if (timeout)
47		/* Reset watchdog */
48		r = efi_set_timer(watchdog_timer_event, EFI_TIMER_RELATIVE,
49				  EFI_SECONDS_TO_100NS * timeout);
50	else
51		/* Deactivate watchdog */
52		r = efi_set_timer(watchdog_timer_event, EFI_TIMER_STOP, 0);
53	return r;
54}
55
56/**
57 * efi_watchdog_register() - initializes the EFI watchdog
58 *
59 * This function is called by efi_init_obj_list().
60 *
61 * Return:	status code
62 */
63efi_status_t efi_watchdog_register(void)
64{
65	efi_status_t r;
66
67	/*
68	 * Create a timer event.
69	 */
70	r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
71			     efi_watchdog_timer_notify, NULL, NULL,
72			     &watchdog_timer_event);
73	if (r != EFI_SUCCESS) {
74		printf("ERROR: Failed to register watchdog event\n");
75		return r;
76	}
77
78	return EFI_SUCCESS;
79}
80