/** @file | |
Initialize Intel TDX support. | |
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <Base.h> | |
#include <PiPei.h> | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/HobLib.h> | |
#include <Library/BaseMemoryLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <IndustryStandard/Tdx.h> | |
#include <IndustryStandard/IntelTdx.h> | |
#include <Library/PeiServicesLib.h> | |
#include <Pi/PiHob.h> | |
#include <WorkArea.h> | |
#include <ConfidentialComputingGuestAttr.h> | |
/** | |
* Build ResourceDescriptorHob for the unaccepted memory region. | |
* This memory region may be splitted into 2 parts because of lazy accept. | |
* | |
* @param Hob Point to the EFI_HOB_RESOURCE_DESCRIPTOR | |
* @return VOID | |
*/ | |
VOID | |
BuildResourceDescriptorHobForUnacceptedMemory ( | |
IN EFI_HOB_RESOURCE_DESCRIPTOR *Hob | |
) | |
{ | |
EFI_PHYSICAL_ADDRESS PhysicalStart; | |
EFI_PHYSICAL_ADDRESS PhysicalEnd; | |
UINT64 ResourceLength; | |
EFI_RESOURCE_TYPE ResourceType; | |
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; | |
UINT64 MaxAcceptedMemoryAddress; | |
ASSERT (Hob->ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED); | |
ResourceType = EFI_RESOURCE_MEMORY_UNACCEPTED; | |
ResourceAttribute = Hob->ResourceAttribute; | |
PhysicalStart = Hob->PhysicalStart; | |
ResourceLength = Hob->ResourceLength; | |
PhysicalEnd = PhysicalStart + ResourceLength; | |
// | |
// In the first stage of lazy-accept, all the memory under 4G will be accepted. | |
// The memory above 4G will not be accepted. | |
// | |
MaxAcceptedMemoryAddress = BASE_4GB; | |
if (PhysicalEnd <= MaxAcceptedMemoryAddress) { | |
// | |
// This memory region has been accepted. | |
// | |
ResourceType = EFI_RESOURCE_SYSTEM_MEMORY; | |
ResourceAttribute |= (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED); | |
} else if (PhysicalStart >= MaxAcceptedMemoryAddress) { | |
// | |
// This memory region hasn't been accepted. | |
// So keep the ResourceType and ResourceAttribute unchange. | |
// | |
} | |
BuildResourceDescriptorHob ( | |
ResourceType, | |
ResourceAttribute, | |
PhysicalStart, | |
ResourceLength | |
); | |
} | |
/** | |
Transfer the incoming HobList for the TD to the final HobList for Dxe. | |
The Hobs transferred in this function are ResourceDescriptor hob and | |
MemoryAllocation hob. | |
@param[in] VmmHobList The Hoblist pass the firmware | |
**/ | |
VOID | |
EFIAPI | |
TransferTdxHobList ( | |
VOID | |
) | |
{ | |
EFI_PEI_HOB_POINTERS Hob; | |
EFI_RESOURCE_TYPE ResourceType; | |
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; | |
VOID *GuidedData; | |
// | |
// PcdOvmfSecGhcbBase is used as the TD_HOB in Tdx guest. | |
// | |
Hob.Raw = (UINT8 *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase); | |
while (!END_OF_HOB_LIST (Hob)) { | |
switch (Hob.Header->HobType) { | |
case EFI_HOB_TYPE_RESOURCE_DESCRIPTOR: | |
ResourceType = Hob.ResourceDescriptor->ResourceType; | |
ResourceAttribute = Hob.ResourceDescriptor->ResourceAttribute; | |
if (ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED) { | |
BuildResourceDescriptorHobForUnacceptedMemory (Hob.ResourceDescriptor); | |
} else { | |
BuildResourceDescriptorHob ( | |
ResourceType, | |
ResourceAttribute, | |
Hob.ResourceDescriptor->PhysicalStart, | |
Hob.ResourceDescriptor->ResourceLength | |
); | |
} | |
break; | |
case EFI_HOB_TYPE_MEMORY_ALLOCATION: | |
BuildMemoryAllocationHob ( | |
Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, | |
Hob.MemoryAllocation->AllocDescriptor.MemoryLength, | |
Hob.MemoryAllocation->AllocDescriptor.MemoryType | |
); | |
break; | |
case EFI_HOB_TYPE_GUID_EXTENSION: | |
GuidedData = (VOID *)(&Hob.Guid->Name + 1); | |
BuildGuidDataHob (&Hob.Guid->Name, GuidedData, Hob.Guid->Header.HobLength - sizeof (EFI_HOB_GUID_TYPE)); | |
break; | |
} | |
Hob.Raw = GET_NEXT_HOB (Hob); | |
} | |
} | |
/** | |
In Tdx guest, the system memory is passed in TdHob by host VMM. So | |
the major task of PlatformTdxPublishRamRegions is to walk thru the | |
TdHob list and transfer the ResourceDescriptorHob and MemoryAllocationHob | |
to the hobs in DXE phase. | |
MemoryAllocationHob should also be created for Mailbox and Ovmf work area. | |
**/ | |
VOID | |
EFIAPI | |
PlatformTdxPublishRamRegions ( | |
VOID | |
) | |
{ | |
if (!TdIsEnabled ()) { | |
return; | |
} | |
TransferTdxHobList (); | |
// | |
// The memory region defined by PcdOvmfSecGhcbBackupBase is pre-allocated by | |
// host VMM and used as the td mailbox at the beginning of system boot. | |
// | |
BuildMemoryAllocationHob ( | |
FixedPcdGet32 (PcdOvmfSecGhcbBackupBase), | |
FixedPcdGet32 (PcdOvmfSecGhcbBackupSize), | |
EfiACPIMemoryNVS | |
); | |
if (FixedPcdGet32 (PcdOvmfWorkAreaSize) != 0) { | |
// | |
// Reserve the work area. | |
// | |
// Since this memory range will be used by the Reset Vector on S3 | |
// resume, it must be reserved as ACPI NVS. | |
// | |
// If S3 is unsupported, then various drivers might still write to the | |
// work area. We ought to prevent DXE from serving allocation requests | |
// such that they would overlap the work area. | |
// | |
BuildMemoryAllocationHob ( | |
(EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaBase), | |
(UINT64)(UINTN)FixedPcdGet32 (PcdOvmfWorkAreaSize), | |
EfiBootServicesData | |
); | |
} | |
} |