3 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // Module Globals used in the DXE to PEI hand off
13 // These must be module globals, so the stack can be switched
15 CONST EFI_DXE_IPL_PPI mDxeIplPpi
= {
19 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi
= {
20 CustomGuidedSectionExtract
23 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi
= {
27 CONST EFI_PEI_PPI_DESCRIPTOR mPpiList
[] = {
29 EFI_PEI_PPI_DESCRIPTOR_PPI
,
34 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
35 &gEfiPeiDecompressPpiGuid
,
36 (VOID
*) &mDecompressPpi
40 CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi
= {
41 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
42 &gEfiEndOfPeiSignalPpiGuid
,
47 Entry point of DXE IPL PEIM.
49 This function installs DXE IPL PPI and Decompress PPI. It also reloads
50 itself to memory on non-S3 resume boot path.
52 @param[in] FileHandle Handle of the file being invoked.
53 @param[in] PeiServices Describes the list of possible PEI Services.
55 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
56 @retval Others Some error occurs during the execution of this function.
61 PeimInitializeDxeIpl (
62 IN EFI_PEI_FILE_HANDLE FileHandle
,
63 IN CONST EFI_PEI_SERVICES
**PeiServices
67 EFI_GUID
*ExtractHandlerGuidTable
;
68 UINTN ExtractHandlerNumber
;
69 EFI_PEI_PPI_DESCRIPTOR
*GuidPpi
;
72 // Get custom extract guided section method guid list
74 ExtractHandlerNumber
= ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable
);
77 // Install custom extraction guid PPI
79 if (ExtractHandlerNumber
> 0) {
80 GuidPpi
= (EFI_PEI_PPI_DESCRIPTOR
*) AllocatePool (ExtractHandlerNumber
* sizeof (EFI_PEI_PPI_DESCRIPTOR
));
81 ASSERT (GuidPpi
!= NULL
);
82 while (ExtractHandlerNumber
-- > 0) {
83 GuidPpi
->Flags
= EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
;
84 GuidPpi
->Ppi
= (VOID
*) &mCustomGuidedSectionExtractionPpi
;
85 GuidPpi
->Guid
= &ExtractHandlerGuidTable
[ExtractHandlerNumber
];
86 Status
= PeiServicesInstallPpi (GuidPpi
++);
87 ASSERT_EFI_ERROR(Status
);
92 // Install DxeIpl and Decompress PPIs.
94 Status
= PeiServicesInstallPpi (mPpiList
);
95 ASSERT_EFI_ERROR(Status
);
101 The ExtractSection() function processes the input section and
102 returns a pointer to the section contents. If the section being
103 extracted does not require processing (if the section
104 GuidedSectionHeader.Attributes has the
105 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
106 OutputBuffer is just updated to point to the start of the
107 section's contents. Otherwise, *Buffer must be allocated
108 from PEI permanent memory.
110 @param[in] This Indicates the
111 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
112 Buffer containing the input GUIDed section to be
113 processed. OutputBuffer OutputBuffer is
114 allocated from PEI permanent memory and contains
115 the new section stream.
116 @param[in] InputSection A pointer to the input buffer, which contains
117 the input section to be processed.
118 @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose
119 size is specified by the contents of OutputSize.
120 @param[out] OutputSize A pointer to a caller-allocated
121 UINTN in which the size of *OutputBuffer
122 allocation is stored. If the function
123 returns anything other than EFI_SUCCESS,
124 the value of OutputSize is undefined.
125 @param[out] AuthenticationStatus A pointer to a caller-allocated
126 UINT32 that indicates the
127 authentication status of the
128 output buffer. If the input
129 section's GuidedSectionHeader.
130 Attributes field has the
131 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
133 AuthenticationStatus must return
134 zero. These bits reflect the
135 status of the extraction
136 operation. If the function
137 returns anything other than
138 EFI_SUCCESS, the value of
139 AuthenticationStatus is
142 @retval EFI_SUCCESS The InputSection was
143 successfully processed and the
144 section contents were returned.
146 @retval EFI_OUT_OF_RESOURCES The system has insufficient
147 resources to process the request.
149 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
150 not match this instance of the
151 GUIDed Section Extraction PPI.
156 CustomGuidedSectionExtract (
157 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*This
,
158 IN CONST VOID
*InputSection
,
159 OUT VOID
**OutputBuffer
,
160 OUT UINTN
*OutputSize
,
161 OUT UINT32
*AuthenticationStatus
165 UINT8
*ScratchBuffer
;
166 UINT32 ScratchBufferSize
;
167 UINT32 OutputBufferSize
;
168 UINT16 SectionAttribute
;
171 // Init local variable
173 ScratchBuffer
= NULL
;
176 // Call GetInfo to get the size and attribute of input guided section data.
178 Status
= ExtractGuidedSectionGetInfo (
185 if (EFI_ERROR (Status
)) {
186 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
190 if (ScratchBufferSize
!= 0) {
192 // Allocate scratch buffer
194 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
195 if (ScratchBuffer
== NULL
) {
196 return EFI_OUT_OF_RESOURCES
;
200 if (((SectionAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) && OutputBufferSize
> 0) {
202 // Allocate output buffer
204 *OutputBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize
) + 1);
205 if (*OutputBuffer
== NULL
) {
206 return EFI_OUT_OF_RESOURCES
;
208 DEBUG ((DEBUG_INFO
, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize
, *OutputBuffer
));
210 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
211 // skip EFI section header to make section data at page alignment.
213 *OutputBuffer
= (VOID
*)((UINT8
*) *OutputBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
));
216 Status
= ExtractGuidedSectionDecode (
222 if (EFI_ERROR (Status
)) {
226 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
230 *OutputSize
= (UINTN
) OutputBufferSize
;
238 Decompresses a section to the output buffer.
240 This function looks up the compression type field in the input section and
241 applies the appropriate compression algorithm to compress the section to a
242 callee allocated buffer.
244 @param[in] This Points to this instance of the
245 EFI_PEI_DECOMPRESS_PEI PPI.
246 @param[in] CompressionSection Points to the compressed section.
247 @param[out] OutputBuffer Holds the returned pointer to the decompressed
249 @param[out] OutputSize Holds the returned size of the decompress
252 @retval EFI_SUCCESS The section was decompressed successfully.
253 OutputBuffer contains the resulting data and
254 OutputSize contains the resulting size.
260 IN CONST EFI_PEI_DECOMPRESS_PPI
*This
,
261 IN CONST EFI_COMPRESSION_SECTION
*CompressionSection
,
262 OUT VOID
**OutputBuffer
,
263 OUT UINTN
*OutputSize
268 UINT8
*ScratchBuffer
;
269 UINT32 DstBufferSize
;
270 UINT32 ScratchBufferSize
;
271 VOID
*CompressionSource
;
272 UINT32 CompressionSourceSize
;
273 UINT32 UncompressedLength
;
274 UINT8 CompressionType
;
276 if (CompressionSection
->CommonHeader
.Type
!= EFI_SECTION_COMPRESSION
) {
278 return EFI_INVALID_PARAMETER
;
281 if (IS_SECTION2 (CompressionSection
)) {
282 CompressionSource
= (VOID
*) ((UINT8
*) CompressionSection
+ sizeof (EFI_COMPRESSION_SECTION2
));
283 CompressionSourceSize
= (UINT32
) (SECTION2_SIZE (CompressionSection
) - sizeof (EFI_COMPRESSION_SECTION2
));
284 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*) CompressionSection
)->UncompressedLength
;
285 CompressionType
= ((EFI_COMPRESSION_SECTION2
*) CompressionSection
)->CompressionType
;
287 CompressionSource
= (VOID
*) ((UINT8
*) CompressionSection
+ sizeof (EFI_COMPRESSION_SECTION
));
288 CompressionSourceSize
= (UINT32
) (SECTION_SIZE (CompressionSection
) - sizeof (EFI_COMPRESSION_SECTION
));
289 UncompressedLength
= CompressionSection
->UncompressedLength
;
290 CompressionType
= CompressionSection
->CompressionType
;
294 // This is a compression set, expand it
296 switch (CompressionType
) {
297 case EFI_STANDARD_COMPRESSION
:
299 // Load EFI standard compression.
300 // For compressed data, decompress them to destination buffer.
302 Status
= UefiDecompressGetInfo (
304 CompressionSourceSize
,
308 if (EFI_ERROR (Status
)) {
312 DEBUG ((DEBUG_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
313 return EFI_NOT_FOUND
;
316 // Allocate scratch buffer
318 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
319 if (ScratchBuffer
== NULL
) {
320 return EFI_OUT_OF_RESOURCES
;
323 // Allocate destination buffer, extra one page for adjustment
325 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
326 if (DstBuffer
== NULL
) {
327 return EFI_OUT_OF_RESOURCES
;
330 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
331 // to make section data at page alignment.
333 DstBuffer
= DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
335 // Call decompress function
337 Status
= UefiDecompress (
342 if (EFI_ERROR (Status
)) {
346 DEBUG ((DEBUG_ERROR
, "Decompress Failed - %r\n", Status
));
347 return EFI_NOT_FOUND
;
351 case EFI_NOT_COMPRESSED
:
353 // Allocate destination buffer
355 DstBufferSize
= UncompressedLength
;
356 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
357 if (DstBuffer
== NULL
) {
358 return EFI_OUT_OF_RESOURCES
;
361 // Adjust DstBuffer offset, skip EFI section header
362 // to make section data at page alignment.
364 DstBuffer
= DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
366 // stream is not actually compressed, just encapsulated. So just copy it.
368 CopyMem (DstBuffer
, CompressionSource
, DstBufferSize
);
373 // Don't support other unknown compression type.
376 return EFI_NOT_FOUND
;
379 *OutputSize
= DstBufferSize
;
380 *OutputBuffer
= DstBuffer
;
386 Main entry point to last PEIM.
388 This function finds DXE Core in the firmware volume and transfer the control to
391 @param[in] This Entry point for DXE IPL PPI.
392 @param[in] PeiServices General purpose services available to every PEIM.
393 @param[in] HobList Address to the Pei HOB list.
395 @return EFI_SUCCESS DXE core was successfully loaded.
396 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
402 IN CONST EFI_DXE_IPL_PPI
*This
,
403 IN EFI_PEI_SERVICES
**PeiServices
,
404 IN EFI_PEI_HOB_POINTERS HobList
409 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP HOB is located at 0x%08X\n", HobList
));
412 // End of PEI phase signal
414 Status
= PeiServicesInstallPpi (&gEndOfPeiSignalPpi
);
415 ASSERT_EFI_ERROR (Status
);
418 // Give control back to BootLoader after FspInit
420 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP is waiting for NOTIFY\n"));
424 // BootLoader called FSP again through NotifyPhase
430 // Give control back to the boot loader framework caller
432 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "============= PEIM FSP is Completed =============\n\n"));
434 SetFspApiReturnStatus(EFI_SUCCESS
);
436 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT
);
438 Pei2LoaderSwitchStack();
441 // Should not come here
444 DEBUG ((DEBUG_ERROR
, "No FSP API should be called after FSP is DONE!\n"));
445 SetFspApiReturnStatus(EFI_UNSUPPORTED
);
446 Pei2LoaderSwitchStack();