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