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