3 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Module Globals used in the DXE to PEI hand off
19 // These must be module globals, so the stack can be switched
21 CONST EFI_DXE_IPL_PPI mDxeIplPpi
= {
25 CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi
= {
26 CustomGuidedSectionExtract
29 CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi
= {
33 CONST EFI_PEI_PPI_DESCRIPTOR mPpiList
[] = {
35 EFI_PEI_PPI_DESCRIPTOR_PPI
,
40 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
41 &gEfiPeiDecompressPpiGuid
,
42 (VOID
*) &mDecompressPpi
46 CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi
= {
47 (EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
48 &gEfiEndOfPeiSignalPpiGuid
,
53 Entry point of DXE IPL PEIM.
55 This function installs DXE IPL PPI and Decompress PPI. It also reloads
56 itself to memory on non-S3 resume boot path.
58 @param[in] FileHandle Handle of the file being invoked.
59 @param[in] PeiServices Describes the list of possible PEI Services.
61 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
62 @retval Others Some error occurs during the execution of this function.
67 PeimInitializeDxeIpl (
68 IN EFI_PEI_FILE_HANDLE FileHandle
,
69 IN CONST EFI_PEI_SERVICES
**PeiServices
73 EFI_GUID
*ExtractHandlerGuidTable
;
74 UINTN ExtractHandlerNumber
;
75 EFI_PEI_PPI_DESCRIPTOR
*GuidPpi
;
78 // Get custom extract guided section method guid list
80 ExtractHandlerNumber
= ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable
);
83 // Install custom extraction guid PPI
85 if (ExtractHandlerNumber
> 0) {
86 GuidPpi
= (EFI_PEI_PPI_DESCRIPTOR
*) AllocatePool (ExtractHandlerNumber
* sizeof (EFI_PEI_PPI_DESCRIPTOR
));
87 ASSERT (GuidPpi
!= NULL
);
88 while (ExtractHandlerNumber
-- > 0) {
89 GuidPpi
->Flags
= EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
;
90 GuidPpi
->Ppi
= (VOID
*) &mCustomGuidedSectionExtractionPpi
;
91 GuidPpi
->Guid
= &ExtractHandlerGuidTable
[ExtractHandlerNumber
];
92 Status
= PeiServicesInstallPpi (GuidPpi
++);
93 ASSERT_EFI_ERROR(Status
);
98 // Install DxeIpl and Decompress PPIs.
100 Status
= PeiServicesInstallPpi (mPpiList
);
101 ASSERT_EFI_ERROR(Status
);
107 The ExtractSection() function processes the input section and
108 returns a pointer to the section contents. If the section being
109 extracted does not require processing (if the section
110 GuidedSectionHeader.Attributes has the
111 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then
112 OutputBuffer is just updated to point to the start of the
113 section's contents. Otherwise, *Buffer must be allocated
114 from PEI permanent memory.
116 @param[in] This Indicates the
117 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.
118 Buffer containing the input GUIDed section to be
119 processed. OutputBuffer OutputBuffer is
120 allocated from PEI permanent memory and contains
121 the new section stream.
122 @param[in] InputSection A pointer to the input buffer, which contains
123 the input section to be processed.
124 @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose
125 size is specified by the contents of OutputSize.
126 @param[out] OutputSize A pointer to a caller-allocated
127 UINTN in which the size of *OutputBuffer
128 allocation is stored. If the function
129 returns anything other than EFI_SUCCESS,
130 the value of OutputSize is undefined.
131 @param[out] AuthenticationStatus A pointer to a caller-allocated
132 UINT32 that indicates the
133 authentication status of the
134 output buffer. If the input
135 section's GuidedSectionHeader.
136 Attributes field has the
137 EFI_GUIDED_SECTION_AUTH_STATUS_VALID
139 AuthenticationStatus must return
140 zero. These bits reflect the
141 status of the extraction
142 operation. If the function
143 returns anything other than
144 EFI_SUCCESS, the value of
145 AuthenticationStatus is
148 @retval EFI_SUCCESS The InputSection was
149 successfully processed and the
150 section contents were returned.
152 @retval EFI_OUT_OF_RESOURCES The system has insufficient
153 resources to process the request.
155 @retval EFI_INVALID_PARAMETER The GUID in InputSection does
156 not match this instance of the
157 GUIDed Section Extraction PPI.
162 CustomGuidedSectionExtract (
163 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI
*This
,
164 IN CONST VOID
*InputSection
,
165 OUT VOID
**OutputBuffer
,
166 OUT UINTN
*OutputSize
,
167 OUT UINT32
*AuthenticationStatus
171 UINT8
*ScratchBuffer
;
172 UINT32 ScratchBufferSize
;
173 UINT32 OutputBufferSize
;
174 UINT16 SectionAttribute
;
177 // Init local variable
179 ScratchBuffer
= NULL
;
182 // Call GetInfo to get the size and attribute of input guided section data.
184 Status
= ExtractGuidedSectionGetInfo (
191 if (EFI_ERROR (Status
)) {
192 DEBUG ((DEBUG_ERROR
, "GetInfo from guided section Failed - %r\n", Status
));
196 if (ScratchBufferSize
!= 0) {
198 // Allocate scratch buffer
200 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
201 if (ScratchBuffer
== NULL
) {
202 return EFI_OUT_OF_RESOURCES
;
206 if (((SectionAttribute
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) != 0) && OutputBufferSize
> 0) {
208 // Allocate output buffer
210 *OutputBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize
) + 1);
211 if (*OutputBuffer
== NULL
) {
212 return EFI_OUT_OF_RESOURCES
;
214 DEBUG ((DEBUG_INFO
, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize
, *OutputBuffer
));
216 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
217 // skip EFI section header to make section data at page alignment.
219 *OutputBuffer
= (VOID
*)((UINT8
*) *OutputBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
));
222 Status
= ExtractGuidedSectionDecode (
228 if (EFI_ERROR (Status
)) {
232 DEBUG ((DEBUG_ERROR
, "Extract guided section Failed - %r\n", Status
));
236 *OutputSize
= (UINTN
) OutputBufferSize
;
244 Decompresses a section to the output buffer.
246 This function looks up the compression type field in the input section and
247 applies the appropriate compression algorithm to compress the section to a
248 callee allocated buffer.
250 @param[in] This Points to this instance of the
251 EFI_PEI_DECOMPRESS_PEI PPI.
252 @param[in] CompressionSection Points to the compressed section.
253 @param[out] OutputBuffer Holds the returned pointer to the decompressed
255 @param[out] OutputSize Holds the returned size of the decompress
258 @retval EFI_SUCCESS The section was decompressed successfully.
259 OutputBuffer contains the resulting data and
260 OutputSize contains the resulting size.
266 IN CONST EFI_PEI_DECOMPRESS_PPI
*This
,
267 IN CONST EFI_COMPRESSION_SECTION
*CompressionSection
,
268 OUT VOID
**OutputBuffer
,
269 OUT UINTN
*OutputSize
274 UINT8
*ScratchBuffer
;
275 UINT32 DstBufferSize
;
276 UINT32 ScratchBufferSize
;
277 VOID
*CompressionSource
;
278 UINT32 CompressionSourceSize
;
279 UINT32 UncompressedLength
;
280 UINT8 CompressionType
;
282 if (CompressionSection
->CommonHeader
.Type
!= EFI_SECTION_COMPRESSION
) {
284 return EFI_INVALID_PARAMETER
;
287 if (IS_SECTION2 (CompressionSection
)) {
288 CompressionSource
= (VOID
*) ((UINT8
*) CompressionSection
+ sizeof (EFI_COMPRESSION_SECTION2
));
289 CompressionSourceSize
= (UINT32
) (SECTION2_SIZE (CompressionSection
) - sizeof (EFI_COMPRESSION_SECTION2
));
290 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*) CompressionSection
)->UncompressedLength
;
291 CompressionType
= ((EFI_COMPRESSION_SECTION2
*) CompressionSection
)->CompressionType
;
293 CompressionSource
= (VOID
*) ((UINT8
*) CompressionSection
+ sizeof (EFI_COMPRESSION_SECTION
));
294 CompressionSourceSize
= (UINT32
) (SECTION_SIZE (CompressionSection
) - sizeof (EFI_COMPRESSION_SECTION
));
295 UncompressedLength
= CompressionSection
->UncompressedLength
;
296 CompressionType
= CompressionSection
->CompressionType
;
300 // This is a compression set, expand it
302 switch (CompressionType
) {
303 case EFI_STANDARD_COMPRESSION
:
305 // Load EFI standard compression.
306 // For compressed data, decompress them to destination buffer.
308 Status
= UefiDecompressGetInfo (
310 CompressionSourceSize
,
314 if (EFI_ERROR (Status
)) {
318 DEBUG ((DEBUG_ERROR
, "Decompress GetInfo Failed - %r\n", Status
));
319 return EFI_NOT_FOUND
;
322 // Allocate scratch buffer
324 ScratchBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize
));
325 if (ScratchBuffer
== NULL
) {
326 return EFI_OUT_OF_RESOURCES
;
329 // Allocate destination buffer, extra one page for adjustment
331 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
332 if (DstBuffer
== NULL
) {
333 return EFI_OUT_OF_RESOURCES
;
336 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
337 // to make section data at page alignment.
339 DstBuffer
= DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
341 // Call decompress function
343 Status
= UefiDecompress (
348 if (EFI_ERROR (Status
)) {
352 DEBUG ((DEBUG_ERROR
, "Decompress Failed - %r\n", Status
));
353 return EFI_NOT_FOUND
;
357 case EFI_NOT_COMPRESSED
:
359 // Allocate destination buffer
361 DstBufferSize
= UncompressedLength
;
362 DstBuffer
= AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize
) + 1);
363 if (DstBuffer
== NULL
) {
364 return EFI_OUT_OF_RESOURCES
;
367 // Adjust DstBuffer offset, skip EFI section header
368 // to make section data at page alignment.
370 DstBuffer
= DstBuffer
+ EFI_PAGE_SIZE
- sizeof (EFI_COMMON_SECTION_HEADER
);
372 // stream is not actually compressed, just encapsulated. So just copy it.
374 CopyMem (DstBuffer
, CompressionSource
, DstBufferSize
);
379 // Don't support other unknown compression type.
382 return EFI_NOT_FOUND
;
385 *OutputSize
= DstBufferSize
;
386 *OutputBuffer
= DstBuffer
;
392 Main entry point to last PEIM.
394 This function finds DXE Core in the firmware volume and transfer the control to
397 @param[in] This Entry point for DXE IPL PPI.
398 @param[in] PeiServices General purpose services available to every PEIM.
399 @param[in] HobList Address to the Pei HOB list.
401 @return EFI_SUCCESS DXE core was successfully loaded.
402 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
408 IN CONST EFI_DXE_IPL_PPI
*This
,
409 IN EFI_PEI_SERVICES
**PeiServices
,
410 IN EFI_PEI_HOB_POINTERS HobList
415 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP HOB is located at 0x%08X\n", HobList
));
418 // End of PEI phase signal
420 Status
= PeiServicesInstallPpi (&gEndOfPeiSignalPpi
);
421 ASSERT_EFI_ERROR (Status
);
424 // Give control back to BootLoader after FspInit
426 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "FSP is waiting for NOTIFY\n"));
430 // BootLoader called FSP again through NotifyPhase
436 // Give control back to the boot loader framework caller
438 DEBUG ((DEBUG_INFO
| DEBUG_INIT
, "============= PEIM FSP is Completed =============\n\n"));
440 SetFspApiReturnStatus(EFI_SUCCESS
);
442 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT
);
444 Pei2LoaderSwitchStack();
447 // Should not come here
450 DEBUG ((DEBUG_ERROR
, "No FSP API should be called after FSP is DONE!\n"));
451 SetFspApiReturnStatus(EFI_UNSUPPORTED
);
452 Pei2LoaderSwitchStack();