SecMain.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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/PlatformInitLib.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. // For Td guests, the memory map info is in TdHobLib. It should be processed
  649. // first so that the memory is accepted. Otherwise access to the unaccepted
  650. // memory will trigger tripple fault.
  651. //
  652. if (ProcessTdxHobList () != EFI_SUCCESS) {
  653. CpuDeadLoop ();
  654. }
  655. }
  656. #endif
  657. //
  658. // To ensure SMM can't be compromised on S3 resume, we must force re-init of
  659. // the BaseExtractGuidedSectionLib. Since this is before library contructors
  660. // are called, we must use a loop rather than SetMem.
  661. //
  662. Table = (UINT8 *)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress);
  663. for (Index = 0;
  664. Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize);
  665. ++Index)
  666. {
  667. Table[Index] = 0;
  668. }
  669. //
  670. // Initialize IDT - Since this is before library constructors are called,
  671. // we use a loop rather than CopyMem.
  672. //
  673. IdtTableInStack.PeiService = NULL;
  674. for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {
  675. //
  676. // Declare the local variables that actually move the data elements as
  677. // volatile to prevent the optimizer from replacing this function with
  678. // the intrinsic memcpy()
  679. //
  680. CONST UINT8 *Src;
  681. volatile UINT8 *Dst;
  682. UINTN Byte;
  683. Src = (CONST UINT8 *)&mIdtEntryTemplate;
  684. Dst = (volatile UINT8 *)&IdtTableInStack.IdtTable[Index];
  685. for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {
  686. Dst[Byte] = Src[Byte];
  687. }
  688. }
  689. IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
  690. IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
  691. if (SevEsIsEnabled ()) {
  692. SevEsProtocolCheck ();
  693. //
  694. // For SEV-ES guests, the exception handler is needed before calling
  695. // ProcessLibraryConstructorList() because some of the library constructors
  696. // perform some functions that result in #VC exceptions being generated.
  697. //
  698. // Due to this code executing before library constructors, *all* library
  699. // API calls are theoretically interface contract violations. However,
  700. // because this is SEC (executing in flash), those constructors cannot
  701. // write variables with static storage duration anyway. Furthermore, only
  702. // a small, restricted set of APIs, such as AsmWriteIdtr() and
  703. // InitializeCpuExceptionHandlers(), are called, where we require that the
  704. // underlying library not require constructors to have been invoked and
  705. // that the library instance not trigger any #VC exceptions.
  706. //
  707. AsmWriteIdtr (&IdtDescriptor);
  708. InitializeCpuExceptionHandlers (NULL);
  709. }
  710. ProcessLibraryConstructorList (NULL, NULL);
  711. if (!SevEsIsEnabled ()) {
  712. //
  713. // For non SEV-ES guests, just load the IDTR.
  714. //
  715. AsmWriteIdtr (&IdtDescriptor);
  716. } else {
  717. //
  718. // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable
  719. // caching in order to speed up the boot. Enable caching early for
  720. // an SEV-ES guest.
  721. //
  722. AsmEnableCache ();
  723. }
  724. #if defined (TDX_GUEST_SUPPORTED)
  725. if (CcProbe () == CcGuestTypeIntelTdx) {
  726. //
  727. // InitializeCpuExceptionHandlers () should be called in Td guests so that
  728. // #VE exceptions can be handled correctly.
  729. //
  730. InitializeCpuExceptionHandlers (NULL);
  731. }
  732. #endif
  733. DEBUG ((
  734. DEBUG_INFO,
  735. "SecCoreStartupWithStack(0x%x, 0x%x)\n",
  736. (UINT32)(UINTN)BootFv,
  737. (UINT32)(UINTN)TopOfCurrentStack
  738. ));
  739. //
  740. // Initialize floating point operating environment
  741. // to be compliant with UEFI spec.
  742. //
  743. InitializeFloatingPointUnits ();
  744. #if defined (MDE_CPU_X64)
  745. //
  746. // ASSERT that the Page Tables were set by the reset vector code to
  747. // the address we expect.
  748. //
  749. ASSERT (AsmReadCr3 () == (UINTN)PcdGet32 (PcdOvmfSecPageTablesBase));
  750. #endif
  751. //
  752. // |-------------| <-- TopOfCurrentStack
  753. // | Stack | 32k
  754. // |-------------|
  755. // | Heap | 32k
  756. // |-------------| <-- SecCoreData.TemporaryRamBase
  757. //
  758. ASSERT (
  759. (UINTN)(PcdGet32 (PcdOvmfSecPeiTempRamBase) +
  760. PcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
  761. (UINTN)TopOfCurrentStack
  762. );
  763. //
  764. // Initialize SEC hand-off state
  765. //
  766. SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
  767. SecCoreData.TemporaryRamSize = (UINTN)PcdGet32 (PcdOvmfSecPeiTempRamSize);
  768. SecCoreData.TemporaryRamBase = (VOID *)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize);
  769. SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
  770. SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
  771. SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize;
  772. SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
  773. SecCoreData.BootFirmwareVolumeBase = BootFv;
  774. SecCoreData.BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
  775. //
  776. // Validate the System RAM used in the SEC Phase
  777. //
  778. SecValidateSystemRam ();
  779. //
  780. // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled
  781. //
  782. IoWrite8 (0x21, 0xff);
  783. IoWrite8 (0xA1, 0xff);
  784. //
  785. // Initialize Local APIC Timer hardware and disable Local APIC Timer
  786. // interrupts before initializing the Debug Agent and the debug timer is
  787. // enabled.
  788. //
  789. InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
  790. DisableApicTimerInterrupt ();
  791. //
  792. // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
  793. //
  794. InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
  795. }
  796. /**
  797. Caller provided function to be invoked at the end of InitializeDebugAgent().
  798. Entry point to the C language phase of SEC. After the SEC assembly
  799. code has initialized some temporary memory and set up the stack,
  800. the control is transferred to this function.
  801. @param[in] Context The first input parameter of InitializeDebugAgent().
  802. **/
  803. VOID
  804. EFIAPI
  805. SecStartupPhase2 (
  806. IN VOID *Context
  807. )
  808. {
  809. EFI_SEC_PEI_HAND_OFF *SecCoreData;
  810. EFI_FIRMWARE_VOLUME_HEADER *BootFv;
  811. EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
  812. EFI_PEI_PPI_DESCRIPTOR *EfiPeiPpiDescriptor;
  813. SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;
  814. //
  815. // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
  816. // is enabled.
  817. //
  818. BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
  819. FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
  820. SecCoreData->BootFirmwareVolumeBase = BootFv;
  821. SecCoreData->BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
  822. //
  823. // Td guest is required to use the MpInitLibUp (unique-processor version).
  824. // Other guests use the MpInitLib (multi-processor version).
  825. //
  826. if (CcProbe () == CcGuestTypeIntelTdx) {
  827. EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableUp;
  828. } else {
  829. EfiPeiPpiDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTableMp;
  830. }
  831. //
  832. // Transfer the control to the PEI core
  833. //
  834. (*PeiCoreEntryPoint)(SecCoreData, EfiPeiPpiDescriptor);
  835. //
  836. // If we get here then the PEI Core returned, which is not recoverable.
  837. //
  838. ASSERT (FALSE);
  839. CpuDeadLoop ();
  840. }
  841. EFI_STATUS
  842. EFIAPI
  843. TemporaryRamMigration (
  844. IN CONST EFI_PEI_SERVICES **PeiServices,
  845. IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
  846. IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
  847. IN UINTN CopySize
  848. )
  849. {
  850. IA32_DESCRIPTOR IdtDescriptor;
  851. VOID *OldHeap;
  852. VOID *NewHeap;
  853. VOID *OldStack;
  854. VOID *NewStack;
  855. DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
  856. BOOLEAN OldStatus;
  857. BASE_LIBRARY_JUMP_BUFFER JumpBuffer;
  858. DEBUG ((
  859. DEBUG_INFO,
  860. "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n",
  861. TemporaryMemoryBase,
  862. PermanentMemoryBase,
  863. (UINT64)CopySize
  864. ));
  865. OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
  866. NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));
  867. OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
  868. NewStack = (VOID *)(UINTN)PermanentMemoryBase;
  869. DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
  870. DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
  871. OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
  872. InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *)&DebugAgentContext, NULL);
  873. //
  874. // Migrate Heap
  875. //
  876. CopyMem (NewHeap, OldHeap, CopySize >> 1);
  877. //
  878. // Migrate Stack
  879. //
  880. CopyMem (NewStack, OldStack, CopySize >> 1);
  881. //
  882. // Rebase IDT table in permanent memory
  883. //
  884. AsmReadIdtr (&IdtDescriptor);
  885. IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
  886. AsmWriteIdtr (&IdtDescriptor);
  887. //
  888. // Use SetJump()/LongJump() to switch to a new stack.
  889. //
  890. if (SetJump (&JumpBuffer) == 0) {
  891. #if defined (MDE_CPU_IA32)
  892. JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset;
  893. JumpBuffer.Ebp = JumpBuffer.Ebp + DebugAgentContext.StackMigrateOffset;
  894. #endif
  895. #if defined (MDE_CPU_X64)
  896. JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset;
  897. JumpBuffer.Rbp = JumpBuffer.Rbp + DebugAgentContext.StackMigrateOffset;
  898. #endif
  899. LongJump (&JumpBuffer, (UINTN)-1);
  900. }
  901. SaveAndSetDebugTimerInterrupt (OldStatus);
  902. return EFI_SUCCESS;
  903. }