3 Copyright (c) 1999 - 2008, 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
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.
18 The tool dumps the contents of a firmware volume
29 #include <Common/UefiBaseTypes.h>
30 #include <Common/UefiCapsule.h>
31 #include <Common/PiFirmwareFile.h>
32 #include <Common/PiFirmwareVolume.h>
33 #include <Guid/PiFirmwareFileSystem.h>
34 #include <IndustryStandard/PeImage.h>
35 #include <Protocol/GuidedSectionExtraction.h>
38 #include "Decompress.h"
40 #include "CommonLib.h"
41 #include "EfiUtilityMsgs.h"
42 #include "FirmwareVolumeBufferLib.h"
44 #include "ParseGuidedSectionTools.h"
45 #include "StringFuncs.h"
48 // Utility global variables
51 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
53 #define UTILITY_MAJOR_VERSION 0
54 #define UTILITY_MINOR_VERSION 82
56 #define UTILITY_NAME "VolInfo"
58 #define EFI_SECTION_ERROR EFIERR (100)
60 #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable
63 // Structure to keep a list of guid-to-basenames
65 typedef struct _GUID_TO_BASENAME
{
66 struct _GUID_TO_BASENAME
*Next
;
67 INT8 Guid
[PRINTED_GUID_BUFFER_SIZE
];
68 INT8 BaseName
[MAX_BASENAME_LEN
];
71 static GUID_TO_BASENAME
*mGuidBaseNameList
= NULL
;
74 // Store GUIDed Section guid->tool mapping
76 EFI_HANDLE mParsedGuidedSectionTools
= NULL
;
78 CHAR8
* mUtilityFilename
= NULL
;
81 ParseGuidBaseNameFile (
86 FreeGuidBaseNameList (
97 IN UINT8
*SectionBuffer
,
98 IN UINT32 BufferLength
104 IN UINT32 SectionLength
112 OUT BOOLEAN
*ErasePolarity
118 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
119 EFI_FFS_FILE_HEADER
*FileHeader
,
120 BOOLEAN ErasePolarity
131 LoadGuidedSectionToolsTxt (
132 IN CHAR8
* FirmwareVolumeFilename
149 GC_TODO: Add function description
153 argc - GC_TODO: add argument description
154 ] - GC_TODO: add argument description
158 GC_TODO: add return values
164 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
168 BOOLEAN ErasePolarity
;
170 SetUtilityName (UTILITY_NAME
);
172 // Print utility header
174 printf ("%s Tiano Firmware Volume FFS image info. Version %d.%d, %s\n",
176 UTILITY_MAJOR_VERSION
,
177 UTILITY_MINOR_VERSION
,
182 // Save, and then skip filename arg
184 mUtilityFilename
= argv
[0];
191 // If they specified -x xref guid/basename cross-reference files, process it.
192 // This will print the basename beside each file guid. To use it, specify
193 // -x xref_filename to processdsc, then use xref_filename as a parameter
197 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
198 ParseGuidBaseNameFile (argv
[1]);
199 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
202 } else if (strcmp(argv
[0], "--offset") == 0) {
206 if ((argv
[1][0] == '0') && (tolower (argv
[1][1]) == 'x')) {
207 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
208 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
209 return GetUtilityStatus ();
212 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
213 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
214 return GetUtilityStatus ();
217 // See if they said something like "64K"
219 if (tolower (argv
[1][strlen (argv
[1]) - 1]) == 'k') {
232 // Check for proper number of arguments
239 // Look for help options
241 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
242 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
248 // Open the file containing the FV
250 InputFile
= fopen (argv
[0], "rb");
251 if (InputFile
== NULL
) {
252 Error (NULL
, 0, 0001, "Error opening the input file", argv
[0]);
253 return GetUtilityStatus ();
256 // Skip over pad bytes if specified. This is used if they prepend 0xff
257 // data to the FV image binary.
260 fseek (InputFile
, Offset
, SEEK_SET
);
263 // Determine size of FV
265 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
266 if (EFI_ERROR (Status
)) {
267 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", argv
[0]);
269 return GetUtilityStatus ();
272 // Allocate a buffer for the FV image
274 FvImage
= malloc (FvSize
);
275 if (FvImage
== NULL
) {
276 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
278 return GetUtilityStatus ();
281 // Seek to the start of the image, then read the entire FV to the buffer
283 fseek (InputFile
, Offset
, SEEK_SET
);
284 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
286 if ((unsigned int) BytesRead
!= FvSize
) {
287 Error (NULL
, 0, 0004, "error reading FvImage from", argv
[0]);
289 return GetUtilityStatus ();
292 LoadGuidedSectionToolsTxt (argv
[0]);
294 PrintFvInfo (FvImage
);
300 FreeGuidBaseNameList ();
301 return GetUtilityStatus ();
314 GC_TODO: Add function description
318 Fv - Firmware Volume to print information about
328 BOOLEAN ErasePolarity
;
330 EFI_FFS_FILE_HEADER
*CurrentFile
;
333 Status
= FvBufGetSize (Fv
, &FvSize
);
337 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
341 // Get the first file
344 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
345 if (EFI_ERROR (Status
)) {
346 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
347 return GetUtilityStatus ();
350 // Display information about files found
352 while (CurrentFile
!= NULL
) {
354 // Increment the number of files counter
359 // Display info about this file
361 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
362 if (EFI_ERROR (Status
)) {
363 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
364 return GetUtilityStatus ();
369 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
370 if (Status
== EFI_NOT_FOUND
) {
372 } else if (EFI_ERROR (Status
)) {
373 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
374 return GetUtilityStatus ();
378 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
385 IN UINT32 ActualSize
,
392 This function returns the next larger size that meets the alignment
393 requirement specified.
398 Alignment The desired alignment.
402 EFI_SUCCESS Function completed successfully.
403 EFI_ABORTED The function encountered an error.
409 OccupiedSize
= ActualSize
;
410 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
420 IN EFI_SECTION_TYPE Type
426 Converts EFI Section names to Strings
430 Type - The EFI Section type
434 CHAR8* - Pointer to the String containing the section name.
439 CHAR8
*SectionTypeStringTable
[] = {
444 "EFI_SECTION_COMPRESSION",
448 "EFI_SECTION_GUID_DEFINED",
452 "Unknown section type - Reserved 0x03",
456 "Unknown section type - Reserved 0x04",
460 "Unknown section type - Reserved 0x05",
464 "Unknown section type - Reserved 0x06",
468 "Unknown section type - Reserved 0x07",
472 "Unknown section type - Reserved 0x08",
476 "Unknown section type - Reserved 0x09",
480 "Unknown section type - Reserved 0x0A",
484 "Unknown section type - Reserved 0x0B",
488 "Unknown section type - Reserved 0x0C",
492 "Unknown section type - Reserved 0x0D",
496 "Unknown section type - Reserved 0x0E",
500 "Unknown section type - Reserved 0x0F",
516 "EFI_SECTION_DXE_DEPEX",
520 "EFI_SECTION_VERSION",
524 "EFI_SECTION_USER_INTERFACE",
528 "EFI_SECTION_COMPATIBILITY16",
532 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
536 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
544 "Unknown section type - 0x1A",
548 "EFI_SECTION_PEI_DEPEX",
552 "Unknown section type - Reserved - beyond last defined section"
558 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
559 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
562 SectionStr
= malloc (100);
563 if (SectionStr
== NULL
) {
564 printf ("Error: Out of memory resources.\n");
567 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
576 OUT BOOLEAN
*ErasePolarity
582 This function determines the size of the FV and the erase polarity. The
583 erase polarity is the FALSE value for file state.
587 InputFile The file that contains the FV image.
588 FvSize The size of the FV.
589 ErasePolarity The FV erase polarity.
593 EFI_SUCCESS Function completed successfully.
594 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
595 EFI_ABORTED The function encountered an error.
599 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
600 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
608 // Check input parameters
610 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
611 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
612 return EFI_INVALID_PARAMETER
;
617 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
618 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
619 Signature
[0] = VolumeHeader
.Signature
;
623 // Print FV header information
625 printf ("Signature: %s (%X)\n", (char *) Signature
, VolumeHeader
.Signature
);
626 printf ("Attributes: %X\n", VolumeHeader
.Attributes
);
628 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
629 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
632 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
633 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
636 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
637 printf (" EFI_FVB2_READ_STATUS\n");
640 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
641 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
644 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
645 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
648 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
649 printf (" EFI_FVB2_WRITE_STATUS\n");
652 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
653 printf (" EFI_FVB2_LOCK_CAP\n");
656 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
657 printf (" EFI_FVB2_LOCK_STATUS\n");
660 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
661 printf (" EFI_FVB2_STICKY_WRITE\n");
664 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
665 printf (" EFI_FVB2_MEMORY_MAPPED\n");
668 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
669 printf (" EFI_FVB2_ERASE_POLARITY\n");
670 *ErasePolarity
= TRUE
;
673 #if (PI_SPECIFICATION_VERSION < 0x00010000)
674 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
675 printf (" EFI_FVB2_ALIGNMENT\n");
678 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
679 printf (" EFI_FVB2_ALIGNMENT_2\n");
682 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
683 printf (" EFI_FVB2_ALIGNMENT_4\n");
686 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
687 printf (" EFI_FVB2_ALIGNMENT_8\n");
690 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
691 printf (" EFI_FVB2_ALIGNMENT_16\n");
694 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
695 printf (" EFI_FVB2_ALIGNMENT_32\n");
698 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
699 printf (" EFI_FVB2_ALIGNMENT_64\n");
702 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
703 printf (" EFI_FVB2_ALIGNMENT_128\n");
706 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
707 printf (" EFI_FVB2_ALIGNMENT_256\n");
710 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
711 printf (" EFI_FVB2_ALIGNMENT_512\n");
714 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
715 printf (" EFI_FVB2_ALIGNMENT_1K\n");
718 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
719 printf (" EFI_FVB2_ALIGNMENT_2K\n");
722 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
723 printf (" EFI_FVB2_ALIGNMENT_4K\n");
726 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
727 printf (" EFI_FVB2_ALIGNMENT_8K\n");
730 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
731 printf (" EFI_FVB2_ALIGNMENT_16K\n");
734 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
735 printf (" EFI_FVB2_ALIGNMENT_32K\n");
738 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
739 printf (" EFI_FVB2_ALIGNMENT_64K\n");
744 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
745 printf (" EFI_FVB2_READ_LOCK_CAP\n");
748 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
749 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
752 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
753 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
756 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
757 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
760 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1
) {
761 printf (" EFI_FVB2_ALIGNMENT_1\n");
764 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
765 printf (" EFI_FVB2_ALIGNMENT_2\n");
768 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
769 printf (" EFI_FVB2_ALIGNMENT_4\n");
772 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
773 printf (" EFI_FVB2_ALIGNMENT_8\n");
776 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
777 printf (" EFI_FVB2_ALIGNMENT_16\n");
780 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
781 printf (" EFI_FVB2_ALIGNMENT_32\n");
784 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
785 printf (" EFI_FVB2_ALIGNMENT_64\n");
788 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
789 printf (" EFI_FVB2_ALIGNMENT_128\n");
792 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
793 printf (" EFI_FVB2_ALIGNMENT_256\n");
796 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
797 printf (" EFI_FVB2_ALIGNMENT_512\n");
800 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
801 printf (" EFI_FVB2_ALIGNMENT_1K\n");
804 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
805 printf (" EFI_FVB2_ALIGNMENT_2K\n");
808 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
809 printf (" EFI_FVB2_ALIGNMENT_4K\n");
812 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
813 printf (" EFI_FVB2_ALIGNMENT_8K\n");
816 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
817 printf (" EFI_FVB2_ALIGNMENT_16K\n");
820 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
821 printf (" EFI_FVB2_ALIGNMENT_32K\n");
824 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
825 printf (" EFI_FVB2_ALIGNMENT_64K\n");
828 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128K
) {
829 printf (" EFI_FVB2_ALIGNMENT_128K\n");
832 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256K
) {
833 printf (" EFI_FVB2_ALIGNMENT_256K\n");
836 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMNET_512K
) {
837 printf (" EFI_FVB2_ALIGNMNET_512K\n");
840 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1M
) {
841 printf (" EFI_FVB2_ALIGNMENT_1M\n");
844 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2M
) {
845 printf (" EFI_FVB2_ALIGNMENT_2M\n");
848 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4M
) {
849 printf (" EFI_FVB2_ALIGNMENT_4M\n");
852 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8M
) {
853 printf (" EFI_FVB2_ALIGNMENT_8M\n");
856 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16M
) {
857 printf (" EFI_FVB2_ALIGNMENT_16M\n");
860 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32M
) {
861 printf (" EFI_FVB2_ALIGNMENT_32M\n");
864 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
865 printf (" EFI_FVB2_ALIGNMENT_64M\n");
868 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
869 printf (" EFI_FVB2_ALIGNMENT_128M\n");
872 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
873 printf (" EFI_FVB2_ALIGNMENT_64M\n");
876 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
877 printf (" EFI_FVB2_ALIGNMENT_128M\n");
880 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256M
) {
881 printf (" EFI_FVB2_ALIGNMENT_256M\n");
884 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512M
) {
885 printf (" EFI_FVB2_ALIGNMENT_512M\n");
888 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1G
) {
889 printf (" EFI_FVB2_ALIGNMENT_1G\n");
892 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2G
) {
893 printf (" EFI_FVB2_ALIGNMENT_2G\n");
897 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
898 printf ("File System ID: ");
899 PrintGuid (&VolumeHeader
.FileSystemGuid
);
903 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
906 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
907 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
909 if (BlockMap
.NumBlocks
!= 0) {
910 printf ("Number of Blocks: 0x%08X\n", BlockMap
.NumBlocks
);
911 printf ("Block Length: 0x%08X\n", BlockMap
.Length
);
912 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
915 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
917 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
918 printf ("ERROR: Header length not consistent with Block Maps!\n");
922 if (VolumeHeader
.FvLength
!= Size
) {
923 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
927 printf ("Total Volume Size: 0x%08X\n", Size
);
932 // rewind (InputFile);
940 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
941 EFI_FFS_FILE_HEADER
*FileHeader
,
942 BOOLEAN ErasePolarity
948 GC_TODO: Add function description
952 FvImage - GC_TODO: add argument description
953 FileHeader - GC_TODO: add argument description
954 ErasePolarity - GC_TODO: add argument description
958 EFI_SUCCESS - GC_TODO: Add description for return value
959 EFI_ABORTED - GC_TODO: Add description for return value
966 EFI_FFS_FILE_HEADER BlankHeader
;
968 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
969 #if (PI_SPECIFICATION_VERSION < 0x00010000)
973 // Check if we have free space
976 memset (&BlankHeader
, -1, sizeof (EFI_FFS_FILE_HEADER
));
978 memset (&BlankHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
981 if (memcmp (&BlankHeader
, FileHeader
, sizeof (EFI_FFS_FILE_HEADER
)) == 0) {
985 // Print file information.
987 printf ("============================================================\n");
989 printf ("File Name: ");
990 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
991 printf ("%s ", GuidBuffer
);
992 PrintGuidName (GuidBuffer
);
996 // PrintGuid (&FileHeader->Name);
999 FileLength
= GetLength (FileHeader
->Size
);
1000 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1001 printf ("File Length: 0x%08X\n", FileLength
);
1002 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1003 printf ("File State: 0x%02X\n", FileHeader
->State
);
1008 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1010 switch (FileState
) {
1012 case EFI_FILE_HEADER_CONSTRUCTION
:
1013 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1016 case EFI_FILE_HEADER_INVALID
:
1017 printf (" EFI_FILE_HEADER_INVALID\n");
1020 case EFI_FILE_HEADER_VALID
:
1021 printf (" EFI_FILE_HEADER_VALID\n");
1022 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1023 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1024 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1025 if (Checksum
!= 0) {
1026 printf ("ERROR: Header checksum invalid.\n");
1032 case EFI_FILE_DELETED
:
1033 printf (" EFI_FILE_DELETED\n");
1035 case EFI_FILE_MARKED_FOR_UPDATE
:
1036 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1038 case EFI_FILE_DATA_VALID
:
1039 printf (" EFI_FILE_DATA_VALID\n");
1042 // Calculate header checksum
1044 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, sizeof (EFI_FFS_FILE_HEADER
));
1045 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1046 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1047 if (Checksum
!= 0) {
1048 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1052 FileLength
= GetLength (FileHeader
->Size
);
1054 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1056 // Calculate file checksum
1058 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, FileLength
);
1059 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1060 if (Checksum
!= 0) {
1061 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1065 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1066 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0x5A", GuidBuffer
);
1070 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1072 // Verify tail if present
1074 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1076 // Verify tail is complement of integrity check field in the header.
1078 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1079 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1080 Error (NULL
, 0, 0003, "error parsing FFS file", \
1081 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1089 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1093 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1095 switch (FileHeader
->Type
) {
1097 case EFI_FV_FILETYPE_RAW
:
1098 printf ("EFI_FV_FILETYPE_RAW\n");
1101 case EFI_FV_FILETYPE_FREEFORM
:
1102 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1105 case EFI_FV_FILETYPE_SECURITY_CORE
:
1106 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1109 case EFI_FV_FILETYPE_PEI_CORE
:
1110 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1113 case EFI_FV_FILETYPE_DXE_CORE
:
1114 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1117 case EFI_FV_FILETYPE_PEIM
:
1118 printf ("EFI_FV_FILETYPE_PEIM\n");
1121 case EFI_FV_FILETYPE_DRIVER
:
1122 printf ("EFI_FV_FILETYPE_DRIVER\n");
1125 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1126 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1129 case EFI_FV_FILETYPE_APPLICATION
:
1130 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1133 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1134 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1137 case EFI_FV_FILETYPE_FFS_PAD
:
1138 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1142 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1147 switch (FileHeader
->Type
) {
1149 case EFI_FV_FILETYPE_ALL
:
1150 case EFI_FV_FILETYPE_RAW
:
1151 case EFI_FV_FILETYPE_FFS_PAD
:
1156 // All other files have sections
1158 Status
= ParseSection (
1159 (UINT8
*) ((UINTN
) FileHeader
+ sizeof (EFI_FFS_FILE_HEADER
)),
1160 GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_FILE_HEADER
)
1162 if (EFI_ERROR (Status
)) {
1164 // printf ("ERROR: Parsing the FFS file.\n");
1176 IN UINT8
*SectionBuffer
,
1177 IN UINT32 BufferLength
1181 Routine Description:
1187 SectionBuffer - Buffer containing the section to parse.
1188 BufferLength - Length of SectionBuffer
1192 EFI_SECTION_ERROR - Problem with section parsing.
1193 (a) compression errors
1194 (b) unrecognized section
1195 EFI_UNSUPPORTED - Do not know how to parse the section.
1196 EFI_SUCCESS - Section successfully parsed.
1197 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1201 EFI_SECTION_TYPE Type
;
1203 UINT32 SectionLength
;
1206 UINT32 ParsedLength
;
1207 UINT8
*CompressedBuffer
;
1208 UINT32 CompressedLength
;
1209 UINT8
*UncompressedBuffer
;
1210 UINT32 UncompressedLength
;
1211 UINT8
*ToolOutputBuffer
;
1212 UINT32 ToolOutputLength
;
1213 UINT8 CompressionType
;
1216 UINT8
*ScratchBuffer
;
1217 DECOMPRESS_FUNCTION DecompressFunction
;
1218 GETINFO_FUNCTION GetInfoFunction
;
1220 CHAR8
*ExtractionTool
;
1221 CHAR8
*ToolInputFile
;
1222 CHAR8
*ToolOutputFile
;
1223 CHAR8
*SystemCommandFormatString
;
1224 CHAR8
*SystemCommand
;
1227 while (ParsedLength
< BufferLength
) {
1228 Ptr
= SectionBuffer
+ ParsedLength
;
1230 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1231 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1234 // This is sort of an odd check, but is necessary because FFS files are
1235 // padded to a QWORD boundary, meaning there is potentially a whole section
1236 // header worth of 0xFF bytes.
1238 if (SectionLength
== 0xffffff && Type
== 0xff) {
1243 SectionName
= SectionNameToStr (Type
);
1244 printf ("------------------------------------------------------------\n");
1245 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, SectionLength
);
1249 case EFI_SECTION_RAW
:
1250 case EFI_SECTION_PE32
:
1251 case EFI_SECTION_PIC
:
1252 case EFI_SECTION_TE
:
1253 // default is no more information
1256 case EFI_SECTION_USER_INTERFACE
:
1257 // name = &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString;
1258 // printf (" String: %s\n", &name);
1261 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1262 Status
= PrintFvInfo (((EFI_FIRMWARE_VOLUME_IMAGE_SECTION
*)Ptr
) + 1);
1263 if (EFI_ERROR (Status
)) {
1264 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1265 return EFI_SECTION_ERROR
;
1269 case EFI_SECTION_COMPATIBILITY16
:
1270 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1272 // Section does not contain any further header information.
1276 case EFI_SECTION_DXE_DEPEX
:
1277 case EFI_SECTION_PEI_DEPEX
:
1278 DumpDepexSection (Ptr
, SectionLength
);
1281 case EFI_SECTION_VERSION
:
1282 printf (" Build Number: 0x%02X\n", ((EFI_VERSION_SECTION
*) Ptr
)->BuildNumber
);
1283 printf (" Version Strg: %s\n", (char*) ((EFI_VERSION_SECTION
*) Ptr
)->VersionString
);
1286 case EFI_SECTION_COMPRESSION
:
1287 UncompressedBuffer
= NULL
;
1288 CompressedLength
= SectionLength
- sizeof (EFI_COMPRESSION_SECTION
);
1289 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*) Ptr
)->UncompressedLength
;
1290 CompressionType
= ((EFI_COMPRESSION_SECTION
*) Ptr
)->CompressionType
;
1291 printf (" Uncompressed Length: 0x%08X\n", UncompressedLength
);
1293 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1294 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1295 if (CompressedLength
!= UncompressedLength
) {
1300 "file is not compressed, but the compressed length does not match the uncompressed length",
1303 return EFI_SECTION_ERROR
;
1306 UncompressedBuffer
= Ptr
+ sizeof (EFI_COMPRESSION_SECTION
);
1307 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1308 GetInfoFunction
= EfiGetInfo
;
1309 DecompressFunction
= EfiDecompress
;
1310 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1312 CompressedBuffer
= Ptr
+ sizeof (EFI_COMPRESSION_SECTION
);
1314 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1315 if (EFI_ERROR (Status
)) {
1316 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1317 return EFI_SECTION_ERROR
;
1320 if (DstSize
!= UncompressedLength
) {
1321 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1322 return EFI_SECTION_ERROR
;
1325 ScratchBuffer
= malloc (ScratchSize
);
1326 UncompressedBuffer
= malloc (UncompressedLength
);
1327 if ((ScratchBuffer
== NULL
) || (UncompressedBuffer
== NULL
)) {
1328 return EFI_OUT_OF_RESOURCES
;
1330 Status
= DecompressFunction (
1338 free (ScratchBuffer
);
1339 if (EFI_ERROR (Status
)) {
1340 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1341 free (UncompressedBuffer
);
1342 return EFI_SECTION_ERROR
;
1345 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", (UINT32
) CompressionType
);
1346 return EFI_SECTION_ERROR
;
1349 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1351 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1353 // We need to deallocate Buffer
1355 free (UncompressedBuffer
);
1358 if (EFI_ERROR (Status
)) {
1359 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1360 return EFI_SECTION_ERROR
;
1364 case EFI_SECTION_GUID_DEFINED
:
1365 printf (" SectionDefinitionGuid: ");
1366 PrintGuid (&((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
);
1368 printf (" DataOffset: 0x%04X\n", ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
);
1369 printf (" Attributes: 0x%04X\n", ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
);
1372 LookupGuidedSectionToolPath (
1373 mParsedGuidedSectionTools
,
1374 &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
1377 if (ExtractionTool
!= NULL
) {
1379 ToolInputFile
= CloneString (tmpnam (NULL
));
1380 ToolOutputFile
= CloneString (tmpnam (NULL
));
1383 // Construction 'system' command string
1385 SystemCommandFormatString
= "%s -d -o %s %s";
1386 SystemCommand
= malloc (
1387 strlen (SystemCommandFormatString
) +
1388 strlen (ExtractionTool
) +
1389 strlen (ToolInputFile
) +
1390 strlen (ToolOutputFile
) +
1395 SystemCommandFormatString
,
1400 free (ExtractionTool
);
1405 (CHAR8
*) SectionBuffer
+ ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
,
1406 BufferLength
- ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
1409 system (SystemCommand
);
1410 remove (ToolInputFile
);
1411 free (ToolInputFile
);
1416 (CHAR8
**)&ToolOutputBuffer
,
1419 remove (ToolOutputFile
);
1420 free (ToolOutputFile
);
1421 if (EFI_ERROR (Status
)) {
1422 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
1423 return EFI_SECTION_ERROR
;
1426 Status
= ParseSection (
1430 if (EFI_ERROR (Status
)) {
1431 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
1432 return EFI_SECTION_ERROR
;
1436 // Check for CRC32 sections which we can handle internally if needed.
1438 } else if (!CompareGuid (
1439 &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
,
1440 &gEfiCrc32GuidedSectionExtractionProtocolGuid
1444 // CRC32 guided section
1446 Status
= ParseSection (
1447 SectionBuffer
+ ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
,
1448 BufferLength
- ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
1450 if (EFI_ERROR (Status
)) {
1451 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
1452 return EFI_SECTION_ERROR
;
1456 // We don't know how to parse it now.
1458 Error (NULL
, 0, 0003, "Error parsing section", \
1459 "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory).");
1460 return EFI_UNSUPPORTED
;
1466 // Unknown section, return error
1468 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", (UINT32
) Type
);
1469 return EFI_SECTION_ERROR
;
1472 ParsedLength
+= SectionLength
;
1474 // We make then next section begin on a 4-byte boundary
1476 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
1479 if (ParsedLength
< BufferLength
) {
1480 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
1481 return EFI_SECTION_ERROR
;
1490 IN UINT32 SectionLength
1494 Routine Description:
1496 GC_TODO: Add function description
1500 Ptr - GC_TODO: add argument description
1501 SectionLength - GC_TODO: add argument description
1505 EFI_SUCCESS - GC_TODO: Add description for return value
1509 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1512 // Need at least a section header + data
1514 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
1518 Ptr
+= sizeof (EFI_COMMON_SECTION_HEADER
);
1519 SectionLength
-= sizeof (EFI_COMMON_SECTION_HEADER
);
1520 while (SectionLength
> 0) {
1523 case EFI_DEP_BEFORE
:
1524 printf ("BEFORE\n");
1537 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1538 printf ("%s ", GuidBuffer
);
1539 PrintGuidName (GuidBuffer
);
1542 // PrintGuid ((EFI_GUID *)(Ptr + 1));
1545 SectionLength
-= 17;
1579 printf ("END DEPEX\n");
1591 printf ("Unrecognized byte in depex: 0x%X\n", (UINT32
) *Ptr
);
1605 Routine Description:
1607 GC_TODO: Add function description
1611 GuidStr - GC_TODO: add argument description
1615 EFI_SUCCESS - GC_TODO: Add description for return value
1616 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1620 GUID_TO_BASENAME
*GPtr
;
1622 // If we have a list of guid-to-basenames, then go through the list to
1623 // look for a guid string match. If found, print the basename to stdout,
1624 // otherwise return a failure.
1626 GPtr
= mGuidBaseNameList
;
1627 while (GPtr
!= NULL
) {
1628 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
1629 printf ("%s", GPtr
->BaseName
);
1636 return EFI_INVALID_PARAMETER
;
1640 ParseGuidBaseNameFile (
1645 Routine Description:
1647 GC_TODO: Add function description
1651 FileName - GC_TODO: add argument description
1655 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1656 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
1657 EFI_SUCCESS - GC_TODO: Add description for return value
1662 CHAR8 Line
[MAX_LINE_LEN
];
1663 GUID_TO_BASENAME
*GPtr
;
1665 if ((Fptr
= fopen (FileName
, "r")) == NULL
) {
1666 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
1667 return EFI_DEVICE_ERROR
;
1670 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
1672 // Allocate space for another guid/basename element
1674 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
1676 return EFI_OUT_OF_RESOURCES
;
1679 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
1680 if (sscanf (Line
, "%s %s", GPtr
->Guid
, GPtr
->BaseName
) == 2) {
1681 GPtr
->Next
= mGuidBaseNameList
;
1682 mGuidBaseNameList
= GPtr
;
1685 // Some sort of error. Just continue.
1696 FreeGuidBaseNameList (
1701 Routine Description:
1703 GC_TODO: Add function description
1711 EFI_SUCCESS - GC_TODO: Add description for return value
1715 GUID_TO_BASENAME
*Next
;
1717 while (mGuidBaseNameList
!= NULL
) {
1718 Next
= mGuidBaseNameList
->Next
;
1719 free (mGuidBaseNameList
);
1720 mGuidBaseNameList
= Next
;
1729 LoadGuidedSectionToolsTxt (
1730 IN CHAR8
* FirmwareVolumeFilename
1733 CHAR8
* PeerFilename
;
1735 FirmwareVolumeFilename
,
1740 mParsedGuidedSectionTools
= NULL
;
1742 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
1743 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
1744 //printf("Loading %s...\n", PeerFilename);
1745 if (OsPathExists (PeerFilename
)) {
1746 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
1748 free (PeerFilename
);
1749 if (mParsedGuidedSectionTools
!= NULL
) {
1762 Routine Description:
1764 GC_TODO: Add function description
1772 GC_TODO: add return values
1779 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
1782 // Copyright declaration
1784 fprintf (stdout
, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
1789 fprintf (stdout
, "Options:\n");
1790 fprintf (stdout
, " -x xref, --xref xref\n\
1791 Parse basename to file-guid cross reference file(s).\n");
1792 fprintf (stdout
, " --offset offset\n\
1793 Offset of file to start processing FV at.\n");
1794 fprintf (stdout
, " -h, --help\n\
1795 Show this help message and exit.\n");