SecMain.c 28 KB

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