]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
1. Update IA32 PeiCore implementation to support load x64 image for EFI_PEI_LOAD_FILE...
[mirror_edk2.git] / MdeModulePkg / Core / DxeIplPeim / DxeLoad.c
CommitLineData
96226baa 1/** @file\r
b0d803fe 2 Last PEIM.\r
3 Responsibility of this module is to load the DXE Core from a Firmware Volume.\r
95276127 4\r
6d3ea23f 5Copyright (c) 2006 - 2009, Intel Corporation. <BR>\r
95276127 6All rights reserved. This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
b0d803fe 14**/\r
95276127 15\r
95276127 16#include "DxeIpl.h"\r
b0d803fe 17\r
95276127 18\r
19//\r
48557c65 20// Module Globals used in the DXE to PEI hand off\r
95276127 21// These must be module globals, so the stack can be switched\r
22//\r
9b937a73 23CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
95276127 24 DxeLoadCore\r
25};\r
26\r
9b937a73 27CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
18fd8d65 28 CustomGuidedSectionExtract\r
95276127 29};\r
30\r
9b937a73 31CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
b0d803fe 32 Decompress\r
d8c79a81
LG
33};\r
34\r
48557c65 35CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
95276127 36 {\r
b0d803fe 37 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
38 &gEfiDxeIplPpiGuid,\r
9b937a73 39 (VOID *) &mDxeIplPpi\r
95276127 40 },\r
41 {\r
b0d803fe 42 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
43 &gEfiPeiDecompressPpiGuid,\r
9b937a73 44 (VOID *) &mDecompressPpi\r
95276127 45 }\r
46};\r
47\r
48557c65 48CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {\r
95276127 49 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
50 &gEfiEndOfPeiSignalPpiGuid,\r
51 NULL\r
52};\r
53\r
b0d803fe 54/**\r
48557c65 55 Entry point of DXE IPL PEIM.\r
56 \r
57 This function installs DXE IPL PPI and Decompress PPI. It also reloads\r
58 itself to memory on non-S3 resume boot path.\r
b0d803fe 59\r
a55caa53
LG
60 @param FileHandle Handle of the file being invoked.\r
61 @param PeiServices Describes the list of possible PEI Services.\r
91d92e25 62\r
48557c65 63 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.\r
64 @retval Others Some error occurs during the execution of this function. \r
65\r
91d92e25 66**/\r
95276127 67EFI_STATUS\r
68EFIAPI\r
69PeimInitializeDxeIpl (\r
a55caa53
LG
70 IN EFI_PEI_FILE_HANDLE FileHandle,\r
71 IN CONST EFI_PEI_SERVICES **PeiServices\r
95276127 72 )\r
95276127 73{\r
74 EFI_STATUS Status;\r
95276127 75 EFI_BOOT_MODE BootMode;\r
18fd8d65
LG
76 EFI_GUID *ExtractHandlerGuidTable;\r
77 UINTN ExtractHandlerNumber;\r
d8c79a81
LG
78 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;\r
79 \r
b98da1b1 80 BootMode = GetBootModeHob ();\r
95276127 81\r
b0d803fe 82 if (BootMode != BOOT_ON_S3_RESUME) {\r
a55caa53 83 Status = PeiServicesRegisterForShadow (FileHandle);\r
b0d803fe 84 if (Status == EFI_SUCCESS) {\r
b0d803fe 85 //\r
48557c65 86 // EFI_SUCESS means it is the first time to call register for shadow. \r
b0d803fe 87 // \r
88 return Status;\r
48557c65 89 }\r
90 \r
91 //\r
92 // Ensure that DXE IPL is shadowed to permanent memory.\r
93 //\r
94 ASSERT (Status == EFI_ALREADY_STARTED);\r
b98da1b1 95 \r
48557c65 96 //\r
97 // Get custom extract guided section method guid list \r
98 //\r
99 ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
100 \r
101 //\r
102 // Install custom extraction guid PPI\r
103 //\r
104 if (ExtractHandlerNumber > 0) {\r
105 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
106 ASSERT (GuidPpi != NULL);\r
107 while (ExtractHandlerNumber-- > 0) {\r
108 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
109 GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;\r
110 GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];\r
111 Status = PeiServicesInstallPpi (GuidPpi++);\r
112 ASSERT_EFI_ERROR(Status);\r
b0d803fe 113 }\r
d8c79a81 114 }\r
48557c65 115 \r
95276127 116 }\r
117 \r
b0d803fe 118 //\r
288f9b38 119 // Install DxeIpl and Decompress PPIs.\r
b0d803fe 120 //\r
121 Status = PeiServicesInstallPpi (mPpiList);\r
288f9b38
LG
122 ASSERT_EFI_ERROR(Status);\r
123\r
95276127 124 return Status;\r
125}\r
126\r
b0d803fe 127/**\r
b98da1b1 128 Main entry point to last PEIM. \r
48557c65 129\r
130 This function finds DXE Core in the firmware volume and transfer the control to\r
131 DXE core.\r
b0d803fe 132 \r
b98da1b1 133 @param This Entry point for DXE IPL PPI.\r
b0d803fe 134 @param PeiServices General purpose services available to every PEIM.\r
b98da1b1 135 @param HobList Address to the Pei HOB list.\r
b0d803fe 136 \r
137 @return EFI_SUCCESS DXE core was successfully loaded. \r
138 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.\r
91d92e25 139\r
b0d803fe 140**/\r
95276127 141EFI_STATUS\r
142EFIAPI\r
143DxeLoadCore (\r
1f3a753e 144 IN CONST EFI_DXE_IPL_PPI *This,\r
95276127 145 IN EFI_PEI_SERVICES **PeiServices,\r
146 IN EFI_PEI_HOB_POINTERS HobList\r
147 )\r
95276127 148{\r
149 EFI_STATUS Status;\r
b6b98e91 150 EFI_FV_FILE_INFO DxeCoreFileInfo;\r
95276127 151 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
152 UINT64 DxeCoreSize;\r
153 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
95276127 154 EFI_BOOT_MODE BootMode;\r
b0d803fe 155 EFI_PEI_FILE_HANDLE FileHandle;\r
b74350e9 156 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
157 UINTN DataSize;\r
708919be 158 EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];\r
95276127 159\r
160 //\r
161 // if in S3 Resume, restore configure\r
162 //\r
b98da1b1 163 BootMode = GetBootModeHob ();\r
95276127 164\r
165 if (BootMode == BOOT_ON_S3_RESUME) {\r
e8da1266 166 Status = AcpiS3ResumeOs();\r
95276127 167 ASSERT_EFI_ERROR (Status);\r
168 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
e8da1266 169 Status = PeiRecoverFirmware ();\r
95276127 170 if (EFI_ERROR (Status)) {\r
91d92e25 171 DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
95276127 172 CpuDeadLoop ();\r
173 }\r
174\r
175 //\r
48557c65 176 // Now should have a HOB with the DXE core\r
95276127 177 //\r
178 }\r
288f9b38 179\r
b74350e9 180 Status = PeiServicesLocatePpi (\r
181 &gEfiPeiReadOnlyVariable2PpiGuid,\r
182 0,\r
183 NULL,\r
184 (VOID **)&Variable\r
185 );\r
b74350e9 186 if (!EFI_ERROR (Status)) {\r
1ad76c34 187 DataSize = sizeof (MemoryData);\r
188 Status = Variable->GetVariable ( \r
189 Variable, \r
190 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
191 &gEfiMemoryTypeInformationGuid,\r
192 NULL,\r
193 &DataSize,\r
194 &MemoryData\r
195 );\r
196 if (!EFI_ERROR (Status)) {\r
197 //\r
198 // Build the GUID'd HOB for DXE\r
199 //\r
200 BuildGuidDataHob (\r
201 &gEfiMemoryTypeInformationGuid,\r
202 MemoryData,\r
203 DataSize\r
204 );\r
205 }\r
b74350e9 206 }\r
288f9b38 207\r
95276127 208 //\r
b6b98e91 209 // Look in all the FVs present in PEI and find the DXE Core FileHandle\r
95276127 210 //\r
b6b98e91 211 FileHandle = DxeIplFindDxeCore ();\r
b0d803fe 212\r
95276127 213 //\r
48557c65 214 // Load the DXE Core from a Firmware Volume, may use LoadFile PPI to do this to save code size.\r
95276127 215 //\r
216 Status = PeiLoadFile (\r
b98da1b1 217 FileHandle,\r
218 &DxeCoreAddress,\r
219 &DxeCoreSize,\r
220 &DxeCoreEntryPoint\r
221 );\r
95276127 222 ASSERT_EFI_ERROR (Status);\r
223\r
b6b98e91 224 //\r
225 // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.\r
226 //\r
227 Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);\r
228 ASSERT_EFI_ERROR (Status);\r
229\r
95276127 230 //\r
231 // Add HOB for the DXE Core\r
232 //\r
233 BuildModuleHob (\r
b6b98e91 234 &DxeCoreFileInfo.FileName,\r
95276127 235 DxeCoreAddress,\r
48557c65 236 ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),\r
95276127 237 DxeCoreEntryPoint\r
238 );\r
239\r
240 //\r
241 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
242 //\r
48557c65 243 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdStatusCodeValuePeiHandoffToDxe));\r
95276127 244\r
4e2dd553 245 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
e98cd821 246\r
95276127 247 //\r
248 // Transfer control to the DXE Core\r
48557c65 249 // The hand off state is simply a pointer to the HOB list\r
95276127 250 //\r
9b937a73 251 HandOffToDxeCore (DxeCoreEntryPoint, HobList);\r
95276127 252 //\r
253 // If we get here, then the DXE Core returned. This is an error\r
48557c65 254 // DxeCore should not return.\r
95276127 255 //\r
256 ASSERT (FALSE);\r
257 CpuDeadLoop ();\r
258\r
259 return EFI_OUT_OF_RESOURCES;\r
260}\r
261\r
91d92e25 262\r
b0d803fe 263/**\r
9b937a73 264 Searches DxeCore in all firmware Volumes and loads the first\r
265 instance that contains DxeCore.\r
b0d803fe 266\r
9b937a73 267 @return FileHandle of DxeCore to load DxeCore.\r
268 \r
91d92e25 269**/\r
9b937a73 270EFI_PEI_FILE_HANDLE\r
288f9b38 271DxeIplFindDxeCore (\r
b6b98e91 272 VOID\r
b0d803fe 273 )\r
95276127 274{\r
9b937a73 275 EFI_STATUS Status;\r
276 UINTN Instance;\r
277 EFI_PEI_FV_HANDLE VolumeHandle;\r
278 EFI_PEI_FILE_HANDLE FileHandle;\r
288f9b38
LG
279 \r
280 Instance = 0;\r
9b937a73 281 while (TRUE) {\r
282 //\r
283 // Traverse all firmware volume instances\r
284 //\r
285 Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
286 //\r
287 // If some error occurs here, then we cannot find any firmware\r
288 // volume that may contain DxeCore.\r
289 //\r
290 ASSERT_EFI_ERROR (Status);\r
291 \r
292 //\r
293 // Find the DxeCore file type from the beginning in this firmware volume.\r
294 //\r
295 FileHandle = NULL;\r
296 Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);\r
288f9b38 297 if (!EFI_ERROR (Status)) {\r
9b937a73 298 //\r
b6b98e91 299 // Find DxeCore FileHandle in this volume, then we skip other firmware volume and\r
300 // return the FileHandle.\r
9b937a73 301 //\r
b6b98e91 302 return FileHandle;\r
95276127 303 }\r
9b937a73 304 //\r
305 // We cannot find DxeCore in this firmware volume, then search the next volume.\r
306 //\r
307 Instance++;\r
308 }\r
95276127 309}\r
310\r
91d92e25 311\r
b0d803fe 312/**\r
313 Loads and relocates a PE/COFF image into memory.\r
314\r
315 @param FileHandle The image file handle\r
316 @param ImageAddress The base address of the relocated PE/COFF image\r
317 @param ImageSize The size of the relocated PE/COFF image\r
318 @param EntryPoint The entry point of the relocated PE/COFF image\r
319 \r
320 @return EFI_SUCCESS The file was loaded and relocated\r
321 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
91d92e25 322\r
b0d803fe 323**/\r
95276127 324EFI_STATUS\r
325PeiLoadFile (\r
b0d803fe 326 IN EFI_PEI_FILE_HANDLE FileHandle,\r
95276127 327 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
328 OUT UINT64 *ImageSize,\r
329 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
330 )\r
b0d803fe 331{\r
95276127 332\r
b0d803fe 333 EFI_STATUS Status;\r
334 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
335 VOID *Pe32Data;\r
b98da1b1 336\r
b0d803fe 337 //\r
6b978d16 338 // First try to find the PE32 section in this ffs file.\r
b0d803fe 339 //\r
340 Status = PeiServicesFfsFindSectionData (\r
341 EFI_SECTION_PE32,\r
342 FileHandle,\r
343 &Pe32Data\r
344 );\r
b0d803fe 345 if (EFI_ERROR (Status)) {\r
346 //\r
347 // NO image types we support so exit.\r
348 //\r
349 return Status;\r
350 }\r
95276127 351\r
352 ZeroMem (&ImageContext, sizeof (ImageContext));\r
353 ImageContext.Handle = Pe32Data;\r
48557c65 354 ImageContext.ImageRead = PeiImageRead;\r
95276127 355\r
95276127 356\r
3d7b0992 357 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
95276127 358 if (EFI_ERROR (Status)) {\r
359 return Status;\r
360 }\r
361 //\r
362 // Allocate Memory for the image\r
363 //\r
4bf952d1 364 Status = PeiServicesAllocatePages (\r
365 EfiBootServicesCode, \r
366 EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), \r
367 &ImageContext.ImageAddress\r
368 );\r
369 ASSERT_EFI_ERROR (Status);\r
95276127 370 ASSERT (ImageContext.ImageAddress != 0);\r
371\r
372 //\r
373 // Load the image to our new buffer\r
374 //\r
3d7b0992 375 Status = PeCoffLoaderLoadImage (&ImageContext);\r
95276127 376 if (EFI_ERROR (Status)) {\r
377 return Status;\r
378 }\r
379 //\r
380 // Relocate the image in our new buffer\r
381 //\r
3d7b0992 382 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
95276127 383 if (EFI_ERROR (Status)) {\r
384 return Status;\r
385 }\r
386\r
387 //\r
48557c65 388 // Flush the instruction cache so the image data are written before we execute it\r
95276127 389 //\r
48557c65 390 InvalidateInstructionCacheRange ((VOID *)(UINTN) ImageContext.ImageAddress, (UINTN) ImageContext.ImageSize);\r
95276127 391\r
392 *ImageAddress = ImageContext.ImageAddress;\r
393 *ImageSize = ImageContext.ImageSize;\r
394 *EntryPoint = ImageContext.EntryPoint;\r
395\r
396 return EFI_SUCCESS;\r
397}\r
398\r
91d92e25 399\r
400\r
401\r
d8c79a81
LG
402/**\r
403 The ExtractSection() function processes the input section and\r
404 returns a pointer to the section contents. If the section being\r
405 extracted does not require processing (if the section\r
406 GuidedSectionHeader.Attributes has the\r
407 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
408 OutputBuffer is just updated to point to the start of the\r
409 section's contents. Otherwise, *Buffer must be allocated\r
410 from PEI permanent memory.\r
411\r
412 @param This Indicates the\r
413 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
414 Buffer containing the input GUIDed section to be\r
415 processed. OutputBuffer OutputBuffer is\r
416 allocated from PEI permanent memory and contains\r
417 the new section stream.\r
91d92e25 418 @param InputSection A pointer to the input buffer, which contains\r
419 the input section to be processed.\r
420 @param OutputBuffer A pointer to a caller-allocated buffer, whose\r
421 size is specified by the contents of OutputSize.\r
d8c79a81
LG
422 @param OutputSize A pointer to a caller-allocated\r
423 UINTN in which the size of *OutputBuffer\r
424 allocation is stored. If the function\r
425 returns anything other than EFI_SUCCESS,\r
426 the value of OutputSize is undefined.\r
d8c79a81
LG
427 @param AuthenticationStatus A pointer to a caller-allocated\r
428 UINT32 that indicates the\r
429 authentication status of the\r
430 output buffer. If the input\r
431 section's GuidedSectionHeader.\r
432 Attributes field has the\r
433 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
434 bit as clear,\r
435 AuthenticationStatus must return\r
436 zero. These bits reflect the\r
437 status of the extraction\r
438 operation. If the function\r
439 returns anything other than\r
440 EFI_SUCCESS, the value of\r
441 AuthenticationStatus is\r
442 undefined.\r
443 \r
444 @retval EFI_SUCCESS The InputSection was\r
445 successfully processed and the\r
446 section contents were returned.\r
447 \r
448 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
449 resources to process the request.\r
450 \r
708919be 451 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
d8c79a81
LG
452 not match this instance of the\r
453 GUIDed Section Extraction PPI.\r
91d92e25 454\r
d8c79a81
LG
455**/\r
456EFI_STATUS\r
6d3ea23f 457EFIAPI\r
18fd8d65 458CustomGuidedSectionExtract (\r
d8c79a81
LG
459 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
460 IN CONST VOID *InputSection,\r
461 OUT VOID **OutputBuffer,\r
462 OUT UINTN *OutputSize,\r
463 OUT UINT32 *AuthenticationStatus\r
464)\r
465{\r
466 EFI_STATUS Status;\r
467 UINT8 *ScratchBuffer;\r
18fd8d65
LG
468 UINT32 ScratchBufferSize;\r
469 UINT32 OutputBufferSize;\r
470 UINT16 SectionAttribute;\r
d8c79a81
LG
471 \r
472 //\r
18fd8d65 473 // Init local variable\r
d8c79a81 474 //\r
18fd8d65
LG
475 ScratchBuffer = NULL;\r
476\r
d8c79a81 477 //\r
18fd8d65 478 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 479 //\r
18fd8d65 480 Status = ExtractGuidedSectionGetInfo (\r
b6b98e91 481 InputSection,\r
482 &OutputBufferSize,\r
483 &ScratchBufferSize,\r
484 &SectionAttribute\r
485 );\r
18fd8d65 486 \r
d8c79a81 487 if (EFI_ERROR (Status)) {\r
91d92e25 488 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
18fd8d65
LG
489 return Status;\r
490 }\r
491 \r
492 if (ScratchBufferSize != 0) {\r
95276127 493 //\r
18fd8d65 494 // Allocate scratch buffer\r
95276127 495 //\r
18fd8d65
LG
496 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
497 if (ScratchBuffer == NULL) {\r
498 return EFI_OUT_OF_RESOURCES;\r
499 }\r
d8c79a81 500 }\r
95276127 501\r
708919be 502 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) { \r
18fd8d65
LG
503 //\r
504 // Allocate output buffer\r
505 //\r
288f9b38 506 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
18fd8d65
LG
507 if (*OutputBuffer == NULL) {\r
508 return EFI_OUT_OF_RESOURCES;\r
509 }\r
48557c65 510 DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
288f9b38
LG
511 //\r
512 // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
513 // skip EFI section header to make section data at page alignment.\r
514 //\r
515 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
95276127 516 }\r
18fd8d65
LG
517 \r
518 Status = ExtractGuidedSectionDecode (\r
519 InputSection, \r
520 OutputBuffer,\r
521 ScratchBuffer,\r
522 AuthenticationStatus\r
48557c65 523 );\r
d8c79a81
LG
524 if (EFI_ERROR (Status)) {\r
525 //\r
18fd8d65 526 // Decode failed\r
d8c79a81 527 //\r
91d92e25 528 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
d8c79a81
LG
529 return Status;\r
530 }\r
531 \r
18fd8d65
LG
532 *OutputSize = (UINTN) OutputBufferSize;\r
533 \r
95276127 534 return EFI_SUCCESS;\r
535}\r
b0d803fe 536\r
91d92e25 537\r
538\r
539/**\r
540 Decompresses a section to the output buffer.\r
541\r
48557c65 542 This function looks up the compression type field in the input section and\r
91d92e25 543 applies the appropriate compression algorithm to compress the section to a\r
544 callee allocated buffer.\r
545 \r
546 @param This Points to this instance of the\r
547 EFI_PEI_DECOMPRESS_PEI PPI.\r
548 @param CompressionSection Points to the compressed section.\r
549 @param OutputBuffer Holds the returned pointer to the decompressed\r
550 sections.\r
551 @param OutputSize Holds the returned size of the decompress\r
552 section streams.\r
553 \r
554 @retval EFI_SUCCESS The section was decompressed successfully.\r
555 OutputBuffer contains the resulting data and\r
556 OutputSize contains the resulting size.\r
557\r
558**/\r
b0d803fe 559EFI_STATUS\r
560EFIAPI \r
561Decompress (\r
562 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
563 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
564 OUT VOID **OutputBuffer,\r
565 OUT UINTN *OutputSize\r
566 )\r
567{\r
568 EFI_STATUS Status;\r
569 UINT8 *DstBuffer;\r
570 UINT8 *ScratchBuffer;\r
571 UINTN DstBufferSize;\r
572 UINT32 ScratchBufferSize;\r
573 EFI_COMMON_SECTION_HEADER *Section;\r
574 UINTN SectionLength;\r
575\r
576 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
577 ASSERT (FALSE);\r
578 return EFI_INVALID_PARAMETER;\r
579 }\r
580\r
581 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
b98da1b1 582 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
b0d803fe 583 \r
584 //\r
585 // This is a compression set, expand it\r
586 //\r
587 switch (CompressionSection->CompressionType) {\r
588 case EFI_STANDARD_COMPRESSION:\r
873b7997 589 if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {\r
b0d803fe 590 //\r
873b7997 591 // Load EFI standard compression.\r
592 // For compressed data, decompress them to destination buffer.\r
b0d803fe 593 //\r
873b7997 594 Status = UefiDecompressGetInfo (\r
595 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
596 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
597 (UINT32 *) &DstBufferSize,\r
598 &ScratchBufferSize\r
599 );\r
600 if (EFI_ERROR (Status)) {\r
601 //\r
602 // GetInfo failed\r
603 //\r
604 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
605 return EFI_NOT_FOUND;\r
606 }\r
607 //\r
608 // Allocate scratch buffer\r
b0d803fe 609 //\r
873b7997 610 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
611 if (ScratchBuffer == NULL) {\r
612 return EFI_OUT_OF_RESOURCES;\r
613 }\r
614 //\r
615 // Allocate destination buffer, extra one page for adjustment \r
616 //\r
617 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
618 if (DstBuffer == NULL) {\r
619 return EFI_OUT_OF_RESOURCES;\r
620 }\r
b0d803fe 621 //\r
873b7997 622 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
623 // to make section data at page alignment.\r
624 //\r
625 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
626 //\r
627 // Call decompress function\r
628 //\r
629 Status = UefiDecompress (\r
630 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
631 DstBuffer,\r
632 ScratchBuffer\r
633 );\r
634 if (EFI_ERROR (Status)) {\r
635 //\r
636 // Decompress failed\r
637 //\r
638 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
639 return EFI_NOT_FOUND;\r
640 }\r
641 break;\r
642 } else {\r
12b3e61e
LG
643 //\r
644 // PcdDxeIplSupportUefiDecompress is FALSE\r
645 // Don't support UEFI decompression algorithm.\r
646 //\r
647 ASSERT (FALSE);\r
b0d803fe 648 return EFI_NOT_FOUND;\r
649 }\r
b0d803fe 650\r
b0d803fe 651 case EFI_NOT_COMPRESSED:\r
652 //\r
653 // Allocate destination buffer\r
654 //\r
655 DstBufferSize = CompressionSection->UncompressedLength;\r
288f9b38 656 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 657 if (DstBuffer == NULL) {\r
658 return EFI_OUT_OF_RESOURCES;\r
659 }\r
660 //\r
288f9b38
LG
661 // Adjust DstBuffer offset, skip EFI section header\r
662 // to make section data at page alignment.\r
663 //\r
664 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
665 //\r
b0d803fe 666 // stream is not actually compressed, just encapsulated. So just copy it.\r
667 //\r
668 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
669 break;\r
670\r
671 default:\r
672 //\r
673 // Don't support other unknown compression type.\r
674 //\r
675 ASSERT (FALSE);\r
676 return EFI_NOT_FOUND;\r
677 }\r
678\r
679 *OutputSize = DstBufferSize;\r
680 *OutputBuffer = DstBuffer;\r
681\r
682 return EFI_SUCCESS;\r
683}\r
684\r
91d92e25 685\r
91d92e25 686/**\r
687 Updates the Stack HOB passed to DXE phase.\r
688\r
689 This function traverses the whole HOB list and update the stack HOB to\r
690 reflect the real stack that is used by DXE core.\r
691\r
692 @param BaseAddress The lower address of stack used by DxeCore.\r
693 @param Length The length of stack used by DxeCore.\r
694\r
695**/\r
30c8f861 696VOID\r
697UpdateStackHob (\r
698 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
699 IN UINT64 Length\r
700 )\r
701{\r
702 EFI_PEI_HOB_POINTERS Hob;\r
703\r
704 Hob.Raw = GetHobList ();\r
705 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
706 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
707 //\r
708 // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type\r
709 // to be reclaimed by DXE core.\r
710 //\r
711 BuildMemoryAllocationHob (\r
712 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
713 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
714 EfiConventionalMemory\r
715 );\r
716 //\r
717 // Update the BSP Stack Hob to reflect the new stack info.\r
718 //\r
719 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
720 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
721 break;\r
722 }\r
723 Hob.Raw = GET_NEXT_HOB (Hob);\r
724 }\r
725}\r