From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../MonotonicCounterRuntimeDxe/MonotonicCounter.c | 269 +++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounter.c (limited to 'roms/edk2/MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounter.c') diff --git a/roms/edk2/MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounter.c b/roms/edk2/MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounter.c new file mode 100644 index 000000000..f74b0b8a1 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounter.c @@ -0,0 +1,269 @@ +/** @file + Produce the UEFI boot service GetNextMonotonicCount() and runtime service + GetNextHighMonotonicCount(). + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +// +// The handle to install Monotonic Counter Architctural Protocol +// +EFI_HANDLE mMonotonicCounterHandle = NULL; + +// +// The current monotonic counter value +// +UINT64 mEfiMtc; + +// +// Event to update the monotonic Counter's high part when low part overflows. +// +EFI_EVENT mEfiMtcEvent; + +/** + Returns a monotonically increasing count for the platform. + + This function returns a 64-bit value that is numerically larger then the last + time the function was called. + The platform monotonic counter is comprised of two parts: the high 32 bits + and the low 32 bits. The low 32-bit value is volatile and is reset to zero on + every system reset. It is increased by 1 on every call to GetNextMonotonicCount(). + The high 32-bit value is nonvolatile and is increased by one on whenever the + system resets or the low 32-bit counter overflows. + + @param Count Pointer to returned value. + + @retval EFI_SUCCESS The next monotonic count was returned. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_UNSUPPORTED This function is called at runtime. + +**/ +EFI_STATUS +EFIAPI +MonotonicCounterDriverGetNextMonotonicCount ( + OUT UINT64 *Count + ) +{ + EFI_TPL OldTpl; + + // + // Cannot be called after ExitBootServices() + // + if (EfiAtRuntime ()) { + return EFI_UNSUPPORTED; + } + // + // Check input parameters + // + if (Count == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Update the monotonic counter with a lock + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + *Count = mEfiMtc; + mEfiMtc++; + gBS->RestoreTPL (OldTpl); + + // + // If the low 32-bit counter overflows (MSB bit toggled), + // then signal that the high part needs update now. + // + if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & BIT31) { + gBS->SignalEvent (mEfiMtcEvent); + } + + return EFI_SUCCESS; +} + + +/** + Returns the next high 32 bits of the platform's monotonic counter. + + The GetNextHighMonotonicCount() function returns the next high 32 bits + of the platform's monotonic counter. The platform's monotonic counter is + comprised of two 32 bit quantities: the high 32 bits and the low 32 bits. + During boot service time the low 32 bit value is volatile: it is reset to + zero on every system reset and is increased by 1 on every call to GetNextMonotonicCount(). + The high 32 bit value is non-volatile and is increased by 1 whenever the system resets, + whenever GetNextHighMonotonicCount() is called, or whenever the low 32 bit count + (returned by GetNextMonoticCount()) overflows. + The GetNextMonotonicCount() function is only available at boot services time. + If the operating system wishes to extend the platform monotonic counter to runtime, + it may do so by utilizing GetNextHighMonotonicCount(). To do this, before calling + ExitBootServices() the operating system would call GetNextMonotonicCount() to obtain + the current platform monotonic count. The operating system would then provide an + interface that returns the next count by: + Adding 1 to the last count. + Before the lower 32 bits of the count overflows, call GetNextHighMonotonicCount(). + This will increase the high 32 bits of the platform's non-volatile portion of the monotonic + count by 1. + + This function may only be called at Runtime. + + @param HighCount Pointer to returned value. + + @retval EFI_SUCCESS The next high monotonic count was returned. + @retval EFI_INVALID_PARAMETER HighCount is NULL. + @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure. + @retval EFI_OUT_OF_RESOURCES If variable service reports that not enough storage + is available to hold the variable and its data. + +**/ +EFI_STATUS +EFIAPI +MonotonicCounterDriverGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +{ + EFI_TPL OldTpl; + + // + // Check input parameters + // + if (HighCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!EfiAtRuntime ()) { + // + // Use a lock if called before ExitBootServices() + // + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; + mEfiMtc = LShiftU64 (*HighCount, 32); + gBS->RestoreTPL (OldTpl); + } else { + *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; + mEfiMtc = LShiftU64 (*HighCount, 32); + } + // + // Update the NV variable to match the new high part + // + return EfiSetVariable ( + MTC_VARIABLE_NAME, + &gMtcVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT32), + HighCount + ); + +} + +/** + Monotonic counter event handler. This handler updates the high part of monotonic counter. + + @param Event The event to handle. + @param Context The event context. + +**/ +VOID +EFIAPI +EfiMtcEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 HighCount; + + MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount); +} + +/** + Entry point of monotonic counter driver. + + @param ImageHandle The image handle of this driver. + @param SystemTable The pointer of EFI_SYSTEM_TABLE. + + @retval EFI_SUCCESS The initialization is successful. + +**/ +EFI_STATUS +EFIAPI +MonotonicCounterDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 HighCount; + UINTN BufferSize; + + // + // Make sure the Monotonic Counter Architectural Protocol has not been installed in the system yet. + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMonotonicCounterArchProtocolGuid); + + // + // Initialize event to handle low-part overflow + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + EfiMtcEventHandler, + NULL, + &mEfiMtcEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Read the last high part + // + BufferSize = sizeof (UINT32); + Status = EfiGetVariable ( + MTC_VARIABLE_NAME, + &gMtcVendorGuid, + NULL, + &BufferSize, + &HighCount + ); + if (EFI_ERROR (Status)) { + HighCount = 0; + } + // + // Set the current value + // + mEfiMtc = LShiftU64 (HighCount, 32); + + // + // Increment the upper 32 bits for this boot + // Continue even if it fails. It will only fail if the variable services are + // not functional. + // + MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount); + + // + // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields + // + gBS->GetNextMonotonicCount = MonotonicCounterDriverGetNextMonotonicCount; + gRT->GetNextHighMonotonicCount = MonotonicCounterDriverGetNextHighMonotonicCount; + + // + // Install the Monotonic Counter Architctural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mMonotonicCounterHandle, + &gEfiMonotonicCounterArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} -- cgit