]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Code Scrub DxeIpl module.
[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
b98da1b1 28CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
95276127 29 DxeLoadCore\r
30};\r
31\r
b98da1b1 32CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
18fd8d65 33 CustomGuidedSectionExtract\r
95276127 34};\r
35\r
b98da1b1 36CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
b0d803fe 37 Decompress\r
d8c79a81
LG
38};\r
39\r
b98da1b1 40CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
95276127 41 {\r
b0d803fe 42 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
43 &gEfiDxeIplPpiGuid,\r
44 &mDxeIplPpi\r
95276127 45 },\r
46 {\r
b0d803fe 47 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
48 &gEfiPeiDecompressPpiGuid,\r
49 &mDecompressPpi\r
95276127 50 }\r
51};\r
52\r
b98da1b1 53CONST EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {\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
105 GuidPpi->Ppi = &mCustomGuidedSectionExtractionPpi;\r
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
145 EFI_GUID DxeCoreFileName;\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
b0d803fe 204 // Look in all the FVs present in PEI and find the DXE Core\r
95276127 205 //\r
288f9b38
LG
206 FileHandle = NULL;\r
207 Status = DxeIplFindDxeCore (&FileHandle);\r
95276127 208 ASSERT_EFI_ERROR (Status);\r
209\r
b98da1b1 210 CopyGuid(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name));\r
b0d803fe 211\r
95276127 212 //\r
6b978d16 213 // Load the DXE Core from a Firmware Volume, may use LoadFile ppi to do this for save code size.\r
95276127 214 //\r
215 Status = PeiLoadFile (\r
b98da1b1 216 FileHandle,\r
217 &DxeCoreAddress,\r
218 &DxeCoreSize,\r
219 &DxeCoreEntryPoint\r
220 );\r
95276127 221 ASSERT_EFI_ERROR (Status);\r
222\r
223 //\r
224 // Add HOB for the DXE Core\r
225 //\r
226 BuildModuleHob (\r
227 &DxeCoreFileName,\r
228 DxeCoreAddress,\r
b98da1b1 229 EFI_SIZE_TO_PAGES ((UINTN) DxeCoreSize) * EFI_PAGE_SIZE,\r
95276127 230 DxeCoreEntryPoint\r
231 );\r
232\r
233 //\r
234 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
235 //\r
236 REPORT_STATUS_CODE (\r
237 EFI_PROGRESS_CODE,\r
797a9d67 238 PcdGet32(PcdStatusCodeValuePeiHandoffToDxe)\r
95276127 239 );\r
240\r
e98cd821
LG
241 DEBUG_CODE_BEGIN ();\r
242\r
243 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;\r
244 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);\r
b98da1b1 245 \r
246 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
247 \r
e98cd821
LG
248\r
249 DEBUG_CODE_END ();\r
95276127 250 //\r
251 // Transfer control to the DXE Core\r
252 // The handoff state is simply a pointer to the HOB list\r
253 //\r
95276127 254 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
255 //\r
256 // If we get here, then the DXE Core returned. This is an error\r
257 // Dxe Core should not return.\r
258 //\r
259 ASSERT (FALSE);\r
260 CpuDeadLoop ();\r
261\r
262 return EFI_OUT_OF_RESOURCES;\r
263}\r
264\r
91d92e25 265\r
266\r
267\r
b0d803fe 268/**\r
288f9b38 269 Find DxeCore driver from all First Volumes.\r
b0d803fe 270\r
b0d803fe 271 @param FileHandle Pointer to FFS file to search.\r
272 \r
273 @return EFI_SUCESS Success to find the FFS in specificed FV\r
274 @return others Fail to find the FFS in specificed FV\r
91d92e25 275\r
276**/\r
b0d803fe 277EFI_STATUS\r
288f9b38 278DxeIplFindDxeCore (\r
b0d803fe 279 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
280 )\r
95276127 281{\r
288f9b38
LG
282 EFI_STATUS Status;\r
283 EFI_STATUS FileStatus;\r
284 UINTN Instance;\r
285 EFI_PEI_FV_HANDLE VolumeHandle;\r
286 \r
287 Instance = 0;\r
288 *FileHandle = NULL;\r
95276127 289\r
b0d803fe 290 do {\r
288f9b38
LG
291 Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
292 if (!EFI_ERROR (Status)) {\r
293 FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);\r
294 if (!EFI_ERROR (FileStatus)) {\r
295 return FileStatus;\r
95276127 296 }\r
297 }\r
288f9b38 298 } while (!EFI_ERROR (Status));\r
b0d803fe 299\r
288f9b38 300 return EFI_NOT_FOUND;\r
95276127 301}\r
302\r
91d92e25 303\r
b0d803fe 304/**\r
305 Loads and relocates a PE/COFF image into memory.\r
306\r
307 @param FileHandle The image file handle\r
308 @param ImageAddress The base address of the relocated PE/COFF image\r
309 @param ImageSize The size of the relocated PE/COFF image\r
310 @param EntryPoint The entry point of the relocated PE/COFF image\r
311 \r
312 @return EFI_SUCCESS The file was loaded and relocated\r
313 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
91d92e25 314\r
b0d803fe 315**/\r
95276127 316EFI_STATUS\r
317PeiLoadFile (\r
b0d803fe 318 IN EFI_PEI_FILE_HANDLE FileHandle,\r
95276127 319 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
320 OUT UINT64 *ImageSize,\r
321 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
322 )\r
b0d803fe 323{\r
95276127 324\r
b0d803fe 325 EFI_STATUS Status;\r
326 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
327 VOID *Pe32Data;\r
b98da1b1 328\r
b0d803fe 329 //\r
6b978d16 330 // First try to find the PE32 section in this ffs file.\r
b0d803fe 331 //\r
332 Status = PeiServicesFfsFindSectionData (\r
333 EFI_SECTION_PE32,\r
334 FileHandle,\r
335 &Pe32Data\r
336 );\r
b0d803fe 337 if (EFI_ERROR (Status)) {\r
338 //\r
339 // NO image types we support so exit.\r
340 //\r
341 return Status;\r
342 }\r
95276127 343\r
344 ZeroMem (&ImageContext, sizeof (ImageContext));\r
345 ImageContext.Handle = Pe32Data;\r
346 Status = GetImageReadFunction (&ImageContext);\r
347\r
348 ASSERT_EFI_ERROR (Status);\r
349\r
3d7b0992 350 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
95276127 351 if (EFI_ERROR (Status)) {\r
352 return Status;\r
353 }\r
354 //\r
355 // Allocate Memory for the image\r
356 //\r
357 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
358 ASSERT (ImageContext.ImageAddress != 0);\r
359\r
360 //\r
361 // Load the image to our new buffer\r
362 //\r
3d7b0992 363 Status = PeCoffLoaderLoadImage (&ImageContext);\r
95276127 364 if (EFI_ERROR (Status)) {\r
365 return Status;\r
366 }\r
367 //\r
368 // Relocate the image in our new buffer\r
369 //\r
3d7b0992 370 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
95276127 371 if (EFI_ERROR (Status)) {\r
372 return Status;\r
373 }\r
374\r
375 //\r
376 // Flush the instruction cache so the image data is written before we execute it\r
377 //\r
378 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
379\r
380 *ImageAddress = ImageContext.ImageAddress;\r
381 *ImageSize = ImageContext.ImageSize;\r
382 *EntryPoint = ImageContext.EntryPoint;\r
383\r
384 return EFI_SUCCESS;\r
385}\r
386\r
91d92e25 387\r
388\r
389\r
d8c79a81
LG
390/**\r
391 The ExtractSection() function processes the input section and\r
392 returns a pointer to the section contents. If the section being\r
393 extracted does not require processing (if the section\r
394 GuidedSectionHeader.Attributes has the\r
395 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
396 OutputBuffer is just updated to point to the start of the\r
397 section's contents. Otherwise, *Buffer must be allocated\r
398 from PEI permanent memory.\r
399\r
400 @param This Indicates the\r
401 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
402 Buffer containing the input GUIDed section to be\r
403 processed. OutputBuffer OutputBuffer is\r
404 allocated from PEI permanent memory and contains\r
405 the new section stream.\r
91d92e25 406 @param InputSection A pointer to the input buffer, which contains\r
407 the input section to be processed.\r
408 @param OutputBuffer A pointer to a caller-allocated buffer, whose\r
409 size is specified by the contents of OutputSize.\r
d8c79a81
LG
410 @param OutputSize A pointer to a caller-allocated\r
411 UINTN in which the size of *OutputBuffer\r
412 allocation is stored. If the function\r
413 returns anything other than EFI_SUCCESS,\r
414 the value of OutputSize is undefined.\r
d8c79a81
LG
415 @param AuthenticationStatus A pointer to a caller-allocated\r
416 UINT32 that indicates the\r
417 authentication status of the\r
418 output buffer. If the input\r
419 section's GuidedSectionHeader.\r
420 Attributes field has the\r
421 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
422 bit as clear,\r
423 AuthenticationStatus must return\r
424 zero. These bits reflect the\r
425 status of the extraction\r
426 operation. If the function\r
427 returns anything other than\r
428 EFI_SUCCESS, the value of\r
429 AuthenticationStatus is\r
430 undefined.\r
431 \r
432 @retval EFI_SUCCESS The InputSection was\r
433 successfully processed and the\r
434 section contents were returned.\r
435 \r
436 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
437 resources to process the request.\r
438 \r
708919be 439 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
d8c79a81
LG
440 not match this instance of the\r
441 GUIDed Section Extraction PPI.\r
91d92e25 442\r
d8c79a81
LG
443**/\r
444EFI_STATUS\r
18fd8d65 445CustomGuidedSectionExtract (\r
d8c79a81
LG
446 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
447 IN CONST VOID *InputSection,\r
448 OUT VOID **OutputBuffer,\r
449 OUT UINTN *OutputSize,\r
450 OUT UINT32 *AuthenticationStatus\r
451)\r
452{\r
453 EFI_STATUS Status;\r
454 UINT8 *ScratchBuffer;\r
18fd8d65
LG
455 UINT32 ScratchBufferSize;\r
456 UINT32 OutputBufferSize;\r
457 UINT16 SectionAttribute;\r
d8c79a81
LG
458 \r
459 //\r
18fd8d65 460 // Init local variable\r
d8c79a81 461 //\r
18fd8d65
LG
462 ScratchBuffer = NULL;\r
463\r
d8c79a81 464 //\r
18fd8d65 465 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 466 //\r
18fd8d65
LG
467 Status = ExtractGuidedSectionGetInfo (\r
468 InputSection,\r
469 &OutputBufferSize,\r
470 &ScratchBufferSize,\r
471 &SectionAttribute\r
472 );\r
473 \r
d8c79a81 474 if (EFI_ERROR (Status)) {\r
91d92e25 475 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
18fd8d65
LG
476 return Status;\r
477 }\r
478 \r
479 if (ScratchBufferSize != 0) {\r
95276127 480 //\r
18fd8d65 481 // Allocate scratch buffer\r
95276127 482 //\r
18fd8d65
LG
483 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
484 if (ScratchBuffer == NULL) {\r
485 return EFI_OUT_OF_RESOURCES;\r
486 }\r
d8c79a81 487 }\r
95276127 488\r
708919be 489 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) { \r
18fd8d65
LG
490 //\r
491 // Allocate output buffer\r
492 //\r
288f9b38 493 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
18fd8d65
LG
494 if (*OutputBuffer == NULL) {\r
495 return EFI_OUT_OF_RESOURCES;\r
496 }\r
91d92e25 497 DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
288f9b38
LG
498 //\r
499 // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
500 // skip EFI section header to make section data at page alignment.\r
501 //\r
502 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
95276127 503 }\r
18fd8d65
LG
504 \r
505 Status = ExtractGuidedSectionDecode (\r
506 InputSection, \r
507 OutputBuffer,\r
508 ScratchBuffer,\r
509 AuthenticationStatus\r
510 );\r
d8c79a81
LG
511 if (EFI_ERROR (Status)) {\r
512 //\r
18fd8d65 513 // Decode failed\r
d8c79a81 514 //\r
91d92e25 515 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
d8c79a81
LG
516 return Status;\r
517 }\r
518 \r
18fd8d65
LG
519 *OutputSize = (UINTN) OutputBufferSize;\r
520 \r
95276127 521 return EFI_SUCCESS;\r
522}\r
b0d803fe 523\r
91d92e25 524\r
525\r
526/**\r
527 Decompresses a section to the output buffer.\r
528\r
529 This function lookes up the compression type field in the input section and\r
530 applies the appropriate compression algorithm to compress the section to a\r
531 callee allocated buffer.\r
532 \r
533 @param This Points to this instance of the\r
534 EFI_PEI_DECOMPRESS_PEI PPI.\r
535 @param CompressionSection Points to the compressed section.\r
536 @param OutputBuffer Holds the returned pointer to the decompressed\r
537 sections.\r
538 @param OutputSize Holds the returned size of the decompress\r
539 section streams.\r
540 \r
541 @retval EFI_SUCCESS The section was decompressed successfully.\r
542 OutputBuffer contains the resulting data and\r
543 OutputSize contains the resulting size.\r
544\r
545**/\r
b0d803fe 546EFI_STATUS\r
547EFIAPI \r
548Decompress (\r
549 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
550 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
551 OUT VOID **OutputBuffer,\r
552 OUT UINTN *OutputSize\r
553 )\r
554{\r
555 EFI_STATUS Status;\r
556 UINT8 *DstBuffer;\r
557 UINT8 *ScratchBuffer;\r
558 UINTN DstBufferSize;\r
559 UINT32 ScratchBufferSize;\r
560 EFI_COMMON_SECTION_HEADER *Section;\r
561 UINTN SectionLength;\r
562\r
563 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
564 ASSERT (FALSE);\r
565 return EFI_INVALID_PARAMETER;\r
566 }\r
567\r
568 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
b98da1b1 569 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
b0d803fe 570 \r
571 //\r
572 // This is a compression set, expand it\r
573 //\r
574 switch (CompressionSection->CompressionType) {\r
575 case EFI_STANDARD_COMPRESSION:\r
576 //\r
577 // Load EFI standard compression.\r
578 // For compressed data, decompress them to dstbuffer.\r
579 //\r
580 Status = UefiDecompressGetInfo (\r
581 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
582 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
583 (UINT32 *) &DstBufferSize,\r
584 &ScratchBufferSize\r
585 );\r
586 if (EFI_ERROR (Status)) {\r
587 //\r
588 // GetInfo failed\r
589 //\r
91d92e25 590 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
b0d803fe 591 return EFI_NOT_FOUND;\r
592 }\r
593 //\r
594 // Allocate scratch buffer\r
595 //\r
596 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
597 if (ScratchBuffer == NULL) {\r
598 return EFI_OUT_OF_RESOURCES;\r
599 }\r
600 //\r
288f9b38 601 // Allocate destination buffer, extra one page for adjustment \r
b0d803fe 602 //\r
288f9b38 603 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 604 if (DstBuffer == NULL) {\r
605 return EFI_OUT_OF_RESOURCES;\r
606 }\r
607 //\r
288f9b38
LG
608 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
609 // to make section data at page alignment.\r
610 //\r
611 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
612 //\r
b0d803fe 613 // Call decompress function\r
614 //\r
615 Status = UefiDecompress (\r
616 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
617 DstBuffer,\r
618 ScratchBuffer\r
619 );\r
620 if (EFI_ERROR (Status)) {\r
621 //\r
622 // Decompress failed\r
623 //\r
91d92e25 624 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
b0d803fe 625 return EFI_NOT_FOUND;\r
626 }\r
627 break;\r
628\r
b0d803fe 629 case EFI_NOT_COMPRESSED:\r
630 //\r
631 // Allocate destination buffer\r
632 //\r
633 DstBufferSize = CompressionSection->UncompressedLength;\r
288f9b38 634 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 635 if (DstBuffer == NULL) {\r
636 return EFI_OUT_OF_RESOURCES;\r
637 }\r
638 //\r
288f9b38
LG
639 // Adjust DstBuffer offset, skip EFI section header\r
640 // to make section data at page alignment.\r
641 //\r
642 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
643 //\r
b0d803fe 644 // stream is not actually compressed, just encapsulated. So just copy it.\r
645 //\r
646 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
647 break;\r
648\r
649 default:\r
650 //\r
651 // Don't support other unknown compression type.\r
652 //\r
653 ASSERT (FALSE);\r
654 return EFI_NOT_FOUND;\r
655 }\r
656\r
657 *OutputSize = DstBufferSize;\r
658 *OutputBuffer = DstBuffer;\r
659\r
660 return EFI_SUCCESS;\r
661}\r
662\r
91d92e25 663\r
664\r
665\r
666/**\r
667 Updates the Stack HOB passed to DXE phase.\r
668\r
669 This function traverses the whole HOB list and update the stack HOB to\r
670 reflect the real stack that is used by DXE core.\r
671\r
672 @param BaseAddress The lower address of stack used by DxeCore.\r
673 @param Length The length of stack used by DxeCore.\r
674\r
675**/\r
30c8f861 676VOID\r
677UpdateStackHob (\r
678 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
679 IN UINT64 Length\r
680 )\r
681{\r
682 EFI_PEI_HOB_POINTERS Hob;\r
683\r
684 Hob.Raw = GetHobList ();\r
685 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
686 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
687 //\r
688 // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type\r
689 // to be reclaimed by DXE core.\r
690 //\r
691 BuildMemoryAllocationHob (\r
692 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
693 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
694 EfiConventionalMemory\r
695 );\r
696 //\r
697 // Update the BSP Stack Hob to reflect the new stack info.\r
698 //\r
699 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
700 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
701 break;\r
702 }\r
703 Hob.Raw = GET_NEXT_HOB (Hob);\r
704 }\r
705}\r