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