1 /** @file
2 These functions assist in parsing and manipulating a Firmware Volume.
3
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 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 //
16 // Include files
17 //
18 #include "FvLib.h"
19 #include "CommonLib.h"
20 #include "EfiUtilityMsgs.h"
21
22 //
23 // Module global variables
24 //
25 EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL;
26 UINT32 mFvLength = 0;
27
28 //
29 // External function implementations
30 //
31 EFI_STATUS
InitializeFvLib(IN VOID * Fv,IN UINT32 FvLength)32 InitializeFvLib (
33 IN VOID *Fv,
34 IN UINT32 FvLength
35 )
36 /*++
37
38 Routine Description:
39
40 This initializes the FV lib with a pointer to the FV and length. It does not
41 verify the FV in any way.
42
43 Arguments:
44
45 Fv Buffer containing the FV.
46 FvLength Length of the FV
47
48 Returns:
49
50 EFI_SUCCESS Function Completed successfully.
51 EFI_INVALID_PARAMETER A required parameter was NULL.
52
53 --*/
54 {
55 //
56 // Verify input arguments
57 //
58 if (Fv == NULL) {
59 return EFI_INVALID_PARAMETER;
60 }
61
62 mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv;
63 mFvLength = FvLength;
64
65 return EFI_SUCCESS;
66 }
67
68 EFI_STATUS
GetFvHeader(OUT EFI_FIRMWARE_VOLUME_HEADER ** FvHeader,OUT UINT32 * FvLength)69 GetFvHeader (
70 OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader,
71 OUT UINT32 *FvLength
72 )
73 /*++
74
75 Routine Description:
76
77 This function returns a pointer to the current FV and the size.
78
79 Arguments:
80
81 FvHeader Pointer to the FV buffer.
82 FvLength Length of the FV
83
84 Returns:
85
86 EFI_SUCCESS Function Completed successfully.
87 EFI_INVALID_PARAMETER A required parameter was NULL.
88 EFI_ABORTED The library needs to be initialized.
89
90 --*/
91 {
92 //
93 // Verify library has been initialized.
94 //
95 if (mFvHeader == NULL || mFvLength == 0) {
96 return EFI_ABORTED;
97 }
98 //
99 // Verify input arguments
100 //
101 if (FvHeader == NULL) {
102 return EFI_INVALID_PARAMETER;
103 }
104
105 *FvHeader = mFvHeader;
106 *FvLength = mFvLength;
107 return EFI_SUCCESS;
108 }
109
110 EFI_STATUS
GetNextFile(IN EFI_FFS_FILE_HEADER * CurrentFile,OUT EFI_FFS_FILE_HEADER ** NextFile)111 GetNextFile (
112 IN EFI_FFS_FILE_HEADER *CurrentFile,
113 OUT EFI_FFS_FILE_HEADER **NextFile
114 )
115 /*++
116
117 Routine Description:
118
119 This function returns the next file. If the current file is NULL, it returns
120 the first file in the FV. If the function returns EFI_SUCCESS and the file
121 pointer is NULL, then there are no more files in the FV.
122
123 Arguments:
124
125 CurrentFile Pointer to the current file, must be within the current FV.
126 NextFile Pointer to the next file in the FV.
127
128 Returns:
129
130 EFI_SUCCESS Function completed successfully.
131 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
132 EFI_ABORTED The library needs to be initialized.
133
134 --*/
135 {
136 EFI_STATUS Status;
137
138 //
139 // Verify library has been initialized.
140 //
141 if (mFvHeader == NULL || mFvLength == 0) {
142 return EFI_ABORTED;
143 }
144 //
145 // Verify input arguments
146 //
147 if (NextFile == NULL) {
148 return EFI_INVALID_PARAMETER;
149 }
150 //
151 // Verify FV header
152 //
153 Status = VerifyFv (mFvHeader);
154 if (EFI_ERROR (Status)) {
155 return EFI_ABORTED;
156 }
157 //
158 // Get first file
159 //
160 if (CurrentFile == NULL) {
161 CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength);
162
163 //
164 // Verify file is valid
165 //
166 Status = VerifyFfsFile (CurrentFile);
167 if (EFI_ERROR (Status)) {
168 //
169 // no files in this FV
170 //
171 *NextFile = NULL;
172 return EFI_SUCCESS;
173 } else {
174 //
175 // Verify file is in this FV.
176 //
177 if ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) {
178 *NextFile = NULL;
179 return EFI_SUCCESS;
180 }
181
182 *NextFile = CurrentFile;
183 return EFI_SUCCESS;
184 }
185 }
186 //
187 // Verify current file is in range
188 //
189 if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) ||
190 ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength)
191 ) {
192 return EFI_INVALID_PARAMETER;
193 }
194 //
195 // Get next file, compensate for 8 byte alignment if necessary.
196 //
197 *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (~(UINTN) 7)) + (UINT8 *) mFvHeader);
198
199 //
200 // Verify file is in this FV.
201 //
202 if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) ||
203 ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength)
204 ) {
205 *NextFile = NULL;
206 return EFI_SUCCESS;
207 }
208 //
209 // Verify file is valid
210 //
211 Status = VerifyFfsFile (*NextFile);
212 if (EFI_ERROR (Status)) {
213 //
214 // no more files in this FV
215 //
216 *NextFile = NULL;
217 return EFI_SUCCESS;
218 }
219
220 return EFI_SUCCESS;
221 }
222
223 EFI_STATUS
GetFileByName(IN EFI_GUID * FileName,OUT EFI_FFS_FILE_HEADER ** File)224 GetFileByName (
225 IN EFI_GUID *FileName,
226 OUT EFI_FFS_FILE_HEADER **File
227 )
228 /*++
229
230 Routine Description:
231
232 Find a file by name. The function will return NULL if the file is not found.
233
234 Arguments:
235
236 FileName The GUID file name of the file to search for.
237 File Return pointer. In the case of an error, contents are undefined.
238
239 Returns:
240
241 EFI_SUCCESS The function completed successfully.
242 EFI_ABORTED An error was encountered.
243 EFI_INVALID_PARAMETER One of the parameters was NULL.
244
245 --*/
246 {
247 EFI_FFS_FILE_HEADER *CurrentFile;
248 EFI_STATUS Status;
249 CHAR8 FileGuidString[80];
250
251 //
252 // Verify library has been initialized.
253 //
254 if (mFvHeader == NULL || mFvLength == 0) {
255 return EFI_ABORTED;
256 }
257 //
258 // Verify input parameters
259 //
260 if (FileName == NULL || File == NULL) {
261 return EFI_INVALID_PARAMETER;
262 }
263 //
264 // File Guid String Name
265 //
266 PrintGuidToBuffer (FileName, (UINT8 *)FileGuidString, sizeof (FileGuidString), TRUE);
267 //
268 // Verify FV header
269 //
270 Status = VerifyFv (mFvHeader);
271 if (EFI_ERROR (Status)) {
272 return EFI_ABORTED;
273 }
274 //
275 // Get the first file
276 //
277 Status = GetNextFile (NULL, &CurrentFile);
278 if (EFI_ERROR (Status)) {
279 Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString);
280 return EFI_ABORTED;
281 }
282 //
283 // Loop as long as we have a valid file
284 //
285 while (CurrentFile) {
286 if (!CompareGuid (&CurrentFile->Name, FileName)) {
287 *File = CurrentFile;
288 return EFI_SUCCESS;
289 }
290
291 Status = GetNextFile (CurrentFile, &CurrentFile);
292 if (EFI_ERROR (Status)) {
293 Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString);
294 return EFI_ABORTED;
295 }
296 }
297 //
298 // File not found in this FV.
299 //
300 *File = NULL;
301 return EFI_SUCCESS;
302 }
303
304 EFI_STATUS
GetFileByType(IN EFI_FV_FILETYPE FileType,IN UINTN Instance,OUT EFI_FFS_FILE_HEADER ** File)305 GetFileByType (
306 IN EFI_FV_FILETYPE FileType,
307 IN UINTN Instance,
308 OUT EFI_FFS_FILE_HEADER **File
309 )
310 /*++
311
312 Routine Description:
313
314 Find a file by type and instance. An instance of 1 is the first instance.
315 The function will return NULL if a matching file cannot be found.
316 File type EFI_FV_FILETYPE_ALL means any file type is valid.
317
318 Arguments:
319
320 FileType Type of file to search for.
321 Instance Instace of the file type to return.
322 File Return pointer. In the case of an error, contents are undefined.
323
324 Returns:
325
326 EFI_SUCCESS The function completed successfully.
327 EFI_ABORTED An error was encountered.
328 EFI_INVALID_PARAMETER One of the parameters was NULL.
329
330 --*/
331 {
332 EFI_FFS_FILE_HEADER *CurrentFile;
333 EFI_STATUS Status;
334 UINTN FileCount;
335
336 //
337 // Verify library has been initialized.
338 //
339 if (mFvHeader == NULL || mFvLength == 0) {
340 return EFI_ABORTED;
341 }
342 //
343 // Verify input parameters
344 //
345 if (File == NULL) {
346 return EFI_INVALID_PARAMETER;
347 }
348 //
349 // Verify FV header
350 //
351 Status = VerifyFv (mFvHeader);
352 if (EFI_ERROR (Status)) {
353 return EFI_ABORTED;
354 }
355 //
356 // Initialize the number of matching files found.
357 //
358 FileCount = 0;
359
360 //
361 // Get the first file
362 //
363 Status = GetNextFile (NULL, &CurrentFile);
364 if (EFI_ERROR (Status)) {
365 Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType);
366 return EFI_ABORTED;
367 }
368 //
369 // Loop as long as we have a valid file
370 //
371 while (CurrentFile) {
372 if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {
373 FileCount++;
374 }
375
376 if (FileCount == Instance) {
377 *File = CurrentFile;
378 return EFI_SUCCESS;
379 }
380
381 Status = GetNextFile (CurrentFile, &CurrentFile);
382 if (EFI_ERROR (Status)) {
383 Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType);
384 return EFI_ABORTED;
385 }
386 }
387
388 *File = NULL;
389 return EFI_SUCCESS;
390 }
391
392 EFI_STATUS
SearchSectionByType(IN EFI_FILE_SECTION_POINTER FirstSection,IN UINT8 * SearchEnd,IN EFI_SECTION_TYPE SectionType,IN OUT UINTN * StartIndex,IN UINTN Instance,OUT EFI_FILE_SECTION_POINTER * Section)393 SearchSectionByType (
394 IN EFI_FILE_SECTION_POINTER FirstSection,
395 IN UINT8 *SearchEnd,
396 IN EFI_SECTION_TYPE SectionType,
397 IN OUT UINTN *StartIndex,
398 IN UINTN Instance,
399 OUT EFI_FILE_SECTION_POINTER *Section
400 )
401 /*++
402
403 Routine Description:
404
405 Helper function to search a sequence of sections from the section pointed
406 by FirstSection to SearchEnd for the Instance-th section of type SectionType.
407 The current counter is saved in StartIndex and when the section is found, it's
408 saved in Section. GUID-defined sections, if special processing is not required,
409 are searched recursively in a depth-first manner.
410
411 Arguments:
412
413 FirstSection The first section to start searching from.
414 SearchEnd The end address to stop search.
415 SectionType The type of section to search.
416 StartIndex The current counter is saved.
417 Instance The requested n-th section number.
418 Section The found section returned.
419
420 Returns:
421
422 EFI_SUCCESS The function completed successfully.
423 EFI_NOT_FOUND The section is not found.
424 --*/
425 {
426 EFI_FILE_SECTION_POINTER CurrentSection;
427 EFI_FILE_SECTION_POINTER InnerSection;
428 EFI_STATUS Status;
429 UINTN SectionSize;
430 UINT16 GuidSecAttr;
431 UINT16 GuidDataOffset;
432
433 GuidSecAttr = 0;
434 GuidDataOffset = 0;
435 CurrentSection = FirstSection;
436
437 while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {
438 if (CurrentSection.CommonHeader->Type == SectionType) {
439 (*StartIndex)++;
440 }
441
442 if (*StartIndex == Instance) {
443 *Section = CurrentSection;
444 return EFI_SUCCESS;
445 }
446 //
447 // If the requesting section is not GUID-defined and
448 // we find a GUID-defined section that doesn't need
449 // special processing, go ahead to search the requesting
450 // section inside the GUID-defined section.
451 //
452 if (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) {
453 if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) {
454 GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes;
455 GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset;
456 } else {
457 GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes;
458 GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset;
459 }
460 }
461 if (SectionType != EFI_SECTION_GUID_DEFINED &&
462 CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&
463 !(GuidSecAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {
464 InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)
465 ((UINTN) CurrentSection.CommonHeader + GuidDataOffset);
466 SectionSize = GetSectionFileLength(CurrentSection.CommonHeader);
467 Status = SearchSectionByType (
468 InnerSection,
469 (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),
470 SectionType,
471 StartIndex,
472 Instance,
473 Section
474 );
475 if (!EFI_ERROR (Status)) {
476 return EFI_SUCCESS;
477 }
478 }
479 //
480 // Find next section (including compensating for alignment issues.
481 //
482 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (~(UINTN) 3));
483 }
484
485 return EFI_NOT_FOUND;
486 }
487
488 EFI_STATUS
GetSectionByType(IN EFI_FFS_FILE_HEADER * File,IN EFI_SECTION_TYPE SectionType,IN UINTN Instance,OUT EFI_FILE_SECTION_POINTER * Section)489 GetSectionByType (
490 IN EFI_FFS_FILE_HEADER *File,
491 IN EFI_SECTION_TYPE SectionType,
492 IN UINTN Instance,
493 OUT EFI_FILE_SECTION_POINTER *Section
494 )
495 /*++
496
497 Routine Description:
498
499 Find a section in a file by type and instance. An instance of 1 is the first
500 instance. The function will return NULL if a matching section cannot be found.
501 GUID-defined sections, if special processing is not needed, are handled in a
502 depth-first manner.
503
504 Arguments:
505
506 File The file to search.
507 SectionType Type of file to search for.
508 Instance Instace of the section to return.
509 Section Return pointer. In the case of an error, contents are undefined.
510
511 Returns:
512
513 EFI_SUCCESS The function completed successfully.
514 EFI_ABORTED An error was encountered.
515 EFI_INVALID_PARAMETER One of the parameters was NULL.
516 EFI_NOT_FOUND No found.
517 --*/
518 {
519 EFI_FILE_SECTION_POINTER CurrentSection;
520 EFI_STATUS Status;
521 UINTN SectionCount;
522
523 //
524 // Verify input parameters
525 //
526 if (File == NULL || Instance == 0) {
527 return EFI_INVALID_PARAMETER;
528 }
529 //
530 // Verify FFS header
531 //
532 Status = VerifyFfsFile (File);
533 if (EFI_ERROR (Status)) {
534 Error (NULL, 0, 0006, "invalid FFS file", NULL);
535 return EFI_ABORTED;
536 }
537 //
538 // Initialize the number of matching sections found.
539 //
540 SectionCount = 0;
541
542 //
543 // Get the first section
544 //
545 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + GetFfsHeaderLength(File));
546
547 //
548 // Depth-first manner to find section file.
549 //
550 Status = SearchSectionByType (
551 CurrentSection,
552 (UINT8 *) ((UINTN) File + GetFfsFileLength (File)),
553 SectionType,
554 &SectionCount,
555 Instance,
556 Section
557 );
558
559 if (!EFI_ERROR (Status)) {
560 return EFI_SUCCESS;
561 } else {
562 //
563 // Section not found
564 //
565 (*Section).Code16Section = NULL;
566 return EFI_NOT_FOUND;
567 }
568 }
569 //
570 // will not parse compressed sections
571 //
572 EFI_STATUS
VerifyFv(IN EFI_FIRMWARE_VOLUME_HEADER * FvHeader)573 VerifyFv (
574 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
575 )
576 /*++
577
578 Routine Description:
579
580 Verify the current pointer points to a valid FV header.
581
582 Arguments:
583
584 FvHeader Pointer to an alleged FV file.
585
586 Returns:
587
588 EFI_SUCCESS The FV header is valid.
589 EFI_VOLUME_CORRUPTED The FV header is not valid.
590 EFI_INVALID_PARAMETER A required parameter was NULL.
591 EFI_ABORTED Operation aborted.
592
593 --*/
594 {
595 UINT16 Checksum;
596
597 //
598 // Verify input parameters
599 //
600 if (FvHeader == NULL) {
601 return EFI_INVALID_PARAMETER;
602 }
603
604 if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
605 Error (NULL, 0, 0006, "invalid FV header signature", NULL);
606 return EFI_VOLUME_CORRUPTED;
607 }
608 //
609 // Verify header checksum
610 //
611 Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
612
613 if (Checksum != 0) {
614 Error (NULL, 0, 0006, "invalid FV header checksum", NULL);
615 return EFI_ABORTED;
616 }
617
618 return EFI_SUCCESS;
619 }
620
621 EFI_STATUS
VerifyFfsFile(IN EFI_FFS_FILE_HEADER * FfsHeader)622 VerifyFfsFile (
623 IN EFI_FFS_FILE_HEADER *FfsHeader
624 )
625 /*++
626
627 Routine Description:
628
629 Verify the current pointer points to a FFS file header.
630
631 Arguments:
632
633 FfsHeader Pointer to an alleged FFS file.
634
635 Returns:
636
637 EFI_SUCCESS The Ffs header is valid.
638 EFI_NOT_FOUND This "file" is the beginning of free space.
639 EFI_VOLUME_CORRUPTED The Ffs header is not valid.
640 EFI_ABORTED The erase polarity is not known.
641
642 --*/
643 {
644 BOOLEAN ErasePolarity;
645 EFI_STATUS Status;
646 EFI_FFS_FILE_HEADER2 BlankHeader;
647 UINT8 Checksum;
648 UINT32 FileLength;
649 UINT8 SavedChecksum;
650 UINT8 SavedState;
651 UINT8 FileGuidString[80];
652 UINT32 FfsHeaderSize;
653
654 //
655 // Verify library has been initialized.
656 //
657 if (mFvHeader == NULL || mFvLength == 0) {
658 return EFI_ABORTED;
659 }
660 //
661 // Verify FV header
662 //
663 Status = VerifyFv (mFvHeader);
664 if (EFI_ERROR (Status)) {
665 return EFI_ABORTED;
666 }
667 //
668 // Get the erase polarity.
669 //
670 Status = GetErasePolarity (&ErasePolarity);
671 if (EFI_ERROR (Status)) {
672 return EFI_ABORTED;
673 }
674
675 FfsHeaderSize = GetFfsHeaderLength(FfsHeader);
676 //
677 // Check if we have free space
678 //
679 if (ErasePolarity) {
680 memset (&BlankHeader, -1, FfsHeaderSize);
681 } else {
682 memset (&BlankHeader, 0, FfsHeaderSize);
683 }
684
685 if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) {
686 return EFI_NOT_FOUND;
687 }
688 //
689 // Convert the GUID to a string so we can at least report which file
690 // if we find an error.
691 //
692 PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
693 //
694 // Verify file header checksum
695 //
696 SavedState = FfsHeader->State;
697 FfsHeader->State = 0;
698 SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
699 FfsHeader->IntegrityCheck.Checksum.File = 0;
700 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize);
701 FfsHeader->State = SavedState;
702 FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
703 if (Checksum != 0) {
704 Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
705 return EFI_ABORTED;
706 }
707 //
708 // Verify file checksum
709 //
710 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
711 //
712 // Verify file data checksum
713 //
714 FileLength = GetFfsFileLength (FfsHeader);
715 Checksum = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);
716 Checksum = Checksum + FfsHeader->IntegrityCheck.Checksum.File;
717 if (Checksum != 0) {
718 Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);
719 return EFI_ABORTED;
720 }
721 } else {
722 //
723 // File does not have a checksum
724 // Verify contents are 0xAA as spec'd
725 //
726 if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
727 Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString);
728 return EFI_ABORTED;
729 }
730 }
731
732 return EFI_SUCCESS;
733 }
734
735 UINT32
GetFfsHeaderLength(IN EFI_FFS_FILE_HEADER * FfsHeader)736 GetFfsHeaderLength(
737 IN EFI_FFS_FILE_HEADER *FfsHeader
738 )
739 {
740 if (FfsHeader == NULL) {
741 return 0;
742 }
743 if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
744 return sizeof(EFI_FFS_FILE_HEADER2);
745 }
746 return sizeof(EFI_FFS_FILE_HEADER);
747 }
748
749 UINT32
GetSectionHeaderLength(IN EFI_COMMON_SECTION_HEADER * SectionHeader)750 GetSectionHeaderLength(
751 IN EFI_COMMON_SECTION_HEADER *SectionHeader
752 )
753 {
754 if (SectionHeader == NULL) {
755 return 0;
756 }
757 if (GetLength(SectionHeader->Size) == 0xffffff) {
758 return sizeof(EFI_COMMON_SECTION_HEADER2);
759 }
760 return sizeof(EFI_COMMON_SECTION_HEADER);
761 }
762
763 UINT32
GetFfsFileLength(EFI_FFS_FILE_HEADER * FfsHeader)764 GetFfsFileLength (
765 EFI_FFS_FILE_HEADER *FfsHeader
766 )
767 /*++
768
769 Routine Description:
770
771 Get FFS file length including FFS header.
772
773 Arguments:
774
775 FfsHeader Pointer to EFI_FFS_FILE_HEADER.
776
777 Returns:
778
779 UINT32 Length of FFS file header.
780
781 --*/
782 {
783 if (FfsHeader == NULL) {
784 return 0;
785 }
786 if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {
787 return (UINT32) ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize;
788 } else {
789 return GetLength(FfsHeader->Size);
790 }
791 }
792
793 UINT32
GetSectionFileLength(EFI_COMMON_SECTION_HEADER * SectionHeader)794 GetSectionFileLength (
795 EFI_COMMON_SECTION_HEADER *SectionHeader
796 )
797 {
798 UINT32 Length;
799 if (SectionHeader == NULL) {
800 return 0;
801 }
802 Length = GetLength(SectionHeader->Size);
803 if (Length == 0xffffff) {
804 Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
805 }
806 return Length;
807 }
808
809 UINT32
GetLength(UINT8 * ThreeByteLength)810 GetLength (
811 UINT8 *ThreeByteLength
812 )
813 /*++
814
815 Routine Description:
816
817 Converts a three byte length value into a UINT32.
818
819 Arguments:
820
821 ThreeByteLength Pointer to the first of the 3 byte length.
822
823 Returns:
824
825 UINT32 Size of the section
826
827 --*/
828 {
829 UINT32 Length;
830
831 if (ThreeByteLength == NULL) {
832 return 0;
833 }
834
835 Length = *((UINT32 *) ThreeByteLength);
836 Length = Length & 0x00FFFFFF;
837
838 return Length;
839 }
840
841 EFI_STATUS
GetErasePolarity(OUT BOOLEAN * ErasePolarity)842 GetErasePolarity (
843 OUT BOOLEAN *ErasePolarity
844 )
845 /*++
846
847 Routine Description:
848
849 This function returns with the FV erase polarity. If the erase polarity
850 for a bit is 1, the function return TRUE.
851
852 Arguments:
853
854 ErasePolarity A pointer to the erase polarity.
855
856 Returns:
857
858 EFI_SUCCESS The function completed successfully.
859 EFI_INVALID_PARAMETER One of the input parameters was invalid.
860 EFI_ABORTED Operation aborted.
861
862 --*/
863 {
864 EFI_STATUS Status;
865
866 //
867 // Verify library has been initialized.
868 //
869 if (mFvHeader == NULL || mFvLength == 0) {
870 return EFI_ABORTED;
871 }
872 //
873 // Verify FV header
874 //
875 Status = VerifyFv (mFvHeader);
876 if (EFI_ERROR (Status)) {
877 return EFI_ABORTED;
878 }
879 //
880 // Verify input parameters.
881 //
882 if (ErasePolarity == NULL) {
883 return EFI_INVALID_PARAMETER;
884 }
885
886 if (mFvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
887 *ErasePolarity = TRUE;
888 } else {
889 *ErasePolarity = FALSE;
890 }
891
892 return EFI_SUCCESS;
893 }
894
895 UINT8
GetFileState(IN BOOLEAN ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader)896 GetFileState (
897 IN BOOLEAN ErasePolarity,
898 IN EFI_FFS_FILE_HEADER *FfsHeader
899 )
900 /*++
901
902 Routine Description:
903
904 This function returns a the highest state bit in the FFS that is set.
905 It in no way validate the FFS file.
906
907 Arguments:
908
909 ErasePolarity The erase polarity for the file state bits.
910 FfsHeader Pointer to a FFS file.
911
912 Returns:
913
914 UINT8 The hightest set state of the file.
915
916 --*/
917 {
918 UINT8 FileState;
919 UINT8 HighestBit;
920
921 FileState = FfsHeader->State;
922
923 if (ErasePolarity) {
924 FileState = (UINT8)~FileState;
925 }
926
927 HighestBit = 0x80;
928 while (HighestBit != 0 && (HighestBit & FileState) == 0) {
929 HighestBit >>= 1;
930 }
931
932 return HighestBit;
933 }
934