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