1 /** @file
2   C functions in SEC
3 
4   Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
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 "SecMain.h"
16 
17 EFI_PEI_TEMPORARY_RAM_DONE_PPI gSecTemporaryRamDonePpi = {
18   SecTemporaryRamDone
19 };
20 
21 EFI_SEC_PLATFORM_INFORMATION_PPI  mSecPlatformInformationPpi = { SecPlatformInformation };
22 
23 EFI_PEI_PPI_DESCRIPTOR            mPeiSecPlatformInformationPpi[] = {
24   {
25     EFI_PEI_PPI_DESCRIPTOR_PPI,
26     &gEfiTemporaryRamDonePpiGuid,
27     &gSecTemporaryRamDonePpi
28   },
29   {
30     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
31     &gEfiSecPlatformInformationPpiGuid,
32     &mSecPlatformInformationPpi
33   }
34 };
35 
36 //
37 // These are IDT entries pointing to 10:FFFFFFE4h.
38 //
39 UINT64  mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
40 
41 /**
42   Caller provided function to be invoked at the end of InitializeDebugAgent().
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] Context    The first input parameter of InitializeDebugAgent().
49 
50 **/
51 VOID
52 EFIAPI
53 SecStartupPhase2(
54   IN VOID                     *Context
55   );
56 
57 /**
58 
59   Entry point to the C language phase of SEC. After the SEC assembly
60   code has initialized some temporary memory and set up the stack,
61   the control is transferred to this function.
62 
63 
64   @param SizeOfRam           Size of the temporary memory available for use.
65   @param TempRamBase         Base address of temporary ram
66   @param BootFirmwareVolume  Base address of the Boot Firmware Volume.
67 **/
68 VOID
69 EFIAPI
SecStartup(IN UINT32 SizeOfRam,IN UINT32 TempRamBase,IN VOID * BootFirmwareVolume)70 SecStartup (
71   IN UINT32                   SizeOfRam,
72   IN UINT32                   TempRamBase,
73   IN VOID                     *BootFirmwareVolume
74   )
75 {
76   EFI_SEC_PEI_HAND_OFF        SecCoreData;
77   IA32_DESCRIPTOR             IdtDescriptor;
78   SEC_IDT_TABLE               IdtTableInStack;
79   UINT32                      Index;
80   UINT32                      PeiStackSize;
81   EFI_STATUS                  Status;
82 
83   //
84   // Report Status Code to indicate entering SEC core
85   //
86   REPORT_STATUS_CODE (
87     EFI_PROGRESS_CODE,
88     EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_ENTRY_POINT
89     );
90 
91   PeiStackSize = PcdGet32 (PcdPeiTemporaryRamStackSize);
92   if (PeiStackSize == 0) {
93     PeiStackSize = (SizeOfRam >> 1);
94   }
95 
96   ASSERT (PeiStackSize < SizeOfRam);
97 
98   //
99   // Process all libraries constructor function linked to SecCore.
100   //
101   ProcessLibraryConstructorList ();
102 
103   //
104   // Initialize floating point operating environment
105   // to be compliant with UEFI spec.
106   //
107   InitializeFloatingPointUnits ();
108 
109   // |-------------------|---->
110   // |IDT Table          |
111   // |-------------------|
112   // |PeiService Pointer |    PeiStackSize
113   // |-------------------|
114   // |                   |
115   // |      Stack        |
116   // |-------------------|---->
117   // |                   |
118   // |                   |
119   // |      Heap         |    PeiTemporayRamSize
120   // |                   |
121   // |                   |
122   // |-------------------|---->  TempRamBase
123 
124   IdtTableInStack.PeiService = 0;
125   for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
126     CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
127   }
128 
129   IdtDescriptor.Base  = (UINTN) &IdtTableInStack.IdtTable;
130   IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
131 
132   AsmWriteIdtr (&IdtDescriptor);
133 
134   //
135   // Setup the default exception handlers
136   //
137   Status = InitializeCpuExceptionHandlers (NULL);
138   ASSERT_EFI_ERROR (Status);
139 
140   //
141   // Update the base address and length of Pei temporary memory
142   //
143   SecCoreData.DataSize               = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
144   SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
145   SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);
146   SecCoreData.TemporaryRamBase       = (VOID*)(UINTN) TempRamBase;
147   SecCoreData.TemporaryRamSize       = SizeOfRam;
148   SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
149   SecCoreData.PeiTemporaryRamSize    = SizeOfRam - PeiStackSize;
150   SecCoreData.StackBase              = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
151   SecCoreData.StackSize              = PeiStackSize;
152 
153   //
154   // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
155   //
156   InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
157 }
158 
159 /**
160   Caller provided function to be invoked at the end of InitializeDebugAgent().
161 
162   Entry point to the C language phase of SEC. After the SEC assembly
163   code has initialized some temporary memory and set up the stack,
164   the control is transferred to this function.
165 
166   @param[in] Context    The first input parameter of InitializeDebugAgent().
167 
168 **/
169 VOID
170 EFIAPI
SecStartupPhase2(IN VOID * Context)171 SecStartupPhase2(
172   IN VOID                     *Context
173   )
174 {
175   EFI_SEC_PEI_HAND_OFF        *SecCoreData;
176   EFI_PEI_PPI_DESCRIPTOR      *PpiList;
177   UINT32                      Index;
178   EFI_PEI_PPI_DESCRIPTOR      *AllSecPpiList;
179   EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
180 
181   SecCoreData   = (EFI_SEC_PEI_HAND_OFF *) Context;
182   AllSecPpiList = (EFI_PEI_PPI_DESCRIPTOR *) SecCoreData->PeiTemporaryRamBase;
183   //
184   // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
185   // is enabled.
186   //
187   FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
188   if (PeiCoreEntryPoint == NULL)
189   {
190     CpuDeadLoop ();
191   }
192 
193   //
194   // Perform platform specific initialization before entering PeiCore.
195   //
196   PpiList = SecPlatformMain (SecCoreData);
197   if (PpiList != NULL) {
198     //
199     // Remove the terminal flag from the terminal PPI
200     //
201     CopyMem (AllSecPpiList, mPeiSecPlatformInformationPpi, sizeof (mPeiSecPlatformInformationPpi));
202     Index = sizeof (mPeiSecPlatformInformationPpi) / sizeof (EFI_PEI_PPI_DESCRIPTOR) - 1;
203     AllSecPpiList[Index].Flags = AllSecPpiList[Index].Flags & (~EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
204 
205     //
206     // Append the platform additional PPI list
207     //
208     Index += 1;
209     while (((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) != EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST)) {
210       CopyMem (&AllSecPpiList[Index], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
211       Index++;
212       PpiList++;
213     }
214 
215     //
216     // Add the terminal PPI
217     //
218     CopyMem (&AllSecPpiList[Index ++], PpiList, sizeof (EFI_PEI_PPI_DESCRIPTOR));
219 
220     //
221     // Set PpiList to the total PPI
222     //
223     PpiList = AllSecPpiList;
224 
225     //
226     // Adjust PEI TEMP RAM Range.
227     //
228     ASSERT (SecCoreData->PeiTemporaryRamSize > Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
229     SecCoreData->PeiTemporaryRamBase = (VOID *)((UINTN) SecCoreData->PeiTemporaryRamBase + Index * sizeof (EFI_PEI_PPI_DESCRIPTOR));
230     SecCoreData->PeiTemporaryRamSize = SecCoreData->PeiTemporaryRamSize - Index * sizeof (EFI_PEI_PPI_DESCRIPTOR);
231   } else {
232     //
233     // No addition PPI, PpiList directly point to the common PPI list.
234     //
235     PpiList = &mPeiSecPlatformInformationPpi[0];
236   }
237 
238   //
239   // Report Status Code to indicate transferring to PEI core
240   //
241   REPORT_STATUS_CODE (
242     EFI_PROGRESS_CODE,
243     EFI_SOFTWARE_SEC | EFI_SW_SEC_PC_HANDOFF_TO_NEXT
244     );
245 
246   //
247   // Transfer the control to the PEI core
248   //
249   ASSERT (PeiCoreEntryPoint != NULL);
250   (*PeiCoreEntryPoint) (SecCoreData, PpiList);
251 
252   //
253   // Should not come here.
254   //
255   return;
256 }
257 
258 /**
259   TemporaryRamDone() disables the use of Temporary RAM. If present, this service is invoked
260   by the PEI Foundation after the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
261 
262   @retval EFI_SUCCESS           Use of Temporary RAM was disabled.
263   @retval EFI_INVALID_PARAMETER Temporary RAM could not be disabled.
264 
265 **/
266 EFI_STATUS
267 EFIAPI
SecTemporaryRamDone(VOID)268 SecTemporaryRamDone (
269   VOID
270   )
271 {
272   BOOLEAN  State;
273 
274   //
275   // Migrate DebugAgentContext.
276   //
277   InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
278 
279   //
280   // Disable interrupts and save current interrupt state
281   //
282   State = SaveAndDisableInterrupts();
283 
284   //
285   // Disable Temporary RAM after Stack and Heap have been migrated at this point.
286   //
287   SecPlatformDisableTemporaryMemory ();
288 
289   //
290   // Restore original interrupt state
291   //
292   SetInterruptState (State);
293 
294   return EFI_SUCCESS;
295 }
296