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