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
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.
18 Produced the Monotonic Counter Services as defined in the DXE CIS
24 #include "MonotonicCounter.h"
27 // The Monotonic Counter Handle
29 EFI_HANDLE mMonotonicCounterHandle
= NULL
;
32 // The current Monotonic count value
38 // Event to use to update the Mtc's high part when wrapping
40 EFI_EVENT mEfiMtcEvent
;
43 // EfiMtcName - Variable name of the MTC value
45 CHAR16
*mEfiMtcName
= (CHAR16
*) L
"MTC";
48 // EfiMtcGuid - Guid of the MTC value
50 EFI_GUID mEfiMtcGuid
= { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } };
57 MonotonicCounterDriverGetNextMonotonicCount (
73 // Can not be called after ExitBootServices()
75 if (EfiAtRuntime ()) {
76 return EFI_UNSUPPORTED
;
79 // Check input parameters
82 return EFI_INVALID_PARAMETER
;
85 // Update the monotonic counter with a lock
87 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
90 gBS
->RestoreTPL (OldTpl
);
93 // If the MSB bit of the low part toggled, then signal that the high
94 // part needs updated now
96 if ((((UINT32
) mEfiMtc
) ^ ((UINT32
) *Count
)) & 0x80000000) {
97 gBS
->SignalEvent (mEfiMtcEvent
);
105 MonotonicCounterDriverGetNextHighMonotonicCount (
106 OUT UINT32
*HighCount
122 // Check input parameters
124 if (HighCount
== NULL
) {
125 return EFI_INVALID_PARAMETER
;
128 if (!EfiAtRuntime ()) {
130 // Use a lock if called before ExitBootServices()
132 OldTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
133 *HighCount
= (UINT32
) RShiftU64 (mEfiMtc
, 32) + 1;
134 mEfiMtc
= LShiftU64 (*HighCount
, 32);
135 gBS
->RestoreTPL (OldTpl
);
137 *HighCount
= (UINT32
) RShiftU64 (mEfiMtc
, 32) + 1;
138 mEfiMtc
= LShiftU64 (*HighCount
, 32);
141 // Update the NvRam store to match the new high part
143 Status
= gRT
->SetVariable (
146 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
164 Monotonic count event handler. This handler updates the high monotonic count.
168 Event The event to handle
169 Context The event context
173 EFI_SUCCESS The event has been handled properly
174 EFI_NOT_FOUND An error occurred updating the variable.
180 MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount
);
185 MonotonicCounterDriverInitialize (
186 IN EFI_HANDLE ImageHandle
,
187 IN EFI_SYSTEM_TABLE
*SystemTable
194 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
205 // Make sure the Monotonic Counter Architectural Protocol is not already installed in the system
207 ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL
, &gEfiMonotonicCounterArchProtocolGuid
);
210 // Initialize event to handle overflows
212 Status
= gBS
->CreateEvent (
213 EFI_EVENT_NOTIFY_SIGNAL
,
220 ASSERT_EFI_ERROR (Status
);
223 // Read the last high part
225 BufferSize
= sizeof (UINT32
);
226 Status
= gRT
->GetVariable (
233 if (EFI_ERROR (Status
)) {
237 // Set the current value
239 mEfiMtc
= LShiftU64 (HighCount
, 32);
242 // Increment the upper 32 bits for this boot
243 // Continue even if it fails. It will only fail if the variable services are
246 Status
= MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount
);
249 // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields
251 gBS
->GetNextMonotonicCount
= MonotonicCounterDriverGetNextMonotonicCount
;
252 gRT
->GetNextHighMonotonicCount
= MonotonicCounterDriverGetNextHighMonotonicCount
;
255 // Install the Monotonic Counter Architctural Protocol onto a new handle
257 Status
= gBS
->InstallMultipleProtocolInterfaces (
258 &mMonotonicCounterHandle
,
259 &gEfiMonotonicCounterArchProtocolGuid
,
263 ASSERT_EFI_ERROR (Status
);