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