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
*SystemCommand
;
1607 CHAR8
*ToolInputFileName
;
1608 CHAR8
*ToolOutputFileName
;
1611 ToolInputFileName
= NULL
;
1612 ToolOutputFileName
= NULL
;
1614 while (ParsedLength
< BufferLength
) {
1615 Ptr
= SectionBuffer
+ ParsedLength
;
1617 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1618 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1621 // This is sort of an odd check, but is necessary because FFS files are
1622 // padded to a QWORD boundary, meaning there is potentially a whole section
1623 // header worth of 0xFF bytes.
1625 if (SectionLength
== 0xffffff && Type
== 0xff) {
1631 // Get real section file size
1633 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1634 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1636 SectionName
= SectionNameToStr (Type
);
1637 if (SectionName
!= NULL
) {
1638 printf ("------------------------------------------------------------\n");
1639 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1644 case EFI_SECTION_RAW
:
1645 case EFI_SECTION_PIC
:
1646 case EFI_SECTION_TE
:
1647 // default is no more information
1650 case EFI_SECTION_PE32
:
1652 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1653 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1654 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1657 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1658 SectionLength
- SectionHeaderLen
1661 SystemCommand
= malloc (
1662 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1663 strlen (OpenSslPath
) +
1664 strlen (ToolInputFileName
) +
1665 strlen (ToolOutputFileName
) +
1668 if (SystemCommand
== NULL
) {
1669 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1670 return EFI_OUT_OF_RESOURCES
;
1674 OPENSSL_COMMAND_FORMAT_STRING
,
1680 if (system (SystemCommand
) != EFI_SUCCESS
) {
1681 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1688 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1689 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1692 fseek(fp
,0,SEEK_SET
);
1693 fseek(fp
,0,SEEK_END
);
1694 nFileLen
= ftell(fp
);
1695 fseek(fp
,0,SEEK_SET
);
1696 StrLine
= malloc(nFileLen
);
1697 if (StrLine
== NULL
) {
1699 free (SystemCommand
);
1700 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1701 return EFI_OUT_OF_RESOURCES
;
1703 fgets(StrLine
, nFileLen
, fp
);
1704 NewStr
= strrchr (StrLine
, '=');
1705 printf (" SHA1: %s\n", NewStr
+ 1);
1710 remove(ToolInputFileName
);
1711 remove(ToolOutputFileName
);
1712 free (SystemCommand
);
1716 case EFI_SECTION_USER_INTERFACE
:
1717 printf (" String: %ls\n", (wchar_t *) &((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
);
1720 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1721 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1722 if (EFI_ERROR (Status
)) {
1723 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1724 return EFI_SECTION_ERROR
;
1728 case EFI_SECTION_COMPATIBILITY16
:
1729 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1731 // Section does not contain any further header information.
1735 case EFI_SECTION_PEI_DEPEX
:
1736 case EFI_SECTION_DXE_DEPEX
:
1737 case EFI_SECTION_SMM_DEPEX
:
1738 DumpDepexSection (Ptr
, SectionLength
);
1741 case EFI_SECTION_VERSION
:
1742 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1743 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1746 case EFI_SECTION_COMPRESSION
:
1747 UncompressedBuffer
= NULL
;
1748 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1749 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1750 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1751 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1753 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1754 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1755 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1757 CompressedLength
= SectionLength
- RealHdrLen
;
1758 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1760 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1761 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1762 if (CompressedLength
!= UncompressedLength
) {
1767 "file is not compressed, but the compressed length does not match the uncompressed length",
1770 return EFI_SECTION_ERROR
;
1773 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1774 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1775 GetInfoFunction
= EfiGetInfo
;
1776 DecompressFunction
= EfiDecompress
;
1777 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1779 CompressedBuffer
= Ptr
+ RealHdrLen
;
1781 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1782 if (EFI_ERROR (Status
)) {
1783 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1784 return EFI_SECTION_ERROR
;
1787 if (DstSize
!= UncompressedLength
) {
1788 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1789 return EFI_SECTION_ERROR
;
1792 ScratchBuffer
= malloc (ScratchSize
);
1793 if (ScratchBuffer
== NULL
) {
1794 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1795 return EFI_OUT_OF_RESOURCES
;
1797 UncompressedBuffer
= malloc (UncompressedLength
);
1798 if (UncompressedBuffer
== NULL
) {
1799 free (ScratchBuffer
);
1800 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1801 return EFI_OUT_OF_RESOURCES
;
1803 Status
= DecompressFunction (
1811 free (ScratchBuffer
);
1812 if (EFI_ERROR (Status
)) {
1813 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1814 free (UncompressedBuffer
);
1815 return EFI_SECTION_ERROR
;
1818 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1819 return EFI_SECTION_ERROR
;
1822 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1824 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1826 // We need to deallocate Buffer
1828 free (UncompressedBuffer
);
1831 if (EFI_ERROR (Status
)) {
1832 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1833 return EFI_SECTION_ERROR
;
1837 case EFI_SECTION_GUID_DEFINED
:
1838 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1839 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1840 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1841 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1843 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1844 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1845 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1847 printf (" SectionDefinitionGuid: ");
1848 PrintGuid (EfiGuid
);
1850 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1851 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1854 LookupGuidedSectionToolPath (
1855 mParsedGuidedSectionTools
,
1859 if (ExtractionTool
!= NULL
) {
1861 ToolInputFile
= CloneString (tmpnam (NULL
));
1862 ToolOutputFile
= CloneString (tmpnam (NULL
));
1864 char tmp1
[] = "/tmp/fileXXXXXX";
1865 char tmp2
[] = "/tmp/fileXXXXXX";
1868 fd1
= mkstemp(tmp1
);
1869 fd2
= mkstemp(tmp2
);
1870 ToolInputFile
= CloneString(tmp1
);
1871 ToolOutputFile
= CloneString(tmp2
);
1876 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1877 if (ToolInputFile
!= NULL
) {
1878 free (ToolInputFile
);
1880 if (ToolOutputFile
!= NULL
) {
1881 free (ToolOutputFile
);
1883 free (ExtractionTool
);
1885 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1886 return EFI_OUT_OF_RESOURCES
;
1890 // Construction 'system' command string
1892 SystemCommand
= malloc (
1893 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1894 strlen (ExtractionTool
) +
1895 strlen (ToolInputFile
) +
1896 strlen (ToolOutputFile
) +
1899 if (SystemCommand
== NULL
) {
1900 free (ToolInputFile
);
1901 free (ToolOutputFile
);
1902 free (ExtractionTool
);
1904 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1905 return EFI_OUT_OF_RESOURCES
;
1909 EXTRACT_COMMAND_FORMAT_STRING
,
1914 free (ExtractionTool
);
1919 (CHAR8
*) SectionBuffer
+ DataOffset
,
1920 BufferLength
- DataOffset
1923 system (SystemCommand
);
1924 remove (ToolInputFile
);
1925 free (ToolInputFile
);
1930 (CHAR8
**)&ToolOutputBuffer
,
1933 remove (ToolOutputFile
);
1934 free (ToolOutputFile
);
1935 free (SystemCommand
);
1936 if (EFI_ERROR (Status
)) {
1937 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
1938 return EFI_SECTION_ERROR
;
1941 Status
= ParseSection (
1945 if (EFI_ERROR (Status
)) {
1946 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
1947 return EFI_SECTION_ERROR
;
1951 // Check for CRC32 sections which we can handle internally if needed.
1953 } else if (!CompareGuid (
1955 &gEfiCrc32GuidedSectionExtractionProtocolGuid
1959 // CRC32 guided section
1961 Status
= ParseSection (
1962 SectionBuffer
+ DataOffset
,
1963 BufferLength
- DataOffset
1965 if (EFI_ERROR (Status
)) {
1966 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
1967 return EFI_SECTION_ERROR
;
1971 // We don't know how to parse it now.
1973 Error (NULL
, 0, 0003, "Error parsing section", \
1974 "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).");
1975 return EFI_UNSUPPORTED
;
1981 // Unknown section, return error
1983 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
1984 return EFI_SECTION_ERROR
;
1987 ParsedLength
+= SectionLength
;
1989 // We make then next section begin on a 4-byte boundary
1991 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
1994 if (ParsedLength
< BufferLength
) {
1995 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
1996 return EFI_SECTION_ERROR
;
2005 IN UINT32 SectionLength
2009 Routine Description:
2011 GC_TODO: Add function description
2015 Ptr - GC_TODO: add argument description
2016 SectionLength - GC_TODO: add argument description
2020 EFI_SUCCESS - GC_TODO: Add description for return value
2024 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2027 // Need at least a section header + data
2029 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2033 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2034 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2035 while (SectionLength
> 0) {
2038 case EFI_DEP_BEFORE
:
2039 printf ("BEFORE\n");
2052 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2053 printf ("%s ", GuidBuffer
);
2054 PrintGuidName (GuidBuffer
);
2057 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2060 SectionLength
-= 17;
2094 printf ("END DEPEX\n");
2106 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2120 Routine Description:
2122 GC_TODO: Add function description
2126 GuidStr - GC_TODO: add argument description
2130 EFI_SUCCESS - GC_TODO: Add description for return value
2131 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2135 GUID_TO_BASENAME
*GPtr
;
2137 // If we have a list of guid-to-basenames, then go through the list to
2138 // look for a guid string match. If found, print the basename to stdout,
2139 // otherwise return a failure.
2141 GPtr
= mGuidBaseNameList
;
2142 while (GPtr
!= NULL
) {
2143 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2144 printf ("%s", GPtr
->BaseName
);
2151 return EFI_INVALID_PARAMETER
;
2155 ParseGuidBaseNameFile (
2160 Routine Description:
2162 GC_TODO: Add function description
2166 FileName - GC_TODO: add argument description
2170 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2171 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2172 EFI_SUCCESS - GC_TODO: Add description for return value
2177 CHAR8 Line
[MAX_LINE_LEN
];
2178 CHAR8
*FormatString
;
2180 GUID_TO_BASENAME
*GPtr
;
2182 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2183 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2184 return EFI_DEVICE_ERROR
;
2188 // Generate the format string for fscanf
2190 FormatLength
= snprintf (
2194 (unsigned) sizeof (GPtr
->Guid
) - 1,
2195 (unsigned) sizeof (GPtr
->BaseName
) - 1
2198 FormatString
= (CHAR8
*) malloc (FormatLength
);
2199 if (FormatString
== NULL
) {
2201 return EFI_OUT_OF_RESOURCES
;
2208 (unsigned) sizeof (GPtr
->Guid
) - 1,
2209 (unsigned) sizeof (GPtr
->BaseName
) - 1
2212 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2214 // Allocate space for another guid/basename element
2216 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2218 free (FormatString
);
2220 return EFI_OUT_OF_RESOURCES
;
2223 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2224 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2225 GPtr
->Next
= mGuidBaseNameList
;
2226 mGuidBaseNameList
= GPtr
;
2229 // Some sort of error. Just continue.
2235 free (FormatString
);
2241 FreeGuidBaseNameList (
2246 Routine Description:
2248 GC_TODO: Add function description
2256 EFI_SUCCESS - GC_TODO: Add description for return value
2260 GUID_TO_BASENAME
*Next
;
2262 while (mGuidBaseNameList
!= NULL
) {
2263 Next
= mGuidBaseNameList
->Next
;
2264 free (mGuidBaseNameList
);
2265 mGuidBaseNameList
= Next
;
2274 LoadGuidedSectionToolsTxt (
2275 IN CHAR8
* FirmwareVolumeFilename
2278 CHAR8
* PeerFilename
;
2285 Places
[0] = FirmwareVolumeFilename
;
2286 //Places[1] = mUtilityFilename;
2288 mParsedGuidedSectionTools
= NULL
;
2290 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2291 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2292 //printf("Loading %s...\n", PeerFilename);
2293 if (OsPathExists (PeerFilename
)) {
2294 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2296 free (PeerFilename
);
2297 if (mParsedGuidedSectionTools
!= NULL
) {
2310 Routine Description:
2312 GC_TODO: Add function description
2320 GC_TODO: add return values
2327 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2330 // Copyright declaration
2332 fprintf (stdout
, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
2333 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2338 fprintf (stdout
, "optional arguments:\n");
2339 fprintf (stdout
, " -h, --help\n\
2340 Show this help message and exit\n");
2341 fprintf (stdout
, " --version\n\
2342 Show program's version number and exit\n");
2343 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2344 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2345 fprintf (stdout
, " -v, --verbose\n\
2346 Print informational statements\n");
2347 fprintf (stdout
, " -q, --quiet\n\
2348 Returns the exit code, error messages will be displayed\n");
2349 fprintf (stdout
, " -s, --silent\n\
2350 Returns only the exit code; informational and error\n\
2351 messages are not displayed\n");
2352 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2353 Parse the basename to file-guid cross reference file(s)\n");
2354 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2355 The offset from the start of the input file to start \n\
2356 processing an FV\n");
2357 fprintf (stdout
, " --hash\n\
2358 Generate HASH value of the entire PE image\n");
2359 fprintf (stdout
, " --sfo\n\
2360 Reserved for future use\n");