/** @file Main SEC phase code. Transitions to PEI. Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define SEC_IDT_ENTRY_COUNT 34 typedef struct _SEC_IDT_TABLE { EFI_PEI_SERVICES *PeiService; IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; } SEC_IDT_TABLE; // // Template of an IDT entry pointing to 10:FFFFFFE4h. // IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { { // Bits 0xffe4, // OffsetLow 0x10, // Selector 0x0, // Reserved_0 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType 0xffff // OffsetHigh } }; VOID EFIAPI SecCoreStartupWithStack ( IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, IN VOID *TopOfCurrentStack ) { EFI_SEC_PEI_HAND_OFF SecCoreData; SEC_IDT_TABLE IdtTableInStack; IA32_DESCRIPTOR IdtDescriptor; UINT32 Index; volatile UINT8 *Table; if (CcProbe () == CcGuestTypeIntelTdx) { // // From the security perspective all the external input should be measured before // it is consumed. TdHob and Configuration FV (Cfv) image are passed from VMM // and should be measured here. // if (EFI_ERROR (TdxHelperMeasureTdHob ())) { CpuDeadLoop (); } if (EFI_ERROR (TdxHelperMeasureCfvImage ())) { CpuDeadLoop (); } // // For Td guests, the memory map info is in TdHobLib. It should be processed // first so that the memory is accepted. Otherwise access to the unaccepted // memory will trigger tripple fault. // if (TdxHelperProcessTdHob () != EFI_SUCCESS) { CpuDeadLoop (); } } // // To ensure SMM can't be compromised on S3 resume, we must force re-init of // the BaseExtractGuidedSectionLib. Since this is before library contructors // are called, we must use a loop rather than SetMem. // Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress); for (Index = 0; Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize); ++Index) { Table[Index] = 0; } // // Initialize IDT - Since this is before library constructors are called, // we use a loop rather than CopyMem. // IdtTableInStack.PeiService = NULL; for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) { // // Declare the local variables that actually move the data elements as // volatile to prevent the optimizer from replacing this function with // the intrinsic memcpy() // CONST UINT8 *Src; volatile UINT8 *Dst; UINTN Byte; Src = (CONST UINT8 *)&mIdtEntryTemplate; Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index]; for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) { Dst[Byte] = Src[Byte]; } } IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); ProcessLibraryConstructorList (); // // Load the IDTR. // AsmWriteIdtr (&IdtDescriptor); if (CcProbe () == CcGuestTypeIntelTdx) { // // InitializeCpuExceptionHandlers () should be called in Td guests so that // #VE exceptions can be handled correctly. // InitializeCpuExceptionHandlers (NULL); } DEBUG (( DEBUG_INFO, "SecCoreStartupWithStack(0x%x, 0x%x)\n", (UINT32)(UINTN)BootFv, (UINT32)(UINTN)TopOfCurrentStack )); // // Initialize floating point operating environment // to be compliant with UEFI spec. // InitializeFloatingPointUnits (); // // ASSERT that the Page Tables were set by the reset vector code to // the address we expect. // ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase)); // // |-------------| <-- TopOfCurrentStack // | Stack | 32k // |-------------| // | Heap | 32k // |-------------| <-- SecCoreData.TemporaryRamBase // ASSERT ( (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) + PcdGet32 (PcdOvmfSecPeiTempRamSize)) == (UINTN)TopOfCurrentStack ); // // Initialize SEC hand-off state // SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize); SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; SecCoreData.BootFirmwareVolumeBase = BootFv; SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength; // // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled // IoWrite8 (0x21, 0xff); IoWrite8 (0xA1, 0xff); // // Initialize Local APIC Timer hardware and disable Local APIC Timer // interrupts before initializing the Debug Agent and the debug timer is // enabled. // InitializeApicTimer (0, MAX_UINT32, TRUE, 5); DisableApicTimerInterrupt (); PeilessStartup (&SecCoreData); ASSERT (FALSE); CpuDeadLoop (); }