Add EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event for MonotonicCounter driver.
[mirror_edk2.git] / EdkModulePkg / Universal / MonotonicCounter / RuntimeDxe / MonotonicCounter.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 MonotonicCounter.c\r
15\r
16Abstract:\r
17\r
18 Produced the Monotonic Counter Services as defined in the DXE CIS\r
19\r
20Revision History:\r
21\r
22--*/\r
23\r
24#include "MonotonicCounter.h"\r
25\r
26//\r
27// The Monotonic Counter Handle\r
28//\r
29EFI_HANDLE mMonotonicCounterHandle = NULL;\r
30\r
31//\r
32// The current Monotonic count value\r
33//\r
34UINT64 mEfiMtc;\r
35\r
878ddf1f 36//\r
37// Event to use to update the Mtc's high part when wrapping\r
38//\r
39EFI_EVENT mEfiMtcEvent;\r
40\r
41//\r
42// EfiMtcName - Variable name of the MTC value\r
43//\r
44CHAR16 *mEfiMtcName = (CHAR16 *) L"MTC";\r
45\r
46//\r
47// EfiMtcGuid - Guid of the MTC value\r
48//\r
49EFI_GUID mEfiMtcGuid = { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } };\r
50\r
51//\r
52// Worker functions\r
53//\r
54EFI_STATUS\r
55EFIAPI\r
56MonotonicCounterDriverGetNextMonotonicCount (\r
57 OUT UINT64 *Count\r
58 )\r
59/*++\r
60\r
61Routine Description:\r
62\r
63Arguments:\r
64\r
65Returns:\r
66\r
67--*/\r
68{\r
69 EFI_TPL OldTpl;\r
70\r
71 //\r
72 // Can not be called after ExitBootServices()\r
73 //\r
74 if (EfiAtRuntime ()) {\r
75 return EFI_UNSUPPORTED;\r
76 }\r
77 //\r
78 // Check input parameters\r
79 //\r
80 if (Count == NULL) {\r
81 return EFI_INVALID_PARAMETER;\r
82 }\r
83 //\r
84 // Update the monotonic counter with a lock\r
85 //\r
86 OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
87 *Count = mEfiMtc;\r
88 mEfiMtc++;\r
89 gBS->RestoreTPL (OldTpl);\r
90\r
91 //\r
92 // If the MSB bit of the low part toggled, then signal that the high\r
93 // part needs updated now\r
94 //\r
95 if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & 0x80000000) {\r
96 gBS->SignalEvent (mEfiMtcEvent);\r
97 }\r
98\r
99 return EFI_SUCCESS;\r
100}\r
101\r
2f23473f 102\r
103\r
104/**\r
105 Call back function on EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
106\r
107 Fixup internal data so that the driver is callable in EFI runtime \r
108 in virtual mode. Convert gRT to virtual address. gRT is from \r
109 UefiRuntimeServicesTableLib class. It is not fixed up by \r
110 UefiRuntimeServicesTableLib instance.\r
111\r
112 @param Event Event whose notification function is being invoked.\r
113 @param Context The context of the Notification context. Not used in\r
114 this call back function.\r
115\r
116**/\r
117VOID\r
118EFIAPI\r
119MonotonicCounterDriverSetVirtualAddressMap (\r
120 IN EFI_EVENT Event,\r
121 IN VOID *Context\r
122 )\r
123/*++\r
124\r
125Routine Description:\r
126\r
127Arguments:\r
128\r
129Returns:\r
130\r
131--*/\r
132{\r
133 gRT->ConvertPointer (0, (VOID **) &gRT);\r
134}\r
135\r
136\r
137\r
878ddf1f 138EFI_STATUS\r
139EFIAPI\r
140MonotonicCounterDriverGetNextHighMonotonicCount (\r
141 OUT UINT32 *HighCount\r
142 )\r
143/*++\r
144\r
145Routine Description:\r
146\r
147Arguments:\r
148\r
149Returns:\r
150\r
151--*/\r
152{\r
153 EFI_STATUS Status;\r
154 EFI_TPL OldTpl;\r
155\r
156 //\r
157 // Check input parameters\r
158 //\r
159 if (HighCount == NULL) {\r
160 return EFI_INVALID_PARAMETER;\r
161 }\r
162\r
163 if (!EfiAtRuntime ()) {\r
164 //\r
165 // Use a lock if called before ExitBootServices()\r
166 //\r
167 OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
168 *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1;\r
169 mEfiMtc = LShiftU64 (*HighCount, 32);\r
170 gBS->RestoreTPL (OldTpl);\r
171 } else {\r
172 *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1;\r
173 mEfiMtc = LShiftU64 (*HighCount, 32);\r
174 }\r
175 //\r
176 // Update the NvRam store to match the new high part\r
177 //\r
178 Status = gRT->SetVariable (\r
179 mEfiMtcName,\r
180 &mEfiMtcGuid,\r
181 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
182 sizeof (UINT32),\r
183 HighCount\r
184 );\r
185\r
186 return Status;\r
187}\r
188\r
189VOID\r
190EFIAPI\r
191EfiMtcEventHandler (\r
192 IN EFI_EVENT Event,\r
193 IN VOID *Context\r
194 )\r
195/*++\r
196\r
197Routine Description:\r
198\r
199 Monotonic count event handler. This handler updates the high monotonic count.\r
200\r
201Arguments:\r
202\r
203 Event The event to handle\r
204 Context The event context\r
205\r
206Returns:\r
207\r
208 EFI_SUCCESS The event has been handled properly \r
209 EFI_NOT_FOUND An error occurred updating the variable.\r
210\r
211--*/\r
212{\r
213 UINT32 HighCount;\r
214\r
215 MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount);\r
216}\r
217\r
218EFI_STATUS\r
219EFIAPI\r
220MonotonicCounterDriverInitialize (\r
221 IN EFI_HANDLE ImageHandle,\r
222 IN EFI_SYSTEM_TABLE *SystemTable\r
223 )\r
224/*++\r
225\r
226Routine Description:\r
227\r
228Arguments:\r
229 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
230\r
231Returns:\r
232\r
233--*/\r
234{\r
235 EFI_STATUS Status;\r
236 UINT32 HighCount;\r
237 UINTN BufferSize;\r
238\r
239 //\r
240 // Make sure the Monotonic Counter Architectural Protocol is not already installed in the system\r
241 //\r
242 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMonotonicCounterArchProtocolGuid);\r
243\r
244 //\r
245 // Initialize event to handle overflows\r
246 //\r
247 Status = gBS->CreateEvent (\r
248 EFI_EVENT_NOTIFY_SIGNAL,\r
249 EFI_TPL_CALLBACK,\r
250 EfiMtcEventHandler,\r
251 NULL,\r
252 &mEfiMtcEvent\r
253 );\r
254\r
255 ASSERT_EFI_ERROR (Status);\r
256\r
257 //\r
258 // Read the last high part\r
259 //\r
260 BufferSize = sizeof (UINT32);\r
261 Status = gRT->GetVariable (\r
262 mEfiMtcName,\r
263 &mEfiMtcGuid,\r
264 NULL,\r
265 &BufferSize,\r
266 &HighCount\r
267 );\r
268 if (EFI_ERROR (Status)) {\r
269 HighCount = 0;\r
270 }\r
271 //\r
272 // Set the current value\r
273 //\r
274 mEfiMtc = LShiftU64 (HighCount, 32);\r
275\r
276 //\r
277 // Increment the upper 32 bits for this boot\r
278 // Continue even if it fails. It will only fail if the variable services are\r
279 // not functional.\r
280 //\r
281 Status = MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount);\r
282\r
283 //\r
284 // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields\r
285 //\r
286 gBS->GetNextMonotonicCount = MonotonicCounterDriverGetNextMonotonicCount;\r
287 gRT->GetNextHighMonotonicCount = MonotonicCounterDriverGetNextHighMonotonicCount;\r
288\r
289 //\r
290 // Install the Monotonic Counter Architctural Protocol onto a new handle\r
291 //\r
292 Status = gBS->InstallMultipleProtocolInterfaces (\r
293 &mMonotonicCounterHandle,\r
294 &gEfiMonotonicCounterArchProtocolGuid,\r
295 NULL,\r
296 NULL\r
297 );\r
298 ASSERT_EFI_ERROR (Status);\r
299\r
300 return EFI_SUCCESS;\r
301}\r