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