CorebootPayloadPkg: Use extra braces to prevent gcc compile fail
[mirror_edk2.git] / CorebootModulePkg / SecCore / SecMain.c
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
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
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
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