123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- /** @file
- C functions in SEC
- Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "SecMain.h"
- EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi = {
- SecTemporaryRamDone
- };
- EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPpi = { SecPlatformInformation };
- EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
- {
- //
- // SecPerformance PPI notify descriptor.
- //
- EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK,
- &gPeiSecPerformancePpiGuid,
- (VOID *)(UINTN)SecPerformancePpiCallBack
- },
- {
- EFI_PEI_PPI_DESCRIPTOR_PPI,
- &gEfiTemporaryRamDonePpiGuid,
- &gSecTemporaryRamDonePpi
- },
- {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiSecPlatformInformationPpiGuid,
- &mSecPlatformInformationPpi
- }
- };
- /**
- Migrates the Global Descriptor Table (GDT) to permanent memory.
- @retval EFI_SUCCESS The GDT was migrated successfully.
- @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
- **/
- EFI_STATUS
- MigrateGdt (
- VOID
- )
- {
- EFI_STATUS Status;
- UINTN GdtBufferSize;
- IA32_DESCRIPTOR Gdtr;
- VOID *GdtBuffer;
- AsmReadGdtr ((IA32_DESCRIPTOR *)&Gdtr);
- GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1;
- Status = PeiServicesAllocatePool (
- GdtBufferSize,
- &GdtBuffer
- );
- ASSERT (GdtBuffer != NULL);
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
- GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR));
- CopyMem (GdtBuffer, (VOID *)Gdtr.Base, Gdtr.Limit + 1);
- Gdtr.Base = (UINTN)GdtBuffer;
- AsmWriteGdtr (&Gdtr);
- return EFI_SUCCESS;
- }
- //
- // 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
- NORETURN
- EFIAPI
- SecStartupPhase2 (
- IN VOID *Context
- );
- /**
- Entry point of the notification callback function itself within the PEIM.
- It is to get SEC performance data and build HOB to convey the SEC performance
- data to DXE phase.
- @param PeiServices Indirect reference to the PEI Services Table.
- @param NotifyDescriptor Address of the notification descriptor data structure.
- @param Ppi Address of the PPI that was installed.
- @return Status of the notification.
- The status code returned from this function is ignored.
- **/
- EFI_STATUS
- EFIAPI
- SecPerformancePpiCallBack (
- IN EFI_PEI_SERVICES **PeiServices,
- IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
- IN VOID *Ppi
- )
- {
- EFI_STATUS Status;
- PEI_SEC_PERFORMANCE_PPI *SecPerf;
- FIRMWARE_SEC_PERFORMANCE Performance;
- SecPerf = (PEI_SEC_PERFORMANCE_PPI *)Ppi;
- Status = SecPerf->GetPerformance ((CONST EFI_PEI_SERVICES **)PeiServices, SecPerf, &Performance);
- if (!EFI_ERROR (Status)) {
- BuildGuidDataHob (
- &gEfiFirmwarePerformanceGuid,
- &Performance,
- sizeof (FIRMWARE_SEC_PERFORMANCE)
- );
- DEBUG ((DEBUG_INFO, "FPDT: SEC Performance Hob ResetEnd = %ld\n", Performance.ResetEnd));
- }
- return Status;
- }
- /**
- 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 SizeOfRam Size of the temporary memory available for use.
- @param TempRamBase Base address of temporary ram
- @param BootFirmwareVolume Base address of the Boot Firmware Volume.
- **/
- VOID
- NORETURN
- 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;
- EFI_STATUS Status;
- //
- // Report Status Code to indicate entering SEC core
- //
- REPORT_STATUS_CODE (
- EFI_PROGRESS_CODE,
- EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT
- );
- DEBUG ((
- DEBUG_INFO,
- "%a() TempRAM Base: 0x%x, TempRAM Size: 0x%x, BootFirmwareVolume 0x%x\n",
- __FUNCTION__,
- TempRamBase,
- SizeOfRam,
- BootFirmwareVolume
- ));
- PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);
- if (PeiStackSize == 0) {
- PeiStackSize = (SizeOfRam >> 1);
- }
- ASSERT (PeiStackSize < SizeOfRam);
- //
- // Process all libraries constructor function linked to SecCore.
- //
- ProcessLibraryConstructorList ();
- //
- // 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++) {
- ZeroMem ((VOID *)&IdtTableInStack.IdtTable[Index], sizeof (IA32_IDT_GATE_DESCRIPTOR));
- CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&mIdtEntryTemplate, sizeof (UINT64));
- }
- IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
- IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
- AsmWriteIdtr (&IdtDescriptor);
- //
- // Setup the default exception handlers
- //
- Status = InitializeCpuExceptionHandlers (NULL);
- ASSERT_EFI_ERROR (Status);
- //
- // 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)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
- 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,
- "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n",
- __FUNCTION__,
- SecCoreData.BootFirmwareVolumeBase,
- SecCoreData.BootFirmwareVolumeSize,
- SecCoreData.TemporaryRamBase,
- SecCoreData.TemporaryRamSize,
- SecCoreData.PeiTemporaryRamBase,
- SecCoreData.PeiTemporaryRamSize,
- SecCoreData.StackBase,
- 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);
- //
- // Should not come here.
- //
- UNREACHABLE ();
- }
- /**
- 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
- NORETURN
- EFIAPI
- SecStartupPhase2 (
- IN VOID *Context
- )
- {
- EFI_SEC_PEI_HAND_OFF *SecCoreData;
- EFI_PEI_PPI_DESCRIPTOR *PpiList;
- UINT32 Index;
- EFI_PEI_PPI_DESCRIPTOR *AllSecPpiList;
- EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
- PeiCoreEntryPoint = NULL;
- SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;
- //
- // Perform platform specific initialization before entering PeiCore.
- //
- PpiList = SecPlatformMain (SecCoreData);
- //
- // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
- // is enabled.
- //
- if (PpiList != NULL) {
- Index = 0;
- do {
- if (CompareGuid (PpiList[Index].Guid, &gEfiPeiCoreFvLocationPpiGuid) &&
- (((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation != 0)
- )
- {
- //
- // In this case, SecCore is in BFV but PeiCore is in another FV reported by PPI.
- //
- FindAndReportEntryPoints (
- (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,
- (EFI_FIRMWARE_VOLUME_HEADER *)((EFI_PEI_CORE_FV_LOCATION_PPI *)PpiList[Index].Ppi)->PeiCoreFvLocation,
- &PeiCoreEntryPoint
- );
- if (PeiCoreEntryPoint != NULL) {
- break;
- } else {
- //
- // Invalid PeiCore FV provided by platform
- //
- CpuDeadLoop ();
- }
- }
- } while ((PpiList[Index++].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
- }
- //
- // If EFI_PEI_CORE_FV_LOCATION_PPI not found, try to locate PeiCore from BFV.
- //
- if (PeiCoreEntryPoint == NULL) {
- //
- // Both SecCore and PeiCore are in BFV.
- //
- FindAndReportEntryPoints (
- (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,
- (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase,
- &PeiCoreEntryPoint
- );
- if (PeiCoreEntryPoint == NULL) {
- CpuDeadLoop ();
- }
- }
- DEBUG ((
- DEBUG_INFO,
- "%a() PeiCoreEntryPoint: 0x%x\n",
- __FUNCTION__,
- PeiCoreEntryPoint
- ));
- if (PpiList != NULL) {
- AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *)SecCoreData->PeiTemporaryRamBase;
- //
- // Remove the terminal flag from the terminal PPI
- //
- CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
- Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;
- AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
- //
- // Append the platform additional PPI list
- //
- Index += 1;
- while (((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++;
- }
- //
- // Add the terminal PPI
- //
- CopyMem (&AllSecPpiList[Index++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
- //
- // Set PpiList to the total PPI
- //
- PpiList = AllSecPpiList;
- //
- // Adjust PEI TEMP RAM Range.
- //
- ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
- SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN)SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
- SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);
- //
- // Adjust the Base and Size to be 8-byte aligned as HOB which has 8byte aligned requirement
- // will be built based on them in PEI phase.
- //
- SecCoreData->PeiTemporaryRamBase = (VOID *)(((UINTN)SecCoreData->PeiTemporaryRamBase + 7) & ~0x07);
- SecCoreData->PeiTemporaryRamSize &= ~(UINTN)0x07;
- DEBUG ((
- DEBUG_INFO,
- "%a() PeiTemporaryRamBase: 0x%x, PeiTemporaryRamSize: 0x%x\n",
- __FUNCTION__,
- SecCoreData->PeiTemporaryRamBase,
- SecCoreData->PeiTemporaryRamSize
- ));
- } else {
- //
- // No addition PPI, PpiList directly point to the common PPI list.
- //
- PpiList = &mPeiSecPlatformInformationPpi[0];
- }
- DEBUG ((
- DEBUG_INFO,
- "%a() Stack Base: 0x%p, Stack Size: 0x%x\n",
- __FUNCTION__,
- SecCoreData->StackBase,
- (UINT32)SecCoreData->StackSize
- ));
- //
- // Report Status Code to indicate transferring to PEI core
- //
- REPORT_STATUS_CODE (
- EFI_PROGRESS_CODE,
- EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
- );
- //
- // Transfer the control to the PEI core
- //
- ASSERT (PeiCoreEntryPoint != NULL);
- (*PeiCoreEntryPoint)(SecCoreData, PpiList);
- //
- // Should not come here.
- //
- UNREACHABLE ();
- }
- /**
- TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
- by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
- @retval EFI_SUCCESS Use of Temporary RAM was disabled.
- @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
- **/
- EFI_STATUS
- EFIAPI
- SecTemporaryRamDone (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_STATUS Status2;
- UINTN Index;
- BOOLEAN State;
- EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;
- REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;
- //
- // Republish Sec Platform Information(2) PPI
- //
- RepublishSecPlatformInformationPpi ();
- //
- // Re-install SEC PPIs using a PEIM produced service if published
- //
- for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {
- Status = PeiServicesLocatePpi (
- &gRepublishSecPpiPpiGuid,
- Index,
- &PeiPpiDescriptor,
- (VOID **)&RepublishSecPpiPpi
- );
- if (!EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));
- Status2 = RepublishSecPpiPpi->RepublishSecPpis ();
- ASSERT_EFI_ERROR (Status2);
- }
- }
- //
- // Migrate DebugAgentContext.
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
- //
- // Disable interrupts and save current interrupt state
- //
- State = SaveAndDisableInterrupts ();
- //
- // Migrate GDT before NEM near down
- //
- if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
- Status = MigrateGdt ();
- ASSERT_EFI_ERROR (Status);
- }
- //
- // Disable Temporary RAM after Stack and Heap have been migrated at this point.
- //
- SecPlatformDisableTemporaryMemory ();
- //
- // Restore original interrupt state
- //
- SetInterruptState (State);
- return EFI_SUCCESS;
- }
|