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