1 /** @file 2 * 3 * Copyright (c) 2011-2014, ARM Limited. All rights reserved. 4 * 5 * This program and the accompanying materials 6 * are licensed and made available under the terms and conditions of the BSD License 7 * which accompanies this distribution. The full text of the license may be found at 8 * http://opensource.org/licenses/bsd-license.php 9 * 10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 * 13 **/ 14 15 #include <PiPei.h> 16 17 #include <Library/DebugAgentLib.h> 18 #include <Library/PrePiLib.h> 19 #include <Library/PrintLib.h> 20 #include <Library/PeCoffGetEntryPointLib.h> 21 #include <Library/PrePiHobListPointerLib.h> 22 #include <Library/TimerLib.h> 23 #include <Library/PerformanceLib.h> 24 25 #include <Ppi/GuidedSectionExtraction.h> 26 #include <Ppi/ArmMpCoreInfo.h> 27 #include <Guid/LzmaDecompress.h> 28 29 #include "PrePi.h" 30 #include "LzmaDecompress.h" 31 32 #define IS_XIP() (((UINT64)FixedPcdGet64 (PcdFdBaseAddress) > mSystemMemoryEnd) || \ 33 ((FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) < FixedPcdGet64 (PcdSystemMemoryBase))) 34 35 UINT64 mSystemMemoryEnd = FixedPcdGet64(PcdSystemMemoryBase) + 36 FixedPcdGet64(PcdSystemMemorySize) - 1; 37 38 EFI_STATUS 39 EFIAPI 40 ExtractGuidedSectionLibConstructor ( 41 VOID 42 ); 43 44 EFI_STATUS 45 EFIAPI 46 LzmaDecompressLibConstructor ( 47 VOID 48 ); 49 50 EFI_STATUS 51 GetPlatformPpi ( 52 IN EFI_GUID *PpiGuid, 53 OUT VOID **Ppi 54 ) 55 { 56 UINTN PpiListSize; 57 UINTN PpiListCount; 58 EFI_PEI_PPI_DESCRIPTOR *PpiList; 59 UINTN Index; 60 61 PpiListSize = 0; 62 ArmPlatformGetPlatformPpiList (&PpiListSize, &PpiList); 63 PpiListCount = PpiListSize / sizeof(EFI_PEI_PPI_DESCRIPTOR); 64 for (Index = 0; Index < PpiListCount; Index++, PpiList++) { 65 if (CompareGuid (PpiList->Guid, PpiGuid) == TRUE) { 66 *Ppi = PpiList->Ppi; 67 return EFI_SUCCESS; 68 } 69 } 70 71 return EFI_NOT_FOUND; 72 } 73 74 VOID 75 PrePiMain ( 76 IN UINTN UefiMemoryBase, 77 IN UINTN StacksBase, 78 IN UINT64 StartTimeStamp 79 ) 80 { 81 EFI_HOB_HANDOFF_INFO_TABLE* HobList; 82 ARM_MP_CORE_INFO_PPI* ArmMpCoreInfoPpi; 83 UINTN ArmCoreCount; 84 ARM_CORE_INFO* ArmCoreInfoTable; 85 EFI_STATUS Status; 86 CHAR8 Buffer[100]; 87 UINTN CharCount; 88 UINTN StacksSize; 89 90 // If ensure the FD is either part of the System Memory or totally outside of the System Memory (XIP) 91 ASSERT (IS_XIP() || 92 ((FixedPcdGet64 (PcdFdBaseAddress) >= FixedPcdGet64 (PcdSystemMemoryBase)) && 93 ((UINT64)(FixedPcdGet64 (PcdFdBaseAddress) + FixedPcdGet32 (PcdFdSize)) <= (UINT64)mSystemMemoryEnd))); 94 95 // Initialize the architecture specific bits 96 ArchInitialize (); 97 98 // Initialize the Serial Port 99 SerialPortInitialize (); 100 CharCount = AsciiSPrint (Buffer,sizeof (Buffer),"UEFI firmware (version %s built at %a on %a)\n\r", 101 (CHAR16*)PcdGetPtr(PcdFirmwareVersionString), __TIME__, __DATE__); 102 SerialPortWrite ((UINT8 *) Buffer, CharCount); 103 104 // Initialize the Debug Agent for Source Level Debugging 105 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL); 106 SaveAndSetDebugTimerInterrupt (TRUE); 107 108 // Declare the PI/UEFI memory region 109 HobList = HobConstructor ( 110 (VOID*)UefiMemoryBase, 111 FixedPcdGet32 (PcdSystemMemoryUefiRegionSize), 112 (VOID*)UefiMemoryBase, 113 (VOID*)StacksBase // The top of the UEFI Memory is reserved for the stacks 114 ); 115 PrePeiSetHobList (HobList); 116 117 // Initialize MMU and Memory HOBs (Resource Descriptor HOBs) 118 Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize)); 119 ASSERT_EFI_ERROR (Status); 120 121 // Create the Stacks HOB (reserve the memory for all stacks) 122 if (ArmIsMpCore ()) { 123 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize) + 124 ((FixedPcdGet32 (PcdCoreCount) - 1) * FixedPcdGet32 (PcdCPUCoreSecondaryStackSize)); 125 } else { 126 StacksSize = PcdGet32 (PcdCPUCorePrimaryStackSize); 127 } 128 BuildStackHob (StacksBase, StacksSize); 129 130 //TODO: Call CpuPei as a library 131 BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize)); 132 133 if (ArmIsMpCore ()) { 134 // Only MP Core platform need to produce gArmMpCoreInfoPpiGuid 135 Status = GetPlatformPpi (&gArmMpCoreInfoPpiGuid, (VOID**)&ArmMpCoreInfoPpi); 136 137 // On MP Core Platform we must implement the ARM MP Core Info PPI (gArmMpCoreInfoPpiGuid) 138 ASSERT_EFI_ERROR (Status); 139 140 // Build the MP Core Info Table 141 ArmCoreCount = 0; 142 Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable); 143 if (!EFI_ERROR(Status) && (ArmCoreCount > 0)) { 144 // Build MPCore Info HOB 145 BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount); 146 } 147 } 148 149 // Set the Boot Mode 150 SetBootMode (ArmPlatformGetBootMode ()); 151 152 // Initialize Platform HOBs (CpuHob and FvHob) 153 Status = PlatformPeim (); 154 ASSERT_EFI_ERROR (Status); 155 156 // Now, the HOB List has been initialized, we can register performance information 157 PERF_START (NULL, "PEI", NULL, StartTimeStamp); 158 159 // SEC phase needs to run library constructors by hand. 160 ExtractGuidedSectionLibConstructor (); 161 LzmaDecompressLibConstructor (); 162 163 // Build HOBs to pass up our version of stuff the DXE Core needs to save space 164 BuildPeCoffLoaderHob (); 165 BuildExtractSectionHob ( 166 &gLzmaCustomDecompressGuid, 167 LzmaGuidedSectionGetInfo, 168 LzmaGuidedSectionExtraction 169 ); 170 171 // Assume the FV that contains the SEC (our code) also contains a compressed FV. 172 Status = DecompressFirstFv (); 173 ASSERT_EFI_ERROR (Status); 174 175 // Load the DXE Core and transfer control to it 176 Status = LoadDxeCoreFromFv (NULL, 0); 177 ASSERT_EFI_ERROR (Status); 178 } 179 180 VOID 181 CEntryPoint ( 182 IN UINTN MpId, 183 IN UINTN UefiMemoryBase, 184 IN UINTN StacksBase 185 ) 186 { 187 UINT64 StartTimeStamp; 188 189 // Initialize the platform specific controllers 190 ArmPlatformInitialize (MpId); 191 192 if (ArmPlatformIsPrimaryCore (MpId) && PerformanceMeasurementEnabled ()) { 193 // Initialize the Timer Library to setup the Timer HW controller 194 TimerConstructor (); 195 // We cannot call yet the PerformanceLib because the HOB List has not been initialized 196 StartTimeStamp = GetPerformanceCounter (); 197 } else { 198 StartTimeStamp = 0; 199 } 200 201 // Data Cache enabled on Primary core when MMU is enabled. 202 ArmDisableDataCache (); 203 // Invalidate Data cache 204 ArmInvalidateDataCache (); 205 // Invalidate instruction cache 206 ArmInvalidateInstructionCache (); 207 // Enable Instruction Caches on all cores. 208 ArmEnableInstructionCache (); 209 210 // Define the Global Variable region when we are not running in XIP 211 if (!IS_XIP()) { 212 if (ArmPlatformIsPrimaryCore (MpId)) { 213 if (ArmIsMpCore()) { 214 // Signal the Global Variable Region is defined (event: ARM_CPU_EVENT_DEFAULT) 215 ArmCallSEV (); 216 } 217 } else { 218 // Wait the Primay core has defined the address of the Global Variable region (event: ARM_CPU_EVENT_DEFAULT) 219 ArmCallWFE (); 220 } 221 } 222 223 // If not primary Jump to Secondary Main 224 if (ArmPlatformIsPrimaryCore (MpId)) { 225 // Goto primary Main. 226 PrimaryMain (UefiMemoryBase, StacksBase, StartTimeStamp); 227 } else { 228 SecondaryMain (MpId); 229 } 230 231 // DXE Core should always load and never return 232 ASSERT (FALSE); 233 } 234 235