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