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