TianoCore EDK2 master
Loading...
Searching...
No Matches
MonotonicCounter.c
Go to the documentation of this file.
1
10#include <Uefi.h>
11
13#include <Guid/MtcVendor.h>
14
15#include <Library/BaseLib.h>
18#include <Library/DebugLib.h>
21
22//
23// The handle to install Monotonic Counter Architctural Protocol
24//
25EFI_HANDLE mMonotonicCounterHandle = NULL;
26
27//
28// The current monotonic counter value
29//
30UINT64 mEfiMtc;
31
32//
33// Event to update the monotonic Counter's high part when low part overflows.
34//
35EFI_EVENT mEfiMtcEvent;
36
57EFIAPI
59 OUT UINT64 *Count
60 )
61{
62 EFI_TPL OldTpl;
63
64 //
65 // Cannot be called after ExitBootServices()
66 //
67 if (EfiAtRuntime ()) {
68 return EFI_UNSUPPORTED;
69 }
70
71 //
72 // Check input parameters
73 //
74 if (Count == NULL) {
75 return EFI_INVALID_PARAMETER;
76 }
77
78 //
79 // Update the monotonic counter with a lock
80 //
81 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
82 *Count = mEfiMtc;
83 mEfiMtc++;
84 gBS->RestoreTPL (OldTpl);
85
86 //
87 // If the low 32-bit counter overflows (MSB bit toggled),
88 // then signal that the high part needs update now.
89 //
90 if ((((UINT32)mEfiMtc) ^ ((UINT32)*Count)) & BIT31) {
91 gBS->SignalEvent (mEfiMtcEvent);
92 }
93
94 return EFI_SUCCESS;
95}
96
134EFIAPI
136 OUT UINT32 *HighCount
137 )
138{
139 EFI_TPL OldTpl;
140
141 //
142 // Check input parameters
143 //
144 if (HighCount == NULL) {
145 return EFI_INVALID_PARAMETER;
146 }
147
148 if (!EfiAtRuntime ()) {
149 //
150 // Use a lock if called before ExitBootServices()
151 //
152 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
153 *HighCount = (UINT32)RShiftU64 (mEfiMtc, 32) + 1;
154 mEfiMtc = LShiftU64 (*HighCount, 32);
155 gBS->RestoreTPL (OldTpl);
156 } else {
157 *HighCount = (UINT32)RShiftU64 (mEfiMtc, 32) + 1;
158 mEfiMtc = LShiftU64 (*HighCount, 32);
159 }
160
161 //
162 // Update the NV variable to match the new high part
163 //
164 return EfiSetVariable (
165 MTC_VARIABLE_NAME,
166 &gMtcVendorGuid,
167 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
168 sizeof (UINT32),
169 HighCount
170 );
171}
172
180VOID
181EFIAPI
183 IN EFI_EVENT Event,
184 IN VOID *Context
185 )
186{
187 UINT32 HighCount;
188
190}
191
202EFIAPI
204 IN EFI_HANDLE ImageHandle,
205 IN EFI_SYSTEM_TABLE *SystemTable
206 )
207{
208 EFI_STATUS Status;
209 UINT32 HighCount;
210 UINTN BufferSize;
211
212 //
213 // Make sure the Monotonic Counter Architectural Protocol has not been installed in the system yet.
214 //
215 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMonotonicCounterArchProtocolGuid);
216
217 //
218 // Initialize event to handle low-part overflow
219 //
220 Status = gBS->CreateEvent (
221 EVT_NOTIFY_SIGNAL,
222 TPL_CALLBACK,
224 NULL,
225 &mEfiMtcEvent
226 );
227 ASSERT_EFI_ERROR (Status);
228
229 //
230 // Read the last high part
231 //
232 BufferSize = sizeof (UINT32);
233 Status = EfiGetVariable (
234 MTC_VARIABLE_NAME,
235 &gMtcVendorGuid,
236 NULL,
237 &BufferSize,
238 &HighCount
239 );
240 if (EFI_ERROR (Status)) {
241 HighCount = 0;
242 }
243
244 //
245 // Set the current value
246 //
247 mEfiMtc = LShiftU64 (HighCount, 32);
248
249 //
250 // Increment the upper 32 bits for this boot
251 // Continue even if it fails. It will only fail if the variable services are
252 // not functional.
253 //
255
256 //
257 // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields
258 //
259 gBS->GetNextMonotonicCount = MonotonicCounterDriverGetNextMonotonicCount;
260 gRT->GetNextHighMonotonicCount = MonotonicCounterDriverGetNextHighMonotonicCount;
261
262 //
263 // Install the Monotonic Counter Architctural Protocol onto a new handle
264 //
265 Status = gBS->InstallMultipleProtocolInterfaces (
266 &mMonotonicCounterHandle,
267 &gEfiMonotonicCounterArchProtocolGuid,
268 NULL,
269 NULL
270 );
271 ASSERT_EFI_ERROR (Status);
272
273 return EFI_SUCCESS;
274}
UINT64 UINTN
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid)
Definition: DebugLib.h:535
VOID EFIAPI EfiMtcEventHandler(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI MonotonicCounterDriverGetNextHighMonotonicCount(OUT UINT32 *HighCount)
EFI_STATUS EFIAPI MonotonicCounterDriverInitialize(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI MonotonicCounterDriverGetNextMonotonicCount(OUT UINT64 *Count)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
#define EFI_VARIABLE_NON_VOLATILE
EFI_STATUS EFIAPI EfiGetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, OUT UINT32 *Attributes OPTIONAL, IN OUT UINTN *DataSize, OUT VOID *Data)
Definition: RuntimeLib.c:408
BOOLEAN EFIAPI EfiAtRuntime(VOID)
Definition: RuntimeLib.c:167
EFI_STATUS EFIAPI EfiSetVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
Definition: RuntimeLib.c:498