]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFspPkg/FspDxeIpl/DxeIpl.c
Update IntelFspPkg to support FSP1.1
[mirror_edk2.git] / IntelFspPkg / FspDxeIpl / DxeIpl.c
CommitLineData
c8ec22a2
JY
1/** @file\r
2\r
9da59186 3 Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
c8ec22a2
JY
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php.\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12**/\r
13\r
14#include "DxeIpl.h"\r
15\r
16\r
17//\r
18// Module Globals used in the DXE to PEI hand off\r
19// These must be module globals, so the stack can be switched\r
20//\r
21CONST EFI_DXE_IPL_PPI mDxeIplPpi = {\r
22 DxeLoadCore\r
23};\r
24\r
25CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {\r
26 CustomGuidedSectionExtract\r
27};\r
28\r
29CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {\r
30 Decompress\r
31};\r
32\r
33CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {\r
34 {\r
35 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
36 &gEfiDxeIplPpiGuid,\r
37 (VOID *) &mDxeIplPpi\r
38 },\r
39 {\r
40 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
41 &gEfiPeiDecompressPpiGuid,\r
42 (VOID *) &mDecompressPpi\r
43 }\r
44};\r
45\r
46CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {\r
47 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
48 &gEfiEndOfPeiSignalPpiGuid,\r
49 NULL\r
50};\r
51\r
52/**\r
53 Entry point of DXE IPL PEIM.\r
54\r
55 This function installs DXE IPL PPI and Decompress PPI. It also reloads\r
56 itself to memory on non-S3 resume boot path.\r
57\r
58 @param[in] FileHandle Handle of the file being invoked.\r
59 @param[in] PeiServices Describes the list of possible PEI Services.\r
60\r
61 @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.\r
62 @retval Others Some error occurs during the execution of this function.\r
63\r
64**/\r
65EFI_STATUS\r
66EFIAPI\r
67PeimInitializeDxeIpl (\r
68 IN EFI_PEI_FILE_HANDLE FileHandle,\r
69 IN CONST EFI_PEI_SERVICES **PeiServices\r
70 )\r
71{\r
72 EFI_STATUS Status;\r
73 EFI_GUID *ExtractHandlerGuidTable;\r
74 UINTN ExtractHandlerNumber;\r
75 EFI_PEI_PPI_DESCRIPTOR *GuidPpi;\r
76\r
77 //\r
78 // Get custom extract guided section method guid list\r
79 //\r
80 ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);\r
81\r
82 //\r
83 // Install custom extraction guid PPI\r
84 //\r
85 if (ExtractHandlerNumber > 0) {\r
86 GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *) AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));\r
87 ASSERT (GuidPpi != NULL);\r
88 while (ExtractHandlerNumber-- > 0) {\r
89 GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;\r
90 GuidPpi->Ppi = (VOID *) &mCustomGuidedSectionExtractionPpi;\r
91 GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];\r
92 Status = PeiServicesInstallPpi (GuidPpi++);\r
93 ASSERT_EFI_ERROR(Status);\r
94 }\r
95 }\r
96\r
97 //\r
98 // Install DxeIpl and Decompress PPIs.\r
99 //\r
100 Status = PeiServicesInstallPpi (mPpiList);\r
101 ASSERT_EFI_ERROR(Status);\r
102\r
103 return Status;\r
104}\r
105\r
106/**\r
107 The ExtractSection() function processes the input section and\r
108 returns a pointer to the section contents. If the section being\r
109 extracted does not require processing (if the section\r
110 GuidedSectionHeader.Attributes has the\r
111 EFI_GUIDED_SECTION_PROCESSING_REQUIRED field cleared), then\r
112 OutputBuffer is just updated to point to the start of the\r
113 section's contents. Otherwise, *Buffer must be allocated\r
114 from PEI permanent memory.\r
115\r
116 @param[in] This Indicates the\r
117 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI instance.\r
118 Buffer containing the input GUIDed section to be\r
119 processed. OutputBuffer OutputBuffer is\r
120 allocated from PEI permanent memory and contains\r
121 the new section stream.\r
122 @param[in] InputSection A pointer to the input buffer, which contains\r
123 the input section to be processed.\r
124 @param[out] OutputBuffer A pointer to a caller-allocated buffer, whose\r
125 size is specified by the contents of OutputSize.\r
126 @param[out] OutputSize A pointer to a caller-allocated\r
127 UINTN in which the size of *OutputBuffer\r
128 allocation is stored. If the function\r
129 returns anything other than EFI_SUCCESS,\r
130 the value of OutputSize is undefined.\r
131 @param[out] AuthenticationStatus A pointer to a caller-allocated\r
132 UINT32 that indicates the\r
133 authentication status of the\r
134 output buffer. If the input\r
135 section's GuidedSectionHeader.\r
136 Attributes field has the\r
137 EFI_GUIDED_SECTION_AUTH_STATUS_VALID\r
138 bit as clear,\r
139 AuthenticationStatus must return\r
140 zero. These bits reflect the\r
141 status of the extraction\r
142 operation. If the function\r
143 returns anything other than\r
144 EFI_SUCCESS, the value of\r
145 AuthenticationStatus is\r
146 undefined.\r
147\r
148 @retval EFI_SUCCESS The InputSection was\r
149 successfully processed and the\r
150 section contents were returned.\r
151\r
152 @retval EFI_OUT_OF_RESOURCES The system has insufficient\r
153 resources to process the request.\r
154\r
155 @retval EFI_INVALID_PARAMETER The GUID in InputSection does\r
156 not match this instance of the\r
157 GUIDed Section Extraction PPI.\r
158\r
159**/\r
160EFI_STATUS\r
161EFIAPI\r
162CustomGuidedSectionExtract (\r
163 IN CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *This,\r
164 IN CONST VOID *InputSection,\r
165 OUT VOID **OutputBuffer,\r
166 OUT UINTN *OutputSize,\r
167 OUT UINT32 *AuthenticationStatus\r
168)\r
169{\r
170 EFI_STATUS Status;\r
171 UINT8 *ScratchBuffer;\r
172 UINT32 ScratchBufferSize;\r
173 UINT32 OutputBufferSize;\r
174 UINT16 SectionAttribute;\r
175\r
176 //\r
177 // Init local variable\r
178 //\r
179 ScratchBuffer = NULL;\r
180\r
181 //\r
182 // Call GetInfo to get the size and attribute of input guided section data.\r
183 //\r
184 Status = ExtractGuidedSectionGetInfo (\r
185 InputSection,\r
186 &OutputBufferSize,\r
187 &ScratchBufferSize,\r
188 &SectionAttribute\r
189 );\r
190\r
191 if (EFI_ERROR (Status)) {\r
192 DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));\r
193 return Status;\r
194 }\r
195\r
196 if (ScratchBufferSize != 0) {\r
197 //\r
198 // Allocate scratch buffer\r
199 //\r
200 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
201 if (ScratchBuffer == NULL) {\r
202 return EFI_OUT_OF_RESOURCES;\r
203 }\r
204 }\r
205\r
206 if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {\r
207 //\r
208 // Allocate output buffer\r
209 //\r
210 *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);\r
211 if (*OutputBuffer == NULL) {\r
212 return EFI_OUT_OF_RESOURCES;\r
213 }\r
214 DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));\r
215 //\r
216 // *OutputBuffer still is one section. Adjust *OutputBuffer offset,\r
217 // skip EFI section header to make section data at page alignment.\r
218 //\r
219 *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));\r
220 }\r
221\r
222 Status = ExtractGuidedSectionDecode (\r
223 InputSection,\r
224 OutputBuffer,\r
225 ScratchBuffer,\r
226 AuthenticationStatus\r
227 );\r
228 if (EFI_ERROR (Status)) {\r
229 //\r
230 // Decode failed\r
231 //\r
232 DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));\r
233 return Status;\r
234 }\r
235\r
236 *OutputSize = (UINTN) OutputBufferSize;\r
237\r
238 return EFI_SUCCESS;\r
239}\r
240\r
241\r
242\r
243/**\r
244 Decompresses a section to the output buffer.\r
245\r
246 This function looks up the compression type field in the input section and\r
247 applies the appropriate compression algorithm to compress the section to a\r
248 callee allocated buffer.\r
249\r
250 @param[in] This Points to this instance of the\r
251 EFI_PEI_DECOMPRESS_PEI PPI.\r
252 @param[in] CompressionSection Points to the compressed section.\r
253 @param[out] OutputBuffer Holds the returned pointer to the decompressed\r
254 sections.\r
255 @param[out] OutputSize Holds the returned size of the decompress\r
256 section streams.\r
257\r
258 @retval EFI_SUCCESS The section was decompressed successfully.\r
259 OutputBuffer contains the resulting data and\r
260 OutputSize contains the resulting size.\r
261\r
262**/\r
263EFI_STATUS\r
264EFIAPI\r
265Decompress (\r
266 IN CONST EFI_PEI_DECOMPRESS_PPI *This,\r
267 IN CONST EFI_COMPRESSION_SECTION *CompressionSection,\r
268 OUT VOID **OutputBuffer,\r
269 OUT UINTN *OutputSize\r
270 )\r
271{\r
272 EFI_STATUS Status;\r
273 UINT8 *DstBuffer;\r
274 UINT8 *ScratchBuffer;\r
275 UINT32 DstBufferSize;\r
276 UINT32 ScratchBufferSize;\r
277 VOID *CompressionSource;\r
278 UINT32 CompressionSourceSize;\r
279 UINT32 UncompressedLength;\r
280 UINT8 CompressionType;\r
281\r
282 if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {\r
283 ASSERT (FALSE);\r
284 return EFI_INVALID_PARAMETER;\r
285 }\r
286\r
287 if (IS_SECTION2 (CompressionSection)) {\r
288 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION2));\r
289 CompressionSourceSize = (UINT32) (SECTION2_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION2));\r
290 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->UncompressedLength;\r
291 CompressionType = ((EFI_COMPRESSION_SECTION2 *) CompressionSection)->CompressionType;\r
292 } else {\r
293 CompressionSource = (VOID *) ((UINT8 *) CompressionSection + sizeof (EFI_COMPRESSION_SECTION));\r
294 CompressionSourceSize = (UINT32) (SECTION_SIZE (CompressionSection) - sizeof (EFI_COMPRESSION_SECTION));\r
295 UncompressedLength = CompressionSection->UncompressedLength;\r
296 CompressionType = CompressionSection->CompressionType;\r
297 }\r
298\r
299 //\r
300 // This is a compression set, expand it\r
301 //\r
302 switch (CompressionType) {\r
303 case EFI_STANDARD_COMPRESSION:\r
304 if (TRUE) {\r
305 //\r
306 // Load EFI standard compression.\r
307 // For compressed data, decompress them to destination buffer.\r
308 //\r
309 Status = UefiDecompressGetInfo (\r
310 CompressionSource,\r
311 CompressionSourceSize,\r
312 &DstBufferSize,\r
313 &ScratchBufferSize\r
314 );\r
315 if (EFI_ERROR (Status)) {\r
316 //\r
317 // GetInfo failed\r
318 //\r
319 DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));\r
320 return EFI_NOT_FOUND;\r
321 }\r
322 //\r
323 // Allocate scratch buffer\r
324 //\r
325 ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));\r
326 if (ScratchBuffer == NULL) {\r
327 return EFI_OUT_OF_RESOURCES;\r
328 }\r
329 //\r
330 // Allocate destination buffer, extra one page for adjustment\r
331 //\r
332 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
333 if (DstBuffer == NULL) {\r
334 return EFI_OUT_OF_RESOURCES;\r
335 }\r
336 //\r
337 // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header\r
338 // to make section data at page alignment.\r
339 //\r
340 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
341 //\r
342 // Call decompress function\r
343 //\r
344 Status = UefiDecompress (\r
345 CompressionSource,\r
346 DstBuffer,\r
347 ScratchBuffer\r
348 );\r
349 if (EFI_ERROR (Status)) {\r
350 //\r
351 // Decompress failed\r
352 //\r
353 DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));\r
354 return EFI_NOT_FOUND;\r
355 }\r
356 break;\r
357 } else {\r
358 //\r
359 // PcdDxeIplSupportUefiDecompress is FALSE\r
360 // Don't support UEFI decompression algorithm.\r
361 //\r
362 ASSERT (FALSE);\r
363 return EFI_NOT_FOUND;\r
364 }\r
365\r
366 case EFI_NOT_COMPRESSED:\r
367 //\r
368 // Allocate destination buffer\r
369 //\r
370 DstBufferSize = UncompressedLength;\r
371 DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);\r
372 if (DstBuffer == NULL) {\r
373 return EFI_OUT_OF_RESOURCES;\r
374 }\r
375 //\r
376 // Adjust DstBuffer offset, skip EFI section header\r
377 // to make section data at page alignment.\r
378 //\r
379 DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);\r
380 //\r
381 // stream is not actually compressed, just encapsulated. So just copy it.\r
382 //\r
383 CopyMem (DstBuffer, CompressionSource, DstBufferSize);\r
384 break;\r
385\r
386 default:\r
387 //\r
388 // Don't support other unknown compression type.\r
389 //\r
390 ASSERT (FALSE);\r
391 return EFI_NOT_FOUND;\r
392 }\r
393\r
394 *OutputSize = DstBufferSize;\r
395 *OutputBuffer = DstBuffer;\r
396\r
397 return EFI_SUCCESS;\r
398}\r
399\r
400/**\r
401 Main entry point to last PEIM.\r
402\r
403 This function finds DXE Core in the firmware volume and transfer the control to\r
404 DXE core.\r
405\r
406 @param[in] This Entry point for DXE IPL PPI.\r
407 @param[in] PeiServices General purpose services available to every PEIM.\r
408 @param[in] HobList Address to the Pei HOB list.\r
409\r
410 @return EFI_SUCCESS DXE core was successfully loaded.\r
411 @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.\r
412\r
413**/\r
414EFI_STATUS\r
415EFIAPI\r
416DxeLoadCore (\r
417 IN CONST EFI_DXE_IPL_PPI *This,\r
418 IN EFI_PEI_SERVICES **PeiServices,\r
419 IN EFI_PEI_HOB_POINTERS HobList\r
420 )\r
421{\r
422 EFI_STATUS Status;\r
423\r
424 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));\r
425\r
baaacdc8
JY
426 //\r
427 // End of PEI phase signal\r
428 //\r
429 Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);\r
430 ASSERT_EFI_ERROR (Status);\r
431\r
c8ec22a2 432 //\r
9da59186 433 // Give control back to BootLoader after FspInit\r
c8ec22a2
JY
434 //\r
435 DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));\r
436 FspInitDone ();\r
437\r
438 //\r
9da59186 439 // BootLoader called FSP again through NotifyPhase\r
c8ec22a2
JY
440 //\r
441 FspWaitForNotify ();\r
442\r
c8ec22a2
JY
443\r
444 //\r
445 // Give control back to the boot loader framework caller\r
446 //\r
447 DEBUG ((DEBUG_INFO | DEBUG_INIT, "============= PEIM FSP is Completed =============\n\n"));\r
448\r
449 SetFspApiReturnStatus(EFI_SUCCESS);\r
450\r
451 SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT);\r
452\r
453 Pei2LoaderSwitchStack();\r
454\r
455 //\r
456 // Should not come here\r
457 //\r
458 while (TRUE) {\r
459 DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));\r
460 SetFspApiReturnStatus(EFI_UNSUPPORTED);\r
461 Pei2LoaderSwitchStack();\r
462 }\r
463\r
464 return EFI_SUCCESS;\r
465}\r