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