1 /** @file
2   C functions in SEC
3 
4   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 
10 #include "SecMain.h"
11 
12 EFI_PEI_PPI_DESCRIPTOR            mPeiSecMainPpi[] = {
13   {
14     EFI_PEI_PPI_DESCRIPTOR_PPI,
15     &gTopOfTemporaryRamPpiGuid,
16     NULL // To be patched later.
17   },
18   {
19     EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
20     &gFspInitDonePpiGuid,
21     &gFspInitDonePpi
22   },
23 };
24 
25 FSP_INIT_DONE_PPI gFspInitDonePpi = {
26   FspInitDoneGetFspHobList
27 };
28 
29 //
30 // These are IDT entries pointing to 10:FFFFFFE4h.
31 //
32 UINT64  mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
33 
34 /**
35   Caller provided function to be invoked at the end of InitializeDebugAgent().
36 
37   Entry point to the C language phase of SEC. After the SEC assembly
38   code has initialized some temporary memory and set up the stack,
39   the control is transferred to this function.
40 
41   @param[in] Context    The first input parameter of InitializeDebugAgent().
42 
43 **/
44 VOID
45 EFIAPI
46 SecStartupPhase2(
47   IN VOID                     *Context
48   );
49 
50 
51 /**
52 
53   Entry point to the C language phase of SEC. After the SEC assembly
54   code has initialized some temporary memory and set up the stack,
55   the control is transferred to this function.
56 
57   @param[in] SizeOfRam           Size of the temporary memory available for use.
58   @param[in] TempRamBase         Base address of temporary ram
59   @param[in] BootFirmwareVolume  Base address of the Boot Firmware Volume.
60 **/
61 VOID
62 EFIAPI
SecStartup(IN UINT32 SizeOfRam,IN UINT32 TempRamBase,IN VOID * BootFirmwareVolume)63 SecStartup (
64   IN UINT32                   SizeOfRam,
65   IN UINT32                   TempRamBase,
66   IN VOID                     *BootFirmwareVolume
67   )
68 {
69   EFI_SEC_PEI_HAND_OFF        SecCoreData;
70   IA32_DESCRIPTOR             IdtDescriptor;
71   SEC_IDT_TABLE               IdtTableInStack;
72   UINT32                      Index;
73   UINT32                      PeiStackSize;
74 
75   PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);
76   if (PeiStackSize == 0) {
77     PeiStackSize = (SizeOfRam >> 1);
78   }
79 
80   ASSERT (PeiStackSize < SizeOfRam);
81 
82   //
83   // Process all libraries constructor function linked to SecCore.
84   //
85   ProcessLibraryConstructorList ();
86 
87   DEBUG ((DEBUG_INFO, "FspPei - SecStartup\n"));
88 
89   //
90   // Initialize floating point operating environment
91   // to be compliant with UEFI spec.
92   //
93   InitializeFloatingPointUnits ();
94 
95 
96   // |-------------------|---->
97   // |Idt Table          |
98   // |-------------------|
99   // |PeiService Pointer |    PeiStackSize
100   // |-------------------|
101   // |                   |
102   // |      Stack        |
103   // |-------------------|---->
104   // |                   |
105   // |                   |
106   // |      Heap         |    PeiTemporayRamSize
107   // |                   |
108   // |                   |
109   // |-------------------|---->  TempRamBase
110 
111   IdtTableInStack.PeiService = 0;
112   for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
113     CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
114   }
115 
116   IdtDescriptor.Base  = (UINTN) &IdtTableInStack.IdtTable;
117   IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
118 
119   AsmWriteIdtr (&IdtDescriptor);
120 
121   //
122   // Update the base address and length of Pei temporary memory
123   //
124   SecCoreData.DataSize               = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
125   SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
126   SecCoreData.BootFirmwareVolumeSize = (UINTN)(SIZE_4GB - (UINTN) BootFirmwareVolume);
127   SecCoreData.TemporaryRamBase       = (VOID*)(UINTN) TempRamBase;
128   SecCoreData.TemporaryRamSize       = SizeOfRam;
129   SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
130   SecCoreData.PeiTemporaryRamSize    = SizeOfRam - PeiStackSize;
131   SecCoreData.StackBase              = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
132   SecCoreData.StackSize              = PeiStackSize;
133 
134   DEBUG ((DEBUG_INFO, "BootFirmwareVolumeBase - 0x%x\n", SecCoreData.BootFirmwareVolumeBase));
135   DEBUG ((DEBUG_INFO, "BootFirmwareVolumeSize - 0x%x\n", SecCoreData.BootFirmwareVolumeSize));
136   DEBUG ((DEBUG_INFO, "TemporaryRamBase       - 0x%x\n", SecCoreData.TemporaryRamBase));
137   DEBUG ((DEBUG_INFO, "TemporaryRamSize       - 0x%x\n", SecCoreData.TemporaryRamSize));
138   DEBUG ((DEBUG_INFO, "PeiTemporaryRamBase    - 0x%x\n", SecCoreData.PeiTemporaryRamBase));
139   DEBUG ((DEBUG_INFO, "PeiTemporaryRamSize    - 0x%x\n", SecCoreData.PeiTemporaryRamSize));
140   DEBUG ((DEBUG_INFO, "StackBase              - 0x%x\n", SecCoreData.StackBase));
141   DEBUG ((DEBUG_INFO, "StackSize              - 0x%x\n", SecCoreData.StackSize));
142 
143   //
144   // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
145   //
146   InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
147 
148 }
149 
150 /**
151   This API patch the TopOfTemporaryRam value in SecPpiList.
152 
153   @param[in,out] SecPpiList           PPI list to be patched.
154   @param[in]     TopOfTemporaryRam    The top of Temporary Ram.
155 
156 **/
157 VOID
PatchTopOfTemporaryRamPpi(IN OUT EFI_PEI_PPI_DESCRIPTOR * SecPpiList,IN VOID * TopOfTemporaryRam)158 PatchTopOfTemporaryRamPpi (
159   IN OUT EFI_PEI_PPI_DESCRIPTOR *SecPpiList,
160   IN VOID                       *TopOfTemporaryRam
161   )
162 {
163   SecPpiList[0].Ppi = TopOfTemporaryRam;
164 }
165 
166 /**
167   Caller provided function to be invoked at the end of InitializeDebugAgent().
168 
169   Entry point to the C language phase of SEC. After the SEC assembly
170   code has initialized some temporary memory and set up the stack,
171   the control is transferred to this function.
172 
173   @param[in] Context    The first input parameter of InitializeDebugAgent().
174 
175 **/
176 VOID
177 EFIAPI
SecStartupPhase2(IN VOID * Context)178 SecStartupPhase2(
179   IN VOID                     *Context
180   )
181 {
182   EFI_SEC_PEI_HAND_OFF        *SecCoreData;
183   EFI_PEI_PPI_DESCRIPTOR      *PpiList;
184   UINT32                      Index;
185   EFI_PEI_PPI_DESCRIPTOR      LocalSecPpiList[sizeof(mPeiSecMainPpi)/sizeof(mPeiSecMainPpi[0])];
186   EFI_PEI_PPI_DESCRIPTOR      AllSecPpiList[FixedPcdGet32(PcdSecCoreMaxPpiSupported)];
187   EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
188 
189   SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
190   //
191   // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
192   // is enabled.
193   //
194   FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
195   if (PeiCoreEntryPoint == NULL)
196   {
197     CpuDeadLoop ();
198   }
199 
200   CopyMem (LocalSecPpiList, mPeiSecMainPpi, sizeof(mPeiSecMainPpi));
201   PatchTopOfTemporaryRamPpi (LocalSecPpiList, (VOID *)((UINTN)SecCoreData->TemporaryRamBase + SecCoreData->TemporaryRamSize));
202 
203   //
204   // Perform platform specific initialization before entering PeiCore.
205   //
206   PpiList = SecPlatformMain (SecCoreData);
207   if (PpiList != NULL) {
208     //
209     // Remove the terminal flag from the terminal Ppi
210     //
211     CopyMem (AllSecPpiList, LocalSecPpiList, sizeof (LocalSecPpiList));
212     for (Index = 0; Index < PcdGet32 (PcdSecCoreMaxPpiSupported); Index ++) {
213       if ((AllSecPpiList[Index].Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) {
214         break;
215       }
216     }
217     AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
218 
219     //
220     // Append the platform additional Ppi list
221     //
222     Index += 1;
223     while (Index < PcdGet32 (PcdSecCoreMaxPpiSupported) &&
224            ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
225       CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
226       Index++;
227       PpiList++;
228     }
229 
230     //
231     // Check whether the total Ppis exceeds the max supported Ppi.
232     //
233     if (Index >= PcdGet32 (PcdSecCoreMaxPpiSupported)) {
234       //
235       // the total Ppi is larger than the supported Max
236       // PcdSecCoreMaxPpiSupported can be enlarged to solve it.
237       //
238       CpuDeadLoop ();
239     } else {
240       //
241       // Add the terminal Ppi
242       //
243       CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
244     }
245 
246     //
247     // Set PpiList to the total Ppi
248     //
249     PpiList = &AllSecPpiList[0];
250   } else {
251     //
252     // No addition Ppi, PpiList directly point to the common Ppi list.
253     //
254     PpiList = &LocalSecPpiList[0];
255   }
256 
257   //
258   // Transfer the control to the PEI core
259   //
260   ASSERT (PeiCoreEntryPoint != NULL);
261   (*PeiCoreEntryPoint) (SecCoreData, PpiList);
262 
263   //
264   // Should not come here.
265   //
266   return ;
267 }
268 
269 /**
270   Return Hob list produced by FSP.
271 
272   @param[in]  PeiServices  The pointer to the PEI Services Table.
273   @param[in]  This         The pointer to this instance of this PPI.
274   @param[out] FspHobList   The pointer to Hob list produced by FSP.
275 
276   @return EFI_SUCCESS FReturn Hob list produced by FSP successfully.
277 **/
278 EFI_STATUS
279 EFIAPI
FspInitDoneGetFspHobList(IN CONST EFI_PEI_SERVICES ** PeiServices,IN FSP_INIT_DONE_PPI * This,OUT VOID ** FspHobList)280 FspInitDoneGetFspHobList (
281   IN  CONST EFI_PEI_SERVICES         **PeiServices,
282   IN  FSP_INIT_DONE_PPI              *This,
283   OUT VOID                           **FspHobList
284   )
285 {
286   VOID        *TopOfTemporaryRamPpi;
287   EFI_STATUS  Status;
288 
289   Status = (*PeiServices)->LocatePpi (
290                              PeiServices,
291                              &gTopOfTemporaryRamPpiGuid,
292                              0,
293                              NULL,
294                              (VOID **) &TopOfTemporaryRamPpi
295                              );
296   if (EFI_ERROR (Status)) {
297     return EFI_NOT_FOUND;
298   }
299 
300   *FspHobList = (VOID *)(UINTN)(*(UINT32 *)((UINTN)TopOfTemporaryRamPpi - sizeof(UINT32)));
301 
302   return EFI_SUCCESS;
303 }
304 
305