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