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