SecMain.c 31 KB

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