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