]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Add missing status code in several modules.
[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
37623a5c 5Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 6This program and the accompanying materials\r
95276127 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
95276127 18\r
19//\r
48557c65 20// Module Globals used in the DXE to PEI hand off\r
95276127 21// These must be module globals, so the stack can be switched\r
22//\r
9b937a73 23CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
95276127 24 DxeLoadCore\r
25};\r
26\r
9b937a73 27CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
18fd8d65 28 CustomGuidedSectionExtract\r
95276127 29};\r
30\r
9b937a73 31CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
b0d803fe 32 Decompress\r
d8c79a81
LG
33};\r
34\r
48557c65 35CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
95276127 36 {\r
b0d803fe 37 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
38 &gEfiDxeIplPpiGuid,\r
9b937a73 39 (VOID *) &mDxeIplPpi\r
95276127 40 },\r
41 {\r
b0d803fe 42 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
43 &gEfiPeiDecompressPpiGuid,\r
9b937a73 44 (VOID *) &mDecompressPpi\r
95276127 45 }\r
46};\r
47\r
48557c65 48CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {\r
95276127 49 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
50 &gEfiEndOfPeiSignalPpiGuid,\r
51 NULL\r
52};\r
53\r
b0d803fe 54/**\r
48557c65 55 Entry point of DXE IPL PEIM.\r
56 \r
57 This function installs DXE IPL PPI and Decompress PPI. It also reloads\r
58 itself to memory on non-S3 resume boot path.\r
b0d803fe 59\r
a55caa53
LG
60 @param FileHandle Handle of the file being invoked.\r
61 @param PeiServices Describes the list of possible PEI Services.\r
91d92e25 62\r
48557c65 63 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.\r
64 @retval Others Some error occurs during the execution of this function. \r
65\r
91d92e25 66**/\r
95276127 67EFI_STATUS\r
68EFIAPI\r
69PeimInitializeDxeIpl (\r
a55caa53
LG
70 IN EFI_PEI_FILE_HANDLE FileHandle,\r
71 IN CONST EFI_PEI_SERVICES **PeiServices\r
95276127 72 )\r
95276127 73{\r
74 EFI_STATUS Status;\r
95276127 75 EFI_BOOT_MODE BootMode;\r
18fd8d65
LG
76 EFI_GUID *ExtractHandlerGuidTable;\r
77 UINTN ExtractHandlerNumber;\r
d8c79a81
LG
78 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;\r
79 \r
b98da1b1 80 BootMode = GetBootModeHob ();\r
95276127 81\r
b0d803fe 82 if (BootMode != BOOT_ON_S3_RESUME) {\r
a55caa53 83 Status = PeiServicesRegisterForShadow (FileHandle);\r
b0d803fe 84 if (Status == EFI_SUCCESS) {\r
b0d803fe 85 //\r
48557c65 86 // EFI_SUCESS means it is the first time to call register for shadow. \r
b0d803fe 87 // \r
88 return Status;\r
48557c65 89 }\r
90 \r
91 //\r
92 // Ensure that DXE IPL is shadowed to permanent memory.\r
93 //\r
94 ASSERT (Status == EFI_ALREADY_STARTED);\r
b98da1b1 95 \r
48557c65 96 //\r
97 // Get custom extract guided section method guid list \r
98 //\r
99 ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
100 \r
101 //\r
102 // Install custom extraction guid PPI\r
103 //\r
104 if (ExtractHandlerNumber > 0) {\r
105 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
106 ASSERT (GuidPpi != NULL);\r
107 while (ExtractHandlerNumber-- > 0) {\r
108 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
109 GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;\r
110 GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];\r
111 Status = PeiServicesInstallPpi (GuidPpi++);\r
112 ASSERT_EFI_ERROR(Status);\r
b0d803fe 113 }\r
d8c79a81 114 }\r
48557c65 115 \r
95276127 116 }\r
117 \r
b0d803fe 118 //\r
288f9b38 119 // Install DxeIpl and Decompress PPIs.\r
b0d803fe 120 //\r
121 Status = PeiServicesInstallPpi (mPpiList);\r
288f9b38
LG
122 ASSERT_EFI_ERROR(Status);\r
123\r
95276127 124 return Status;\r
125}\r
126\r
a95b6045
ED
127/**\r
128 Validate variable data for the MemoryTypeInformation. \r
129\r
130 @param MemoryData Variable data.\r
131 @param MemoryDataSize Variable data length.\r
132\r
133 @return TRUE The variable data is valid.\r
134 @return FALSE The variable data is invalid.\r
135\r
136**/\r
137BOOLEAN\r
138ValidateMemoryTypeInfoVariable (\r
139 IN EFI_MEMORY_TYPE_INFORMATION *MemoryData,\r
140 IN UINTN MemoryDataSize\r
141 )\r
142{\r
143 UINTN Count;\r
144 UINTN Index;\r
145\r
146 // Check the input parameter.\r
147 if (MemoryData == NULL) {\r
148 return FALSE;\r
149 }\r
150\r
151 // Get Count\r
152 Count = MemoryDataSize / sizeof (*MemoryData);\r
153\r
154 // Check Size\r
155 if (Count * sizeof(*MemoryData) != MemoryDataSize) {\r
156 return FALSE;\r
157 }\r
158\r
159 // Check last entry type filed.\r
160 if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {\r
161 return FALSE;\r
162 }\r
163\r
164 // Check the type filed.\r
165 for (Index = 0; Index < Count - 1; Index++) {\r
166 if (MemoryData[Index].Type >= EfiMaxMemoryType) {\r
167 return FALSE;\r
168 }\r
169 }\r
170\r
171 return TRUE;\r
172}\r
173\r
b0d803fe 174/**\r
b98da1b1 175 Main entry point to last PEIM. \r
48557c65 176\r
177 This function finds DXE Core in the firmware volume and transfer the control to\r
178 DXE core.\r
b0d803fe 179 \r
b98da1b1 180 @param This Entry point for DXE IPL PPI.\r
b0d803fe 181 @param PeiServices General purpose services available to every PEIM.\r
b98da1b1 182 @param HobList Address to the Pei HOB list.\r
b0d803fe 183 \r
184 @return EFI_SUCCESS DXE core was successfully loaded. \r
185 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.\r
91d92e25 186\r
b0d803fe 187**/\r
95276127 188EFI_STATUS\r
189EFIAPI\r
190DxeLoadCore (\r
1f3a753e 191 IN CONST EFI_DXE_IPL_PPI *This,\r
95276127 192 IN EFI_PEI_SERVICES **PeiServices,\r
193 IN EFI_PEI_HOB_POINTERS HobList\r
194 )\r
95276127 195{\r
196 EFI_STATUS Status;\r
b6b98e91 197 EFI_FV_FILE_INFO DxeCoreFileInfo;\r
95276127 198 EFI_PHYSICAL_ADDRESS DxeCoreAddress;\r
199 UINT64 DxeCoreSize;\r
200 EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint;\r
95276127 201 EFI_BOOT_MODE BootMode;\r
b0d803fe 202 EFI_PEI_FILE_HANDLE FileHandle;\r
b74350e9 203 EFI_PEI_READ_ONLY_VARIABLE2_PPI *Variable;\r
28efc722 204 EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
205 UINTN Instance;\r
206 UINT32 AuthenticationState;\r
b74350e9 207 UINTN DataSize;\r
77215d10 208 EFI_PEI_S3_RESUME2_PPI *S3Resume;\r
28efc722 209 EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery;\r
708919be 210 EFI_MEMORY_TYPE_INFORMATION MemoryData[EfiMaxMemoryType + 1];\r
95276127 211\r
212 //\r
213 // if in S3 Resume, restore configure\r
214 //\r
b98da1b1 215 BootMode = GetBootModeHob ();\r
95276127 216\r
217 if (BootMode == BOOT_ON_S3_RESUME) {\r
28efc722 218 Status = PeiServicesLocatePpi (\r
77215d10 219 &gEfiPeiS3Resume2PpiGuid,\r
28efc722 220 0,\r
221 NULL,\r
222 (VOID **) &S3Resume\r
223 );\r
37623a5c 224 if (EFI_ERROR (Status)) {\r
225 //\r
226 // Report Status code that S3Resume PPI can not be found\r
227 //\r
228 REPORT_STATUS_CODE (\r
229 EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
230 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_S3_RESUME_PPI_NOT_FOUND)\r
231 );\r
232 }\r
28efc722 233 ASSERT_EFI_ERROR (Status);\r
234 \r
77215d10 235 Status = S3Resume->S3RestoreConfig2 (S3Resume);\r
95276127 236 ASSERT_EFI_ERROR (Status);\r
237 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
37623a5c 238 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_RECOVERY_BEGIN));\r
28efc722 239 Status = PeiServicesLocatePpi (\r
240 &gEfiPeiRecoveryModulePpiGuid,\r
241 0,\r
242 NULL,\r
243 (VOID **) &PeiRecovery\r
244 );\r
37623a5c 245 //\r
246 // Report Status code the failure of locating Recovery PPI \r
247 //\r
248 REPORT_STATUS_CODE (\r
249 EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
250 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_RECOVERY_PPI_NOT_FOUND)\r
251 ); \r
28efc722 252 ASSERT_EFI_ERROR (Status);\r
37623a5c 253 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_LOAD));\r
28efc722 254 Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);\r
95276127 255 if (EFI_ERROR (Status)) {\r
91d92e25 256 DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
37623a5c 257 //\r
258 // Report Status code that S3Resume PPI can not be found\r
259 //\r
260 REPORT_STATUS_CODE (\r
261 EFI_ERROR_CODE | EFI_ERROR_MAJOR,\r
262 (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_EC_NO_RECOVERY_CAPSULE)\r
263 );\r
95276127 264 CpuDeadLoop ();\r
265 }\r
37623a5c 266 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_CAPSULE_START));\r
95276127 267 //\r
48557c65 268 // Now should have a HOB with the DXE core\r
95276127 269 //\r
270 }\r
288f9b38 271\r
b74350e9 272 Status = PeiServicesLocatePpi (\r
273 &gEfiPeiReadOnlyVariable2PpiGuid,\r
274 0,\r
275 NULL,\r
276 (VOID **)&Variable\r
277 );\r
b74350e9 278 if (!EFI_ERROR (Status)) {\r
1ad76c34 279 DataSize = sizeof (MemoryData);\r
280 Status = Variable->GetVariable ( \r
281 Variable, \r
282 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
283 &gEfiMemoryTypeInformationGuid,\r
284 NULL,\r
285 &DataSize,\r
286 &MemoryData\r
287 );\r
a95b6045 288 if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {\r
1ad76c34 289 //\r
290 // Build the GUID'd HOB for DXE\r
291 //\r
292 BuildGuidDataHob (\r
293 &gEfiMemoryTypeInformationGuid,\r
294 MemoryData,\r
295 DataSize\r
296 );\r
297 }\r
b74350e9 298 }\r
288f9b38 299\r
95276127 300 //\r
b6b98e91 301 // Look in all the FVs present in PEI and find the DXE Core FileHandle\r
95276127 302 //\r
b6b98e91 303 FileHandle = DxeIplFindDxeCore ();\r
b0d803fe 304\r
95276127 305 //\r
28efc722 306 // Load the DXE Core from a Firmware Volume.\r
95276127 307 //\r
28efc722 308 Instance = 0;\r
309 do {\r
310 Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);\r
311 //\r
312 // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.\r
313 //\r
314 ASSERT_EFI_ERROR (Status);\r
315\r
316 Status = LoadFile->LoadFile (\r
317 LoadFile,\r
318 FileHandle,\r
319 &DxeCoreAddress,\r
320 &DxeCoreSize,\r
321 &DxeCoreEntryPoint,\r
322 &AuthenticationState\r
323 );\r
324 } while (EFI_ERROR (Status));\r
95276127 325\r
b6b98e91 326 //\r
327 // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.\r
328 //\r
329 Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);\r
330 ASSERT_EFI_ERROR (Status);\r
331\r
95276127 332 //\r
333 // Add HOB for the DXE Core\r
334 //\r
335 BuildModuleHob (\r
b6b98e91 336 &DxeCoreFileInfo.FileName,\r
95276127 337 DxeCoreAddress,\r
48557c65 338 ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),\r
95276127 339 DxeCoreEntryPoint\r
340 );\r
341\r
342 //\r
343 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
344 //\r
f9876ecf 345 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));\r
95276127 346\r
4e2dd553 347 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
e98cd821 348\r
95276127 349 //\r
350 // Transfer control to the DXE Core\r
48557c65 351 // The hand off state is simply a pointer to the HOB list\r
95276127 352 //\r
9b937a73 353 HandOffToDxeCore (DxeCoreEntryPoint, HobList);\r
95276127 354 //\r
355 // If we get here, then the DXE Core returned. This is an error\r
48557c65 356 // DxeCore should not return.\r
95276127 357 //\r
358 ASSERT (FALSE);\r
359 CpuDeadLoop ();\r
360\r
361 return EFI_OUT_OF_RESOURCES;\r
362}\r
363\r
91d92e25 364\r
b0d803fe 365/**\r
9b937a73 366 Searches DxeCore in all firmware Volumes and loads the first\r
367 instance that contains DxeCore.\r
b0d803fe 368\r
9b937a73 369 @return FileHandle of DxeCore to load DxeCore.\r
370 \r
91d92e25 371**/\r
9b937a73 372EFI_PEI_FILE_HANDLE\r
288f9b38 373DxeIplFindDxeCore (\r
b6b98e91 374 VOID\r
b0d803fe 375 )\r
95276127 376{\r
9b937a73 377 EFI_STATUS Status;\r
378 UINTN Instance;\r
379 EFI_PEI_FV_HANDLE VolumeHandle;\r
380 EFI_PEI_FILE_HANDLE FileHandle;\r
288f9b38
LG
381 \r
382 Instance = 0;\r
9b937a73 383 while (TRUE) {\r
384 //\r
385 // Traverse all firmware volume instances\r
386 //\r
387 Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
388 //\r
389 // If some error occurs here, then we cannot find any firmware\r
390 // volume that may contain DxeCore.\r
391 //\r
3d0a2385 392 if (EFI_ERROR (Status)) {\r
393 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));\r
394 }\r
9b937a73 395 ASSERT_EFI_ERROR (Status);\r
396 \r
397 //\r
398 // Find the DxeCore file type from the beginning in this firmware volume.\r
399 //\r
400 FileHandle = NULL;\r
401 Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);\r
288f9b38 402 if (!EFI_ERROR (Status)) {\r
9b937a73 403 //\r
b6b98e91 404 // Find DxeCore FileHandle in this volume, then we skip other firmware volume and\r
405 // return the FileHandle.\r
9b937a73 406 //\r
b6b98e91 407 return FileHandle;\r
95276127 408 }\r
9b937a73 409 //\r
410 // We cannot find DxeCore in this firmware volume, then search the next volume.\r
411 //\r
412 Instance++;\r
413 }\r
95276127 414}\r
415\r
91d92e25 416\r
91d92e25 417\r
d8c79a81
LG
418/**\r
419 The ExtractSection() function processes the input section and\r
420 returns a pointer to the section contents. If the section being\r
421 extracted does not require processing (if the section\r
422 GuidedSectionHeader.Attributes has the\r
423 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
424 OutputBuffer is just updated to point to the start of the\r
425 section's contents. Otherwise, *Buffer must be allocated\r
426 from PEI permanent memory.\r
427\r
428 @param This Indicates the\r
429 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
430 Buffer containing the input GUIDed section to be\r
431 processed. OutputBuffer OutputBuffer is\r
432 allocated from PEI permanent memory and contains\r
433 the new section stream.\r
91d92e25 434 @param InputSection A pointer to the input buffer, which contains\r
435 the input section to be processed.\r
436 @param OutputBuffer A pointer to a caller-allocated buffer, whose\r
437 size is specified by the contents of OutputSize.\r
d8c79a81
LG
438 @param OutputSize A pointer to a caller-allocated\r
439 UINTN in which the size of *OutputBuffer\r
440 allocation is stored. If the function\r
441 returns anything other than EFI_SUCCESS,\r
442 the value of OutputSize is undefined.\r
d8c79a81
LG
443 @param AuthenticationStatus A pointer to a caller-allocated\r
444 UINT32 that indicates the\r
445 authentication status of the\r
446 output buffer. If the input\r
447 section's GuidedSectionHeader.\r
448 Attributes field has the\r
449 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
450 bit as clear,\r
451 AuthenticationStatus must return\r
452 zero. These bits reflect the\r
453 status of the extraction\r
454 operation. If the function\r
455 returns anything other than\r
456 EFI_SUCCESS, the value of\r
457 AuthenticationStatus is\r
458 undefined.\r
459 \r
460 @retval EFI_SUCCESS The InputSection was\r
461 successfully processed and the\r
462 section contents were returned.\r
463 \r
464 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
465 resources to process the request.\r
466 \r
708919be 467 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
d8c79a81
LG
468 not match this instance of the\r
469 GUIDed Section Extraction PPI.\r
91d92e25 470\r
d8c79a81
LG
471**/\r
472EFI_STATUS\r
6d3ea23f 473EFIAPI\r
18fd8d65 474CustomGuidedSectionExtract (\r
d8c79a81
LG
475 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
476 IN CONST VOID *InputSection,\r
477 OUT VOID **OutputBuffer,\r
478 OUT UINTN *OutputSize,\r
479 OUT UINT32 *AuthenticationStatus\r
480)\r
481{\r
482 EFI_STATUS Status;\r
483 UINT8 *ScratchBuffer;\r
18fd8d65
LG
484 UINT32 ScratchBufferSize;\r
485 UINT32 OutputBufferSize;\r
486 UINT16 SectionAttribute;\r
d8c79a81
LG
487 \r
488 //\r
18fd8d65 489 // Init local variable\r
d8c79a81 490 //\r
18fd8d65
LG
491 ScratchBuffer = NULL;\r
492\r
d8c79a81 493 //\r
18fd8d65 494 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 495 //\r
18fd8d65 496 Status = ExtractGuidedSectionGetInfo (\r
b6b98e91 497 InputSection,\r
498 &OutputBufferSize,\r
499 &ScratchBufferSize,\r
500 &SectionAttribute\r
501 );\r
18fd8d65 502 \r
d8c79a81 503 if (EFI_ERROR (Status)) {\r
91d92e25 504 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
18fd8d65
LG
505 return Status;\r
506 }\r
507 \r
508 if (ScratchBufferSize != 0) {\r
95276127 509 //\r
18fd8d65 510 // Allocate scratch buffer\r
95276127 511 //\r
18fd8d65
LG
512 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
513 if (ScratchBuffer == NULL) {\r
514 return EFI_OUT_OF_RESOURCES;\r
515 }\r
d8c79a81 516 }\r
95276127 517\r
708919be 518 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) { \r
18fd8d65
LG
519 //\r
520 // Allocate output buffer\r
521 //\r
288f9b38 522 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
18fd8d65
LG
523 if (*OutputBuffer == NULL) {\r
524 return EFI_OUT_OF_RESOURCES;\r
525 }\r
48557c65 526 DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
288f9b38
LG
527 //\r
528 // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
529 // skip EFI section header to make section data at page alignment.\r
530 //\r
531 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
95276127 532 }\r
18fd8d65
LG
533 \r
534 Status = ExtractGuidedSectionDecode (\r
535 InputSection, \r
536 OutputBuffer,\r
537 ScratchBuffer,\r
538 AuthenticationStatus\r
48557c65 539 );\r
d8c79a81
LG
540 if (EFI_ERROR (Status)) {\r
541 //\r
18fd8d65 542 // Decode failed\r
d8c79a81 543 //\r
91d92e25 544 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
d8c79a81
LG
545 return Status;\r
546 }\r
547 \r
18fd8d65
LG
548 *OutputSize = (UINTN) OutputBufferSize;\r
549 \r
95276127 550 return EFI_SUCCESS;\r
551}\r
b0d803fe 552\r
91d92e25 553\r
554\r
555/**\r
556 Decompresses a section to the output buffer.\r
557\r
48557c65 558 This function looks up the compression type field in the input section and\r
91d92e25 559 applies the appropriate compression algorithm to compress the section to a\r
560 callee allocated buffer.\r
561 \r
562 @param This Points to this instance of the\r
563 EFI_PEI_DECOMPRESS_PEI PPI.\r
564 @param CompressionSection Points to the compressed section.\r
565 @param OutputBuffer Holds the returned pointer to the decompressed\r
566 sections.\r
567 @param OutputSize Holds the returned size of the decompress\r
568 section streams.\r
569 \r
570 @retval EFI_SUCCESS The section was decompressed successfully.\r
571 OutputBuffer contains the resulting data and\r
572 OutputSize contains the resulting size.\r
573\r
574**/\r
b0d803fe 575EFI_STATUS\r
576EFIAPI \r
577Decompress (\r
578 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
579 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
580 OUT VOID **OutputBuffer,\r
581 OUT UINTN *OutputSize\r
582 )\r
583{\r
584 EFI_STATUS Status;\r
585 UINT8 *DstBuffer;\r
586 UINT8 *ScratchBuffer;\r
635021c5 587 UINT32 DstBufferSize;\r
b0d803fe 588 UINT32 ScratchBufferSize;\r
890e5417
SZ
589 VOID *CompressionSource;\r
590 UINT32 CompressionSourceSize;\r
591 UINT32 UncompressedLength;\r
592 UINT8 CompressionType;\r
b0d803fe 593\r
594 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
595 ASSERT (FALSE);\r
596 return EFI_INVALID_PARAMETER;\r
597 }\r
598\r
890e5417
SZ
599 if (IS_SECTION2 (CompressionSection)) {\r
600 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));\r
601 CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));\r
602 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;\r
603 CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;\r
604 } else {\r
605 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));\r
606 CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));\r
607 UncompressedLength = CompressionSection->UncompressedLength;\r
608 CompressionType = CompressionSection->CompressionType;\r
609 }\r
b0d803fe 610 \r
611 //\r
612 // This is a compression set, expand it\r
613 //\r
890e5417 614 switch (CompressionType) {\r
b0d803fe 615 case EFI_STANDARD_COMPRESSION:\r
873b7997 616 if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {\r
b0d803fe 617 //\r
873b7997 618 // Load EFI standard compression.\r
619 // For compressed data, decompress them to destination buffer.\r
b0d803fe 620 //\r
873b7997 621 Status = UefiDecompressGetInfo (\r
890e5417
SZ
622 CompressionSource,\r
623 CompressionSourceSize,\r
635021c5 624 &DstBufferSize,\r
873b7997 625 &ScratchBufferSize\r
626 );\r
627 if (EFI_ERROR (Status)) {\r
628 //\r
629 // GetInfo failed\r
630 //\r
631 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
632 return EFI_NOT_FOUND;\r
633 }\r
634 //\r
635 // Allocate scratch buffer\r
b0d803fe 636 //\r
873b7997 637 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
638 if (ScratchBuffer == NULL) {\r
639 return EFI_OUT_OF_RESOURCES;\r
640 }\r
641 //\r
642 // Allocate destination buffer, extra one page for adjustment \r
643 //\r
644 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
645 if (DstBuffer == NULL) {\r
646 return EFI_OUT_OF_RESOURCES;\r
647 }\r
b0d803fe 648 //\r
873b7997 649 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
650 // to make section data at page alignment.\r
651 //\r
652 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
653 //\r
654 // Call decompress function\r
655 //\r
656 Status = UefiDecompress (\r
890e5417 657 CompressionSource,\r
873b7997 658 DstBuffer,\r
659 ScratchBuffer\r
660 );\r
661 if (EFI_ERROR (Status)) {\r
662 //\r
663 // Decompress failed\r
664 //\r
665 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
666 return EFI_NOT_FOUND;\r
667 }\r
668 break;\r
669 } else {\r
12b3e61e
LG
670 //\r
671 // PcdDxeIplSupportUefiDecompress is FALSE\r
672 // Don't support UEFI decompression algorithm.\r
673 //\r
674 ASSERT (FALSE);\r
b0d803fe 675 return EFI_NOT_FOUND;\r
676 }\r
b0d803fe 677\r
b0d803fe 678 case EFI_NOT_COMPRESSED:\r
679 //\r
680 // Allocate destination buffer\r
681 //\r
890e5417 682 DstBufferSize = UncompressedLength;\r
288f9b38 683 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 684 if (DstBuffer == NULL) {\r
685 return EFI_OUT_OF_RESOURCES;\r
686 }\r
687 //\r
288f9b38
LG
688 // Adjust DstBuffer offset, skip EFI section header\r
689 // to make section data at page alignment.\r
690 //\r
691 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
692 //\r
b0d803fe 693 // stream is not actually compressed, just encapsulated. So just copy it.\r
694 //\r
890e5417 695 CopyMem (DstBuffer, CompressionSource, DstBufferSize);\r
b0d803fe 696 break;\r
697\r
698 default:\r
699 //\r
700 // Don't support other unknown compression type.\r
701 //\r
702 ASSERT (FALSE);\r
703 return EFI_NOT_FOUND;\r
704 }\r
705\r
706 *OutputSize = DstBufferSize;\r
707 *OutputBuffer = DstBuffer;\r
708\r
709 return EFI_SUCCESS;\r
710}\r
711\r
91d92e25 712\r
91d92e25 713/**\r
714 Updates the Stack HOB passed to DXE phase.\r
715\r
716 This function traverses the whole HOB list and update the stack HOB to\r
717 reflect the real stack that is used by DXE core.\r
718\r
719 @param BaseAddress The lower address of stack used by DxeCore.\r
720 @param Length The length of stack used by DxeCore.\r
721\r
722**/\r
30c8f861 723VOID\r
724UpdateStackHob (\r
725 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
726 IN UINT64 Length\r
727 )\r
728{\r
729 EFI_PEI_HOB_POINTERS Hob;\r
730\r
731 Hob.Raw = GetHobList ();\r
732 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
733 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
734 //\r
9a43bc39 735 // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to \r
736 // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some \r
737 // PEIMs may also keep key information on stack\r
30c8f861 738 //\r
739 BuildMemoryAllocationHob (\r
740 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
741 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
9a43bc39 742 EfiBootServicesData\r
30c8f861 743 );\r
744 //\r
745 // Update the BSP Stack Hob to reflect the new stack info.\r
746 //\r
747 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
748 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
749 break;\r
750 }\r
751 Hob.Raw = GET_NEXT_HOB (Hob);\r
752 }\r
753}\r