1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * EFI watchdog 4 * 5 * Copyright (c) 2017 Heinrich Schuchardt 6 */ 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 14 static struct efi_event *watchdog_timer_event; 15 16 /* 17 * Reset the system when the watchdog event is notified. 18 * 19 * @event: the watchdog event 20 * @context: not used 21 */ 22 static void EFIAPI efi_watchdog_timer_notify(struct efi_event *event, 23 void *context) 24 { 25 EFI_ENTRY("%p, %p", event, context); 26 27 printf("\nEFI: Watchdog timeout\n"); 28 EFI_CALL_VOID(efi_runtime_services.reset_system(EFI_RESET_COLD, 29 EFI_SUCCESS, 0, NULL)); 30 31 EFI_EXIT(EFI_UNSUPPORTED); 32 } 33 34 /* 35 * Reset 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 */ 42 efi_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 * Initialize the EFI watchdog. 58 * 59 * This function is called by efi_init_obj_list() 60 */ 61 efi_status_t efi_watchdog_register(void) 62 { 63 efi_status_t r; 64 65 /* 66 * Create a timer event. 67 */ 68 r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, 69 efi_watchdog_timer_notify, NULL, NULL, 70 &watchdog_timer_event); 71 if (r != EFI_SUCCESS) { 72 printf("ERROR: Failed to register watchdog event\n"); 73 return r; 74 } 75 /* 76 * The UEFI standard requires that the watchdog timer is set to five 77 * minutes when invoking an EFI boot option. 78 * 79 * Unified Extensible Firmware Interface (UEFI), version 2.7 Errata A 80 * 7.5. Miscellaneous Boot Services - EFI_BOOT_SERVICES.SetWatchdogTimer 81 */ 82 r = efi_set_watchdog(300); 83 if (r != EFI_SUCCESS) { 84 printf("ERROR: Failed to set watchdog timer\n"); 85 return r; 86 } 87 return EFI_SUCCESS; 88 } 89