DxeIpl.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /** @file
  2. Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include "DxeIpl.h"
  6. //
  7. // Module Globals used in the DXE to PEI hand off
  8. // These must be module globals, so the stack can be switched
  9. //
  10. CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
  11. DxeLoadCore
  12. };
  13. CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
  14. CustomGuidedSectionExtract
  15. };
  16. CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
  17. Decompress
  18. };
  19. CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
  20. {
  21. EFI_PEI_PPI_DESCRIPTOR_PPI,
  22. &gEfiDxeIplPpiGuid,
  23. (VOID *) &mDxeIplPpi
  24. },
  25. {
  26. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  27. &gEfiPeiDecompressPpiGuid,
  28. (VOID *) &mDecompressPpi
  29. }
  30. };
  31. CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
  32. (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
  33. &gEfiEndOfPeiSignalPpiGuid,
  34. NULL
  35. };
  36. /**
  37. Entry point of DXE IPL PEIM.
  38. This function installs DXE IPL PPI and Decompress PPI. It also reloads
  39. itself to memory on non-S3 resume boot path.
  40. @param[in] FileHandle Handle of the file being invoked.
  41. @param[in] PeiServices Describes the list of possible PEI Services.
  42. @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
  43. @retval Others Some error occurs during the execution of this function.
  44. **/
  45. EFI_STATUS
  46. EFIAPI
  47. PeimInitializeDxeIpl (
  48. IN EFI_PEI_FILE_HANDLE FileHandle,
  49. IN CONST EFI_PEI_SERVICES **PeiServices
  50. )
  51. {
  52. EFI_STATUS Status;
  53. EFI_GUID *ExtractHandlerGuidTable;
  54. UINTN ExtractHandlerNumber;
  55. EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
  56. //
  57. // Get custom extract guided section method guid list
  58. //
  59. ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
  60. //
  61. // Install custom extraction guid PPI
  62. //
  63. if (ExtractHandlerNumber > 0) {
  64. GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
  65. ASSERT (GuidPpi != NULL);
  66. while (ExtractHandlerNumber-- > 0) {
  67. GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
  68. GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;
  69. GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
  70. Status = PeiServicesInstallPpi (GuidPpi++);
  71. ASSERT_EFI_ERROR(Status);
  72. }
  73. }
  74. //
  75. // Install DxeIpl and Decompress PPIs.
  76. //
  77. Status = PeiServicesInstallPpi (mPpiList);
  78. ASSERT_EFI_ERROR(Status);
  79. return Status;
  80. }
  81. /**
  82. The ExtractSection() function processes the input section and
  83. returns a pointer to the section contents. If the section being
  84. extracted does not require processing (if the section
  85. GuidedSectionHeader.Attributes has the
  86. EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
  87. OutputBuffer is just updated to point to the start of the
  88. section's contents. Otherwise, *Buffer must be allocated
  89. from PEI permanent memory.
  90. @param[in] This Indicates the
  91. EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
  92. Buffer containing the input GUIDed section to be
  93. processed. OutputBuffer OutputBuffer is
  94. allocated from PEI permanent memory and contains
  95. the new section stream.
  96. @param[in] InputSection A pointer to the input buffer, which contains
  97. the input section to be processed.
  98. @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose
  99. size is specified by the contents of OutputSize.
  100. @param[out] OutputSize A pointer to a caller-allocated
  101. UINTN in which the size of *OutputBuffer
  102. allocation is stored. If the function
  103. returns anything other than EFI_SUCCESS,
  104. the value of OutputSize is undefined.
  105. @param[out] AuthenticationStatus A pointer to a caller-allocated
  106. UINT32 that indicates the
  107. authentication status of the
  108. output buffer. If the input
  109. section's GuidedSectionHeader.
  110. Attributes field has the
  111. EFI_GUIDED_SECTION_AUTH_STATUS_VALID
  112. bit as clear,
  113. AuthenticationStatus must return
  114. zero. These bits reflect the
  115. status of the extraction
  116. operation. If the function
  117. returns anything other than
  118. EFI_SUCCESS, the value of
  119. AuthenticationStatus is
  120. undefined.
  121. @retval EFI_SUCCESS The InputSection was
  122. successfully processed and the
  123. section contents were returned.
  124. @retval EFI_OUT_OF_RESOURCES The system has insufficient
  125. resources to process the request.
  126. @retval EFI_INVALID_PARAMETER The GUID in InputSection does
  127. not match this instance of the
  128. GUIDed Section Extraction PPI.
  129. **/
  130. EFI_STATUS
  131. EFIAPI
  132. CustomGuidedSectionExtract (
  133. IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
  134. IN CONST VOID *InputSection,
  135. OUT VOID **OutputBuffer,
  136. OUT UINTN *OutputSize,
  137. OUT UINT32 *AuthenticationStatus
  138. )
  139. {
  140. EFI_STATUS Status;
  141. UINT8 *ScratchBuffer;
  142. UINT32 ScratchBufferSize;
  143. UINT32 OutputBufferSize;
  144. UINT16 SectionAttribute;
  145. //
  146. // Init local variable
  147. //
  148. ScratchBuffer = NULL;
  149. //
  150. // Call GetInfo to get the size and attribute of input guided section data.
  151. //
  152. Status = ExtractGuidedSectionGetInfo (
  153. InputSection,
  154. &OutputBufferSize,
  155. &ScratchBufferSize,
  156. &SectionAttribute
  157. );
  158. if (EFI_ERROR (Status)) {
  159. DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
  160. return Status;
  161. }
  162. if (ScratchBufferSize != 0) {
  163. //
  164. // Allocate scratch buffer
  165. //
  166. ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
  167. if (ScratchBuffer == NULL) {
  168. return EFI_OUT_OF_RESOURCES;
  169. }
  170. }
  171. if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
  172. //
  173. // Allocate output buffer
  174. //
  175. *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
  176. if (*OutputBuffer == NULL) {
  177. return EFI_OUT_OF_RESOURCES;
  178. }
  179. DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
  180. //
  181. // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
  182. // skip EFI section header to make section data at page alignment.
  183. //
  184. *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
  185. }
  186. Status = ExtractGuidedSectionDecode (
  187. InputSection,
  188. OutputBuffer,
  189. ScratchBuffer,
  190. AuthenticationStatus
  191. );
  192. if (EFI_ERROR (Status)) {
  193. //
  194. // Decode failed
  195. //
  196. DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
  197. return Status;
  198. }
  199. *OutputSize = (UINTN) OutputBufferSize;
  200. return EFI_SUCCESS;
  201. }
  202. /**
  203. Decompresses a section to the output buffer.
  204. This function looks up the compression type field in the input section and
  205. applies the appropriate compression algorithm to compress the section to a
  206. callee allocated buffer.
  207. @param[in] This Points to this instance of the
  208. EFI_PEI_DECOMPRESS_PEI PPI.
  209. @param[in] CompressionSection Points to the compressed section.
  210. @param[out] OutputBuffer Holds the returned pointer to the decompressed
  211. sections.
  212. @param[out] OutputSize Holds the returned size of the decompress
  213. section streams.
  214. @retval EFI_SUCCESS The section was decompressed successfully.
  215. OutputBuffer contains the resulting data and
  216. OutputSize contains the resulting size.
  217. **/
  218. EFI_STATUS
  219. EFIAPI
  220. Decompress (
  221. IN CONST EFI_PEI_DECOMPRESS_PPI *This,
  222. IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
  223. OUT VOID **OutputBuffer,
  224. OUT UINTN *OutputSize
  225. )
  226. {
  227. EFI_STATUS Status;
  228. UINT8 *DstBuffer;
  229. UINT8 *ScratchBuffer;
  230. UINT32 DstBufferSize;
  231. UINT32 ScratchBufferSize;
  232. VOID *CompressionSource;
  233. UINT32 CompressionSourceSize;
  234. UINT32 UncompressedLength;
  235. UINT8 CompressionType;
  236. if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
  237. ASSERT (FALSE);
  238. return EFI_INVALID_PARAMETER;
  239. }
  240. if (IS_SECTION2 (CompressionSection)) {
  241. CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));
  242. CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));
  243. UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;
  244. CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;
  245. } else {
  246. CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));
  247. CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));
  248. UncompressedLength = CompressionSection->UncompressedLength;
  249. CompressionType = CompressionSection->CompressionType;
  250. }
  251. //
  252. // This is a compression set, expand it
  253. //
  254. switch (CompressionType) {
  255. case EFI_STANDARD_COMPRESSION:
  256. //
  257. // Load EFI standard compression.
  258. // For compressed data, decompress them to destination buffer.
  259. //
  260. Status = UefiDecompressGetInfo (
  261. CompressionSource,
  262. CompressionSourceSize,
  263. &DstBufferSize,
  264. &ScratchBufferSize
  265. );
  266. if (EFI_ERROR (Status)) {
  267. //
  268. // GetInfo failed
  269. //
  270. DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
  271. return EFI_NOT_FOUND;
  272. }
  273. //
  274. // Allocate scratch buffer
  275. //
  276. ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
  277. if (ScratchBuffer == NULL) {
  278. return EFI_OUT_OF_RESOURCES;
  279. }
  280. //
  281. // Allocate destination buffer, extra one page for adjustment
  282. //
  283. DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
  284. if (DstBuffer == NULL) {
  285. return EFI_OUT_OF_RESOURCES;
  286. }
  287. //
  288. // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
  289. // to make section data at page alignment.
  290. //
  291. DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
  292. //
  293. // Call decompress function
  294. //
  295. Status = UefiDecompress (
  296. CompressionSource,
  297. DstBuffer,
  298. ScratchBuffer
  299. );
  300. if (EFI_ERROR (Status)) {
  301. //
  302. // Decompress failed
  303. //
  304. DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
  305. return EFI_NOT_FOUND;
  306. }
  307. break;
  308. case EFI_NOT_COMPRESSED:
  309. //
  310. // Allocate destination buffer
  311. //
  312. DstBufferSize = UncompressedLength;
  313. DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
  314. if (DstBuffer == NULL) {
  315. return EFI_OUT_OF_RESOURCES;
  316. }
  317. //
  318. // Adjust DstBuffer offset, skip EFI section header
  319. // to make section data at page alignment.
  320. //
  321. DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
  322. //
  323. // stream is not actually compressed, just encapsulated. So just copy it.
  324. //
  325. CopyMem (DstBuffer, CompressionSource, DstBufferSize);
  326. break;
  327. default:
  328. //
  329. // Don't support other unknown compression type.
  330. //
  331. ASSERT (FALSE);
  332. return EFI_NOT_FOUND;
  333. }
  334. *OutputSize = DstBufferSize;
  335. *OutputBuffer = DstBuffer;
  336. return EFI_SUCCESS;
  337. }
  338. /**
  339. Main entry point to last PEIM.
  340. This function finds DXE Core in the firmware volume and transfer the control to
  341. DXE core.
  342. @param[in] This Entry point for DXE IPL PPI.
  343. @param[in] PeiServices General purpose services available to every PEIM.
  344. @param[in] HobList Address to the Pei HOB list.
  345. @return EFI_SUCCESS DXE core was successfully loaded.
  346. @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
  347. **/
  348. EFI_STATUS
  349. EFIAPI
  350. DxeLoadCore (
  351. IN CONST EFI_DXE_IPL_PPI *This,
  352. IN EFI_PEI_SERVICES **PeiServices,
  353. IN EFI_PEI_HOB_POINTERS HobList
  354. )
  355. {
  356. EFI_STATUS Status;
  357. DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));
  358. //
  359. // End of PEI phase signal
  360. //
  361. Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
  362. ASSERT_EFI_ERROR (Status);
  363. //
  364. // Give control back to BootLoader after FspInit
  365. //
  366. DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));
  367. FspInitDone ();
  368. //
  369. // BootLoader called FSP again through NotifyPhase
  370. //
  371. FspWaitForNotify ();
  372. //
  373. // Give control back to the boot loader framework caller
  374. //
  375. DEBUG ((DEBUG_INFO | DEBUG_INIT, "============= PEIM FSP is Completed =============\n\n"));
  376. SetFspApiReturnStatus(EFI_SUCCESS);
  377. SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT);
  378. Pei2LoaderSwitchStack();
  379. //
  380. // Should not come here
  381. //
  382. while (TRUE) {
  383. DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));
  384. SetFspApiReturnStatus(EFI_UNSUPPORTED);
  385. Pei2LoaderSwitchStack();
  386. }
  387. return EFI_SUCCESS;
  388. }