de4c8a30 |
1 | /*++\r |
2 | \r |
3 | Copyright (c) 2006, Intel Corporation\r |
4 | All rights reserved. This program and the accompanying materials\r |
5 | are licensed and made available under the terms and conditions of the BSD License\r |
6 | which accompanies this distribution. The full text of the license may be found at\r |
7 | http://opensource.org/licenses/bsd-license.php\r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
11 | \r |
12 | Module Name:\r |
13 | \r |
14 | WatchDogTimer.c\r |
15 | \r |
16 | Abstract:\r |
17 | \r |
18 | Generic watchdog timer implemenetation using EFI APIs\r |
19 | \r |
20 | Revision History\r |
21 | \r |
22 | --*/\r |
23 | \r |
de4c8a30 |
24 | #include "WatchDogTimer.h"\r |
25 | \r |
26 | //\r |
27 | // Handle for the Watchdog Timer Architectural Protocol instance produced by this driver\r |
28 | //\r |
29 | EFI_HANDLE mWatchdogTimerHandle = NULL;\r |
30 | \r |
31 | //\r |
32 | // The Watchdog Timer Architectural Protocol instance produced by this driver\r |
33 | //\r |
34 | EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = {\r |
35 | WatchdogTimerDriverRegisterHandler,\r |
36 | WatchdogTimerDriverSetTimerPeriod,\r |
37 | WatchdogTimerDriverGetTimerPeriod\r |
38 | };\r |
39 | \r |
40 | //\r |
41 | // The watchdog timer period in 100 nS units\r |
42 | //\r |
43 | UINT64 mWatchdogTimerPeriod = 0;\r |
44 | \r |
45 | //\r |
46 | // The notification function to call if the watchdig timer fires\r |
47 | //\r |
48 | EFI_WATCHDOG_TIMER_NOTIFY mWatchdogTimerNotifyFunction = NULL;\r |
49 | \r |
50 | //\r |
51 | // The one-shot timer event that is armed when the watchdog timer is enabled\r |
52 | //\r |
53 | EFI_EVENT mWatchdogTimerEvent;\r |
54 | \r |
55 | //\r |
56 | // Worker Functions\r |
57 | //\r |
58 | STATIC\r |
59 | VOID\r |
60 | EFIAPI\r |
61 | WatchdogTimerDriverExpires (\r |
62 | IN EFI_EVENT Timer,\r |
63 | IN VOID *Context\r |
64 | )\r |
65 | /*++\r |
66 | \r |
67 | Routine Description:\r |
68 | \r |
69 | Notification function that is called if the watchdog timer is fired. If a\r |
70 | handler has been registered with the Watchdog Timer Architectural Protocol,\r |
71 | then that handler is called passing in the time period that has passed that\r |
72 | cause the watchdog timer to fire. Then, a call to the Runtime Service\r |
73 | ResetSystem() is made to reset the platform.\r |
74 | \r |
75 | Arguments:\r |
76 | \r |
77 | Timer - The one-shot timer event that was signaled when the watchdog timer\r |
78 | expired.\r |
79 | \r |
80 | Context - The context that was registered when the event Timer was created.\r |
81 | \r |
82 | Returns:\r |
83 | \r |
84 | None.\r |
85 | \r |
86 | --*/\r |
87 | {\r |
ba237732 |
88 | REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_MINOR, PcdGet32 (PcdStatusCodeValueEfiWatchDogTimerExpired));\r |
de4c8a30 |
89 | \r |
90 | //\r |
91 | // If a notification function has been registered, then call it\r |
92 | //\r |
93 | if (mWatchdogTimerNotifyFunction != NULL) {\r |
94 | mWatchdogTimerNotifyFunction (mWatchdogTimerPeriod);\r |
95 | }\r |
96 | //\r |
97 | // Reset the platform\r |
98 | //\r |
99 | gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, 0, NULL);\r |
100 | }\r |
101 | \r |
ba237732 |
102 | \r |
de4c8a30 |
103 | EFI_STATUS\r |
104 | EFIAPI\r |
105 | WatchdogTimerDriverRegisterHandler (\r |
106 | IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,\r |
107 | IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction\r |
108 | )\r |
109 | /*++\r |
110 | \r |
111 | Routine Description:\r |
112 | \r |
113 | This function registers a handler that is to be invoked when the watchdog\r |
114 | timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the\r |
115 | Runtime Service ResetSystem() when the watchdog timer fires. If a\r |
116 | NotifyFunction is registered, then the NotifyFunction will be called before\r |
117 | the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then\r |
118 | the watchdog handler is unregistered. If a watchdog handler is registered,\r |
119 | then EFI_SUCCESS is returned. If an attempt is made to register a handler\r |
120 | when a handler is already registered, then EFI_ALREADY_STARTED is returned.\r |
121 | If an attempt is made to uninstall a handler when a handler is not installed,\r |
122 | then return EFI_INVALID_PARAMETER.\r |
123 | \r |
124 | Arguments:\r |
125 | \r |
126 | This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.\r |
127 | \r |
128 | NotifyFunction - The function to call when the watchdog timer fires. If this\r |
129 | is NULL, then the handler will be unregistered.\r |
130 | \r |
131 | Returns:\r |
132 | \r |
133 | EFI_SUCCESS - The watchdog timer handler was registered or\r |
134 | unregistered.\r |
135 | \r |
136 | EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already\r |
137 | registered.\r |
138 | \r |
139 | EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not\r |
140 | previously registered.\r |
141 | \r |
142 | --*/\r |
143 | {\r |
144 | if (NotifyFunction == NULL && mWatchdogTimerNotifyFunction == NULL) {\r |
145 | return EFI_INVALID_PARAMETER;\r |
146 | }\r |
147 | \r |
148 | if (NotifyFunction != NULL && mWatchdogTimerNotifyFunction != NULL) {\r |
149 | return EFI_ALREADY_STARTED;\r |
150 | }\r |
151 | \r |
152 | mWatchdogTimerNotifyFunction = NotifyFunction;\r |
153 | \r |
154 | return EFI_SUCCESS;\r |
155 | }\r |
156 | \r |
157 | EFI_STATUS\r |
158 | EFIAPI\r |
159 | WatchdogTimerDriverSetTimerPeriod (\r |
160 | IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,\r |
161 | IN UINT64 TimerPeriod\r |
162 | )\r |
163 | /*++\r |
164 | \r |
165 | Routine Description:\r |
166 | \r |
167 | This function sets the amount of time to wait before firing the watchdog\r |
168 | timer to TimerPeriod 100 nS units. If TimerPeriod is 0, then the watchdog\r |
169 | timer is disabled.\r |
170 | \r |
171 | Arguments:\r |
172 | \r |
173 | This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.\r |
174 | \r |
175 | TimerPeriod - The amount of time in 100 nS units to wait before the watchdog\r |
176 | timer is fired. If TimerPeriod is zero, then the watchdog\r |
177 | timer is disabled.\r |
178 | \r |
179 | Returns:\r |
180 | \r |
181 | EFI_SUCCESS - The watchdog timer has been programmed to fire in Time\r |
182 | 100 nS units.\r |
183 | \r |
184 | EFI_DEVICE_ERROR - A watchdog timer could not be programmed due to a device\r |
185 | error.\r |
186 | \r |
187 | --*/\r |
188 | {\r |
189 | mWatchdogTimerPeriod = TimerPeriod;\r |
190 | \r |
191 | return gBS->SetTimer (\r |
192 | mWatchdogTimerEvent,\r |
193 | (mWatchdogTimerPeriod == 0) ? TimerCancel : TimerRelative,\r |
194 | mWatchdogTimerPeriod\r |
195 | );\r |
196 | }\r |
197 | \r |
198 | EFI_STATUS\r |
199 | EFIAPI\r |
200 | WatchdogTimerDriverGetTimerPeriod (\r |
201 | IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,\r |
202 | IN UINT64 *TimerPeriod\r |
203 | )\r |
204 | /*++\r |
205 | \r |
206 | Routine Description:\r |
207 | \r |
208 | This function retrieves the amount of time the system will wait before firing\r |
209 | the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS\r |
210 | is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned.\r |
211 | \r |
212 | Arguments:\r |
213 | \r |
214 | This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.\r |
215 | \r |
216 | TimerPeriod - A pointer to the amount of time in 100 nS units that the system\r |
217 | will wait before the watchdog timer is fired. If TimerPeriod of\r |
218 | zero is returned, then the watchdog timer is disabled.\r |
219 | \r |
220 | Returns:\r |
221 | \r |
222 | EFI_SUCCESS - The amount of time that the system will wait before\r |
223 | firing the watchdog timer was returned in TimerPeriod.\r |
224 | \r |
225 | EFI_INVALID_PARAMETER - TimerPeriod is NULL.\r |
226 | \r |
227 | --*/\r |
228 | {\r |
229 | if (TimerPeriod == NULL) {\r |
230 | return EFI_INVALID_PARAMETER;\r |
231 | }\r |
232 | \r |
233 | *TimerPeriod = mWatchdogTimerPeriod;\r |
234 | \r |
235 | return EFI_SUCCESS;\r |
236 | }\r |
237 | \r |
238 | EFI_STATUS\r |
239 | EFIAPI\r |
240 | WatchdogTimerDriverInitialize (\r |
241 | IN EFI_HANDLE ImageHandle,\r |
242 | IN EFI_SYSTEM_TABLE *SystemTable\r |
243 | )\r |
244 | /*++\r |
245 | \r |
246 | Routine Description:\r |
247 | \r |
248 | Initialize the Watchdog Timer Architectural Protocol driver\r |
249 | \r |
250 | Arguments:\r |
251 | \r |
252 | ImageHandle - ImageHandle of the loaded driver\r |
253 | \r |
254 | SystemTable - Pointer to the System Table\r |
255 | \r |
256 | Returns:\r |
257 | \r |
258 | EFI_SUCCESS - Timer Architectural Protocol created\r |
259 | \r |
260 | EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver.\r |
261 | \r |
262 | EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver.\r |
263 | \r |
264 | --*/\r |
265 | {\r |
266 | EFI_STATUS Status;\r |
267 | \r |
de4c8a30 |
268 | //\r |
269 | // Make sure the Watchdog Timer Architectural Protocol is not already installed in the system\r |
270 | //\r |
271 | ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);\r |
272 | \r |
273 | //\r |
274 | // Create the timer event used to implement a simple watchdog timer\r |
275 | //\r |
276 | Status = gBS->CreateEvent (\r |
277 | EVT_TIMER | EVT_NOTIFY_SIGNAL,\r |
278 | TPL_NOTIFY,\r |
279 | WatchdogTimerDriverExpires,\r |
280 | NULL,\r |
281 | &mWatchdogTimerEvent\r |
282 | );\r |
283 | ASSERT_EFI_ERROR (Status);\r |
284 | \r |
285 | //\r |
286 | // Install the Watchdog Timer Arch Protocol onto a new handle\r |
287 | //\r |
288 | Status = gBS->InstallMultipleProtocolInterfaces (\r |
289 | &mWatchdogTimerHandle,\r |
290 | &gEfiWatchdogTimerArchProtocolGuid,\r |
291 | &mWatchdogTimer,\r |
292 | NULL\r |
293 | );\r |
294 | ASSERT_EFI_ERROR (Status);\r |
295 | \r |
de4c8a30 |
296 | return Status;\r |
297 | }\r |