2 The tool dumps the contents of a firmware volume
4 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/UefiCapsule.h>
29 #include <Common/PiFirmwareFile.h>
30 #include <Common/PiFirmwareVolume.h>
31 #include <Guid/PiFirmwareFileSystem.h>
32 #include <IndustryStandard/PeImage.h>
33 #include <Protocol/GuidedSectionExtraction.h>
36 #include "Decompress.h"
38 #include "CommonLib.h"
39 #include "EfiUtilityMsgs.h"
40 #include "FirmwareVolumeBufferLib.h"
42 #include "ParseGuidedSectionTools.h"
43 #include "StringFuncs.h"
45 #include "PeCoffLib.h"
48 // Utility global variables
51 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
53 #define UTILITY_MAJOR_VERSION 1
54 #define UTILITY_MINOR_VERSION 0
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
;
80 BOOLEAN EnableHash
= FALSE
;
81 CHAR8
*OpenSslPath
= NULL
;
84 ParseGuidBaseNameFile (
89 FreeGuidBaseNameList (
100 IN UINT8
*SectionBuffer
,
101 IN UINT32 BufferLength
107 IN UINT32 SectionLength
115 OUT BOOLEAN
*ErasePolarity
121 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
122 EFI_FFS_FILE_HEADER
*FileHeader
,
123 BOOLEAN ErasePolarity
135 LoadGuidedSectionToolsTxt (
136 IN CHAR8
* FirmwareVolumeFilename
141 IN CHAR8
* DefaultPath
,
142 IN CHAR8
* AppendPath
,
160 GC_TODO: Add function description
164 argc - GC_TODO: add argument description
165 ] - GC_TODO: add argument description
169 GC_TODO: add return values
175 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
179 BOOLEAN ErasePolarity
;
182 CHAR8
*OpenSslCommand
;
184 SetUtilityName (UTILITY_NAME
);
186 // Print utility header
188 printf ("%s Version %d.%d Build %s\n",
190 UTILITY_MAJOR_VERSION
,
191 UTILITY_MINOR_VERSION
,
206 // Look for help options
208 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
209 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
211 return STATUS_SUCCESS
;
214 // Version has already be printed, so just return success
216 if (strcmp(argv
[0], "--version") == 0) {
217 return STATUS_SUCCESS
;
221 // If they specified -x xref guid/basename cross-reference files, process it.
222 // This will print the basename beside each file guid. To use it, specify
223 // -x xref_filename to processdsc, then use xref_filename as a parameter
227 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
228 ParseGuidBaseNameFile (argv
[1]);
229 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
234 if (strcmp(argv
[0], "--offset") == 0) {
238 if ((argv
[1][0] == '0') && (tolower ((int)argv
[1][1]) == 'x')) {
239 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
240 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
241 return GetUtilityStatus ();
244 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
245 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
246 return GetUtilityStatus ();
249 // See if they said something like "64K"
251 if (tolower ((int)argv
[1][strlen (argv
[1]) - 1]) == 'k') {
260 if ((stricmp (argv
[0], "--hash") == 0)) {
261 if (EnableHash
== TRUE
) {
263 // --hash already given in the option, ignore this one
270 OpenSslCommand
= "openssl";
271 OpenSslEnv
= getenv("OPENSSL_PATH");
272 if (OpenSslEnv
== NULL
) {
273 OpenSslPath
= OpenSslCommand
;
275 OpenSslPath
= malloc(strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
276 if (OpenSslPath
== NULL
) {
277 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
278 return GetUtilityStatus ();
280 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
282 if (OpenSslPath
== NULL
){
283 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
284 return GetUtilityStatus ();
291 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
292 SetPrintLevel (VERBOSE_LOG_LEVEL
);
298 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
299 SetPrintLevel (KEY_LOG_LEVEL
);
305 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
306 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
307 if (EFI_ERROR (Status
)) {
308 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
312 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
315 SetPrintLevel (LogLevel
);
316 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
322 mUtilityFilename
= argv
[0];
328 // Open the file containing the FV
330 if (mUtilityFilename
== NULL
) {
331 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
332 return GetUtilityStatus ();
334 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
335 if (InputFile
== NULL
) {
336 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
337 return GetUtilityStatus ();
340 // Skip over pad bytes if specified. This is used if they prepend 0xff
341 // data to the FV image binary.
344 fseek (InputFile
, Offset
, SEEK_SET
);
347 // Determine size of FV
349 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
350 if (EFI_ERROR (Status
)) {
351 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
353 return GetUtilityStatus ();
356 // Allocate a buffer for the FV image
358 FvImage
= malloc (FvSize
);
359 if (FvImage
== NULL
) {
360 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
362 return GetUtilityStatus ();
365 // Seek to the start of the image, then read the entire FV to the buffer
367 fseek (InputFile
, Offset
, SEEK_SET
);
368 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
370 if ((unsigned int) BytesRead
!= FvSize
) {
371 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
373 return GetUtilityStatus ();
376 LoadGuidedSectionToolsTxt (mUtilityFilename
);
378 PrintFvInfo (FvImage
, FALSE
);
384 FreeGuidBaseNameList ();
385 return GetUtilityStatus ();
399 GC_TODO: Add function description
403 Fv - Firmware Volume to print information about
404 IsChildFv - Flag specifies whether the input FV is a child FV.
414 BOOLEAN ErasePolarity
;
416 EFI_FFS_FILE_HEADER
*CurrentFile
;
419 Status
= FvBufGetSize (Fv
, &FvSize
);
423 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
427 // Get the first file
430 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
431 if (EFI_ERROR (Status
)) {
432 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
433 return GetUtilityStatus ();
436 // Display information about files found
438 while (CurrentFile
!= NULL
) {
440 // Increment the number of files counter
445 // Display info about this file
447 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
448 if (EFI_ERROR (Status
)) {
449 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
450 return GetUtilityStatus ();
455 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
456 if (Status
== EFI_NOT_FOUND
) {
458 } else if (EFI_ERROR (Status
)) {
459 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
460 return GetUtilityStatus ();
465 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
467 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
475 IN UINT32 ActualSize
,
482 This function returns the next larger size that meets the alignment
483 requirement specified.
488 Alignment The desired alignment.
492 EFI_SUCCESS Function completed successfully.
493 EFI_ABORTED The function encountered an error.
499 OccupiedSize
= ActualSize
;
500 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
510 IN EFI_SECTION_TYPE Type
516 Converts EFI Section names to Strings
520 Type - The EFI Section type
524 CHAR8* - Pointer to the String containing the section name.
529 CHAR8
*SectionTypeStringTable
[] = {
537 "EFI_SECTION_COMPRESSION",
541 "EFI_SECTION_GUID_DEFINED",
545 "Unknown section type - Reserved 0x03",
549 "Unknown section type - Reserved 0x04",
553 "Unknown section type - Reserved 0x05",
557 "Unknown section type - Reserved 0x06",
561 "Unknown section type - Reserved 0x07",
565 "Unknown section type - Reserved 0x08",
569 "Unknown section type - Reserved 0x09",
573 "Unknown section type - Reserved 0x0A",
577 "Unknown section type - Reserved 0x0B",
581 "Unknown section type - Reserved 0x0C",
585 "Unknown section type - Reserved 0x0D",
589 "Unknown section type - Reserved 0x0E",
593 "Unknown section type - Reserved 0x0E",
609 "EFI_SECTION_DXE_DEPEX",
613 "EFI_SECTION_VERSION",
617 "EFI_SECTION_USER_INTERFACE",
621 "EFI_SECTION_COMPATIBILITY16",
625 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
629 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
637 "Unknown section type - 0x1A",
641 "EFI_SECTION_PEI_DEPEX",
645 "EFI_SECTION_SMM_DEPEX",
649 "Unknown section type - Reserved - beyond last defined section"
652 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
653 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
656 SectionStr
= malloc (100);
657 if (SectionStr
== NULL
) {
658 printf ("Error: Out of memory resources.\n");
661 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
670 OUT BOOLEAN
*ErasePolarity
676 This function determines the size of the FV and the erase polarity. The
677 erase polarity is the FALSE value for file state.
681 InputFile The file that contains the FV image.
682 FvSize The size of the FV.
683 ErasePolarity The FV erase polarity.
687 EFI_SUCCESS Function completed successfully.
688 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
689 EFI_ABORTED The function encountered an error.
693 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
694 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
702 // Check input parameters
704 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
705 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
706 return EFI_INVALID_PARAMETER
;
711 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
712 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
713 Signature
[0] = VolumeHeader
.Signature
;
717 // Print FV header information
719 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
720 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
722 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
723 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
726 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
727 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
730 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
731 printf (" EFI_FVB2_READ_STATUS\n");
734 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
735 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
738 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
739 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
742 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
743 printf (" EFI_FVB2_WRITE_STATUS\n");
746 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
747 printf (" EFI_FVB2_LOCK_CAP\n");
750 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
751 printf (" EFI_FVB2_LOCK_STATUS\n");
754 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
755 printf (" EFI_FVB2_STICKY_WRITE\n");
758 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
759 printf (" EFI_FVB2_MEMORY_MAPPED\n");
762 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
763 printf (" EFI_FVB2_ERASE_POLARITY\n");
764 *ErasePolarity
= TRUE
;
767 #if (PI_SPECIFICATION_VERSION < 0x00010000)
768 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
769 printf (" EFI_FVB2_ALIGNMENT\n");
772 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
773 printf (" EFI_FVB2_ALIGNMENT_2\n");
776 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
777 printf (" EFI_FVB2_ALIGNMENT_4\n");
780 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
781 printf (" EFI_FVB2_ALIGNMENT_8\n");
784 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
785 printf (" EFI_FVB2_ALIGNMENT_16\n");
788 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
789 printf (" EFI_FVB2_ALIGNMENT_32\n");
792 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
793 printf (" EFI_FVB2_ALIGNMENT_64\n");
796 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
797 printf (" EFI_FVB2_ALIGNMENT_128\n");
800 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
801 printf (" EFI_FVB2_ALIGNMENT_256\n");
804 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
805 printf (" EFI_FVB2_ALIGNMENT_512\n");
808 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
809 printf (" EFI_FVB2_ALIGNMENT_1K\n");
812 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
813 printf (" EFI_FVB2_ALIGNMENT_2K\n");
816 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
817 printf (" EFI_FVB2_ALIGNMENT_4K\n");
820 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
821 printf (" EFI_FVB2_ALIGNMENT_8K\n");
824 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
825 printf (" EFI_FVB2_ALIGNMENT_16K\n");
828 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
829 printf (" EFI_FVB2_ALIGNMENT_32K\n");
832 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
833 printf (" EFI_FVB2_ALIGNMENT_64K\n");
838 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
839 printf (" EFI_FVB2_READ_LOCK_CAP\n");
842 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
843 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
846 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
847 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
850 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
851 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
854 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1
) {
855 printf (" EFI_FVB2_ALIGNMENT_1\n");
858 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
859 printf (" EFI_FVB2_ALIGNMENT_2\n");
862 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
863 printf (" EFI_FVB2_ALIGNMENT_4\n");
866 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
867 printf (" EFI_FVB2_ALIGNMENT_8\n");
870 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
871 printf (" EFI_FVB2_ALIGNMENT_16\n");
874 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
875 printf (" EFI_FVB2_ALIGNMENT_32\n");
878 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
879 printf (" EFI_FVB2_ALIGNMENT_64\n");
882 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
883 printf (" EFI_FVB2_ALIGNMENT_128\n");
886 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
887 printf (" EFI_FVB2_ALIGNMENT_256\n");
890 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
891 printf (" EFI_FVB2_ALIGNMENT_512\n");
894 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
895 printf (" EFI_FVB2_ALIGNMENT_1K\n");
898 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
899 printf (" EFI_FVB2_ALIGNMENT_2K\n");
902 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
903 printf (" EFI_FVB2_ALIGNMENT_4K\n");
906 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
907 printf (" EFI_FVB2_ALIGNMENT_8K\n");
910 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
911 printf (" EFI_FVB2_ALIGNMENT_16K\n");
914 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
915 printf (" EFI_FVB2_ALIGNMENT_32K\n");
918 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
919 printf (" EFI_FVB2_ALIGNMENT_64K\n");
922 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128K
) {
923 printf (" EFI_FVB2_ALIGNMENT_128K\n");
926 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256K
) {
927 printf (" EFI_FVB2_ALIGNMENT_256K\n");
930 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512K
) {
931 printf (" EFI_FVB2_ALIGNMENT_512K\n");
934 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1M
) {
935 printf (" EFI_FVB2_ALIGNMENT_1M\n");
938 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2M
) {
939 printf (" EFI_FVB2_ALIGNMENT_2M\n");
942 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4M
) {
943 printf (" EFI_FVB2_ALIGNMENT_4M\n");
946 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8M
) {
947 printf (" EFI_FVB2_ALIGNMENT_8M\n");
950 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16M
) {
951 printf (" EFI_FVB2_ALIGNMENT_16M\n");
954 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32M
) {
955 printf (" EFI_FVB2_ALIGNMENT_32M\n");
958 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
959 printf (" EFI_FVB2_ALIGNMENT_64M\n");
962 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
963 printf (" EFI_FVB2_ALIGNMENT_128M\n");
966 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
967 printf (" EFI_FVB2_ALIGNMENT_64M\n");
970 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
971 printf (" EFI_FVB2_ALIGNMENT_128M\n");
974 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256M
) {
975 printf (" EFI_FVB2_ALIGNMENT_256M\n");
978 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512M
) {
979 printf (" EFI_FVB2_ALIGNMENT_512M\n");
982 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1G
) {
983 printf (" EFI_FVB2_ALIGNMENT_1G\n");
986 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2G
) {
987 printf (" EFI_FVB2_ALIGNMENT_2G\n");
991 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
992 printf ("File System ID: ");
993 PrintGuid (&VolumeHeader
.FileSystemGuid
);
997 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1000 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1001 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1003 if (BlockMap
.NumBlocks
!= 0) {
1004 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1005 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1006 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1009 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1011 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1012 printf ("ERROR: Header length not consistent with Block Maps!\n");
1016 if (VolumeHeader
.FvLength
!= Size
) {
1017 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
1021 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1026 // rewind (InputFile);
1034 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1035 EFI_FFS_FILE_HEADER
*FileHeader
,
1036 BOOLEAN ErasePolarity
1040 Routine Description:
1042 GC_TODO: Add function description
1046 FvImage - GC_TODO: add argument description
1047 FileHeader - GC_TODO: add argument description
1048 ErasePolarity - GC_TODO: add argument description
1052 EFI_SUCCESS - GC_TODO: Add description for return value
1053 EFI_ABORTED - GC_TODO: Add description for return value
1060 EFI_FFS_FILE_HEADER2 BlankHeader
;
1062 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1064 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1068 // Check if we have free space
1070 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1071 if (ErasePolarity
) {
1072 memset (&BlankHeader
, -1, HeaderSize
);
1074 memset (&BlankHeader
, 0, HeaderSize
);
1077 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1081 // Print file information.
1083 printf ("============================================================\n");
1085 printf ("File Name: ");
1086 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1087 printf ("%s ", GuidBuffer
);
1088 PrintGuidName (GuidBuffer
);
1092 // PrintGuid (&FileHeader->Name);
1095 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1096 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1097 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1098 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1099 printf ("File State: 0x%02X\n", FileHeader
->State
);
1104 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1106 switch (FileState
) {
1108 case EFI_FILE_HEADER_CONSTRUCTION
:
1109 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1112 case EFI_FILE_HEADER_INVALID
:
1113 printf (" EFI_FILE_HEADER_INVALID\n");
1116 case EFI_FILE_HEADER_VALID
:
1117 printf (" EFI_FILE_HEADER_VALID\n");
1118 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1119 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1120 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1121 if (Checksum
!= 0) {
1122 printf ("ERROR: Header checksum invalid.\n");
1128 case EFI_FILE_DELETED
:
1129 printf (" EFI_FILE_DELETED\n");
1131 case EFI_FILE_MARKED_FOR_UPDATE
:
1132 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1134 case EFI_FILE_DATA_VALID
:
1135 printf (" EFI_FILE_DATA_VALID\n");
1138 // Calculate header checksum
1140 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1141 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1142 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1143 if (Checksum
!= 0) {
1144 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1148 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1150 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1152 // Calculate file checksum
1154 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1155 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1156 if (Checksum
!= 0) {
1157 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1161 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1162 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer
);
1166 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1168 // Verify tail if present
1170 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1172 // Verify tail is complement of integrity check field in the header.
1174 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1175 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1176 Error (NULL
, 0, 0003, "error parsing FFS file", \
1177 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1185 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1189 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1191 switch (FileHeader
->Type
) {
1193 case EFI_FV_FILETYPE_RAW
:
1194 printf ("EFI_FV_FILETYPE_RAW\n");
1197 case EFI_FV_FILETYPE_FREEFORM
:
1198 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1201 case EFI_FV_FILETYPE_SECURITY_CORE
:
1202 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1205 case EFI_FV_FILETYPE_PEI_CORE
:
1206 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1209 case EFI_FV_FILETYPE_DXE_CORE
:
1210 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1213 case EFI_FV_FILETYPE_PEIM
:
1214 printf ("EFI_FV_FILETYPE_PEIM\n");
1217 case EFI_FV_FILETYPE_DRIVER
:
1218 printf ("EFI_FV_FILETYPE_DRIVER\n");
1221 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1222 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1225 case EFI_FV_FILETYPE_APPLICATION
:
1226 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1229 case EFI_FV_FILETYPE_SMM
:
1230 printf ("EFI_FV_FILETYPE_SMM\n");
1233 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1234 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1237 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1238 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1241 case EFI_FV_FILETYPE_SMM_CORE
:
1242 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1245 case EFI_FV_FILETYPE_FFS_PAD
:
1246 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1250 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1255 switch (FileHeader
->Type
) {
1257 case EFI_FV_FILETYPE_ALL
:
1258 case EFI_FV_FILETYPE_RAW
:
1259 case EFI_FV_FILETYPE_FFS_PAD
:
1264 // All other files have sections
1266 Status
= ParseSection (
1267 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1268 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1270 if (EFI_ERROR (Status
)) {
1272 // printf ("ERROR: Parsing the FFS file.\n");
1284 IN VOID
*FileHandle
,
1285 IN UINTN FileOffset
,
1286 IN OUT UINT32
*ReadSize
,
1291 Routine Description:
1293 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1297 FileHandle - The handle to the PE/COFF file
1299 FileOffset - The offset, in bytes, into the file to read
1301 ReadSize - The number of bytes to read from the file starting at FileOffset
1303 Buffer - A pointer to the buffer to read the data into.
1307 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1311 CHAR8
*Destination8
;
1315 Destination8
= Buffer
;
1316 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1319 *(Destination8
++) = *(Source8
++);
1326 SetAddressToSectionHeader (
1328 IN OUT UINT8
*FileBuffer
,
1329 IN UINT64 NewPe32BaseAddress
1333 Routine Description:
1335 Set new base address into the section header of PeImage
1339 FileName - Name of file
1340 FileBuffer - Pointer to PeImage.
1341 NewPe32BaseAddress - New Base Address for PE image.
1345 EFI_SUCCESS Set new base address into this image successfully.
1350 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1352 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1353 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1356 // Initialize context
1358 memset (&ImageContext
, 0, sizeof (ImageContext
));
1359 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1360 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1361 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1362 if (EFI_ERROR (Status
)) {
1363 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1367 if (ImageContext
.RelocationsStripped
) {
1368 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1373 // Get PeHeader pointer
1375 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1378 // Get section header list
1380 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1383 sizeof (EFI_IMAGE_FILE_HEADER
) +
1384 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1388 // Set base address into the first section header that doesn't point to code section.
1390 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1391 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1392 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1398 // BaseAddress is set to section header.
1406 IN OUT UINT8
*FileBuffer
,
1407 IN UINT64 NewPe32BaseAddress
1411 Routine Description:
1413 Set new base address into PeImage, and fix up PeImage based on new address.
1417 FileName - Name of file
1418 FileBuffer - Pointer to PeImage.
1419 NewPe32BaseAddress - New Base Address for PE image.
1423 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1424 EFI_SUCCESS - Update PeImage is correctly.
1429 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1431 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1432 UINT8
*MemoryImagePointer
;
1433 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1436 // Initialize context
1438 memset (&ImageContext
, 0, sizeof (ImageContext
));
1439 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1440 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1441 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1442 if (EFI_ERROR (Status
)) {
1443 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1447 if (ImageContext
.RelocationsStripped
) {
1448 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1453 // Get PeHeader pointer
1455 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1458 // Load and Relocate Image Data
1460 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1461 if (MemoryImagePointer
== NULL
) {
1462 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1463 return EFI_OUT_OF_RESOURCES
;
1465 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1466 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1468 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1469 if (EFI_ERROR (Status
)) {
1470 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1471 free ((VOID
*) MemoryImagePointer
);
1475 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1476 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1477 if (EFI_ERROR (Status
)) {
1478 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1479 free ((VOID
*) MemoryImagePointer
);
1484 // Copy Relocated data to raw image file.
1486 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1489 sizeof (EFI_IMAGE_FILE_HEADER
) +
1490 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1493 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1495 FileBuffer
+ SectionHeader
->PointerToRawData
,
1496 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1497 SectionHeader
->SizeOfRawData
1501 free ((VOID
*) MemoryImagePointer
);
1504 // Update Image Base Address
1506 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1507 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1508 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1509 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1511 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1512 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1519 // Set new base address into section header
1521 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1528 IN CHAR8
* DefaultPath
,
1529 IN CHAR8
* AppendPath
,
1533 UINT32 DefaultPathLen
;
1534 DefaultPathLen
= strlen(DefaultPath
);
1535 strcpy(NewPath
, DefaultPath
);
1537 for (; Index
< DefaultPathLen
; Index
++) {
1538 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1539 if (NewPath
[Index
+ 1] != '\0') {
1540 NewPath
[Index
] = '/';
1544 if (NewPath
[Index
-1] != '/') {
1545 NewPath
[Index
] = '/';
1546 NewPath
[Index
+ 1] = '\0';
1548 strcat(NewPath
, AppendPath
);
1554 IN UINT8
*SectionBuffer
,
1555 IN UINT32 BufferLength
1559 Routine Description:
1565 SectionBuffer - Buffer containing the section to parse.
1566 BufferLength - Length of SectionBuffer
1570 EFI_SECTION_ERROR - Problem with section parsing.
1571 (a) compression errors
1572 (b) unrecognized section
1573 EFI_UNSUPPORTED - Do not know how to parse the section.
1574 EFI_SUCCESS - Section successfully parsed.
1575 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1579 EFI_SECTION_TYPE Type
;
1581 UINT32 SectionLength
;
1582 UINT32 SectionHeaderLen
;
1585 UINT32 ParsedLength
;
1586 UINT8
*CompressedBuffer
;
1587 UINT32 CompressedLength
;
1588 UINT8
*UncompressedBuffer
;
1589 UINT32 UncompressedLength
;
1590 UINT8
*ToolOutputBuffer
;
1591 UINT32 ToolOutputLength
;
1592 UINT8 CompressionType
;
1595 UINT8
*ScratchBuffer
;
1596 DECOMPRESS_FUNCTION DecompressFunction
;
1597 GETINFO_FUNCTION GetInfoFunction
;
1599 CHAR8
*ExtractionTool
;
1600 CHAR8
*ToolInputFile
;
1601 CHAR8
*ToolOutputFile
;
1602 CHAR8
*SystemCommandFormatString
;
1603 CHAR8
*SystemCommand
;
1608 CHAR8
*ToolInputFileName
;
1609 CHAR8
*ToolOutputFileName
;
1612 ToolInputFileName
= NULL
;
1613 ToolOutputFileName
= NULL
;
1615 while (ParsedLength
< BufferLength
) {
1616 Ptr
= SectionBuffer
+ ParsedLength
;
1618 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1619 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1622 // This is sort of an odd check, but is necessary because FFS files are
1623 // padded to a QWORD boundary, meaning there is potentially a whole section
1624 // header worth of 0xFF bytes.
1626 if (SectionLength
== 0xffffff && Type
== 0xff) {
1632 // Get real section file size
1634 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1635 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1637 SectionName
= SectionNameToStr (Type
);
1638 if (SectionName
!= NULL
) {
1639 printf ("------------------------------------------------------------\n");
1640 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1645 case EFI_SECTION_RAW
:
1646 case EFI_SECTION_PIC
:
1647 case EFI_SECTION_TE
:
1648 // default is no more information
1651 case EFI_SECTION_PE32
:
1653 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1654 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1655 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1658 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1659 SectionLength
- SectionHeaderLen
1662 SystemCommandFormatString
= "%s sha1 -out %s %s";
1663 SystemCommand
= malloc (
1664 strlen (SystemCommandFormatString
) +
1665 strlen (OpenSslPath
) +
1666 strlen (ToolInputFileName
) +
1667 strlen (ToolOutputFileName
) +
1670 if (SystemCommand
== NULL
) {
1671 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1672 return EFI_OUT_OF_RESOURCES
;
1676 SystemCommandFormatString
,
1682 if (system (SystemCommand
) != EFI_SUCCESS
) {
1683 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1690 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1691 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1694 fseek(fp
,0,SEEK_SET
);
1695 fseek(fp
,0,SEEK_END
);
1696 nFileLen
= ftell(fp
);
1697 fseek(fp
,0,SEEK_SET
);
1698 StrLine
= malloc(nFileLen
);
1699 if (StrLine
== NULL
) {
1701 free (SystemCommand
);
1702 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1703 return EFI_OUT_OF_RESOURCES
;
1705 fgets(StrLine
, nFileLen
, fp
);
1706 NewStr
= strrchr (StrLine
, '=');
1707 printf (" SHA1: %s\n", NewStr
+ 1);
1712 remove(ToolInputFileName
);
1713 remove(ToolOutputFileName
);
1714 free (SystemCommand
);
1718 case EFI_SECTION_USER_INTERFACE
:
1719 printf (" String: %ls\n", (wchar_t *) &((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
);
1722 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1723 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1724 if (EFI_ERROR (Status
)) {
1725 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1726 return EFI_SECTION_ERROR
;
1730 case EFI_SECTION_COMPATIBILITY16
:
1731 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1733 // Section does not contain any further header information.
1737 case EFI_SECTION_PEI_DEPEX
:
1738 case EFI_SECTION_DXE_DEPEX
:
1739 case EFI_SECTION_SMM_DEPEX
:
1740 DumpDepexSection (Ptr
, SectionLength
);
1743 case EFI_SECTION_VERSION
:
1744 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1745 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1748 case EFI_SECTION_COMPRESSION
:
1749 UncompressedBuffer
= NULL
;
1750 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1751 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1752 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1753 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1755 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1756 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1757 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1759 CompressedLength
= SectionLength
- RealHdrLen
;
1760 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1762 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1763 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1764 if (CompressedLength
!= UncompressedLength
) {
1769 "file is not compressed, but the compressed length does not match the uncompressed length",
1772 return EFI_SECTION_ERROR
;
1775 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1776 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1777 GetInfoFunction
= EfiGetInfo
;
1778 DecompressFunction
= EfiDecompress
;
1779 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1781 CompressedBuffer
= Ptr
+ RealHdrLen
;
1783 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1784 if (EFI_ERROR (Status
)) {
1785 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1786 return EFI_SECTION_ERROR
;
1789 if (DstSize
!= UncompressedLength
) {
1790 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1791 return EFI_SECTION_ERROR
;
1794 ScratchBuffer
= malloc (ScratchSize
);
1795 if (ScratchBuffer
== NULL
) {
1796 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1797 return EFI_OUT_OF_RESOURCES
;
1799 UncompressedBuffer
= malloc (UncompressedLength
);
1800 if (UncompressedBuffer
== NULL
) {
1801 free (ScratchBuffer
);
1802 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1803 return EFI_OUT_OF_RESOURCES
;
1805 Status
= DecompressFunction (
1813 free (ScratchBuffer
);
1814 if (EFI_ERROR (Status
)) {
1815 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1816 free (UncompressedBuffer
);
1817 return EFI_SECTION_ERROR
;
1820 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1821 return EFI_SECTION_ERROR
;
1824 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1826 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1828 // We need to deallocate Buffer
1830 free (UncompressedBuffer
);
1833 if (EFI_ERROR (Status
)) {
1834 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1835 return EFI_SECTION_ERROR
;
1839 case EFI_SECTION_GUID_DEFINED
:
1840 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1841 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1842 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1843 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1845 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1846 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1847 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1849 printf (" SectionDefinitionGuid: ");
1850 PrintGuid (EfiGuid
);
1852 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1853 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1856 LookupGuidedSectionToolPath (
1857 mParsedGuidedSectionTools
,
1861 if (ExtractionTool
!= NULL
) {
1863 ToolInputFile
= CloneString (tmpnam (NULL
));
1864 ToolOutputFile
= CloneString (tmpnam (NULL
));
1866 char tmp1
[] = "/tmp/fileXXXXXX";
1867 char tmp2
[] = "/tmp/fileXXXXXX";
1870 fd1
= mkstemp(tmp1
);
1871 fd2
= mkstemp(tmp2
);
1872 ToolInputFile
= CloneString(tmp1
);
1873 ToolOutputFile
= CloneString(tmp2
);
1878 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1879 if (ToolInputFile
!= NULL
) {
1880 free (ToolInputFile
);
1882 if (ToolOutputFile
!= NULL
) {
1883 free (ToolOutputFile
);
1885 free (ExtractionTool
);
1887 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1888 return EFI_OUT_OF_RESOURCES
;
1892 // Construction 'system' command string
1894 SystemCommandFormatString
= "%s -d -o %s %s";
1895 SystemCommand
= malloc (
1896 strlen (SystemCommandFormatString
) +
1897 strlen (ExtractionTool
) +
1898 strlen (ToolInputFile
) +
1899 strlen (ToolOutputFile
) +
1902 if (SystemCommand
== NULL
) {
1903 free (ToolInputFile
);
1904 free (ToolOutputFile
);
1905 free (ExtractionTool
);
1907 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1908 return EFI_OUT_OF_RESOURCES
;
1912 SystemCommandFormatString
,
1917 free (ExtractionTool
);
1922 (CHAR8
*) SectionBuffer
+ DataOffset
,
1923 BufferLength
- DataOffset
1926 system (SystemCommand
);
1927 remove (ToolInputFile
);
1928 free (ToolInputFile
);
1933 (CHAR8
**)&ToolOutputBuffer
,
1936 remove (ToolOutputFile
);
1937 free (ToolOutputFile
);
1938 free (SystemCommand
);
1939 if (EFI_ERROR (Status
)) {
1940 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
1941 return EFI_SECTION_ERROR
;
1944 Status
= ParseSection (
1948 if (EFI_ERROR (Status
)) {
1949 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
1950 return EFI_SECTION_ERROR
;
1954 // Check for CRC32 sections which we can handle internally if needed.
1956 } else if (!CompareGuid (
1958 &gEfiCrc32GuidedSectionExtractionProtocolGuid
1962 // CRC32 guided section
1964 Status
= ParseSection (
1965 SectionBuffer
+ DataOffset
,
1966 BufferLength
- DataOffset
1968 if (EFI_ERROR (Status
)) {
1969 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
1970 return EFI_SECTION_ERROR
;
1974 // We don't know how to parse it now.
1976 Error (NULL
, 0, 0003, "Error parsing section", \
1977 "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).");
1978 return EFI_UNSUPPORTED
;
1984 // Unknown section, return error
1986 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
1987 return EFI_SECTION_ERROR
;
1990 ParsedLength
+= SectionLength
;
1992 // We make then next section begin on a 4-byte boundary
1994 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
1997 if (ParsedLength
< BufferLength
) {
1998 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
1999 return EFI_SECTION_ERROR
;
2008 IN UINT32 SectionLength
2012 Routine Description:
2014 GC_TODO: Add function description
2018 Ptr - GC_TODO: add argument description
2019 SectionLength - GC_TODO: add argument description
2023 EFI_SUCCESS - GC_TODO: Add description for return value
2027 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2030 // Need at least a section header + data
2032 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2036 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2037 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2038 while (SectionLength
> 0) {
2041 case EFI_DEP_BEFORE
:
2042 printf ("BEFORE\n");
2055 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2056 printf ("%s ", GuidBuffer
);
2057 PrintGuidName (GuidBuffer
);
2060 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2063 SectionLength
-= 17;
2097 printf ("END DEPEX\n");
2109 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2123 Routine Description:
2125 GC_TODO: Add function description
2129 GuidStr - GC_TODO: add argument description
2133 EFI_SUCCESS - GC_TODO: Add description for return value
2134 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2138 GUID_TO_BASENAME
*GPtr
;
2140 // If we have a list of guid-to-basenames, then go through the list to
2141 // look for a guid string match. If found, print the basename to stdout,
2142 // otherwise return a failure.
2144 GPtr
= mGuidBaseNameList
;
2145 while (GPtr
!= NULL
) {
2146 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2147 printf ("%s", GPtr
->BaseName
);
2154 return EFI_INVALID_PARAMETER
;
2158 ParseGuidBaseNameFile (
2163 Routine Description:
2165 GC_TODO: Add function description
2169 FileName - GC_TODO: add argument description
2173 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2174 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2175 EFI_SUCCESS - GC_TODO: Add description for return value
2180 CHAR8 Line
[MAX_LINE_LEN
];
2181 CHAR8
*FormatString
;
2183 GUID_TO_BASENAME
*GPtr
;
2185 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2186 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2187 return EFI_DEVICE_ERROR
;
2191 // Generate the format string for fscanf
2193 FormatLength
= snprintf (
2197 (unsigned) sizeof (GPtr
->Guid
) - 1,
2198 (unsigned) sizeof (GPtr
->BaseName
) - 1
2201 FormatString
= (CHAR8
*) malloc (FormatLength
);
2202 if (FormatString
== NULL
) {
2204 return EFI_OUT_OF_RESOURCES
;
2211 (unsigned) sizeof (GPtr
->Guid
) - 1,
2212 (unsigned) sizeof (GPtr
->BaseName
) - 1
2215 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2217 // Allocate space for another guid/basename element
2219 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2221 free (FormatString
);
2223 return EFI_OUT_OF_RESOURCES
;
2226 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2227 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2228 GPtr
->Next
= mGuidBaseNameList
;
2229 mGuidBaseNameList
= GPtr
;
2232 // Some sort of error. Just continue.
2238 free (FormatString
);
2244 FreeGuidBaseNameList (
2249 Routine Description:
2251 GC_TODO: Add function description
2259 EFI_SUCCESS - GC_TODO: Add description for return value
2263 GUID_TO_BASENAME
*Next
;
2265 while (mGuidBaseNameList
!= NULL
) {
2266 Next
= mGuidBaseNameList
->Next
;
2267 free (mGuidBaseNameList
);
2268 mGuidBaseNameList
= Next
;
2277 LoadGuidedSectionToolsTxt (
2278 IN CHAR8
* FirmwareVolumeFilename
2281 CHAR8
* PeerFilename
;
2288 Places
[0] = FirmwareVolumeFilename
;
2289 //Places[1] = mUtilityFilename;
2291 mParsedGuidedSectionTools
= NULL
;
2293 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2294 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2295 //printf("Loading %s...\n", PeerFilename);
2296 if (OsPathExists (PeerFilename
)) {
2297 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2299 free (PeerFilename
);
2300 if (mParsedGuidedSectionTools
!= NULL
) {
2313 Routine Description:
2315 GC_TODO: Add function description
2323 GC_TODO: add return values
2330 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2333 // Copyright declaration
2335 fprintf (stdout
, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
2336 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2341 fprintf (stdout
, "optional arguments:\n");
2342 fprintf (stdout
, " -h, --help\n\
2343 Show this help message and exit\n");
2344 fprintf (stdout
, " --version\n\
2345 Show program's version number and exit\n");
2346 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2347 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2348 fprintf (stdout
, " -v, --verbose\n\
2349 Print informational statements\n");
2350 fprintf (stdout
, " -q, --quiet\n\
2351 Returns the exit code, error messages will be displayed\n");
2352 fprintf (stdout
, " -s, --silent\n\
2353 Returns only the exit code; informational and error\n\
2354 messages are not displayed\n");
2355 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2356 Parse the basename to file-guid cross reference file(s)\n");
2357 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2358 The offset from the start of the input file to start \n\
2359 processing an FV\n");
2360 fprintf (stdout
, " --hash\n\
2361 Generate HASH value of the entire PE image\n");
2362 fprintf (stdout
, " --sfo\n\
2363 Reserved for future use\n");