]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / WatchdogTimerDxe / WatchdogTimer.c
1 /** @file
2 Implementation of Watchdog Timer Architectural Protocol using UEFI APIs.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "WatchdogTimer.h"
10
11 //
12 // Handle for the Watchdog Timer Architectural Protocol instance produced by this driver
13 //
14 EFI_HANDLE mWatchdogTimerHandle = NULL;
15
16 //
17 // The Watchdog Timer Architectural Protocol instance produced by this driver
18 //
19 EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = {
20 WatchdogTimerDriverRegisterHandler,
21 WatchdogTimerDriverSetTimerPeriod,
22 WatchdogTimerDriverGetTimerPeriod
23 };
24
25 //
26 // The watchdog timer period in 100 ns units
27 //
28 UINT64 mWatchdogTimerPeriod = 0;
29
30 //
31 // The notification function to call if the watchdig timer fires
32 //
33 EFI_WATCHDOG_TIMER_NOTIFY mWatchdogTimerNotifyFunction = NULL;
34
35 //
36 // The one-shot timer event that is armed when the watchdog timer is enabled
37 //
38 EFI_EVENT mWatchdogTimerEvent;
39
40
41 /**
42 Notification function that is called if the watchdog timer is fired.
43
44 Notification function for the one-shot timer event that was signaled
45 when the watchdog timer expired. If a handler has been registered with
46 the Watchdog Timer Architectural Protocol, then that handler is called
47 passing in the time period that has passed that cause the watchdog timer
48 to fire. Then, a call to the Runtime Service ResetSystem() is made to
49 reset the platform.
50
51 @param Timer The one-shot timer event that was signaled when the
52 watchdog timer expired.
53 @param Context The context that was registered when the event Timer was created.
54
55 **/
56 VOID
57 EFIAPI
58 WatchdogTimerDriverExpires (
59 IN EFI_EVENT Timer,
60 IN VOID *Context
61 )
62 {
63 REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_MINOR, (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_TIMER_EXPIRED));
64
65 //
66 // If a notification function has been registered, then call it
67 //
68 if (mWatchdogTimerNotifyFunction != NULL) {
69 mWatchdogTimerNotifyFunction (mWatchdogTimerPeriod);
70 }
71
72 DEBUG ((EFI_D_ERROR, "Watchdog Timer resetting system\n"));
73
74 //
75 // Reset the platform
76 //
77 gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, 0, NULL);
78 }
79
80
81 /**
82 Registers a handler that is to be invoked when the watchdog timer fires.
83
84 This function registers a handler that is to be invoked when the watchdog
85 timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the
86 Runtime Service ResetSystem() when the watchdog timer fires. If a
87 NotifyFunction is registered, then the NotifyFunction will be called before
88 the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then
89 the watchdog handler is unregistered. If a watchdog handler is registered,
90 then EFI_SUCCESS is returned. If an attempt is made to register a handler
91 when a handler is already registered, then EFI_ALREADY_STARTED is returned.
92 If an attempt is made to uninstall a handler when a handler is not installed,
93 then return EFI_INVALID_PARAMETER.
94
95 @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
96 @param NotifyFunction The function to call when the watchdog timer fires. If this
97 is NULL, then the handler will be unregistered.
98
99 @retval EFI_SUCCESS The watchdog timer handler was registered or unregistered.
100 @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already registered.
101 @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not previously registered.
102
103 **/
104 EFI_STATUS
105 EFIAPI
106 WatchdogTimerDriverRegisterHandler (
107 IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
108 IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
109 )
110 {
111 //
112 // If NotifyFunction is NULL, and a handler was not previously registered,
113 // return EFI_INVALID_PARAMETER.
114 //
115 if (NotifyFunction == NULL && mWatchdogTimerNotifyFunction == NULL) {
116 return EFI_INVALID_PARAMETER;
117 }
118 //
119 // If NotifyFunction is not NULL, and a handler is already registered,
120 // return EFI_ALREADY_STARTED.
121 //
122 if (NotifyFunction != NULL && mWatchdogTimerNotifyFunction != NULL) {
123 return EFI_ALREADY_STARTED;
124 }
125
126 mWatchdogTimerNotifyFunction = NotifyFunction;
127
128 return EFI_SUCCESS;
129 }
130
131 /**
132 Sets the amount of time in the future to fire the watchdog timer.
133
134 This function sets the amount of time to wait before firing the watchdog
135 timer to TimerPeriod 100 ns units. If TimerPeriod is 0, then the watchdog
136 timer is disabled.
137
138 @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
139 @param TimerPeriod The amount of time in 100 ns units to wait before the watchdog
140 timer is fired. If TimerPeriod is zero, then the watchdog
141 timer is disabled.
142
143 @retval EFI_SUCCESS The watchdog timer has been programmed to fire in Time
144 100 ns units.
145 @retval EFI_DEVICE_ERROR A watchdog timer could not be programmed due to a device
146 error.
147
148 **/
149 EFI_STATUS
150 EFIAPI
151 WatchdogTimerDriverSetTimerPeriod (
152 IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
153 IN UINT64 TimerPeriod
154 )
155 {
156 mWatchdogTimerPeriod = TimerPeriod;
157
158 return gBS->SetTimer (
159 mWatchdogTimerEvent,
160 (mWatchdogTimerPeriod == 0) ? TimerCancel : TimerRelative,
161 mWatchdogTimerPeriod
162 );
163 }
164
165 /**
166 Retrieves the amount of time in 100 ns units that the system will wait before firing the watchdog timer.
167
168 This function retrieves the amount of time the system will wait before firing
169 the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS
170 is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned.
171
172 @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
173 @param TimerPeriod A pointer to the amount of time in 100 ns units that the system
174 will wait before the watchdog timer is fired. If TimerPeriod of
175 zero is returned, then the watchdog timer is disabled.
176
177 @retval EFI_SUCCESS The amount of time that the system will wait before
178 firing the watchdog timer was returned in TimerPeriod.
179 @retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
180
181 **/
182 EFI_STATUS
183 EFIAPI
184 WatchdogTimerDriverGetTimerPeriod (
185 IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
186 IN UINT64 *TimerPeriod
187 )
188 {
189 if (TimerPeriod == NULL) {
190 return EFI_INVALID_PARAMETER;
191 }
192
193 *TimerPeriod = mWatchdogTimerPeriod;
194
195 return EFI_SUCCESS;
196 }
197
198 /**
199 Entry point of the Watchdog Timer Architectural Protocol driver.
200
201 @param ImageHandle The image handle of this driver.
202 @param SystemTable The pointer of EFI_SYSTEM_TABLE.
203
204 @retval EFI_SUCCESS Watchdog Timer Architectural Protocol successfully installed.
205
206 **/
207 EFI_STATUS
208 EFIAPI
209 WatchdogTimerDriverInitialize (
210 IN EFI_HANDLE ImageHandle,
211 IN EFI_SYSTEM_TABLE *SystemTable
212 )
213 {
214 EFI_STATUS Status;
215
216 //
217 // Make sure the Watchdog Timer Architectural Protocol has not been installed in the system yet.
218 //
219 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);
220
221 //
222 // Create the timer event to implement a simple watchdog timer
223 //
224 Status = gBS->CreateEvent (
225 EVT_TIMER | EVT_NOTIFY_SIGNAL,
226 TPL_NOTIFY,
227 WatchdogTimerDriverExpires,
228 NULL,
229 &mWatchdogTimerEvent
230 );
231 ASSERT_EFI_ERROR (Status);
232
233 //
234 // Install the Watchdog Timer Arch Protocol onto a new handle
235 //
236 Status = gBS->InstallMultipleProtocolInterfaces (
237 &mWatchdogTimerHandle,
238 &gEfiWatchdogTimerArchProtocolGuid,
239 &mWatchdogTimer,
240 NULL
241 );
242 ASSERT_EFI_ERROR (Status);
243
244 return EFI_SUCCESS;
245 }