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