BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4243 ProcessHobList once was implemented in PlatformInitLib and it walks thru TdHob list and accept un-accepted memories. This patch moves the codes to SecTdxHelperLib and rename ProcessHobList as TdxHelperProcessTdHob After TdxHelperProcessTdHob is introduced, below changes are applied: - Call TdxHelperProcessTdHob instead of ProcessHobList in SecMain.c (in both OvmfPkgX64/Sec and IntelTdx/Sec). - Delete the duplicated codes in PlatformInitLib Cc: Erdem Aktas <erdemaktas@google.com> Cc: James Bottomley <jejb@linux.ibm.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Michael Roth <michael.roth@amd.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Min Xu <min.m.xu@intel.com>
		
			
				
	
	
		
			980 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			980 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  TdxHelper Functions which are used in SEC phase
 | 
						|
 | 
						|
  Copyright (c) 2022 - 2023, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <PiPei.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/HobLib.h>
 | 
						|
#include <Library/BaseCryptLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <IndustryStandard/Tdx.h>
 | 
						|
#include <IndustryStandard/IntelTdx.h>
 | 
						|
#include <IndustryStandard/Tpm20.h>
 | 
						|
#include <Library/TdxLib.h>
 | 
						|
#include <Library/TdxMailboxLib.h>
 | 
						|
#include <Library/SynchronizationLib.h>
 | 
						|
#include <Pi/PrePiHob.h>
 | 
						|
#include <WorkArea.h>
 | 
						|
#include <ConfidentialComputingGuestAttr.h>
 | 
						|
#include <Library/TdxHelperLib.h>
 | 
						|
 | 
						|
#define ALIGNED_2MB_MASK  0x1fffff
 | 
						|
#define MEGABYTE_SHIFT    20
 | 
						|
 | 
						|
#define ACCEPT_CHUNK_SIZE  SIZE_32MB
 | 
						|
#define AP_STACK_SIZE      SIZE_16KB
 | 
						|
#define APS_STACK_SIZE(CpusNum)  (ALIGN_VALUE(CpusNum*AP_STACK_SIZE, SIZE_2MB))
 | 
						|
 | 
						|
