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