VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/Sec/SecMain.c@ 101291

Last change on this file since 101291 was 101291, checked in by vboxsync, 14 months ago

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • Property svn:eol-style set to native
File size: 29.9 KB
Line 
1/** @file
2 Main SEC phase code. Transitions to PEI.
3
4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
6 Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <PiPei.h>
13
14#include <Library/PeimEntryPoint.h>
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/BaseMemoryLib.h>
18#include <Library/PeiServicesLib.h>
19#include <Library/PcdLib.h>
20#include <Library/CpuLib.h>
21#include <Library/DebugAgentLib.h>
22#include <Library/IoLib.h>
23#include <Library/PeCoffLib.h>
24#include <Library/PeCoffGetEntryPointLib.h>
25#include <Library/PeCoffExtraActionLib.h>
26#include <Library/ExtractGuidedSectionLib.h>
27#include <Library/LocalApicLib.h>
28#include <Library/CpuExceptionHandlerLib.h>
29#include <Ppi/TemporaryRamSupport.h>
30#include <Ppi/MpInitLibDep.h>
31#include <Library/TdxHelperLib.h>
32#include <Library/CcProbeLib.h>
33#include "AmdSev.h"
34
35#define SEC_IDT_ENTRY_COUNT 34
36
37typedef struct _SEC_IDT_TABLE {
38 EFI_PEI_SERVICES *PeiService;
39 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
40} SEC_IDT_TABLE;
41
42VOID
43EFIAPI
44SecStartupPhase2 (
45 IN VOID *Context
46 );
47
48EFI_STATUS
49EFIAPI
50TemporaryRamMigration (
51 IN CONST EFI_PEI_SERVICES **PeiServices,
52 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
53 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
54 IN UINTN CopySize
55 );
56
57//
58//
59//
60EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
61 TemporaryRamMigration
62};
63
64EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableMp[] = {
65 {
66 (EFI_PEI_PPI_DESCRIPTOR_PPI),
67 &gEfiTemporaryRamSupportPpiGuid,
68 &mTemporaryRamSupportPpi
69 },
70 {
71 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
72 &gEfiPeiMpInitLibMpDepPpiGuid,
73 NULL
74 },
75};
76
77EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTableUp[] = {
78 {
79 (EFI_PEI_PPI_DESCRIPTOR_PPI),
80 &gEfiTemporaryRamSupportPpiGuid,
81 &mTemporaryRamSupportPpi
82 },
83 {
84 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
85 &gEfiPeiMpInitLibUpDepPpiGuid,
86 NULL
87 },
88};
89
90//
91// Template of an IDT entry pointing to 10:FFFFFFE4h.
92//
93IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = {
94 { // Bits
95 0xffe4, // OffsetLow
96 0x10, // Selector
97 0x0, // Reserved_0
98 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType
99 0xffff // OffsetHigh
100 }
101};
102
103/**
104 Locates the main boot firmware volume.
105
106 @param[in,out] BootFv On input, the base of the BootFv
107 On output, the decompressed main firmware volume
108
109 @retval EFI_SUCCESS The main firmware volume was located and decompressed
110 @retval EFI_NOT_FOUND The main firmware volume was not found
111
112**/
113EFI_STATUS
114FindMainFv (
115 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv
116 )
117{
118 EFI_FIRMWARE_VOLUME_HEADER *Fv;
119 UINTN Distance;
120
121 ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0);
122
123 Fv = *BootFv;
124 Distance = (UINTN)(*BootFv)->FvLength;
125 do {
126 Fv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv - EFI_PAGE_SIZE);
127 Distance += EFI_PAGE_SIZE;
128 if (Distance > SIZE_32MB) {
129 return EFI_NOT_FOUND;
130 }
131
132 if (Fv->Signature != EFI_FVH_SIGNATURE) {
133 continue;
134 }
135
136 if ((UINTN)Fv->FvLength > Distance) {
137 continue;
138 }
139
140 *BootFv = Fv;
141 return EFI_SUCCESS;
142 } while (TRUE);
143}
144
145/**
146 Locates a section within a series of sections
147 with the specified section type.
148
149 The Instance parameter indicates which instance of the section
150 type to return. (0 is first instance, 1 is second...)
151
152 @param[in] Sections The sections to search
153 @param[in] SizeOfSections Total size of all sections
154 @param[in] SectionType The section type to locate
155 @param[in] Instance The section instance number
156 @param[out] FoundSection The FFS section if found
157
158 @retval EFI_SUCCESS The file and section was found
159 @retval EFI_NOT_FOUND The file and section was not found
160 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
161
162**/
163EFI_STATUS
164FindFfsSectionInstance (
165 IN VOID *Sections,
166 IN UINTN SizeOfSections,
167 IN EFI_SECTION_TYPE SectionType,
168 IN UINTN Instance,
169 OUT EFI_COMMON_SECTION_HEADER **FoundSection
170 )
171{
172 EFI_PHYSICAL_ADDRESS CurrentAddress;
173 UINT32 Size;
174 EFI_PHYSICAL_ADDRESS EndOfSections;
175 EFI_COMMON_SECTION_HEADER *Section;
176 EFI_PHYSICAL_ADDRESS EndOfSection;
177
178 //
179 // Loop through the FFS file sections within the PEI Core FFS file
180 //
181 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections;
182 EndOfSections = EndOfSection + SizeOfSections;
183 for ( ; ;) {
184 if (EndOfSection == EndOfSections) {
185 break;
186 }
187
188 CurrentAddress = (EndOfSection + 3) & ~(3ULL);
189 if (CurrentAddress >= EndOfSections) {
190 return EFI_VOLUME_CORRUPTED;
191 }
192
193 Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
194
195 Size = SECTION_SIZE (Section);
196 if (Size < sizeof (*Section)) {
197 return EFI_VOLUME_CORRUPTED;
198 }
199
200 EndOfSection = CurrentAddress + Size;
201 if (EndOfSection > EndOfSections) {
202 return EFI_VOLUME_CORRUPTED;
203 }
204
205 //
206 // Look for the requested section type
207 //
208 if (Section->Type == SectionType) {
209 if (Instance == 0) {
210 *FoundSection = Section;
211 return EFI_SUCCESS;
212 } else {
213 Instance--;
214 }
215 }
216 }
217
218 return EFI_NOT_FOUND;
219}
220
221/**
222 Locates a section within a series of sections
223 with the specified section type.
224
225 @param[in] Sections The sections to search
226 @param[in] SizeOfSections Total size of all sections
227 @param[in] SectionType The section type to locate
228 @param[out] FoundSection The FFS section if found
229
230 @retval EFI_SUCCESS The file and section was found
231 @retval EFI_NOT_FOUND The file and section was not found
232 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
233
234**/
235EFI_STATUS
236FindFfsSectionInSections (
237 IN VOID *Sections,
238 IN UINTN SizeOfSections,
239 IN EFI_SECTION_TYPE SectionType,
240 OUT EFI_COMMON_SECTION_HEADER **FoundSection
241 )
242{
243 return FindFfsSectionInstance (
244 Sections,
245 SizeOfSections,
246 SectionType,
247 0,
248 FoundSection
249 );
250}
251
252/**
253 Locates a FFS file with the specified file type and a section
254 within that file with the specified section type.
255
256 @param[in] Fv The firmware volume to search
257 @param[in] FileType The file type to locate
258 @param[in] SectionType The section type to locate
259 @param[out] FoundSection The FFS section if found
260
261 @retval EFI_SUCCESS The file and section was found
262 @retval EFI_NOT_FOUND The file and section was not found
263 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
264
265**/
266EFI_STATUS
267FindFfsFileAndSection (
268 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
269 IN EFI_FV_FILETYPE FileType,
270 IN EFI_SECTION_TYPE SectionType,
271 OUT EFI_COMMON_SECTION_HEADER **FoundSection
272 )
273{
274 EFI_STATUS Status;
275 EFI_PHYSICAL_ADDRESS CurrentAddress;
276 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
277 EFI_FFS_FILE_HEADER *File;
278 UINT32 Size;
279 EFI_PHYSICAL_ADDRESS EndOfFile;
280
281 if (Fv->Signature != EFI_FVH_SIGNATURE) {
282 DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));
283 return EFI_VOLUME_CORRUPTED;
284 }
285
286 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv;
287 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
288
289 //
290 // Loop through the FFS files in the Boot Firmware Volume
291 //
292 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
293 CurrentAddress = (EndOfFile + 7) & ~(7ULL);
294 if (CurrentAddress > EndOfFirmwareVolume) {
295 return EFI_VOLUME_CORRUPTED;
296 }
297
298 File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
299 Size = FFS_FILE_SIZE (File);
300 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
301 return EFI_VOLUME_CORRUPTED;
302 }
303
304 EndOfFile = CurrentAddress + Size;
305 if (EndOfFile > EndOfFirmwareVolume) {
306 return EFI_VOLUME_CORRUPTED;
307 }
308
309 //
310 // Look for the request file type
311 //
312 if (File->Type != FileType) {
313 continue;
314 }
315
316 Status = FindFfsSectionInSections (
317 (VOID *)(File + 1),
318 (UINTN)EndOfFile - (UINTN)(File + 1),
319 SectionType,
320 FoundSection
321 );
322 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) {
323 return Status;
324 }
325 }
326}
327
328/**
329 Locates the compressed main firmware volume and decompresses it.
330
331 @param[in,out] Fv On input, the firmware volume to search
332 On output, the decompressed BOOT/PEI FV
333
334 @retval EFI_SUCCESS The file and section was found
335 @retval EFI_NOT_FOUND The file and section was not found
336 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
337
338**/
339EFI_STATUS
340DecompressMemFvs (
341 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv
342 )
343{
344 EFI_STATUS Status;
345 EFI_GUID_DEFINED_SECTION *Section;
346 UINT32 OutputBufferSize;
347 UINT32 ScratchBufferSize;
348 UINT16 SectionAttribute;
349 UINT32 AuthenticationStatus;
350 VOID *OutputBuffer;
351 VOID *ScratchBuffer;
352 EFI_COMMON_SECTION_HEADER *FvSection;
353 EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv;
354 EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv;
355 UINT32 FvHeaderSize;
356 UINT32 FvSectionSize;
357
358 FvSection = (EFI_COMMON_SECTION_HEADER *)NULL;
359
360 Status = FindFfsFileAndSection (
361 *Fv,
362 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
363 EFI_SECTION_GUID_DEFINED,
364 (EFI_COMMON_SECTION_HEADER **)&Section
365 );
366 if (EFI_ERROR (Status)) {
367 DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n"));
368 return Status;
369 }
370
371 Status = ExtractGuidedSectionGetInfo (
372 Section,
373 &OutputBufferSize,
374 &ScratchBufferSize,
375 &SectionAttribute
376 );
377 if (EFI_ERROR (Status)) {
378 DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n"));
379 return Status;
380 }
381
382 OutputBuffer = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB);
383 ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB);
384
385 DEBUG ((
386 DEBUG_VERBOSE,
387 "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x "
388 "PcdOvmfDecompressionScratchEnd=0x%x\n",
389 __func__,
390 OutputBuffer,
391 OutputBufferSize,
392 ScratchBuffer,
393 ScratchBufferSize,
394 PcdGet32 (PcdOvmfDecompressionScratchEnd)
395 ));
396 ASSERT (
397 (UINTN)ScratchBuffer + ScratchBufferSize ==
398 PcdGet32 (PcdOvmfDecompressionScratchEnd)
399 );
400
401 Status = ExtractGuidedSectionDecode (
402 Section,
403 &OutputBuffer,
404 ScratchBuffer,
405 &AuthenticationStatus
406 );
407 if (EFI_ERROR (Status)) {
408 DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n"));
409 return Status;
410 }
411
412 Status = FindFfsSectionInstance (
413 OutputBuffer,
414 OutputBufferSize,
415 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
416 0,
417 &FvSection
418 );
419 if (EFI_ERROR (Status)) {
420 DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n"));
421 return Status;
422 }
423
424 ASSERT (
425 SECTION_SIZE (FvSection) ==
426 (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection))
427 );
428 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
429
430 PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase);
431 CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize));
432
433 if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
434 DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
435 CpuDeadLoop ();
436 return EFI_VOLUME_CORRUPTED;
437 }
438
439 Status = FindFfsSectionInstance (
440 OutputBuffer,
441 OutputBufferSize,
442 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
443 1,
444 &FvSection
445 );
446 if (EFI_ERROR (Status)) {
447 DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n"));
448 return Status;
449 }
450
451 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
452
453 if (IS_SECTION2 (FvSection)) {
454 FvSectionSize = SECTION2_SIZE (FvSection);
455 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);
456 } else {
457 FvSectionSize = SECTION_SIZE (FvSection);
458 FvHeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
459 }
460
461 ASSERT (FvSectionSize == (PcdGet32 (PcdOvmfDxeMemFvSize) + FvHeaderSize));
462
463 DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfDxeMemFvBase);
464 CopyMem (DxeMemFv, (VOID *)((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdOvmfDxeMemFvSize));
465
466 if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
467 DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
468 CpuDeadLoop ();
469 return EFI_VOLUME_CORRUPTED;
470 }
471
472 *Fv = PeiMemFv;
473 return EFI_SUCCESS;
474}
475
476/**
477 Locates the PEI Core entry point address
478
479 @param[in] Fv The firmware volume to search
480 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
481
482 @retval EFI_SUCCESS The file and section was found
483 @retval EFI_NOT_FOUND The file and section was not found
484 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
485
486**/
487EFI_STATUS
488FindPeiCoreImageBaseInFv (
489 IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
490 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
491 )
492{
493 EFI_STATUS Status;
494 EFI_COMMON_SECTION_HEADER *Section;
495
496 Status = FindFfsFileAndSection (
497 Fv,
498 EFI_FV_FILETYPE_PEI_CORE,
499 EFI_SECTION_PE32,
500 &Section
501 );
502 if (EFI_ERROR (Status)) {
503 Status = FindFfsFileAndSection (
504 Fv,
505 EFI_FV_FILETYPE_PEI_CORE,
506 EFI_SECTION_TE,
507 &Section
508 );
509 if (EFI_ERROR (Status)) {
510 DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));
511 return Status;
512 }
513 }
514
515 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
516 return EFI_SUCCESS;
517}
518
519/**
520 Reads 8-bits of CMOS data.
521
522 Reads the 8-bits of CMOS data at the location specified by Index.
523 The 8-bit read value is returned.
524
525 @param Index The CMOS location to read.
526
527 @return The value read.
528
529**/
530STATIC
531UINT8
532CmosRead8 (
533 IN UINTN Index
534 )
535{
536 IoWrite8 (0x70, (UINT8)Index);
537 return IoRead8 (0x71);
538}
539
540STATIC
541BOOLEAN
542IsS3Resume (
543 VOID
544 )
545{
546 return (CmosRead8 (0xF) == 0xFE);
547}
548
549STATIC
550EFI_STATUS
551GetS3ResumePeiFv (
552 IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv
553 )
554{
555 *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdOvmfPeiMemFvBase);
556 return EFI_SUCCESS;
557}
558
559/**
560 Locates the PEI Core entry point address
561
562 @param[in,out] Fv The firmware volume to search
563 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
564
565 @retval EFI_SUCCESS The file and section was found
566 @retval EFI_NOT_FOUND The file and section was not found
567 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
568
569**/
570VOID
571FindPeiCoreImageBase (
572 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv,
573 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
574 )
575{
576 BOOLEAN S3Resume;
577
578 *PeiCoreImageBase = 0;
579
580 S3Resume = IsS3Resume ();
581 if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) {
582 //
583 // A malicious runtime OS may have injected something into our previously
584 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required.
585 //
586 DEBUG ((DEBUG_VERBOSE, "SEC: S3 resume\n"));
587 GetS3ResumePeiFv (BootFv);
588 } else {
589 //
590 // We're either not resuming, or resuming "securely" -- we'll decompress
591 // both PEI FV and DXE FV from pristine flash.
592 //
593 DEBUG ((
594 DEBUG_VERBOSE,
595 "SEC: %a\n",
596 S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot"
597 ));
598 FindMainFv (BootFv);
599
600 DecompressMemFvs (BootFv);
601 }
602
603 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
604}
605
606/**
607 Find core image base.
608
609**/
610EFI_STATUS
611FindImageBase (
612 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
613 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase
614 )
615{
616 EFI_PHYSICAL_ADDRESS CurrentAddress;
617 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
618 EFI_FFS_FILE_HEADER *File;
619 UINT32 Size;
620 EFI_PHYSICAL_ADDRESS EndOfFile;
621 EFI_COMMON_SECTION_HEADER *Section;
622 EFI_PHYSICAL_ADDRESS EndOfSection;
623
624 *SecCoreImageBase = 0;
625
626 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr;
627 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
628
629 //
630 // Loop through the FFS files in the Boot Firmware Volume
631 //
632 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
633 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
634 if (CurrentAddress > EndOfFirmwareVolume) {
635 return EFI_NOT_FOUND;
636 }
637
638 File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
639 Size = FFS_FILE_SIZE (File);
640 if (Size < sizeof (*File)) {
641 return EFI_NOT_FOUND;
642 }
643
644 EndOfFile = CurrentAddress + Size;
645 if (EndOfFile > EndOfFirmwareVolume) {
646 return EFI_NOT_FOUND;
647 }
648
649 //
650 // Look for SEC Core
651 //
652 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
653 continue;
654 }
655
656 //
657 // Loop through the FFS file sections within the FFS file
658 //
659 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1);
660 for ( ; ;) {
661 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
662 Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
663
664 Size = SECTION_SIZE (Section);
665 if (Size < sizeof (*Section)) {
666 return EFI_NOT_FOUND;
667 }
668
669 EndOfSection = CurrentAddress + Size;
670 if (EndOfSection > EndOfFile) {
671 return EFI_NOT_FOUND;
672 }
673
674 //
675 // Look for executable sections
676 //
677 if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
678 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
679 *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1);
680 }
681
682 break;
683 }
684 }
685
686 //
687 // SEC Core image found
688 //
689 if (*SecCoreImageBase != 0) {
690 return EFI_SUCCESS;
691 }
692 }
693}
694
695/*
696 Find and return Pei Core entry point.
697
698 It also find SEC and PEI Core file debug information. It will report them if
699 remote debug is enabled.
700
701**/
702VOID
703FindAndReportEntryPoints (
704 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
705 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
706 )
707{
708 EFI_STATUS Status;
709 EFI_PHYSICAL_ADDRESS SecCoreImageBase;
710 EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
711 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
712
713 //
714 // Find SEC Core and PEI Core image base
715 //
716 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
717 ASSERT_EFI_ERROR (Status);
718
719 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
720
721 ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
722 //
723 // Report SEC Core debug information when remote debug is enabled
724 //
725 ImageContext.ImageAddress = SecCoreImageBase;
726 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
727 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
728
729 //
730 // Report PEI Core debug information when remote debug is enabled
731 //
732 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
733 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
734 PeCoffLoaderRelocateImageExtraAction (&ImageContext);
735
736 //
737 // Find PEI Core entry point
738 //
739 Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID **)PeiCoreEntryPoint);
740 if (EFI_ERROR (Status)) {
741 *PeiCoreEntryPoint = 0;
742 }
743
744 return;
745}
746
747VOID
748EFIAPI
749SecCoreStartupWithStack (
750 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
751 IN VOID *TopOfCurrentStack
752 )
753{
754 EFI_SEC_PEI_HAND_OFF SecCoreData;
755 SEC_IDT_TABLE IdtTableInStack;
756 IA32_DESCRIPTOR IdtDescriptor;
757 UINT32 Index;
758 volatile UINT8 *Table;
759
760 #if defined (TDX_GUEST_SUPPORTED)
761 if (CcProbe () == CcGuestTypeIntelTdx) {
762 //
763 // From the security perspective all the external input should be measured before
764 // it is consumed. TdHob and Configuration FV (Cfv) image are passed from VMM
765 // and should be measured here.
766 //
767 if (EFI_ERROR (TdxHelperMeasureTdHob ())) {
768 CpuDeadLoop ();
769 }
770
771 if (EFI_ERROR (TdxHelperMeasureCfvImage ())) {
772 CpuDeadLoop ();
773 }
774
775 //
776 // For Td guests, the memory map info is in TdHobLib. It should be processed
777 // first so that the memory is accepted. Otherwise access to the unaccepted
778 // memory will trigger tripple fault.
779 //
780 if (TdxHelperProcessTdHob () != EFI_SUCCESS) {
781 CpuDeadLoop ();
782 }
783 }
784
785 #endif
786
787 //
788 // To ensure SMM can't be compromised on S3 resume, we must force re-init of
789 // the BaseExtractGuidedSectionLib. Since this is before library contructors
790 // are called, we must use a loop rather than SetMem.
791 //
792 Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
793 for (Index = 0;
794 Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
795 ++Index)
796 {
797 Table[Index] = 0;
798 }
799
800 //
801 // Initialize IDT - Since this is before library constructors are called,
802 // we use a loop rather than CopyMem.
803 //
804 IdtTableInStack.PeiService = NULL;
805
806 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {
807 //
808 // Declare the local variables that actually move the data elements as
809 // volatile to prevent the optimizer from replacing this function with
810 // the intrinsic memcpy()
811 //
812 CONST UINT8 *Src;
813 volatile UINT8 *Dst;
814 UINTN Byte;
815
816 Src = (CONST UINT8 *)&mIdtEntryTemplate;
817 Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];
818 for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {
819 Dst[Byte] = Src[Byte];
820 }
821 }
822
823 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
824 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
825
826 if (SevEsIsEnabled ()) {
827 SevEsProtocolCheck ();
828
829 //
830 // For SEV-ES guests, the exception handler is needed before calling
831 // ProcessLibraryConstructorList() because some of the library constructors
832 // perform some functions that result in #VC exceptions being generated.
833 //
834 // Due to this code executing before library constructors, *all* library
835 // API calls are theoretically interface contract violations. However,
836 // because this is SEC (executing in flash), those constructors cannot
837 // write variables with static storage duration anyway. Furthermore, only
838 // a small, restricted set of APIs, such as AsmWriteIdtr() and
839 // InitializeCpuExceptionHandlers(), are called, where we require that the
840 // underlying library not require constructors to have been invoked and
841 // that the library instance not trigger any #VC exceptions.
842 //
843 AsmWriteIdtr (&IdtDescriptor);
844 InitializeCpuExceptionHandlers (NULL);
845 }
846
847 ProcessLibraryConstructorList (NULL, NULL);
848
849 if (!SevEsIsEnabled ()) {
850 //
851 // For non SEV-ES guests, just load the IDTR.
852 //
853 AsmWriteIdtr (&IdtDescriptor);
854 } else {
855 //
856 // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable
857 // caching in order to speed up the boot. Enable caching early for
858 // an SEV-ES guest.
859 //
860 AsmEnableCache ();
861 }
862
863 #if defined (TDX_GUEST_SUPPORTED)
864 if (CcProbe () == CcGuestTypeIntelTdx) {
865 //
866 // InitializeCpuExceptionHandlers () should be called in Td guests so that
867 // #VE exceptions can be handled correctly.
868 //
869 InitializeCpuExceptionHandlers (NULL);
870 }
871
872 #endif
873
874 DEBUG ((
875 DEBUG_INFO,
876 "SecCoreStartupWithStack(0x%x, 0x%x)\n",
877 (UINT32)(UINTN)BootFv,
878 (UINT32)(UINTN)TopOfCurrentStack
879 ));
880
881 //
882 // Initialize floating point operating environment
883 // to be compliant with UEFI spec.
884 //
885 InitializeFloatingPointUnits ();
886
887 #if defined (MDE_CPU_X64)
888 //
889 // ASSERT that the Page Tables were set by the reset vector code to
890 // the address we expect.
891 //
892 ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));
893 #endif
894
895 //
896 // |-------------| <-- TopOfCurrentStack
897 // | Stack | 32k
898 // |-------------|
899 // | Heap | 32k
900 // |-------------| <-- SecCoreData.TemporaryRamBase
901 //
902
903 ASSERT (
904 (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +
905 PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
906 (UINTN)TopOfCurrentStack
907 );
908
909 //
910 // Initialize SEC hand-off state
911 //
912 SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
913
914 SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);
915 SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
916
917 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
918 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
919
920 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
921 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
922
923 SecCoreData.BootFirmwareVolumeBase = BootFv;
924 SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
925
926 //
927 // Validate the System RAM used in the SEC Phase
928 //
929 SecValidateSystemRam ();
930
931 //
932 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
933 //
934 IoWrite8 (0x21, 0xff);
935 IoWrite8 (0xA1, 0xff);
936
937 //
938 // Initialize Local APIC Timer hardware and disable Local APIC Timer
939 // interrupts before initializing the Debug Agent and the debug timer is
940 // enabled.
941 //
942 InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
943 DisableApicTimerInterrupt ();
944
945 //
946 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
947 //
948 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
949}
950
951/**
952 Caller provided function to be invoked at the end of InitializeDebugAgent().
953
954 Entry point to the C language phase of SEC. After the SEC assembly
955 code has initialized some temporary memory and set up the stack,
956 the control is transferred to this function.
957
958 @param[in] Context The first input parameter of InitializeDebugAgent().
959
960**/
961VOID
962EFIAPI
963SecStartupPhase2 (
964 IN VOID *Context
965 )
966{
967 EFI_SEC_PEI_HAND_OFF *SecCoreData;
968 EFI_FIRMWARE_VOLUME_HEADER *BootFv;
969 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
970 EFI_PEI_PPI_DESCRIPTOR *EfiPeiPpiDescriptor;
971
972 SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;
973
974 //
975 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
976 // is enabled.
977 //
978 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
979 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
980 SecCoreData->BootFirmwareVolumeBase = BootFv;
981 SecCoreData->BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
982
983 //
984 // Td guest is required to use the MpInitLibUp (unique-processor version).
985 // Other guests use the MpInitLib (multi-processor version).
986 //
987 if (CcProbe () == CcGuestTypeIntelTdx) {
988 EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableUp;
989 } else {
990 EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableMp;
991 }
992
993 //
994 // Transfer the control to the PEI core
995 //
996 (*PeiCoreEntryPoint)(SecCoreData, EfiPeiPpiDescriptor);
997
998 //
999 // If we get here then the PEI Core returned, which is not recoverable.
1000 //
1001 ASSERT (FALSE);
1002 CpuDeadLoop ();
1003}
1004
1005EFI_STATUS
1006EFIAPI
1007TemporaryRamMigration (
1008 IN CONST EFI_PEI_SERVICES **PeiServices,
1009 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
1010 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
1011 IN UINTN CopySize
1012 )
1013{
1014 IA32_DESCRIPTOR IdtDescriptor;
1015 VOID *OldHeap;
1016 VOID *NewHeap;
1017 VOID *OldStack;
1018 VOID *NewStack;
1019 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
1020 BOOLEAN OldStatus;
1021 BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
1022
1023 DEBUG ((
1024 DEBUG_INFO,
1025 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
1026 TemporaryMemoryBase,
1027 PermanentMemoryBase,
1028 (UINT64)CopySize
1029 ));
1030
1031 OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
1032 NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));
1033
1034 OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
1035 NewStack = (VOID *)(UINTN)PermanentMemoryBase;
1036
1037 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
1038 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
1039
1040 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
1041 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *)&DebugAgentContext, NULL);
1042
1043 //
1044 // Migrate Heap
1045 //
1046 CopyMem (NewHeap, OldHeap, CopySize >> 1);
1047
1048 //
1049 // Migrate Stack
1050 //
1051 CopyMem (NewStack, OldStack, CopySize >> 1);
1052
1053 //
1054 // Rebase IDT table in permanent memory
1055 //
1056 AsmReadIdtr (&IdtDescriptor);
1057 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
1058
1059 AsmWriteIdtr (&IdtDescriptor);
1060
1061 //
1062 // Use SetJump()/LongJump() to switch to a new stack.
1063 //
1064 if (SetJump (&JumpBuffer) == 0) {
1065 #if defined (MDE_CPU_IA32)
1066 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
1067 JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;
1068 #endif
1069 #if defined (MDE_CPU_X64)
1070 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
1071 JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;
1072 #endif
1073 LongJump (&JumpBuffer, (UINTN)-1);
1074 }
1075
1076 SaveAndSetDebugTimerInterrupt (OldStatus);
1077
1078 return EFI_SUCCESS;
1079}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette