2 Generic Monotonic Counter services
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // The current Monotonic count value
26 // Event to use to update the Mtc's high part when wrapping
28 EFI_EVENT mEfiMtcEvent
;
31 // EfiMtcName - Variable name of the MTC value
33 CHAR16
*mEfiMtcName
= L
"MTC";
36 // EfiMtcGuid - Guid of the MTC value
38 EFI_GUID mEfiMtcGuid
= { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } };
57 Monotonic count event handler. This handler updates the high monotonic count.
61 Event The event to handle
62 Context The event context
66 EFI_SUCCESS The event has been handled properly
67 EFI_NOT_FOUND An error occurred updating the variable.
73 EfiGetNextHighMonotonicCount (&HighCount
);
80 LibMtcVirtualAddressChangeEvent (VOID
)
87 LibMtcGetNextHighMonotonicCount (
95 // Check input parameters
97 if (HighCount
== NULL
) {
98 return EFI_INVALID_PARAMETER
;
102 if (!EfiAtRuntime ()) {
103 // Use a lock if called before ExitBootServices()
104 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
107 *HighCount
= (UINT32
) RShiftU64 (mEfiMtc
, 32) + 1;
108 mEfiMtc
= LShiftU64 (*HighCount
, 32);
110 if (!EfiAtRuntime ()) {
111 gBS
->RestoreTPL (OldTpl
);
115 // Update the NvRam store to match the new high part
117 Status
= EfiSetVariable (
120 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
130 LibMtcGetNextMonotonicCount (
140 // Can not be called after ExitBootServices()
142 if (EfiAtRuntime ()) {
143 return EFI_UNSUPPORTED
;
147 // Check input parameters
150 return EFI_INVALID_PARAMETER
;
155 // If the MTC has not been initialized read the variable
159 // Read the last high part
161 BufferSize
= sizeof (UINT32
);
162 Status
= EfiGetVariable (
169 if (EFI_ERROR (Status
)) {
174 // Set the current value
176 mEfiMtc
= LShiftU64 (HighCount
, 32);
178 // Increment the upper 32 bits for this boot
179 // Continue even if it fails. It will only fail if the variable services are
182 Status
= EfiGetNextHighMonotonicCount (&HighCount
);
187 // Update the monotonic counter with a lock
189 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
192 gBS
->RestoreTPL (OldTpl
);
195 // If the MSB bit of the low part toggled, then signal that the high
196 // part needs updated now
198 if ((((UINT32
) mEfiMtc
) ^ ((UINT32
) *Count
)) & 0x80000000) {
199 gBS
->SignalEvent (mEfiMtcEvent
);
215 // Initialize event to handle overflows
217 Status
= gBS
->CreateEvent (
224 ASSERT_EFI_ERROR (Status
);