edk2/MdeModulePkg/Universal/WatchDogTimerDxe:
[people/mcb30/edk2.git] / edk2 / MdeModulePkg / Universal / WatchdogTimerDxe / WatchDogTimer.c
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
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
88   REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_MINOR, PcdGet32 (PcdStatusCodeValueEfiWatchDogTimerExpired));\r
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
102 \r
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
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
296   return Status;\r
297 }\r