]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Add PCD PcdRealTimeClockUpdateTimeout and update code accordingly.
[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
b74350e9 279 if (!EFI_ERROR (Status)) {\r
1ad76c34 280 DataSize = sizeof (MemoryData);\r
281 Status = Variable->GetVariable ( \r
282 Variable, \r
283 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
284 &gEfiMemoryTypeInformationGuid,\r
285 NULL,\r
286 &DataSize,\r
287 &MemoryData\r
288 );\r
289 if (!EFI_ERROR (Status)) {\r
290 //\r
291 // Build the GUID'd HOB for DXE\r
292 //\r
293 BuildGuidDataHob (\r
294 &gEfiMemoryTypeInformationGuid,\r
295 MemoryData,\r
296 DataSize\r
297 );\r
298 }\r
b74350e9 299 }\r
288f9b38 300\r
95276127 301 //\r
b0d803fe 302 // Look in all the FVs present in PEI and find the DXE Core\r
95276127 303 //\r
288f9b38
LG
304 FileHandle = NULL;\r
305 Status = DxeIplFindDxeCore (&FileHandle);\r
95276127 306 ASSERT_EFI_ERROR (Status);\r
307\r
b0d803fe 308 CopyMem(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name), sizeof (EFI_GUID));\r
309\r
95276127 310 //\r
6b978d16 311 // Load the DXE Core from a Firmware Volume, may use LoadFile ppi to do this for save code size.\r
95276127 312 //\r
313 Status = PeiLoadFile (\r
b0d803fe 314 FileHandle,\r
315 &DxeCoreAddress,\r
316 &DxeCoreSize,\r
317 &DxeCoreEntryPoint\r
318 );\r
319\r
95276127 320 ASSERT_EFI_ERROR (Status);\r
321\r
322 //\r
323 // Add HOB for the DXE Core\r
324 //\r
325 BuildModuleHob (\r
326 &DxeCoreFileName,\r
327 DxeCoreAddress,\r
0a7d0741 328 EFI_SIZE_TO_PAGES ((UINT32) DxeCoreSize) * EFI_PAGE_SIZE,\r
95276127 329 DxeCoreEntryPoint\r
330 );\r
331\r
332 //\r
333 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
334 //\r
335 REPORT_STATUS_CODE (\r
336 EFI_PROGRESS_CODE,\r
797a9d67 337 PcdGet32(PcdStatusCodeValuePeiHandoffToDxe)\r
95276127 338 );\r
339\r
e98cd821
LG
340 DEBUG_CODE_BEGIN ();\r
341\r
342 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;\r
343 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);\r
344 \r
345 if (PtrPeImage.Pe32->FileHeader.Machine != IMAGE_FILE_MACHINE_IA64) {\r
91d92e25 346 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, (VOID *)(UINTN)DxeCoreEntryPoint));\r
e98cd821
LG
347 } else {\r
348 //\r
349 // For IPF Image, the real entry point should be print.\r
350 //\r
91d92e25 351 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
352 }\r
353\r
354 DEBUG_CODE_END ();\r
95276127 355 //\r
356 // Transfer control to the DXE Core\r
357 // The handoff state is simply a pointer to the HOB list\r
358 //\r
95276127 359 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);\r
360 //\r
361 // If we get here, then the DXE Core returned. This is an error\r
362 // Dxe Core should not return.\r
363 //\r
364 ASSERT (FALSE);\r
365 CpuDeadLoop ();\r
366\r
367 return EFI_OUT_OF_RESOURCES;\r
368}\r
369\r
91d92e25 370\r
371\r
372\r
b0d803fe 373/**\r
288f9b38 374 Find DxeCore driver from all First Volumes.\r
b0d803fe 375\r
b0d803fe 376 @param FileHandle Pointer to FFS file to search.\r
377 \r
378 @return EFI_SUCESS Success to find the FFS in specificed FV\r
379 @return others Fail to find the FFS in specificed FV\r
91d92e25 380\r
381**/\r
b0d803fe 382EFI_STATUS\r
288f9b38 383DxeIplFindDxeCore (\r
b0d803fe 384 OUT EFI_PEI_FILE_HANDLE *FileHandle\r
385 )\r
95276127 386{\r
288f9b38
LG
387 EFI_STATUS Status;\r
388 EFI_STATUS FileStatus;\r
389 UINTN Instance;\r
390 EFI_PEI_FV_HANDLE VolumeHandle;\r
391 \r
392 Instance = 0;\r
393 *FileHandle = NULL;\r
95276127 394\r
b0d803fe 395 do {\r
288f9b38
LG
396 Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);\r
397 if (!EFI_ERROR (Status)) {\r
398 FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);\r
399 if (!EFI_ERROR (FileStatus)) {\r
400 return FileStatus;\r
95276127 401 }\r
402 }\r
288f9b38 403 } while (!EFI_ERROR (Status));\r
b0d803fe 404\r
288f9b38 405 return EFI_NOT_FOUND;\r
95276127 406}\r
407\r
91d92e25 408\r
409\r
410\r
b0d803fe 411/**\r
412 Loads and relocates a PE/COFF image into memory.\r
413\r
414 @param FileHandle The image file handle\r
415 @param ImageAddress The base address of the relocated PE/COFF image\r
416 @param ImageSize The size of the relocated PE/COFF image\r
417 @param EntryPoint The entry point of the relocated PE/COFF image\r
418 \r
419 @return EFI_SUCCESS The file was loaded and relocated\r
420 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
91d92e25 421\r
b0d803fe 422**/\r
95276127 423EFI_STATUS\r
424PeiLoadFile (\r
b0d803fe 425 IN EFI_PEI_FILE_HANDLE FileHandle,\r
95276127 426 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
427 OUT UINT64 *ImageSize,\r
428 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
429 )\r
b0d803fe 430{\r
95276127 431\r
b0d803fe 432 EFI_STATUS Status;\r
433 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
434 VOID *Pe32Data;\r
b0d803fe 435 //\r
6b978d16 436 // First try to find the PE32 section in this ffs file.\r
b0d803fe 437 //\r
438 Status = PeiServicesFfsFindSectionData (\r
439 EFI_SECTION_PE32,\r
440 FileHandle,\r
441 &Pe32Data\r
442 );\r
b0d803fe 443 \r
444 if (EFI_ERROR (Status)) {\r
445 //\r
446 // NO image types we support so exit.\r
447 //\r
448 return Status;\r
449 }\r
95276127 450\r
451 ZeroMem (&ImageContext, sizeof (ImageContext));\r
452 ImageContext.Handle = Pe32Data;\r
453 Status = GetImageReadFunction (&ImageContext);\r
454\r
455 ASSERT_EFI_ERROR (Status);\r
456\r
3d7b0992 457 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
95276127 458 if (EFI_ERROR (Status)) {\r
459 return Status;\r
460 }\r
461 //\r
462 // Allocate Memory for the image\r
463 //\r
464 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
465 ASSERT (ImageContext.ImageAddress != 0);\r
466\r
467 //\r
468 // Load the image to our new buffer\r
469 //\r
3d7b0992 470 Status = PeCoffLoaderLoadImage (&ImageContext);\r
95276127 471 if (EFI_ERROR (Status)) {\r
472 return Status;\r
473 }\r
474 //\r
475 // Relocate the image in our new buffer\r
476 //\r
3d7b0992 477 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
95276127 478 if (EFI_ERROR (Status)) {\r
479 return Status;\r
480 }\r
481\r
482 //\r
483 // Flush the instruction cache so the image data is written before we execute it\r
484 //\r
485 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
486\r
487 *ImageAddress = ImageContext.ImageAddress;\r
488 *ImageSize = ImageContext.ImageSize;\r
489 *EntryPoint = ImageContext.EntryPoint;\r
490\r
491 return EFI_SUCCESS;\r
492}\r
493\r
91d92e25 494\r
495\r
496\r
d8c79a81
LG
497/**\r
498 The ExtractSection() function processes the input section and\r
499 returns a pointer to the section contents. If the section being\r
500 extracted does not require processing (if the section\r
501 GuidedSectionHeader.Attributes has the\r
502 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
503 OutputBuffer is just updated to point to the start of the\r
504 section's contents. Otherwise, *Buffer must be allocated\r
505 from PEI permanent memory.\r
506\r
507 @param This Indicates the\r
508 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
509 Buffer containing the input GUIDed section to be\r
510 processed. OutputBuffer OutputBuffer is\r
511 allocated from PEI permanent memory and contains\r
512 the new section stream.\r
91d92e25 513 @param InputSection A pointer to the input buffer, which contains\r
514 the input section to be processed.\r
515 @param OutputBuffer A pointer to a caller-allocated buffer, whose\r
516 size is specified by the contents of OutputSize.\r
d8c79a81
LG
517 @param OutputSize A pointer to a caller-allocated\r
518 UINTN in which the size of *OutputBuffer\r
519 allocation is stored. If the function\r
520 returns anything other than EFI_SUCCESS,\r
521 the value of OutputSize is undefined.\r
d8c79a81
LG
522 @param AuthenticationStatus A pointer to a caller-allocated\r
523 UINT32 that indicates the\r
524 authentication status of the\r
525 output buffer. If the input\r
526 section's GuidedSectionHeader.\r
527 Attributes field has the\r
528 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
529 bit as clear,\r
530 AuthenticationStatus must return\r
531 zero. These bits reflect the\r
532 status of the extraction\r
533 operation. If the function\r
534 returns anything other than\r
535 EFI_SUCCESS, the value of\r
536 AuthenticationStatus is\r
537 undefined.\r
538 \r
539 @retval EFI_SUCCESS The InputSection was\r
540 successfully processed and the\r
541 section contents were returned.\r
542 \r
543 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
544 resources to process the request.\r
545 \r
708919be 546 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
d8c79a81
LG
547 not match this instance of the\r
548 GUIDed Section Extraction PPI.\r
91d92e25 549\r
d8c79a81
LG
550**/\r
551EFI_STATUS\r
18fd8d65 552CustomGuidedSectionExtract (\r
d8c79a81
LG
553 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
554 IN CONST VOID *InputSection,\r
555 OUT VOID **OutputBuffer,\r
556 OUT UINTN *OutputSize,\r
557 OUT UINT32 *AuthenticationStatus\r
558)\r
559{\r
560 EFI_STATUS Status;\r
561 UINT8 *ScratchBuffer;\r
18fd8d65
LG
562 UINT32 ScratchBufferSize;\r
563 UINT32 OutputBufferSize;\r
564 UINT16 SectionAttribute;\r
d8c79a81
LG
565 \r
566 //\r
18fd8d65 567 // Init local variable\r
d8c79a81 568 //\r
18fd8d65
LG
569 ScratchBuffer = NULL;\r
570\r
d8c79a81 571 //\r
18fd8d65 572 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 573 //\r
18fd8d65
LG
574 Status = ExtractGuidedSectionGetInfo (\r
575 InputSection,\r
576 &OutputBufferSize,\r
577 &ScratchBufferSize,\r
578 &SectionAttribute\r
579 );\r
580 \r
d8c79a81 581 if (EFI_ERROR (Status)) {\r
91d92e25 582 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
18fd8d65
LG
583 return Status;\r
584 }\r
585 \r
586 if (ScratchBufferSize != 0) {\r
95276127 587 //\r
18fd8d65 588 // Allocate scratch buffer\r
95276127 589 //\r
18fd8d65
LG
590 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
591 if (ScratchBuffer == NULL) {\r
592 return EFI_OUT_OF_RESOURCES;\r
593 }\r
d8c79a81 594 }\r
95276127 595\r
708919be 596 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) { \r
18fd8d65
LG
597 //\r
598 // Allocate output buffer\r
599 //\r
288f9b38 600 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
18fd8d65
LG
601 if (*OutputBuffer == NULL) {\r
602 return EFI_OUT_OF_RESOURCES;\r
603 }\r
91d92e25 604 DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
288f9b38
LG
605 //\r
606 // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
607 // skip EFI section header to make section data at page alignment.\r
608 //\r
609 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
95276127 610 }\r
18fd8d65
LG
611 \r
612 Status = ExtractGuidedSectionDecode (\r
613 InputSection, \r
614 OutputBuffer,\r
615 ScratchBuffer,\r
616 AuthenticationStatus\r
617 );\r
95276127 618\r
d8c79a81
LG
619 if (EFI_ERROR (Status)) {\r
620 //\r
18fd8d65 621 // Decode failed\r
d8c79a81 622 //\r
91d92e25 623 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
d8c79a81
LG
624 return Status;\r
625 }\r
626 \r
18fd8d65
LG
627 *OutputSize = (UINTN) OutputBufferSize;\r
628 \r
95276127 629 return EFI_SUCCESS;\r
630}\r
b0d803fe 631\r
91d92e25 632\r
633\r
634/**\r
635 Decompresses a section to the output buffer.\r
636\r
637 This function lookes up the compression type field in the input section and\r
638 applies the appropriate compression algorithm to compress the section to a\r
639 callee allocated buffer.\r
640 \r
641 @param This Points to this instance of the\r
642 EFI_PEI_DECOMPRESS_PEI PPI.\r
643 @param CompressionSection Points to the compressed section.\r
644 @param OutputBuffer Holds the returned pointer to the decompressed\r
645 sections.\r
646 @param OutputSize Holds the returned size of the decompress\r
647 section streams.\r
648 \r
649 @retval EFI_SUCCESS The section was decompressed successfully.\r
650 OutputBuffer contains the resulting data and\r
651 OutputSize contains the resulting size.\r
652\r
653**/\r
b0d803fe 654EFI_STATUS\r
655EFIAPI \r
656Decompress (\r
657 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
658 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
659 OUT VOID **OutputBuffer,\r
660 OUT UINTN *OutputSize\r
661 )\r
662{\r
663 EFI_STATUS Status;\r
664 UINT8 *DstBuffer;\r
665 UINT8 *ScratchBuffer;\r
666 UINTN DstBufferSize;\r
667 UINT32 ScratchBufferSize;\r
668 EFI_COMMON_SECTION_HEADER *Section;\r
669 UINTN SectionLength;\r
670\r
671 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
672 ASSERT (FALSE);\r
673 return EFI_INVALID_PARAMETER;\r
674 }\r
675\r
676 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;\r
677 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;\r
678 \r
679 //\r
680 // This is a compression set, expand it\r
681 //\r
682 switch (CompressionSection->CompressionType) {\r
683 case EFI_STANDARD_COMPRESSION:\r
684 //\r
685 // Load EFI standard compression.\r
686 // For compressed data, decompress them to dstbuffer.\r
687 //\r
688 Status = UefiDecompressGetInfo (\r
689 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
690 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),\r
691 (UINT32 *) &DstBufferSize,\r
692 &ScratchBufferSize\r
693 );\r
694 if (EFI_ERROR (Status)) {\r
695 //\r
696 // GetInfo failed\r
697 //\r
91d92e25 698 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
b0d803fe 699 return EFI_NOT_FOUND;\r
700 }\r
701 //\r
702 // Allocate scratch buffer\r
703 //\r
704 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
705 if (ScratchBuffer == NULL) {\r
706 return EFI_OUT_OF_RESOURCES;\r
707 }\r
708 //\r
288f9b38 709 // Allocate destination buffer, extra one page for adjustment \r
b0d803fe 710 //\r
288f9b38 711 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 712 if (DstBuffer == NULL) {\r
713 return EFI_OUT_OF_RESOURCES;\r
714 }\r
715 //\r
288f9b38
LG
716 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
717 // to make section data at page alignment.\r
718 //\r
719 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
720 //\r
b0d803fe 721 // Call decompress function\r
722 //\r
723 Status = UefiDecompress (\r
724 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),\r
725 DstBuffer,\r
726 ScratchBuffer\r
727 );\r
728 if (EFI_ERROR (Status)) {\r
729 //\r
730 // Decompress failed\r
731 //\r
91d92e25 732 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
b0d803fe 733 return EFI_NOT_FOUND;\r
734 }\r
735 break;\r
736\r
b0d803fe 737 case EFI_NOT_COMPRESSED:\r
738 //\r
739 // Allocate destination buffer\r
740 //\r
741 DstBufferSize = CompressionSection->UncompressedLength;\r
288f9b38 742 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 743 if (DstBuffer == NULL) {\r
744 return EFI_OUT_OF_RESOURCES;\r
745 }\r
746 //\r
288f9b38
LG
747 // Adjust DstBuffer offset, skip EFI section header\r
748 // to make section data at page alignment.\r
749 //\r
750 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
751 //\r
b0d803fe 752 // stream is not actually compressed, just encapsulated. So just copy it.\r
753 //\r
754 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);\r
755 break;\r
756\r
757 default:\r
758 //\r
759 // Don't support other unknown compression type.\r
760 //\r
761 ASSERT (FALSE);\r
762 return EFI_NOT_FOUND;\r
763 }\r
764\r
765 *OutputSize = DstBufferSize;\r
766 *OutputBuffer = DstBuffer;\r
767\r
768 return EFI_SUCCESS;\r
769}\r
770\r
91d92e25 771\r
772\r
773\r
774/**\r
775 Updates the Stack HOB passed to DXE phase.\r
776\r
777 This function traverses the whole HOB list and update the stack HOB to\r
778 reflect the real stack that is used by DXE core.\r
779\r
780 @param BaseAddress The lower address of stack used by DxeCore.\r
781 @param Length The length of stack used by DxeCore.\r
782\r
783**/\r
30c8f861 784VOID\r
785UpdateStackHob (\r
786 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
787 IN UINT64 Length\r
788 )\r
789{\r
790 EFI_PEI_HOB_POINTERS Hob;\r
791\r
792 Hob.Raw = GetHobList ();\r
793 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
794 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
795 //\r
796 // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type\r
797 // to be reclaimed by DXE core.\r
798 //\r
799 BuildMemoryAllocationHob (\r
800 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
801 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
802 EfiConventionalMemory\r
803 );\r
804 //\r
805 // Update the BSP Stack Hob to reflect the new stack info.\r
806 //\r
807 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
808 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
809 break;\r
810 }\r
811 Hob.Raw = GET_NEXT_HOB (Hob);\r
812 }\r
813}\r