1 /** @file
2   C funtions in SEC
3 
4 Copyright (c) 2013, 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 
16 #include "SecMain.h"
17 
18 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
19   SecTemporaryRamSupport
20 };
21 
22 EFI_PEI_PPI_DESCRIPTOR            mPeiSecPlatformInformationPpi[] = {
23   {
24     (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
25     &gEfiTemporaryRamSupportPpiGuid,
26     &gSecTemporaryRamSupportPpi
27   }
28 };
29 
30 //
31 // These are IDT entries pointing to 10:FFFFFFE4h.
32 //
33 UINT64  mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
34 
35 /**
36   Caller provided function to be invoked at the end of InitializeDebugAgent().
37 
38   Entry point to the C language phase of SEC. After the SEC assembly
39   code has initialized some temporary memory and set up the stack,
40   the control is transferred to this function.
41 
42   @param[in] Context    The first input parameter of InitializeDebugAgent().
43 
44 **/
45 VOID
46 EFIAPI
47 SecStartupPhase2(
48   IN VOID                     *Context
49   );
50 
51 
52 /**
53 
54   Entry point to the C language phase of SEC. After the SEC assembly
55   code has initialized some temporary memory and set up the stack,
56   the control is transferred to this function.
57 
58 
59   @param SizeOfRam           Size of the temporary memory available for use.
60   @param TempRamBase         Base address of tempory ram
61   @param BootFirmwareVolume  Base address of the Boot Firmware Volume.
62 **/
63 VOID
64 EFIAPI
SecStartup(IN UINT32 SizeOfRam,IN UINT32 TempRamBase,IN VOID * BootFirmwareVolume)65 SecStartup (
66   IN UINT32                   SizeOfRam,
67   IN UINT32                   TempRamBase,
68   IN VOID                     *BootFirmwareVolume
69   )
70 {
71   EFI_SEC_PEI_HAND_OFF        SecCoreData;
72   IA32_DESCRIPTOR             IdtDescriptor;
73   SEC_IDT_TABLE               IdtTableInStack;
74   UINT32                      Index;
75   UINT32                      PeiStackSize;
76 
77   PeiStackSize = (SizeOfRam >> 1);
78 
79   ASSERT (PeiStackSize < SizeOfRam);
80 
81   //
82   // Process all libraries constructor function linked to SecCore.
83   //
84   ProcessLibraryConstructorList ();
85 
86   //
87   // Initialize floating point operating environment
88   // to be compliant with UEFI spec.
89   //
90   InitializeFloatingPointUnits ();
91 
92 
93   // |-------------------|---->
94   // |Idt Table          |
95   // |-------------------|
96   // |PeiService Pointer |    PeiStackSize
97   // |-------------------|
98   // |                   |
99   // |      Stack        |
100   // |-------------------|---->
101   // |                   |
102   // |                   |
103   // |      Heap         |    PeiTemporayRamSize
104   // |                   |
105   // |                   |
106   // |-------------------|---->  TempRamBase
107 
108   IdtTableInStack.PeiService = 0;
109   for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
110     CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
111   }
112 
113   IdtDescriptor.Base  = (UINTN) &IdtTableInStack.IdtTable;
114   IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
115 
116   AsmWriteIdtr (&IdtDescriptor);
117 
118   //
119   // Update the base address and length of Pei temporary memory
120   //
121   SecCoreData.DataSize               = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
122   SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
123   SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);
124   SecCoreData.TemporaryRamBase       = (VOID*)(UINTN) TempRamBase;
125   SecCoreData.TemporaryRamSize       = SizeOfRam;
126   SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
127   SecCoreData.PeiTemporaryRamSize    = SizeOfRam - PeiStackSize;
128   SecCoreData.StackBase              = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
129   SecCoreData.StackSize              = PeiStackSize;
130 
131   //
132   // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
133   //
134   InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
135 
136 }
137 
138 /**
139   Caller provided function to be invoked at the end of InitializeDebugAgent().
140 
141   Entry point to the C language phase of SEC. After the SEC assembly
142   code has initialized some temporary memory and set up the stack,
143   the control is transferred to this function.
144 
145   @param[in] Context    The first input parameter of InitializeDebugAgent().
146 
147 **/
148 VOID
149 EFIAPI
SecStartupPhase2(IN VOID * Context)150 SecStartupPhase2(
151   IN VOID                     *Context
152   )
153 {
154   EFI_SEC_PEI_HAND_OFF        *SecCoreData;
155   EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
156 
157   SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
158   //
159   // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
160   // is enabled.
161   //
162   FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
163   if (PeiCoreEntryPoint == NULL)
164   {
165     CpuDeadLoop ();
166   }
167 
168   //
169   // Transfer the control to the PEI core
170   //
171   ASSERT (PeiCoreEntryPoint != NULL);
172   (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi);
173 
174   //
175   // Should not come here.
176   //
177   return ;
178 }
179 
180 /**
181   This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
182   permanent memory.
183 
184   @param PeiServices            Pointer to the PEI Services Table.
185   @param TemporaryMemoryBase    Source Address in temporary memory from which the SEC or PEIM will copy the
186                                 Temporary RAM contents.
187   @param PermanentMemoryBase    Destination Address in permanent memory into which the SEC or PEIM will copy the
188                                 Temporary RAM contents.
189   @param CopySize               Amount of memory to migrate from temporary to permanent memory.
190 
191   @retval EFI_SUCCESS           The data was successfully returned.
192   @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
193                                 TemporaryMemoryBase > PermanentMemoryBase.
194 
195 **/
196 EFI_STATUS
197 EFIAPI
SecTemporaryRamSupport(IN CONST EFI_PEI_SERVICES ** PeiServices,IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,IN UINTN CopySize)198 SecTemporaryRamSupport (
199   IN CONST EFI_PEI_SERVICES   **PeiServices,
200   IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
201   IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
202   IN UINTN                    CopySize
203   )
204 {
205   IA32_DESCRIPTOR   IdtDescriptor;
206   VOID*             OldHeap;
207   VOID*             NewHeap;
208   VOID*             OldStack;
209   VOID*             NewStack;
210   DEBUG_AGENT_CONTEXT_POSTMEM_SEC  DebugAgentContext;
211   BOOLEAN           OldStatus;
212   UINTN             PeiStackSize;
213 
214   PeiStackSize = (CopySize >> 1);
215 
216   ASSERT (PeiStackSize < CopySize);
217 
218   //
219   // |-------------------|---->
220   // |      Stack        |    PeiStackSize
221   // |-------------------|---->
222   // |      Heap         |    PeiTemporayRamSize
223   // |-------------------|---->  TempRamBase
224   //
225   // |-------------------|---->
226   // |      Heap         |    PeiTemporayRamSize
227   // |-------------------|---->
228   // |      Stack        |    PeiStackSize
229   // |-------------------|---->  PermanentMemoryBase
230   //
231 
232   OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
233   NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);
234 
235   OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);
236   NewStack = (VOID*)(UINTN)PermanentMemoryBase;
237 
238   DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
239   DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
240 
241   OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
242   //
243   // Initialize Debug Agent to support source level debug in PEI phase after memory ready.
244   // It will build HOB and fix up the pointer in IDT table.
245   //
246   InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
247 
248   //
249   // Migrate Heap
250   //
251   CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);
252 
253   //
254   // Migrate Stack
255   //
256   CopyMem (NewStack, OldStack, PeiStackSize);
257 
258 
259   //
260   // We need *not* fix the return address because currently,
261   // The PeiCore is executed in flash.
262   //
263 
264   //
265   // Rebase IDT table in permanent memory
266   //
267   AsmReadIdtr (&IdtDescriptor);
268   IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
269 
270   AsmWriteIdtr (&IdtDescriptor);
271 
272 
273   //
274   // Program MTRR
275   //
276 
277   //
278   // SecSwitchStack function must be invoked after the memory migration
279   // immediatly, also we need fixup the stack change caused by new call into
280   // permenent memory.
281   //
282   SecSwitchStack (
283     (UINT32) (UINTN) OldStack,
284     (UINT32) (UINTN) NewStack
285     );
286 
287   SaveAndSetDebugTimerInterrupt (OldStatus);
288 
289   return EFI_SUCCESS;
290 }
291 
292