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