]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
Code Scrub DxeIpl module.
[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 &mDxeIplPpi
45 },
46 {
47 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
48 &gEfiPeiDecompressPpiGuid,
49 &mDecompressPpi
50 }
51 };
52
53 CONST EFI_PEI_PPI_DESCRIPTOR mPpiSignal = {
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 = &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_GUID DxeCoreFileName;
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
205 //
206 FileHandle = NULL;
207 Status = DxeIplFindDxeCore (&FileHandle);
208 ASSERT_EFI_ERROR (Status);
209
210 CopyGuid(&DxeCoreFileName, &(((EFI_FFS_FILE_HEADER*)FileHandle)->Name));
211
212 //
213 // Load the DXE Core from a Firmware Volume, may use LoadFile ppi to do this for save code size.
214 //
215 Status = PeiLoadFile (
216 FileHandle,
217 &DxeCoreAddress,
218 &DxeCoreSize,
219 &DxeCoreEntryPoint
220 );
221 ASSERT_EFI_ERROR (Status);
222
223 //
224 // Add HOB for the DXE Core
225 //
226 BuildModuleHob (
227 &DxeCoreFileName,
228 DxeCoreAddress,
229 EFI_SIZE_TO_PAGES ((UINTN) DxeCoreSize) * EFI_PAGE_SIZE,
230 DxeCoreEntryPoint
231 );
232
233 //
234 // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT
235 //
236 REPORT_STATUS_CODE (
237 EFI_PROGRESS_CODE,
238 PcdGet32(PcdStatusCodeValuePeiHandoffToDxe)
239 );
240
241 DEBUG_CODE_BEGIN ();
242
243 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION PtrPeImage;
244 PtrPeImage.Pe32 = (EFI_IMAGE_NT_HEADERS32 *) ((UINTN) DxeCoreAddress + ((EFI_IMAGE_DOS_HEADER *) (UINTN) DxeCoreAddress)->e_lfanew);
245
246 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DXE CORE at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)DxeCoreAddress, FUNCTION_ENTRY_POINT (DxeCoreEntryPoint)));
247
248
249 DEBUG_CODE_END ();
250 //
251 // Transfer control to the DXE Core
252 // The handoff state is simply a pointer to the HOB list
253 //
254 HandOffToDxeCore (DxeCoreEntryPoint, HobList, &mPpiSignal);
255 //
256 // If we get here, then the DXE Core returned. This is an error
257 // Dxe Core should not return.
258 //
259 ASSERT (FALSE);
260 CpuDeadLoop ();
261
262 return EFI_OUT_OF_RESOURCES;
263 }
264
265
266
267
268 /**
269 Find DxeCore driver from all First Volumes.
270
271 @param FileHandle Pointer to FFS file to search.
272
273 @return EFI_SUCESS Success to find the FFS in specificed FV
274 @return others Fail to find the FFS in specificed FV
275
276 **/
277 EFI_STATUS
278 DxeIplFindDxeCore (
279 OUT EFI_PEI_FILE_HANDLE *FileHandle
280 )
281 {
282 EFI_STATUS Status;
283 EFI_STATUS FileStatus;
284 UINTN Instance;
285 EFI_PEI_FV_HANDLE VolumeHandle;
286
287 Instance = 0;
288 *FileHandle = NULL;
289
290 do {
291 Status = PeiServicesFfsFindNextVolume (Instance++, &VolumeHandle);
292 if (!EFI_ERROR (Status)) {
293 FileStatus = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, FileHandle);
294 if (!EFI_ERROR (FileStatus)) {
295 return FileStatus;
296 }
297 }
298 } while (!EFI_ERROR (Status));
299
300 return EFI_NOT_FOUND;
301 }
302
303
304 /**
305 Loads and relocates a PE/COFF image into memory.
306
307 @param FileHandle The image file handle
308 @param ImageAddress The base address of the relocated PE/COFF image
309 @param ImageSize The size of the relocated PE/COFF image
310 @param EntryPoint The entry point of the relocated PE/COFF image
311
312 @return EFI_SUCCESS The file was loaded and relocated
313 @return EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file
314
315 **/
316 EFI_STATUS
317 PeiLoadFile (
318 IN EFI_PEI_FILE_HANDLE FileHandle,
319 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
320 OUT UINT64 *ImageSize,
321 OUT EFI_PHYSICAL_ADDRESS *EntryPoint
322 )
323 {
324
325 EFI_STATUS Status;
326 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
327 VOID *Pe32Data;
328
329 //
330 // First try to find the PE32 section in this ffs file.
331 //
332 Status = PeiServicesFfsFindSectionData (
333 EFI_SECTION_PE32,
334 FileHandle,
335 &Pe32Data
336 );
337 if (EFI_ERROR (Status)) {
338 //
339 // NO image types we support so exit.
340 //
341 return Status;
342 }
343
344 ZeroMem (&ImageContext, sizeof (ImageContext));
345 ImageContext.Handle = Pe32Data;
346 Status = GetImageReadFunction (&ImageContext);
347
348 ASSERT_EFI_ERROR (Status);
349
350 Status = PeCoffLoaderGetImageInfo (&ImageContext);
351 if (EFI_ERROR (Status)) {
352 return Status;
353 }
354 //
355 // Allocate Memory for the image
356 //
357 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));
358 ASSERT (ImageContext.ImageAddress != 0);
359
360 //
361 // Load the image to our new buffer
362 //
363 Status = PeCoffLoaderLoadImage (&ImageContext);
364 if (EFI_ERROR (Status)) {
365 return Status;
366 }
367 //
368 // Relocate the image in our new buffer
369 //
370 Status = PeCoffLoaderRelocateImage (&ImageContext);
371 if (EFI_ERROR (Status)) {
372 return Status;
373 }
374
375 //
376 // Flush the instruction cache so the image data is written before we execute it
377 //
378 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
379
380 *ImageAddress = ImageContext.ImageAddress;
381 *ImageSize = ImageContext.ImageSize;
382 *EntryPoint = ImageContext.EntryPoint;
383
384 return EFI_SUCCESS;
385 }
386
387
388
389
390 /**
391 The ExtractSection() function processes the input section and
392 returns a pointer to the section contents. If the section being
393 extracted does not require processing (if the section
394 GuidedSectionHeader.Attributes has the
395 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
396 OutputBuffer is just updated to point to the start of the
397 section's contents. Otherwise, *Buffer must be allocated
398 from PEI permanent memory.
399
400 @param This Indicates the
401 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
402 Buffer containing the input GUIDed section to be
403 processed. OutputBuffer OutputBuffer is
404 allocated from PEI permanent memory and contains
405 the new section stream.
406 @param InputSection A pointer to the input buffer, which contains
407 the input section to be processed.
408 @param OutputBuffer A pointer to a caller-allocated buffer, whose
409 size is specified by the contents of OutputSize.
410 @param OutputSize A pointer to a caller-allocated
411 UINTN in which the size of *OutputBuffer
412 allocation is stored. If the function
413 returns anything other than EFI_SUCCESS,
414 the value of OutputSize is undefined.
415 @param AuthenticationStatus A pointer to a caller-allocated
416 UINT32 that indicates the
417 authentication status of the
418 output buffer. If the input
419 section's GuidedSectionHeader.
420 Attributes field has the
421 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
422 bit as clear,
423 AuthenticationStatus must return
424 zero. These bits reflect the
425 status of the extraction
426 operation. If the function
427 returns anything other than
428 EFI_SUCCESS, the value of
429 AuthenticationStatus is
430 undefined.
431
432 @retval EFI_SUCCESS The InputSection was
433 successfully processed and the
434 section contents were returned.
435
436 @retval EFI_OUT_OF_RESOURCES The system has insufficient
437 resources to process the request.
438
439 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
440 not match this instance of the
441 GUIDed Section Extraction PPI.
442
443 **/
444 EFI_STATUS
445 CustomGuidedSectionExtract (
446 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,
447 IN CONST VOID *InputSection,
448 OUT VOID **OutputBuffer,
449 OUT UINTN *OutputSize,
450 OUT UINT32 *AuthenticationStatus
451 )
452 {
453 EFI_STATUS Status;
454 UINT8 *ScratchBuffer;
455 UINT32 ScratchBufferSize;
456 UINT32 OutputBufferSize;
457 UINT16 SectionAttribute;
458
459 //
460 // Init local variable
461 //
462 ScratchBuffer = NULL;
463
464 //
465 // Call GetInfo to get the size and attribute of input guided section data.
466 //
467 Status = ExtractGuidedSectionGetInfo (
468 InputSection,
469 &OutputBufferSize,
470 &ScratchBufferSize,
471 &SectionAttribute
472 );
473
474 if (EFI_ERROR (Status)) {
475 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
476 return Status;
477 }
478
479 if (ScratchBufferSize != 0) {
480 //
481 // Allocate scratch buffer
482 //
483 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
484 if (ScratchBuffer == NULL) {
485 return EFI_OUT_OF_RESOURCES;
486 }
487 }
488
489 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
490 //
491 // Allocate output buffer
492 //
493 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
494 if (*OutputBuffer == NULL) {
495 return EFI_OUT_OF_RESOURCES;
496 }
497 DEBUG ((DEBUG_INFO, "Customed Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
498 //
499 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
500 // skip EFI section header to make section data at page alignment.
501 //
502 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
503 }
504
505 Status = ExtractGuidedSectionDecode (
506 InputSection,
507 OutputBuffer,
508 ScratchBuffer,
509 AuthenticationStatus
510 );
511 if (EFI_ERROR (Status)) {
512 //
513 // Decode failed
514 //
515 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
516 return Status;
517 }
518
519 *OutputSize = (UINTN) OutputBufferSize;
520
521 return EFI_SUCCESS;
522 }
523
524
525
526 /**
527 Decompresses a section to the output buffer.
528
529 This function lookes up the compression type field in the input section and
530 applies the appropriate compression algorithm to compress the section to a
531 callee allocated buffer.
532
533 @param This Points to this instance of the
534 EFI_PEI_DECOMPRESS_PEI PPI.
535 @param CompressionSection Points to the compressed section.
536 @param OutputBuffer Holds the returned pointer to the decompressed
537 sections.
538 @param OutputSize Holds the returned size of the decompress
539 section streams.
540
541 @retval EFI_SUCCESS The section was decompressed successfully.
542 OutputBuffer contains the resulting data and
543 OutputSize contains the resulting size.
544
545 **/
546 EFI_STATUS
547 EFIAPI
548 Decompress (
549 IN CONST EFI_PEI_DECOMPRESS_PPI *This,
550 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
551 OUT VOID **OutputBuffer,
552 OUT UINTN *OutputSize
553 )
554 {
555 EFI_STATUS Status;
556 UINT8 *DstBuffer;
557 UINT8 *ScratchBuffer;
558 UINTN DstBufferSize;
559 UINT32 ScratchBufferSize;
560 EFI_COMMON_SECTION_HEADER *Section;
561 UINTN SectionLength;
562
563 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
564 ASSERT (FALSE);
565 return EFI_INVALID_PARAMETER;
566 }
567
568 Section = (EFI_COMMON_SECTION_HEADER *) CompressionSection;
569 SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff;
570
571 //
572 // This is a compression set, expand it
573 //
574 switch (CompressionSection->CompressionType) {
575 case EFI_STANDARD_COMPRESSION:
576 //
577 // Load EFI standard compression.
578 // For compressed data, decompress them to dstbuffer.
579 //
580 Status = UefiDecompressGetInfo (
581 (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
582 (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION),
583 (UINT32 *) &DstBufferSize,
584 &ScratchBufferSize
585 );
586 if (EFI_ERROR (Status)) {
587 //
588 // GetInfo failed
589 //
590 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
591 return EFI_NOT_FOUND;
592 }
593 //
594 // Allocate scratch buffer
595 //
596 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
597 if (ScratchBuffer == NULL) {
598 return EFI_OUT_OF_RESOURCES;
599 }
600 //
601 // Allocate destination buffer, extra one page for adjustment
602 //
603 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
604 if (DstBuffer == NULL) {
605 return EFI_OUT_OF_RESOURCES;
606 }
607 //
608 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
609 // to make section data at page alignment.
610 //
611 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
612 //
613 // Call decompress function
614 //
615 Status = UefiDecompress (
616 (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1),
617 DstBuffer,
618 ScratchBuffer
619 );
620 if (EFI_ERROR (Status)) {
621 //
622 // Decompress failed
623 //
624 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
625 return EFI_NOT_FOUND;
626 }
627 break;
628
629 case EFI_NOT_COMPRESSED:
630 //
631 // Allocate destination buffer
632 //
633 DstBufferSize = CompressionSection->UncompressedLength;
634 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
635 if (DstBuffer == NULL) {
636 return EFI_OUT_OF_RESOURCES;
637 }
638 //
639 // Adjust DstBuffer offset, skip EFI section header
640 // to make section data at page alignment.
641 //
642 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
643 //
644 // stream is not actually compressed, just encapsulated. So just copy it.
645 //
646 CopyMem (DstBuffer, CompressionSection + 1, DstBufferSize);
647 break;
648
649 default:
650 //
651 // Don't support other unknown compression type.
652 //
653 ASSERT (FALSE);
654 return EFI_NOT_FOUND;
655 }
656
657 *OutputSize = DstBufferSize;
658 *OutputBuffer = DstBuffer;
659
660 return EFI_SUCCESS;
661 }
662
663
664
665
666 /**
667 Updates the Stack HOB passed to DXE phase.
668
669 This function traverses the whole HOB list and update the stack HOB to
670 reflect the real stack that is used by DXE core.
671
672 @param BaseAddress The lower address of stack used by DxeCore.
673 @param Length The length of stack used by DxeCore.
674
675 **/
676 VOID
677 UpdateStackHob (
678 IN EFI_PHYSICAL_ADDRESS BaseAddress,
679 IN UINT64 Length
680 )
681 {
682 EFI_PEI_HOB_POINTERS Hob;
683
684 Hob.Raw = GetHobList ();
685 while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
686 if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
687 //
688 // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type
689 // to be reclaimed by DXE core.
690 //
691 BuildMemoryAllocationHob (
692 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
693 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
694 EfiConventionalMemory
695 );
696 //
697 // Update the BSP Stack Hob to reflect the new stack info.
698 //
699 Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
700 Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
701 break;
702 }
703 Hob.Raw = GET_NEXT_HOB (Hob);
704 }
705 }