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