aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c')
-rw-r--r--roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c377
1 files changed, 377 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c b/roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c
new file mode 100644
index 000000000..1f36b5cc0
--- /dev/null
+++ b/roms/edk2/OvmfPkg/Library/LockBoxLib/LockBoxLib.c
@@ -0,0 +1,377 @@
+/** @file
+
+ Library implementing the LockBox interface for OVMF
+
+ Copyright (C) 2013, Red Hat, Inc.
+ Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/LockBoxLib.h>
+#include <Library/PcdLib.h>
+#include <LockBoxLib.h>
+
+#pragma pack(1)
+typedef struct {
+ EFI_GUID Guid;
+ EFI_PHYSICAL_ADDRESS OrigAddress;
+ EFI_PHYSICAL_ADDRESS CopyAddress;
+ UINT32 Size;
+ UINT64 Attributes;
+} LOCK_BOX_ENTRY;
+#pragma pack()
+
+LOCK_BOX_GLOBAL *mLockBoxGlobal = NULL;
+STATIC LOCK_BOX_ENTRY *StartOfEntries = NULL;
+STATIC LOCK_BOX_ENTRY *EndOfEntries = NULL;
+
+RETURN_STATUS
+EFIAPI
+LockBoxLibInitialize (
+ VOID
+ )
+{
+ UINTN NumEntries;
+
+ ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
+
+ if (PcdGet32 (PcdOvmfLockBoxStorageSize) < sizeof (LOCK_BOX_GLOBAL)) {
+ return RETURN_UNSUPPORTED;
+ }
+
+ mLockBoxGlobal = (LOCK_BOX_GLOBAL *)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase);
+ StartOfEntries = ((LOCK_BOX_ENTRY *) (mLockBoxGlobal + 1));
+ NumEntries = ((PcdGet32 (PcdOvmfLockBoxStorageSize) - sizeof (LOCK_BOX_GLOBAL)) /
+ sizeof (LOCK_BOX_ENTRY));
+ EndOfEntries = StartOfEntries + NumEntries;
+ if (mLockBoxGlobal->Signature != LOCK_BOX_GLOBAL_SIGNATURE) {
+ //
+ // Note: This code depends on the lock box being cleared in early
+ // PEI before usage, so the SubPageBuffer and SubPageRemaining
+ // fields don't need to be set to 0.
+ //
+ mLockBoxGlobal->Signature = LOCK_BOX_GLOBAL_SIGNATURE;
+ }
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Find LockBox entry based on GUID.
+
+ @param[in] Guid The GUID to search for.
+
+ @return Address of the LOCK_BOX_ENTRY found.
+
+ If NULL, then the item was not found, and there is no space
+ left to store a new item.
+
+ If non-NULL and LOCK_BOX_ENTRY.Size == 0, then the item was not
+ found, but a new item can be inserted at the returned location.
+
+ If non-NULL and LOCK_BOX_ENTRY.Size > 0, then the item was found.
+**/
+STATIC
+LOCK_BOX_ENTRY *
+EFIAPI
+FindHeaderByGuid (
+ IN CONST EFI_GUID *Guid
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+
+ for (Header = StartOfEntries; Header < EndOfEntries; Header++) {
+ if (Header->Size == 0 || CompareGuid (Guid, &Header->Guid)) {
+ return Header;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ This function will save confidential information to lockbox.
+
+ @param Guid the guid to identify the confidential information
+ @param Buffer the address of the confidential information
+ @param Length the length of the confidential information
+
+ @retval RETURN_SUCCESS the information is saved successfully.
+ @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
+ Length is 0
+ @retval RETURN_ALREADY_STARTED the requested GUID already exist.
+ @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
+ @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
+ @retval RETURN_NOT_STARTED it is too early to invoke this interface
+ @retval RETURN_UNSUPPORTED the service is not supported by
+ implementaion.
+**/
+RETURN_STATUS
+EFIAPI
+SaveLockBox (
+ IN GUID *Guid,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+ VOID *CopyBuffer;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p Length=0x%x\n", __FUNCTION__,
+ Guid, Buffer, (UINT32) Length));
+
+ if (Guid == NULL || Buffer == NULL || Length == 0) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (Length > 0xFFFFFFFF) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Header = FindHeaderByGuid (Guid);
+ if (Header == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (Header->Size > 0) {
+ return RETURN_ALREADY_STARTED;
+ }
+
+ CopyBuffer = AllocateAcpiNvsPool (Length);
+ if (CopyBuffer == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ //
+ // overwrite the current terminator header with new metadata
+ //
+ CopyGuid (&Header->Guid, Guid);
+ Header->OrigAddress = (UINTN) Buffer;
+ Header->CopyAddress = (UINTN) CopyBuffer;
+ Header->Size = (UINT32) Length;
+ Header->Attributes = 0;
+
+ //
+ // copy contents
+ //
+ CopyMem (CopyBuffer, Buffer, Length);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ This function will set lockbox attributes.
+
+ @param Guid the guid to identify the confidential information
+ @param Attributes the attributes of the lockbox
+
+ @retval RETURN_SUCCESS the information is saved successfully.
+ @retval RETURN_INVALID_PARAMETER attributes is invalid.
+ @retval RETURN_NOT_FOUND the requested GUID not found.
+ @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
+ @retval RETURN_NOT_STARTED it is too early to invoke this interface
+ @retval RETURN_UNSUPPORTED the service is not supported by
+ implementaion.
+**/
+RETURN_STATUS
+EFIAPI
+SetLockBoxAttributes (
+ IN GUID *Guid,
+ IN UINT64 Attributes
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Attributes=0x%Lx\n", __FUNCTION__, Guid,
+ Attributes));
+
+ if (Guid == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Header = FindHeaderByGuid (Guid);
+ if (!Header || Header->Size == 0) {
+ return RETURN_NOT_FOUND;
+ }
+ Header->Attributes = Attributes;
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ This function will update confidential information to lockbox.
+
+ @param Guid the guid to identify the original confidential information
+ @param Offset the offset of the original confidential information
+ @param Buffer the address of the updated confidential information
+ @param Length the length of the updated confidential information
+
+ @retval RETURN_SUCCESS the information is saved successfully.
+ @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or
+ Length is 0.
+ @retval RETURN_NOT_FOUND the requested GUID not found.
+ @retval RETURN_BUFFER_TOO_SMALL for lockbox without attribute
+ LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, the
+ original buffer to too small to hold new
+ information.
+ @retval RETURN_OUT_OF_RESOURCES for lockbox with attribute
+ LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY, no
+ enough resource to save the information.
+ @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
+ @retval RETURN_NOT_STARTED it is too early to invoke this interface
+ @retval RETURN_UNSUPPORTED the service is not supported by
+ implementaion.
+**/
+RETURN_STATUS
+EFIAPI
+UpdateLockBox (
+ IN GUID *Guid,
+ IN UINTN Offset,
+ IN VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Offset=0x%x Length=0x%x\n", __FUNCTION__,
+ Guid, (UINT32) Offset, (UINT32) Length));
+
+ if (Guid == NULL || Buffer == NULL || Length == 0) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Header = FindHeaderByGuid (Guid);
+ if (!Header || Header->Size == 0) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (Header->Size < Offset ||
+ Length > Header->Size - Offset) {
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ CopyMem ((UINT8 *)(UINTN) (Header->CopyAddress) + Offset, Buffer, Length);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ This function will restore confidential information from lockbox.
+
+ @param Guid the guid to identify the confidential information
+ @param Buffer the address of the restored confidential information
+ NULL means restored to original address, Length MUST be NULL at
+ same time.
+ @param Length the length of the restored confidential information
+
+ @retval RETURN_SUCCESS the information is restored successfully.
+ @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and
+ Length is NULL.
+ @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox
+ has no LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE
+ attribute.
+ @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the
+ confidential information.
+ @retval RETURN_NOT_FOUND the requested GUID not found.
+ @retval RETURN_NOT_STARTED it is too early to invoke this interface
+ @retval RETURN_ACCESS_DENIED not allow to restore to the address
+ @retval RETURN_UNSUPPORTED the service is not supported by
+ implementaion.
+**/
+RETURN_STATUS
+EFIAPI
+RestoreLockBox (
+ IN GUID *Guid,
+ IN VOID *Buffer, OPTIONAL
+ IN OUT UINTN *Length OPTIONAL
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__, Guid,
+ Buffer));
+
+ if ((Guid == NULL) ||
+ ((Buffer == NULL) && (Length != NULL)) ||
+ ((Buffer != NULL) && (Length == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Header = FindHeaderByGuid (Guid);
+ if (!Header || Header->Size == 0) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (Buffer == NULL) {
+ if (!(Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE)) {
+ return RETURN_WRITE_PROTECTED;
+ }
+ if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {
+ return RETURN_UNSUPPORTED;
+ }
+ Buffer = (VOID *)(UINTN) Header->OrigAddress;
+ }
+
+ //
+ // Set RestoreLength
+ //
+ if (Length != NULL) {
+ if (Header->Size > *Length) {
+ //
+ // Input buffer is too small to hold all data.
+ //
+ *Length = Header->Size;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ *Length = Header->Size;
+ }
+
+ CopyMem (Buffer, (VOID*)(UINTN) Header->CopyAddress, Header->Size);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ This function will restore confidential information from all lockbox which
+ have RestoreInPlace attribute.
+
+ @retval RETURN_SUCCESS the information is restored successfully.
+ @retval RETURN_NOT_STARTED it is too early to invoke this interface
+ @retval RETURN_UNSUPPORTED the service is not supported by
+ implementaion.
+**/
+RETURN_STATUS
+EFIAPI
+RestoreAllLockBoxInPlace (
+ VOID
+ )
+{
+ LOCK_BOX_ENTRY *Header;
+
+ for (Header = StartOfEntries;
+ Header < EndOfEntries && Header->Size > 0;
+ Header++) {
+ if (Header->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) {
+ VOID *Buffer;
+
+ if (Header->OrigAddress + (Header->Size - 1) > MAX_ADDRESS) {
+ return RETURN_UNSUPPORTED;
+ }
+ Buffer = (VOID *)(UINTN) Header->OrigAddress;
+ CopyMem (Buffer, (VOID*)(UINTN)Header->CopyAddress, Header->Size);
+ DEBUG ((DEBUG_VERBOSE, "%a: Guid=%g Buffer=%p\n", __FUNCTION__,
+ &Header->Guid, Buffer));
+ }
+ }
+ return RETURN_SUCCESS;
+}