]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/Common/FvLib.c
1. Removed the unnecessary #include statements and include files
[mirror_edk2.git] / Tools / Source / TianoTools / Common / FvLib.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2004, 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
878ddf1f 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 >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {\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 + sizeof (EFI_FIRMWARE_VOLUME_HEADER)) ||\r
196 ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\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 >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) {\r
209 *NextFile = NULL;\r
210 return EFI_SUCCESS;\r
211 }\r
212 //\r
213 // Verify file is valid\r
214 //\r
215 Status = VerifyFfsFile (*NextFile);\r
216 if (EFI_ERROR (Status)) {\r
217 //\r
218 // no more files in this FV\r
219 //\r
220 *NextFile = NULL;\r
221 return EFI_SUCCESS;\r
222 }\r
223\r
224 return EFI_SUCCESS;\r
225}\r
226\r
227EFI_STATUS\r
228GetFileByName (\r
229 IN EFI_GUID *FileName,\r
230 OUT EFI_FFS_FILE_HEADER **File\r
231 )\r
232/*++\r
233\r
234Routine Description:\r
235\r
236 Find a file by name. The function will return NULL if the file is not found.\r
237\r
238Arguments:\r
239\r
240 FileName The GUID file name of the file to search for.\r
241 File Return pointer. In the case of an error, contents are undefined.\r
242\r
243Returns:\r
244\r
245 EFI_SUCCESS The function completed successfully.\r
246 EFI_ABORTED An error was encountered.\r
247 EFI_INVALID_PARAMETER One of the parameters was NULL.\r
248\r
249--*/\r
250{\r
251 EFI_FFS_FILE_HEADER *CurrentFile;\r
252 EFI_STATUS Status;\r
253\r
254 //\r
255 // Verify library has been initialized.\r
256 //\r
257 if (mFvHeader == NULL || mFvLength == 0) {\r
258 return EFI_ABORTED;\r
259 }\r
260 //\r
261 // Verify input parameters\r
262 //\r
263 if (FileName == NULL || File == NULL) {\r
264 return EFI_INVALID_PARAMETER;\r
265 }\r
266 //\r
267 // Verify FV header\r
268 //\r
269 Status = VerifyFv (mFvHeader);\r
270 if (EFI_ERROR (Status)) {\r
271 return EFI_ABORTED;\r
272 }\r
273 //\r
274 // Get the first file\r
275 //\r
276 Status = GetNextFile (NULL, &CurrentFile);\r
277 if (EFI_ERROR (Status)) {\r
278 Error (NULL, 0, 0, "error parsing the FV", NULL);\r
279 return EFI_ABORTED;\r
280 }\r
281 //\r
282 // Loop as long as we have a valid file\r
283 //\r
284 while (CurrentFile) {\r
285 if (!CompareGuid (&CurrentFile->Name, FileName)) {\r
286 *File = CurrentFile;\r
287 return EFI_SUCCESS;\r
288 }\r
289\r
290 Status = GetNextFile (CurrentFile, &CurrentFile);\r
291 if (EFI_ERROR (Status)) {\r
292 Error (NULL, 0, 0, "error parsing the FV", NULL);\r
293 return EFI_ABORTED;\r
294 }\r
295 }\r
296 //\r
297 // File not found in this FV.\r
298 //\r
299 *File = NULL;\r
300 return EFI_SUCCESS;\r
301}\r
302\r
303EFI_STATUS\r
304GetFileByType (\r
305 IN EFI_FV_FILETYPE FileType,\r
306 IN UINTN Instance,\r
307 OUT EFI_FFS_FILE_HEADER **File\r
308 )\r
309/*++\r
310\r
311Routine Description:\r
312\r
313 Find a file by type and instance. An instance of 1 is the first instance.\r
314 The function will return NULL if a matching file cannot be found.\r
315 File type EFI_FV_FILETYPE_ALL means any file type is valid.\r
316\r
317Arguments:\r
318\r
319 FileType Type of file to search for.\r
320 Instance Instace of the file type to return.\r
321 File Return pointer. In the case of an error, contents are undefined.\r
322\r
323Returns:\r
324\r
325 EFI_SUCCESS The function completed successfully.\r
326 EFI_ABORTED An error was encountered.\r
327 EFI_INVALID_PARAMETER One of the parameters was NULL.\r
328\r
329--*/\r
330{\r
331 EFI_FFS_FILE_HEADER *CurrentFile;\r
332 EFI_STATUS Status;\r
333 UINTN FileCount;\r
334\r
335 //\r
336 // Verify library has been initialized.\r
337 //\r
338 if (mFvHeader == NULL || mFvLength == 0) {\r
339 return EFI_ABORTED;\r
340 }\r
341 //\r
342 // Verify input parameters\r
343 //\r
344 if (File == NULL) {\r
345 return EFI_INVALID_PARAMETER;\r
346 }\r
347 //\r
348 // Verify FV header\r
349 //\r
350 Status = VerifyFv (mFvHeader);\r
351 if (EFI_ERROR (Status)) {\r
352 return EFI_ABORTED;\r
353 }\r
354 //\r
355 // Initialize the number of matching files found.\r
356 //\r
357 FileCount = 0;\r
358\r
359 //\r
360 // Get the first file\r
361 //\r
362 Status = GetNextFile (NULL, &CurrentFile);\r
363 if (EFI_ERROR (Status)) {\r
364 Error (NULL, 0, 0, "error parsing FV", NULL);\r
365 return EFI_ABORTED;\r
366 }\r
367 //\r
368 // Loop as long as we have a valid file\r
369 //\r
370 while (CurrentFile) {\r
371 if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {\r
372 FileCount++;\r
373 }\r
374\r
375 if (FileCount == Instance) {\r
376 *File = CurrentFile;\r
377 return EFI_SUCCESS;\r
378 }\r
379\r
380 Status = GetNextFile (CurrentFile, &CurrentFile);\r
381 if (EFI_ERROR (Status)) {\r
382 Error (NULL, 0, 0, "error parsing the FV", NULL);\r
383 return EFI_ABORTED;\r
384 }\r
385 }\r
386\r
387 *File = NULL;\r
388 return EFI_SUCCESS;\r
389}\r
390\r
391EFI_STATUS\r
392GetSectionByType (\r
393 IN EFI_FFS_FILE_HEADER *File,\r
394 IN EFI_SECTION_TYPE SectionType,\r
395 IN UINTN Instance,\r
396 OUT EFI_FILE_SECTION_POINTER *Section\r
397 )\r
398/*++\r
399\r
400Routine Description:\r
401\r
402 Find a section in a file by type and instance. An instance of 1 is the first \r
403 instance. The function will return NULL if a matching section cannot be found.\r
404 The function will not handle encapsulating sections.\r
405\r
406Arguments:\r
407\r
408 File The file to search.\r
409 SectionType Type of file to search for.\r
410 Instance Instace of the section to return.\r
411 Section Return pointer. In the case of an error, contents are undefined.\r
412\r
413Returns:\r
414\r
415 EFI_SUCCESS The function completed successfully.\r
416 EFI_ABORTED An error was encountered.\r
417 EFI_INVALID_PARAMETER One of the parameters was NULL.\r
418 EFI_NOT_FOUND No found.\r
419--*/\r
420{\r
421 EFI_FILE_SECTION_POINTER CurrentSection;\r
422 EFI_STATUS Status;\r
423 UINTN SectionCount;\r
424\r
425 //\r
426 // Verify input parameters\r
427 //\r
428 if (File == NULL || Instance == 0) {\r
429 return EFI_INVALID_PARAMETER;\r
430 }\r
431 //\r
432 // Verify FFS header\r
433 //\r
434 Status = VerifyFfsFile (File);\r
435 if (EFI_ERROR (Status)) {\r
436 Error (NULL, 0, 0, "invalid FFS file", NULL);\r
437 return EFI_ABORTED;\r
438 }\r
439 //\r
440 // Initialize the number of matching sections found.\r
441 //\r
442 SectionCount = 0;\r
443\r
444 //\r
445 // Get the first section\r
446 //\r
447 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));\r
448\r
449 //\r
450 // Loop as long as we have a valid file\r
451 //\r
452 while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) {\r
453 if (CurrentSection.CommonHeader->Type == SectionType) {\r
454 SectionCount++;\r
455 }\r
456\r
457 if (SectionCount == Instance) {\r
458 *Section = CurrentSection;\r
459 return EFI_SUCCESS;\r
460 }\r
461 //\r
462 // Find next section (including compensating for alignment issues.\r
463 //\r
464 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));\r
465 }\r
466 //\r
467 // Section not found\r
468 //\r
469 (*Section).Code16Section = NULL;\r
470 return EFI_NOT_FOUND;\r
471}\r
472//\r
473// will not parse compressed sections\r
474//\r
475EFI_STATUS\r
476VerifyFv (\r
477 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
478 )\r
479/*++\r
480\r
481Routine Description:\r
482\r
483 Verify the current pointer points to a valid FV header.\r
484\r
485Arguments:\r
486\r
487 FvHeader Pointer to an alleged FV file.\r
488\r
489Returns:\r
490\r
491 EFI_SUCCESS The FV header is valid.\r
492 EFI_VOLUME_CORRUPTED The FV header is not valid.\r
493 EFI_INVALID_PARAMETER A required parameter was NULL.\r
494 EFI_ABORTED Operation aborted.\r
495\r
496--*/\r
497{\r
498 UINT16 Checksum;\r
499\r
500 //\r
501 // Verify input parameters\r
502 //\r
503 if (FvHeader == NULL) {\r
504 return EFI_INVALID_PARAMETER;\r
505 }\r
506\r
507 if (FvHeader->Signature != EFI_FVH_SIGNATURE) {\r
508 Error (NULL, 0, 0, "invalid FV header signature", NULL);\r
509 return EFI_VOLUME_CORRUPTED;\r
510 }\r
511 //\r
512 // Verify header checksum\r
513 //\r
514 Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
515\r
516 if (Checksum != 0) {\r
517 Error (NULL, 0, 0, "invalid FV header checksum", NULL);\r
518 return EFI_ABORTED;\r
519 }\r
520\r
521 return EFI_SUCCESS;\r
522}\r
523\r
524EFI_STATUS\r
525VerifyFfsFile (\r
526 IN EFI_FFS_FILE_HEADER *FfsHeader\r
527 )\r
528/*++\r
529\r
530Routine Description:\r
531\r
532 Verify the current pointer points to a FFS file header.\r
533\r
534Arguments:\r
535\r
536 FfsHeader Pointer to an alleged FFS file.\r
537\r
538Returns:\r
539\r
540 EFI_SUCCESS The Ffs header is valid.\r
541 EFI_NOT_FOUND This "file" is the beginning of free space.\r
542 EFI_VOLUME_CORRUPTED The Ffs header is not valid.\r
543 EFI_ABORTED The erase polarity is not known.\r
544\r
545--*/\r
546{\r
547 BOOLEAN ErasePolarity;\r
548 EFI_STATUS Status;\r
549 EFI_FFS_FILE_HEADER BlankHeader;\r
550 UINT8 Checksum;\r
551 UINT32 FileLength;\r
552 UINT32 OccupiedFileLength;\r
553 EFI_FFS_FILE_TAIL *Tail;\r
554 UINT8 SavedChecksum;\r
555 UINT8 SavedState;\r
556 UINT8 FileGuidString[80];\r
557 UINT32 TailSize;\r
558 //\r
559 // Verify library has been initialized.\r
560 //\r
561 if (mFvHeader == NULL || mFvLength == 0) {\r
562 return EFI_ABORTED;\r
563 }\r
564 //\r
565 // Verify FV header\r
566 //\r
567 Status = VerifyFv (mFvHeader);\r
568 if (EFI_ERROR (Status)) {\r
569 return EFI_ABORTED;\r
570 }\r
571 //\r
572 // Get the erase polarity.\r
573 //\r
574 Status = GetErasePolarity (&ErasePolarity);\r
575 if (EFI_ERROR (Status)) {\r
576 return EFI_ABORTED;\r
577 }\r
578 //\r
579 // Check if we have free space\r
580 //\r
581 if (ErasePolarity) {\r
582 memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));\r
583 } else {\r
584 memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
585 }\r
586\r
587 if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {\r
588 return EFI_NOT_FOUND;\r
589 }\r
590 //\r
591 // Convert the GUID to a string so we can at least report which file\r
592 // if we find an error.\r
593 //\r
594 PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
595 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
596 TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
597 } else {\r
598 TailSize = 0;\r
599 }\r
600 //\r
601 // Verify file header checksum\r
602 //\r
603 SavedState = FfsHeader->State;\r
604 FfsHeader->State = 0;\r
605 SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
606 FfsHeader->IntegrityCheck.Checksum.File = 0;\r
607 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));\r
608 FfsHeader->State = SavedState;\r
609 FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;\r
610 if (Checksum != 0) {\r
611 Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum");\r
612 return EFI_ABORTED;\r
613 }\r
614 //\r
615 // Verify file checksum\r
616 //\r
617 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
618 //\r
619 // Verify file data checksum\r
620 //\r
621 FileLength = GetLength (FfsHeader->Size);\r
622 OccupiedFileLength = (FileLength + 0x07) & (-1 << 3);\r
623 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize);\r
624 Checksum = (UINT8) (Checksum - FfsHeader->State);\r
625 if (Checksum != 0) {\r
626 Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum");\r
627 return EFI_ABORTED;\r
628 }\r
629 } else {\r
630 //\r
631 // File does not have a checksum\r
632 // Verify contents are 0x5A as spec'd\r
633 //\r
634 if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {\r
635 Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum");\r
636 return EFI_ABORTED;\r
637 }\r
638 }\r
639 //\r
640 // Check if the tail is present and verify it if it is.\r
641 //\r
642 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
643 //\r
644 // Verify tail is complement of integrity check field in the header.\r
645 //\r
646 Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL));\r
647 if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) {\r
648 Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail");\r
649 return EFI_ABORTED;\r
650 }\r
651 }\r
652\r
653 return EFI_SUCCESS;\r
654}\r
655\r
656UINT32\r
657GetLength (\r
658 UINT8 *ThreeByteLength\r
659 )\r
660/*++\r
661\r
662Routine Description:\r
663\r
664 Converts a three byte length value into a UINT32.\r
665\r
666Arguments:\r
667\r
668 ThreeByteLength Pointer to the first of the 3 byte length.\r
669\r
670Returns:\r
671\r
672 UINT32 Size of the section\r
673\r
674--*/\r
675{\r
676 UINT32 Length;\r
677\r
678 if (ThreeByteLength == NULL) {\r
679 return 0;\r
680 }\r
681\r
682 Length = *((UINT32 *) ThreeByteLength);\r
683 Length = Length & 0x00FFFFFF;\r
684\r
685 return Length;\r
686}\r
687\r
688EFI_STATUS\r
689GetErasePolarity (\r
690 OUT BOOLEAN *ErasePolarity\r
691 )\r
692/*++\r
693\r
694Routine Description:\r
695\r
696 This function returns with the FV erase polarity. If the erase polarity\r
697 for a bit is 1, the function return TRUE.\r
698\r
699Arguments:\r
700\r
701 ErasePolarity A pointer to the erase polarity.\r
702\r
703Returns:\r
704\r
705 EFI_SUCCESS The function completed successfully.\r
706 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
707 EFI_ABORTED Operation aborted.\r
708 \r
709--*/\r
710{\r
711 EFI_STATUS Status;\r
712\r
713 //\r
714 // Verify library has been initialized.\r
715 //\r
716 if (mFvHeader == NULL || mFvLength == 0) {\r
717 return EFI_ABORTED;\r
718 }\r
719 //\r
720 // Verify FV header\r
721 //\r
722 Status = VerifyFv (mFvHeader);\r
723 if (EFI_ERROR (Status)) {\r
724 return EFI_ABORTED;\r
725 }\r
726 //\r
727 // Verify input parameters.\r
728 //\r
729 if (ErasePolarity == NULL) {\r
730 return EFI_INVALID_PARAMETER;\r
731 }\r
732\r
733 if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
734 *ErasePolarity = TRUE;\r
735 } else {\r
736 *ErasePolarity = FALSE;\r
737 }\r
738\r
739 return EFI_SUCCESS;\r
740}\r
741\r
742UINT8\r
743GetFileState (\r
744 IN BOOLEAN ErasePolarity,\r
745 IN EFI_FFS_FILE_HEADER *FfsHeader\r
746 )\r
747/*++\r
748\r
749Routine Description:\r
750\r
751 This function returns a the highest state bit in the FFS that is set.\r
752 It in no way validate the FFS file.\r
753\r
754Arguments:\r
755 \r
756 ErasePolarity The erase polarity for the file state bits.\r
757 FfsHeader Pointer to a FFS file.\r
758\r
759Returns:\r
760\r
761 UINT8 The hightest set state of the file.\r
762\r
763--*/\r
764{\r
765 UINT8 FileState;\r
766 UINT8 HighestBit;\r
767\r
768 FileState = FfsHeader->State;\r
769\r
770 if (ErasePolarity) {\r
771 FileState = (UINT8)~FileState;\r
772 }\r
773\r
774 HighestBit = 0x80;\r
775 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
776 HighestBit >>= 1;\r
777 }\r
778\r
779 return HighestBit;\r
780}\r