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