]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/Common/FvLib.c
Sync BaseTool trunk (version r2610) into EDKII BaseTools.
[mirror_edk2.git] / BaseTools / Source / C / Common / FvLib.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
e8a47801 3Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR>\r
40d841f6 4This program and the accompanying materials \r
30fdf114
LG
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
e8a47801 184 if ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) {\r
30fdf114
LG
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
e8a47801 197 ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength)\r
30fdf114
LG
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
e8a47801 204 *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (-1 << 3)) + (UINT8 *) mFvHeader);\r
30fdf114
LG
205\r
206 //\r
207 // Verify file is in this FV.\r
208 //\r
e8a47801
LG
209 if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) ||\r
210 ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength)\r
30fdf114
LG
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
e8a47801
LG
437 UINT16 GuidSecAttr;\r
438 UINT16 GuidDataOffset;\r
30fdf114 439\r
e8a47801
LG
440 GuidSecAttr = 0;\r
441 GuidDataOffset = 0;\r
30fdf114
LG
442 CurrentSection = FirstSection;\r
443\r
444 while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {\r
445 if (CurrentSection.CommonHeader->Type == SectionType) {\r
446 (*StartIndex)++;\r
447 }\r
448\r
449 if (*StartIndex == Instance) {\r
450 *Section = CurrentSection;\r
451 return EFI_SUCCESS;\r
452 }\r
453 //\r
454 // If the requesting section is not GUID-defined and\r
455 // we find a GUID-defined section that doesn't need\r
456 // special processing, go ahead to search the requesting\r
457 // section inside the GUID-defined section.\r
458 //\r
e8a47801
LG
459 if (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) {\r
460 if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) {\r
461 GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes;\r
462 GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset;\r
463 } else {\r
464 GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes;\r
465 GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset;\r
466 }\r
467 }\r
30fdf114
LG
468 if (SectionType != EFI_SECTION_GUID_DEFINED &&\r
469 CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&\r
e8a47801 470 !(GuidSecAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {\r
30fdf114 471 InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)\r
e8a47801
LG
472 ((UINTN) CurrentSection.CommonHeader + GuidDataOffset);\r
473 SectionSize = GetSectionFileLength(CurrentSection.CommonHeader);\r
30fdf114
LG
474 Status = SearchSectionByType (\r
475 InnerSection,\r
476 (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),\r
477 SectionType,\r
478 StartIndex,\r
479 Instance,\r
480 Section\r
481 );\r
482 if (!EFI_ERROR (Status)) {\r
483 return EFI_SUCCESS;\r
484 }\r
485 }\r
486 //\r
487 // Find next section (including compensating for alignment issues.\r
488 //\r
e8a47801 489 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (-1 << 2));\r
30fdf114
LG
490 }\r
491\r
492 return EFI_NOT_FOUND;\r
493}\r
494\r
495EFI_STATUS\r
496GetSectionByType (\r
497 IN EFI_FFS_FILE_HEADER *File,\r
498 IN EFI_SECTION_TYPE SectionType,\r
499 IN UINTN Instance,\r
500 OUT EFI_FILE_SECTION_POINTER *Section\r
501 )\r
502/*++\r
503\r
504Routine Description:\r
505\r
506 Find a section in a file by type and instance. An instance of 1 is the first \r
507 instance. The function will return NULL if a matching section cannot be found.\r
508 GUID-defined sections, if special processing is not needed, are handled in a\r
509 depth-first manner.\r
510\r
511Arguments:\r
512\r
513 File The file to search.\r
514 SectionType Type of file to search for.\r
515 Instance Instace of the section to return.\r
516 Section Return pointer. In the case of an error, contents are undefined.\r
517\r
518Returns:\r
519\r
520 EFI_SUCCESS The function completed successfully.\r
521 EFI_ABORTED An error was encountered.\r
522 EFI_INVALID_PARAMETER One of the parameters was NULL.\r
523 EFI_NOT_FOUND No found.\r
524--*/\r
525{\r
526 EFI_FILE_SECTION_POINTER CurrentSection;\r
527 EFI_STATUS Status;\r
528 UINTN SectionCount;\r
529\r
530 //\r
531 // Verify input parameters\r
532 //\r
533 if (File == NULL || Instance == 0) {\r
534 return EFI_INVALID_PARAMETER;\r
535 }\r
536 //\r
537 // Verify FFS header\r
538 //\r
539 Status = VerifyFfsFile (File);\r
540 if (EFI_ERROR (Status)) {\r
541 Error (NULL, 0, 0006, "invalid FFS file", NULL);\r
542 return EFI_ABORTED;\r
543 }\r
544 //\r
545 // Initialize the number of matching sections found.\r
546 //\r
547 SectionCount = 0;\r
548\r
549 //\r
550 // Get the first section\r
551 //\r
e8a47801 552 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + GetFfsHeaderLength(File));\r
30fdf114
LG
553 \r
554 //\r
555 // Depth-first manner to find section file.\r
556 //\r
557 Status = SearchSectionByType (\r
558 CurrentSection,\r
e8a47801 559 (UINT8 *) ((UINTN) File + GetFfsFileLength (File)),\r
30fdf114
LG
560 SectionType,\r
561 &SectionCount,\r
562 Instance,\r
563 Section\r
564 );\r
565\r
566 if (!EFI_ERROR (Status)) {\r
567 return EFI_SUCCESS;\r
568 } else {\r
569 //\r
570 // Section not found\r
571 //\r
572 (*Section).Code16Section = NULL;\r
573 return EFI_NOT_FOUND;\r
574 }\r
575}\r
576//\r
577// will not parse compressed sections\r
578//\r
579EFI_STATUS\r
580VerifyFv (\r
581 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
582 )\r
583/*++\r
584\r
585Routine Description:\r
586\r
587 Verify the current pointer points to a valid FV header.\r
588\r
589Arguments:\r
590\r
591 FvHeader Pointer to an alleged FV file.\r
592\r
593Returns:\r
594\r
595 EFI_SUCCESS The FV header is valid.\r
596 EFI_VOLUME_CORRUPTED The FV header is not valid.\r
597 EFI_INVALID_PARAMETER A required parameter was NULL.\r
598 EFI_ABORTED Operation aborted.\r
599\r
600--*/\r
601{\r
602 UINT16 Checksum;\r
603\r
604 //\r
605 // Verify input parameters\r
606 //\r
607 if (FvHeader == NULL) {\r
608 return EFI_INVALID_PARAMETER;\r
609 }\r
610\r
611 if (FvHeader->Signature != EFI_FVH_SIGNATURE) {\r
612 Error (NULL, 0, 0006, "invalid FV header signature", NULL);\r
613 return EFI_VOLUME_CORRUPTED;\r
614 }\r
615 //\r
616 // Verify header checksum\r
617 //\r
618 Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));\r
619\r
620 if (Checksum != 0) {\r
621 Error (NULL, 0, 0006, "invalid FV header checksum", NULL);\r
622 return EFI_ABORTED;\r
623 }\r
624\r
625 return EFI_SUCCESS;\r
626}\r
627\r
628EFI_STATUS\r
629VerifyFfsFile (\r
630 IN EFI_FFS_FILE_HEADER *FfsHeader\r
631 )\r
632/*++\r
633\r
634Routine Description:\r
635\r
636 Verify the current pointer points to a FFS file header.\r
637\r
638Arguments:\r
639\r
640 FfsHeader Pointer to an alleged FFS file.\r
641\r
642Returns:\r
643\r
644 EFI_SUCCESS The Ffs header is valid.\r
645 EFI_NOT_FOUND This "file" is the beginning of free space.\r
646 EFI_VOLUME_CORRUPTED The Ffs header is not valid.\r
647 EFI_ABORTED The erase polarity is not known.\r
648\r
649--*/\r
650{\r
651 BOOLEAN ErasePolarity;\r
652 EFI_STATUS Status;\r
e8a47801 653 EFI_FFS_FILE_HEADER2 BlankHeader;\r
30fdf114
LG
654 UINT8 Checksum;\r
655 UINT32 FileLength;\r
656 UINT8 SavedChecksum;\r
657 UINT8 SavedState;\r
658 UINT8 FileGuidString[80];\r
e8a47801
LG
659 UINT32 FfsHeaderSize;\r
660\r
30fdf114
LG
661 //\r
662 // Verify library has been initialized.\r
663 //\r
664 if (mFvHeader == NULL || mFvLength == 0) {\r
665 return EFI_ABORTED;\r
666 }\r
667 //\r
668 // Verify FV header\r
669 //\r
670 Status = VerifyFv (mFvHeader);\r
671 if (EFI_ERROR (Status)) {\r
672 return EFI_ABORTED;\r
673 }\r
674 //\r
675 // Get the erase polarity.\r
676 //\r
677 Status = GetErasePolarity (&ErasePolarity);\r
678 if (EFI_ERROR (Status)) {\r
679 return EFI_ABORTED;\r
680 }\r
e8a47801
LG
681\r
682 FfsHeaderSize = GetFfsHeaderLength(FfsHeader);\r
30fdf114
LG
683 //\r
684 // Check if we have free space\r
685 //\r
686 if (ErasePolarity) {\r
e8a47801 687 memset (&BlankHeader, -1, FfsHeaderSize);\r
30fdf114 688 } else {\r
e8a47801 689 memset (&BlankHeader, 0, FfsHeaderSize);\r
30fdf114
LG
690 }\r
691\r
e8a47801 692 if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) {\r
30fdf114
LG
693 return EFI_NOT_FOUND;\r
694 }\r
695 //\r
696 // Convert the GUID to a string so we can at least report which file\r
697 // if we find an error.\r
698 //\r
699 PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
700 //\r
701 // Verify file header checksum\r
702 //\r
703 SavedState = FfsHeader->State;\r
704 FfsHeader->State = 0;\r
705 SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;\r
706 FfsHeader->IntegrityCheck.Checksum.File = 0;\r
e8a47801 707 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize);\r
30fdf114
LG
708 FfsHeader->State = SavedState;\r
709 FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;\r
710 if (Checksum != 0) {\r
711 Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString);\r
712 return EFI_ABORTED;\r
713 }\r
714 //\r
715 // Verify file checksum\r
716 //\r
717 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
718 //\r
719 // Verify file data checksum\r
720 //\r
e8a47801
LG
721 FileLength = GetFfsFileLength (FfsHeader);\r
722 Checksum = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize);\r
b303ea72 723 Checksum = Checksum + FfsHeader->IntegrityCheck.Checksum.File;\r
30fdf114
LG
724 if (Checksum != 0) {\r
725 Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString);\r
726 return EFI_ABORTED;\r
727 }\r
728 } else {\r
729 //\r
730 // File does not have a checksum\r
b303ea72 731 // Verify contents are 0xAA as spec'd\r
30fdf114
LG
732 //\r
733 if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {\r
734 Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString);\r
735 return EFI_ABORTED;\r
736 }\r
737 }\r
738\r
739 return EFI_SUCCESS;\r
740}\r
741\r
e8a47801
LG
742UINT32\r
743GetFfsHeaderLength(\r
744 IN EFI_FFS_FILE_HEADER *FfsHeader\r
745 )\r
746{\r
747 if (FfsHeader == NULL) {\r
748 return 0;\r
749 }\r
750 if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
751 return sizeof(EFI_FFS_FILE_HEADER2);\r
752 }\r
753 return sizeof(EFI_FFS_FILE_HEADER);\r
754}\r
755\r
756UINT32\r
757GetSectionHeaderLength(\r
758 IN EFI_COMMON_SECTION_HEADER *SectionHeader\r
759 )\r
760{\r
761 if (SectionHeader == NULL) {\r
762 return 0;\r
763 }\r
764 if (GetLength(SectionHeader->Size) == 0xffffff) {\r
765 return sizeof(EFI_COMMON_SECTION_HEADER2);\r
766 }\r
767 return sizeof(EFI_COMMON_SECTION_HEADER);\r
768}\r
769\r
770UINT32\r
771GetFfsFileLength (\r
772 EFI_FFS_FILE_HEADER *FfsHeader\r
773 )\r
774/*++\r
775\r
776Routine Description:\r
777\r
778 Get FFS file length including FFS header.\r
779\r
780Arguments:\r
781\r
782 FfsHeader Pointer to EFI_FFS_FILE_HEADER.\r
783\r
784Returns:\r
785\r
786 UINT32 Length of FFS file header.\r
787\r
788--*/\r
789{\r
790 if (FfsHeader == NULL) {\r
791 return 0;\r
792 }\r
793 if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) {\r
794 return ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize;\r
795 } else {\r
796 return GetLength(FfsHeader->Size);\r
797 }\r
798}\r
799\r
800UINT32\r
801GetSectionFileLength (\r
802 EFI_COMMON_SECTION_HEADER *SectionHeader\r
803 )\r
804{\r
805 UINT32 Length;\r
806 if (SectionHeader == NULL) {\r
807 return 0;\r
808 }\r
809 Length = GetLength(SectionHeader->Size);\r
810 if (Length == 0xffffff) {\r
811 Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;\r
812 }\r
813 return Length;\r
814}\r
815\r
30fdf114
LG
816UINT32\r
817GetLength (\r
818 UINT8 *ThreeByteLength\r
819 )\r
820/*++\r
821\r
822Routine Description:\r
823\r
824 Converts a three byte length value into a UINT32.\r
825\r
826Arguments:\r
827\r
828 ThreeByteLength Pointer to the first of the 3 byte length.\r
829\r
830Returns:\r
831\r
832 UINT32 Size of the section\r
833\r
834--*/\r
835{\r
836 UINT32 Length;\r
837\r
838 if (ThreeByteLength == NULL) {\r
839 return 0;\r
840 }\r
841\r
842 Length = *((UINT32 *) ThreeByteLength);\r
843 Length = Length & 0x00FFFFFF;\r
844\r
845 return Length;\r
846}\r
847\r
848EFI_STATUS\r
849GetErasePolarity (\r
850 OUT BOOLEAN *ErasePolarity\r
851 )\r
852/*++\r
853\r
854Routine Description:\r
855\r
856 This function returns with the FV erase polarity. If the erase polarity\r
857 for a bit is 1, the function return TRUE.\r
858\r
859Arguments:\r
860\r
861 ErasePolarity A pointer to the erase polarity.\r
862\r
863Returns:\r
864\r
865 EFI_SUCCESS The function completed successfully.\r
866 EFI_INVALID_PARAMETER One of the input parameters was invalid.\r
867 EFI_ABORTED Operation aborted.\r
868 \r
869--*/\r
870{\r
871 EFI_STATUS Status;\r
872\r
873 //\r
874 // Verify library has been initialized.\r
875 //\r
876 if (mFvHeader == NULL || mFvLength == 0) {\r
877 return EFI_ABORTED;\r
878 }\r
879 //\r
880 // Verify FV header\r
881 //\r
882 Status = VerifyFv (mFvHeader);\r
883 if (EFI_ERROR (Status)) {\r
884 return EFI_ABORTED;\r
885 }\r
886 //\r
887 // Verify input parameters.\r
888 //\r
889 if (ErasePolarity == NULL) {\r
890 return EFI_INVALID_PARAMETER;\r
891 }\r
892\r
893 if (mFvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {\r
894 *ErasePolarity = TRUE;\r
895 } else {\r
896 *ErasePolarity = FALSE;\r
897 }\r
898\r
899 return EFI_SUCCESS;\r
900}\r
901\r
902UINT8\r
903GetFileState (\r
904 IN BOOLEAN ErasePolarity,\r
905 IN EFI_FFS_FILE_HEADER *FfsHeader\r
906 )\r
907/*++\r
908\r
909Routine Description:\r
910\r
911 This function returns a the highest state bit in the FFS that is set.\r
912 It in no way validate the FFS file.\r
913\r
914Arguments:\r
915 \r
916 ErasePolarity The erase polarity for the file state bits.\r
917 FfsHeader Pointer to a FFS file.\r
918\r
919Returns:\r
920\r
921 UINT8 The hightest set state of the file.\r
922\r
923--*/\r
924{\r
925 UINT8 FileState;\r
926 UINT8 HighestBit;\r
927\r
928 FileState = FfsHeader->State;\r
929\r
930 if (ErasePolarity) {\r
931 FileState = (UINT8)~FileState;\r
932 }\r
933\r
934 HighestBit = 0x80;\r
935 while (HighestBit != 0 && (HighestBit & FileState) == 0) {\r
936 HighestBit >>= 1;\r
937 }\r
938\r
939 return HighestBit;\r
940}\r