iPXE
efi_watchdog.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27/**
28 * @file
29 *
30 * EFI watchdog holdoff timer
31 *
32 */
33
34#include <errno.h>
35#include <string.h>
36#include <ipxe/retry.h>
37#include <ipxe/timer.h>
38#include <ipxe/init.h>
39#include <ipxe/efi/efi.h>
41
42/** Watchdog holdoff interval (in seconds) */
43#define WATCHDOG_HOLDOFF_SECS 10
44
45/** Watchdog timeout (in seconds) */
46#define WATCHDOG_TIMEOUT_SECS ( 5 * 60 )
47
48/** Watchdog code (to be logged on watchdog timeout) */
49#define WATCHDOG_CODE 0x6950584544454144ULL
50
51/** Watchdog data (to be logged on watchdog timeout) */
52#define WATCHDOG_DATA L"iPXE";
53
54/**
55 * Hold off watchdog timer
56 *
57 * @v retry Retry timer
58 * @v over Failure indicator
59 */
61 int over __unused ) {
62 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
63 static CHAR16 data[] = WATCHDOG_DATA;
64 EFI_STATUS efirc;
65 int rc;
66
67 DBGC2 ( timer, "EFI holding off watchdog timer\n" );
68
69 /* Restart this holdoff timer */
71
72 /* Reset watchdog timer */
73 if ( ( efirc = bs->SetWatchdogTimer ( WATCHDOG_TIMEOUT_SECS,
74 WATCHDOG_CODE, sizeof ( data ),
75 data ) ) != 0 ) {
76 rc = -EEFI ( efirc );
77 DBGC ( timer, "EFI could not set watchdog timer: %s\n",
78 strerror ( rc ) );
79 return;
80 }
81}
82
83/** Watchdog holdoff timer */
85
86/**
87 * Disable watching when shutting down to boot an operating system
88 *
89 * @v booting System is shutting down for OS boot
90 */
91static void efi_watchdog_shutdown ( int booting ) {
92 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
93 EFI_STATUS efirc;
94 int rc;
95
96 /* If we are shutting down to boot an operating system, then
97 * disable the boot services watchdog timer. The UEFI
98 * specification mandates that the platform firmware does this
99 * as part of the ExitBootServices() call, but some platforms
100 * (e.g. Hyper-V) are observed to occasionally forget to do
101 * so, resulting in a reboot approximately five minutes after
102 * starting the operating system.
103 */
104 if ( booting &&
105 ( ( efirc = bs->SetWatchdogTimer ( 0, 0, 0, NULL ) ) != 0 ) ) {
106 rc = -EEFI ( efirc );
107 DBGC ( &efi_watchdog, "EFI could not disable watchdog timer: "
108 "%s\n", strerror ( rc ) );
109 /* Nothing we can do */
110 }
111}
112
113/** Watchdog startup/shutdown function */
114struct startup_fn efi_watchdog_startup_fn __startup_fn ( STARTUP_EARLY ) = {
115 .name = "efi_watchdog",
116 .shutdown = efi_watchdog_shutdown,
117};
unsigned short CHAR16
2-byte Character.
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define WATCHDOG_DATA
Watchdog data (to be logged on watchdog timeout)
#define WATCHDOG_TIMEOUT_SECS
Watchdog timeout (in seconds)
#define WATCHDOG_HOLDOFF_SECS
Watchdog holdoff interval (in seconds)
static void efi_watchdog_expired(struct retry_timer *timer, int over __unused)
Hold off watchdog timer.
static void efi_watchdog_shutdown(int booting)
Disable watching when shutting down to boot an operating system.
struct retry_timer efi_watchdog
Watchdog holdoff timer.
#define WATCHDOG_CODE
Watchdog code (to be logged on watchdog timeout)
EFI watchdog holdoff timer.
uint8_t data[48]
Additional event data.
Definition ena.h:11
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define STARTUP_EARLY
Early startup.
Definition init.h:64
EFI API.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:175
EFI_SYSTEM_TABLE * efi_systab
iPXE timers
#define TICKS_PER_SEC
Number of ticks per second.
Definition timer.h:16
String functions.
#define __startup_fn(startup_order)
Declare a startup/shutdown function.
Definition init.h:53
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
Retry timers.
#define TIMER_INIT(expired_fn)
Initialise a static timer.
Definition retry.h:83
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_SET_WATCHDOG_TIMER SetWatchdogTimer
Definition UefiSpec.h:1989
A retry timer.
Definition retry.h:22
A startup/shutdown function.
Definition init.h:43
A timer.
Definition timer.h:29