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