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