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