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 } 90