1 | /** @file
|
---|
2 |
|
---|
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.
|
---|
8 |
|
---|
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.
|
---|
11 |
|
---|
12 | **/
|
---|
13 |
|
---|
14 | #include "DxeIpl.h"
|
---|
15 |
|
---|
16 |
|
---|
17 | //
|
---|
18 | // Module Globals used in the DXE to PEI hand off
|
---|
19 | // These must be module globals, so the stack can be switched
|
---|
20 | //
|
---|
21 | CONST EFI_DXE_IPL_PPI mDxeIplPpi = {
|
---|
22 | DxeLoadCore
|
---|
23 | };
|
---|
24 |
|
---|
25 | CONST EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI mCustomGuidedSectionExtractionPpi = {
|
---|
26 | CustomGuidedSectionExtract
|
---|
27 | };
|
---|
28 |
|
---|
29 | CONST EFI_PEI_DECOMPRESS_PPI mDecompressPpi = {
|
---|
30 | Decompress
|
---|
31 | };
|
---|
32 |
|
---|
33 | CONST EFI_PEI_PPI_DESCRIPTOR mPpiList[] = {
|
---|
34 | {
|
---|
35 | EFI_PEI_PPI_DESCRIPTOR_PPI,
|
---|
36 | &gEfiDxeIplPpiGuid,
|
---|
37 | (VOID *) &mDxeIplPpi
|
---|
38 | },
|
---|
39 | {
|
---|
40 | (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
---|
41 | &gEfiPeiDecompressPpiGuid,
|
---|
42 | (VOID *) &mDecompressPpi
|
---|
43 | }
|
---|
44 | };
|
---|
45 |
|
---|
46 | CONST EFI_PEI_PPI_DESCRIPTOR gEndOfPeiSignalPpi = {
|
---|
47 | (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
---|
48 | &gEfiEndOfPeiSignalPpiGuid,
|
---|
49 | NULL
|
---|
50 | };
|
---|
51 |
|
---|
52 | /**
|
---|
53 | Entry point of DXE IPL PEIM.
|
---|
54 |
|
---|
55 | This function installs DXE IPL PPI and Decompress PPI. It also reloads
|
---|
56 | itself to memory on non-S3 resume boot path.
|
---|
57 |
|
---|
58 | @param[in] FileHandle Handle of the file being invoked.
|
---|
59 | @param[in] PeiServices Describes the list of possible PEI Services.
|
---|
60 |
|
---|
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.
|
---|
63 |
|
---|
64 | **/
|
---|
65 | EFI_STATUS
|
---|
66 | EFIAPI
|
---|
67 | PeimInitializeDxeIpl (
|
---|
68 | IN EFI_PEI_FILE_HANDLE FileHandle,
|
---|
69 | IN CONST EFI_PEI_SERVICES **PeiServices
|
---|
70 | )
|
---|
71 | {
|
---|
72 | EFI_STATUS Status;
|
---|
73 | EFI_GUID *ExtractHandlerGuidTable;
|
---|
74 | UINTN ExtractHandlerNumber;
|
---|
75 | EFI_PEI_PPI_DESCRIPTOR *GuidPpi;
|
---|
76 |
|
---|
77 | //
|
---|
78 | // Get custom extract guided section method guid list
|
---|
79 | //
|
---|
80 | ExtractHandlerNumber = ExtractGuidedSectionGetGuidList (&ExtractHandlerGuidTable);
|
---|
81 |
|
---|
82 | //
|
---|
83 | // Install custom extraction guid PPI
|
---|
84 | //
|
---|
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);
|
---|
94 | }
|
---|
95 | }
|
---|
96 |
|
---|
97 | //
|
---|
98 | // Install DxeIpl and Decompress PPIs.
|
---|
99 | //
|
---|
100 | Status = PeiServicesInstallPpi (mPpiList);
|
---|
101 | ASSERT_EFI_ERROR(Status);
|
---|
102 |
|
---|
103 | return Status;
|
---|
104 | }
|
---|
105 |
|
---|
106 | /**
|
---|
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.
|
---|
115 |
|
---|
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
|
---|
138 | bit as clear,
|
---|
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
|
---|
146 | undefined.
|
---|
147 |
|
---|
148 | @retval EFI_SUCCESS The InputSection was
|
---|
149 | successfully processed and the
|
---|
150 | section contents were returned.
|
---|
151 |
|
---|
152 | @retval EFI_OUT_OF_RESOURCES The system has insufficient
|
---|
153 | resources to process the request.
|
---|
154 |
|
---|
155 | @retval EFI_INVALID_PARAMETER The GUID in InputSection does
|
---|
156 | not match this instance of the
|
---|
157 | GUIDed Section Extraction PPI.
|
---|
158 |
|
---|
159 | **/
|
---|
160 | EFI_STATUS
|
---|
161 | EFIAPI
|
---|
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
|
---|
168 | )
|
---|
169 | {
|
---|
170 | EFI_STATUS Status;
|
---|
171 | UINT8 *ScratchBuffer;
|
---|
172 | UINT32 ScratchBufferSize;
|
---|
173 | UINT32 OutputBufferSize;
|
---|
174 | UINT16 SectionAttribute;
|
---|
175 |
|
---|
176 | //
|
---|
177 | // Init local variable
|
---|
178 | //
|
---|
179 | ScratchBuffer = NULL;
|
---|
180 |
|
---|
181 | //
|
---|
182 | // Call GetInfo to get the size and attribute of input guided section data.
|
---|
183 | //
|
---|
184 | Status = ExtractGuidedSectionGetInfo (
|
---|
185 | InputSection,
|
---|
186 | &OutputBufferSize,
|
---|
187 | &ScratchBufferSize,
|
---|
188 | &SectionAttribute
|
---|
189 | );
|
---|
190 |
|
---|
191 | if (EFI_ERROR (Status)) {
|
---|
192 | DEBUG ((DEBUG_ERROR, "GetInfo from guided section Failed - %r\n", Status));
|
---|
193 | return Status;
|
---|
194 | }
|
---|
195 |
|
---|
196 | if (ScratchBufferSize != 0) {
|
---|
197 | //
|
---|
198 | // Allocate scratch buffer
|
---|
199 | //
|
---|
200 | ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
|
---|
201 | if (ScratchBuffer == NULL) {
|
---|
202 | return EFI_OUT_OF_RESOURCES;
|
---|
203 | }
|
---|
204 | }
|
---|
205 |
|
---|
206 | if (((SectionAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) && OutputBufferSize > 0) {
|
---|
207 | //
|
---|
208 | // Allocate output buffer
|
---|
209 | //
|
---|
210 | *OutputBuffer = AllocatePages (EFI_SIZE_TO_PAGES (OutputBufferSize) + 1);
|
---|
211 | if (*OutputBuffer == NULL) {
|
---|
212 | return EFI_OUT_OF_RESOURCES;
|
---|
213 | }
|
---|
214 | DEBUG ((DEBUG_INFO, "Customized Guided section Memory Size required is 0x%x and address is 0x%p\n", OutputBufferSize, *OutputBuffer));
|
---|
215 | //
|
---|
216 | // *OutputBuffer still is one section. Adjust *OutputBuffer offset,
|
---|
217 | // skip EFI section header to make section data at page alignment.
|
---|
218 | //
|
---|
219 | *OutputBuffer = (VOID *)((UINT8 *) *OutputBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER));
|
---|
220 | }
|
---|
221 |
|
---|
222 | Status = ExtractGuidedSectionDecode (
|
---|
223 | InputSection,
|
---|
224 | OutputBuffer,
|
---|
225 | ScratchBuffer,
|
---|
226 | AuthenticationStatus
|
---|
227 | );
|
---|
228 | if (EFI_ERROR (Status)) {
|
---|
229 | //
|
---|
230 | // Decode failed
|
---|
231 | //
|
---|
232 | DEBUG ((DEBUG_ERROR, "Extract guided section Failed - %r\n", Status));
|
---|
233 | return Status;
|
---|
234 | }
|
---|
235 |
|
---|
236 | *OutputSize = (UINTN) OutputBufferSize;
|
---|
237 |
|
---|
238 | return EFI_SUCCESS;
|
---|
239 | }
|
---|
240 |
|
---|
241 |
|
---|
242 |
|
---|
243 | /**
|
---|
244 | Decompresses a section to the output buffer.
|
---|
245 |
|
---|
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.
|
---|
249 |
|
---|
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
|
---|
254 | sections.
|
---|
255 | @param[out] OutputSize Holds the returned size of the decompress
|
---|
256 | section streams.
|
---|
257 |
|
---|
258 | @retval EFI_SUCCESS The section was decompressed successfully.
|
---|
259 | OutputBuffer contains the resulting data and
|
---|
260 | OutputSize contains the resulting size.
|
---|
261 |
|
---|
262 | **/
|
---|
263 | EFI_STATUS
|
---|
264 | EFIAPI
|
---|
265 | Decompress (
|
---|
266 | IN CONST EFI_PEI_DECOMPRESS_PPI *This,
|
---|
267 | IN CONST EFI_COMPRESSION_SECTION *CompressionSection,
|
---|
268 | OUT VOID **OutputBuffer,
|
---|
269 | OUT UINTN *OutputSize
|
---|
270 | )
|
---|
271 | {
|
---|
272 | EFI_STATUS Status;
|
---|
273 | UINT8 *DstBuffer;
|
---|
274 | UINT8 *ScratchBuffer;
|
---|
275 | UINT32 DstBufferSize;
|
---|
276 | UINT32 ScratchBufferSize;
|
---|
277 | VOID *CompressionSource;
|
---|
278 | UINT32 CompressionSourceSize;
|
---|
279 | UINT32 UncompressedLength;
|
---|
280 | UINT8 CompressionType;
|
---|
281 |
|
---|
282 | if (CompressionSection->CommonHeader.Type != EFI_SECTION_COMPRESSION) {
|
---|
283 | ASSERT (FALSE);
|
---|
284 | return EFI_INVALID_PARAMETER;
|
---|
285 | }
|
---|
286 |
|
---|
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;
|
---|
292 | } else {
|
---|
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;
|
---|
297 | }
|
---|
298 |
|
---|
299 | //
|
---|
300 | // This is a compression set, expand it
|
---|
301 | //
|
---|
302 | switch (CompressionType) {
|
---|
303 | case EFI_STANDARD_COMPRESSION:
|
---|
304 | //
|
---|
305 | // Load EFI standard compression.
|
---|
306 | // For compressed data, decompress them to destination buffer.
|
---|
307 | //
|
---|
308 | Status = UefiDecompressGetInfo (
|
---|
309 | CompressionSource,
|
---|
310 | CompressionSourceSize,
|
---|
311 | &DstBufferSize,
|
---|
312 | &ScratchBufferSize
|
---|
313 | );
|
---|
314 | if (EFI_ERROR (Status)) {
|
---|
315 | //
|
---|
316 | // GetInfo failed
|
---|
317 | //
|
---|
318 | DEBUG ((DEBUG_ERROR, "Decompress GetInfo Failed - %r\n", Status));
|
---|
319 | return EFI_NOT_FOUND;
|
---|
320 | }
|
---|
321 | //
|
---|
322 | // Allocate scratch buffer
|
---|
323 | //
|
---|
324 | ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize));
|
---|
325 | if (ScratchBuffer == NULL) {
|
---|
326 | return EFI_OUT_OF_RESOURCES;
|
---|
327 | }
|
---|
328 | //
|
---|
329 | // Allocate destination buffer, extra one page for adjustment
|
---|
330 | //
|
---|
331 | DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
|
---|
332 | if (DstBuffer == NULL) {
|
---|
333 | return EFI_OUT_OF_RESOURCES;
|
---|
334 | }
|
---|
335 | //
|
---|
336 | // DstBuffer still is one section. Adjust DstBuffer offset, skip EFI section header
|
---|
337 | // to make section data at page alignment.
|
---|
338 | //
|
---|
339 | DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
|
---|
340 | //
|
---|
341 | // Call decompress function
|
---|
342 | //
|
---|
343 | Status = UefiDecompress (
|
---|
344 | CompressionSource,
|
---|
345 | DstBuffer,
|
---|
346 | ScratchBuffer
|
---|
347 | );
|
---|
348 | if (EFI_ERROR (Status)) {
|
---|
349 | //
|
---|
350 | // Decompress failed
|
---|
351 | //
|
---|
352 | DEBUG ((DEBUG_ERROR, "Decompress Failed - %r\n", Status));
|
---|
353 | return EFI_NOT_FOUND;
|
---|
354 | }
|
---|
355 | break;
|
---|
356 |
|
---|
357 | case EFI_NOT_COMPRESSED:
|
---|
358 | //
|
---|
359 | // Allocate destination buffer
|
---|
360 | //
|
---|
361 | DstBufferSize = UncompressedLength;
|
---|
362 | DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize) + 1);
|
---|
363 | if (DstBuffer == NULL) {
|
---|
364 | return EFI_OUT_OF_RESOURCES;
|
---|
365 | }
|
---|
366 | //
|
---|
367 | // Adjust DstBuffer offset, skip EFI section header
|
---|
368 | // to make section data at page alignment.
|
---|
369 | //
|
---|
370 | DstBuffer = DstBuffer + EFI_PAGE_SIZE - sizeof (EFI_COMMON_SECTION_HEADER);
|
---|
371 | //
|
---|
372 | // stream is not actually compressed, just encapsulated. So just copy it.
|
---|
373 | //
|
---|
374 | CopyMem (DstBuffer, CompressionSource, DstBufferSize);
|
---|
375 | break;
|
---|
376 |
|
---|
377 | default:
|
---|
378 | //
|
---|
379 | // Don't support other unknown compression type.
|
---|
380 | //
|
---|
381 | ASSERT (FALSE);
|
---|
382 | return EFI_NOT_FOUND;
|
---|
383 | }
|
---|
384 |
|
---|
385 | *OutputSize = DstBufferSize;
|
---|
386 | *OutputBuffer = DstBuffer;
|
---|
387 |
|
---|
388 | return EFI_SUCCESS;
|
---|
389 | }
|
---|
390 |
|
---|
391 | /**
|
---|
392 | Main entry point to last PEIM.
|
---|
393 |
|
---|
394 | This function finds DXE Core in the firmware volume and transfer the control to
|
---|
395 | DXE core.
|
---|
396 |
|
---|
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.
|
---|
400 |
|
---|
401 | @return EFI_SUCCESS DXE core was successfully loaded.
|
---|
402 | @return EFI_OUT_OF_RESOURCES There are not enough resources to load DXE core.
|
---|
403 |
|
---|
404 | **/
|
---|
405 | EFI_STATUS
|
---|
406 | EFIAPI
|
---|
407 | DxeLoadCore (
|
---|
408 | IN CONST EFI_DXE_IPL_PPI *This,
|
---|
409 | IN EFI_PEI_SERVICES **PeiServices,
|
---|
410 | IN EFI_PEI_HOB_POINTERS HobList
|
---|
411 | )
|
---|
412 | {
|
---|
413 | EFI_STATUS Status;
|
---|
414 |
|
---|
415 | DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP HOB is located at 0x%08X\n", HobList));
|
---|
416 |
|
---|
417 | //
|
---|
418 | // End of PEI phase signal
|
---|
419 | //
|
---|
420 | Status = PeiServicesInstallPpi (&gEndOfPeiSignalPpi);
|
---|
421 | ASSERT_EFI_ERROR (Status);
|
---|
422 |
|
---|
423 | //
|
---|
424 | // Give control back to BootLoader after FspInit
|
---|
425 | //
|
---|
426 | DEBUG ((DEBUG_INFO | DEBUG_INIT, "FSP is waiting for NOTIFY\n"));
|
---|
427 | FspInitDone ();
|
---|
428 |
|
---|
429 | //
|
---|
430 | // BootLoader called FSP again through NotifyPhase
|
---|
431 | //
|
---|
432 | FspWaitForNotify ();
|
---|
433 |
|
---|
434 |
|
---|
435 | //
|
---|
436 | // Give control back to the boot loader framework caller
|
---|
437 | //
|
---|
438 | DEBUG ((DEBUG_INFO | DEBUG_INIT, "============= PEIM FSP is Completed =============\n\n"));
|
---|
439 |
|
---|
440 | SetFspApiReturnStatus(EFI_SUCCESS);
|
---|
441 |
|
---|
442 | SetFspMeasurePoint (FSP_PERF_ID_API_NOTIFY_RDYBOOT_EXIT);
|
---|
443 |
|
---|
444 | Pei2LoaderSwitchStack();
|
---|
445 |
|
---|
446 | //
|
---|
447 | // Should not come here
|
---|
448 | //
|
---|
449 | while (TRUE) {
|
---|
450 | DEBUG ((DEBUG_ERROR, "No FSP API should be called after FSP is DONE!\n"));
|
---|
451 | SetFspApiReturnStatus(EFI_UNSUPPORTED);
|
---|
452 | Pei2LoaderSwitchStack();
|
---|
453 | }
|
---|
454 |
|
---|
455 | return EFI_SUCCESS;
|
---|
456 | }
|
---|