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