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