]>
Commit | Line | Data |
---|---|---|
b3d60900 HS |
1 | /* |
2 | * EFI watchdog | |
3 | * | |
4 | * Copyright (c) 2017 Heinrich Schuchardt | |
5 | * | |
6 | * SPDX-License-Identifier: GPL-2.0+ | |
7 | */ | |
8 | ||
9 | #include <common.h> | |
10 | #include <efi_loader.h> | |
11 | ||
12 | /* Conversion factor from seconds to multiples of 100ns */ | |
13 | #define EFI_SECONDS_TO_100NS 10000000ULL | |
14 | ||
15 | static struct efi_event *watchdog_timer_event; | |
16 | ||
17 | /* | |
18 | * Reset the system when the watchdog event is notified. | |
19 | * | |
20 | * @event: the watchdog event | |
21 | * @context: not used | |
22 | */ | |
23 | static 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 | EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD, | |
30 | EFI_SUCCESS, 0, NULL)); | |
31 | ||
32 | EFI_EXIT(EFI_UNSUPPORTED); | |
33 | } | |
34 | ||
35 | /* | |
36 | * Reset the watchdog timer. | |
37 | * | |
38 | * This function is used by the SetWatchdogTimer service. | |
39 | * | |
40 | * @timeout: seconds before reset by watchdog | |
41 | * @return: status code | |
42 | */ | |
43 | efi_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 | ||
57 | /* | |
58 | * Initialize the EFI watchdog. | |
59 | * | |
60 | * This function is called by efi_init_obj_list() | |
61 | */ | |
62 | int efi_watchdog_register(void) | |
63 | { | |
64 | efi_status_t r; | |
65 | ||
66 | /* | |
67 | * Create a timer event. | |
68 | */ | |
69 | r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, | |
70 | efi_watchdog_timer_notify, NULL, | |
71 | &watchdog_timer_event); | |
72 | if (r != EFI_SUCCESS) { | |
73 | printf("ERROR: Failed to register watchdog event\n"); | |
74 | return r; | |
75 | } | |
76 | /* | |
77 | * The UEFI standard requires that the watchdog timer is set to five | |
78 | * minutes when invoking an EFI boot option. | |
79 | * | |
80 | * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A | |
81 | * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer | |
82 | */ | |
83 | r = efi_set_watchdog(300); | |
84 | if (r != EFI_SUCCESS) { | |
85 | printf("ERROR: Failed to set watchdog timer\n"); | |
86 | return r; | |
87 | } | |
88 | return 0; | |
89 | } |