]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
OvmfPkg: Move SEC/PEI Temporary RAM from 0x70000 to 0x810000
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
bb4aa855
JJ
1/** @file\r
2 Main SEC phase code. Transitions to PEI.\r
3\r
4 Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <PiPei.h>\r
17\r
18#include <Library/PeimEntryPoint.h>\r
19#include <Library/BaseLib.h>\r
20#include <Library/DebugLib.h>\r
21#include <Library/BaseMemoryLib.h>\r
22#include <Library/PeiServicesLib.h>\r
23#include <Library/PcdLib.h>\r
24#include <Library/UefiCpuLib.h>\r
25#include <Library/DebugAgentLib.h>\r
26#include <Library/IoLib.h>\r
27#include <Library/PeCoffLib.h>\r
28#include <Library/PeCoffGetEntryPointLib.h>\r
29#include <Library/PeCoffExtraActionLib.h>\r
30#include <Library/ExtractGuidedSectionLib.h>\r
31\r
32#include <Ppi/TemporaryRamSupport.h>\r
33\r
34#define SEC_IDT_ENTRY_COUNT 34\r
35\r
36typedef struct _SEC_IDT_TABLE {\r
37 EFI_PEI_SERVICES *PeiService;\r
38 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];\r
39} SEC_IDT_TABLE;\r
40\r
41VOID\r
42EFIAPI\r
43SecStartupPhase2 (\r
44 IN VOID *Context\r
45 );\r
46\r
47EFI_STATUS\r
48EFIAPI\r
49TemporaryRamMigration (\r
50 IN CONST EFI_PEI_SERVICES **PeiServices,\r
51 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
52 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
53 IN UINTN CopySize\r
54 );\r
55\r
56//\r
57//\r
58// \r
59EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {\r
60 TemporaryRamMigration\r
61};\r
62\r
63EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {\r
64 {\r
65 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
66 &gEfiTemporaryRamSupportPpiGuid,\r
67 &mTemporaryRamSupportPpi\r
68 },\r
69};\r
70\r
71//\r
72// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
73//\r
74IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {\r
75 { // Bits\r
76 0xffe4, // OffsetLow\r
77 0x10, // Selector\r
78 0x0, // Reserved_0\r
79 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType\r
80 0xffff // OffsetHigh\r
81 } \r
82};\r
83\r
84/**\r
85 Locates the main boot firmware volume.\r
86\r
87 @param[in,out] BootFv On input, the base of the BootFv\r
88 On output, the decompressed main firmware volume\r
89\r
90 @retval EFI_SUCCESS The main firmware volume was located and decompressed\r
91 @retval EFI_NOT_FOUND The main firmware volume was not found\r
92\r
93**/\r
94EFI_STATUS\r
95FindMainFv (\r
96 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv\r
97 )\r
98{\r
99 EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
100 UINTN Distance;\r
101\r
102 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);\r
103\r
104 Fv = *BootFv;\r
105 Distance = (UINTN) (*BootFv)->FvLength;\r
106 do {\r
107 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);\r
108 Distance += EFI_PAGE_SIZE;\r
109 if (Distance > SIZE_32MB) {\r
110 return EFI_NOT_FOUND;\r
111 }\r
112\r
113 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
114 continue;\r
115 }\r
116\r
117 if ((UINTN) Fv->FvLength > Distance) {\r
118 continue;\r
119 }\r
120\r
121 *BootFv = Fv;\r
122 return EFI_SUCCESS;\r
123\r
124 } while (TRUE);\r
125}\r
126\r
127/**\r
128 Locates a section within a series of sections\r
129 with the specified section type.\r
130\r
131 @param[in] Sections The sections to search\r
132 @param[in] SizeOfSections Total size of all sections\r
133 @param[in] SectionType The section type to locate\r
134 @param[out] FoundSection The FFS section if found\r
135\r
136 @retval EFI_SUCCESS The file and section was found\r
137 @retval EFI_NOT_FOUND The file and section was not found\r
138 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
139\r
140**/\r
141EFI_STATUS\r
142FindFfsSectionInSections (\r
143 IN VOID *Sections,\r
144 IN UINTN SizeOfSections,\r
145 IN EFI_SECTION_TYPE SectionType,\r
146 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
147 )\r
148{\r
149 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
150 UINT32 Size;\r
151 EFI_PHYSICAL_ADDRESS EndOfSections;\r
152 EFI_COMMON_SECTION_HEADER *Section;\r
153 EFI_PHYSICAL_ADDRESS EndOfSection;\r
154\r
155 //\r
156 // Loop through the FFS file sections within the PEI Core FFS file\r
157 //\r
158 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;\r
159 EndOfSections = EndOfSection + SizeOfSections;\r
160 for (;;) {\r
161 if (EndOfSection == EndOfSections) {\r
162 break;\r
163 }\r
164 CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
165 if (CurrentAddress >= EndOfSections) {\r
166 return EFI_VOLUME_CORRUPTED;\r
167 }\r
168\r
169 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
170 DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type));\r
171\r
172 Size = SECTION_SIZE (Section);\r
173 if (Size < sizeof (*Section)) {\r
174 return EFI_VOLUME_CORRUPTED;\r
175 }\r
176\r
177 EndOfSection = CurrentAddress + Size;\r
178 if (EndOfSection > EndOfSections) {\r
179 return EFI_VOLUME_CORRUPTED;\r
180 }\r
181\r
182 //\r
183 // Look for the requested section type\r
184 //\r
185 if (Section->Type == SectionType) {\r
186 *FoundSection = Section;\r
187 return EFI_SUCCESS;\r
188 }\r
189 DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType));\r
190 }\r
191\r
192 return EFI_NOT_FOUND;\r
193}\r
194\r
195/**\r
196 Locates a FFS file with the specified file type and a section\r
197 within that file with the specified section type.\r
198\r
199 @param[in] Fv The firmware volume to search\r
200 @param[in] FileType The file type to locate\r
201 @param[in] SectionType The section type to locate\r
202 @param[out] FoundSection The FFS section if found\r
203\r
204 @retval EFI_SUCCESS The file and section was found\r
205 @retval EFI_NOT_FOUND The file and section was not found\r
206 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
207\r
208**/\r
209EFI_STATUS\r
210EFIAPI\r
211FindFfsFileAndSection (\r
212 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
213 IN EFI_FV_FILETYPE FileType,\r
214 IN EFI_SECTION_TYPE SectionType,\r
215 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
216 )\r
217{\r
218 EFI_STATUS Status;\r
219 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
220 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
221 EFI_FFS_FILE_HEADER *File;\r
222 UINT32 Size;\r
223 EFI_PHYSICAL_ADDRESS EndOfFile;\r
224\r
225 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
226 DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv));\r
227 return EFI_VOLUME_CORRUPTED;\r
228 }\r
229\r
230 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
231 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
232\r
233 //\r
234 // Loop through the FFS files in the Boot Firmware Volume\r
235 //\r
236 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
237\r
238 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
239 if (CurrentAddress > EndOfFirmwareVolume) {\r
240 return EFI_VOLUME_CORRUPTED;\r
241 }\r
242\r
243 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
244 Size = *(UINT32*) File->Size & 0xffffff;\r
245 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
246 return EFI_VOLUME_CORRUPTED;\r
247 }\r
248 DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type));\r
249\r
250 EndOfFile = CurrentAddress + Size;\r
251 if (EndOfFile > EndOfFirmwareVolume) {\r
252 return EFI_VOLUME_CORRUPTED;\r
253 }\r
254\r
255 //\r
256 // Look for the request file type\r
257 //\r
258 if (File->Type != FileType) {\r
259 DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType));\r
260 continue;\r
261 }\r
262\r
263 Status = FindFfsSectionInSections (\r
264 (VOID*) (File + 1),\r
265 (UINTN) EndOfFile - (UINTN) (File + 1),\r
266 SectionType,\r
267 FoundSection\r
268 );\r
269 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
270 return Status;\r
271 }\r
272 }\r
273}\r
274\r
275/**\r
276 Locates the compressed main firmware volume and decompresses it.\r
277\r
278 @param[in,out] Fv On input, the firmware volume to search\r
279 On output, the decompressed main FV\r
280\r
281 @retval EFI_SUCCESS The file and section was found\r
282 @retval EFI_NOT_FOUND The file and section was not found\r
283 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
284\r
285**/\r
286EFI_STATUS\r
287EFIAPI\r
288DecompressGuidedFv (\r
289 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
290 )\r
291{\r
292 EFI_STATUS Status;\r
293 EFI_GUID_DEFINED_SECTION *Section;\r
294 UINT32 OutputBufferSize;\r
295 UINT32 ScratchBufferSize;\r
296 UINT16 SectionAttribute;\r
297 UINT32 AuthenticationStatus;\r
298 VOID *OutputBuffer;\r
299 VOID *ScratchBuffer;\r
300 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;\r
301 EFI_FIRMWARE_VOLUME_HEADER *NewFv;\r
302\r
303 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
304\r
305 Status = FindFfsFileAndSection (\r
306 *Fv,\r
307 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
308 EFI_SECTION_GUID_DEFINED,\r
309 (EFI_COMMON_SECTION_HEADER**) &Section\r
310 );\r
311 if (EFI_ERROR (Status)) {\r
312 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
313 return Status;\r
314 }\r
315\r
316 Status = ExtractGuidedSectionGetInfo (\r
317 Section,\r
318 &OutputBufferSize,\r
319 &ScratchBufferSize,\r
320 &SectionAttribute\r
321 );\r
322 if (EFI_ERROR (Status)) {\r
323 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
324 return Status;\r
325 }\r
326\r
327 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)\r
328 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);\r
329 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
330 Status = ExtractGuidedSectionDecode (\r
331 Section,\r
332 &OutputBuffer,\r
333 ScratchBuffer,\r
334 &AuthenticationStatus\r
335 );\r
336 if (EFI_ERROR (Status)) {\r
337 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
338 return Status;\r
339 }\r
340\r
341 Status = FindFfsSectionInSections (\r
342 OutputBuffer,\r
343 OutputBufferSize,\r
344 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
345 (EFI_COMMON_SECTION_HEADER**) &NewFvSection\r
346 );\r
347 if (EFI_ERROR (Status)) {\r
348 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));\r
349 return Status;\r
350 }\r
351\r
352 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);\r
353 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));\r
354\r
355 if (NewFv->Signature != EFI_FVH_SIGNATURE) {\r
356 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));\r
357 CpuDeadLoop ();\r
358 return EFI_VOLUME_CORRUPTED;\r
359 }\r
360\r
361 *Fv = NewFv;\r
362 return EFI_SUCCESS;\r
363}\r
364\r
365/**\r
366 Locates the PEI Core entry point address\r
367\r
368 @param[in] Fv The firmware volume to search\r
369 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
370\r
371 @retval EFI_SUCCESS The file and section was found\r
372 @retval EFI_NOT_FOUND The file and section was not found\r
373 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378FindPeiCoreImageBaseInFv (\r
379 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
380 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
381 )\r
382{\r
383 EFI_STATUS Status;\r
384 EFI_COMMON_SECTION_HEADER *Section;\r
385\r
386 Status = FindFfsFileAndSection (\r
387 Fv,\r
388 EFI_FV_FILETYPE_PEI_CORE,\r
389 EFI_SECTION_PE32,\r
390 &Section\r
391 );\r
392 if (EFI_ERROR (Status)) {\r
393 Status = FindFfsFileAndSection (\r
394 Fv,\r
395 EFI_FV_FILETYPE_PEI_CORE,\r
396 EFI_SECTION_TE,\r
397 &Section\r
398 );\r
399 if (EFI_ERROR (Status)) {\r
400 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
401 return Status;\r
402 }\r
403 }\r
404\r
405 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
406 return EFI_SUCCESS;\r
407}\r
408\r
409/**\r
410 Locates the PEI Core entry point address\r
411\r
412 @param[in,out] Fv The firmware volume to search\r
413 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
414\r
415 @retval EFI_SUCCESS The file and section was found\r
416 @retval EFI_NOT_FOUND The file and section was not found\r
417 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
418\r
419**/\r
420VOID\r
421EFIAPI\r
422FindPeiCoreImageBase (\r
423 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
424 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
425 )\r
426{\r
427 *PeiCoreImageBase = 0;\r
428\r
429 FindMainFv (BootFv);\r
430\r
431 DecompressGuidedFv (BootFv);\r
432\r
433 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
434}\r
435\r
436/**\r
437 Find core image base.\r
438\r
439**/\r
440EFI_STATUS\r
441EFIAPI\r
442FindImageBase (\r
443 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
444 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
445 )\r
446{\r
447 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
448 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
449 EFI_FFS_FILE_HEADER *File;\r
450 UINT32 Size;\r
451 EFI_PHYSICAL_ADDRESS EndOfFile;\r
452 EFI_COMMON_SECTION_HEADER *Section;\r
453 EFI_PHYSICAL_ADDRESS EndOfSection;\r
454\r
455 *SecCoreImageBase = 0;\r
456\r
457 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
458 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
459\r
460 //\r
461 // Loop through the FFS files in the Boot Firmware Volume\r
462 //\r
463 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
464\r
465 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
466 if (CurrentAddress > EndOfFirmwareVolume) {\r
467 return EFI_NOT_FOUND;\r
468 }\r
469\r
470 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
471 Size = *(UINT32*) File->Size & 0xffffff;\r
472 if (Size < sizeof (*File)) {\r
473 return EFI_NOT_FOUND;\r
474 }\r
475\r
476 EndOfFile = CurrentAddress + Size;\r
477 if (EndOfFile > EndOfFirmwareVolume) {\r
478 return EFI_NOT_FOUND;\r
479 }\r
480\r
481 //\r
482 // Look for SEC Core\r
483 //\r
484 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
485 continue;\r
486 }\r
487\r
488 //\r
489 // Loop through the FFS file sections within the FFS file\r
490 //\r
491 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
492 for (;;) {\r
493 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
494 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
495\r
496 Size = *(UINT32*) Section->Size & 0xffffff;\r
497 if (Size < sizeof (*Section)) {\r
498 return EFI_NOT_FOUND;\r
499 }\r
500\r
501 EndOfSection = CurrentAddress + Size;\r
502 if (EndOfSection > EndOfFile) {\r
503 return EFI_NOT_FOUND;\r
504 }\r
505\r
506 //\r
507 // Look for executable sections\r
508 //\r
509 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
510 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
511 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
512 }\r
513 break;\r
514 }\r
515 }\r
516\r
517 //\r
518 // SEC Core image found\r
519 //\r
520 if (*SecCoreImageBase != 0) {\r
521 return EFI_SUCCESS;\r
522 }\r
523 }\r
524}\r
525\r
526/*\r
527 Find and return Pei Core entry point.\r
528\r
529 It also find SEC and PEI Core file debug inforamtion. It will report them if\r
530 remote debug is enabled.\r
531\r
532**/\r
533VOID\r
534EFIAPI\r
535FindAndReportEntryPoints (\r
536 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
537 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
538 )\r
539{\r
540 EFI_STATUS Status;\r
541 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
542 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
543 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
544\r
545 //\r
546 // Find SEC Core and PEI Core image base\r
547 //\r
548 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
549 ASSERT_EFI_ERROR (Status);\r
550\r
551 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
552 \r
553 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
554 //\r
555 // Report SEC Core debug information when remote debug is enabled\r
556 //\r
557 ImageContext.ImageAddress = SecCoreImageBase;\r
558 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
559 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
560\r
561 //\r
562 // Report PEI Core debug information when remote debug is enabled\r
563 //\r
564 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
565 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
566 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
567\r
568 //\r
569 // Find PEI Core entry point\r
570 //\r
571 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
572 if (EFI_ERROR (Status)) {\r
573 *PeiCoreEntryPoint = 0;\r
574 }\r
575\r
576 return;\r
577}\r
578\r
579VOID\r
580EFIAPI\r
581SecCoreStartupWithStack (\r
582 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
583 IN VOID *TopOfCurrentStack\r
584 )\r
585{\r
586 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
587 SEC_IDT_TABLE IdtTableInStack;\r
588 IA32_DESCRIPTOR IdtDescriptor;\r
589 UINT32 Index;\r
590\r
591 ProcessLibraryConstructorList (NULL, NULL);\r
592\r
593 DEBUG ((EFI_D_ERROR,\r
594 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
595 (UINT32)(UINTN)BootFv,\r
596 (UINT32)(UINTN)TopOfCurrentStack\r
597 ));\r
598\r
599 //\r
600 // Initialize floating point operating environment\r
601 // to be compliant with UEFI spec.\r
602 //\r
603 InitializeFloatingPointUnits ();\r
604\r
605 //\r
606 // Initialize IDT\r
607 // \r
608 IdtTableInStack.PeiService = NULL;\r
609 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
610 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
611 }\r
612\r
613 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
614 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
615\r
616 AsmWriteIdtr (&IdtDescriptor);\r
617\r
b382ede3
JJ
618#if defined (MDE_CPU_X64)\r
619 //\r
620 // ASSERT that the Page Tables were set by the reset vector code to\r
621 // the address we expect.\r
622 //\r
623 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
624#endif\r
625\r
bb4aa855
JJ
626 //\r
627 // |-------------| <-- TopOfCurrentStack\r
628 // | Stack | 32k\r
629 // |-------------|\r
630 // | Heap | 32k\r
631 // |-------------| <-- SecCoreData.TemporaryRamBase\r
632 //\r
633\r
7cb6b0e0
JJ
634 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
635 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
636 (UINTN) TopOfCurrentStack);\r
637\r
bb4aa855
JJ
638 //\r
639 // Initialize SEC hand-off state\r
640 //\r
641 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
642\r
7cb6b0e0 643 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
644 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
645\r
646 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
647 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
648\r
649 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
650 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
651\r
652 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
653 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
654\r
655 //\r
656 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
657 //\r
658 IoWrite8 (0x21, 0xff);\r
659 IoWrite8 (0xA1, 0xff);\r
660 \r
661 //\r
662 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
663 //\r
664 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
665}\r
666 \r
667/**\r
668 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
669\r
670 Entry point to the C language phase of SEC. After the SEC assembly\r
671 code has initialized some temporary memory and set up the stack,\r
672 the control is transferred to this function.\r
673\r
674 @param[in] Context The first input parameter of InitializeDebugAgent().\r
675\r
676**/\r
677VOID\r
678EFIAPI\r
679SecStartupPhase2(\r
680 IN VOID *Context\r
681 )\r
682{\r
683 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
684 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
685 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
686 \r
687 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
688 \r
689 //\r
690 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
691 // is enabled.\r
692 //\r
693 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
694 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
695 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
696 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
697\r
698 //\r
699 // Transfer the control to the PEI core\r
700 //\r
701 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
702 \r
703 //\r
704 // If we get here then the PEI Core returned, which is not recoverable.\r
705 //\r
706 ASSERT (FALSE);\r
707 CpuDeadLoop ();\r
708}\r
709\r
710EFI_STATUS\r
711EFIAPI\r
712TemporaryRamMigration (\r
713 IN CONST EFI_PEI_SERVICES **PeiServices,\r
714 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
715 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
716 IN UINTN CopySize\r
717 )\r
718{\r
719 IA32_DESCRIPTOR IdtDescriptor;\r
720 VOID *OldHeap;\r
721 VOID *NewHeap;\r
722 VOID *OldStack;\r
723 VOID *NewStack;\r
724 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
725 BOOLEAN OldStatus;\r
726 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
727 \r
728 DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize));\r
729 \r
730 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
731 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
732 \r
733 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
734 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
735\r
736 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
737 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
738 \r
739 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
740 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
741\r
742 //\r
743 // Migrate Heap\r
744 //\r
745 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
746\r
747 //\r
748 // Migrate Stack\r
749 //\r
750 CopyMem (NewStack, OldStack, CopySize >> 1);\r
751 \r
752 //\r
753 // Rebase IDT table in permanent memory\r
754 //\r
755 AsmReadIdtr (&IdtDescriptor);\r
756 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
757\r
758 AsmWriteIdtr (&IdtDescriptor);\r
759\r
760 //\r
761 // Use SetJump()/LongJump() to switch to a new stack.\r
762 // \r
763 if (SetJump (&JumpBuffer) == 0) {\r
764#if defined (MDE_CPU_IA32)\r
765 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
766#endif \r
767#if defined (MDE_CPU_X64)\r
768 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
769#endif \r
770 LongJump (&JumpBuffer, (UINTN)-1);\r
771 }\r
772\r
773 SaveAndSetDebugTimerInterrupt (OldStatus);\r
774\r
775 return EFI_SUCCESS;\r
776}\r
777\r