From 993532d0b8084b8ea667ce4306ec44eee5ef3bc6 Mon Sep 17 00:00:00 2001 From: jljusten Date: Tue, 2 Aug 2011 21:06:13 +0000 Subject: MdeModulePkg: Add SmmLockBox PEI implementation Signed-off-by: jljusten Reviewed-by: rsun3 git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12077 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Library/SmmLockBoxLib/SmmLockBoxPeiLib.c | 741 +++++++++++++++++++++ .../Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf | 56 ++ MdeModulePkg/MdeModulePkg.dsc | 2 + 3 files changed, 799 insertions(+) create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.c create mode 100644 MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.c b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.c new file mode 100644 index 0000000000..bd3204b195 --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.c @@ -0,0 +1,741 @@ +/** @file + +Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.
+ +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the BSD License which accompanies this distribution. The +full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SmmLockBoxLibPrivate.h" + +#if defined (MDE_CPU_IA32) +typedef struct _LIST_ENTRY64 LIST_ENTRY64; +struct _LIST_ENTRY64 { + LIST_ENTRY64 *ForwardLink; + UINT32 Reserved1; + LIST_ENTRY64 *BackLink; + UINT32 Reserved2; +}; + +typedef struct { + EFI_TABLE_HEADER Hdr; + UINT64 SmmFirmwareVendor; + UINT64 SmmFirmwareRevision; + UINT64 SmmInstallConfigurationTable; + UINT64 SmmIoMemRead; + UINT64 SmmIoMemWrite; + UINT64 SmmIoIoRead; + UINT64 SmmIoIoWrite; + UINT64 SmmAllocatePool; + UINT64 SmmFreePool; + UINT64 SmmAllocatePages; + UINT64 SmmFreePages; + UINT64 SmmStartupThisAp; + UINT64 CurrentlyExecutingCpu; + UINT64 NumberOfCpus; + UINT64 CpuSaveStateSize; + UINT64 CpuSaveState; + UINT64 NumberOfTableEntries; + UINT64 SmmConfigurationTable; +} EFI_SMM_SYSTEM_TABLE2_64; + +typedef struct { + EFI_GUID VendorGuid; + UINT64 VendorTable; +} EFI_CONFIGURATION_TABLE64; +#endif + +#if defined (MDE_CPU_X64) +typedef LIST_ENTRY LIST_ENTRY64; +typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64; +typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64; +#endif + +/** + This function return first node of LinkList queue. + + @param LockBoxQueue LinkList queue + + @return first node of LinkList queue +**/ +LIST_ENTRY * +InternalInitLinkDxe ( + IN LIST_ENTRY *LinkList + ) +{ + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + // + // 32 PEI + 64 DXE + // + return (LIST_ENTRY *)(((LIST_ENTRY64 *)LinkList)->ForwardLink); + } else { + return LinkList->ForwardLink; + } +} + +/** + This function return next node of LinkList. + + @param Link LinkList node + + @return next node of LinkList +**/ +LIST_ENTRY * +InternalNextLinkDxe ( + IN LIST_ENTRY *Link + ) +{ + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + // + // 32 PEI + 64 DXE + // + return (LIST_ENTRY *)(((LIST_ENTRY64 *)Link)->ForwardLink); + } else { + return Link->ForwardLink; + } +} + +/** + This function find LockBox by GUID from SMRAM. + + @param LockBoxQueue The LockBox queue in SMRAM + @param Guid The guid to indentify the LockBox + + @return LockBoxData +**/ +SMM_LOCK_BOX_DATA * +InternalFindLockBoxByGuidFromSmram ( + IN LIST_ENTRY *LockBoxQueue, + IN EFI_GUID *Guid + ) +{ + LIST_ENTRY *Link; + SMM_LOCK_BOX_DATA *LockBox; + + for (Link = InternalInitLinkDxe (LockBoxQueue); + Link != LockBoxQueue; + Link = InternalNextLinkDxe (Link)) { + LockBox = BASE_CR ( + Link, + SMM_LOCK_BOX_DATA, + Link + ); + if (CompareGuid (&LockBox->Guid, Guid)) { + return LockBox; + } + } + return NULL; +} + +/** + Get VendorTable by VendorGuid in Smst. + + @param Signature Signature of SMM_S3_RESUME_STATE + @param Smst SMM system table + @param VendorGuid vendor guid + + @return vendor table. +**/ +VOID * +InternalSmstGetVendorTableByGuid ( + IN UINT64 Signature, + IN EFI_SMM_SYSTEM_TABLE2 *Smst, + IN EFI_GUID *VendorGuid + ) +{ + EFI_CONFIGURATION_TABLE *SmmConfigurationTable; + UINTN NumberOfTableEntries; + UINTN Index; + EFI_SMM_SYSTEM_TABLE2_64 *Smst64; + EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64; + + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode))) { + // + // 32 PEI + 64 DXE + // + Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst; + SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable; + NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries; + for (Index = 0; Index < NumberOfTableEntries; Index++) { + if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) { + return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable; + } + } + return NULL; + } else { + SmmConfigurationTable = Smst->SmmConfigurationTable; + NumberOfTableEntries = Smst->NumberOfTableEntries; + for (Index = 0; Index < NumberOfTableEntries; Index++) { + if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) { + return (VOID *)SmmConfigurationTable[Index].VendorTable; + } + } + return NULL; + } +} + +/** + Get SMM LockBox context. + + @return SMM LockBox context. +**/ +SMM_LOCK_BOX_CONTEXT * +InternalGetSmmLockBoxContext ( + VOID + ) +{ + EFI_SMRAM_DESCRIPTOR *SmramDescriptor; + SMM_S3_RESUME_STATE *SmmS3ResumeState; + VOID *GuidHob; + SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext; + + GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid); + ASSERT (GuidHob != NULL); + SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob); + SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart; + + SmmLockBoxContext = (SMM_LOCK_BOX_CONTEXT *)InternalSmstGetVendorTableByGuid ( + SmmS3ResumeState->Signature, + (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst, + &gEfiSmmLockBoxCommunicationGuid + ); + ASSERT (SmmLockBoxContext != NULL); + + return SmmLockBoxContext; +} + +/** + This function will restore confidential information from lockbox in SMRAM directly. + + @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_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. +**/ +EFI_STATUS +InternalRestoreLockBoxFromSmram ( + IN GUID *Guid, + IN VOID *Buffer, OPTIONAL + IN OUT UINTN *Length OPTIONAL + ) +{ + PEI_SMM_ACCESS_PPI *SmmAccess; + UINTN Index; + EFI_STATUS Status; + SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext; + LIST_ENTRY *LockBoxQueue; + SMM_LOCK_BOX_DATA *LockBox; + VOID *RestoreBuffer; + + // + // Get needed resource + // + Status = PeiServicesLocatePpi ( + &gPeiSmmAccessPpiGuid, + 0, + NULL, + (VOID **)&SmmAccess + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; !EFI_ERROR (Status); Index++) { + Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index); + } + } + + // + // Get LockBox context + // + SmmLockBoxContext = InternalGetSmmLockBoxContext (); + LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress; + + // + // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller. + // + + // + // Restore this, Buffer and Length MUST be both NULL or both non-NULL + // + + // + // Find LockBox + // + LockBox = InternalFindLockBoxByGuidFromSmram (LockBoxQueue, Guid); + if (LockBox == NULL) { + // + // Not found + // + return EFI_NOT_FOUND; + } + + // + // Set RestoreBuffer + // + if (Buffer != NULL) { + // + // restore to new buffer + // + RestoreBuffer = Buffer; + } else { + // + // restore to original buffer + // + if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) { + return EFI_WRITE_PROTECTED; + } + RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer; + } + + // + // Set RestoreLength + // + if (Length != NULL) { + if (*Length < (UINTN)LockBox->Length) { + // + // Input buffer is too small to hold all data. + // + *Length = (UINTN)LockBox->Length; + return EFI_BUFFER_TOO_SMALL; + } + *Length = (UINTN)LockBox->Length; + } + + // + // Restore data + // + CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length); + + // + // Done + // + return EFI_SUCCESS; +} + +/** + This function will restore confidential information from all lockbox which have RestoreInPlace attribute. + + @retval RETURN_SUCCESS the information is restored successfully. +**/ +EFI_STATUS +InternalRestoreAllLockBoxInPlaceFromSmram ( + VOID + ) +{ + PEI_SMM_ACCESS_PPI *SmmAccess; + UINTN Index; + EFI_STATUS Status; + SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext; + LIST_ENTRY *LockBoxQueue; + SMM_LOCK_BOX_DATA *LockBox; + LIST_ENTRY *Link; + + // + // Get needed resource + // + Status = PeiServicesLocatePpi ( + &gPeiSmmAccessPpiGuid, + 0, + NULL, + (VOID **)&SmmAccess + ); + if (!EFI_ERROR (Status)) { + for (Index = 0; !EFI_ERROR (Status); Index++) { + Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index); + } + } + + // + // Get LockBox context + // + SmmLockBoxContext = InternalGetSmmLockBoxContext (); + LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress; + + // + // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller. + // + + // + // Restore all, Buffer and Length MUST be NULL + // + for (Link = InternalInitLinkDxe (LockBoxQueue); + Link != LockBoxQueue; + Link = InternalNextLinkDxe (Link)) { + LockBox = BASE_CR ( + Link, + SMM_LOCK_BOX_DATA, + Link + ); + if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) { + // + // Restore data + // + CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length); + } + } + // + // Done + // + return EFI_SUCCESS; +} + +/** + 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 + ) +{ + ASSERT (FALSE); + + // + // No support to save at PEI phase + // + return RETURN_UNSUPPORTED; +} + +/** + 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 + ) +{ + ASSERT (FALSE); + + // + // No support to save at PEI phase + // + return RETURN_UNSUPPORTED; +} + +/** + 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 the original buffer to too small to hold new 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 + ) +{ + ASSERT (FALSE); + + // + // No support to update at PEI phase + // + return RETURN_UNSUPPORTED; +} + +/** + 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 + ) +{ + EFI_STATUS Status; + EFI_PEI_SMM_COMMUNICATION_PPI *SmmCommunicationPpi; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)]; + UINTN CommSize; + UINT64 MessageLength; + + // + // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI. + // typedef struct { + // EFI_GUID HeaderGuid; + // UINTN MessageLength; + // UINT8 Data[1]; + // } EFI_SMM_COMMUNICATE_HEADER; + // + + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Enter\n")); + + // + // Basic check + // + if ((Guid == NULL) || + ((Buffer == NULL) && (Length != NULL)) || + ((Buffer != NULL) && (Length == NULL))) { + return EFI_INVALID_PARAMETER; + } + + // + // Get needed resource + // + Status = PeiServicesLocatePpi ( + &gEfiPeiSmmCommunicationPpiGuid, + 0, + NULL, + (VOID **)&SmmCommunicationPpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + MessageLength = sizeof(*LockBoxParameterRestore); + CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength)); + } else { + CommHeader->MessageLength = sizeof(*LockBoxParameterRestore); + } + + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib CommBuffer - %x\n", &CommBuffer[0])); + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)]; + } else { + LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)]; + } + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib LockBoxParameterRestore - %x\n", LockBoxParameterRestore)); + LockBoxParameterRestore->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE; + LockBoxParameterRestore->Header.DataLength = sizeof(*LockBoxParameterRestore); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)-1; + if (Guid != 0) { + CopyMem (&LockBoxParameterRestore->Guid, Guid, sizeof(*Guid)); + } else { + ZeroMem (&LockBoxParameterRestore->Guid, sizeof(*Guid)); + } + LockBoxParameterRestore->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; + if (Length != NULL) { + LockBoxParameterRestore->Length = (EFI_PHYSICAL_ADDRESS)*Length; + } else { + LockBoxParameterRestore->Length = 0; + } + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunicationPpi->Communicate ( + SmmCommunicationPpi, + &CommBuffer[0], + &CommSize + ); + if (Status == EFI_NOT_STARTED) { + // + // Pei SMM communication not ready yet, so we access SMRAM directly + // + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status)); + Status = InternalRestoreLockBoxFromSmram (Guid, Buffer, Length); + LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status; + if (Length != NULL) { + LockBoxParameterRestore->Length = (UINT64)*Length; + } + } + ASSERT_EFI_ERROR (Status); + + if (Length != NULL) { + *Length = (UINTN)LockBoxParameterRestore->Length; + } + + Status = (EFI_STATUS)LockBoxParameterRestore->Header.ReturnStatus; + if (Status != EFI_SUCCESS) { + // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32. + Status |= MAX_BIT; + } + + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + +/** + 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 + ) +{ + EFI_STATUS Status; + EFI_PEI_SMM_COMMUNICATION_PPI *SmmCommunicationPpi; + EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace; + EFI_SMM_COMMUNICATE_HEADER *CommHeader; + UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)]; + UINTN CommSize; + UINT64 MessageLength; + + // + // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI. + // typedef struct { + // EFI_GUID HeaderGuid; + // UINTN MessageLength; + // UINT8 Data[1]; + // } EFI_SMM_COMMUNICATE_HEADER; + // + + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Enter\n")); + + // + // Get needed resource + // + Status = PeiServicesLocatePpi ( + &gEfiPeiSmmCommunicationPpiGuid, + 0, + NULL, + (VOID **)&SmmCommunicationPpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + // + // Prepare parameter + // + CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0]; + CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid)); + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace); + CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength)); + } else { + CommHeader->MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace); + } + + if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) { + LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)]; + } else { + LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)]; + } + LockBoxParameterRestoreAllInPlace->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE; + LockBoxParameterRestoreAllInPlace->Header.DataLength = sizeof(*LockBoxParameterRestoreAllInPlace); + LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)-1; + + // + // Send command + // + CommSize = sizeof(CommBuffer); + Status = SmmCommunicationPpi->Communicate ( + SmmCommunicationPpi, + &CommBuffer[0], + &CommSize + ); + if (Status == EFI_NOT_STARTED) { + // + // Pei SMM communication not ready yet, so we access SMRAM directly + // + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status)); + Status = InternalRestoreAllLockBoxInPlaceFromSmram (); + LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status; + } + ASSERT_EFI_ERROR (Status); + + Status = (EFI_STATUS)LockBoxParameterRestoreAllInPlace->Header.ReturnStatus; + if (Status != EFI_SUCCESS) { + // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32. + Status |= MAX_BIT; + } + + DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status)); + + // + // Done + // + return Status; +} + diff --git a/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf new file mode 100644 index 0000000000..b84408cf9f --- /dev/null +++ b/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf @@ -0,0 +1,56 @@ +## @file +# Component description file for LockBox library. +# +# Copyright (c) 2010, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions +# of the BSD License which accompanies this distribution. The +# full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmLockBoxPeiLib + FILE_GUID = 5F5E6140-E7BA-4bd6-B85F-236B5BCD8E1E + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + LIBRARY_CLASS = LockBoxLib|PEIM + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SmmLockBoxPeiLib.c + SmmLockBoxLibPrivate.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + PeiServicesTablePointerLib + PeiServicesLib + BaseLib + BaseMemoryLib + HobLib + DebugLib + +[FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode + +[Guids] + gEfiSmmLockBoxCommunicationGuid ## CONSUMED + gEfiAcpiVariableGuid ## CONSUMED + +[Ppis] + gEfiPeiSmmCommunicationPpiGuid ## CONSUMED + gPeiSmmAccessPpiGuid ## CONSUMED diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index af66ca1387..b44b1e7523 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -99,6 +99,7 @@ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf [LibraryClasses.common.DXE_CORE] HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf @@ -236,6 +237,7 @@ MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf + MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf -- cgit v1.2.3