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