]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Sec/SecMain.c
IntelFsp2Pkg/SplitFspBin.py: Support rebasing 1.x binary.
[mirror_edk2.git] / OvmfPkg / Sec / SecMain.c
CommitLineData
bb4aa855
JJ
1/** @file\r
2 Main SEC phase code. Transitions to PEI.\r
3\r
f3e34b9d 4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>\r
5e443e37 5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
bb4aa855 6\r
b26f0cf9 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
bb4aa855
JJ
8\r
9**/\r
10\r
11#include <PiPei.h>\r
12\r
13#include <Library/PeimEntryPoint.h>\r
14#include <Library/BaseLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/PeiServicesLib.h>\r
18#include <Library/PcdLib.h>\r
19#include <Library/UefiCpuLib.h>\r
20#include <Library/DebugAgentLib.h>\r
21#include <Library/IoLib.h>\r
22#include <Library/PeCoffLib.h>\r
23#include <Library/PeCoffGetEntryPointLib.h>\r
24#include <Library/PeCoffExtraActionLib.h>\r
25#include <Library/ExtractGuidedSectionLib.h>\r
f3e34b9d 26#include <Library/LocalApicLib.h>\r
bb4aa855
JJ
27\r
28#include <Ppi/TemporaryRamSupport.h>\r
29\r
30#define SEC_IDT_ENTRY_COUNT 34\r
31\r
32typedef struct _SEC_IDT_TABLE {\r
33 EFI_PEI_SERVICES *PeiService;\r
34 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];\r
35} SEC_IDT_TABLE;\r
36\r
37VOID\r
38EFIAPI\r
39SecStartupPhase2 (\r
40 IN VOID *Context\r
41 );\r
42\r
43EFI_STATUS\r
44EFIAPI\r
45TemporaryRamMigration (\r
46 IN CONST EFI_PEI_SERVICES **PeiServices,\r
47 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
48 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
49 IN UINTN CopySize\r
50 );\r
51\r
52//\r
53//\r
54// \r
55EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {\r
56 TemporaryRamMigration\r
57};\r
58\r
59EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {\r
60 {\r
61 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
62 &gEfiTemporaryRamSupportPpiGuid,\r
63 &mTemporaryRamSupportPpi\r
64 },\r
65};\r
66\r
67//\r
68// Template of an IDT entry pointing to 10:FFFFFFE4h.\r
69//\r
70IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {\r
71 { // Bits\r
72 0xffe4, // OffsetLow\r
73 0x10, // Selector\r
74 0x0, // Reserved_0\r
75 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType\r
76 0xffff // OffsetHigh\r
77 } \r
78};\r
79\r
80/**\r
81 Locates the main boot firmware volume.\r
82\r
83 @param[in,out] BootFv On input, the base of the BootFv\r
84 On output, the decompressed main firmware volume\r
85\r
86 @retval EFI_SUCCESS The main firmware volume was located and decompressed\r
87 @retval EFI_NOT_FOUND The main firmware volume was not found\r
88\r
89**/\r
90EFI_STATUS\r
91FindMainFv (\r
92 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv\r
93 )\r
94{\r
95 EFI_FIRMWARE_VOLUME_HEADER *Fv;\r
96 UINTN Distance;\r
97\r
98 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0);\r
99\r
100 Fv = *BootFv;\r
101 Distance = (UINTN) (*BootFv)->FvLength;\r
102 do {\r
103 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE);\r
104 Distance += EFI_PAGE_SIZE;\r
105 if (Distance > SIZE_32MB) {\r
106 return EFI_NOT_FOUND;\r
107 }\r
108\r
109 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
110 continue;\r
111 }\r
112\r
113 if ((UINTN) Fv->FvLength > Distance) {\r
114 continue;\r
115 }\r
116\r
117 *BootFv = Fv;\r
118 return EFI_SUCCESS;\r
119\r
120 } while (TRUE);\r
121}\r
122\r
123/**\r
124 Locates a section within a series of sections\r
125 with the specified section type.\r
126\r
4b4b783d
JJ
127 The Instance parameter indicates which instance of the section\r
128 type to return. (0 is first instance, 1 is second...)\r
129\r
bb4aa855
JJ
130 @param[in] Sections The sections to search\r
131 @param[in] SizeOfSections Total size of all sections\r
132 @param[in] SectionType The section type to locate\r
4b4b783d 133 @param[in] Instance The section instance number\r
bb4aa855
JJ
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
4b4b783d 142FindFfsSectionInstance (\r
bb4aa855
JJ
143 IN VOID *Sections,\r
144 IN UINTN SizeOfSections,\r
145 IN EFI_SECTION_TYPE SectionType,\r
4b4b783d 146 IN UINTN Instance,\r
bb4aa855
JJ
147 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
148 )\r
149{\r
150 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
151 UINT32 Size;\r
152 EFI_PHYSICAL_ADDRESS EndOfSections;\r
153 EFI_COMMON_SECTION_HEADER *Section;\r
154 EFI_PHYSICAL_ADDRESS EndOfSection;\r
155\r
156 //\r
157 // Loop through the FFS file sections within the PEI Core FFS file\r
158 //\r
159 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections;\r
160 EndOfSections = EndOfSection + SizeOfSections;\r
161 for (;;) {\r
162 if (EndOfSection == EndOfSections) {\r
163 break;\r
164 }\r
165 CurrentAddress = (EndOfSection + 3) & ~(3ULL);\r
166 if (CurrentAddress >= EndOfSections) {\r
167 return EFI_VOLUME_CORRUPTED;\r
168 }\r
169\r
170 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
bb4aa855
JJ
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
4b4b783d
JJ
186 if (Instance == 0) {\r
187 *FoundSection = Section;\r
188 return EFI_SUCCESS;\r
189 } else {\r
190 Instance--;\r
191 }\r
bb4aa855 192 }\r
bb4aa855
JJ
193 }\r
194\r
195 return EFI_NOT_FOUND;\r
196}\r
197\r
4b4b783d
JJ
198/**\r
199 Locates a section within a series of sections\r
200 with the specified section type.\r
201\r
202 @param[in] Sections The sections to search\r
203 @param[in] SizeOfSections Total size of all sections\r
204 @param[in] SectionType The section type to locate\r
205 @param[out] FoundSection The FFS section if found\r
206\r
207 @retval EFI_SUCCESS The file and section was found\r
208 @retval EFI_NOT_FOUND The file and section was not found\r
209 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
210\r
211**/\r
212EFI_STATUS\r
213FindFfsSectionInSections (\r
214 IN VOID *Sections,\r
215 IN UINTN SizeOfSections,\r
216 IN EFI_SECTION_TYPE SectionType,\r
217 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
218 )\r
219{\r
220 return FindFfsSectionInstance (\r
221 Sections,\r
222 SizeOfSections,\r
223 SectionType,\r
224 0,\r
225 FoundSection\r
226 );\r
227}\r
228\r
bb4aa855
JJ
229/**\r
230 Locates a FFS file with the specified file type and a section\r
231 within that file with the specified section type.\r
232\r
233 @param[in] Fv The firmware volume to search\r
234 @param[in] FileType The file type to locate\r
235 @param[in] SectionType The section type to locate\r
236 @param[out] FoundSection The FFS section if found\r
237\r
238 @retval EFI_SUCCESS The file and section was found\r
239 @retval EFI_NOT_FOUND The file and section was not found\r
240 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
241\r
242**/\r
243EFI_STATUS\r
bb4aa855
JJ
244FindFfsFileAndSection (\r
245 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
246 IN EFI_FV_FILETYPE FileType,\r
247 IN EFI_SECTION_TYPE SectionType,\r
248 OUT EFI_COMMON_SECTION_HEADER **FoundSection\r
249 )\r
250{\r
251 EFI_STATUS Status;\r
252 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
253 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
254 EFI_FFS_FILE_HEADER *File;\r
255 UINT32 Size;\r
256 EFI_PHYSICAL_ADDRESS EndOfFile;\r
257\r
258 if (Fv->Signature != EFI_FVH_SIGNATURE) {\r
c67178b7 259 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv));\r
bb4aa855
JJ
260 return EFI_VOLUME_CORRUPTED;\r
261 }\r
262\r
263 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv;\r
264 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;\r
265\r
266 //\r
267 // Loop through the FFS files in the Boot Firmware Volume\r
268 //\r
269 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {\r
270\r
271 CurrentAddress = (EndOfFile + 7) & ~(7ULL);\r
272 if (CurrentAddress > EndOfFirmwareVolume) {\r
273 return EFI_VOLUME_CORRUPTED;\r
274 }\r
275\r
276 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
b9d4847e 277 Size = FFS_FILE_SIZE (File);\r
bb4aa855
JJ
278 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {\r
279 return EFI_VOLUME_CORRUPTED;\r
280 }\r
bb4aa855
JJ
281\r
282 EndOfFile = CurrentAddress + Size;\r
283 if (EndOfFile > EndOfFirmwareVolume) {\r
284 return EFI_VOLUME_CORRUPTED;\r
285 }\r
286\r
287 //\r
288 // Look for the request file type\r
289 //\r
290 if (File->Type != FileType) {\r
bb4aa855
JJ
291 continue;\r
292 }\r
293\r
294 Status = FindFfsSectionInSections (\r
295 (VOID*) (File + 1),\r
296 (UINTN) EndOfFile - (UINTN) (File + 1),\r
297 SectionType,\r
298 FoundSection\r
299 );\r
300 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {\r
301 return Status;\r
302 }\r
303 }\r
304}\r
305\r
306/**\r
307 Locates the compressed main firmware volume and decompresses it.\r
308\r
309 @param[in,out] Fv On input, the firmware volume to search\r
b36f701d 310 On output, the decompressed BOOT/PEI FV\r
bb4aa855
JJ
311\r
312 @retval EFI_SUCCESS The file and section was found\r
313 @retval EFI_NOT_FOUND The file and section was not found\r
314 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
315\r
316**/\r
317EFI_STATUS\r
b36f701d 318DecompressMemFvs (\r
bb4aa855
JJ
319 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv\r
320 )\r
321{\r
322 EFI_STATUS Status;\r
323 EFI_GUID_DEFINED_SECTION *Section;\r
324 UINT32 OutputBufferSize;\r
325 UINT32 ScratchBufferSize;\r
326 UINT16 SectionAttribute;\r
327 UINT32 AuthenticationStatus;\r
328 VOID *OutputBuffer;\r
329 VOID *ScratchBuffer;\r
5e443e37 330 EFI_COMMON_SECTION_HEADER *FvSection;\r
b36f701d
JJ
331 EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;\r
332 EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;\r
39dbc4d5
TP
333 UINT32 FvHeaderSize;\r
334 UINT32 FvSectionSize;\r
bb4aa855 335\r
5e443e37 336 FvSection = (EFI_COMMON_SECTION_HEADER*) NULL;\r
bb4aa855
JJ
337\r
338 Status = FindFfsFileAndSection (\r
339 *Fv,\r
340 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,\r
341 EFI_SECTION_GUID_DEFINED,\r
342 (EFI_COMMON_SECTION_HEADER**) &Section\r
343 );\r
344 if (EFI_ERROR (Status)) {\r
345 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n"));\r
346 return Status;\r
347 }\r
348\r
349 Status = ExtractGuidedSectionGetInfo (\r
350 Section,\r
351 &OutputBufferSize,\r
352 &ScratchBufferSize,\r
353 &SectionAttribute\r
354 );\r
355 if (EFI_ERROR (Status)) {\r
356 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n"));\r
357 return Status;\r
358 }\r
359\r
b36f701d 360 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);\r
bb4aa855 361 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB);\r
9beac0d8
LE
362\r
363 DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "\r
364 "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer,\r
365 OutputBufferSize, ScratchBuffer, ScratchBufferSize,\r
366 PcdGet32 (PcdOvmfDecompressionScratchEnd)));\r
367 ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize ==\r
368 PcdGet32 (PcdOvmfDecompressionScratchEnd));\r
369\r
bb4aa855
JJ
370 Status = ExtractGuidedSectionDecode (\r
371 Section,\r
372 &OutputBuffer,\r
373 ScratchBuffer,\r
374 &AuthenticationStatus\r
375 );\r
376 if (EFI_ERROR (Status)) {\r
377 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n"));\r
378 return Status;\r
379 }\r
380\r
b36f701d 381 Status = FindFfsSectionInstance (\r
bb4aa855
JJ
382 OutputBuffer,\r
383 OutputBufferSize,\r
384 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
b36f701d 385 0,\r
5e443e37 386 &FvSection\r
bb4aa855
JJ
387 );\r
388 if (EFI_ERROR (Status)) {\r
b36f701d 389 DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n"));\r
bb4aa855
JJ
390 return Status;\r
391 }\r
392\r
b36f701d
JJ
393 ASSERT (SECTION_SIZE (FvSection) ==\r
394 (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection)));\r
395 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
bb4aa855 396\r
b36f701d
JJ
397 PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
398 CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));\r
399\r
400 if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {\r
401 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));\r
402 CpuDeadLoop ();\r
403 return EFI_VOLUME_CORRUPTED;\r
404 }\r
405\r
406 Status = FindFfsSectionInstance (\r
407 OutputBuffer,\r
408 OutputBufferSize,\r
409 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,\r
410 1,\r
5e443e37 411 &FvSection\r
b36f701d
JJ
412 );\r
413 if (EFI_ERROR (Status)) {\r
414 DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n"));\r
415 return Status;\r
416 }\r
417\r
418 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);\r
39dbc4d5
TP
419\r
420 if (IS_SECTION2 (FvSection)) {\r
421 FvSectionSize = SECTION2_SIZE (FvSection);\r
422 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
423 } else {\r
424 FvSectionSize = SECTION_SIZE (FvSection);\r
425 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
426 }\r
427\r
428 ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));\r
b36f701d
JJ
429\r
430 DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase);\r
39dbc4d5 431 CopyMem (DxeMemFv, (VOID*) ((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));\r
b36f701d
JJ
432\r
433 if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {\r
434 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));\r
bb4aa855
JJ
435 CpuDeadLoop ();\r
436 return EFI_VOLUME_CORRUPTED;\r
437 }\r
438\r
b36f701d 439 *Fv = PeiMemFv;\r
bb4aa855
JJ
440 return EFI_SUCCESS;\r
441}\r
442\r
443/**\r
444 Locates the PEI Core entry point address\r
445\r
446 @param[in] Fv The firmware volume to search\r
447 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
448\r
449 @retval EFI_SUCCESS The file and section was found\r
450 @retval EFI_NOT_FOUND The file and section was not found\r
451 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
452\r
453**/\r
454EFI_STATUS\r
bb4aa855
JJ
455FindPeiCoreImageBaseInFv (\r
456 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,\r
457 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
458 )\r
459{\r
460 EFI_STATUS Status;\r
461 EFI_COMMON_SECTION_HEADER *Section;\r
462\r
463 Status = FindFfsFileAndSection (\r
464 Fv,\r
465 EFI_FV_FILETYPE_PEI_CORE,\r
466 EFI_SECTION_PE32,\r
467 &Section\r
468 );\r
469 if (EFI_ERROR (Status)) {\r
470 Status = FindFfsFileAndSection (\r
471 Fv,\r
472 EFI_FV_FILETYPE_PEI_CORE,\r
473 EFI_SECTION_TE,\r
474 &Section\r
475 );\r
476 if (EFI_ERROR (Status)) {\r
477 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n"));\r
478 return Status;\r
479 }\r
480 }\r
481\r
482 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);\r
483 return EFI_SUCCESS;\r
484}\r
485\r
a781f709
JJ
486\r
487/**\r
488 Reads 8-bits of CMOS data.\r
489\r
490 Reads the 8-bits of CMOS data at the location specified by Index.\r
491 The 8-bit read value is returned.\r
492\r
493 @param Index The CMOS location to read.\r
494\r
495 @return The value read.\r
496\r
497**/\r
498STATIC\r
499UINT8\r
500CmosRead8 (\r
501 IN UINTN Index\r
502 )\r
503{\r
504 IoWrite8 (0x70, (UINT8) Index);\r
505 return IoRead8 (0x71);\r
506}\r
507\r
508\r
509STATIC\r
510BOOLEAN\r
511IsS3Resume (\r
512 VOID\r
513 )\r
514{\r
515 return (CmosRead8 (0xF) == 0xFE);\r
516}\r
517\r
518\r
519STATIC\r
520EFI_STATUS\r
521GetS3ResumePeiFv (\r
522 IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv\r
523 )\r
524{\r
525 *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase);\r
526 return EFI_SUCCESS;\r
527}\r
528\r
529\r
bb4aa855
JJ
530/**\r
531 Locates the PEI Core entry point address\r
532\r
533 @param[in,out] Fv The firmware volume to search\r
534 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image\r
535\r
536 @retval EFI_SUCCESS The file and section was found\r
537 @retval EFI_NOT_FOUND The file and section was not found\r
538 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted\r
539\r
540**/\r
541VOID\r
bb4aa855
JJ
542FindPeiCoreImageBase (\r
543 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,\r
544 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase\r
545 )\r
546{\r
efb0f16e
LE
547 BOOLEAN S3Resume;\r
548\r
bb4aa855
JJ
549 *PeiCoreImageBase = 0;\r
550\r
efb0f16e
LE
551 S3Resume = IsS3Resume ();\r
552 if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {\r
553 //\r
554 // A malicious runtime OS may have injected something into our previously\r
555 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.\r
556 //\r
a781f709
JJ
557 DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n"));\r
558 GetS3ResumePeiFv (BootFv);\r
559 } else {\r
efb0f16e
LE
560 //\r
561 // We're either not resuming, or resuming "securely" -- we'll decompress\r
562 // both PEI FV and DXE FV from pristine flash.\r
563 //\r
564 DEBUG ((EFI_D_VERBOSE, "SEC: %a\n",\r
565 S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"));\r
a781f709 566 FindMainFv (BootFv);\r
bb4aa855 567\r
a781f709
JJ
568 DecompressMemFvs (BootFv);\r
569 }\r
bb4aa855
JJ
570\r
571 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);\r
572}\r
573\r
574/**\r
575 Find core image base.\r
576\r
577**/\r
578EFI_STATUS\r
bb4aa855
JJ
579FindImageBase (\r
580 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,\r
581 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase\r
582 )\r
583{\r
584 EFI_PHYSICAL_ADDRESS CurrentAddress;\r
585 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;\r
586 EFI_FFS_FILE_HEADER *File;\r
587 UINT32 Size;\r
588 EFI_PHYSICAL_ADDRESS EndOfFile;\r
589 EFI_COMMON_SECTION_HEADER *Section;\r
590 EFI_PHYSICAL_ADDRESS EndOfSection;\r
591\r
592 *SecCoreImageBase = 0;\r
593\r
594 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;\r
595 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;\r
596\r
597 //\r
598 // Loop through the FFS files in the Boot Firmware Volume\r
599 //\r
600 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {\r
601\r
602 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;\r
603 if (CurrentAddress > EndOfFirmwareVolume) {\r
604 return EFI_NOT_FOUND;\r
605 }\r
606\r
607 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;\r
b9d4847e 608 Size = FFS_FILE_SIZE (File);\r
bb4aa855
JJ
609 if (Size < sizeof (*File)) {\r
610 return EFI_NOT_FOUND;\r
611 }\r
612\r
613 EndOfFile = CurrentAddress + Size;\r
614 if (EndOfFile > EndOfFirmwareVolume) {\r
615 return EFI_NOT_FOUND;\r
616 }\r
617\r
618 //\r
619 // Look for SEC Core\r
620 //\r
621 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {\r
622 continue;\r
623 }\r
624\r
625 //\r
626 // Loop through the FFS file sections within the FFS file\r
627 //\r
628 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1);\r
629 for (;;) {\r
630 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;\r
631 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;\r
632\r
b9d4847e 633 Size = SECTION_SIZE (Section);\r
bb4aa855
JJ
634 if (Size < sizeof (*Section)) {\r
635 return EFI_NOT_FOUND;\r
636 }\r
637\r
638 EndOfSection = CurrentAddress + Size;\r
639 if (EndOfSection > EndOfFile) {\r
640 return EFI_NOT_FOUND;\r
641 }\r
642\r
643 //\r
644 // Look for executable sections\r
645 //\r
646 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {\r
647 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {\r
648 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1);\r
649 }\r
650 break;\r
651 }\r
652 }\r
653\r
654 //\r
655 // SEC Core image found\r
656 //\r
657 if (*SecCoreImageBase != 0) {\r
658 return EFI_SUCCESS;\r
659 }\r
660 }\r
661}\r
662\r
663/*\r
664 Find and return Pei Core entry point.\r
665\r
f17c0ab6 666 It also find SEC and PEI Core file debug information. It will report them if\r
bb4aa855
JJ
667 remote debug is enabled.\r
668\r
669**/\r
670VOID\r
bb4aa855
JJ
671FindAndReportEntryPoints (\r
672 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,\r
673 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint\r
674 )\r
675{\r
676 EFI_STATUS Status;\r
677 EFI_PHYSICAL_ADDRESS SecCoreImageBase;\r
678 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;\r
679 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
680\r
681 //\r
682 // Find SEC Core and PEI Core image base\r
683 //\r
684 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);\r
685 ASSERT_EFI_ERROR (Status);\r
686\r
687 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);\r
688 \r
689 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));\r
690 //\r
691 // Report SEC Core debug information when remote debug is enabled\r
692 //\r
693 ImageContext.ImageAddress = SecCoreImageBase;\r
694 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
695 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
696\r
697 //\r
698 // Report PEI Core debug information when remote debug is enabled\r
699 //\r
700 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;\r
701 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);\r
702 PeCoffLoaderRelocateImageExtraAction (&ImageContext);\r
703\r
704 //\r
705 // Find PEI Core entry point\r
706 //\r
707 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);\r
708 if (EFI_ERROR (Status)) {\r
709 *PeiCoreEntryPoint = 0;\r
710 }\r
711\r
712 return;\r
713}\r
714\r
715VOID\r
716EFIAPI\r
717SecCoreStartupWithStack (\r
718 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,\r
719 IN VOID *TopOfCurrentStack\r
720 )\r
721{\r
722 EFI_SEC_PEI_HAND_OFF SecCoreData;\r
723 SEC_IDT_TABLE IdtTableInStack;\r
724 IA32_DESCRIPTOR IdtDescriptor;\r
725 UINT32 Index;\r
320b4f08
LE
726 volatile UINT8 *Table;\r
727\r
728 //\r
729 // To ensure SMM can't be compromised on S3 resume, we must force re-init of\r
730 // the BaseExtractGuidedSectionLib. Since this is before library contructors\r
731 // are called, we must use a loop rather than SetMem.\r
732 //\r
733 Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);\r
734 for (Index = 0;\r
735 Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);\r
736 ++Index) {\r
737 Table[Index] = 0;\r
738 }\r
bb4aa855
JJ
739\r
740 ProcessLibraryConstructorList (NULL, NULL);\r
741\r
c67178b7 742 DEBUG ((EFI_D_INFO,\r
bb4aa855
JJ
743 "SecCoreStartupWithStack(0x%x, 0x%x)\n",\r
744 (UINT32)(UINTN)BootFv,\r
745 (UINT32)(UINTN)TopOfCurrentStack\r
746 ));\r
747\r
748 //\r
749 // Initialize floating point operating environment\r
750 // to be compliant with UEFI spec.\r
751 //\r
752 InitializeFloatingPointUnits ();\r
753\r
754 //\r
755 // Initialize IDT\r
756 // \r
757 IdtTableInStack.PeiService = NULL;\r
758 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {\r
759 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));\r
760 }\r
761\r
762 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;\r
763 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);\r
764\r
765 AsmWriteIdtr (&IdtDescriptor);\r
766\r
b382ede3
JJ
767#if defined (MDE_CPU_X64)\r
768 //\r
769 // ASSERT that the Page Tables were set by the reset vector code to\r
770 // the address we expect.\r
771 //\r
772 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase));\r
773#endif\r
774\r
bb4aa855
JJ
775 //\r
776 // |-------------| <-- TopOfCurrentStack\r
777 // | Stack | 32k\r
778 // |-------------|\r
779 // | Heap | 32k\r
780 // |-------------| <-- SecCoreData.TemporaryRamBase\r
781 //\r
782\r
7cb6b0e0
JJ
783 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) +\r
784 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==\r
785 (UINTN) TopOfCurrentStack);\r
786\r
bb4aa855
JJ
787 //\r
788 // Initialize SEC hand-off state\r
789 //\r
790 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF);\r
791\r
7cb6b0e0 792 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize);\r
bb4aa855
JJ
793 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);\r
794\r
795 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;\r
796 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;\r
797\r
798 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;\r
799 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;\r
800\r
801 SecCoreData.BootFirmwareVolumeBase = BootFv;\r
802 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
803\r
804 //\r
805 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled\r
806 //\r
807 IoWrite8 (0x21, 0xff);\r
808 IoWrite8 (0xA1, 0xff);\r
f3e34b9d
MK
809\r
810 //\r
811 // Initialize Local APIC Timer hardware and disable Local APIC Timer\r
812 // interrupts before initializing the Debug Agent and the debug timer is\r
813 // enabled.\r
814 //\r
815 InitializeApicTimer (0, MAX_UINT32, TRUE, 5);\r
816 DisableApicTimerInterrupt ();\r
bb4aa855
JJ
817 \r
818 //\r
819 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.\r
820 //\r
821 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);\r
822}\r
823 \r
824/**\r
825 Caller provided function to be invoked at the end of InitializeDebugAgent().\r
826\r
827 Entry point to the C language phase of SEC. After the SEC assembly\r
828 code has initialized some temporary memory and set up the stack,\r
829 the control is transferred to this function.\r
830\r
831 @param[in] Context The first input parameter of InitializeDebugAgent().\r
832\r
833**/\r
834VOID\r
835EFIAPI\r
836SecStartupPhase2(\r
837 IN VOID *Context\r
838 )\r
839{\r
840 EFI_SEC_PEI_HAND_OFF *SecCoreData;\r
841 EFI_FIRMWARE_VOLUME_HEADER *BootFv;\r
842 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;\r
843 \r
844 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;\r
845 \r
846 //\r
847 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug\r
848 // is enabled.\r
849 //\r
850 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;\r
851 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);\r
852 SecCoreData->BootFirmwareVolumeBase = BootFv;\r
853 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;\r
854\r
855 //\r
856 // Transfer the control to the PEI core\r
857 //\r
858 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);\r
859 \r
860 //\r
861 // If we get here then the PEI Core returned, which is not recoverable.\r
862 //\r
863 ASSERT (FALSE);\r
864 CpuDeadLoop ();\r
865}\r
866\r
867EFI_STATUS\r
868EFIAPI\r
869TemporaryRamMigration (\r
870 IN CONST EFI_PEI_SERVICES **PeiServices,\r
871 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,\r
872 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,\r
873 IN UINTN CopySize\r
874 )\r
875{\r
876 IA32_DESCRIPTOR IdtDescriptor;\r
877 VOID *OldHeap;\r
878 VOID *NewHeap;\r
879 VOID *OldStack;\r
880 VOID *NewStack;\r
881 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;\r
882 BOOLEAN OldStatus;\r
883 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;\r
884 \r
c67178b7 885 DEBUG ((EFI_D_INFO,\r
6394c35a
LE
886 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",\r
887 TemporaryMemoryBase,\r
888 PermanentMemoryBase,\r
889 (UINT64)CopySize\r
c67178b7 890 ));\r
bb4aa855
JJ
891 \r
892 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;\r
893 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));\r
894 \r
895 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));\r
896 NewStack = (VOID*)(UINTN)PermanentMemoryBase;\r
897\r
898 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;\r
899 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;\r
900 \r
901 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);\r
902 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);\r
903\r
904 //\r
905 // Migrate Heap\r
906 //\r
907 CopyMem (NewHeap, OldHeap, CopySize >> 1);\r
908\r
909 //\r
910 // Migrate Stack\r
911 //\r
912 CopyMem (NewStack, OldStack, CopySize >> 1);\r
913 \r
914 //\r
915 // Rebase IDT table in permanent memory\r
916 //\r
917 AsmReadIdtr (&IdtDescriptor);\r
918 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;\r
919\r
920 AsmWriteIdtr (&IdtDescriptor);\r
921\r
922 //\r
923 // Use SetJump()/LongJump() to switch to a new stack.\r
924 // \r
925 if (SetJump (&JumpBuffer) == 0) {\r
926#if defined (MDE_CPU_IA32)\r
927 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;\r
89796c69 928 JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;\r
bb4aa855
JJ
929#endif \r
930#if defined (MDE_CPU_X64)\r
931 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;\r
89796c69 932 JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;\r
bb4aa855
JJ
933#endif \r
934 LongJump (&JumpBuffer, (UINTN)-1);\r
935 }\r
936\r
937 SaveAndSetDebugTimerInterrupt (OldStatus);\r
938\r
939 return EFI_SUCCESS;\r
940}\r
941\r