]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Pei/FwVol/FwVol.c
Add compatibility logic to handle framework fvhob and install FvInfo ppi. And remove...
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
1 /** @file
2 Pei Core Firmware File System service routines.
3
4 Copyright (c) 2006 - 2008, 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 <PeiMain.h>
16
17 STATIC 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
24 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
25 ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
26
27 /**
28 Returns the file state set by the highest zero bit in the State field
29
30 @param ErasePolarity Erase Polarity as defined by EFI_FVB2_ERASE_POLARITY
31 in the Attributes field.
32 @param FfsHeader Pointer to FFS File Header.
33
34 @retval EFI_FFS_FILE_STATE File state is set by the highest none zero bit
35 in the header State field.
36 **/
37 EFI_FFS_FILE_STATE
38 GetFileState(
39 IN UINT8 ErasePolarity,
40 IN EFI_FFS_FILE_HEADER *FfsHeader
41 )
42 {
43 EFI_FFS_FILE_STATE FileState;
44 EFI_FFS_FILE_STATE HighestBit;
45
46 FileState = FfsHeader->State;
47
48 if (ErasePolarity != 0) {
49 FileState = (EFI_FFS_FILE_STATE)~FileState;
50 }
51
52 //
53 // Get file state set by its highest none zero bit.
54 //
55 HighestBit = 0x80;
56 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
57 HighestBit >>= 1;
58 }
59
60 return HighestBit;
61 }
62
63 /**
64 Calculates the checksum of the header of a file.
65
66 @param FileHeader Pointer to FFS File Header.
67
68 @return Checksum of the header.
69 Zero means the header is good.
70 Non-zero means the header is bad.
71 **/
72 UINT8
73 CalculateHeaderChecksum (
74 IN EFI_FFS_FILE_HEADER *FileHeader
75 )
76 {
77 EFI_FFS_FILE_HEADER TestFileHeader;
78
79 CopyMem (&TestFileHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER));
80 //
81 // Ingore State and File field in FFS header.
82 //
83 TestFileHeader.State = 0;
84 TestFileHeader.IntegrityCheck.Checksum.File = 0;
85
86 return CalculateSum8 ((CONST UINT8 *) &TestFileHeader, sizeof (EFI_FFS_FILE_HEADER));
87 }
88
89 /**
90 Find FV handler according some FileHandle in that FV.
91
92 @param FileHandle Handle of file image
93 @param VolumeHandle Handle of the found FV, if not found, NULL will be set.
94
95 @retval TRUE The corresponding FV handler is found.
96 @retval FALSE The corresponding FV handler is not found.
97
98 **/
99 BOOLEAN
100 EFIAPI
101 PeiFileHandleToVolume (
102 IN EFI_PEI_FILE_HANDLE FileHandle,
103 OUT EFI_PEI_FV_HANDLE *VolumeHandle
104 )
105 {
106 UINTN Index;
107 PEI_CORE_INSTANCE *PrivateData;
108 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
109
110 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());
111 for (Index = 0; Index < PrivateData->FvCount; Index++) {
112 FwVolHeader = PrivateData->Fv[Index].FvHeader;
113 if (((UINT64) (UINTN) FileHandle > (UINT64) (UINTN) FwVolHeader ) && \
114 ((UINT64) (UINTN) FileHandle <= ((UINT64) (UINTN) FwVolHeader + FwVolHeader->FvLength - 1))) {
115 *VolumeHandle = (EFI_PEI_FV_HANDLE)FwVolHeader;
116 return TRUE;
117 }
118 }
119 *VolumeHandle = NULL;
120 return FALSE;
121 }
122
123 /**
124 Given the input file pointer, search for the first matching file in the
125 FFS volume as defined by SearchType. The search starts from FileHeader inside
126 the Firmware Volume defined by FwVolHeader.
127 If SearchType is EFI_FV_FILETYPE_ALL, the first FFS file will return without check its file type.
128 If SearchType is PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE,
129 the first PEIM, or COMBINED PEIM or FV file type FFS file will return.
130
131 @param FvHandle Pointer to the FV header of the volume to search
132 @param FileName File name
133 @param SearchType Filter to find only files of this type.
134 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
135 @param FileHandle This parameter must point to a valid FFS volume.
136 @param AprioriFile Pointer to AprioriFile image in this FV if has
137
138 @return EFI_NOT_FOUND No files matching the search criteria were found
139 @retval EFI_SUCCESS Success to search given file
140
141 **/
142 EFI_STATUS
143 PeiFindFileEx (
144 IN CONST EFI_PEI_FV_HANDLE FvHandle,
145 IN CONST EFI_GUID *FileName, OPTIONAL
146 IN EFI_FV_FILETYPE SearchType,
147 IN OUT EFI_PEI_FILE_HANDLE *FileHandle,
148 IN OUT EFI_PEI_FV_HANDLE *AprioriFile OPTIONAL
149 )
150 {
151 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
152 EFI_FFS_FILE_HEADER **FileHeader;
153 EFI_FFS_FILE_HEADER *FfsFileHeader;
154 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
155 UINT32 FileLength;
156 UINT32 FileOccupiedSize;
157 UINT32 FileOffset;
158 UINT64 FvLength;
159 UINT8 ErasePolarity;
160 UINT8 FileState;
161
162 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FvHandle;
163 FileHeader = (EFI_FFS_FILE_HEADER **)FileHandle;
164
165 FvLength = FwVolHeader->FvLength;
166 if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
167 ErasePolarity = 1;
168 } else {
169 ErasePolarity = 0;
170 }
171
172 //
173 // If FileHeader is not specified (NULL) or FileName is not NULL,
174 // start with the first file in the firmware volume. Otherwise,
175 // start from the FileHeader.
176 //
177 if ((*FileHeader == NULL) || (FileName != NULL)) {
178 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength);
179 if (FwVolHeader->ExtHeaderOffset != 0) {
180 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(((UINT8 *)FwVolHeader) + FwVolHeader->ExtHeaderOffset);
181 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FwVolExHeaderInfo) + FwVolExHeaderInfo->ExtHeaderSize);
182 }
183 } else {
184 //
185 // Length is 24 bits wide so mask upper 8 bits
186 // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
187 //
188 FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF;
189 FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8);
190 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize);
191 }
192
193 FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader);
194 ASSERT (FileOffset <= 0xFFFFFFFF);
195
196 while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
197 //
198 // Get FileState which is the highest bit of the State
199 //
200 FileState = GetFileState (ErasePolarity, FfsFileHeader);
201 switch (FileState) {
202
203 case EFI_FILE_HEADER_INVALID:
204 FileOffset += sizeof(EFI_FFS_FILE_HEADER);
205 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER));
206 break;
207
208 case EFI_FILE_DATA_VALID:
209 case EFI_FILE_MARKED_FOR_UPDATE:
210 if (CalculateHeaderChecksum (FfsFileHeader) != 0) {
211 ASSERT (FALSE);
212 *FileHeader = NULL;
213 return EFI_NOT_FOUND;
214 }
215
216 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
217 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
218
219 if (FileName != NULL) {
220 if (CompareGuid (&FfsFileHeader->Name, (EFI_GUID*)FileName)) {
221 *FileHeader = FfsFileHeader;
222 return EFI_SUCCESS;
223 }
224 } else if (SearchType == PEI_CORE_INTERNAL_FFS_FILE_DISPATCH_TYPE) {
225 if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) ||
226 (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER) ||
227 (FfsFileHeader->Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE)) {
228
229 *FileHeader = FfsFileHeader;
230 return EFI_SUCCESS;
231 } else if (AprioriFile != NULL) {
232 if (FfsFileHeader->Type == EFI_FV_FILETYPE_FREEFORM) {
233 if (CompareGuid (&FfsFileHeader->Name, &gPeiAprioriFileNameGuid)) {
234 *AprioriFile = FfsFileHeader;
235 }
236 }
237 }
238 } else if (((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) &&
239 (FfsFileHeader->Type != EFI_FV_FILETYPE_FFS_PAD)) {
240 *FileHeader = FfsFileHeader;
241 return EFI_SUCCESS;
242 }
243
244 FileOffset += FileOccupiedSize;
245 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
246 break;
247
248 case EFI_FILE_DELETED:
249 FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
250 FileOccupiedSize = GET_OCCUPIED_SIZE(FileLength, 8);
251 FileOffset += FileOccupiedSize;
252 FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize);
253 break;
254
255 default:
256 *FileHeader = NULL;
257 return EFI_NOT_FOUND;
258 }
259 }
260
261 *FileHeader = NULL;
262 return EFI_NOT_FOUND;
263 }
264
265 /**
266 Initialize PeiCore Fv List.
267
268 @param PrivateData - Pointer to PEI_CORE_INSTANCE.
269 @param SecCoreData - Pointer to EFI_SEC_PEI_HAND_OFF.
270 **/
271 VOID
272 PeiInitializeFv (
273 IN PEI_CORE_INSTANCE *PrivateData,
274 IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
275 )
276 {
277 EFI_STATUS Status;
278 //
279 // The BFV must be the first entry. The Core FV support is stateless
280 // The AllFV list has a single entry per FV in PEI.
281 // The Fv list only includes FV that PEIMs will be dispatched from and
282 // its File System Format is PI 1.0 definition.
283 //
284 PrivateData->FvCount = 1;
285 PrivateData->Fv[0].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
286
287 PrivateData->AllFvCount = 1;
288 PrivateData->AllFv[0] = (EFI_PEI_FV_HANDLE)PrivateData->Fv[0].FvHeader;
289
290
291 //
292 // Post a call-back for the FvInfoPPI services to expose
293 // additional Fvs to PeiCore.
294 //
295 Status = PeiServicesNotifyPpi (&mNotifyOnFvInfoList);
296 ASSERT_EFI_ERROR (Status);
297
298 }
299
300 /**
301 Process Firmware Volum Information once FvInfoPPI install.
302 The FV Info will be registered into PeiCore private data structure.
303 And search the inside FV image, if found, the new FV INFO PPI will be installed.
304
305 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
306 @param NotifyDescriptor Address of the notification descriptor data structure.
307 @param Ppi Address of the PPI that was installed.
308
309 @retval EFI_SUCCESS The FV Info is registered into PeiCore private data structure.
310
311 **/
312 EFI_STATUS
313 EFIAPI
314 FirmwareVolmeInfoPpiNotifyCallback (
315 IN EFI_PEI_SERVICES **PeiServices,
316 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
317 IN VOID *Ppi
318 )
319 {
320 UINT8 FvCount;
321 EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *Fv;
322 PEI_CORE_INSTANCE *PrivateData;
323 EFI_PEI_FILE_HANDLE FileHandle;
324 VOID *DepexData;
325 UINT32 AuthenticationStatus;
326 EFI_STATUS Status;
327
328 FileHandle = NULL;
329 DepexData = NULL;
330 Status = EFI_SUCCESS;
331 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
332
333 if (PrivateData->FvCount >= FixedPcdGet32 (PcdPeiCoreMaxFvSupported)) {
334 ASSERT (FALSE);
335 }
336
337 Fv = (EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *)Ppi;
338
339 if (CompareGuid (&Fv->FvFormat, &gEfiFirmwareFileSystem2Guid)) {
340 for (FvCount = 0; FvCount < PrivateData->FvCount; FvCount ++) {
341 if ((UINTN)PrivateData->Fv[FvCount].FvHeader == (UINTN)Fv->FvInfo) {
342 return EFI_SUCCESS;
343 }
344 }
345 PrivateData->Fv[PrivateData->FvCount++].FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv->FvInfo;
346
347 //
348 // Only add FileSystem2 Fv to the All list
349 //
350 PrivateData->AllFv[PrivateData->AllFvCount++] = (EFI_PEI_FV_HANDLE)Fv->FvInfo;
351
352 DEBUG ((EFI_D_INFO, "The %dth FvImage start address is 0x%11p and size is 0x%08x\n", PrivateData->AllFvCount, (VOID *) Fv->FvInfo, Fv->FvInfoSize));
353 //
354 // Preprocess all FV type files in this new FileSystem2 Fv image
355 //
356 do {
357 Status = PeiFindFileEx (
358 (EFI_PEI_FV_HANDLE)Fv->FvInfo,
359 NULL,
360 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
361 &FileHandle,
362 NULL
363 );
364 if (!EFI_ERROR (Status)) {
365 Status = PeiFfsFindSectionData (
366 (CONST EFI_PEI_SERVICES **) PeiServices,
367 EFI_SECTION_PEI_DEPEX,
368 FileHandle,
369 (VOID **)&DepexData
370 );
371 if (!EFI_ERROR (Status)) {
372 if (!PeimDispatchReadiness (PeiServices, DepexData)) {
373 //
374 // Dependency is not satisfied.
375 //
376 continue;
377 }
378 }
379 //
380 // Process FvFile to install FvInfo ppi and build FvHob
381 //
382 ProcessFvFile (PeiServices, FileHandle, &AuthenticationStatus);
383 }
384 } while (FileHandle != NULL);
385 }
386
387 return EFI_SUCCESS;
388 }
389
390 /**
391 Go through the file to search SectionType section.
392 Search within encapsulation sections (compression and GUIDed) recursively,
393 until the match section is found.
394
395 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
396 @param SectionType - Filter to find only section of this type.
397 @param Section - From where to search.
398 @param SectionSize - The file size to search.
399 @param OutputBuffer - A pointer to the discovered section, if successful.
400 NULL if section not found
401
402 @return EFI_NOT_FOUND The match section is not found.
403 @return EFI_SUCCESS The match section is found.
404
405 **/
406 EFI_STATUS
407 PeiFfsProcessSection (
408 IN CONST EFI_PEI_SERVICES **PeiServices,
409 IN EFI_SECTION_TYPE SectionType,
410 IN EFI_COMMON_SECTION_HEADER *Section,
411 IN UINTN SectionSize,
412 OUT VOID **OutputBuffer
413 )
414 {
415 EFI_STATUS Status;
416 UINT32 SectionLength;
417 UINT32 ParsedLength;
418 EFI_PEI_GUIDED_SECTION_EXTRACTION_PPI *GuidSectionPpi;
419 EFI_PEI_DECOMPRESS_PPI *DecompressPpi;
420 VOID *PpiOutput;
421 UINTN PpiOutputSize;
422 UINTN Index;
423 UINT32 Authentication;
424 PEI_CORE_INSTANCE *PrivateData;
425
426 PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
427 *OutputBuffer = NULL;
428 ParsedLength = 0;
429 Index = 0;
430 Status = EFI_NOT_FOUND;
431 PpiOutput = NULL;
432 PpiOutputSize = 0;
433 while (ParsedLength < SectionSize) {
434 if (Section->Type == SectionType) {
435 *OutputBuffer = (VOID *)(Section + 1);
436 return EFI_SUCCESS;
437 } else if ((Section->Type == EFI_SECTION_GUID_DEFINED) || (Section->Type == EFI_SECTION_COMPRESSION)) {
438 //
439 // Check the encapsulated section is extracted into the cache data.
440 //
441 for (Index = 0; Index < PrivateData->CacheSection.AllSectionCount; Index ++) {
442 if (Section == PrivateData->CacheSection.Section[Index]) {
443 PpiOutput = PrivateData->CacheSection.SectionData[Index];
444 PpiOutputSize = PrivateData->CacheSection.SectionSize[Index];
445 //
446 // Search section directly from the cache data.
447 //
448 return PeiFfsProcessSection (
449 PeiServices,
450 SectionType,
451 PpiOutput,
452 PpiOutputSize,
453 OutputBuffer
454 );
455 }
456 }
457
458 Status = EFI_NOT_FOUND;
459 if (Section->Type == EFI_SECTION_GUID_DEFINED) {
460 Status = PeiServicesLocatePpi (
461 &((EFI_GUID_DEFINED_SECTION *)Section)->SectionDefinitionGuid,
462 0,
463 NULL,
464 (VOID **) &GuidSectionPpi
465 );
466 if (!EFI_ERROR (Status)) {
467 Status = GuidSectionPpi->ExtractSection (
468 GuidSectionPpi,
469 Section,
470 &PpiOutput,
471 &PpiOutputSize,
472 &Authentication
473 );
474 }
475 } else if (Section->Type == EFI_SECTION_COMPRESSION) {
476 Status = PeiServicesLocatePpi (&gEfiPeiDecompressPpiGuid, 0, NULL, (VOID **) &DecompressPpi);
477 if (!EFI_ERROR (Status)) {
478 Status = DecompressPpi->Decompress (
479 DecompressPpi,
480 (CONST EFI_COMPRESSION_SECTION*) Section,
481 &PpiOutput,
482 &PpiOutputSize
483 );
484 }
485 }
486
487 if (!EFI_ERROR (Status)) {
488 //
489 // Update cache section data.
490 //
491 if (PrivateData->CacheSection.AllSectionCount < CACHE_SETION_MAX_NUMBER) {
492 PrivateData->CacheSection.AllSectionCount ++;
493 }
494 PrivateData->CacheSection.Section [PrivateData->CacheSection.SectionIndex] = Section;
495 PrivateData->CacheSection.SectionData [PrivateData->CacheSection.SectionIndex] = PpiOutput;
496 PrivateData->CacheSection.SectionSize [PrivateData->CacheSection.SectionIndex] = PpiOutputSize;
497 PrivateData->CacheSection.SectionIndex = (PrivateData->CacheSection.SectionIndex + 1)%CACHE_SETION_MAX_NUMBER;
498
499 return PeiFfsProcessSection (
500 PeiServices,
501 SectionType,
502 PpiOutput,
503 PpiOutputSize,
504 OutputBuffer
505 );
506 }
507 }
508
509 //
510 // Size is 24 bits wide so mask upper 8 bits.
511 // SectionLength is adjusted it is 4 byte aligned.
512 // Go to the next section
513 //
514 SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF;
515 SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
516 ASSERT (SectionLength != 0);
517 ParsedLength += SectionLength;
518 Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength);
519 }
520
521 return EFI_NOT_FOUND;
522 }
523
524
525 /**
526 Given the input file pointer, search for the first matching section in the
527 FFS volume.
528
529 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
530 @param SectionType Filter to find only sections of this type.
531 @param FileHandle Pointer to the current file to search.
532 @param SectionData A pointer to the discovered section, if successful.
533 NULL if section not found
534
535 @retval EFI_NOT_FOUND No files matching the search criteria were found
536 @retval EFI_SUCCESS Success to find section data in given file
537
538 **/
539 EFI_STATUS
540 EFIAPI
541 PeiFfsFindSectionData (
542 IN CONST EFI_PEI_SERVICES **PeiServices,
543 IN EFI_SECTION_TYPE SectionType,
544 IN EFI_PEI_FILE_HANDLE FileHandle,
545 IN OUT VOID **SectionData
546 )
547 {
548 EFI_FFS_FILE_HEADER *FfsFileHeader;
549 UINT32 FileSize;
550 EFI_COMMON_SECTION_HEADER *Section;
551
552 FfsFileHeader = (EFI_FFS_FILE_HEADER *)(FileHandle);
553
554 //
555 // Size is 24 bits wide so mask upper 8 bits.
556 // Does not include FfsFileHeader header size
557 // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
558 //
559 Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1);
560 FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF;
561 FileSize -= sizeof (EFI_FFS_FILE_HEADER);
562
563 return PeiFfsProcessSection (
564 PeiServices,
565 SectionType,
566 Section,
567 FileSize,
568 SectionData
569 );
570 }
571
572 /**
573 Given the input file pointer, search for the next matching file in the
574 FFS volume as defined by SearchType. The search starts from FileHeader inside
575 the Firmware Volume defined by FwVolHeader.
576
577
578 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
579 @param SearchType Filter to find only files of this type.
580 Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
581 @param VolumeHandle Pointer to the FV header of the volume to search.
582 @param FileHandle Pointer to the current file from which to begin searching.
583 This pointer will be updated upon return to reflect the file found.
584 @retval EFI_NOT_FOUND No files matching the search criteria were found
585 @retval EFI_SUCCESS Success to find next file in given volume
586
587 **/
588 EFI_STATUS
589 EFIAPI
590 PeiFfsFindNextFile (
591 IN CONST EFI_PEI_SERVICES **PeiServices,
592 IN UINT8 SearchType,
593 IN EFI_PEI_FV_HANDLE VolumeHandle,
594 IN OUT EFI_PEI_FILE_HANDLE *FileHandle
595 )
596 {
597 return PeiFindFileEx (VolumeHandle, NULL, SearchType, FileHandle, NULL);
598 }
599
600
601 /**
602 Search the firmware volumes by index
603
604 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
605 @param Instance Instance of FV to find
606 @param VolumeHandle Pointer to found Volume.
607
608 @retval EFI_INVALID_PARAMETER FwVolHeader is NULL
609 @retval EFI_SUCCESS Firmware volume instance successfully found.
610
611 **/
612 EFI_STATUS
613 EFIAPI
614 PeiFvFindNextVolume (
615 IN CONST EFI_PEI_SERVICES **PeiServices,
616 IN UINTN Instance,
617 IN OUT EFI_PEI_FV_HANDLE *VolumeHandle
618 )
619 {
620 PEI_CORE_INSTANCE *Private;
621 UINTN Index;
622 BOOLEAN Match;
623 EFI_HOB_FIRMWARE_VOLUME *FvHob;
624
625 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices);
626 if (VolumeHandle == NULL) {
627 return EFI_INVALID_PARAMETER;
628 }
629
630 //
631 // Handle Framework FvHob and Install FvInfo Ppi for it.
632 //
633 if (FeaturePcdGet (PcdFrameworkFvHobCompatibilitySupport)) {
634 //
635 // Loop to search the wanted FirmwareVolume which supports FFS
636 //
637 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetFirstHob (EFI_HOB_TYPE_FV);
638 while (FvHob != NULL) {
639 for (Index = 0, Match = FALSE; Index < Private->AllFvCount; Index++) {
640 if ((EFI_PEI_FV_HANDLE)(UINTN)FvHob->BaseAddress == Private->AllFv[Index]) {
641 Match = TRUE;
642 break;
643 }
644 }
645 //
646 // If Not Found, Install FvInfo Ppi for it.
647 //
648 if (!Match) {
649 PiLibInstallFvInfoPpi (
650 NULL,
651 (VOID *)(UINTN)FvHob->BaseAddress,
652 (UINT32)FvHob->Length,
653 NULL,
654 NULL
655 );
656 }
657 FvHob = (EFI_HOB_FIRMWARE_VOLUME *)GetNextHob (EFI_HOB_TYPE_FV, (VOID *)((UINTN)FvHob + FvHob->Header.HobLength));
658 }
659 }
660
661 if (Instance >= Private->AllFvCount) {
662 VolumeHandle = NULL;
663 return EFI_NOT_FOUND;
664 }
665
666 *VolumeHandle = Private->AllFv[Instance];
667 return EFI_SUCCESS;
668 }
669
670
671 /**
672 Find a file within a volume by its name.
673
674 @param FileName A pointer to the name of the file to find within the firmware volume.
675 @param VolumeHandle The firmware volume to search
676 @param FileHandle Upon exit, points to the found file's handle
677 or NULL if it could not be found.
678
679 @retval EFI_SUCCESS File was found.
680 @retval EFI_NOT_FOUND File was not found.
681 @retval EFI_INVALID_PARAMETER VolumeHandle or FileHandle or FileName was NULL.
682
683 **/
684 EFI_STATUS
685 EFIAPI
686 PeiFfsFindFileByName (
687 IN CONST EFI_GUID *FileName,
688 IN EFI_PEI_FV_HANDLE VolumeHandle,
689 OUT EFI_PEI_FILE_HANDLE *FileHandle
690 )
691 {
692 EFI_STATUS Status;
693 if ((VolumeHandle == NULL) || (FileName == NULL) || (FileHandle == NULL)) {
694 return EFI_INVALID_PARAMETER;
695 }
696 Status = PeiFindFileEx (VolumeHandle, FileName, 0, FileHandle, NULL);
697 if (Status == EFI_NOT_FOUND) {
698 *FileHandle = NULL;
699 }
700 return Status;
701 }
702
703 /**
704
705 Returns information about a specific file.
706
707
708 @param FileHandle - The handle to file.
709 @param FileInfo - Pointer to the file information.
710
711 @retval EFI_INVALID_PARAMETER Invalid FileHandle or FileInfo.
712 @retval EFI_SUCCESS Success to collect file info.
713
714 **/
715 EFI_STATUS
716 EFIAPI
717 PeiFfsGetFileInfo (
718 IN EFI_PEI_FILE_HANDLE FileHandle,
719 OUT EFI_FV_FILE_INFO *FileInfo
720 )
721 {
722 UINT8 FileState;
723 UINT8 ErasePolarity;
724 EFI_FFS_FILE_HEADER *FileHeader;
725 EFI_PEI_FV_HANDLE VolumeHandle;
726
727 if ((FileHandle == NULL) || (FileInfo == NULL)) {
728 return EFI_INVALID_PARAMETER;
729 }
730
731 VolumeHandle = 0;
732 //
733 // Retrieve the FirmwareVolume which the file resides in.
734 //
735 if (!PeiFileHandleToVolume(FileHandle, &VolumeHandle)) {
736 return EFI_INVALID_PARAMETER;
737 }
738
739 if (((EFI_FIRMWARE_VOLUME_HEADER*)VolumeHandle)->Attributes & EFI_FVB2_ERASE_POLARITY) {
740 ErasePolarity = 1;
741 } else {
742 ErasePolarity = 0;
743 }
744
745 //
746 // Get FileState which is the highest bit of the State
747 //
748 FileState = GetFileState (ErasePolarity, (EFI_FFS_FILE_HEADER*)FileHandle);
749
750 switch (FileState) {
751 case EFI_FILE_DATA_VALID:
752 case EFI_FILE_MARKED_FOR_UPDATE:
753 break;
754 default:
755 return EFI_INVALID_PARAMETER;
756 }
757
758 FileHeader = (EFI_FFS_FILE_HEADER *)FileHandle;
759 CopyMem (&FileInfo->FileName, &FileHeader->Name, sizeof(EFI_GUID));
760 FileInfo->FileType = FileHeader->Type;
761 FileInfo->FileAttributes = FileHeader->Attributes;
762 FileInfo->BufferSize = ((*(UINT32 *)FileHeader->Size) & 0x00FFFFFF) - sizeof (EFI_FFS_FILE_HEADER);
763 FileInfo->Buffer = (FileHeader + 1);
764 return EFI_SUCCESS;
765 }
766
767
768 /**
769
770 Collect information of given Fv Volume.
771
772 @param VolumeHandle - The handle to Fv Volume.
773 @param VolumeInfo - The pointer to volume information.
774
775 @retval EFI_INVALID_PARAMETER VolumeInfo is NULL
776 @retval EFI_SUCCESS Success to collect fv info.
777 **/
778 EFI_STATUS
779 EFIAPI
780 PeiFfsGetVolumeInfo (
781 IN EFI_PEI_FV_HANDLE VolumeHandle,
782 OUT EFI_FV_INFO *VolumeInfo
783 )
784 {
785 EFI_FIRMWARE_VOLUME_HEADER FwVolHeader;
786 EFI_FIRMWARE_VOLUME_EXT_HEADER *FwVolExHeaderInfo;
787
788 if (VolumeInfo == NULL) {
789 return EFI_INVALID_PARAMETER;
790 }
791
792 //
793 // VolumeHandle may not align at 8 byte,
794 // but FvLength is UINT64 type, which requires FvHeader align at least 8 byte.
795 // So, Copy FvHeader into the local FvHeader structure.
796 //
797 CopyMem (&FwVolHeader, VolumeHandle, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
798 //
799 // Check Fv Image Signature
800 //
801 if (FwVolHeader.Signature != EFI_FVH_SIGNATURE) {
802 return EFI_INVALID_PARAMETER;
803 }
804 VolumeInfo->FvAttributes = FwVolHeader.Attributes;
805 VolumeInfo->FvStart = (VOID *) VolumeHandle;
806 VolumeInfo->FvSize = FwVolHeader.FvLength;
807 CopyMem (&VolumeInfo->FvFormat, &FwVolHeader.FileSystemGuid, sizeof(EFI_GUID));
808
809 if (FwVolHeader.ExtHeaderOffset != 0) {
810 FwVolExHeaderInfo = (EFI_FIRMWARE_VOLUME_EXT_HEADER*)(((UINT8 *)VolumeHandle) + FwVolHeader.ExtHeaderOffset);
811 CopyMem (&VolumeInfo->FvName, &FwVolExHeaderInfo->FvName, sizeof(EFI_GUID));
812 }
813 return EFI_SUCCESS;
814 }
815