]> 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
3d0a2385 5Copyright (c) 2006 - 2011, 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
224 ASSERT_EFI_ERROR (Status);\r
225 \r
77215d10 226 Status = S3Resume->S3RestoreConfig2 (S3Resume);\r
95276127 227 ASSERT_EFI_ERROR (Status);\r
228 } else if (BootMode == BOOT_IN_RECOVERY_MODE) {\r
28efc722 229 Status = PeiServicesLocatePpi (\r
230 &gEfiPeiRecoveryModulePpiGuid,\r
231 0,\r
232 NULL,\r
233 (VOID **) &PeiRecovery\r
234 );\r
235 ASSERT_EFI_ERROR (Status);\r
236 \r
237 Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery);\r
95276127 238 if (EFI_ERROR (Status)) {\r
91d92e25 239 DEBUG ((DEBUG_ERROR, "Load Recovery Capsule Failed.(Status = %r)\n", Status));\r
95276127 240 CpuDeadLoop ();\r
241 }\r
242\r
243 //\r
48557c65 244 // Now should have a HOB with the DXE core\r
95276127 245 //\r
246 }\r
288f9b38 247\r
b74350e9 248 Status = PeiServicesLocatePpi (\r
249 &gEfiPeiReadOnlyVariable2PpiGuid,\r
250 0,\r
251 NULL,\r
252 (VOID **)&Variable\r
253 );\r
b74350e9 254 if (!EFI_ERROR (Status)) {\r
1ad76c34 255 DataSize = sizeof (MemoryData);\r
256 Status = Variable->GetVariable ( \r
257 Variable, \r
258 EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,\r
259 &gEfiMemoryTypeInformationGuid,\r
260 NULL,\r
261 &DataSize,\r
262 &MemoryData\r
263 );\r
a95b6045 264 if (!EFI_ERROR (Status) && ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {\r
1ad76c34 265 //\r
266 // Build the GUID'd HOB for DXE\r
267 //\r
268 BuildGuidDataHob (\r
269 &gEfiMemoryTypeInformationGuid,\r
270 MemoryData,\r
271 DataSize\r
272 );\r
273 }\r
b74350e9 274 }\r
288f9b38 275\r
95276127 276 //\r
b6b98e91 277 // Look in all the FVs present in PEI and find the DXE Core FileHandle\r
95276127 278 //\r
b6b98e91 279 FileHandle = DxeIplFindDxeCore ();\r
b0d803fe 280\r
95276127 281 //\r
28efc722 282 // Load the DXE Core from a Firmware Volume.\r
95276127 283 //\r
28efc722 284 Instance = 0;\r
285 do {\r
286 Status = PeiServicesLocatePpi (&gEfiPeiLoadFilePpiGuid, Instance++, NULL, (VOID **) &LoadFile);\r
287 //\r
288 // These must exist an instance of EFI_PEI_LOAD_FILE_PPI to support to load DxeCore file handle successfully.\r
289 //\r
290 ASSERT_EFI_ERROR (Status);\r
291\r
292 Status = LoadFile->LoadFile (\r
293 LoadFile,\r
294 FileHandle,\r
295 &DxeCoreAddress,\r
296 &DxeCoreSize,\r
297 &DxeCoreEntryPoint,\r
298 &AuthenticationState\r
299 );\r
300 } while (EFI_ERROR (Status));\r
95276127 301\r
b6b98e91 302 //\r
303 // Get the DxeCore File Info from the FileHandle for the DxeCore GUID file name.\r
304 //\r
305 Status = PeiServicesFfsGetFileInfo (FileHandle, &DxeCoreFileInfo);\r
306 ASSERT_EFI_ERROR (Status);\r
307\r
95276127 308 //\r
309 // Add HOB for the DXE Core\r
310 //\r
311 BuildModuleHob (\r
b6b98e91 312 &DxeCoreFileInfo.FileName,\r
95276127 313 DxeCoreAddress,\r
48557c65 314 ALIGN_VALUE (DxeCoreSize, EFI_PAGE_SIZE),\r
95276127 315 DxeCoreEntryPoint\r
316 );\r
317\r
318 //\r
319 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT\r
320 //\r
f9876ecf 321 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_CORE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT));\r
95276127 322\r
4e2dd553 323 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%11p EntryPoint=0x%11p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));\r
e98cd821 324\r
95276127 325 //\r
326 // Transfer control to the DXE Core\r
48557c65 327 // The hand off state is simply a pointer to the HOB list\r
95276127 328 //\r
9b937a73 329 HandOffToDxeCore (DxeCoreEntryPoint, HobList);\r
95276127 330 //\r
331 // If we get here, then the DXE Core returned. This is an error\r
48557c65 332 // DxeCore should not return.\r
95276127 333 //\r
334 ASSERT (FALSE);\r
335 CpuDeadLoop ();\r
336\r
337 return EFI_OUT_OF_RESOURCES;\r
338}\r
339\r
91d92e25 340\r
b0d803fe 341/**\r
9b937a73 342 Searches DxeCore in all firmware Volumes and loads the first\r
343 instance that contains DxeCore.\r
b0d803fe 344\r
9b937a73 345 @return FileHandle of DxeCore to load DxeCore.\r
346 \r
91d92e25 347**/\r
9b937a73 348EFI_PEI_FILE_HANDLE\r
288f9b38 349DxeIplFindDxeCore (\r
b6b98e91 350 VOID\r
b0d803fe 351 )\r
95276127 352{\r
9b937a73 353 EFI_STATUS Status;\r
354 UINTN Instance;\r
355 EFI_PEI_FV_HANDLE VolumeHandle;\r
356 EFI_PEI_FILE_HANDLE FileHandle;\r
288f9b38
LG
357 \r
358 Instance = 0;\r
9b937a73 359 while (TRUE) {\r
360 //\r
361 // Traverse all firmware volume instances\r
362 //\r
363 Status = PeiServicesFfsFindNextVolume (Instance, &VolumeHandle);\r
364 //\r
365 // If some error occurs here, then we cannot find any firmware\r
366 // volume that may contain DxeCore.\r
367 //\r
3d0a2385 368 if (EFI_ERROR (Status)) {\r
369 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));\r
370 }\r
9b937a73 371 ASSERT_EFI_ERROR (Status);\r
372 \r
373 //\r
374 // Find the DxeCore file type from the beginning in this firmware volume.\r
375 //\r
376 FileHandle = NULL;\r
377 Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);\r
288f9b38 378 if (!EFI_ERROR (Status)) {\r
9b937a73 379 //\r
b6b98e91 380 // Find DxeCore FileHandle in this volume, then we skip other firmware volume and\r
381 // return the FileHandle.\r
9b937a73 382 //\r
b6b98e91 383 return FileHandle;\r
95276127 384 }\r
9b937a73 385 //\r
386 // We cannot find DxeCore in this firmware volume, then search the next volume.\r
387 //\r
388 Instance++;\r
389 }\r
95276127 390}\r
391\r
91d92e25 392\r
91d92e25 393\r
d8c79a81
LG
394/**\r
395 The ExtractSection() function processes the input section and\r
396 returns a pointer to the section contents. If the section being\r
397 extracted does not require processing (if the section\r
398 GuidedSectionHeader.Attributes has the\r
399 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
400 OutputBuffer is just updated to point to the start of the\r
401 section's contents. Otherwise, *Buffer must be allocated\r
402 from PEI permanent memory.\r
403\r
404 @param This Indicates the\r
405 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
406 Buffer containing the input GUIDed section to be\r
407 processed. OutputBuffer OutputBuffer is\r
408 allocated from PEI permanent memory and contains\r
409 the new section stream.\r
91d92e25 410 @param InputSection A pointer to the input buffer, which contains\r
411 the input section to be processed.\r
412 @param OutputBuffer A pointer to a caller-allocated buffer, whose\r
413 size is specified by the contents of OutputSize.\r
d8c79a81
LG
414 @param OutputSize A pointer to a caller-allocated\r
415 UINTN in which the size of *OutputBuffer\r
416 allocation is stored. If the function\r
417 returns anything other than EFI_SUCCESS,\r
418 the value of OutputSize is undefined.\r
d8c79a81
LG
419 @param AuthenticationStatus A pointer to a caller-allocated\r
420 UINT32 that indicates the\r
421 authentication status of the\r
422 output buffer. If the input\r
423 section's GuidedSectionHeader.\r
424 Attributes field has the\r
425 EFI_GUIDED_SECTION_AUTH_STATUS_VALID \r
426 bit as clear,\r
427 AuthenticationStatus must return\r
428 zero. These bits reflect the\r
429 status of the extraction\r
430 operation. If the function\r
431 returns anything other than\r
432 EFI_SUCCESS, the value of\r
433 AuthenticationStatus is\r
434 undefined.\r
435 \r
436 @retval EFI_SUCCESS The InputSection was\r
437 successfully processed and the\r
438 section contents were returned.\r
439 \r
440 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
441 resources to process the request.\r
442 \r
708919be 443 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
d8c79a81
LG
444 not match this instance of the\r
445 GUIDed Section Extraction PPI.\r
91d92e25 446\r
d8c79a81
LG
447**/\r
448EFI_STATUS\r
6d3ea23f 449EFIAPI\r
18fd8d65 450CustomGuidedSectionExtract (\r
d8c79a81
LG
451 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
452 IN CONST VOID *InputSection,\r
453 OUT VOID **OutputBuffer,\r
454 OUT UINTN *OutputSize,\r
455 OUT UINT32 *AuthenticationStatus\r
456)\r
457{\r
458 EFI_STATUS Status;\r
459 UINT8 *ScratchBuffer;\r
18fd8d65
LG
460 UINT32 ScratchBufferSize;\r
461 UINT32 OutputBufferSize;\r
462 UINT16 SectionAttribute;\r
d8c79a81
LG
463 \r
464 //\r
18fd8d65 465 // Init local variable\r
d8c79a81 466 //\r
18fd8d65
LG
467 ScratchBuffer = NULL;\r
468\r
d8c79a81 469 //\r
18fd8d65 470 // Call GetInfo to get the size and attribute of input guided section data.\r
d8c79a81 471 //\r
18fd8d65 472 Status = ExtractGuidedSectionGetInfo (\r
b6b98e91 473 InputSection,\r
474 &OutputBufferSize,\r
475 &ScratchBufferSize,\r
476 &SectionAttribute\r
477 );\r
18fd8d65 478 \r
d8c79a81 479 if (EFI_ERROR (Status)) {\r
91d92e25 480 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
18fd8d65
LG
481 return Status;\r
482 }\r
483 \r
484 if (ScratchBufferSize != 0) {\r
95276127 485 //\r
18fd8d65 486 // Allocate scratch buffer\r
95276127 487 //\r
18fd8d65
LG
488 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
489 if (ScratchBuffer == NULL) {\r
490 return EFI_OUT_OF_RESOURCES;\r
491 }\r
d8c79a81 492 }\r
95276127 493\r
708919be 494 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) { \r
18fd8d65
LG
495 //\r
496 // Allocate output buffer\r
497 //\r
288f9b38 498 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
18fd8d65
LG
499 if (*OutputBuffer == NULL) {\r
500 return EFI_OUT_OF_RESOURCES;\r
501 }\r
48557c65 502 DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
288f9b38
LG
503 //\r
504 // *OutputBuffer still is one section. Adjust *OutputBuffer offset, \r
505 // skip EFI section header to make section data at page alignment.\r
506 //\r
507 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
95276127 508 }\r
18fd8d65
LG
509 \r
510 Status = ExtractGuidedSectionDecode (\r
511 InputSection, \r
512 OutputBuffer,\r
513 ScratchBuffer,\r
514 AuthenticationStatus\r
48557c65 515 );\r
d8c79a81
LG
516 if (EFI_ERROR (Status)) {\r
517 //\r
18fd8d65 518 // Decode failed\r
d8c79a81 519 //\r
91d92e25 520 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
d8c79a81
LG
521 return Status;\r
522 }\r
523 \r
18fd8d65
LG
524 *OutputSize = (UINTN) OutputBufferSize;\r
525 \r
95276127 526 return EFI_SUCCESS;\r
527}\r
b0d803fe 528\r
91d92e25 529\r
530\r
531/**\r
532 Decompresses a section to the output buffer.\r
533\r
48557c65 534 This function looks up the compression type field in the input section and\r
91d92e25 535 applies the appropriate compression algorithm to compress the section to a\r
536 callee allocated buffer.\r
537 \r
538 @param This Points to this instance of the\r
539 EFI_PEI_DECOMPRESS_PEI PPI.\r
540 @param CompressionSection Points to the compressed section.\r
541 @param OutputBuffer Holds the returned pointer to the decompressed\r
542 sections.\r
543 @param OutputSize Holds the returned size of the decompress\r
544 section streams.\r
545 \r
546 @retval EFI_SUCCESS The section was decompressed successfully.\r
547 OutputBuffer contains the resulting data and\r
548 OutputSize contains the resulting size.\r
549\r
550**/\r
b0d803fe 551EFI_STATUS\r
552EFIAPI \r
553Decompress (\r
554 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
555 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
556 OUT VOID **OutputBuffer,\r
557 OUT UINTN *OutputSize\r
558 )\r
559{\r
560 EFI_STATUS Status;\r
561 UINT8 *DstBuffer;\r
562 UINT8 *ScratchBuffer;\r
635021c5 563 UINT32 DstBufferSize;\r
b0d803fe 564 UINT32 ScratchBufferSize;\r
890e5417
SZ
565 VOID *CompressionSource;\r
566 UINT32 CompressionSourceSize;\r
567 UINT32 UncompressedLength;\r
568 UINT8 CompressionType;\r
b0d803fe 569\r
570 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
571 ASSERT (FALSE);\r
572 return EFI_INVALID_PARAMETER;\r
573 }\r
574\r
890e5417
SZ
575 if (IS_SECTION2 (CompressionSection)) {\r
576 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));\r
577 CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));\r
578 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;\r
579 CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;\r
580 } else {\r
581 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));\r
582 CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));\r
583 UncompressedLength = CompressionSection->UncompressedLength;\r
584 CompressionType = CompressionSection->CompressionType;\r
585 }\r
b0d803fe 586 \r
587 //\r
588 // This is a compression set, expand it\r
589 //\r
890e5417 590 switch (CompressionType) {\r
b0d803fe 591 case EFI_STANDARD_COMPRESSION:\r
873b7997 592 if (FeaturePcdGet(PcdDxeIplSupportUefiDecompress)) {\r
b0d803fe 593 //\r
873b7997 594 // Load EFI standard compression.\r
595 // For compressed data, decompress them to destination buffer.\r
b0d803fe 596 //\r
873b7997 597 Status = UefiDecompressGetInfo (\r
890e5417
SZ
598 CompressionSource,\r
599 CompressionSourceSize,\r
635021c5 600 &DstBufferSize,\r
873b7997 601 &ScratchBufferSize\r
602 );\r
603 if (EFI_ERROR (Status)) {\r
604 //\r
605 // GetInfo failed\r
606 //\r
607 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
608 return EFI_NOT_FOUND;\r
609 }\r
610 //\r
611 // Allocate scratch buffer\r
b0d803fe 612 //\r
873b7997 613 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
614 if (ScratchBuffer == NULL) {\r
615 return EFI_OUT_OF_RESOURCES;\r
616 }\r
617 //\r
618 // Allocate destination buffer, extra one page for adjustment \r
619 //\r
620 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
621 if (DstBuffer == NULL) {\r
622 return EFI_OUT_OF_RESOURCES;\r
623 }\r
b0d803fe 624 //\r
873b7997 625 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
626 // to make section data at page alignment.\r
627 //\r
628 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
629 //\r
630 // Call decompress function\r
631 //\r
632 Status = UefiDecompress (\r
890e5417 633 CompressionSource,\r
873b7997 634 DstBuffer,\r
635 ScratchBuffer\r
636 );\r
637 if (EFI_ERROR (Status)) {\r
638 //\r
639 // Decompress failed\r
640 //\r
641 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
642 return EFI_NOT_FOUND;\r
643 }\r
644 break;\r
645 } else {\r
12b3e61e
LG
646 //\r
647 // PcdDxeIplSupportUefiDecompress is FALSE\r
648 // Don't support UEFI decompression algorithm.\r
649 //\r
650 ASSERT (FALSE);\r
b0d803fe 651 return EFI_NOT_FOUND;\r
652 }\r
b0d803fe 653\r
b0d803fe 654 case EFI_NOT_COMPRESSED:\r
655 //\r
656 // Allocate destination buffer\r
657 //\r
890e5417 658 DstBufferSize = UncompressedLength;\r
288f9b38 659 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
b0d803fe 660 if (DstBuffer == NULL) {\r
661 return EFI_OUT_OF_RESOURCES;\r
662 }\r
663 //\r
288f9b38
LG
664 // Adjust DstBuffer offset, skip EFI section header\r
665 // to make section data at page alignment.\r
666 //\r
667 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
668 //\r
b0d803fe 669 // stream is not actually compressed, just encapsulated. So just copy it.\r
670 //\r
890e5417 671 CopyMem (DstBuffer, CompressionSource, DstBufferSize);\r
b0d803fe 672 break;\r
673\r
674 default:\r
675 //\r
676 // Don't support other unknown compression type.\r
677 //\r
678 ASSERT (FALSE);\r
679 return EFI_NOT_FOUND;\r
680 }\r
681\r
682 *OutputSize = DstBufferSize;\r
683 *OutputBuffer = DstBuffer;\r
684\r
685 return EFI_SUCCESS;\r
686}\r
687\r
91d92e25 688\r
91d92e25 689/**\r
690 Updates the Stack HOB passed to DXE phase.\r
691\r
692 This function traverses the whole HOB list and update the stack HOB to\r
693 reflect the real stack that is used by DXE core.\r
694\r
695 @param BaseAddress The lower address of stack used by DxeCore.\r
696 @param Length The length of stack used by DxeCore.\r
697\r
698**/\r
30c8f861 699VOID\r
700UpdateStackHob (\r
701 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
702 IN UINT64 Length\r
703 )\r
704{\r
705 EFI_PEI_HOB_POINTERS Hob;\r
706\r
707 Hob.Raw = GetHobList ();\r
708 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {\r
709 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {\r
710 //\r
9a43bc39 711 // Build a new memory allocation HOB with old stack info with EfiBootServicesData type. Need to \r
712 // avoid this region be reclaimed by DXE core as the IDT built in SEC might be on stack, and some \r
713 // PEIMs may also keep key information on stack\r
30c8f861 714 //\r
715 BuildMemoryAllocationHob (\r
716 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,\r
717 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,\r
9a43bc39 718 EfiBootServicesData\r
30c8f861 719 );\r
720 //\r
721 // Update the BSP Stack Hob to reflect the new stack info.\r
722 //\r
723 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;\r
724 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;\r
725 break;\r
726 }\r
727 Hob.Raw = GET_NEXT_HOB (Hob);\r
728 }\r
729}\r