2 The tool dumps the contents of a firmware volume
4 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2022, Konstantin Aladyshev <aladyshev22@gmail.com><BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
22 #include <Common/UefiBaseTypes.h>
23 #include <Common/UefiCapsule.h>
24 #include <Common/PiFirmwareFile.h>
25 #include <Common/PiFirmwareVolume.h>
26 #include <Guid/PiFirmwareFileSystem.h>
27 #include <IndustryStandard/PeImage.h>
28 #include <Protocol/GuidedSectionExtraction.h>
31 #include "Decompress.h"
33 #include "CommonLib.h"
34 #include "EfiUtilityMsgs.h"
35 #include "FirmwareVolumeBufferLib.h"
37 #include "ParseGuidedSectionTools.h"
38 #include "StringFuncs.h"
40 #include "PeCoffLib.h"
43 // Utility global variables
46 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
47 EFI_GUID gPeiAprioriFileNameGuid
= { 0x1b45cc0a, 0x156a, 0x428a, { 0XAF, 0x62, 0x49, 0x86, 0x4d, 0xa0, 0xe6, 0xe6 }};
48 EFI_GUID gAprioriGuid
= { 0xFC510EE7, 0xFFDC, 0x11D4, { 0xBD, 0x41, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
50 #define UTILITY_MAJOR_VERSION 1
51 #define UTILITY_MINOR_VERSION 0
53 #define UTILITY_NAME "VolInfo"
55 #define EFI_SECTION_ERROR EFIERR (100)
58 // Structure to keep a list of guid-to-basenames
60 typedef struct _GUID_TO_BASENAME
{
61 struct _GUID_TO_BASENAME
*Next
;
62 INT8 Guid
[PRINTED_GUID_BUFFER_SIZE
];
63 INT8 BaseName
[MAX_LINE_LEN
];
66 static GUID_TO_BASENAME
*mGuidBaseNameList
= NULL
;
69 // Store GUIDed Section guid->tool mapping
71 EFI_HANDLE mParsedGuidedSectionTools
= NULL
;
73 CHAR8
* mUtilityFilename
= NULL
;
75 BOOLEAN EnableHash
= FALSE
;
76 CHAR8
*OpenSslPath
= NULL
;
79 ParseGuidBaseNameFile (
84 FreeGuidBaseNameList (
95 IN UINT8
*SectionBuffer
,
96 IN UINT32 BufferLength
102 IN UINT32 SectionLength
110 OUT BOOLEAN
*ErasePolarity
116 EFI_FFS_FILE_HEADER
*FileHeader
122 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
123 EFI_FFS_FILE_HEADER
*FileHeader
,
124 BOOLEAN ErasePolarity
136 LoadGuidedSectionToolsTxt (
137 IN CHAR8
* FirmwareVolumeFilename
142 IN CHAR8
* DefaultPath
,
143 IN CHAR8
* AppendPath
,
160 Returns the length of a null-terminated unicode string.
164 String - The pointer to a null-terminated unicode string.
174 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++) {
181 Unicode2AsciiString (
183 OUT CHAR8
*Destination
189 Convert a null-terminated unicode string to a null-terminated ascii string.
193 Source - The pointer to the null-terminated input unicode string.
194 Destination - The pointer to the null-terminated output ascii string.
202 while (*Source
!= '\0') {
203 *(Destination
++) = (CHAR8
) *(Source
++);
206 // End the ascii with a NULL.
220 GC_TODO: Add function description
224 argc - GC_TODO: add argument description
225 ] - GC_TODO: add argument description
229 GC_TODO: add return values
235 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
239 BOOLEAN ErasePolarity
;
242 CHAR8
*OpenSslCommand
;
244 SetUtilityName (UTILITY_NAME
);
246 // Print utility header
248 printf ("%s Version %d.%d Build %s\n",
250 UTILITY_MAJOR_VERSION
,
251 UTILITY_MINOR_VERSION
,
266 // Look for help options
268 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
269 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
271 return STATUS_SUCCESS
;
274 // Version has already be printed, so just return success
276 if (strcmp(argv
[0], "--version") == 0) {
277 return STATUS_SUCCESS
;
281 // If they specified -x xref guid/basename cross-reference files, process it.
282 // This will print the basename beside each file guid. To use it, specify
283 // -x xref_filename to processdsc, then use xref_filename as a parameter
287 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
288 ParseGuidBaseNameFile (argv
[1]);
289 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
294 if (strcmp(argv
[0], "--offset") == 0) {
298 if ((argv
[1][0] == '0') && (tolower ((int)argv
[1][1]) == 'x')) {
299 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
300 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
301 return GetUtilityStatus ();
304 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
305 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
306 return GetUtilityStatus ();
309 // See if they said something like "64K"
311 if (tolower ((int)argv
[1][strlen (argv
[1]) - 1]) == 'k') {
320 if ((stricmp (argv
[0], "--hash") == 0)) {
321 if (EnableHash
== TRUE
) {
323 // --hash already given in the option, ignore this one
330 OpenSslCommand
= "openssl";
331 OpenSslEnv
= getenv("OPENSSL_PATH");
332 if (OpenSslEnv
== NULL
) {
333 OpenSslPath
= OpenSslCommand
;
336 // We add quotes to the Openssl Path in case it has space characters
338 OpenSslPath
= malloc(2+strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
339 if (OpenSslPath
== NULL
) {
340 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
341 return GetUtilityStatus ();
343 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
345 if (OpenSslPath
== NULL
){
346 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
347 return GetUtilityStatus ();
354 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
355 SetPrintLevel (VERBOSE_LOG_LEVEL
);
361 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
362 SetPrintLevel (KEY_LOG_LEVEL
);
368 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
369 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
370 if (EFI_ERROR (Status
)) {
371 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
375 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
378 SetPrintLevel (LogLevel
);
379 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
385 mUtilityFilename
= argv
[0];
391 // Open the file containing the FV
393 if (mUtilityFilename
== NULL
) {
394 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
395 return GetUtilityStatus ();
397 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
398 if (InputFile
== NULL
) {
399 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
400 return GetUtilityStatus ();
403 // Skip over pad bytes if specified. This is used if they prepend 0xff
404 // data to the FV image binary.
407 fseek (InputFile
, Offset
, SEEK_SET
);
410 // Determine size of FV
412 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
413 if (EFI_ERROR (Status
)) {
414 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
416 return GetUtilityStatus ();
419 // Allocate a buffer for the FV image
421 FvImage
= malloc (FvSize
);
422 if (FvImage
== NULL
) {
423 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
425 return GetUtilityStatus ();
428 // Seek to the start of the image, then read the entire FV to the buffer
430 fseek (InputFile
, Offset
, SEEK_SET
);
431 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
433 if ((unsigned int) BytesRead
!= FvSize
) {
434 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
436 return GetUtilityStatus ();
439 LoadGuidedSectionToolsTxt (mUtilityFilename
);
441 PrintFvInfo (FvImage
, FALSE
);
447 FreeGuidBaseNameList ();
448 return GetUtilityStatus ();
462 GC_TODO: Add function description
466 Fv - Firmware Volume to print information about
467 IsChildFv - Flag specifies whether the input FV is a child FV.
477 BOOLEAN ErasePolarity
;
479 EFI_FFS_FILE_HEADER
*CurrentFile
;
482 Status
= FvBufGetSize (Fv
, &FvSize
);
486 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
490 // Get the first file
493 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
494 if (EFI_ERROR (Status
)) {
495 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
496 return GetUtilityStatus ();
499 // Display information about files found
501 while (CurrentFile
!= NULL
) {
503 // Increment the number of files counter
508 // Display info about this file
510 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
511 if (EFI_ERROR (Status
)) {
512 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
513 return GetUtilityStatus ();
518 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
519 if (Status
== EFI_NOT_FOUND
) {
521 } else if (EFI_ERROR (Status
)) {
522 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
523 return GetUtilityStatus ();
528 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
530 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
538 IN UINT32 ActualSize
,
545 This function returns the next larger size that meets the alignment
546 requirement specified.
551 Alignment The desired alignment.
555 EFI_SUCCESS Function completed successfully.
556 EFI_ABORTED The function encountered an error.
562 OccupiedSize
= ActualSize
;
563 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
573 IN EFI_SECTION_TYPE Type
579 Converts EFI Section names to Strings
583 Type - The EFI Section type
587 CHAR8* - Pointer to the String containing the section name.
592 CHAR8
*SectionTypeStringTable
[] = {
600 "EFI_SECTION_COMPRESSION",
604 "EFI_SECTION_GUID_DEFINED",
608 "Unknown section type - Reserved 0x03",
612 "Unknown section type - Reserved 0x04",
616 "Unknown section type - Reserved 0x05",
620 "Unknown section type - Reserved 0x06",
624 "Unknown section type - Reserved 0x07",
628 "Unknown section type - Reserved 0x08",
632 "Unknown section type - Reserved 0x09",
636 "Unknown section type - Reserved 0x0A",
640 "Unknown section type - Reserved 0x0B",
644 "Unknown section type - Reserved 0x0C",
648 "Unknown section type - Reserved 0x0D",
652 "Unknown section type - Reserved 0x0E",
656 "Unknown section type - Reserved 0x0E",
672 "EFI_SECTION_DXE_DEPEX",
676 "EFI_SECTION_VERSION",
680 "EFI_SECTION_USER_INTERFACE",
684 "EFI_SECTION_COMPATIBILITY16",
688 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",
692 "EFI_SECTION_FREEFORM_SUBTYPE_GUID",
700 "Unknown section type - 0x1A",
704 "EFI_SECTION_PEI_DEPEX",
708 "EFI_SECTION_MM_DEPEX",
712 "Unknown section type - Reserved - beyond last defined section"
715 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
716 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
719 SectionStr
= malloc (100);
720 if (SectionStr
== NULL
) {
721 printf ("Error: Out of memory resources.\n");
724 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
733 OUT BOOLEAN
*ErasePolarity
739 This function determines the size of the FV and the erase polarity. The
740 erase polarity is the FALSE value for file state.
744 InputFile The file that contains the FV image.
745 FvSize The size of the FV.
746 ErasePolarity The FV erase polarity.
750 EFI_SUCCESS Function completed successfully.
751 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
752 EFI_ABORTED The function encountered an error.
756 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
757 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
766 // Check input parameters
768 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
769 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
770 return EFI_INVALID_PARAMETER
;
775 ReadSize
= fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
779 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
780 Signature
[0] = VolumeHeader
.Signature
;
784 // Print FV header information
786 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
787 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
789 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
790 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
793 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
794 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
797 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
798 printf (" EFI_FVB2_READ_STATUS\n");
801 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
802 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
805 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
806 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
809 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
810 printf (" EFI_FVB2_WRITE_STATUS\n");
813 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
814 printf (" EFI_FVB2_LOCK_CAP\n");
817 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
818 printf (" EFI_FVB2_LOCK_STATUS\n");
821 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
822 printf (" EFI_FVB2_STICKY_WRITE\n");
825 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
826 printf (" EFI_FVB2_MEMORY_MAPPED\n");
829 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
830 printf (" EFI_FVB2_ERASE_POLARITY\n");
831 *ErasePolarity
= TRUE
;
834 #if (PI_SPECIFICATION_VERSION < 0x00010000)
835 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
836 printf (" EFI_FVB2_ALIGNMENT\n");
839 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
840 printf (" EFI_FVB2_ALIGNMENT_2\n");
843 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
844 printf (" EFI_FVB2_ALIGNMENT_4\n");
847 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
848 printf (" EFI_FVB2_ALIGNMENT_8\n");
851 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
852 printf (" EFI_FVB2_ALIGNMENT_16\n");
855 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
856 printf (" EFI_FVB2_ALIGNMENT_32\n");
859 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
860 printf (" EFI_FVB2_ALIGNMENT_64\n");
863 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
864 printf (" EFI_FVB2_ALIGNMENT_128\n");
867 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
868 printf (" EFI_FVB2_ALIGNMENT_256\n");
871 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
872 printf (" EFI_FVB2_ALIGNMENT_512\n");
875 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
876 printf (" EFI_FVB2_ALIGNMENT_1K\n");
879 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
880 printf (" EFI_FVB2_ALIGNMENT_2K\n");
883 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
884 printf (" EFI_FVB2_ALIGNMENT_4K\n");
887 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
888 printf (" EFI_FVB2_ALIGNMENT_8K\n");
891 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
892 printf (" EFI_FVB2_ALIGNMENT_16K\n");
895 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
896 printf (" EFI_FVB2_ALIGNMENT_32K\n");
899 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
900 printf (" EFI_FVB2_ALIGNMENT_64K\n");
905 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
906 printf (" EFI_FVB2_READ_LOCK_CAP\n");
909 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
910 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
913 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
914 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
917 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
918 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
921 switch (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
922 case EFI_FVB2_ALIGNMENT_1
:
923 printf (" EFI_FVB2_ALIGNMENT_1\n");
926 case EFI_FVB2_ALIGNMENT_2
:
927 printf (" EFI_FVB2_ALIGNMENT_2\n");
930 case EFI_FVB2_ALIGNMENT_4
:
931 printf (" EFI_FVB2_ALIGNMENT_4\n");
934 case EFI_FVB2_ALIGNMENT_8
:
935 printf (" EFI_FVB2_ALIGNMENT_8\n");
938 case EFI_FVB2_ALIGNMENT_16
:
939 printf (" EFI_FVB2_ALIGNMENT_16\n");
942 case EFI_FVB2_ALIGNMENT_32
:
943 printf (" EFI_FVB2_ALIGNMENT_32\n");
946 case EFI_FVB2_ALIGNMENT_64
:
947 printf (" EFI_FVB2_ALIGNMENT_64\n");
950 case EFI_FVB2_ALIGNMENT_128
:
951 printf (" EFI_FVB2_ALIGNMENT_128\n");
954 case EFI_FVB2_ALIGNMENT_256
:
955 printf (" EFI_FVB2_ALIGNMENT_256\n");
958 case EFI_FVB2_ALIGNMENT_512
:
959 printf (" EFI_FVB2_ALIGNMENT_512\n");
962 case EFI_FVB2_ALIGNMENT_1K
:
963 printf (" EFI_FVB2_ALIGNMENT_1K\n");
966 case EFI_FVB2_ALIGNMENT_2K
:
967 printf (" EFI_FVB2_ALIGNMENT_2K\n");
970 case EFI_FVB2_ALIGNMENT_4K
:
971 printf (" EFI_FVB2_ALIGNMENT_4K\n");
974 case EFI_FVB2_ALIGNMENT_8K
:
975 printf (" EFI_FVB2_ALIGNMENT_8K\n");
978 case EFI_FVB2_ALIGNMENT_16K
:
979 printf (" EFI_FVB2_ALIGNMENT_16K\n");
982 case EFI_FVB2_ALIGNMENT_32K
:
983 printf (" EFI_FVB2_ALIGNMENT_32K\n");
986 case EFI_FVB2_ALIGNMENT_64K
:
987 printf (" EFI_FVB2_ALIGNMENT_64K\n");
990 case EFI_FVB2_ALIGNMENT_128K
:
991 printf (" EFI_FVB2_ALIGNMENT_128K\n");
994 case EFI_FVB2_ALIGNMENT_256K
:
995 printf (" EFI_FVB2_ALIGNMENT_256K\n");
998 case EFI_FVB2_ALIGNMENT_512K
:
999 printf (" EFI_FVB2_ALIGNMENT_512K\n");
1002 case EFI_FVB2_ALIGNMENT_1M
:
1003 printf (" EFI_FVB2_ALIGNMENT_1M\n");
1006 case EFI_FVB2_ALIGNMENT_2M
:
1007 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1010 case EFI_FVB2_ALIGNMENT_4M
:
1011 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1014 case EFI_FVB2_ALIGNMENT_8M
:
1015 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1018 case EFI_FVB2_ALIGNMENT_16M
:
1019 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1022 case EFI_FVB2_ALIGNMENT_32M
:
1023 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1026 case EFI_FVB2_ALIGNMENT_64M
:
1027 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1030 case EFI_FVB2_ALIGNMENT_128M
:
1031 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1034 case EFI_FVB2_ALIGNMENT_256M
:
1035 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1038 case EFI_FVB2_ALIGNMENT_512M
:
1039 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1042 case EFI_FVB2_ALIGNMENT_1G
:
1043 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1046 case EFI_FVB2_ALIGNMENT_2G
:
1047 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1052 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1053 printf ("File System ID: ");
1054 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1058 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1061 ReadSize
= fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1062 if (ReadSize
!= 1) {
1065 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1067 if (BlockMap
.NumBlocks
!= 0) {
1068 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1069 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1070 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1073 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1075 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1076 printf ("ERROR: Header length not consistent with Block Maps!\n");
1080 if (VolumeHeader
.FvLength
!= Size
) {
1081 printf ("ERROR: Volume Size not consistent with Block Maps!\n");
1085 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1090 // rewind (InputFile);
1098 EFI_FFS_FILE_HEADER
*FileHeader
1102 Routine Description:
1104 Print GUIDs from the APRIORI file
1108 FileHeader - The file header
1112 EFI_SUCCESS - The APRIORI file was parsed correctly
1113 EFI_SECTION_ERROR - Problem with file parsing
1117 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1120 HeaderSize
= FvBufGetFfsHeaderSize (FileHeader
);
1122 if (FileHeader
->Type
!= EFI_FV_FILETYPE_FREEFORM
)
1123 return EFI_SECTION_ERROR
;
1125 EFI_COMMON_SECTION_HEADER
* SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) FileHeader
+ HeaderSize
);
1126 if (SectionHeader
->Type
!= EFI_SECTION_RAW
)
1127 return EFI_SECTION_ERROR
;
1129 UINT32 SectionLength
= GetSectionFileLength (SectionHeader
);
1130 EFI_GUID
* FileName
= (EFI_GUID
*) ((UINT8
*) SectionHeader
+ sizeof (EFI_COMMON_SECTION_HEADER
));
1131 while (((UINT8
*) FileName
) < ((UINT8
*) SectionHeader
+ SectionLength
)) {
1132 PrintGuidToBuffer (FileName
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1133 printf ("%s ", GuidBuffer
);
1134 PrintGuidName (GuidBuffer
);
1145 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1146 EFI_FFS_FILE_HEADER
*FileHeader
,
1147 BOOLEAN ErasePolarity
1151 Routine Description:
1153 GC_TODO: Add function description
1157 FvImage - GC_TODO: add argument description
1158 FileHeader - GC_TODO: add argument description
1159 ErasePolarity - GC_TODO: add argument description
1163 EFI_SUCCESS - GC_TODO: Add description for return value
1164 EFI_ABORTED - GC_TODO: Add description for return value
1171 EFI_FFS_FILE_HEADER2 BlankHeader
;
1173 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1175 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1179 // Check if we have free space
1181 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1182 if (ErasePolarity
) {
1183 memset (&BlankHeader
, -1, HeaderSize
);
1185 memset (&BlankHeader
, 0, HeaderSize
);
1188 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1192 // Print file information.
1194 printf ("============================================================\n");
1196 printf ("File Name: ");
1197 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1198 printf ("%s ", GuidBuffer
);
1199 PrintGuidName (GuidBuffer
);
1203 // PrintGuid (&FileHeader->Name);
1206 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1207 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1208 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1209 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1210 printf ("File State: 0x%02X\n", FileHeader
->State
);
1215 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1217 switch (FileState
) {
1219 case EFI_FILE_HEADER_CONSTRUCTION
:
1220 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1223 case EFI_FILE_HEADER_INVALID
:
1224 printf (" EFI_FILE_HEADER_INVALID\n");
1227 case EFI_FILE_HEADER_VALID
:
1228 printf (" EFI_FILE_HEADER_VALID\n");
1229 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1230 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1231 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1232 if (Checksum
!= 0) {
1233 printf ("ERROR: Header checksum invalid.\n");
1239 case EFI_FILE_DELETED
:
1240 printf (" EFI_FILE_DELETED\n");
1242 case EFI_FILE_MARKED_FOR_UPDATE
:
1243 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1245 case EFI_FILE_DATA_VALID
:
1246 printf (" EFI_FILE_DATA_VALID\n");
1249 // Calculate header checksum
1251 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1252 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1253 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1254 if (Checksum
!= 0) {
1255 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1259 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1261 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1263 // Calculate file checksum
1265 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1266 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1267 if (Checksum
!= 0) {
1268 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1272 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1273 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
);
1277 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1279 // Verify tail if present
1281 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1283 // Verify tail is complement of integrity check field in the header.
1285 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1286 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1287 Error (NULL
, 0, 0003, "error parsing FFS file", \
1288 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1296 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1300 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1302 switch (FileHeader
->Type
) {
1304 case EFI_FV_FILETYPE_RAW
:
1305 printf ("EFI_FV_FILETYPE_RAW\n");
1308 case EFI_FV_FILETYPE_FREEFORM
:
1309 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1312 case EFI_FV_FILETYPE_SECURITY_CORE
:
1313 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1316 case EFI_FV_FILETYPE_PEI_CORE
:
1317 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1320 case EFI_FV_FILETYPE_DXE_CORE
:
1321 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1324 case EFI_FV_FILETYPE_PEIM
:
1325 printf ("EFI_FV_FILETYPE_PEIM\n");
1328 case EFI_FV_FILETYPE_DRIVER
:
1329 printf ("EFI_FV_FILETYPE_DRIVER\n");
1332 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1333 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1336 case EFI_FV_FILETYPE_APPLICATION
:
1337 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1340 case EFI_FV_FILETYPE_SMM
:
1341 printf ("EFI_FV_FILETYPE_MM\n");
1344 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1345 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1348 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1349 printf ("EFI_FV_FILETYPE_COMBINED_MM_DXE\n");
1352 case EFI_FV_FILETYPE_SMM_CORE
:
1353 printf ("EFI_FV_FILETYPE_MM_CORE\n");
1356 case EFI_FV_FILETYPE_MM_STANDALONE
:
1357 printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
1360 case EFI_FV_FILETYPE_MM_CORE_STANDALONE
:
1361 printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
1364 case EFI_FV_FILETYPE_FFS_PAD
:
1365 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1369 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1374 switch (FileHeader
->Type
) {
1376 case EFI_FV_FILETYPE_ALL
:
1377 case EFI_FV_FILETYPE_RAW
:
1378 case EFI_FV_FILETYPE_FFS_PAD
:
1383 // All other files have sections
1385 Status
= ParseSection (
1386 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1387 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1389 if (EFI_ERROR (Status
)) {
1391 // printf ("ERROR: Parsing the FFS file.\n");
1400 &gPeiAprioriFileNameGuid
1404 printf("PEI APRIORI FILE:\n");
1405 return PrintAprioriFile (FileHeader
);
1413 printf("DXE APRIORI FILE:\n");
1414 return PrintAprioriFile (FileHeader
);
1422 IN VOID
*FileHandle
,
1423 IN UINTN FileOffset
,
1424 IN OUT UINT32
*ReadSize
,
1429 Routine Description:
1431 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1435 FileHandle - The handle to the PE/COFF file
1437 FileOffset - The offset, in bytes, into the file to read
1439 ReadSize - The number of bytes to read from the file starting at FileOffset
1441 Buffer - A pointer to the buffer to read the data into.
1445 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1449 CHAR8
*Destination8
;
1453 Destination8
= Buffer
;
1454 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1457 *(Destination8
++) = *(Source8
++);
1464 SetAddressToSectionHeader (
1466 IN OUT UINT8
*FileBuffer
,
1467 IN UINT64 NewPe32BaseAddress
1471 Routine Description:
1473 Set new base address into the section header of PeImage
1477 FileName - Name of file
1478 FileBuffer - Pointer to PeImage.
1479 NewPe32BaseAddress - New Base Address for PE image.
1483 EFI_SUCCESS Set new base address into this image successfully.
1488 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1490 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1491 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1494 // Initialize context
1496 memset (&ImageContext
, 0, sizeof (ImageContext
));
1497 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1498 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1499 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1500 if (EFI_ERROR (Status
)) {
1501 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1505 if (ImageContext
.RelocationsStripped
) {
1506 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1511 // Get PeHeader pointer
1513 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1516 // Get section header list
1518 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1521 sizeof (EFI_IMAGE_FILE_HEADER
) +
1522 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1526 // Set base address into the first section header that doesn't point to code section.
1528 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1529 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1530 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1536 // BaseAddress is set to section header.
1544 IN OUT UINT8
*FileBuffer
,
1545 IN UINT64 NewPe32BaseAddress
1549 Routine Description:
1551 Set new base address into PeImage, and fix up PeImage based on new address.
1555 FileName - Name of file
1556 FileBuffer - Pointer to PeImage.
1557 NewPe32BaseAddress - New Base Address for PE image.
1561 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1562 EFI_SUCCESS - Update PeImage is correctly.
1567 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1569 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1570 UINT8
*MemoryImagePointer
;
1571 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1574 // Initialize context
1576 memset (&ImageContext
, 0, sizeof (ImageContext
));
1577 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1578 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1579 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1580 if (EFI_ERROR (Status
)) {
1581 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1585 if (ImageContext
.RelocationsStripped
) {
1586 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1591 // Get PeHeader pointer
1593 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1596 // Load and Relocate Image Data
1598 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1599 if (MemoryImagePointer
== NULL
) {
1600 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1601 return EFI_OUT_OF_RESOURCES
;
1603 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1604 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1606 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1607 if (EFI_ERROR (Status
)) {
1608 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1609 free ((VOID
*) MemoryImagePointer
);
1613 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1614 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1615 if (EFI_ERROR (Status
)) {
1616 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1617 free ((VOID
*) MemoryImagePointer
);
1622 // Copy Relocated data to raw image file.
1624 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1627 sizeof (EFI_IMAGE_FILE_HEADER
) +
1628 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1631 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1633 FileBuffer
+ SectionHeader
->PointerToRawData
,
1634 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1635 SectionHeader
->SizeOfRawData
1639 free ((VOID
*) MemoryImagePointer
);
1642 // Update Image Base Address
1644 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1645 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1646 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1647 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1649 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1650 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1657 // Set new base address into section header
1659 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1666 IN CHAR8
* DefaultPath
,
1667 IN CHAR8
* AppendPath
,
1671 UINT32 DefaultPathLen
;
1673 CHAR8 QuotesStr
[] = "\"";
1674 strcpy(NewPath
, QuotesStr
);
1675 DefaultPathLen
= strlen(DefaultPath
);
1676 strcat(NewPath
, DefaultPath
);
1678 for (; Index
< DefaultPathLen
+ 1; Index
++) {
1679 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1680 if (NewPath
[Index
+ 1] != '\0') {
1681 NewPath
[Index
] = '/';
1685 if (NewPath
[Index
-1] != '/') {
1686 NewPath
[Index
] = '/';
1687 NewPath
[Index
+ 1] = '\0';
1689 strcat(NewPath
, AppendPath
);
1690 strcat(NewPath
, QuotesStr
);
1696 IN UINT8
*SectionBuffer
,
1697 IN UINT32 BufferLength
1701 Routine Description:
1707 SectionBuffer - Buffer containing the section to parse.
1708 BufferLength - Length of SectionBuffer
1712 EFI_SECTION_ERROR - Problem with section parsing.
1713 (a) compression errors
1714 (b) unrecognized section
1715 EFI_UNSUPPORTED - Do not know how to parse the section.
1716 EFI_SUCCESS - Section successfully parsed.
1717 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1721 EFI_SECTION_TYPE Type
;
1723 UINT32 SectionLength
;
1724 UINT32 SectionHeaderLen
;
1727 UINT32 ParsedLength
;
1728 UINT8
*CompressedBuffer
;
1729 UINT32 CompressedLength
;
1730 UINT8
*UncompressedBuffer
;
1731 UINT32 UncompressedLength
;
1732 UINT8
*ToolOutputBuffer
;
1733 UINT32 ToolOutputLength
;
1734 UINT8 CompressionType
;
1737 UINT8
*ScratchBuffer
;
1738 DECOMPRESS_FUNCTION DecompressFunction
;
1739 GETINFO_FUNCTION GetInfoFunction
;
1741 CHAR8
*ExtractionTool
;
1742 CHAR8
*ToolInputFile
;
1743 CHAR8
*ToolOutputFile
;
1744 CHAR8
*SystemCommand
;
1749 CHAR8
*ToolInputFileName
;
1750 CHAR8
*ToolOutputFileName
;
1752 CHAR8
*VersionString
;
1755 ToolInputFileName
= NULL
;
1756 ToolOutputFileName
= NULL
;
1758 while (ParsedLength
< BufferLength
) {
1759 Ptr
= SectionBuffer
+ ParsedLength
;
1761 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1762 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1765 // This is sort of an odd check, but is necessary because FFS files are
1766 // padded to a QWORD boundary, meaning there is potentially a whole section
1767 // header worth of 0xFF bytes.
1769 if (SectionLength
== 0xffffff && Type
== 0xff) {
1775 // Get real section file size
1777 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1778 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1780 SectionName
= SectionNameToStr (Type
);
1781 if (SectionName
!= NULL
) {
1782 printf ("------------------------------------------------------------\n");
1783 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1788 case EFI_SECTION_RAW
:
1789 case EFI_SECTION_PIC
:
1790 case EFI_SECTION_TE
:
1791 // default is no more information
1794 case EFI_SECTION_PE32
:
1796 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1797 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1798 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1801 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1802 SectionLength
- SectionHeaderLen
1805 SystemCommand
= malloc (
1806 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1807 strlen (OpenSslPath
) +
1808 strlen (ToolInputFileName
) +
1809 strlen (ToolOutputFileName
) +
1812 if (SystemCommand
== NULL
) {
1813 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1814 return EFI_OUT_OF_RESOURCES
;
1818 OPENSSL_COMMAND_FORMAT_STRING
,
1824 if (system (SystemCommand
) != EFI_SUCCESS
) {
1825 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1832 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1833 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1836 fseek(fp
,0,SEEK_SET
);
1837 fseek(fp
,0,SEEK_END
);
1838 nFileLen
= ftell(fp
);
1839 fseek(fp
,0,SEEK_SET
);
1840 StrLine
= malloc(nFileLen
);
1841 if (StrLine
== NULL
) {
1843 free (SystemCommand
);
1844 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1845 return EFI_OUT_OF_RESOURCES
;
1847 fgets(StrLine
, nFileLen
, fp
);
1848 NewStr
= strrchr (StrLine
, '=');
1849 printf (" SHA1: %s\n", NewStr
+ 1);
1854 remove(ToolInputFileName
);
1855 remove(ToolOutputFileName
);
1856 free (SystemCommand
);
1860 case EFI_SECTION_USER_INTERFACE
:
1861 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1862 if (UIFileName
== NULL
) {
1863 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1864 return EFI_OUT_OF_RESOURCES
;
1866 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1867 printf (" String: %s\n", UIFileName
);
1871 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1872 printf ("/------------ Firmware Volume section start ---------------\\\n");
1873 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1874 if (EFI_ERROR (Status
)) {
1875 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1876 return EFI_SECTION_ERROR
;
1878 printf ("\\------------ Firmware Volume section end -----------------/\n");
1881 case EFI_SECTION_COMPATIBILITY16
:
1883 // Section does not contain any further header information.
1887 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1889 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
))
1890 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION
*)Ptr
)->SubTypeGuid
);
1892 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION2
*)Ptr
)->SubTypeGuid
);
1896 case EFI_SECTION_PEI_DEPEX
:
1897 case EFI_SECTION_DXE_DEPEX
:
1898 case EFI_SECTION_SMM_DEPEX
:
1899 DumpDepexSection (Ptr
, SectionLength
);
1902 case EFI_SECTION_VERSION
:
1903 printf (" Build Number: 0x%04X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1904 VersionString
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
) + 1);
1905 if (VersionString
== NULL
) {
1906 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1907 return EFI_OUT_OF_RESOURCES
;
1909 Unicode2AsciiString (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
, VersionString
);
1910 printf (" Version String: %s\n", VersionString
);
1913 case EFI_SECTION_COMPRESSION
:
1914 UncompressedBuffer
= NULL
;
1915 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1916 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1917 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1918 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1920 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1921 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1922 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1924 CompressedLength
= SectionLength
- RealHdrLen
;
1925 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1927 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1928 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1929 if (CompressedLength
!= UncompressedLength
) {
1934 "file is not compressed, but the compressed length does not match the uncompressed length",
1937 return EFI_SECTION_ERROR
;
1940 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1941 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1942 GetInfoFunction
= EfiGetInfo
;
1943 DecompressFunction
= EfiDecompress
;
1944 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1946 CompressedBuffer
= Ptr
+ RealHdrLen
;
1948 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1949 if (EFI_ERROR (Status
)) {
1950 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1951 return EFI_SECTION_ERROR
;
1954 if (DstSize
!= UncompressedLength
) {
1955 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1956 return EFI_SECTION_ERROR
;
1959 ScratchBuffer
= malloc (ScratchSize
);
1960 if (ScratchBuffer
== NULL
) {
1961 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1962 return EFI_OUT_OF_RESOURCES
;
1964 UncompressedBuffer
= malloc (UncompressedLength
);
1965 if (UncompressedBuffer
== NULL
) {
1966 free (ScratchBuffer
);
1967 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1968 return EFI_OUT_OF_RESOURCES
;
1970 Status
= DecompressFunction (
1978 free (ScratchBuffer
);
1979 if (EFI_ERROR (Status
)) {
1980 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1981 free (UncompressedBuffer
);
1982 return EFI_SECTION_ERROR
;
1985 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1986 return EFI_SECTION_ERROR
;
1989 printf ("/------------ Encapsulation section start -----------------\\\n");
1990 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1991 printf ("\\------------ Encapsulation section end -------------------/\n");
1993 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1995 // We need to deallocate Buffer
1997 free (UncompressedBuffer
);
2000 if (EFI_ERROR (Status
)) {
2001 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
2002 return EFI_SECTION_ERROR
;
2006 case EFI_SECTION_GUID_DEFINED
:
2007 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
2008 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
2009 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
2010 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
2012 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
2013 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
2014 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
2016 printf (" SectionDefinitionGuid: ");
2017 PrintGuid (EfiGuid
);
2019 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
2020 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
2023 LookupGuidedSectionToolPath (
2024 mParsedGuidedSectionTools
,
2028 if (ExtractionTool
!= NULL
) {
2030 ToolInputFile
= CloneString (tmpnam (NULL
));
2031 ToolOutputFile
= CloneString (tmpnam (NULL
));
2033 char tmp1
[] = "/tmp/fileXXXXXX";
2034 char tmp2
[] = "/tmp/fileXXXXXX";
2037 fd1
= mkstemp(tmp1
);
2038 fd2
= mkstemp(tmp2
);
2039 ToolInputFile
= CloneString(tmp1
);
2040 ToolOutputFile
= CloneString(tmp2
);
2045 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
2046 if (ToolInputFile
!= NULL
) {
2047 free (ToolInputFile
);
2049 if (ToolOutputFile
!= NULL
) {
2050 free (ToolOutputFile
);
2052 free (ExtractionTool
);
2054 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2055 return EFI_OUT_OF_RESOURCES
;
2059 // Construction 'system' command string
2061 SystemCommand
= malloc (
2062 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
2063 strlen (ExtractionTool
) +
2064 strlen (ToolInputFile
) +
2065 strlen (ToolOutputFile
) +
2068 if (SystemCommand
== NULL
) {
2069 free (ToolInputFile
);
2070 free (ToolOutputFile
);
2071 free (ExtractionTool
);
2073 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2074 return EFI_OUT_OF_RESOURCES
;
2078 EXTRACT_COMMAND_FORMAT_STRING
,
2083 free (ExtractionTool
);
2087 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2095 (CHAR8
*)Ptr
+ DataOffset
,
2096 SectionLength
- DataOffset
2099 system (SystemCommand
);
2100 remove (ToolInputFile
);
2101 free (ToolInputFile
);
2106 (CHAR8
**)&ToolOutputBuffer
,
2109 remove (ToolOutputFile
);
2110 free (ToolOutputFile
);
2111 free (SystemCommand
);
2112 if (EFI_ERROR (Status
)) {
2113 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2114 return EFI_SECTION_ERROR
;
2117 printf ("/------------ Encapsulation section start -----------------\\\n");
2118 Status
= ParseSection (
2122 if (EFI_ERROR (Status
)) {
2123 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2124 return EFI_SECTION_ERROR
;
2126 printf ("\\------------ Encapsulation section end -------------------/\n");
2129 // Check for CRC32 sections which we can handle internally if needed.
2131 } else if (!CompareGuid (
2133 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2137 // CRC32 guided section
2139 printf ("/------------ Encapsulation section start -----------------\\\n");
2140 Status
= ParseSection (
2142 SectionLength
- DataOffset
2144 if (EFI_ERROR (Status
)) {
2145 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2146 return EFI_SECTION_ERROR
;
2148 printf ("\\------------ Encapsulation section end -------------------/\n");
2151 // We don't know how to parse it now.
2153 Error (NULL
, 0, 0003, "Error parsing section", \
2154 "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).");
2155 return EFI_UNSUPPORTED
;
2161 // Unknown section, return error
2163 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2164 return EFI_SECTION_ERROR
;
2167 ParsedLength
+= SectionLength
;
2169 // We make then next section begin on a 4-byte boundary
2171 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2174 if (ParsedLength
< BufferLength
) {
2175 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2176 return EFI_SECTION_ERROR
;
2185 IN UINT32 SectionLength
2189 Routine Description:
2191 GC_TODO: Add function description
2195 Ptr - GC_TODO: add argument description
2196 SectionLength - GC_TODO: add argument description
2200 EFI_SUCCESS - GC_TODO: Add description for return value
2204 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2207 // Need at least a section header + data
2209 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2213 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2214 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2215 while (SectionLength
> 0) {
2218 case EFI_DEP_BEFORE
:
2219 printf ("BEFORE\n");
2232 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2233 printf ("%s ", GuidBuffer
);
2234 PrintGuidName (GuidBuffer
);
2237 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2240 SectionLength
-= 17;
2274 printf ("END DEPEX\n");
2286 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2300 Routine Description:
2302 GC_TODO: Add function description
2306 GuidStr - GC_TODO: add argument description
2310 EFI_SUCCESS - GC_TODO: Add description for return value
2311 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2315 GUID_TO_BASENAME
*GPtr
;
2317 // If we have a list of guid-to-basenames, then go through the list to
2318 // look for a guid string match. If found, print the basename to stdout,
2319 // otherwise return a failure.
2321 GPtr
= mGuidBaseNameList
;
2322 while (GPtr
!= NULL
) {
2323 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2324 printf ("%s", GPtr
->BaseName
);
2331 return EFI_INVALID_PARAMETER
;
2335 ParseGuidBaseNameFile (
2340 Routine Description:
2342 GC_TODO: Add function description
2346 FileName - GC_TODO: add argument description
2350 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2351 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2352 EFI_SUCCESS - GC_TODO: Add description for return value
2357 CHAR8 Line
[MAX_LINE_LEN
];
2358 CHAR8 FormatString
[MAX_LINE_LEN
];
2359 GUID_TO_BASENAME
*GPtr
;
2361 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2362 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2363 return EFI_DEVICE_ERROR
;
2367 // Generate the format string for fscanf
2372 (unsigned) sizeof (GPtr
->Guid
) - 1,
2373 (unsigned) sizeof (GPtr
->BaseName
) - 1
2376 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2378 // Allocate space for another guid/basename element
2380 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2383 return EFI_OUT_OF_RESOURCES
;
2386 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2387 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2388 GPtr
->Next
= mGuidBaseNameList
;
2389 mGuidBaseNameList
= GPtr
;
2392 // Some sort of error. Just continue.
2403 FreeGuidBaseNameList (
2408 Routine Description:
2410 GC_TODO: Add function description
2418 EFI_SUCCESS - GC_TODO: Add description for return value
2422 GUID_TO_BASENAME
*Next
;
2424 while (mGuidBaseNameList
!= NULL
) {
2425 Next
= mGuidBaseNameList
->Next
;
2426 free (mGuidBaseNameList
);
2427 mGuidBaseNameList
= Next
;
2436 LoadGuidedSectionToolsTxt (
2437 IN CHAR8
* FirmwareVolumeFilename
2440 CHAR8
* PeerFilename
;
2447 Places
[0] = FirmwareVolumeFilename
;
2448 //Places[1] = mUtilityFilename;
2450 mParsedGuidedSectionTools
= NULL
;
2452 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2453 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2454 //printf("Loading %s...\n", PeerFilename);
2455 if (OsPathExists (PeerFilename
)) {
2456 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2458 free (PeerFilename
);
2459 if (mParsedGuidedSectionTools
!= NULL
) {
2472 Routine Description:
2474 GC_TODO: Add function description
2482 GC_TODO: add return values
2489 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2492 // Copyright declaration
2494 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
2495 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2500 fprintf (stdout
, "optional arguments:\n");
2501 fprintf (stdout
, " -h, --help\n\
2502 Show this help message and exit\n");
2503 fprintf (stdout
, " --version\n\
2504 Show program's version number and exit\n");
2505 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2506 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2507 fprintf (stdout
, " -v, --verbose\n\
2508 Print informational statements\n");
2509 fprintf (stdout
, " -q, --quiet\n\
2510 Returns the exit code, error messages will be displayed\n");
2511 fprintf (stdout
, " -s, --silent\n\
2512 Returns only the exit code; informational and error\n\
2513 messages are not displayed\n");
2514 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2515 Parse the basename to file-guid cross reference file(s)\n");
2516 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2517 The offset from the start of the input file to start \n\
2518 processing an FV\n");
2519 fprintf (stdout
, " --hash\n\
2520 Generate HASH value of the entire PE image\n");
2521 fprintf (stdout
, " --sfo\n\
2522 Reserved for future use\n");