mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-26 20:22:34 +00:00 
			
		
		
		
	 993532d0b8
			
		
	
	
		993532d0b8
		
	
	
	
	
		
			
			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
		
			
				
	
	
		
			742 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			742 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| 
 | |
| Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
| 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 <PiPei.h>
 | |
| #include <PiDxe.h>
 | |
| #include <PiSmm.h>
 | |
| #include <Library/PeiServicesTablePointerLib.h>
 | |
| #include <Library/PeiServicesLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/LockBoxLib.h>
 | |
| #include <Library/HobLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/PcdLib.h>
 | |
| #include <Protocol/SmmCommunication.h>
 | |
| #include <Ppi/SmmCommunication.h>
 | |
| #include <Ppi/SmmAccess.h>
 | |
| #include <Guid/AcpiS3Context.h>
 | |
| #include <Guid/SmmLockBox.h>
 | |
| 
 | |
| #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;
 | |
| }
 | |
| 
 |