| /** @file | |
| Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <PiPei.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Protocol/DebugSupport.h> | |
| #include <Library/TdxLib.h> | |
| #include <IndustryStandard/Tdx.h> | |
| #include <Library/PrePiLib.h> | |
| #include <Library/PeilessStartupLib.h> | |
| #include <Library/PlatformInitLib.h> | |
| #include <Library/TdxHelperLib.h> | |
| #include <ConfidentialComputingGuestAttr.h> | |
| #include <Guid/MemoryTypeInformation.h> | |
| #include <OvmfPlatforms.h> | |
| #include "PeilessStartupInternal.h" | |
| #define GET_GPAW_INIT_STATE(INFO) ((UINT8) ((INFO) & 0x3f)) | |
| EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { | |
| { EfiACPIMemoryNVS, 0x004 }, | |
| { EfiACPIReclaimMemory, 0x008 }, | |
| { EfiReservedMemoryType, 0x004 }, | |
| { EfiRuntimeServicesData, 0x024 }, | |
| { EfiRuntimeServicesCode, 0x030 }, | |
| { EfiBootServicesCode, 0x180 }, | |
| { EfiBootServicesData, 0xF00 }, | |
| { EfiMaxMemoryType, 0x000 } | |
| }; | |
| EFI_STATUS | |
| EFIAPI | |
| InitializePlatform ( | |
| EFI_HOB_PLATFORM_INFO *PlatformInfoHob | |
| ) | |
| { | |
| VOID *VariableStore; | |
| DEBUG ((DEBUG_INFO, "InitializePlatform in Pei-less boot\n")); | |
| PlatformDebugDumpCmos (); | |
| PlatformInfoHob->DefaultMaxCpuNumber = 64; | |
| PlatformInfoHob->PcdPciMmio64Size = 0x800000000; | |
| PlatformInfoHob->HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID); | |
| DEBUG ((DEBUG_INFO, "HostBridgeDeviceId = 0x%x\n", PlatformInfoHob->HostBridgeDevId)); | |
| PlatformAddressWidthInitialization (PlatformInfoHob); | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "PhysMemAddressWidth=0x%x, Pci64Base=0x%llx, Pci64Size=0x%llx\n", | |
| PlatformInfoHob->PhysMemAddressWidth, | |
| PlatformInfoHob->PcdPciMmio64Base, | |
| PlatformInfoHob->PcdPciMmio64Size | |
| )); | |
| PlatformMaxCpuCountInitialization (PlatformInfoHob); | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "MaxCpuCount=%d, BootCpuCount=%d\n", | |
| PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber, | |
| PlatformInfoHob->PcdCpuBootLogicalProcessorNumber | |
| )); | |
| PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob); | |
| PlatformQemuUc32BaseInitialization (PlatformInfoHob); | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "Uc32Base = 0x%x, Uc32Size = 0x%x, LowerMemorySize = 0x%x\n", | |
| PlatformInfoHob->Uc32Base, | |
| PlatformInfoHob->Uc32Size, | |
| PlatformInfoHob->LowMemory | |
| )); | |
| VariableStore = PlatformReserveEmuVariableNvStore (); | |
| PlatformInfoHob->PcdEmuVariableNvStoreReserved = (UINT64)(UINTN)VariableStore; | |
| if (FeaturePcdGet (PcdSecureBootSupported)) { | |
| PlatformInitEmuVariableNvStore (VariableStore); | |
| } | |
| if (TdIsEnabled ()) { | |
| PlatformTdxPublishRamRegions (); | |
| } else { | |
| PlatformQemuInitializeRam (PlatformInfoHob); | |
| PlatformQemuInitializeRamForS3 (PlatformInfoHob); | |
| } | |
| // | |
| // Create Memory Type Information HOB | |
| // | |
| BuildGuidDataHob ( | |
| &gEfiMemoryTypeInformationGuid, | |
| mDefaultMemoryTypeInformation, | |
| sizeof (mDefaultMemoryTypeInformation) | |
| ); | |
| PlatformMemMapInitialization (PlatformInfoHob); | |
| PlatformNoexecDxeInitialization (PlatformInfoHob); | |
| if (TdIsEnabled ()) { | |
| PlatformInfoHob->PcdConfidentialComputingGuestAttr = CCAttrIntelTdx; | |
| PlatformInfoHob->PcdTdxSharedBitMask = TdSharedPageMask (); | |
| PlatformInfoHob->PcdSetNxForStack = TRUE; | |
| } | |
| PlatformMiscInitialization (PlatformInfoHob); | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| * This function brings up the Tdx guest from SEC phase to DXE phase. | |
| * PEI phase is skipped because most of the components in PEI phase | |
| * is not needed for Tdx guest, for example, MP Services, TPM etc. | |
| * In this way, the attack surfaces are reduced as much as possible. | |
| * | |
| * @param Context The pointer to the SecCoreData | |
| * @return VOID This function never returns | |
| */ | |
| VOID | |
| EFIAPI | |
| PeilessStartup ( | |
| IN VOID *Context | |
| ) | |
| { | |
| EFI_SEC_PEI_HAND_OFF *SecCoreData; | |
| EFI_FIRMWARE_VOLUME_HEADER *BootFv; | |
| EFI_STATUS Status; | |
| EFI_HOB_PLATFORM_INFO PlatformInfoHob; | |
| UINT32 DxeCodeBase; | |
| UINT32 DxeCodeSize; | |
| TD_RETURN_DATA TdReturnData; | |
| VOID *VmmHobList; | |
| Status = EFI_SUCCESS; | |
| BootFv = NULL; | |
| VmmHobList = NULL; | |
| SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context; | |
| ZeroMem (&PlatformInfoHob, sizeof (PlatformInfoHob)); | |
| if (TdIsEnabled ()) { | |
| VmmHobList = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase); | |
| Status = TdCall (TDCALL_TDINFO, 0, 0, 0, &TdReturnData); | |
| ASSERT (Status == EFI_SUCCESS); | |
| DEBUG (( | |
| DEBUG_INFO, | |
| "Tdx started with(Hob: 0x%x, Gpaw: 0x%x, Cpus: %d)\n", | |
| (UINT32)(UINTN)VmmHobList, | |
| GET_GPAW_INIT_STATE (TdReturnData.TdInfo.Gpaw), | |
| TdReturnData.TdInfo.NumVcpus | |
| )); | |
| Status = ConstructFwHobList (VmmHobList); | |
| } else { | |
| DEBUG ((DEBUG_INFO, "Ovmf started\n")); | |
| Status = ConstructSecHobList (); | |
| } | |
| if (EFI_ERROR (Status)) { | |
| ASSERT (FALSE); | |
| CpuDeadLoop (); | |
| } | |
| DEBUG ((DEBUG_INFO, "HobList: %p\n", GetHobList ())); | |
| if (TdIsEnabled ()) { | |
| // | |
| // Build GuidHob for the tdx measurements which were done in SEC phase. | |
| // | |
| Status = TdxHelperBuildGuidHobForTdxMeasurement (); | |
| if (EFI_ERROR (Status)) { | |
| ASSERT (FALSE); | |
| CpuDeadLoop (); | |
| } | |
| } | |
| // | |
| // Initialize the Platform | |
| // | |
| Status = InitializePlatform (&PlatformInfoHob); | |
| if (EFI_ERROR (Status)) { | |
| ASSERT (FALSE); | |
| CpuDeadLoop (); | |
| } | |
| BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO)); | |
| // | |
| // SecFV | |
| // | |
| BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; | |
| BuildFvHob ((UINTN)BootFv, BootFv->FvLength); | |
| // | |
| // DxeFV | |
| // | |
| DxeCodeBase = PcdGet32 (PcdBfvBase); | |
| DxeCodeSize = PcdGet32 (PcdBfvRawDataSize) - (UINT32)BootFv->FvLength; | |
| BuildFvHob (DxeCodeBase, DxeCodeSize); | |
| DEBUG ((DEBUG_INFO, "SecFv : %p, 0x%x\n", BootFv, BootFv->FvLength)); | |
| DEBUG ((DEBUG_INFO, "DxeFv : %x, 0x%x\n", DxeCodeBase, DxeCodeSize)); | |
| BuildStackHob ((UINTN)SecCoreData->StackBase, SecCoreData->StackSize <<= 1); | |
| BuildResourceDescriptorHob ( | |
| EFI_RESOURCE_SYSTEM_MEMORY, | |
| EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
| EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
| EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | | |
| EFI_RESOURCE_ATTRIBUTE_TESTED, | |
| (UINT64)SecCoreData->TemporaryRamBase, | |
| (UINT64)SecCoreData->TemporaryRamSize | |
| ); | |
| // | |
| // Load the DXE Core and transfer control to it. | |
| // Only DxeFV is in the compressed section. | |
| // | |
| Status = DxeLoadCore (1); | |
| // | |
| // Never arrive here. | |
| // | |
| ASSERT (FALSE); | |
| CpuDeadLoop (); | |
| } |