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