/** @file C functions in SEC Copyright (c) 2014, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SecMain.h" EFI_PEI_PPI_DESCRIPTOR mPeiSecMainPpi[] = { { EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, &gTopOfTemporaryRamPpiGuid, NULL // To be patched later. }, }; // // These are IDT entries pointing to 10:FFFFFFE4h. // UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL; /** Caller provided function to be invoked at the end of InitializeDebugAgent(). Entry point to the C language phase of SEC. After the SEC assembly code has initialized some temporary memory and set up the stack, the control is transferred to this function. @param[in] Context The first input parameter of InitializeDebugAgent(). **/ VOID EFIAPI SecStartupPhase2( IN VOID *Context ); /** Entry point to the C language phase of SEC. After the SEC assembly code has initialized some temporary memory and set up the stack, the control is transferred to this function. @param[in] SizeOfRam Size of the temporary memory available for use. @param[in] TempRamBase Base address of temporary ram @param[in] BootFirmwareVolume Base address of the Boot Firmware Volume. **/ VOID EFIAPI SecStartup ( IN UINT32 SizeOfRam, IN UINT32 TempRamBase, IN VOID *BootFirmwareVolume ) { EFI_SEC_PEI_HAND_OFF SecCoreData; IA32_DESCRIPTOR IdtDescriptor; SEC_IDT_TABLE IdtTableInStack; UINT32 Index; UINT32 PeiStackSize; PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize); if (PeiStackSize == 0) { PeiStackSize = (SizeOfRam >> 1); } ASSERT (PeiStackSize < SizeOfRam); // // Process all libraries constructor function linked to SecCore. // ProcessLibraryConstructorList (); DEBUG ((DEBUG_INFO, "SecCore - SecStartup\n")); // // Initialize floating point operating environment // to be compliant with UEFI spec. // InitializeFloatingPointUnits (); // |-------------------|----> // |Idt Table | // |-------------------| // |PeiService Pointer | PeiStackSize // |-------------------| // | | // | Stack | // |-------------------|----> // | | // | | // | Heap | PeiTemporayRamSize // | | // | | // |-------------------|----> TempRamBase IdtTableInStack.PeiService = 0; for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64)); } IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable; IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); AsmWriteIdtr (&IdtDescriptor); // // Update the base address and length of Pei temporary memory // SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF); SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume; SecCoreData.BootFirmwareVolumeSize = (UINTN)(SIZE_4GB - (UINTN) BootFirmwareVolume); SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase; SecCoreData.TemporaryRamSize = SizeOfRam; SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize; SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize); SecCoreData.StackSize = PeiStackSize; DEBUG ((DEBUG_INFO, "BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase)); DEBUG ((DEBUG_INFO, "BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize)); DEBUG ((DEBUG_INFO, "TemporaryRamBase - 0x%x\n", SecCoreData.TemporaryRamBase)); DEBUG ((DEBUG_INFO, "TemporaryRamSize - 0x%x\n", SecCoreData.TemporaryRamSize)); DEBUG ((DEBUG_INFO, "PeiTemporaryRamBase - 0x%x\n", SecCoreData.PeiTemporaryRamBase)); DEBUG ((DEBUG_INFO, "PeiTemporaryRamSize - 0x%x\n", SecCoreData.PeiTemporaryRamSize)); DEBUG ((DEBUG_INFO, "StackBase - 0x%x\n", SecCoreData.StackBase)); DEBUG ((DEBUG_INFO, "StackSize - 0x%x\n", SecCoreData.StackSize)); // // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. // InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); } /** This API patch the TopOfTemporaryRam value in SecPpiList. @param[in,out] SecPpiList PPI list to be patched. @param[in] TopOfTemporaryRam The top of CAR. **/ VOID PatchTopOfTemporaryRamPpi ( IN OUT EFI_PEI_PPI_DESCRIPTOR *SecPpiList, IN VOID *TopOfTemporaryRam ) { SecPpiList[0].Ppi = TopOfTemporaryRam; } /** Caller provided function to be invoked at the end of InitializeDebugAgent(). Entry point to the C language phase of SEC. After the SEC assembly code has initialized some temporary memory and set up the stack, the control is transferred to this function. @param[in] Context The first input parameter of InitializeDebugAgent(). **/ VOID EFIAPI SecStartupPhase2( IN VOID *Context ) { EFI_SEC_PEI_HAND_OFF *SecCoreData; EFI_PEI_PPI_DESCRIPTOR *PpiList; UINT32 Index; EFI_PEI_PPI_DESCRIPTOR LocalSecPpiList[sizeof(mPeiSecMainPpi)/sizeof(mPeiSecMainPpi[0])]; EFI_PEI_PPI_DESCRIPTOR AllSecPpiList[FixedPcdGet32(PcdSecCoreMaxPpiSupported)]; EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; // // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug // is enabled. // FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint); if (PeiCoreEntryPoint == NULL) { CpuDeadLoop (); } CopyMem (LocalSecPpiList, mPeiSecMainPpi, sizeof(mPeiSecMainPpi)); PatchTopOfTemporaryRamPpi (LocalSecPpiList, (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecCoreData->TemporaryRamSize)); // // Perform platform specific initialization before entering PeiCore. // PpiList = SecPlatformMain (SecCoreData); if (PpiList != NULL) { // // Remove the terminal flag from the terminal Ppi // CopyMem (AllSecPpiList, LocalSecPpiList, sizeof (LocalSecPpiList)); for (Index = 0; Index < PcdGet32 (PcdSecCoreMaxPpiSupported); Index ++) { if ((AllSecPpiList[Index].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { break; } } AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); // // Append the platform additional Ppi list // Index += 1; while (Index < PcdGet32 (PcdSecCoreMaxPpiSupported) && ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) { CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR)); Index++; PpiList++; } // // Check whether the total Ppis exceeds the max supported Ppi. // if (Index >= PcdGet32 (PcdSecCoreMaxPpiSupported)) { // // the total Ppi is larger than the supported Max // PcdSecCoreMaxPpiSupported can be enlarged to solve it. // CpuDeadLoop (); } else { // // Add the terminal Ppi // CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR)); } // // Set PpiList to the total Ppi // PpiList = &AllSecPpiList[0]; } else { // // No addition Ppi, PpiList directly point to the common Ppi list. // PpiList = &LocalSecPpiList[0]; } // // Transfer the control to the PEI core // ASSERT (PeiCoreEntryPoint != NULL); (*PeiCoreEntryPoint) (SecCoreData, PpiList); // // Should not come here. // return ; }