/**
 | 
						|
  Build the GuidHob for tdx measurements which were done in SEC phase.
 | 
						|
  The measurement values are stored in WorkArea.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS  The GuidHob is built successfully
 | 
						|
  @retval Others       Other errors as indicated
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
InternalBuildGuidHobForTdxMeasurement (
 | 
						|
  VOID
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  This function will be called to accept pages. Only BSP accepts pages.
 | 
						|
 | 
						|
  TDCALL(ACCEPT_PAGE) supports the accept page size of 4k and 2M. To
 | 
						|
  simplify the implementation, the Memory to be accpeted is splitted
 | 
						|
  into 3 parts:
 | 
						|
  -----------------  <-- StartAddress1 (not 2M aligned)
 | 
						|
  |  part 1       |      Length1 < 2M
 | 
						|
  |---------------|  <-- StartAddress2 (2M aligned)
 | 
						|
  |               |      Length2 = Integer multiples of 2M
 | 
						|
  |  part 2       |
 | 
						|
  |               |
 | 
						|
  |---------------|  <-- StartAddress3
 | 
						|
  |  part 3       |      Length3 < 2M
 | 
						|
  |---------------|
 | 
						|
 | 
						|
  @param[in] PhysicalAddress   Start physical adress
 | 
						|
  @param[in] PhysicalEnd       End physical address
 | 
						|
 | 
						|
  @retval    EFI_SUCCESS       Accept memory successfully
 | 
						|
  @retval    Others            Other errors as indicated
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BspAcceptMemoryResourceRange (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  PhysicalAddress,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  PhysicalEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINT32      AcceptPageSize;
 | 
						|
  UINT64      StartAddress1;
 | 
						|
  UINT64      StartAddress2;
 | 
						|
  UINT64      StartAddress3;
 | 
						|
  UINT64      TotalLength;
 | 
						|
  UINT64      Length1;
 | 
						|
  UINT64      Length2;
 | 
						|
  UINT64      Length3;
 | 
						|
  UINT64      Pages;
 | 
						|
 | 
						|
  AcceptPageSize = FixedPcdGet32 (PcdTdxAcceptPageSize);
 | 
						|
  TotalLength    = PhysicalEnd - PhysicalAddress;
 | 
						|
  StartAddress1  = 0;
 | 
						|
  StartAddress2  = 0;
 | 
						|
  StartAddress3  = 0;
 | 
						|
  Length1        = 0;
 | 
						|
  Length2        = 0;
 | 
						|
  Length3        = 0;
 | 
						|
 | 
						|
  if (TotalLength == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ALIGN_VALUE (PhysicalAddress, SIZE_2MB) != PhysicalAddress) {
 | 
						|
    StartAddress1 = PhysicalAddress;
 | 
						|
    Length1       = ALIGN_VALUE (PhysicalAddress, SIZE_2MB) - PhysicalAddress;
 | 
						|
    if (Length1 >= TotalLength) {
 | 
						|
      Length1 = TotalLength;
 | 
						|
    }
 | 
						|
 | 
						|
    PhysicalAddress += Length1;
 | 
						|
    TotalLength     -= Length1;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TotalLength > SIZE_2MB) {
 | 
						|
    StartAddress2    = PhysicalAddress;
 | 
						|
    Length2          = TotalLength & ~(UINT64)ALIGNED_2MB_MASK;
 | 
						|
    PhysicalAddress += Length2;
 | 
						|
    TotalLength     -= Length2;
 | 
						|
  }
 | 
						|
 | 
						|
  if (TotalLength) {
 | 
						|
    StartAddress3 = PhysicalAddress;
 | 
						|
    Length3       = TotalLength;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
  if (Length1 > 0) {
 | 
						|
    Pages  = Length1 / SIZE_4KB;
 | 
						|
    Status = TdAcceptPages (StartAddress1, Pages, SIZE_4KB);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Length2 > 0) {
 | 
						|
    Pages  = Length2 / AcceptPageSize;
 | 
						|
    Status = TdAcceptPages (StartAddress2, Pages, AcceptPageSize);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Length3 > 0) {
 | 
						|
    Pages  = Length3 / SIZE_4KB;
 | 
						|
    Status = TdAcceptPages (StartAddress3, Pages, SIZE_4KB);
 | 
						|
    ASSERT (!EFI_ERROR (Status));
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This function is called by BSP and APs to accept memory.
 | 
						|
 * Note:
 | 
						|
 * The input PhysicalStart/PhysicalEnd indicates the whole memory region
 | 
						|
 * to be accepted. BSP or AP only accepts one piece in the whole memory region.
 | 
						|
 *
 | 
						|
 * @param CpuIndex        vCPU index
 | 
						|
 * @param CpusNum         Total vCPU number of a Tdx guest
 | 
						|
 * @param PhysicalStart   Start address of a memory region which is to be accepted
 | 
						|
 * @param PhysicalEnd     End address of a memory region which is to be accepted
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS    Successfully accept the memory
 | 
						|
 * @retval Other          Other errors as indicated
 | 
						|
 */
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BspApAcceptMemoryResourceRange (
 | 
						|
  UINT32                CpuIndex,
 | 
						|
  UINT32                CpusNum,
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalStart,
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64                Status;
 | 
						|
  UINT64                Pages;
 | 
						|
  UINT64                Stride;
 | 
						|
  UINT64                AcceptPageSize;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalAddress;
 | 
						|
 | 
						|
  AcceptPageSize = (UINT64)(UINTN)FixedPcdGet32 (PcdTdxAcceptPageSize);
 | 
						|
 | 
						|
  Status          = EFI_SUCCESS;
 | 
						|
  Stride          = (UINTN)CpusNum * ACCEPT_CHUNK_SIZE;
 | 
						|
  PhysicalAddress = PhysicalStart + ACCEPT_CHUNK_SIZE * (UINTN)CpuIndex;
 | 
						|
 | 
						|
  while (!EFI_ERROR (Status) && PhysicalAddress < PhysicalEnd) {
 | 
						|
    Pages  = MIN (ACCEPT_CHUNK_SIZE, PhysicalEnd - PhysicalAddress) / AcceptPageSize;
 | 
						|
    Status = TdAcceptPages (PhysicalAddress, Pages, (UINT32)(UINTN)AcceptPageSize);
 | 
						|
    ASSERT (!EFI_ERROR (Status));
 | 
						|
    PhysicalAddress += Stride;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This function is called by APs to accept memory.
 | 
						|
 *
 | 
						|
 * @param CpuIndex        vCPU index of an AP
 | 
						|
 * @param PhysicalStart   Start address of a memory region which is to be accepted
 | 
						|
 * @param PhysicalEnd     End address of a memory region which is to be accepted
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS    Successfully accept the memory
 | 
						|
 * @retval Others         Other errors as indicated
 | 
						|
 */
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ApAcceptMemoryResourceRange (
 | 
						|
  UINT32                CpuIndex,
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalStart,
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64          Status;
 | 
						|
  TD_RETURN_DATA  TdReturnData;
 | 
						|
 | 
						|
  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
 | 
						|
  if (Status != TDX_EXIT_REASON_SUCCESS) {
 | 
						|
    ASSERT (FALSE);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((CpuIndex == 0) || (CpuIndex >= TdReturnData.TdInfo.NumVcpus)) {
 | 
						|
    ASSERT (FALSE);
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return BspApAcceptMemoryResourceRange (CpuIndex, TdReturnData.TdInfo.NumVcpus, PhysicalStart, PhysicalEnd);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * This function is called by BSP. It coordinates BSP/APs to accept memory together.
 | 
						|
 *
 | 
						|
 * @param PhysicalStart     Start address of a memory region which is to be accepted
 | 
						|
 * @param PhysicalEnd       End address of a memory region which is to be accepted
 | 
						|
 * @param APsStackAddress   APs stack address
 | 
						|
 * @param CpusNum           Total vCPU number of the Tdx guest
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS      Successfully accept the memory
 | 
						|
 * @retval Others           Other errors as indicated
 | 
						|
 */
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MpAcceptMemoryResourceRange (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS      PhysicalStart,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS      PhysicalEnd,
 | 
						|
  IN OUT EFI_PHYSICAL_ADDRESS  APsStackAddress,
 | 
						|
  IN UINT32                    CpusNum
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT64      Length;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Length = PhysicalEnd - PhysicalStart;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "MpAccept : 0x%llx - 0x%llx (0x%llx)\n", PhysicalStart, PhysicalEnd, Length));
 | 
						|
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The start address is not 2M aligned. BSP first accept the part which is not 2M aligned.
 | 
						|
  //
 | 
						|
  if (ALIGN_VALUE (PhysicalStart, SIZE_2MB) != PhysicalStart) {
 | 
						|
    Length = MIN (ALIGN_VALUE (PhysicalStart, SIZE_2MB) - PhysicalStart, Length);
 | 
						|
    Status = BspAcceptMemoryResourceRange (PhysicalStart, PhysicalStart + Length);
 | 
						|
    ASSERT (Status == EFI_SUCCESS);
 | 
						|
 | 
						|
    PhysicalStart += Length;
 | 
						|
    Length         = PhysicalEnd - PhysicalStart;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Length == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // BSP will accept the memory by itself if the memory is not big enough compared with a chunk.
 | 
						|
  //
 | 
						|
  if (Length <= ACCEPT_CHUNK_SIZE) {
 | 
						|
    return BspAcceptMemoryResourceRange (PhysicalStart, PhysicalEnd);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Now APs are asked to accept the memory together.
 | 
						|
  //
 | 
						|
  MpSerializeStart ();
 | 
						|
 | 
						|
  MpSendWakeupCommand (
 | 
						|
    MpProtectedModeWakeupCommandAcceptPages,
 | 
						|
    (UINT64)(UINTN)ApAcceptMemoryResourceRange,
 | 
						|
    PhysicalStart,
 | 
						|
    PhysicalEnd,
 | 
						|
    APsStackAddress,
 | 
						|
    AP_STACK_SIZE
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Now BSP does its job.
 | 
						|
  //
 | 
						|
  BspApAcceptMemoryResourceRange (0, CpusNum, PhysicalStart, PhysicalEnd);
 | 
						|
 | 
						|
  MpSerializeEnd ();
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  BSP accept a small piece of memory which will be used as APs stack.
 | 
						|
 | 
						|
  @param[in] VmmHobList    The Hoblist pass the firmware
 | 
						|
  @param[in] APsStackSize  APs stack size
 | 
						|
  @param[out] PhysicalAddressEnd    The physical end address of accepted memory in phase-1
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS     Process the HobList successfully
 | 
						|
  @retval  Others          Other errors as indicated
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AcceptMemoryForAPsStack (
 | 
						|
  IN CONST VOID             *VmmHobList,
 | 
						|
  IN UINT32                 APsStackSize,
 | 
						|
  OUT EFI_PHYSICAL_ADDRESS  *PhysicalAddressEnd
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_PEI_HOB_POINTERS  Hob;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalEnd;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalStart;
 | 
						|
  UINT64                ResourceLength;
 | 
						|
  BOOLEAN               MemoryRegionFound;
 | 
						|
 | 
						|
  ASSERT (VmmHobList != NULL);
 | 
						|
 | 
						|
  Status            = EFI_SUCCESS;
 | 
						|
  Hob.Raw           = (UINT8 *)VmmHobList;
 | 
						|
  MemoryRegionFound = FALSE;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "AcceptMemoryForAPsStack with APsStackSize=0x%x\n", APsStackSize));
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the HOB list until end of list or matching type is found.
 | 
						|
  //
 | 
						|
  while (!END_OF_HOB_LIST (Hob) && !MemoryRegionFound) {
 | 
						|
    if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | 
						|
      DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
 | 
						|
 | 
						|
      if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
 | 
						|
        ResourceLength = Hob.ResourceDescriptor->ResourceLength;
 | 
						|
        PhysicalStart  = Hob.ResourceDescriptor->PhysicalStart;
 | 
						|
        PhysicalEnd    = PhysicalStart + ResourceLength;
 | 
						|
 | 
						|
        DEBUG ((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
 | 
						|
        DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%llx\n", PhysicalStart));
 | 
						|
        DEBUG ((DEBUG_INFO, "ResourceLength: 0x%llx\n", ResourceLength));
 | 
						|
        DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
 | 
						|
 | 
						|
        if (ResourceLength >= APsStackSize) {
 | 
						|
          MemoryRegionFound = TRUE;
 | 
						|
          if (ResourceLength > ACCEPT_CHUNK_SIZE) {
 | 
						|
            PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + APsStackSize;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        Status = BspAcceptMemoryResourceRange (
 | 
						|
                   Hob.ResourceDescriptor->PhysicalStart,
 | 
						|
                   PhysicalEnd
 | 
						|
                   );
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Hob.Raw = GET_NEXT_HOB (Hob);
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (MemoryRegionFound);
 | 
						|
  *PhysicalAddressEnd = PhysicalEnd;
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  BSP and APs work togeter to accept memory which is under the address of 4G.
 | 
						|
 | 
						|
  @param[in] VmmHobList           The Hoblist pass the firmware
 | 
						|
  @param[in] CpusNum              Number of vCPUs
 | 
						|
  @param[in] APsStackStartAddres  Start address of APs stack
 | 
						|
  @param[in] PhysicalAddressStart Start physical address which to be accepted
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS     Process the HobList successfully
 | 
						|
  @retval  Others          Other errors as indicated
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
AcceptMemory (
 | 
						|
  IN CONST VOID            *VmmHobList,
 | 
						|
  IN UINT32                CpusNum,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  APsStackStartAddress,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  PhysicalAddressStart
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_PEI_HOB_POINTERS  Hob;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalStart;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalEnd;
 | 
						|
  EFI_PHYSICAL_ADDRESS  AcceptMemoryEndAddress;
 | 
						|
 | 
						|
  Status                 = EFI_SUCCESS;
 | 
						|
  AcceptMemoryEndAddress = BASE_4GB;
 | 
						|
 | 
						|
  ASSERT (VmmHobList != NULL);
 | 
						|
  Hob.Raw = (UINT8 *)VmmHobList;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "AcceptMemory under address of 4G\n"));
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the HOB list until end of list or matching type is found.
 | 
						|
  //
 | 
						|
  while (!END_OF_HOB_LIST (Hob)) {
 | 
						|
    if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | 
						|
      if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
 | 
						|
        PhysicalStart = Hob.ResourceDescriptor->PhysicalStart;
 | 
						|
        PhysicalEnd   = PhysicalStart + Hob.ResourceDescriptor->ResourceLength;
 | 
						|
 | 
						|
        if (PhysicalEnd <= PhysicalAddressStart) {
 | 
						|
          // this memory region has been accepted. Skipped it.
 | 
						|
          Hob.Raw = GET_NEXT_HOB (Hob);
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (PhysicalStart >= AcceptMemoryEndAddress) {
 | 
						|
          // this memory region is not to be accepted. And we're done.
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (PhysicalStart >= PhysicalAddressStart) {
 | 
						|
          // this memory region has not been acceted.
 | 
						|
        } else if ((PhysicalStart < PhysicalAddressStart) && (PhysicalEnd > PhysicalAddressStart)) {
 | 
						|
          // part of the memory region has been accepted.
 | 
						|
          PhysicalStart = PhysicalAddressStart;
 | 
						|
        }
 | 
						|
 | 
						|
        // then compare the PhysicalEnd with AcceptMemoryEndAddress
 | 
						|
        if (PhysicalEnd >= AcceptMemoryEndAddress) {
 | 
						|
          PhysicalEnd = AcceptMemoryEndAddress;
 | 
						|
        }
 | 
						|
 | 
						|
        DEBUG ((DEBUG_INFO, "ResourceAttribute: 0x%x\n", Hob.ResourceDescriptor->ResourceAttribute));
 | 
						|
        DEBUG ((DEBUG_INFO, "PhysicalStart: 0x%llx\n", Hob.ResourceDescriptor->PhysicalStart));
 | 
						|
        DEBUG ((DEBUG_INFO, "ResourceLength: 0x%llx\n", Hob.ResourceDescriptor->ResourceLength));
 | 
						|
        DEBUG ((DEBUG_INFO, "Owner: %g\n\n", &Hob.ResourceDescriptor->Owner));
 | 
						|
 | 
						|
        // Now we're ready to accept memory [PhysicalStart, PhysicalEnd)
 | 
						|
        if (CpusNum == 1) {
 | 
						|
          Status = BspAcceptMemoryResourceRange (PhysicalStart, PhysicalEnd);
 | 
						|
        } else {
 | 
						|
          Status = MpAcceptMemoryResourceRange (
 | 
						|
                     PhysicalStart,
 | 
						|
                     PhysicalEnd,
 | 
						|
                     APsStackStartAddress,
 | 
						|
                     CpusNum
 | 
						|
                     );
 | 
						|
        }
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          ASSERT (FALSE);
 | 
						|
          break;
 | 
						|
        }
 | 
						|
 | 
						|
        if (PhysicalEnd == AcceptMemoryEndAddress) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Hob.Raw = GET_NEXT_HOB (Hob);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the value whether in the valid list.
 | 
						|
 | 
						|
  @param[in] Value             A value
 | 
						|
  @param[in] ValidList         A pointer to valid list
 | 
						|
  @param[in] ValidListLength   Length of valid list
 | 
						|
 | 
						|
  @retval  TRUE   The value is in valid list.
 | 
						|
  @retval  FALSE  The value is not in valid list.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
IsInValidList (
 | 
						|
  IN UINT32  Value,
 | 
						|
  IN UINT32  *ValidList,
 | 
						|
  IN UINT32  ValidListLength
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  index;
 | 
						|
 | 
						|
  if (ValidList == NULL) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  for (index = 0; index < ValidListLength; index++) {
 | 
						|
    if (ValidList[index] == Value) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the integrity of VMM Hob List.
 | 
						|
 | 
						|
  @param[in] VmmHobList   A pointer to Hob List
 | 
						|
 | 
						|
  @retval  TRUE     The Hob List is valid.
 | 
						|
  @retval  FALSE    The Hob List is invalid.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
EFIAPI
 | 
						|
ValidateHobList (
 | 
						|
  IN CONST VOID  *VmmHobList
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS  Hob;
 | 
						|
  UINT32                EFI_BOOT_MODE_LIST[] = {
 | 
						|
    BOOT_WITH_FULL_CONFIGURATION,
 | 
						|
    BOOT_WITH_MINIMAL_CONFIGURATION,
 | 
						|
    BOOT_ASSUMING_NO_CONFIGURATION_CHANGES,
 | 
						|
    BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS,
 | 
						|
    BOOT_WITH_DEFAULT_SETTINGS,
 | 
						|
    BOOT_ON_S4_RESUME,
 | 
						|
    BOOT_ON_S5_RESUME,
 | 
						|
    BOOT_WITH_MFG_MODE_SETTINGS,
 | 
						|
    BOOT_ON_S2_RESUME,
 | 
						|
    BOOT_ON_S3_RESUME,
 | 
						|
    BOOT_ON_FLASH_UPDATE,
 | 
						|
    BOOT_IN_RECOVERY_MODE
 | 
						|
  };
 | 
						|
 | 
						|
  UINT32  EFI_RESOURCE_TYPE_LIST[] = {
 | 
						|
    EFI_RESOURCE_SYSTEM_MEMORY,
 | 
						|
    EFI_RESOURCE_MEMORY_MAPPED_IO,
 | 
						|
    EFI_RESOURCE_IO,
 | 
						|
    EFI_RESOURCE_FIRMWARE_DEVICE,
 | 
						|
    EFI_RESOURCE_MEMORY_MAPPED_IO_PORT,
 | 
						|
    EFI_RESOURCE_MEMORY_RESERVED,
 | 
						|
    EFI_RESOURCE_IO_RESERVED,
 | 
						|
    BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED
 | 
						|
  };
 | 
						|
 | 
						|
  if (VmmHobList == NULL) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "HOB: HOB data pointer is NULL\n"));
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  Hob.Raw = (UINT8 *)VmmHobList;
 | 
						|
 | 
						|
  //
 | 
						|
  // Parse the HOB list until end of list or matching type is found.
 | 
						|
  //
 | 
						|
  while (!END_OF_HOB_LIST (Hob)) {
 | 
						|
    if (Hob.Header->Reserved != (UINT32)0) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "HOB: Hob header Reserved filed should be zero\n"));
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Hob.Header->HobLength == 0) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "HOB: Hob header LEANGTH should not be zero\n"));
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    switch (Hob.Header->HobType) {
 | 
						|
      case EFI_HOB_TYPE_HANDOFF:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_HANDOFF_INFO_TABLE)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_HANDOFF));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        if (IsInValidList (Hob.HandoffInformationTable->BootMode, EFI_BOOT_MODE_LIST, ARRAY_SIZE (EFI_BOOT_MODE_LIST)) == FALSE) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Unknow HandoffInformationTable BootMode type. Type: 0x%08x\n", Hob.HandoffInformationTable->BootMode));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((Hob.HandoffInformationTable->EfiFreeMemoryTop % 4096) != 0) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: HandoffInformationTable EfiFreeMemoryTop address must be 4-KB aligned to meet page restrictions of UEFI.\
 | 
						|
                               Address: 0x%016lx\n", Hob.HandoffInformationTable->EfiFreeMemoryTop));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_RESOURCE_DESCRIPTOR));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        if (IsInValidList (Hob.ResourceDescriptor->ResourceType, EFI_RESOURCE_TYPE_LIST, ARRAY_SIZE (EFI_RESOURCE_TYPE_LIST)) == FALSE) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceType type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceType));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        if ((Hob.ResourceDescriptor->ResourceAttribute & (~(EFI_RESOURCE_ATTRIBUTE_PRESENT |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_TESTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_PERSISTENT |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_16_BIT_IO |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_32_BIT_IO |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_64_BIT_IO |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_READ_PROTECTABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_PERSISTABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE |
 | 
						|
                                                            EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE))) != 0)
 | 
						|
        {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceAttribute type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceAttribute));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      // EFI_HOB_GUID_TYPE is variable length data, so skip check
 | 
						|
      case EFI_HOB_TYPE_GUID_EXTENSION:
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HOB_TYPE_FV:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HOB_TYPE_FV2:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME2)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV2));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HOB_TYPE_FV3:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_FIRMWARE_VOLUME3)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_FV3));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case EFI_HOB_TYPE_CPU:
 | 
						|
        if (Hob.Header->HobLength != sizeof (EFI_HOB_CPU)) {
 | 
						|
          DEBUG ((DEBUG_ERROR, "HOB: Hob length is not equal corresponding hob structure. Type: 0x%04x\n", EFI_HOB_TYPE_CPU));
 | 
						|
          return FALSE;
 | 
						|
        }
 | 
						|
 | 
						|
        for (UINT32 index = 0; index < 6; index++) {
 | 
						|
          if (Hob.Cpu->Reserved[index] != 0) {
 | 
						|
            DEBUG ((DEBUG_ERROR, "HOB: Cpu Reserved field will always be set to zero.\n"));
 | 
						|
            return FALSE;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        DEBUG ((DEBUG_ERROR, "HOB: Hob type is not know. Type: 0x%04x\n", Hob.Header->HobType));
 | 
						|
        return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    // Get next HOB
 | 
						|
    Hob.Raw = (UINT8 *)(Hob.Raw + Hob.Header->HobLength);
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Processing the incoming HobList for the TDX
 | 
						|
 | 
						|
  Firmware must parse list, and accept the pages of memory before their can be
 | 
						|
  use by the guest.
 | 
						|
 | 
						|
  @param[in] VmmHobList    The Hoblist pass the firmware
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS     Process the HobList successfully
 | 
						|
  @retval  Others          Other errors as indicated
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ProcessHobList (
 | 
						|
  IN CONST VOID  *VmmHobList
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  UINT32                CpusNum;
 | 
						|
  EFI_PHYSICAL_ADDRESS  PhysicalEnd;
 | 
						|
  EFI_PHYSICAL_ADDRESS  APsStackStartAddress;
 | 
						|
 | 
						|
  CpusNum = GetCpusNum ();
 | 
						|
 | 
						|
  //
 | 
						|
  // If there are mutli-vCPU in a TDX guest, accept memory is split into 2 phases.
 | 
						|
  // Phase-1 accepts a small piece of memory by BSP. This piece of memory
 | 
						|
  // is used to setup AP's stack.
 | 
						|
  // After that phase-2 accepts a big piece of memory by BSP/APs.
 | 
						|
  //
 | 
						|
  // TDVF supports 4K and 2M accept-page-size. The memory which can be accpeted
 | 
						|
  // in 2M accept-page-size must be 2M aligned and multiple 2M. So we align
 | 
						|
  // APsStackSize to 2M size aligned.
 | 
						|
  //
 | 
						|
  if (CpusNum > 1) {
 | 
						|
    Status = AcceptMemoryForAPsStack (VmmHobList, APS_STACK_SIZE (CpusNum), &PhysicalEnd);
 | 
						|
    ASSERT (Status == EFI_SUCCESS);
 | 
						|
    APsStackStartAddress = PhysicalEnd - APS_STACK_SIZE (CpusNum);
 | 
						|
  } else {
 | 
						|
    PhysicalEnd          = 0;
 | 
						|
    APsStackStartAddress = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = AcceptMemory (VmmHobList, CpusNum, APsStackStartAddress, PhysicalEnd);
 | 
						|
  ASSERT (Status == EFI_SUCCESS);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  In Tdx guest, some information need to be passed from host VMM to guest
 | 
						|
  firmware. For example, the memory resource, etc. These information are
 | 
						|
  prepared by host VMM and put in TdHob which is described in TdxMetadata.
 | 
						|
  TDVF processes the TdHob to accept memories.
 | 
						|
 | 
						|
  @retval   EFI_SUCCESS   Successfully process the TdHob
 | 
						|
  @retval   Others        Other error as indicated
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TdxHelperProcessTdHob (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  VOID            *TdHob;
 | 
						|
  TD_RETURN_DATA  TdReturnData;
 | 
						|
 | 
						|
  TdHob  = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);
 | 
						|
  Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_INFO,
 | 
						|
    "Intel Tdx Started with (GPAW: %d, Cpus: %d)\n",
 | 
						|
    TdReturnData.TdInfo.Gpaw,
 | 
						|
    TdReturnData.TdInfo.NumVcpus
 | 
						|
    ));
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate HobList
 | 
						|
  //
 | 
						|
  if (ValidateHobList (TdHob) == FALSE) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Process Hoblist to accept memory
 | 
						|
  //
 | 
						|
  Status = ProcessHobList (TdHob);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Calculate the sha384 of input Data and extend it to RTMR register.
 | 
						|
 *
 | 
						|
 * @param RtmrIndex       Index of the RTMR register
 | 
						|
 * @param DataToHash      Data to be hashed
 | 
						|
 * @param DataToHashLen   Length of the data
 | 
						|
 * @param Digest          Hash value of the input data
 | 
						|
 * @param DigestLen       Length of the hash value
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS    Successfully hash and extend to RTMR
 | 
						|
 * @retval Others         Other errors as indicated
 | 
						|
 */
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
HashAndExtendToRtmr (
 | 
						|
  IN UINT32  RtmrIndex,
 | 
						|
  IN VOID    *DataToHash,
 | 
						|
  IN UINTN   DataToHashLen,
 | 
						|
  OUT UINT8  *Digest,
 | 
						|
  IN  UINTN  DigestLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  if ((DataToHash == NULL) || (DataToHashLen == 0)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Digest == NULL) || (DigestLen != SHA384_DIGEST_SIZE)) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Calculate the sha384 of the data
 | 
						|
  //
 | 
						|
  if (!Sha384HashAll (DataToHash, DataToHashLen, Digest)) {
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Extend to RTMR
 | 
						|
  //
 | 
						|
  Status = TdExtendRtmr (
 | 
						|
             (UINT32 *)Digest,
 | 
						|
             SHA384_DIGEST_SIZE,
 | 
						|
             (UINT8)RtmrIndex
 | 
						|
             );
 | 
						|
 | 
						|
  ASSERT (!EFI_ERROR (Status));
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  In Tdx guest, TdHob is passed from host VMM to guest firmware and it contains
 | 
						|
  the information of the memory resource. From the security perspective before
 | 
						|
  it is consumed, it should be measured and extended.
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS Successfully measure the TdHob
 | 
						|
 * @retval Others      Other error as indicated
 | 
						|
 */
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TdxHelperMeasureTdHob (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS  Hob;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  UINT8                 Digest[SHA384_DIGEST_SIZE];
 | 
						|
  OVMF_WORK_AREA        *WorkArea;
 | 
						|
  VOID                  *TdHob;
 | 
						|
 | 
						|
  TdHob   = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase);
 | 
						|
  Hob.Raw = (UINT8 *)TdHob;
 | 
						|
 | 
						|
  //
 | 
						|
  // Walk thru the TdHob list until end of list.
 | 
						|
  //
 | 
						|
  while (!END_OF_HOB_LIST (Hob)) {
 | 
						|
    Hob.Raw = GET_NEXT_HOB (Hob);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = HashAndExtendToRtmr (
 | 
						|
             0,
 | 
						|
             (UINT8 *)TdHob,
 | 
						|
             (UINTN)((UINT8 *)Hob.Raw - (UINT8 *)TdHob),
 | 
						|
             Digest,
 | 
						|
             SHA384_DIGEST_SIZE
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // This function is called in SEC phase and at that moment the Hob service
 | 
						|
  // is not available. So the TdHob measurement value is stored in workarea.
 | 
						|
  //
 | 
						|
  WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);
 | 
						|
  if (WorkArea == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap |= TDX_MEASUREMENT_TDHOB_BITMASK;
 | 
						|
  CopyMem (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.TdHobHashValue, Digest, SHA384_DIGEST_SIZE);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * In Tdx guest, Configuration FV (CFV) is treated as external input because it
 | 
						|
 * may contain the data provided by VMM. From the sucurity perspective Cfv image
 | 
						|
 * should be measured before it is consumed.
 | 
						|
 *
 | 
						|
 * @retval EFI_SUCCESS Successfully measure the CFV image
 | 
						|
 * @retval Others      Other error as indicated
 | 
						|
 */
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TdxHelperMeasureCfvImage (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  UINT8           Digest[SHA384_DIGEST_SIZE];
 | 
						|
  OVMF_WORK_AREA  *WorkArea;
 | 
						|
 | 
						|
  Status = HashAndExtendToRtmr (
 | 
						|
             0,
 | 
						|
             (UINT8 *)(UINTN)PcdGet32 (PcdOvmfFlashNvStorageVariableBase),
 | 
						|
             (UINT64)PcdGet32 (PcdCfvRawDataSize),
 | 
						|
             Digest,
 | 
						|
             SHA384_DIGEST_SIZE
 | 
						|
             );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // This function is called in SEC phase and at that moment the Hob service
 | 
						|
  // is not available. So CfvImage measurement value is stored in workarea.
 | 
						|
  //
 | 
						|
  WorkArea = (OVMF_WORK_AREA *)FixedPcdGet32 (PcdOvmfWorkAreaBase);
 | 
						|
  if (WorkArea == NULL) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.MeasurementsBitmap |= TDX_MEASUREMENT_CFVIMG_BITMASK;
 | 
						|
  CopyMem (WorkArea->TdxWorkArea.SecTdxWorkArea.TdxMeasurementsData.CfvImgHashValue, Digest, SHA384_DIGEST_SIZE);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Build the GuidHob for tdx measurements which were done in SEC phase.
 | 
						|
  The measurement values are stored in WorkArea.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS  The GuidHob is built successfully
 | 
						|
  @retval Others       Other errors as indicated
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TdxHelperBuildGuidHobForTdxMeasurement (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
 #ifdef TDX_PEI_LESS_BOOT
 | 
						|
  return InternalBuildGuidHobForTdxMeasurement ();
 | 
						|
 #else
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
 #endif
 | 
						|
}
 |