• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
GetPlatformPpi(IN EFI_GUID * PpiGuid,OUT VOID ** Ppi)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
PrePiMain(IN UINTN UefiMemoryBase,IN UINTN StacksBase,IN UINT64 StartTimeStamp)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
CEntryPoint(IN UINTN MpId,IN UINTN UefiMemoryBase,IN UINTN StacksBase)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