/*++ Routine Description: Arguments: FileHandle - Handle of the file being invoked. PeiServices - Describes the list of possible PEI Services. Returns: Status - EFI_SUCCESS if the boot mode could be set --*/ EFI_STATUS EFIAPI InitializeCpuPeim ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { EFI_STATUS Status; ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi; UINTN ArmCoreCount; ARM_CORE_INFO *ArmCoreInfoTable; // Enable program flow prediction, if supported. ArmEnableBranchPrediction (); // Publish the CPU memory and io spaces sizes BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize)); // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid Status = PeiServicesLocatePpi (&gArmMpCoreInfoPpiGuid, 0, NULL, (VOID**)&ArmMpCoreInfoPpi); if (!EFI_ERROR(Status)) { // Build the MP Core Info Table ArmCoreCount = 0; Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable); if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) { // Build MPCore Info HOB BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount); } } return EFI_SUCCESS; }
/* * This is the main function for secondary cores. They loop around until a non Null value is written to * SYS_FLAGS register.The SYS_FLAGS register is platform specific. * Note:The secondary cores, while executing secondary_main, assumes that: * : SGI 0 is configured as Non-secure interrupt * : Priority Mask is configured to allow SGI 0 * : Interrupt Distributor and CPU interfaces are enabled * */ VOID EFIAPI SecondaryMain ( IN UINTN MpId ) { EFI_STATUS Status; UINTN PpiListSize; UINTN PpiListCount; EFI_PEI_PPI_DESCRIPTOR *PpiList; ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi; UINTN Index; UINTN ArmCoreCount; ARM_CORE_INFO *ArmCoreInfoTable; UINT32 ClusterId; UINT32 CoreId; VOID (*SecondaryStart)(VOID); UINTN SecondaryEntryAddr; UINTN AcknowledgeInterrupt; UINTN InterruptId; ClusterId = GET_CLUSTER_ID(MpId); CoreId = GET_CORE_ID(MpId); // Get the gArmMpCoreInfoPpiGuid PpiListSize = 0; ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList); PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR); for (Index = 0; Index < PpiListCount; Index++, PpiList++) { if (CompareGuid (PpiList->Guid, &gArmMpCoreInfoPpiGuid) == TRUE) { break; } } // On MP Core Platform we must implement the ARM MP Core Info PPI ASSERT (Index != PpiListCount); ArmMpCoreInfoPpi = PpiList->Ppi; ArmCoreCount = 0; Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable); ASSERT_EFI_ERROR (Status); // Find the core in the ArmCoreTable for (Index = 0; Index < ArmCoreCount; Index++) { if ((ArmCoreInfoTable[Index].ClusterId == ClusterId) && (ArmCoreInfoTable[Index].CoreId == CoreId)) { break; } } // The ARM Core Info Table must define every core ASSERT (Index != ArmCoreCount); // Clear Secondary cores MailBox MmioWrite32 (ArmCoreInfoTable[Index].MailboxClearAddress, ArmCoreInfoTable[Index].MailboxClearValue); do { ArmCallWFI (); // Read the Mailbox SecondaryEntryAddr = MmioRead32 (ArmCoreInfoTable[Index].MailboxGetAddress); // Acknowledge the interrupt and send End of Interrupt signal. AcknowledgeInterrupt = ArmGicAcknowledgeInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), &InterruptId); // Check if it is a valid interrupt ID if (InterruptId < ArmGicGetMaxNumInterrupts (PcdGet32 (PcdGicDistributorBase))) { // Got a valid SGI number hence signal End of Interrupt ArmGicEndOfInterrupt (PcdGet32 (PcdGicInterruptInterfaceBase), AcknowledgeInterrupt); } } while (SecondaryEntryAddr == 0); // Jump to secondary core entry point. SecondaryStart = (VOID (*)())SecondaryEntryAddr; SecondaryStart(); // The secondaries shouldn't reach here ASSERT(FALSE); }
VOID PrePiMain ( IN UINTN UefiMemoryBase, IN UINTN StacksBase, IN UINT64 StartTimeStamp ) { EFI_HOB_HANDOFF_INFO_TABLE* HobList; ARM_MP_CORE_INFO_PPI* ArmMpCoreInfoPpi; UINTN ArmCoreCount; ARM_CORE_INFO* ArmCoreInfoTable; EFI_STATUS Status; CHAR8 Buffer[100]; UINTN CharCount; UINTN StacksSize; // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP) ASSERT (IS_XIP() || ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) && ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd))); // Initialize the architecture specific bits ArchInitialize (); // Initialize the Serial Port SerialPortInitialize (); CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r", (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); SerialPortWrite ((UINT8 *) Buffer, CharCount); // Initialize the Debug Agent for Source Level Debugging InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL); SaveAndSetDebugTimerInterrupt (TRUE); // Declare the PI/UEFI memory region HobList = HobConstructor ( (VOID*)UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize), (VOID*)UefiMemoryBase, (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks ); PrePeiSetHobList (HobList); // Initialize MMU and Memory HOBs (Resource Descriptor HOBs) Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)); ASSERT_EFI_ERROR (Status); // Create the Stacks HOB (reserve the memory for all stacks) if (ArmIsMpCore ()) { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize)); } else { StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize); } BuildStackHob (StacksBase, StacksSize); //TODO: Call CpuPei as a library BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize)); if (ArmIsMpCore ()) { // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi); // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid) ASSERT_EFI_ERROR (Status); // Build the MP Core Info Table ArmCoreCount = 0; Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable); if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) { // Build MPCore Info HOB BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount); } } // Set the Boot Mode SetBootMode (ArmPlatformGetBootMode ()); // Initialize Platform HOBs (CpuHob and FvHob) Status = PlatformPeim (); ASSERT_EFI_ERROR (Status); // Now, the HOB List has been initialized, we can register performance information PERF_START (NULL, "PEI", NULL, StartTimeStamp); // SEC phase needs to run library constructors by hand. ExtractGuidedSectionLibConstructor (); LzmaDecompressLibConstructor (); // Build HOBs to pass up our version of stuff the DXE Core needs to save space BuildPeCoffLoaderHob (); BuildExtractSectionHob ( &gLzmaCustomDecompressGuid, LzmaGuidedSectionGetInfo, LzmaGuidedSectionExtraction ); // Assume the FV that contains the SEC (our code) also contains a compressed FV. Status = DecompressFirstFv (); ASSERT_EFI_ERROR (Status); // Load the DXE Core and transfer control to it Status = LoadDxeCoreFromFv (NULL, 0); ASSERT_EFI_ERROR (Status); }