]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
OvmfPkg/Sec: Add FindFfsSectionInstance
[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
314 On output, the decompressed main FV\r
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
bb4aa855
JJ
322DecompressGuidedFv (\r
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
334 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection;\r
335 EFI_FIRMWARE_VOLUME_HEADER *NewFv;\r
336\r
337 NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL;\r
338\r
339 Status = FindFfsFileAndSection (\r
340 *Fv,\r
341 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
342 EFI_SECTION_GUID_DEFINED,\r
343 (EFI_COMMON_SECTION_HEADER**) &Section\r
344 );\r
345 if (EFI_ERROR (Status)) {\r
346 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
347 return Status;\r
348 }\r
349\r
350 Status = ExtractGuidedSectionGetInfo (\r
351 Section,\r
352 &OutputBufferSize,\r
353 &ScratchBufferSize,\r
354 &SectionAttribute\r
355 );\r
356 if (EFI_ERROR (Status)) {\r
357 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
358 return Status;\r
359 }\r
360\r
361 //PcdGet32 (PcdOvmfMemFvBase), PcdGet32 (PcdOvmfMemFvSize)\r
362 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfMemFvBase) + SIZE_1MB);\r
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
375 Status = FindFfsSectionInSections (\r
376 OutputBuffer,\r
377 OutputBufferSize,\r
378 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
379 (EFI_COMMON_SECTION_HEADER**) &NewFvSection\r
380 );\r
381 if (EFI_ERROR (Status)) {\r
382 DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n"));\r
383 return Status;\r
384 }\r
385\r
386 NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfMemFvBase);\r
387 CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdOvmfMemFvSize));\r
388\r
389 if (NewFv->Signature != EFI_FVH_SIGNATURE) {\r
390 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv));\r
391 CpuDeadLoop ();\r
392 return EFI_VOLUME_CORRUPTED;\r
393 }\r
394\r
395 *Fv = NewFv;\r
396 return EFI_SUCCESS;\r
397}\r
398\r
399/**\r
400 Locates the PEI Core entry point address\r
401\r
402 @param[in] Fv The firmware volume to search\r
403 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
404\r
405 @retval EFI_SUCCESS The file and section was found\r
406 @retval EFI_NOT_FOUND The file and section was not found\r
407 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
408\r
409**/\r
410EFI_STATUS\r
bb4aa855
JJ
411FindPeiCoreImageBaseInFv (\r
412 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
413 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
414 )\r
415{\r
416 EFI_STATUS Status;\r
417 EFI_COMMON_SECTION_HEADER *Section;\r
418\r
419 Status = FindFfsFileAndSection (\r
420 Fv,\r
421 EFI_FV_FILETYPE_PEI_CORE,\r
422 EFI_SECTION_PE32,\r
423 &Section\r
424 );\r
425 if (EFI_ERROR (Status)) {\r
426 Status = FindFfsFileAndSection (\r
427 Fv,\r
428 EFI_FV_FILETYPE_PEI_CORE,\r
429 EFI_SECTION_TE,\r
430 &Section\r
431 );\r
432 if (EFI_ERROR (Status)) {\r
433 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
434 return Status;\r
435 }\r
436 }\r
437\r
438 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
439 return EFI_SUCCESS;\r
440}\r
441\r
442/**\r
443 Locates the PEI Core entry point address\r
444\r
445 @param[in,out] Fv The firmware volume to search\r
446 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
447\r
448 @retval EFI_SUCCESS The file and section was found\r
449 @retval EFI_NOT_FOUND The file and section was not found\r
450 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
451\r
452**/\r
453VOID\r
bb4aa855
JJ
454FindPeiCoreImageBase (\r
455 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
456 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
457 )\r
458{\r
459 *PeiCoreImageBase = 0;\r
460\r
461 FindMainFv (BootFv);\r
462\r
463 DecompressGuidedFv (BootFv);\r
464\r
465 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
466}\r
467\r
468/**\r
469 Find core image base.\r
470\r
471**/\r
472EFI_STATUS\r
bb4aa855
JJ
473FindImageBase (\r
474 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
475 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
476 )\r
477{\r
478 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
479 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
480 EFI_FFS_FILE_HEADER *File;\r
481 UINT32 Size;\r
482 EFI_PHYSICAL_ADDRESS EndOfFile;\r
483 EFI_COMMON_SECTION_HEADER *Section;\r
484 EFI_PHYSICAL_ADDRESS EndOfSection;\r
485\r
486 *SecCoreImageBase = 0;\r
487\r
488 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
489 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
490\r
491 //\r
492 // Loop through the FFS files in the Boot Firmware Volume\r
493 //\r
494 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
495\r
496 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
497 if (CurrentAddress > EndOfFirmwareVolume) {\r
498 return EFI_NOT_FOUND;\r
499 }\r
500\r
501 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
502 Size = *(UINT32*) File->Size & 0xffffff;\r
503 if (Size < sizeof (*File)) {\r
504 return EFI_NOT_FOUND;\r
505 }\r
506\r
507 EndOfFile = CurrentAddress + Size;\r
508 if (EndOfFile > EndOfFirmwareVolume) {\r
509 return EFI_NOT_FOUND;\r
510 }\r
511\r
512 //\r
513 // Look for SEC Core\r
514 //\r
515 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
516 continue;\r
517 }\r
518\r
519 //\r
520 // Loop through the FFS file sections within the FFS file\r
521 //\r
522 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
523 for (;;) {\r
524 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
525 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
526\r
527 Size = *(UINT32*) Section->Size & 0xffffff;\r
528 if (Size < sizeof (*Section)) {\r
529 return EFI_NOT_FOUND;\r
530 }\r
531\r
532 EndOfSection = CurrentAddress + Size;\r
533 if (EndOfSection > EndOfFile) {\r
534 return EFI_NOT_FOUND;\r
535 }\r
536\r
537 //\r
538 // Look for executable sections\r
539 //\r
540 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
541 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
542 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
543 }\r
544 break;\r
545 }\r
546 }\r
547\r
548 //\r
549 // SEC Core image found\r
550 //\r
551 if (*SecCoreImageBase != 0) {\r
552 return EFI_SUCCESS;\r
553 }\r
554 }\r
555}\r
556\r
557/*\r
558 Find and return Pei Core entry point.\r
559\r
560 It also find SEC and PEI Core file debug inforamtion. It will report them if\r
561 remote debug is enabled.\r
562\r
563**/\r
564VOID\r
bb4aa855
JJ
565FindAndReportEntryPoints (\r
566 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
567 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
568 )\r
569{\r
570 EFI_STATUS Status;\r
571 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
572 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
573 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
574\r
575 //\r
576 // Find SEC Core and PEI Core image base\r
577 //\r
578 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
579 ASSERT_EFI_ERROR (Status);\r
580\r
581 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
582 \r
583 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
584 //\r
585 // Report SEC Core debug information when remote debug is enabled\r
586 //\r
587 ImageContext.ImageAddress = SecCoreImageBase;\r
588 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
589 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
590\r
591 //\r
592 // Report PEI Core debug information when remote debug is enabled\r
593 //\r
594 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
595 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
596 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
597\r
598 //\r
599 // Find PEI Core entry point\r
600 //\r
601 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
602 if (EFI_ERROR (Status)) {\r
603 *PeiCoreEntryPoint = 0;\r
604 }\r
605\r
606 return;\r
607}\r
608\r
609VOID\r
610EFIAPI\r
611SecCoreStartupWithStack (\r
612 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
613 IN VOID *TopOfCurrentStack\r
614 )\r
615{\r
616 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
617 SEC_IDT_TABLE IdtTableInStack;\r
618 IA32_DESCRIPTOR IdtDescriptor;\r
619 UINT32 Index;\r
620\r
621 ProcessLibraryConstructorList (NULL, NULL);\r
622\r
c67178b7 623 DEBUG ((EFI_D_INFO,\r
bb4aa855
JJ
624 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
625 (UINT32)(UINTN)BootFv,\r
626 (UINT32)(UINTN)TopOfCurrentStack\r
627 ));\r
628\r
629 //\r
630 // Initialize floating point operating environment\r
631 // to be compliant with UEFI spec.\r
632 //\r
633 InitializeFloatingPointUnits ();\r
634\r
635 //\r
636 // Initialize IDT\r
637 // \r
638 IdtTableInStack.PeiService = NULL;\r
639 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
640 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
641 }\r
642\r
643 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
644 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
645\r
646 AsmWriteIdtr (&IdtDescriptor);\r
647\r
b382ede3
JJ
648#if defined (MDE_CPU_X64)\r
649 //\r
650 // ASSERT that the Page Tables were set by the reset vector code to\r
651 // the address we expect.\r
652 //\r
653 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
654#endif\r
655\r
bb4aa855
JJ
656 //\r
657 // |-------------| <-- TopOfCurrentStack\r
658 // | Stack | 32k\r
659 // |-------------|\r
660 // | Heap | 32k\r
661 // |-------------| <-- SecCoreData.TemporaryRamBase\r
662 //\r
663\r
7cb6b0e0
JJ
664 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
665 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
666 (UINTN) TopOfCurrentStack);\r
667\r
bb4aa855
JJ
668 //\r
669 // Initialize SEC hand-off state\r
670 //\r
671 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
672\r
7cb6b0e0 673 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
674 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
675\r
676 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
677 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
678\r
679 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
680 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
681\r
682 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
683 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
684\r
685 //\r
686 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
687 //\r
688 IoWrite8 (0x21, 0xff);\r
689 IoWrite8 (0xA1, 0xff);\r
690 \r
691 //\r
692 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
693 //\r
694 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
695}\r
696 \r
697/**\r
698 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
699\r
700 Entry point to the C language phase of SEC. After the SEC assembly\r
701 code has initialized some temporary memory and set up the stack,\r
702 the control is transferred to this function.\r
703\r
704 @param[in] Context The first input parameter of InitializeDebugAgent().\r
705\r
706**/\r
707VOID\r
708EFIAPI\r
709SecStartupPhase2(\r
710 IN VOID *Context\r
711 )\r
712{\r
713 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
714 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
715 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
716 \r
717 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
718 \r
719 //\r
720 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
721 // is enabled.\r
722 //\r
723 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
724 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
725 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
726 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
727\r
728 //\r
729 // Transfer the control to the PEI core\r
730 //\r
731 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
732 \r
733 //\r
734 // If we get here then the PEI Core returned, which is not recoverable.\r
735 //\r
736 ASSERT (FALSE);\r
737 CpuDeadLoop ();\r
738}\r
739\r
740EFI_STATUS\r
741EFIAPI\r
742TemporaryRamMigration (\r
743 IN CONST EFI_PEI_SERVICES **PeiServices,\r
744 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
745 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
746 IN UINTN CopySize\r
747 )\r
748{\r
749 IA32_DESCRIPTOR IdtDescriptor;\r
750 VOID *OldHeap;\r
751 VOID *NewHeap;\r
752 VOID *OldStack;\r
753 VOID *NewStack;\r
754 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
755 BOOLEAN OldStatus;\r
756 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
757 \r
c67178b7
JJ
758 DEBUG ((EFI_D_INFO,\r
759 "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n",\r
760 (UINTN) TemporaryMemoryBase,\r
761 (UINTN) PermanentMemoryBase,\r
762 CopySize\r
763 ));\r
bb4aa855
JJ
764 \r
765 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
766 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
767 \r
768 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
769 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
770\r
771 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
772 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
773 \r
774 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
775 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
776\r
777 //\r
778 // Migrate Heap\r
779 //\r
780 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
781\r
782 //\r
783 // Migrate Stack\r
784 //\r
785 CopyMem (NewStack, OldStack, CopySize >> 1);\r
786 \r
787 //\r
788 // Rebase IDT table in permanent memory\r
789 //\r
790 AsmReadIdtr (&IdtDescriptor);\r
791 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
792\r
793 AsmWriteIdtr (&IdtDescriptor);\r
794\r
795 //\r
796 // Use SetJump()/LongJump() to switch to a new stack.\r
797 // \r
798 if (SetJump (&JumpBuffer) == 0) {\r
799#if defined (MDE_CPU_IA32)\r
800 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
801#endif \r
802#if defined (MDE_CPU_X64)\r
803 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
804#endif \r
805 LongJump (&JumpBuffer, (UINTN)-1);\r
806 }\r
807\r
808 SaveAndSetDebugTimerInterrupt (OldStatus);\r
809\r
810 return EFI_SUCCESS;\r
811}\r
812\r