]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Move the Fv updating of PeiCore's internal structure PrivateData out of the implement...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
1 /** @file
2 Pei Core Firmware File System service routines.
3
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "FwVol.h"
16
17 EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnFvInfoList = {
18 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
19 &gEfiPeiFirmwareVolumeInfoPpiGuid,
20 FirmwareVolmeInfoPpiNotifyCallback
21 };
22
23 EFI_PEI_FIRMWARE_VOLUME_PPI mPeiFfs2FvPpi = {
24 PeiFfs2FvPpiProcessVolume,
25 PeiFfs2FvPpiFindFileByType,
26 PeiFfs2FvPpiFindFileByName,
27 PeiFfs2FvPpiGetFileInfo,
28 PeiFfs2FvPpiGetVolumeInfo,
29 PeiFfs2FvPpiFindSectionByType
30 };
31
32 EFI_PEI_PPI_DESCRIPTOR mPeiFfs2FvPpiList = {
33 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
34 &gEfiFirmwareFileSystem2Guid,
35 &mPeiFfs2FvPpi
36 };
37
38 /**
39 Returns the file state set by the highest zero bit in the State field
40
41 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
42 in the Attributes field.
43 @param FfsHeader Pointer to FFS File Header.
44
45 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
46 in the header State field.
47 **/
48 EFI_FFS_FILE_STATE
49 GetFileState(
50 IN UINT8 ErasePolarity,
51 IN EFI_FFS_FILE_HEADER *FfsHeader
52 )
53 {
54 EFI_FFS_FILE_STATE FileState;
55 EFI_FFS_FILE_STATE HighestBit;
56
57 FileState = FfsHeader->State;
58
59 if (ErasePolarity != 0) {
60 FileState = (EFI_FFS_FILE_STATE)~FileState;
61 }
62
63 //
64 // Get file state set by its highest none zero bit.
65 //
66 HighestBit = 0x80;
67 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
68 HighestBit >>= 1;
69 }
70
71 return HighestBit;
72 }
73
74 /**
75 Calculates the checksum of the header of a file.
76
77 @param FileHeader Pointer to FFS File Header.
78
79 @return Checksum of the header.
80 Zero means the header is good.
81 Non-zero means the header is bad.
82 **/
83 UINT8
84 CalculateHeaderChecksum (
85 IN EFI_FFS_FILE_HEADER *FileHeader
86 )
87 {
88 EFI_FFS_FILE_HEADER TestFileHeader;
89
90 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));
91 //
92 // Ingore State and File field in FFS header.
93 //
94 TestFileHeader.State = 0;
95 TestFileHeader.IntegrityCheck.Checksum.File = 0;
96
97 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));
98 }
99
100 /**
101 Find FV handler according to FileHandle in that FV.
102
103 @param FileHandle Handle of file image
104
105 @return Pointer to instance of PEI_CORE_FV_HANDLE.
106 **/
107 PEI_CORE_FV_HANDLE*
108 FileHandleToVolume (
109 IN EFI_PEI_FILE_HANDLE FileHandle
110 )
111 {
112 UINTN Index;
113 PEI_CORE_INSTANCE *PrivateData;
114 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
115
116 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
117
118 for (Index = 0; Index < PrivateData->FvCount; Index++) {
119 FwVolHeader = PrivateData->Fv[Index].FvHeader;
120 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \
121 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {
122 return &PrivateData->Fv[Index];
123 }
124 }
125 return NULL;
126 }
127
128 /**
129 Given the input file pointer, search for the first matching file in the
130 FFS volume as defined by SearchType. The search starts from FileHeader inside
131 the Firmware Volume defined by FwVolHeader.
132 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
133 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
134 the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
135
136 @param FvHandle Pointer to the FV header of the volume to search
137 @param FileName File name
138 @param SearchType Filter to find only files of this type.
139 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
140 @param FileHandle This parameter must point to a valid FFS volume.
141 @param AprioriFile Pointer to AprioriFile image in this FV if has
142
143 @return EFI_NOT_FOUND No files matching the search criteria were found
144 @retval EFI_SUCCESS Success to search given file
145
146 **/
147 EFI_STATUS
148 FindFileEx (
149 IN CONST EFI_PEI_FV_HANDLE FvHandle,
150 IN CONST EFI_GUID *FileName, OPTIONAL
151 IN EFI_FV_FILETYPE SearchType,
152 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,
153 IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL
154 )
155 {
156 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
157 EFI_FFS_FILE_HEADER **FileHeader;
158 EFI_FFS_FILE_HEADER *FfsFileHeader;
159 UINT32 FileLength;
160 UINT32 FileOccupiedSize;
161 UINT32 FileOffset;
162 UINT64 FvLength;
163 UINT8 ErasePolarity;
164 UINT8 FileState;
165
166 //
167 // Convert the handle of FV to FV header for memory-mapped firmware volume
168 //
169 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvHandle;
170 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;
171
172 FvLength = FwVolHeader->FvLength;
173 if ((FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) != 0) {
174 ErasePolarity = 1;
175 } else {
176 ErasePolarity = 0;
177 }
178
179 //
180 // If FileHeader is not specified (NULL) or FileName is not NULL,
181 // start with the first file in the firmware volume. Otherwise,
182 // start from the FileHeader.
183 //
184 if ((*FileHeader == NULL) || (FileName != NULL)) {
185 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
186 } else {
187 //
188 // Length is 24 bits wide so mask upper 8 bits
189 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
190 //
191 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
192 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
193 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
194 }
195
196 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
197 ASSERT (FileOffset <= 0xFFFFFFFF);
198
199 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
200 //
201 // Get FileState which is the highest bit of the State
202 //
203 FileState = GetFileState (ErasePolarity, FfsFileHeader);
204 switch (FileState) {
205
206 case EFI_FILE_HEADER_INVALID:
207 FileOffset += sizeof(EFI_FFS_FILE_HEADER);
208 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
209 break;
210
211 case EFI_FILE_DATA_VALID:
212 case EFI_FILE_MARKED_FOR_UPDATE:
213 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
214 ASSERT (FALSE);
215 *FileHeader = NULL;
216 return EFI_NOT_FOUND;
217 }
218
219 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
220 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
221
222 if (FileName != NULL) {
223 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {
224 *FileHeader = FfsFileHeader;
225 return EFI_SUCCESS;
226 }
227 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {
228 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
229 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||
230 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) {
231
232 *FileHeader = FfsFileHeader;
233 return EFI_SUCCESS;
234 } else if (AprioriFile != NULL) {
235 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {
236 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {
237 *AprioriFile = FfsFileHeader;
238 }
239 }
240 }
241 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&
242 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) {
243 *FileHeader = FfsFileHeader;
244 return EFI_SUCCESS;
245 }
246
247 FileOffset += FileOccupiedSize;
248 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
249 break;
250
251 case EFI_FILE_DELETED:
252 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
253 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
254 FileOffset += FileOccupiedSize;
255 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
256 break;
257
258 default:
259 *FileHeader = NULL;
260 return EFI_NOT_FOUND;
261 }
262 }
263
264 *FileHeader = NULL;
265 return EFI_NOT_FOUND;
266 }
267
268 /**
269 Initialize PeiCore Fv List.
270
271 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
272 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
273 **/
274 VOID
275 PeiInitializeFv (
276 IN PEI_CORE_INSTANCE *PrivateData,
277 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
278 )
279 {
280 EFI_STATUS Status;
281 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
282 EFI_PEI_FV_HANDLE FvHandle;
283 EFI_FIRMWARE_VOLUME_HEADER *BfvHeader;
284
285 //
286 // Install FV_PPI for FFS2 file system.
287 //
288 PeiServicesInstallPpi (&mPeiFfs2FvPpiList);
289
290 BfvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
291
292 //
293 // The FV_PPI in BFV's format should be installed.
294 //
295 Status = PeiServicesLocatePpi (
296 &BfvHeader->FileSystemGuid,
297 0,
298 NULL,
299 (VOID**)&FvPpi
300 );
301 ASSERT_EFI_ERROR (Status);
302
303 //
304 // Get handle of BFV
305 //
306 FvPpi->ProcessVolume (
307 FvPpi,
308 SecCoreData->BootFirmwareVolumeBase,
309 (UINTN)BfvHeader->FvLength,
310 &FvHandle
311 );
312
313 //
314 // Update internal PEI_CORE_FV array.
315 //
316 PrivateData->Fv[PrivateData->FvCount].FvHeader = BfvHeader;
317 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
318 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
319 DEBUG ((
320 EFI_D_INFO,
321 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
322 (UINT32) PrivateData->FvCount,
323 (VOID *) BfvHeader,
324 BfvHeader->FvLength,
325 FvHandle
326 ));
327 PrivateData->FvCount ++;
328
329 //
330 // Post a call-back for the FvInfoPPI services to expose
331 // additional Fvs to PeiCore.
332 //
333 Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList);
334 ASSERT_EFI_ERROR (Status);
335
336 }
337
338 /**
339 Process Firmware Volum Information once FvInfoPPI install.
340 The FV Info will be registered into PeiCore private data structure.
341 And search the inside FV image, if found, the new FV INFO PPI will be installed.
342
343 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
344 @param NotifyDescriptor Address of the notification descriptor data structure.
345 @param Ppi Address of the PPI that was installed.
346
347 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
348 @return if not EFI_SUCESS, fail to verify FV.
349
350 **/
351 EFI_STATUS
352 EFIAPI
353 FirmwareVolmeInfoPpiNotifyCallback (
354 IN EFI_PEI_SERVICES **PeiServices,
355 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
356 IN VOID *Ppi
357 )
358 {
359 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
360 EFI_PEI_FIRMWARE_VOLUME_PPI *FvPpi;
361 PEI_CORE_INSTANCE *PrivateData;
362 EFI_STATUS Status;
363 EFI_PEI_FV_HANDLE FvHandle;
364 UINTN FvIndex;
365 EFI_PEI_FILE_HANDLE FileHandle;
366 VOID *DepexData;
367
368 Status = EFI_SUCCESS;
369 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
370
371 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
372 DEBUG ((EFI_D_ERROR, "The number of Fv Images (%d) exceed the max supported FVs (%d) in Pei", PrivateData->FvCount + 1, FixedPcdGet32 (PcdPeiCoreMaxFvSupported)));
373 DEBUG ((EFI_D_ERROR, "PcdPeiCoreMaxFvSupported value need be reconfigurated in DSC"));
374 ASSERT (FALSE);
375 }
376
377 FvInfoPpi = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;
378
379 //
380 // Locate the corresponding FV_PPI according to founded FV's format guid
381 //
382 Status = PeiServicesLocatePpi (
383 &FvInfoPpi->FvFormat,
384 0,
385 NULL,
386 (VOID**)&FvPpi
387 );
388 if (!EFI_ERROR (Status)) {
389 //
390 // Process new found FV and get FV handle.
391 //
392 Status = FvPpi->ProcessVolume (FvPpi, FvInfoPpi->FvInfo, FvInfoPpi->FvInfoSize, &FvHandle);
393 if (EFI_ERROR (Status)) {
394 DEBUG ((EFI_D_ERROR, "Fail to process new found FV, FV may be corrupted!\n"));
395 return Status;
396 }
397
398 //
399 // Check whether the FV has already been processed.
400 //
401 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
402 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
403 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvInfoPpi->FvInfo));
404 return EFI_SUCCESS;
405 }
406 }
407
408 //
409 // Update internal PEI_CORE_FV array.
410 //
411 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;
412 PrivateData->Fv[PrivateData->FvCount].FvPpi = FvPpi;
413 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
414 DEBUG ((
415 EFI_D_INFO,
416 "The %dth FV start address is 0x%11p, size is 0x%08x, handle is 0x%p\n",
417 (UINT32) PrivateData->FvCount,
418 (VOID *) FvInfoPpi->FvInfo,
419 FvInfoPpi->FvInfoSize,
420 FvHandle
421 ));
422 PrivateData->FvCount ++;
423
424 //
425 // Scan and process the new discoveried FV for EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
426 //
427 FileHandle = NULL;
428 do {
429 Status = FvPpi->FindFileByType (
430 FvPpi,
431 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
432 FvHandle,
433 &FileHandle
434 );
435 if (!EFI_ERROR (Status)) {
436 Status = FvPpi->FindSectionByType (
437 FvPpi,
438 EFI_SECTION_PEI_DEPEX,
439 FileHandle,
440 (VOID**)&DepexData
441 );
442 if (!EFI_ERROR (Status)) {
443 if (!PeimDispatchReadiness (PeiServices, DepexData)) {
444 //
445 // Dependency is not satisfied.
446 //
447 continue;
448 }
449 }
450
451 DEBUG ((EFI_D_INFO, "Found firmware volume Image File %p in FV[%d] %p\n", FileHandle, PrivateData->FvCount - 1, FvHandle));
452 ProcessFvFile (&PrivateData->Fv[PrivateData->FvCount - 1], FileHandle);
453 }
454 } while (FileHandle != NULL);
455 } else {
456 DEBUG ((EFI_D_ERROR, "Fail to process FV %p because no corresponding EFI_FIRMWARE_VOLUME_PPI is found!\n", FvInfoPpi->FvInfo));
457
458 //
459 // If can not find EFI_FIRMWARE_VOLUME_PPI to process firmware to get FvHandle,
460 // use the address of FV buffer as its handle.
461 //
462 FvHandle = FvInfoPpi->FvInfo;
463
464 //
465 // Check whether the FV has already been processed.
466 //
467 for (FvIndex = 0; FvIndex < PrivateData->FvCount; FvIndex ++) {
468 if (PrivateData->Fv[FvIndex].FvHandle == FvHandle) {
469 DEBUG ((EFI_D_INFO, "The Fv %p has already been processed!\n", FvHandle));
470 return EFI_SUCCESS;
471 }
472 }
473
474 PrivateData->Fv[PrivateData->FvCount].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) FvInfoPpi->FvInfo;
475 PrivateData->Fv[PrivateData->FvCount].FvPpi = NULL;
476 PrivateData->Fv[PrivateData->FvCount].FvHandle = FvHandle;
477 PrivateData->FvCount ++;
478 }
479
480 return EFI_SUCCESS;
481 }
482
483 /**
484 Go through the file to search SectionType section.
485 Search within encapsulation sections (compression and GUIDed) recursively,
486 until the match section is found.
487
488 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
489 @param SectionType Filter to find only section of this type.
490 @param Section From where to search.
491 @param SectionSize The file size to search.
492 @param OutputBuffer A pointer to the discovered section, if successful.
493 NULL if section not found
494
495 @return EFI_NOT_FOUND The match section is not found.
496 @return EFI_SUCCESS The match section is found.
497
498 **/
499 EFI_STATUS
500 ProcessSection (
501 IN CONST EFI_PEI_SERVICES **PeiServices,
502 IN EFI_SECTION_TYPE SectionType,
503 IN EFI_COMMON_SECTION_HEADER *Section,
504 IN UINTN SectionSize,
505 OUT VOID **OutputBuffer
506 )
507 {
508 EFI_STATUS Status;
509 UINT32 SectionLength;
510 UINT32 ParsedLength;
511 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;
512 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;
513 VOID *PpiOutput;
514 UINTN PpiOutputSize;
515 UINTN Index;
516 UINT32 Authentication;
517 PEI_CORE_INSTANCE *PrivateData;
518
519 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
520 *OutputBuffer = NULL;
521 ParsedLength = 0;
522 Index = 0;
523 Status = EFI_NOT_FOUND;
524 PpiOutput = NULL;
525 PpiOutputSize = 0;
526 while (ParsedLength < SectionSize) {
527 if (Section->Type == SectionType) {
528 *OutputBuffer = (VOID *)(Section + 1);
529 return EFI_SUCCESS;
530 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {
531 //
532 // Check the encapsulated section is extracted into the cache data.
533 //
534 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {
535 if (Section == PrivateData->CacheSection.Section[Index]) {
536 PpiOutput = PrivateData->CacheSection.SectionData[Index];
537 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];
538 //
539 // Search section directly from the cache data.
540 //
541 return ProcessSection (
542 PeiServices,
543 SectionType,
544 PpiOutput,
545 PpiOutputSize,
546 OutputBuffer
547 );
548 }
549 }
550
551 Status = EFI_NOT_FOUND;
552 if (Section->Type == EFI_SECTION_GUID_DEFINED) {
553 Status = PeiServicesLocatePpi (
554 &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid,
555 0,
556 NULL,
557 (VOID **) &GuidSectionPpi
558 );
559 if (!EFI_ERROR (Status)) {
560 Status = GuidSectionPpi->ExtractSection (
561 GuidSectionPpi,
562 Section,
563 &PpiOutput,
564 &PpiOutputSize,
565 &Authentication
566 );
567 }
568 } else if (Section->Type == EFI_SECTION_COMPRESSION) {
569 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);
570 if (!EFI_ERROR (Status)) {
571 Status = DecompressPpi->Decompress (
572 DecompressPpi,
573 (CONST EFI_COMPRESSION_SECTION*) Section,
574 &PpiOutput,
575 &PpiOutputSize
576 );
577 }
578 }
579
580 if (!EFI_ERROR (Status)) {
581 //
582 // Update cache section data.
583 //
584 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {
585 PrivateData->CacheSection.AllSectionCount ++;
586 }
587 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;
588 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;
589 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;
590 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;
591
592 return ProcessSection (
593 PeiServices,
594 SectionType,
595 PpiOutput,
596 PpiOutputSize,
597 OutputBuffer
598 );
599 }
600 }
601
602 //
603 // Size is 24 bits wide so mask upper 8 bits.
604 // SectionLength is adjusted it is 4 byte aligned.
605 // Go to the next section
606 //
607 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
608 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
609 ASSERT (SectionLength != 0);
610 ParsedLength += SectionLength;
611 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
612 }
613
614 return EFI_NOT_FOUND;
615 }
616
617
618 /**
619 Searches for the next matching section within the specified file.
620
621 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
622 @param SectionType Filter to find only sections of this type.
623 @param FileHandle Pointer to the current file to search.
624 @param SectionData A pointer to the discovered section, if successful.
625 NULL if section not found
626
627 @retval EFI_NOT_FOUND The section was not found.
628 @retval EFI_SUCCESS The section was found.
629
630 **/
631 EFI_STATUS
632 EFIAPI
633 PeiFfsFindSectionData (
634 IN CONST EFI_PEI_SERVICES **PeiServices,
635 IN EFI_SECTION_TYPE SectionType,
636 IN EFI_PEI_FILE_HANDLE FileHandle,
637 OUT VOID **SectionData
638 )
639 {
640 PEI_CORE_FV_HANDLE *CoreFvHandle;
641
642 CoreFvHandle = FileHandleToVolume (FileHandle);
643 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
644 return EFI_NOT_FOUND;
645 }
646
647 return CoreFvHandle->FvPpi->FindSectionByType (CoreFvHandle->FvPpi, SectionType, FileHandle, SectionData);
648 }
649
650 /**
651 Searches for the next matching file in the firmware volume.
652
653 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
654 @param SearchType Filter to find only files of this type.
655 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
656 @param VolumeHandle Handle of firmware volume in which to search.
657 @param FileHandle On entry, points to the current handle from which to begin searching or NULL to start
658 at the beginning of the firmware volume. On exit, points the file handle of the next file
659 in the volume or NULL if there are no more files.
660
661 @retval EFI_NOT_FOUND The file was not found.
662 @retval EFI_NOT_FOUND The header checksum was not zero.
663 @retval EFI_SUCCESS The file was found.
664
665 **/
666 EFI_STATUS
667 EFIAPI
668 PeiFfsFindNextFile (
669 IN CONST EFI_PEI_SERVICES **PeiServices,
670 IN UINT8 SearchType,
671 IN EFI_PEI_FV_HANDLE FvHandle,
672 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
673 )
674 {
675 PEI_CORE_FV_HANDLE *CoreFvHandle;
676
677 CoreFvHandle = FvHandleToCoreHandle (FvHandle);
678
679 //
680 // To make backward compatiblity, if can not find corresponding the handle of FV
681 // then treat FV as build-in FFS2 format and memory mapped FV that FV handle is pointed
682 // to the address of first byte of FV.
683 //
684 if ((CoreFvHandle == NULL) && FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
685 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
686 }
687
688 if ((CoreFvHandle == NULL) || CoreFvHandle->FvPpi == NULL) {
689 return EFI_NOT_FOUND;
690 }
691
692 return CoreFvHandle->FvPpi->FindFileByType (CoreFvHandle->FvPpi, SearchType, FvHandle, FileHandle);
693 }
694
695
696 /**
697 Search the firmware volumes by index
698
699 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
700 @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware
701 Volume (BFV).
702 @param VolumeHandle On exit, points to the next volume handle or NULL if it does not exist.
703
704 @retval EFI_INVALID_PARAMETER VolumeHandle is NULL
705 @retval EFI_NOT_FOUND The volume was not found.
706 @retval EFI_SUCCESS The volume was found.
707
708 **/
709 EFI_STATUS
710 EFIAPI
711 PeiFfsFindNextVolume (
712 IN CONST EFI_PEI_SERVICES **PeiServices,
713 IN UINTN Instance,
714 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
715 )
716 {
717 PEI_CORE_INSTANCE *Private;
718 PEI_CORE_FV_HANDLE *CoreFvHandle;
719
720 if (VolumeHandle == NULL) {
721 return EFI_INVALID_PARAMETER;
722 }
723
724 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
725
726 CoreFvHandle = FindNextCoreFvHandle (Private, Instance);
727 if (CoreFvHandle == NULL) {
728 *VolumeHandle = NULL;
729 return EFI_NOT_FOUND;
730 }
731
732 *VolumeHandle = CoreFvHandle->FvHandle;
733
734 return EFI_SUCCESS;
735 }
736
737
738 /**
739 Find a file within a volume by its name.
740
741 @param FileName A pointer to the name of the file to find within the firmware volume.
742 @param VolumeHandle The firmware volume to search
743 @param FileHandle Upon exit, points to the found file's handle
744 or NULL if it could not be found.
745
746 @retval EFI_SUCCESS File was found.
747 @retval EFI_NOT_FOUND File was not found.
748 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
749
750 **/
751 EFI_STATUS
752 EFIAPI
753 PeiFfsFindFileByName (
754 IN CONST EFI_GUID *FileName,
755 IN EFI_PEI_FV_HANDLE VolumeHandle,
756 OUT EFI_PEI_FILE_HANDLE *FileHandle
757 )
758 {
759 PEI_CORE_FV_HANDLE *CoreFvHandle;
760
761 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
762 return EFI_INVALID_PARAMETER;
763 }
764
765 CoreFvHandle = FvHandleToCoreHandle (VolumeHandle);
766 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
767 return EFI_NOT_FOUND;
768 }
769
770 return CoreFvHandle->FvPpi->FindFileByName (CoreFvHandle->FvPpi, FileName, &VolumeHandle, FileHandle);
771 }
772
773 /**
774 Returns information about a specific file.
775
776 @param FileHandle Handle of the file.
777 @param FileInfo Upon exit, points to the file’s information.
778
779 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
780 @retval EFI_INVALID_PARAMETER If FileHandle does not represent a valid file.
781 @retval EFI_SUCCESS File information returned.
782
783 **/
784 EFI_STATUS
785 EFIAPI
786 PeiFfsGetFileInfo (
787 IN EFI_PEI_FILE_HANDLE FileHandle,
788 OUT EFI_FV_FILE_INFO *FileInfo
789 )
790 {
791 PEI_CORE_FV_HANDLE *CoreFvHandle;
792
793 if ((FileHandle == NULL) || (FileInfo == NULL)) {
794 return EFI_INVALID_PARAMETER;
795 }
796
797 //
798 // Retrieve the FirmwareVolume which the file resides in.
799 //
800 CoreFvHandle = FileHandleToVolume (FileHandle);
801 if ((CoreFvHandle == NULL) || (CoreFvHandle->FvPpi == NULL)) {
802 return EFI_INVALID_PARAMETER;
803 }
804
805 return CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, FileHandle, FileInfo);
806 }
807
808
809 /**
810 Returns information about the specified volume.
811
812 This function returns information about a specific firmware
813 volume, including its name, type, attributes, starting address
814 and size.
815
816 @param VolumeHandle Handle of the volume.
817 @param VolumeInfo Upon exit, points to the volume's information.
818
819 @retval EFI_SUCCESS Volume information returned.
820 @retval EFI_INVALID_PARAMETER If VolumeHandle does not represent a valid volume.
821 @retval EFI_INVALID_PARAMETER If VolumeHandle is NULL.
822 @retval EFI_SUCCESS Information successfully returned.
823 @retval EFI_INVALID_PARAMETER The volume designated by the VolumeHandle is not available.
824
825 **/
826 EFI_STATUS
827 EFIAPI
828 PeiFfsGetVolumeInfo (
829 IN EFI_PEI_FV_HANDLE VolumeHandle,
830 OUT EFI_FV_INFO *VolumeInfo
831 )
832 {
833 PEI_CORE_FV_HANDLE *CoreHandle;
834
835 if (VolumeInfo == NULL) {
836 return EFI_INVALID_PARAMETER;
837 }
838
839 CoreHandle = FvHandleToCoreHandle (VolumeHandle);
840
841 if ((CoreHandle == NULL) || (CoreHandle->FvPpi == NULL)) {
842 return EFI_INVALID_PARAMETER;
843 }
844
845 return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);
846 }
847
848 /**
849 Get Fv image from the FV type file, then install FV INFO ppi, Build FV hob.
850
851 @param ParentFvCoreHandle Pointer of EFI_CORE_FV_HANDLE to parent Fv image that contain this Fv image.
852 @param ParentFvFileHandle File handle of a Fv type file that contain this Fv image.
853
854 @retval EFI_NOT_FOUND FV image can't be found.
855 @retval EFI_SUCCESS Successfully to process it.
856 @retval EFI_OUT_OF_RESOURCES Can not allocate page when aligning FV image
857 @retval Others Can not find EFI_SECTION_FIRMWARE_VOLUME_IMAGE section
858
859 **/
860 EFI_STATUS
861 ProcessFvFile (
862 IN PEI_CORE_FV_HANDLE *ParentFvCoreHandle,
863 IN EFI_PEI_FILE_HANDLE ParentFvFileHandle
864 )
865 {
866 EFI_STATUS Status;
867 EFI_FV_INFO ParentFvImageInfo;
868 UINT32 FvAlignment;
869 VOID *NewFvBuffer;
870 EFI_PEI_HOB_POINTERS HobPtr;
871 EFI_PEI_FIRMWARE_VOLUME_PPI *ParentFvPpi;
872 EFI_PEI_FV_HANDLE ParentFvHandle;
873 EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
874 EFI_FV_FILE_INFO FileInfo;
875
876 //
877 // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already
878 // been extracted.
879 //
880 HobPtr.Raw = GetHobList ();
881 while ((HobPtr.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobPtr.Raw)) != NULL) {
882 if (CompareGuid (&(((EFI_FFS_FILE_HEADER *)ParentFvFileHandle)->Name), &HobPtr.FirmwareVolume2->FileName)) {
883 //
884 // this FILE has been dispatched, it will not be dispatched again.
885 //
886 DEBUG ((EFI_D_INFO, "FV file %p has been dispatched!\r\n", ParentFvFileHandle));
887 return EFI_SUCCESS;
888 }
889 HobPtr.Raw = GET_NEXT_HOB (HobPtr);
890 }
891
892 ParentFvHandle = ParentFvCoreHandle->FvHandle;
893 ParentFvPpi = ParentFvCoreHandle->FvPpi;
894
895 //
896 // Find FvImage in FvFile
897 //
898 Status = ParentFvPpi->FindSectionByType (
899 ParentFvPpi,
900 EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
901 ParentFvFileHandle,
902 (VOID **)&FvHeader
903 );
904
905 if (EFI_ERROR (Status)) {
906 return Status;
907 }
908
909 //
910 // FvAlignment must be more than 8 bytes required by FvHeader structure.
911 //
912 FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
913 if (FvAlignment < 8) {
914 FvAlignment = 8;
915 }
916
917 //
918 // Check FvImage
919 //
920 if ((UINTN) FvHeader % FvAlignment != 0) {
921 NewFvBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINT32) FvHeader->FvLength), FvAlignment);
922 if (NewFvBuffer == NULL) {
923 return EFI_OUT_OF_RESOURCES;
924 }
925 CopyMem (NewFvBuffer, FvHeader, (UINTN) FvHeader->FvLength);
926 FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;
927 }
928
929 Status = ParentFvPpi->GetVolumeInfo (ParentFvPpi, ParentFvHandle, &ParentFvImageInfo);
930 ASSERT_EFI_ERROR (Status);
931
932 Status = ParentFvPpi->GetFileInfo (ParentFvPpi, ParentFvFileHandle, &FileInfo);
933 ASSERT_EFI_ERROR (Status);
934
935 //
936 // Install FvPpi and Build FvHob
937 //
938 PeiServicesInstallFvInfoPpi (
939 &FvHeader->FileSystemGuid,
940 (VOID**) FvHeader,
941 (UINT32) FvHeader->FvLength,
942 &ParentFvImageInfo.FvName,
943 &FileInfo.FileName
944 );
945
946 //
947 // Inform the extracted FvImage to Fv HOB consumer phase, i.e. DXE phase
948 //
949 BuildFvHob (
950 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
951 FvHeader->FvLength
952 );
953
954 //
955 // Makes the encapsulated volume show up in DXE phase to skip processing of
956 // encapsulated file again.
957 //
958 BuildFv2Hob (
959 (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,
960 FvHeader->FvLength,
961 &ParentFvImageInfo.FvName,
962 &FileInfo.FileName
963 );
964
965 return EFI_SUCCESS;
966 }
967
968 /**
969 Process a firmware volume and create a volume handle.
970
971 Create a volume handle from the information in the buffer. For
972 memory-mapped firmware volumes, Buffer and BufferSize refer to
973 the start of the firmware volume and the firmware volume size.
974 For non memory-mapped firmware volumes, this points to a
975 buffer which contains the necessary information for creating
976 the firmware volume handle. Normally, these values are derived
977 from the EFI_FIRMWARE_VOLUME_INFO_PPI.
978
979
980 @param This Points to this instance of the
981 EFI_PEI_FIRMWARE_VOLUME_PPI.
982 @param Buffer Points to the start of the buffer.
983 @param BufferSize Size of the buffer.
984 @param FvHandle Points to the returned firmware volume
985 handle. The firmware volume handle must
986 be unique within the system.
987
988 @retval EFI_SUCCESS Firmware volume handle created.
989 @retval EFI_VOLUME_CORRUPTED Volume was corrupt.
990
991 **/
992 EFI_STATUS
993 EFIAPI
994 PeiFfs2FvPpiProcessVolume (
995 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
996 IN VOID *Buffer,
997 IN UINTN BufferSize,
998 OUT EFI_PEI_FV_HANDLE *FvHandle
999 )
1000 {
1001 EFI_STATUS Status;
1002
1003 ASSERT (FvHandle != NULL);
1004
1005 if (Buffer == NULL) {
1006 return EFI_VOLUME_CORRUPTED;
1007 }
1008
1009 //
1010 // The build-in EFI_PEI_FIRMWARE_VOLUME_PPI for FFS2 support memory-mapped
1011 // FV image and the handle is pointed to Fv image's buffer.
1012 //
1013 *FvHandle = (EFI_PEI_FV_HANDLE) Buffer;
1014
1015 //
1016 // Do verify for given FV buffer.
1017 //
1018 Status = VerifyFv ((EFI_FIRMWARE_VOLUME_HEADER*) Buffer);
1019 if (EFI_ERROR(Status)) {
1020 DEBUG ((EFI_D_ERROR, "Fail to verify FV which address is 0x%11p", Buffer));
1021 return EFI_VOLUME_CORRUPTED;
1022 }
1023
1024 return EFI_SUCCESS;
1025 }
1026
1027 /**
1028 Finds the next file of the specified type.
1029
1030 This service enables PEI modules to discover additional firmware files.
1031 The FileHandle must be unique within the system.
1032
1033 @param This Points to this instance of the
1034 EFI_PEI_FIRMWARE_VOLUME_PPI.
1035 @param SearchType A filter to find only files of this type. Type
1036 EFI_FV_FILETYPE_ALL causes no filtering to be
1037 done.
1038 @param FvHandle Handle of firmware volume in which to
1039 search.
1040 @param FileHandle Points to the current handle from which to
1041 begin searching or NULL to start at the
1042 beginning of the firmware volume. Updated
1043 upon return to reflect the file found.
1044
1045 @retval EFI_SUCCESS The file was found.
1046 @retval EFI_NOT_FOUND The file was not found. FileHandle contains NULL.
1047
1048 **/
1049 EFI_STATUS
1050 EFIAPI
1051 PeiFfs2FvPpiFindFileByType (
1052 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1053 IN EFI_FV_FILETYPE SearchType,
1054 IN EFI_PEI_FV_HANDLE FvHandle,
1055 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
1056 )
1057 {
1058 return FindFileEx (FvHandle, NULL, SearchType, FileHandle, NULL);
1059 }
1060
1061 /**
1062 Find a file within a volume by its name.
1063
1064 This service searches for files with a specific name, within
1065 either the specified firmware volume or all firmware volumes.
1066
1067 @param This Points to this instance of the
1068 EFI_PEI_FIRMWARE_VOLUME_PPI.
1069 @param FileName A pointer to the name of the file to find
1070 within the firmware volume.
1071 @param FvHandle Upon entry, the pointer to the firmware
1072 volume to search or NULL if all firmware
1073 volumes should be searched. Upon exit, the
1074 actual firmware volume in which the file was
1075 found.
1076 @param FileHandle Upon exit, points to the found file's
1077 handle or NULL if it could not be found.
1078
1079 @retval EFI_SUCCESS File was found.
1080 @retval EFI_NOT_FOUND File was not found.
1081 @retval EFI_INVALID_PARAMETER FvHandle or FileHandle or
1082 FileName was NULL.
1083
1084
1085 **/
1086 EFI_STATUS
1087 EFIAPI
1088 PeiFfs2FvPpiFindFileByName (
1089 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1090 IN CONST EFI_GUID *FileName,
1091 IN EFI_PEI_FV_HANDLE *FvHandle,
1092 OUT EFI_PEI_FILE_HANDLE *FileHandle
1093 )
1094 {
1095 EFI_STATUS Status;
1096 PEI_CORE_INSTANCE *PrivateData;
1097 UINTN Index;
1098
1099 if ((FvHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
1100 return EFI_INVALID_PARAMETER;
1101 }
1102
1103 if (*FvHandle != NULL) {
1104 Status = FindFileEx (*FvHandle, FileName, 0, FileHandle, NULL);
1105 if (Status == EFI_NOT_FOUND) {
1106 *FileHandle = NULL;
1107 }
1108 } else {
1109 //
1110 // If *FvHandle = NULL, so search all FV for given filename
1111 //
1112 Status = EFI_NOT_FOUND;
1113
1114 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1115 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1116 //
1117 // Only search the FV which is associated with a EFI_PEI_FIRMWARE_VOLUME_PPI instance.
1118 //
1119 if (PrivateData->Fv[Index].FvPpi != NULL) {
1120 Status = FindFileEx (PrivateData->Fv[Index].FvHandle, FileName, 0, FileHandle, NULL);
1121 if (!EFI_ERROR (Status)) {
1122 *FvHandle = PrivateData->Fv[Index].FvHandle;
1123 }
1124 }
1125 }
1126 }
1127
1128 return Status;
1129 }
1130
1131 /**
1132 Returns information about a specific file.
1133
1134 This function returns information about a specific
1135 file, including its file name, type, attributes, starting
1136 address and size.
1137
1138 @param This Points to this instance of the
1139 EFI_PEI_FIRMWARE_VOLUME_PPI.
1140 @param FileHandle Handle of the file.
1141 @param FileInfo Upon exit, points to the file's
1142 information.
1143
1144 @retval EFI_SUCCESS File information returned.
1145 @retval EFI_INVALID_PARAMETER If FileHandle does not
1146 represent a valid file.
1147 @retval EFI_INVALID_PARAMETER If FileInfo is NULL.
1148
1149 **/
1150 EFI_STATUS
1151 EFIAPI
1152 PeiFfs2FvPpiGetFileInfo (
1153 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1154 IN EFI_PEI_FILE_HANDLE FileHandle,
1155 OUT EFI_FV_FILE_INFO *FileInfo
1156 )
1157 {
1158 UINT8 FileState;
1159 UINT8 ErasePolarity;
1160 EFI_FFS_FILE_HEADER *FileHeader;
1161 PEI_CORE_FV_HANDLE *CoreFvHandle;
1162
1163 if ((FileHandle == NULL) || (FileInfo == NULL)) {
1164 return EFI_INVALID_PARAMETER;
1165 }
1166
1167 //
1168 // Retrieve the FirmwareVolume which the file resides in.
1169 //
1170 CoreFvHandle = FileHandleToVolume (FileHandle);
1171 if (CoreFvHandle == NULL) {
1172 return EFI_INVALID_PARAMETER;
1173 }
1174
1175 if (CoreFvHandle->FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
1176 ErasePolarity = 1;
1177 } else {
1178 ErasePolarity = 0;
1179 }
1180
1181 //
1182 // Get FileState which is the highest bit of the State
1183 //
1184 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
1185
1186 switch (FileState) {
1187 case EFI_FILE_DATA_VALID:
1188 case EFI_FILE_MARKED_FOR_UPDATE:
1189 break;
1190 default:
1191 return EFI_INVALID_PARAMETER;
1192 }
1193
1194 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
1195 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
1196 FileInfo->FileType = FileHeader->Type;
1197 FileInfo->FileAttributes = FileHeader->Attributes;
1198 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);
1199 FileInfo->Buffer = (FileHeader + 1);
1200 return EFI_SUCCESS;
1201 }
1202
1203 /**
1204 This function returns information about the firmware volume.
1205
1206 @param This Points to this instance of the
1207 EFI_PEI_FIRMWARE_VOLUME_PPI.
1208 @param FvHandle Handle to the firmware handle.
1209 @param VolumeInfo Points to the returned firmware volume
1210 information.
1211
1212 @retval EFI_SUCCESS Information returned successfully.
1213 @retval EFI_INVALID_PARAMETER FvHandle does not indicate a valid
1214 firmware volume or VolumeInfo is NULL.
1215
1216 **/
1217 EFI_STATUS
1218 EFIAPI
1219 PeiFfs2FvPpiGetVolumeInfo (
1220 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1221 IN EFI_PEI_FV_HANDLE FvHandle,
1222 OUT EFI_FV_INFO *VolumeInfo
1223 )
1224 {
1225 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
1226 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
1227
1228 if (VolumeInfo == NULL) {
1229 return EFI_INVALID_PARAMETER;
1230 }
1231
1232 //
1233 // VolumeHandle may not align at 8 byte,
1234 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
1235 // So, Copy FvHeader into the local FvHeader structure.
1236 //
1237 CopyMem (&FwVolHeader, FvHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
1238
1239 //
1240 // Check Fv Image Signature
1241 //
1242 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
1243 return EFI_INVALID_PARAMETER;
1244 }
1245
1246 ZeroMem (VolumeInfo, sizeof (EFI_FV_INFO));
1247 VolumeInfo->FvAttributes = FwVolHeader.Attributes;
1248 VolumeInfo->FvStart = (VOID *) FvHandle;
1249 VolumeInfo->FvSize = FwVolHeader.FvLength;
1250 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
1251
1252 if (FwVolHeader.ExtHeaderOffset != 0) {
1253 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)FvHandle) + FwVolHeader.ExtHeaderOffset);
1254 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
1255 }
1256
1257 return EFI_SUCCESS;
1258 }
1259
1260 /**
1261 Find the next matching section in the firmware file.
1262
1263 This service enables PEI modules to discover sections
1264 of a given type within a valid file.
1265
1266 @param This Points to this instance of the
1267 EFI_PEI_FIRMWARE_VOLUME_PPI.
1268 @param SearchType A filter to find only sections of this
1269 type.
1270 @param FileHandle Handle of firmware file in which to
1271 search.
1272 @param SectionData Updated upon return to point to the
1273 section found.
1274
1275 @retval EFI_SUCCESS Section was found.
1276 @retval EFI_NOT_FOUND Section of the specified type was not
1277 found. SectionData contains NULL.
1278 **/
1279 EFI_STATUS
1280 EFIAPI
1281 PeiFfs2FvPpiFindSectionByType (
1282 IN CONST EFI_PEI_FIRMWARE_VOLUME_PPI *This,
1283 IN EFI_SECTION_TYPE SearchType,
1284 IN EFI_PEI_FILE_HANDLE FileHandle,
1285 OUT VOID **SectionData
1286 )
1287 {
1288 EFI_FFS_FILE_HEADER *FfsFileHeader;
1289 UINT32 FileSize;
1290 EFI_COMMON_SECTION_HEADER *Section;
1291
1292 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
1293
1294 //
1295 // Size is 24 bits wide so mask upper 8 bits.
1296 // Does not include FfsFileHeader header size
1297 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
1298 //
1299 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
1300 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
1301 FileSize -= sizeof (EFI_FFS_FILE_HEADER);
1302
1303 return ProcessSection (
1304 GetPeiServicesTablePointer (),
1305 SearchType,
1306 Section,
1307 FileSize,
1308 SectionData
1309 );
1310 }
1311
1312 /**
1313 Convert the handle of FV to pointer of corresponding PEI_CORE_FV_HANDLE.
1314
1315 @param FvHandle The handle of a FV.
1316
1317 @retval NULL if can not find.
1318 @return Pointer of corresponding PEI_CORE_FV_HANDLE.
1319 **/
1320 PEI_CORE_FV_HANDLE *
1321 FvHandleToCoreHandle (
1322 IN EFI_PEI_FV_HANDLE FvHandle
1323 )
1324 {
1325 UINTN Index;
1326 PEI_CORE_INSTANCE *PrivateData;
1327
1328 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer());
1329 for (Index = 0; Index < PrivateData->FvCount; Index ++) {
1330 if (FvHandle == PrivateData->Fv[Index].FvHandle) {
1331 return &PrivateData->Fv[Index];
1332 }
1333 }
1334
1335 return NULL;
1336 }
1337
1338 /**
1339 Get instance of PEI_CORE_FV_HANDLE for next volume according to given index.
1340
1341 This routine also will install FvInfo ppi for FV hob in PI ways.
1342
1343 @param Private Pointer of PEI_CORE_INSTANCE
1344 @param Instance The index of FV want to be searched.
1345
1346 @return Instance of PEI_CORE_FV_HANDLE.
1347 **/
1348 PEI_CORE_FV_HANDLE *
1349 FindNextCoreFvHandle (
1350 IN PEI_CORE_INSTANCE *Private,
1351 IN UINTN Instance
1352 )
1353 {
1354 UINTN Index;
1355 BOOLEAN Match;
1356 EFI_HOB_FIRMWARE_VOLUME *FvHob;
1357
1358 //
1359 // Handle Framework FvHob and Install FvInfo Ppi for it.
1360 //
1361 if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {
1362 //
1363 // Loop to search the wanted FirmwareVolume which supports FFS
1364 //
1365 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);
1366 while (FvHob != NULL) {
1367 for (Index = 0, Match = FALSE; Index < Private->FvCount; Index++) {
1368 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->Fv[Index].FvHeader) {
1369 Match = TRUE;
1370 break;
1371 }
1372 }
1373 //
1374 // If Not Found, Install FvInfo Ppi for it.
1375 //
1376 if (!Match) {
1377 PeiServicesInstallFvInfoPpi (
1378 &(((EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvHob->BaseAddress)->FileSystemGuid),
1379 (VOID *)(UINTN)FvHob->BaseAddress,
1380 (UINT32)FvHob->Length,
1381 NULL,
1382 NULL
1383 );
1384 }
1385 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength));
1386 }
1387 }
1388
1389 if (Instance >= Private->FvCount) {
1390 return NULL;
1391 }
1392
1393 return &Private->Fv[Instance];
1394 }
1395
1396 /**
1397 After PeiCore image is shadowed into permanent memory, all build-in FvPpi should
1398 be re-installed with the instance in permanent memory and all cached FvPpi pointers in
1399 PrivateData->Fv[] array should be fixed up to be pointed to the one in permenant
1400 memory.
1401
1402 @param PrivateData Pointer to PEI_CORE_INSTANCE.
1403 **/
1404 VOID
1405 PeiReinitializeFv (
1406 IN PEI_CORE_INSTANCE *PrivateData
1407 )
1408 {
1409 VOID *OldFfs2FvPpi;
1410 EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
1411 UINTN Index;
1412 EFI_STATUS Status;
1413
1414 //
1415 // Locate old build-in Ffs2 EFI_PEI_FIRMWARE_VOLUME_PPI which
1416 // in flash.
1417 //
1418 Status = PeiServicesLocatePpi (
1419 &gEfiFirmwareFileSystem2Guid,
1420 0,
1421 &OldDescriptor,
1422 &OldFfs2FvPpi
1423 );
1424 ASSERT_EFI_ERROR (Status);
1425
1426 //
1427 // Re-install the EFI_PEI_FIRMWARE_VOLUME_PPI for build-in Ffs2
1428 // which is shadowed from flash to permanent memory within PeiCore image.
1429 //
1430 Status = PeiServicesReInstallPpi (OldDescriptor, &mPeiFfs2FvPpiList);
1431 ASSERT_EFI_ERROR (Status);
1432
1433 //
1434 // Fixup all FvPpi pointers for the implementation in flash to permanent memory.
1435 //
1436 for (Index = 0; Index < FixedPcdGet32 (PcdPeiCoreMaxFvSupported); Index ++) {
1437 if (PrivateData->Fv[Index].FvPpi == OldFfs2FvPpi) {
1438 PrivateData->Fv[Index].FvPpi = &mPeiFfs2FvPpi;
1439 }
1440 }
1441 }
1442