]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
OvmfPkg/PlatformPei: Skip various items for S3 resume
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
bb4aa855
JJ
1/** @file\r
2 Main SEC phase code. Transitions to PEI.\r
3\r
c67178b7 4 Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>\r
bb4aa855
JJ
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
4b4b783d
JJ
131 The Instance parameter indicates which instance of the section\r
132 type to return. (0 is first instance, 1 is second...)\r
133\r
bb4aa855
JJ
134 @param[in] Sections The sections to search\r
135 @param[in] SizeOfSections Total size of all sections\r
136 @param[in] SectionType The section type to locate\r
4b4b783d 137 @param[in] Instance The section instance number\r
bb4aa855
JJ
138 @param[out] FoundSection The FFS section if found\r
139\r
140 @retval EFI_SUCCESS The file and section was found\r
141 @retval EFI_NOT_FOUND The file and section was not found\r
142 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
143\r
144**/\r
145EFI_STATUS\r
4b4b783d 146FindFfsSectionInstance (\r
bb4aa855
JJ
147 IN VOID *Sections,\r
148 IN UINTN SizeOfSections,\r
149 IN EFI_SECTION_TYPE SectionType,\r
4b4b783d 150 IN UINTN Instance,\r
bb4aa855
JJ
151 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
152 )\r
153{\r
154 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
155 UINT32 Size;\r
156 EFI_PHYSICAL_ADDRESS EndOfSections;\r
157 EFI_COMMON_SECTION_HEADER *Section;\r
158 EFI_PHYSICAL_ADDRESS EndOfSection;\r
159\r
160 //\r
161 // Loop through the FFS file sections within the PEI Core FFS file\r
162 //\r
163 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;\r
164 EndOfSections = EndOfSection + SizeOfSections;\r
165 for (;;) {\r
166 if (EndOfSection == EndOfSections) {\r
167 break;\r
168 }\r
169 CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
170 if (CurrentAddress >= EndOfSections) {\r
171 return EFI_VOLUME_CORRUPTED;\r
172 }\r
173\r
174 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
bb4aa855
JJ
175\r
176 Size = SECTION_SIZE (Section);\r
177 if (Size < sizeof (*Section)) {\r
178 return EFI_VOLUME_CORRUPTED;\r
179 }\r
180\r
181 EndOfSection = CurrentAddress + Size;\r
182 if (EndOfSection > EndOfSections) {\r
183 return EFI_VOLUME_CORRUPTED;\r
184 }\r
185\r
186 //\r
187 // Look for the requested section type\r
188 //\r
189 if (Section->Type == SectionType) {\r
4b4b783d
JJ
190 if (Instance == 0) {\r
191 *FoundSection = Section;\r
192 return EFI_SUCCESS;\r
193 } else {\r
194 Instance--;\r
195 }\r
bb4aa855 196 }\r
bb4aa855
JJ
197 }\r
198\r
199 return EFI_NOT_FOUND;\r
200}\r
201\r
4b4b783d
JJ
202/**\r
203 Locates a section within a series of sections\r
204 with the specified section type.\r
205\r
206 @param[in] Sections The sections to search\r
207 @param[in] SizeOfSections Total size of all sections\r
208 @param[in] SectionType The section type to locate\r
209 @param[out] FoundSection The FFS section if found\r
210\r
211 @retval EFI_SUCCESS The file and section was found\r
212 @retval EFI_NOT_FOUND The file and section was not found\r
213 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
214\r
215**/\r
216EFI_STATUS\r
217FindFfsSectionInSections (\r
218 IN VOID *Sections,\r
219 IN UINTN SizeOfSections,\r
220 IN EFI_SECTION_TYPE SectionType,\r
221 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
222 )\r
223{\r
224 return FindFfsSectionInstance (\r
225 Sections,\r
226 SizeOfSections,\r
227 SectionType,\r
228 0,\r
229 FoundSection\r
230 );\r
231}\r
232\r
bb4aa855
JJ
233/**\r
234 Locates a FFS file with the specified file type and a section\r
235 within that file with the specified section type.\r
236\r
237 @param[in] Fv The firmware volume to search\r
238 @param[in] FileType The file type to locate\r
239 @param[in] SectionType The section type to locate\r
240 @param[out] FoundSection The FFS section if found\r
241\r
242 @retval EFI_SUCCESS The file and section was found\r
243 @retval EFI_NOT_FOUND The file and section was not found\r
244 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
245\r
246**/\r
247EFI_STATUS\r
bb4aa855
JJ
248FindFfsFileAndSection (\r
249 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
250 IN EFI_FV_FILETYPE FileType,\r
251 IN EFI_SECTION_TYPE SectionType,\r
252 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
256 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
257 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
258 EFI_FFS_FILE_HEADER *File;\r
259 UINT32 Size;\r
260 EFI_PHYSICAL_ADDRESS EndOfFile;\r
261\r
262 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
c67178b7 263 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
bb4aa855
JJ
264 return EFI_VOLUME_CORRUPTED;\r
265 }\r
266\r
267 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
268 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
269\r
270 //\r
271 // Loop through the FFS files in the Boot Firmware Volume\r
272 //\r
273 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
274\r
275 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
276 if (CurrentAddress > EndOfFirmwareVolume) {\r
277 return EFI_VOLUME_CORRUPTED;\r
278 }\r
279\r
280 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
281 Size = *(UINT32*) File->Size & 0xffffff;\r
282 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
283 return EFI_VOLUME_CORRUPTED;\r
284 }\r
bb4aa855
JJ
285\r
286 EndOfFile = CurrentAddress + Size;\r
287 if (EndOfFile > EndOfFirmwareVolume) {\r
288 return EFI_VOLUME_CORRUPTED;\r
289 }\r
290\r
291 //\r
292 // Look for the request file type\r
293 //\r
294 if (File->Type != FileType) {\r
bb4aa855
JJ
295 continue;\r
296 }\r
297\r
298 Status = FindFfsSectionInSections (\r
299 (VOID*) (File + 1),\r
300 (UINTN) EndOfFile - (UINTN) (File + 1),\r
301 SectionType,\r
302 FoundSection\r
303 );\r
304 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
305 return Status;\r
306 }\r
307 }\r
308}\r
309\r
310/**\r
311 Locates the compressed main firmware volume and decompresses it.\r
312\r
313 @param[in,out] Fv On input, the firmware volume to search\r
b36f701d 314 On output, the decompressed BOOT/PEI FV\r
bb4aa855
JJ
315\r
316 @retval EFI_SUCCESS The file and section was found\r
317 @retval EFI_NOT_FOUND The file and section was not found\r
318 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
319\r
320**/\r
321EFI_STATUS\r
b36f701d 322DecompressMemFvs (\r
bb4aa855
JJ
323 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
324 )\r
325{\r
326 EFI_STATUS Status;\r
327 EFI_GUID_DEFINED_SECTION *Section;\r
328 UINT32 OutputBufferSize;\r
329 UINT32 ScratchBufferSize;\r
330 UINT16 SectionAttribute;\r
331 UINT32 AuthenticationStatus;\r
332 VOID *OutputBuffer;\r
333 VOID *ScratchBuffer;\r
b36f701d
JJ
334 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection;\r
335 EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;\r
336 EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;\r
bb4aa855 337\r
b36f701d 338 FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
bb4aa855
JJ
339\r
340 Status = FindFfsFileAndSection (\r
341 *Fv,\r
342 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
343 EFI_SECTION_GUID_DEFINED,\r
344 (EFI_COMMON_SECTION_HEADER**) &Section\r
345 );\r
346 if (EFI_ERROR (Status)) {\r
347 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
348 return Status;\r
349 }\r
350\r
351 Status = ExtractGuidedSectionGetInfo (\r
352 Section,\r
353 &OutputBufferSize,\r
354 &ScratchBufferSize,\r
355 &SectionAttribute\r
356 );\r
357 if (EFI_ERROR (Status)) {\r
358 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
359 return Status;\r
360 }\r
361\r
b36f701d 362 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
bb4aa855
JJ
363 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
364 Status = ExtractGuidedSectionDecode (\r
365 Section,\r
366 &OutputBuffer,\r
367 ScratchBuffer,\r
368 &AuthenticationStatus\r
369 );\r
370 if (EFI_ERROR (Status)) {\r
371 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
372 return Status;\r
373 }\r
374\r
b36f701d 375 Status = FindFfsSectionInstance (\r
bb4aa855
JJ
376 OutputBuffer,\r
377 OutputBufferSize,\r
378 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
b36f701d
JJ
379 0,\r
380 (EFI_COMMON_SECTION_HEADER**) &FvSection\r
bb4aa855
JJ
381 );\r
382 if (EFI_ERROR (Status)) {\r
b36f701d 383 DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));\r
bb4aa855
JJ
384 return Status;\r
385 }\r
386\r
b36f701d
JJ
387 ASSERT (SECTION_SIZE (FvSection) ==\r
388 (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection)));\r
389 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
bb4aa855 390\r
b36f701d
JJ
391 PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
392 CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));\r
393\r
394 if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {\r
395 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));\r
396 CpuDeadLoop ();\r
397 return EFI_VOLUME_CORRUPTED;\r
398 }\r
399\r
400 Status = FindFfsSectionInstance (\r
401 OutputBuffer,\r
402 OutputBufferSize,\r
403 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
404 1,\r
405 (EFI_COMMON_SECTION_HEADER**) &FvSection\r
406 );\r
407 if (EFI_ERROR (Status)) {\r
408 DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));\r
409 return Status;\r
410 }\r
411\r
412 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
413 ASSERT (SECTION_SIZE (FvSection) ==\r
414 (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection)));\r
415\r
416 DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);\r
417 CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize));\r
418\r
419 if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {\r
420 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));\r
bb4aa855
JJ
421 CpuDeadLoop ();\r
422 return EFI_VOLUME_CORRUPTED;\r
423 }\r
424\r
b36f701d 425 *Fv = PeiMemFv;\r
bb4aa855
JJ
426 return EFI_SUCCESS;\r
427}\r
428\r
429/**\r
430 Locates the PEI Core entry point address\r
431\r
432 @param[in] Fv The firmware volume to search\r
433 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
434\r
435 @retval EFI_SUCCESS The file and section was found\r
436 @retval EFI_NOT_FOUND The file and section was not found\r
437 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
438\r
439**/\r
440EFI_STATUS\r
bb4aa855
JJ
441FindPeiCoreImageBaseInFv (\r
442 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
443 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
444 )\r
445{\r
446 EFI_STATUS Status;\r
447 EFI_COMMON_SECTION_HEADER *Section;\r
448\r
449 Status = FindFfsFileAndSection (\r
450 Fv,\r
451 EFI_FV_FILETYPE_PEI_CORE,\r
452 EFI_SECTION_PE32,\r
453 &Section\r
454 );\r
455 if (EFI_ERROR (Status)) {\r
456 Status = FindFfsFileAndSection (\r
457 Fv,\r
458 EFI_FV_FILETYPE_PEI_CORE,\r
459 EFI_SECTION_TE,\r
460 &Section\r
461 );\r
462 if (EFI_ERROR (Status)) {\r
463 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
464 return Status;\r
465 }\r
466 }\r
467\r
468 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
469 return EFI_SUCCESS;\r
470}\r
471\r
472/**\r
473 Locates the PEI Core entry point address\r
474\r
475 @param[in,out] Fv The firmware volume to search\r
476 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
477\r
478 @retval EFI_SUCCESS The file and section was found\r
479 @retval EFI_NOT_FOUND The file and section was not found\r
480 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
481\r
482**/\r
483VOID\r
bb4aa855
JJ
484FindPeiCoreImageBase (\r
485 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
486 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
487 )\r
488{\r
489 *PeiCoreImageBase = 0;\r
490\r
491 FindMainFv (BootFv);\r
492\r
b36f701d 493 DecompressMemFvs (BootFv);\r
bb4aa855
JJ
494\r
495 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
496}\r
497\r
498/**\r
499 Find core image base.\r
500\r
501**/\r
502EFI_STATUS\r
bb4aa855
JJ
503FindImageBase (\r
504 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
505 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
506 )\r
507{\r
508 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
509 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
510 EFI_FFS_FILE_HEADER *File;\r
511 UINT32 Size;\r
512 EFI_PHYSICAL_ADDRESS EndOfFile;\r
513 EFI_COMMON_SECTION_HEADER *Section;\r
514 EFI_PHYSICAL_ADDRESS EndOfSection;\r
515\r
516 *SecCoreImageBase = 0;\r
517\r
518 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
519 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
520\r
521 //\r
522 // Loop through the FFS files in the Boot Firmware Volume\r
523 //\r
524 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
525\r
526 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
527 if (CurrentAddress > EndOfFirmwareVolume) {\r
528 return EFI_NOT_FOUND;\r
529 }\r
530\r
531 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
532 Size = *(UINT32*) File->Size & 0xffffff;\r
533 if (Size < sizeof (*File)) {\r
534 return EFI_NOT_FOUND;\r
535 }\r
536\r
537 EndOfFile = CurrentAddress + Size;\r
538 if (EndOfFile > EndOfFirmwareVolume) {\r
539 return EFI_NOT_FOUND;\r
540 }\r
541\r
542 //\r
543 // Look for SEC Core\r
544 //\r
545 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
546 continue;\r
547 }\r
548\r
549 //\r
550 // Loop through the FFS file sections within the FFS file\r
551 //\r
552 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
553 for (;;) {\r
554 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
555 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
556\r
557 Size = *(UINT32*) Section->Size & 0xffffff;\r
558 if (Size < sizeof (*Section)) {\r
559 return EFI_NOT_FOUND;\r
560 }\r
561\r
562 EndOfSection = CurrentAddress + Size;\r
563 if (EndOfSection > EndOfFile) {\r
564 return EFI_NOT_FOUND;\r
565 }\r
566\r
567 //\r
568 // Look for executable sections\r
569 //\r
570 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
571 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
572 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
573 }\r
574 break;\r
575 }\r
576 }\r
577\r
578 //\r
579 // SEC Core image found\r
580 //\r
581 if (*SecCoreImageBase != 0) {\r
582 return EFI_SUCCESS;\r
583 }\r
584 }\r
585}\r
586\r
587/*\r
588 Find and return Pei Core entry point.\r
589\r
590 It also find SEC and PEI Core file debug inforamtion. It will report them if\r
591 remote debug is enabled.\r
592\r
593**/\r
594VOID\r
bb4aa855
JJ
595FindAndReportEntryPoints (\r
596 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
597 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
598 )\r
599{\r
600 EFI_STATUS Status;\r
601 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
602 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
603 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
604\r
605 //\r
606 // Find SEC Core and PEI Core image base\r
607 //\r
608 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
609 ASSERT_EFI_ERROR (Status);\r
610\r
611 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
612 \r
613 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
614 //\r
615 // Report SEC Core debug information when remote debug is enabled\r
616 //\r
617 ImageContext.ImageAddress = SecCoreImageBase;\r
618 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
619 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
620\r
621 //\r
622 // Report PEI Core debug information when remote debug is enabled\r
623 //\r
624 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
625 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
626 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
627\r
628 //\r
629 // Find PEI Core entry point\r
630 //\r
631 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
632 if (EFI_ERROR (Status)) {\r
633 *PeiCoreEntryPoint = 0;\r
634 }\r
635\r
636 return;\r
637}\r
638\r
639VOID\r
640EFIAPI\r
641SecCoreStartupWithStack (\r
642 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
643 IN VOID *TopOfCurrentStack\r
644 )\r
645{\r
646 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
647 SEC_IDT_TABLE IdtTableInStack;\r
648 IA32_DESCRIPTOR IdtDescriptor;\r
649 UINT32 Index;\r
650\r
651 ProcessLibraryConstructorList (NULL, NULL);\r
652\r
c67178b7 653 DEBUG ((EFI_D_INFO,\r
bb4aa855
JJ
654 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
655 (UINT32)(UINTN)BootFv,\r
656 (UINT32)(UINTN)TopOfCurrentStack\r
657 ));\r
658\r
659 //\r
660 // Initialize floating point operating environment\r
661 // to be compliant with UEFI spec.\r
662 //\r
663 InitializeFloatingPointUnits ();\r
664\r
665 //\r
666 // Initialize IDT\r
667 // \r
668 IdtTableInStack.PeiService = NULL;\r
669 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
670 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
671 }\r
672\r
673 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
674 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
675\r
676 AsmWriteIdtr (&IdtDescriptor);\r
677\r
b382ede3
JJ
678#if defined (MDE_CPU_X64)\r
679 //\r
680 // ASSERT that the Page Tables were set by the reset vector code to\r
681 // the address we expect.\r
682 //\r
683 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
684#endif\r
685\r
bb4aa855
JJ
686 //\r
687 // |-------------| <-- TopOfCurrentStack\r
688 // | Stack | 32k\r
689 // |-------------|\r
690 // | Heap | 32k\r
691 // |-------------| <-- SecCoreData.TemporaryRamBase\r
692 //\r
693\r
7cb6b0e0
JJ
694 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
695 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
696 (UINTN) TopOfCurrentStack);\r
697\r
bb4aa855
JJ
698 //\r
699 // Initialize SEC hand-off state\r
700 //\r
701 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
702\r
7cb6b0e0 703 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
704 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
705\r
706 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
707 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
708\r
709 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
710 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
711\r
712 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
713 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
714\r
715 //\r
716 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
717 //\r
718 IoWrite8 (0x21, 0xff);\r
719 IoWrite8 (0xA1, 0xff);\r
720 \r
721 //\r
722 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
723 //\r
724 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
725}\r
726 \r
727/**\r
728 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
729\r
730 Entry point to the C language phase of SEC. After the SEC assembly\r
731 code has initialized some temporary memory and set up the stack,\r
732 the control is transferred to this function.\r
733\r
734 @param[in] Context The first input parameter of InitializeDebugAgent().\r
735\r
736**/\r
737VOID\r
738EFIAPI\r
739SecStartupPhase2(\r
740 IN VOID *Context\r
741 )\r
742{\r
743 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
744 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
745 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
746 \r
747 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
748 \r
749 //\r
750 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
751 // is enabled.\r
752 //\r
753 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
754 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
755 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
756 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
757\r
758 //\r
759 // Transfer the control to the PEI core\r
760 //\r
761 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
762 \r
763 //\r
764 // If we get here then the PEI Core returned, which is not recoverable.\r
765 //\r
766 ASSERT (FALSE);\r
767 CpuDeadLoop ();\r
768}\r
769\r
770EFI_STATUS\r
771EFIAPI\r
772TemporaryRamMigration (\r
773 IN CONST EFI_PEI_SERVICES **PeiServices,\r
774 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
775 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
776 IN UINTN CopySize\r
777 )\r
778{\r
779 IA32_DESCRIPTOR IdtDescriptor;\r
780 VOID *OldHeap;\r
781 VOID *NewHeap;\r
782 VOID *OldStack;\r
783 VOID *NewStack;\r
784 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
785 BOOLEAN OldStatus;\r
786 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
787 \r
c67178b7
JJ
788 DEBUG ((EFI_D_INFO,\r
789 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
790 (UINTN) TemporaryMemoryBase,\r
791 (UINTN) PermanentMemoryBase,\r
792 CopySize\r
793 ));\r
bb4aa855
JJ
794 \r
795 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
796 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
797 \r
798 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
799 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
800\r
801 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
802 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
803 \r
804 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
805 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
806\r
807 //\r
808 // Migrate Heap\r
809 //\r
810 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
811\r
812 //\r
813 // Migrate Stack\r
814 //\r
815 CopyMem (NewStack, OldStack, CopySize >> 1);\r
816 \r
817 //\r
818 // Rebase IDT table in permanent memory\r
819 //\r
820 AsmReadIdtr (&IdtDescriptor);\r
821 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
822\r
823 AsmWriteIdtr (&IdtDescriptor);\r
824\r
825 //\r
826 // Use SetJump()/LongJump() to switch to a new stack.\r
827 // \r
828 if (SetJump (&JumpBuffer) == 0) {\r
829#if defined (MDE_CPU_IA32)\r
830 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
831#endif \r
832#if defined (MDE_CPU_X64)\r
833 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
834#endif \r
835 LongJump (&JumpBuffer, (UINTN)-1);\r
836 }\r
837\r
838 SaveAndSetDebugTimerInterrupt (OldStatus);\r
839\r
840 return EFI_SUCCESS;\r
841}\r
842\r