2 The tool dumps the contents of a firmware volume
4 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
21 #include <Common/UefiBaseTypes.h>
22 #include <Common/UefiCapsule.h>
23 #include <Common/PiFirmwareFile.h>
24 #include <Common/PiFirmwareVolume.h>
25 #include <Guid/PiFirmwareFileSystem.h>
26 #include <IndustryStandard/PeImage.h>
27 #include <Protocol/GuidedSectionExtraction.h>
30 #include "Decompress.h"
32 #include "CommonLib.h"
33 #include "EfiUtilityMsgs.h"
34 #include "FirmwareVolumeBufferLib.h"
36 #include "ParseGuidedSectionTools.h"
37 #include "StringFuncs.h"
39 #include "PeCoffLib.h"
42 // Utility global variables
45 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
47 #define UTILITY_MAJOR_VERSION 1
48 #define UTILITY_MINOR_VERSION 0
50 #define UTILITY_NAME "VolInfo"
52 #define EFI_SECTION_ERROR EFIERR (100)
55 // Structure to keep a list of guid-to-basenames
57 typedef struct _GUID_TO_BASENAME
{
58 struct _GUID_TO_BASENAME
*Next
;
59 INT8 Guid
[PRINTED_GUID_BUFFER_SIZE
];
60 INT8 BaseName
[MAX_LINE_LEN
];
63 static GUID_TO_BASENAME
*mGuidBaseNameList
= NULL
;
66 // Store GUIDed Section guid->tool mapping
68 EFI_HANDLE mParsedGuidedSectionTools
= NULL
;
70 CHAR8
* mUtilityFilename
= NULL
;
72 BOOLEAN EnableHash
= FALSE
;
73 CHAR8
*OpenSslPath
= NULL
;
76 ParseGuidBaseNameFile (
81 FreeGuidBaseNameList (
92 IN UINT8
*SectionBuffer
,
93 IN UINT32 BufferLength
99 IN UINT32 SectionLength
107 OUT BOOLEAN
*ErasePolarity
113 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
114 EFI_FFS_FILE_HEADER
*FileHeader
,
115 BOOLEAN ErasePolarity
127 LoadGuidedSectionToolsTxt (
128 IN CHAR8
* FirmwareVolumeFilename
133 IN CHAR8
* DefaultPath
,
134 IN CHAR8
* AppendPath
,
151 Returns the length of a null-terminated unicode string.
155 String - The pointer to a null-terminated unicode string.
165 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++) {
172 Unicode2AsciiString (
174 OUT CHAR8
*Destination
180 Convert a null-terminated unicode string to a null-terminated ascii string.
184 Source - The pointer to the null-terminated input unicode string.
185 Destination - The pointer to the null-terminated output ascii string.
193 while (*Source
!= '\0') {
194 *(Destination
++) = (CHAR8
) *(Source
++);
197 // End the ascii with a NULL.
211 GC_TODO: Add function description
215 argc - GC_TODO: add argument description
216 ] - GC_TODO: add argument description
220 GC_TODO: add return values
226 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
230 BOOLEAN ErasePolarity
;
233 CHAR8
*OpenSslCommand
;
235 SetUtilityName (UTILITY_NAME
);
237 // Print utility header
239 printf ("%s Version %d.%d Build %s\n",
241 UTILITY_MAJOR_VERSION
,
242 UTILITY_MINOR_VERSION
,
257 // Look for help options
259 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
260 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
262 return STATUS_SUCCESS
;
265 // Version has already be printed, so just return success
267 if (strcmp(argv
[0], "--version") == 0) {
268 return STATUS_SUCCESS
;
272 // If they specified -x xref guid/basename cross-reference files, process it.
273 // This will print the basename beside each file guid. To use it, specify
274 // -x xref_filename to processdsc, then use xref_filename as a parameter
278 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
279 ParseGuidBaseNameFile (argv
[1]);
280 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
285 if (strcmp(argv
[0], "--offset") == 0) {
289 if ((argv
[1][0] == '0') && (tolower ((int)argv
[1][1]) == 'x')) {
290 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
291 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
292 return GetUtilityStatus ();
295 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
296 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
297 return GetUtilityStatus ();
300 // See if they said something like "64K"
302 if (tolower ((int)argv
[1][strlen (argv
[1]) - 1]) == 'k') {
311 if ((stricmp (argv
[0], "--hash") == 0)) {
312 if (EnableHash
== TRUE
) {
314 // --hash already given in the option, ignore this one
321 OpenSslCommand
= "openssl";
322 OpenSslEnv
= getenv("OPENSSL_PATH");
323 if (OpenSslEnv
== NULL
) {
324 OpenSslPath
= OpenSslCommand
;
327 // We add quotes to the Openssl Path in case it has space characters
329 OpenSslPath
= malloc(2+strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
330 if (OpenSslPath
== NULL
) {
331 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
332 return GetUtilityStatus ();
334 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
336 if (OpenSslPath
== NULL
){
337 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
338 return GetUtilityStatus ();
345 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
346 SetPrintLevel (VERBOSE_LOG_LEVEL
);
352 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
353 SetPrintLevel (KEY_LOG_LEVEL
);
359 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
360 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
361 if (EFI_ERROR (Status
)) {
362 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
366 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
369 SetPrintLevel (LogLevel
);
370 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
376 mUtilityFilename
= argv
[0];
382 // Open the file containing the FV
384 if (mUtilityFilename
== NULL
) {
385 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
386 return GetUtilityStatus ();
388 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
389 if (InputFile
== NULL
) {
390 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
391 return GetUtilityStatus ();
394 // Skip over pad bytes if specified. This is used if they prepend 0xff
395 // data to the FV image binary.
398 fseek (InputFile
, Offset
, SEEK_SET
);
401 // Determine size of FV
403 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
404 if (EFI_ERROR (Status
)) {
405 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
407 return GetUtilityStatus ();
410 // Allocate a buffer for the FV image
412 FvImage
= malloc (FvSize
);
413 if (FvImage
== NULL
) {
414 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
416 return GetUtilityStatus ();
419 // Seek to the start of the image, then read the entire FV to the buffer
421 fseek (InputFile
, Offset
, SEEK_SET
);
422 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
424 if ((unsigned int) BytesRead
!= FvSize
) {
425 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
427 return GetUtilityStatus ();
430 LoadGuidedSectionToolsTxt (mUtilityFilename
);
432 PrintFvInfo (FvImage
, FALSE
);
438 FreeGuidBaseNameList ();
439 return GetUtilityStatus ();
453 GC_TODO: Add function description
457 Fv - Firmware Volume to print information about
458 IsChildFv - Flag specifies whether the input FV is a child FV.
468 BOOLEAN ErasePolarity
;
470 EFI_FFS_FILE_HEADER
*CurrentFile
;
473 Status
= FvBufGetSize (Fv
, &FvSize
);
477 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
481 // Get the first file
484 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
485 if (EFI_ERROR (Status
)) {
486 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
487 return GetUtilityStatus ();
490 // Display information about files found
492 while (CurrentFile
!= NULL
) {
494 // Increment the number of files counter
499 // Display info about this file
501 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
502 if (EFI_ERROR (Status
)) {
503 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
504 return GetUtilityStatus ();
509 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
510 if (Status
== EFI_NOT_FOUND
) {
512 } else if (EFI_ERROR (Status
)) {
513 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
514 return GetUtilityStatus ();
519 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
521 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
529 IN UINT32 ActualSize
,
536 This function returns the next larger size that meets the alignment
537 requirement specified.
542 Alignment The desired alignment.
546 EFI_SUCCESS Function completed successfully.
547 EFI_ABORTED The function encountered an error.
553 OccupiedSize
= ActualSize
;
554 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
564 IN EFI_SECTION_TYPE Type
570 Converts EFI Section names to Strings
574 Type - The EFI Section type
578 CHAR8* - Pointer to the String containing the section name.
583 CHAR8
*SectionTypeStringTable
[] = {
591 "EFI_SECTION_COMPRESSION",
595 "EFI_SECTION_GUID_DEFINED",
599 "Unknown section type - Reserved 0x03",
603 "Unknown section type - Reserved 0x04",
607 "Unknown section type - Reserved 0x05",
611 "Unknown section type - Reserved 0x06",
615 "Unknown section type - Reserved 0x07",
619 "Unknown section type - Reserved 0x08",
623 "Unknown section type - Reserved 0x09",
627 "Unknown section type - Reserved 0x0A",
631 "Unknown section type - Reserved 0x0B",
635 "Unknown section type - Reserved 0x0C",
639 "Unknown section type - Reserved 0x0D",
643 "Unknown section type - Reserved 0x0E",
647 "Unknown section type - Reserved 0x0E",
663 "EFI_SECTION_DXE_DEPEX",
667 "EFI_SECTION_VERSION",
671 "EFI_SECTION_USER_INTERFACE",
675 "EFI_SECTION_COMPATIBILITY16",
679 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
683 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
691 "Unknown section type - 0x1A",
695 "EFI_SECTION_PEI_DEPEX",
699 "EFI_SECTION_SMM_DEPEX",
703 "Unknown section type - Reserved - beyond last defined section"
706 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
707 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
710 SectionStr
= malloc (100);
711 if (SectionStr
== NULL
) {
712 printf ("Error: Out of memory resources.\n");
715 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
724 OUT BOOLEAN
*ErasePolarity
730 This function determines the size of the FV and the erase polarity. The
731 erase polarity is the FALSE value for file state.
735 InputFile The file that contains the FV image.
736 FvSize The size of the FV.
737 ErasePolarity The FV erase polarity.
741 EFI_SUCCESS Function completed successfully.
742 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
743 EFI_ABORTED The function encountered an error.
747 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
748 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
757 // Check input parameters
759 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
760 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
761 return EFI_INVALID_PARAMETER
;
766 ReadSize
= fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
770 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
771 Signature
[0] = VolumeHeader
.Signature
;
775 // Print FV header information
777 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
778 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
780 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
781 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
784 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
785 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
788 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
789 printf (" EFI_FVB2_READ_STATUS\n");
792 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
793 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
796 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
797 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
800 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
801 printf (" EFI_FVB2_WRITE_STATUS\n");
804 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
805 printf (" EFI_FVB2_LOCK_CAP\n");
808 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
809 printf (" EFI_FVB2_LOCK_STATUS\n");
812 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
813 printf (" EFI_FVB2_STICKY_WRITE\n");
816 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
817 printf (" EFI_FVB2_MEMORY_MAPPED\n");
820 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
821 printf (" EFI_FVB2_ERASE_POLARITY\n");
822 *ErasePolarity
= TRUE
;
825 #if (PI_SPECIFICATION_VERSION < 0x00010000)
826 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
827 printf (" EFI_FVB2_ALIGNMENT\n");
830 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
831 printf (" EFI_FVB2_ALIGNMENT_2\n");
834 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
835 printf (" EFI_FVB2_ALIGNMENT_4\n");
838 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
839 printf (" EFI_FVB2_ALIGNMENT_8\n");
842 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
843 printf (" EFI_FVB2_ALIGNMENT_16\n");
846 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
847 printf (" EFI_FVB2_ALIGNMENT_32\n");
850 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
851 printf (" EFI_FVB2_ALIGNMENT_64\n");
854 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
855 printf (" EFI_FVB2_ALIGNMENT_128\n");
858 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
859 printf (" EFI_FVB2_ALIGNMENT_256\n");
862 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
863 printf (" EFI_FVB2_ALIGNMENT_512\n");
866 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
867 printf (" EFI_FVB2_ALIGNMENT_1K\n");
870 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
871 printf (" EFI_FVB2_ALIGNMENT_2K\n");
874 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
875 printf (" EFI_FVB2_ALIGNMENT_4K\n");
878 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
879 printf (" EFI_FVB2_ALIGNMENT_8K\n");
882 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
883 printf (" EFI_FVB2_ALIGNMENT_16K\n");
886 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
887 printf (" EFI_FVB2_ALIGNMENT_32K\n");
890 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
891 printf (" EFI_FVB2_ALIGNMENT_64K\n");
896 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
897 printf (" EFI_FVB2_READ_LOCK_CAP\n");
900 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
901 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
904 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
905 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
908 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
909 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
912 switch (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
913 case EFI_FVB2_ALIGNMENT_1
:
914 printf (" EFI_FVB2_ALIGNMENT_1\n");
917 case EFI_FVB2_ALIGNMENT_2
:
918 printf (" EFI_FVB2_ALIGNMENT_2\n");
921 case EFI_FVB2_ALIGNMENT_4
:
922 printf (" EFI_FVB2_ALIGNMENT_4\n");
925 case EFI_FVB2_ALIGNMENT_8
:
926 printf (" EFI_FVB2_ALIGNMENT_8\n");
929 case EFI_FVB2_ALIGNMENT_16
:
930 printf (" EFI_FVB2_ALIGNMENT_16\n");
933 case EFI_FVB2_ALIGNMENT_32
:
934 printf (" EFI_FVB2_ALIGNMENT_32\n");
937 case EFI_FVB2_ALIGNMENT_64
:
938 printf (" EFI_FVB2_ALIGNMENT_64\n");
941 case EFI_FVB2_ALIGNMENT_128
:
942 printf (" EFI_FVB2_ALIGNMENT_128\n");
945 case EFI_FVB2_ALIGNMENT_256
:
946 printf (" EFI_FVB2_ALIGNMENT_256\n");
949 case EFI_FVB2_ALIGNMENT_512
:
950 printf (" EFI_FVB2_ALIGNMENT_512\n");
953 case EFI_FVB2_ALIGNMENT_1K
:
954 printf (" EFI_FVB2_ALIGNMENT_1K\n");
957 case EFI_FVB2_ALIGNMENT_2K
:
958 printf (" EFI_FVB2_ALIGNMENT_2K\n");
961 case EFI_FVB2_ALIGNMENT_4K
:
962 printf (" EFI_FVB2_ALIGNMENT_4K\n");
965 case EFI_FVB2_ALIGNMENT_8K
:
966 printf (" EFI_FVB2_ALIGNMENT_8K\n");
969 case EFI_FVB2_ALIGNMENT_16K
:
970 printf (" EFI_FVB2_ALIGNMENT_16K\n");
973 case EFI_FVB2_ALIGNMENT_32K
:
974 printf (" EFI_FVB2_ALIGNMENT_32K\n");
977 case EFI_FVB2_ALIGNMENT_64K
:
978 printf (" EFI_FVB2_ALIGNMENT_64K\n");
981 case EFI_FVB2_ALIGNMENT_128K
:
982 printf (" EFI_FVB2_ALIGNMENT_128K\n");
985 case EFI_FVB2_ALIGNMENT_256K
:
986 printf (" EFI_FVB2_ALIGNMENT_256K\n");
989 case EFI_FVB2_ALIGNMENT_512K
:
990 printf (" EFI_FVB2_ALIGNMENT_512K\n");
993 case EFI_FVB2_ALIGNMENT_1M
:
994 printf (" EFI_FVB2_ALIGNMENT_1M\n");
997 case EFI_FVB2_ALIGNMENT_2M
:
998 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1001 case EFI_FVB2_ALIGNMENT_4M
:
1002 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1005 case EFI_FVB2_ALIGNMENT_8M
:
1006 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1009 case EFI_FVB2_ALIGNMENT_16M
:
1010 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1013 case EFI_FVB2_ALIGNMENT_32M
:
1014 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1017 case EFI_FVB2_ALIGNMENT_64M
:
1018 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1021 case EFI_FVB2_ALIGNMENT_128M
:
1022 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1025 case EFI_FVB2_ALIGNMENT_256M
:
1026 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1029 case EFI_FVB2_ALIGNMENT_512M
:
1030 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1033 case EFI_FVB2_ALIGNMENT_1G
:
1034 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1037 case EFI_FVB2_ALIGNMENT_2G
:
1038 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1043 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1044 printf ("File System ID: ");
1045 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1049 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1052 ReadSize
= fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1053 if (ReadSize
!= 1) {
1056 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1058 if (BlockMap
.NumBlocks
!= 0) {
1059 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1060 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1061 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1064 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1066 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1067 printf ("ERROR: Header length not consistent with Block Maps!\n");
1071 if (VolumeHeader
.FvLength
!= Size
) {
1072 printf ("ERROR: Volume Size not consistent with Block Maps!\n");
1076 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1081 // rewind (InputFile);
1089 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1090 EFI_FFS_FILE_HEADER
*FileHeader
,
1091 BOOLEAN ErasePolarity
1095 Routine Description:
1097 GC_TODO: Add function description
1101 FvImage - GC_TODO: add argument description
1102 FileHeader - GC_TODO: add argument description
1103 ErasePolarity - GC_TODO: add argument description
1107 EFI_SUCCESS - GC_TODO: Add description for return value
1108 EFI_ABORTED - GC_TODO: Add description for return value
1115 EFI_FFS_FILE_HEADER2 BlankHeader
;
1117 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1119 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1123 // Check if we have free space
1125 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1126 if (ErasePolarity
) {
1127 memset (&BlankHeader
, -1, HeaderSize
);
1129 memset (&BlankHeader
, 0, HeaderSize
);
1132 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1136 // Print file information.
1138 printf ("============================================================\n");
1140 printf ("File Name: ");
1141 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1142 printf ("%s ", GuidBuffer
);
1143 PrintGuidName (GuidBuffer
);
1147 // PrintGuid (&FileHeader->Name);
1150 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1151 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1152 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1153 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1154 printf ("File State: 0x%02X\n", FileHeader
->State
);
1159 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1161 switch (FileState
) {
1163 case EFI_FILE_HEADER_CONSTRUCTION
:
1164 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1167 case EFI_FILE_HEADER_INVALID
:
1168 printf (" EFI_FILE_HEADER_INVALID\n");
1171 case EFI_FILE_HEADER_VALID
:
1172 printf (" EFI_FILE_HEADER_VALID\n");
1173 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1174 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1175 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1176 if (Checksum
!= 0) {
1177 printf ("ERROR: Header checksum invalid.\n");
1183 case EFI_FILE_DELETED
:
1184 printf (" EFI_FILE_DELETED\n");
1186 case EFI_FILE_MARKED_FOR_UPDATE
:
1187 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1189 case EFI_FILE_DATA_VALID
:
1190 printf (" EFI_FILE_DATA_VALID\n");
1193 // Calculate header checksum
1195 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1196 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1197 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1198 if (Checksum
!= 0) {
1199 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1203 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1205 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1207 // Calculate file checksum
1209 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1210 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1211 if (Checksum
!= 0) {
1212 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1216 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1217 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
);
1221 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1223 // Verify tail if present
1225 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1227 // Verify tail is complement of integrity check field in the header.
1229 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1230 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1231 Error (NULL
, 0, 0003, "error parsing FFS file", \
1232 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1240 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1244 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1246 switch (FileHeader
->Type
) {
1248 case EFI_FV_FILETYPE_RAW
:
1249 printf ("EFI_FV_FILETYPE_RAW\n");
1252 case EFI_FV_FILETYPE_FREEFORM
:
1253 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1256 case EFI_FV_FILETYPE_SECURITY_CORE
:
1257 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1260 case EFI_FV_FILETYPE_PEI_CORE
:
1261 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1264 case EFI_FV_FILETYPE_DXE_CORE
:
1265 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1268 case EFI_FV_FILETYPE_PEIM
:
1269 printf ("EFI_FV_FILETYPE_PEIM\n");
1272 case EFI_FV_FILETYPE_DRIVER
:
1273 printf ("EFI_FV_FILETYPE_DRIVER\n");
1276 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1277 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1280 case EFI_FV_FILETYPE_APPLICATION
:
1281 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1284 case EFI_FV_FILETYPE_SMM
:
1285 printf ("EFI_FV_FILETYPE_SMM\n");
1288 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1289 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1292 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1293 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1296 case EFI_FV_FILETYPE_SMM_CORE
:
1297 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1300 case EFI_FV_FILETYPE_MM_STANDALONE
:
1301 printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
1304 case EFI_FV_FILETYPE_MM_CORE_STANDALONE
:
1305 printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
1308 case EFI_FV_FILETYPE_FFS_PAD
:
1309 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1313 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1318 switch (FileHeader
->Type
) {
1320 case EFI_FV_FILETYPE_ALL
:
1321 case EFI_FV_FILETYPE_RAW
:
1322 case EFI_FV_FILETYPE_FFS_PAD
:
1327 // All other files have sections
1329 Status
= ParseSection (
1330 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1331 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1333 if (EFI_ERROR (Status
)) {
1335 // printf ("ERROR: Parsing the FFS file.\n");
1347 IN VOID
*FileHandle
,
1348 IN UINTN FileOffset
,
1349 IN OUT UINT32
*ReadSize
,
1354 Routine Description:
1356 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1360 FileHandle - The handle to the PE/COFF file
1362 FileOffset - The offset, in bytes, into the file to read
1364 ReadSize - The number of bytes to read from the file starting at FileOffset
1366 Buffer - A pointer to the buffer to read the data into.
1370 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1374 CHAR8
*Destination8
;
1378 Destination8
= Buffer
;
1379 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1382 *(Destination8
++) = *(Source8
++);
1389 SetAddressToSectionHeader (
1391 IN OUT UINT8
*FileBuffer
,
1392 IN UINT64 NewPe32BaseAddress
1396 Routine Description:
1398 Set new base address into the section header of PeImage
1402 FileName - Name of file
1403 FileBuffer - Pointer to PeImage.
1404 NewPe32BaseAddress - New Base Address for PE image.
1408 EFI_SUCCESS Set new base address into this image successfully.
1413 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1415 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1416 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1419 // Initialize context
1421 memset (&ImageContext
, 0, sizeof (ImageContext
));
1422 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1423 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1424 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1425 if (EFI_ERROR (Status
)) {
1426 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1430 if (ImageContext
.RelocationsStripped
) {
1431 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1436 // Get PeHeader pointer
1438 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1441 // Get section header list
1443 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1446 sizeof (EFI_IMAGE_FILE_HEADER
) +
1447 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1451 // Set base address into the first section header that doesn't point to code section.
1453 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1454 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1455 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1461 // BaseAddress is set to section header.
1469 IN OUT UINT8
*FileBuffer
,
1470 IN UINT64 NewPe32BaseAddress
1474 Routine Description:
1476 Set new base address into PeImage, and fix up PeImage based on new address.
1480 FileName - Name of file
1481 FileBuffer - Pointer to PeImage.
1482 NewPe32BaseAddress - New Base Address for PE image.
1486 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1487 EFI_SUCCESS - Update PeImage is correctly.
1492 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1494 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1495 UINT8
*MemoryImagePointer
;
1496 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1499 // Initialize context
1501 memset (&ImageContext
, 0, sizeof (ImageContext
));
1502 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1503 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1504 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1505 if (EFI_ERROR (Status
)) {
1506 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1510 if (ImageContext
.RelocationsStripped
) {
1511 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1516 // Get PeHeader pointer
1518 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1521 // Load and Relocate Image Data
1523 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1524 if (MemoryImagePointer
== NULL
) {
1525 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1526 return EFI_OUT_OF_RESOURCES
;
1528 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1529 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1531 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1532 if (EFI_ERROR (Status
)) {
1533 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1534 free ((VOID
*) MemoryImagePointer
);
1538 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1539 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1540 if (EFI_ERROR (Status
)) {
1541 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1542 free ((VOID
*) MemoryImagePointer
);
1547 // Copy Relocated data to raw image file.
1549 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1552 sizeof (EFI_IMAGE_FILE_HEADER
) +
1553 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1556 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1558 FileBuffer
+ SectionHeader
->PointerToRawData
,
1559 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1560 SectionHeader
->SizeOfRawData
1564 free ((VOID
*) MemoryImagePointer
);
1567 // Update Image Base Address
1569 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1570 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1571 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1572 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1574 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1575 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1582 // Set new base address into section header
1584 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1591 IN CHAR8
* DefaultPath
,
1592 IN CHAR8
* AppendPath
,
1596 UINT32 DefaultPathLen
;
1598 CHAR8 QuotesStr
[] = "\"";
1599 strcpy(NewPath
, QuotesStr
);
1600 DefaultPathLen
= strlen(DefaultPath
);
1601 strcat(NewPath
, DefaultPath
);
1603 for (; Index
< DefaultPathLen
+ 1; Index
++) {
1604 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1605 if (NewPath
[Index
+ 1] != '\0') {
1606 NewPath
[Index
] = '/';
1610 if (NewPath
[Index
-1] != '/') {
1611 NewPath
[Index
] = '/';
1612 NewPath
[Index
+ 1] = '\0';
1614 strcat(NewPath
, AppendPath
);
1615 strcat(NewPath
, QuotesStr
);
1621 IN UINT8
*SectionBuffer
,
1622 IN UINT32 BufferLength
1626 Routine Description:
1632 SectionBuffer - Buffer containing the section to parse.
1633 BufferLength - Length of SectionBuffer
1637 EFI_SECTION_ERROR - Problem with section parsing.
1638 (a) compression errors
1639 (b) unrecognized section
1640 EFI_UNSUPPORTED - Do not know how to parse the section.
1641 EFI_SUCCESS - Section successfully parsed.
1642 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1646 EFI_SECTION_TYPE Type
;
1648 UINT32 SectionLength
;
1649 UINT32 SectionHeaderLen
;
1652 UINT32 ParsedLength
;
1653 UINT8
*CompressedBuffer
;
1654 UINT32 CompressedLength
;
1655 UINT8
*UncompressedBuffer
;
1656 UINT32 UncompressedLength
;
1657 UINT8
*ToolOutputBuffer
;
1658 UINT32 ToolOutputLength
;
1659 UINT8 CompressionType
;
1662 UINT8
*ScratchBuffer
;
1663 DECOMPRESS_FUNCTION DecompressFunction
;
1664 GETINFO_FUNCTION GetInfoFunction
;
1666 CHAR8
*ExtractionTool
;
1667 CHAR8
*ToolInputFile
;
1668 CHAR8
*ToolOutputFile
;
1669 CHAR8
*SystemCommand
;
1674 CHAR8
*ToolInputFileName
;
1675 CHAR8
*ToolOutputFileName
;
1677 CHAR8
*VersionString
;
1680 ToolInputFileName
= NULL
;
1681 ToolOutputFileName
= NULL
;
1683 while (ParsedLength
< BufferLength
) {
1684 Ptr
= SectionBuffer
+ ParsedLength
;
1686 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1687 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1690 // This is sort of an odd check, but is necessary because FFS files are
1691 // padded to a QWORD boundary, meaning there is potentially a whole section
1692 // header worth of 0xFF bytes.
1694 if (SectionLength
== 0xffffff && Type
== 0xff) {
1700 // Get real section file size
1702 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1703 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1705 SectionName
= SectionNameToStr (Type
);
1706 if (SectionName
!= NULL
) {
1707 printf ("------------------------------------------------------------\n");
1708 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1713 case EFI_SECTION_RAW
:
1714 case EFI_SECTION_PIC
:
1715 case EFI_SECTION_TE
:
1716 // default is no more information
1719 case EFI_SECTION_PE32
:
1721 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1722 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1723 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1726 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1727 SectionLength
- SectionHeaderLen
1730 SystemCommand
= malloc (
1731 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1732 strlen (OpenSslPath
) +
1733 strlen (ToolInputFileName
) +
1734 strlen (ToolOutputFileName
) +
1737 if (SystemCommand
== NULL
) {
1738 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1739 return EFI_OUT_OF_RESOURCES
;
1743 OPENSSL_COMMAND_FORMAT_STRING
,
1749 if (system (SystemCommand
) != EFI_SUCCESS
) {
1750 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1757 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1758 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1761 fseek(fp
,0,SEEK_SET
);
1762 fseek(fp
,0,SEEK_END
);
1763 nFileLen
= ftell(fp
);
1764 fseek(fp
,0,SEEK_SET
);
1765 StrLine
= malloc(nFileLen
);
1766 if (StrLine
== NULL
) {
1768 free (SystemCommand
);
1769 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1770 return EFI_OUT_OF_RESOURCES
;
1772 fgets(StrLine
, nFileLen
, fp
);
1773 NewStr
= strrchr (StrLine
, '=');
1774 printf (" SHA1: %s\n", NewStr
+ 1);
1779 remove(ToolInputFileName
);
1780 remove(ToolOutputFileName
);
1781 free (SystemCommand
);
1785 case EFI_SECTION_USER_INTERFACE
:
1786 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1787 if (UIFileName
== NULL
) {
1788 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1789 return EFI_OUT_OF_RESOURCES
;
1791 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1792 printf (" String: %s\n", UIFileName
);
1796 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1797 printf ("/------------ Firmware Volume section start ---------------\\\n");
1798 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1799 if (EFI_ERROR (Status
)) {
1800 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1801 return EFI_SECTION_ERROR
;
1803 printf ("\\------------ Firmware Volume section end -----------------/\n");
1806 case EFI_SECTION_COMPATIBILITY16
:
1808 // Section does not contain any further header information.
1812 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1814 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
))
1815 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION
*)Ptr
)->SubTypeGuid
);
1817 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION2
*)Ptr
)->SubTypeGuid
);
1821 case EFI_SECTION_PEI_DEPEX
:
1822 case EFI_SECTION_DXE_DEPEX
:
1823 case EFI_SECTION_SMM_DEPEX
:
1824 DumpDepexSection (Ptr
, SectionLength
);
1827 case EFI_SECTION_VERSION
:
1828 printf (" Build Number: 0x%04X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1829 VersionString
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
) + 1);
1830 if (VersionString
== NULL
) {
1831 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1832 return EFI_OUT_OF_RESOURCES
;
1834 Unicode2AsciiString (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
, VersionString
);
1835 printf (" Version String: %s\n", VersionString
);
1838 case EFI_SECTION_COMPRESSION
:
1839 UncompressedBuffer
= NULL
;
1840 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1841 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1842 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1843 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1845 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1846 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1847 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1849 CompressedLength
= SectionLength
- RealHdrLen
;
1850 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1852 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1853 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1854 if (CompressedLength
!= UncompressedLength
) {
1859 "file is not compressed, but the compressed length does not match the uncompressed length",
1862 return EFI_SECTION_ERROR
;
1865 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1866 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1867 GetInfoFunction
= EfiGetInfo
;
1868 DecompressFunction
= EfiDecompress
;
1869 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1871 CompressedBuffer
= Ptr
+ RealHdrLen
;
1873 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1874 if (EFI_ERROR (Status
)) {
1875 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1876 return EFI_SECTION_ERROR
;
1879 if (DstSize
!= UncompressedLength
) {
1880 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1881 return EFI_SECTION_ERROR
;
1884 ScratchBuffer
= malloc (ScratchSize
);
1885 if (ScratchBuffer
== NULL
) {
1886 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1887 return EFI_OUT_OF_RESOURCES
;
1889 UncompressedBuffer
= malloc (UncompressedLength
);
1890 if (UncompressedBuffer
== NULL
) {
1891 free (ScratchBuffer
);
1892 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1893 return EFI_OUT_OF_RESOURCES
;
1895 Status
= DecompressFunction (
1903 free (ScratchBuffer
);
1904 if (EFI_ERROR (Status
)) {
1905 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1906 free (UncompressedBuffer
);
1907 return EFI_SECTION_ERROR
;
1910 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1911 return EFI_SECTION_ERROR
;
1914 printf ("/------------ Encapsulation section start -----------------\\\n");
1915 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1916 printf ("\\------------ Encapsulation section end -------------------/\n");
1918 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1920 // We need to deallocate Buffer
1922 free (UncompressedBuffer
);
1925 if (EFI_ERROR (Status
)) {
1926 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1927 return EFI_SECTION_ERROR
;
1931 case EFI_SECTION_GUID_DEFINED
:
1932 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1933 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1934 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1935 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1937 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1938 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1939 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1941 printf (" SectionDefinitionGuid: ");
1942 PrintGuid (EfiGuid
);
1944 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1945 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1948 LookupGuidedSectionToolPath (
1949 mParsedGuidedSectionTools
,
1953 if (ExtractionTool
!= NULL
) {
1955 ToolInputFile
= CloneString (tmpnam (NULL
));
1956 ToolOutputFile
= CloneString (tmpnam (NULL
));
1958 char tmp1
[] = "/tmp/fileXXXXXX";
1959 char tmp2
[] = "/tmp/fileXXXXXX";
1962 fd1
= mkstemp(tmp1
);
1963 fd2
= mkstemp(tmp2
);
1964 ToolInputFile
= CloneString(tmp1
);
1965 ToolOutputFile
= CloneString(tmp2
);
1970 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1971 if (ToolInputFile
!= NULL
) {
1972 free (ToolInputFile
);
1974 if (ToolOutputFile
!= NULL
) {
1975 free (ToolOutputFile
);
1977 free (ExtractionTool
);
1979 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1980 return EFI_OUT_OF_RESOURCES
;
1984 // Construction 'system' command string
1986 SystemCommand
= malloc (
1987 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1988 strlen (ExtractionTool
) +
1989 strlen (ToolInputFile
) +
1990 strlen (ToolOutputFile
) +
1993 if (SystemCommand
== NULL
) {
1994 free (ToolInputFile
);
1995 free (ToolOutputFile
);
1996 free (ExtractionTool
);
1998 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1999 return EFI_OUT_OF_RESOURCES
;
2003 EXTRACT_COMMAND_FORMAT_STRING
,
2008 free (ExtractionTool
);
2012 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2020 (CHAR8
*)Ptr
+ DataOffset
,
2021 SectionLength
- DataOffset
2024 system (SystemCommand
);
2025 remove (ToolInputFile
);
2026 free (ToolInputFile
);
2031 (CHAR8
**)&ToolOutputBuffer
,
2034 remove (ToolOutputFile
);
2035 free (ToolOutputFile
);
2036 free (SystemCommand
);
2037 if (EFI_ERROR (Status
)) {
2038 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2039 return EFI_SECTION_ERROR
;
2042 printf ("/------------ Encapsulation section start -----------------\\\n");
2043 Status
= ParseSection (
2047 if (EFI_ERROR (Status
)) {
2048 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2049 return EFI_SECTION_ERROR
;
2051 printf ("\\------------ Encapsulation section end -------------------/\n");
2054 // Check for CRC32 sections which we can handle internally if needed.
2056 } else if (!CompareGuid (
2058 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2062 // CRC32 guided section
2064 printf ("/------------ Encapsulation section start -----------------\\\n");
2065 Status
= ParseSection (
2067 SectionLength
- DataOffset
2069 if (EFI_ERROR (Status
)) {
2070 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2071 return EFI_SECTION_ERROR
;
2073 printf ("\\------------ Encapsulation section end -------------------/\n");
2076 // We don't know how to parse it now.
2078 Error (NULL
, 0, 0003, "Error parsing section", \
2079 "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).");
2080 return EFI_UNSUPPORTED
;
2086 // Unknown section, return error
2088 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2089 return EFI_SECTION_ERROR
;
2092 ParsedLength
+= SectionLength
;
2094 // We make then next section begin on a 4-byte boundary
2096 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2099 if (ParsedLength
< BufferLength
) {
2100 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2101 return EFI_SECTION_ERROR
;
2110 IN UINT32 SectionLength
2114 Routine Description:
2116 GC_TODO: Add function description
2120 Ptr - GC_TODO: add argument description
2121 SectionLength - GC_TODO: add argument description
2125 EFI_SUCCESS - GC_TODO: Add description for return value
2129 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2132 // Need at least a section header + data
2134 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2138 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2139 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2140 while (SectionLength
> 0) {
2143 case EFI_DEP_BEFORE
:
2144 printf ("BEFORE\n");
2157 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2158 printf ("%s ", GuidBuffer
);
2159 PrintGuidName (GuidBuffer
);
2162 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2165 SectionLength
-= 17;
2199 printf ("END DEPEX\n");
2211 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2225 Routine Description:
2227 GC_TODO: Add function description
2231 GuidStr - GC_TODO: add argument description
2235 EFI_SUCCESS - GC_TODO: Add description for return value
2236 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2240 GUID_TO_BASENAME
*GPtr
;
2242 // If we have a list of guid-to-basenames, then go through the list to
2243 // look for a guid string match. If found, print the basename to stdout,
2244 // otherwise return a failure.
2246 GPtr
= mGuidBaseNameList
;
2247 while (GPtr
!= NULL
) {
2248 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2249 printf ("%s", GPtr
->BaseName
);
2256 return EFI_INVALID_PARAMETER
;
2260 ParseGuidBaseNameFile (
2265 Routine Description:
2267 GC_TODO: Add function description
2271 FileName - GC_TODO: add argument description
2275 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2276 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2277 EFI_SUCCESS - GC_TODO: Add description for return value
2282 CHAR8 Line
[MAX_LINE_LEN
];
2283 CHAR8 FormatString
[MAX_LINE_LEN
];
2284 GUID_TO_BASENAME
*GPtr
;
2286 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2287 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2288 return EFI_DEVICE_ERROR
;
2292 // Generate the format string for fscanf
2297 (unsigned) sizeof (GPtr
->Guid
) - 1,
2298 (unsigned) sizeof (GPtr
->BaseName
) - 1
2301 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2303 // Allocate space for another guid/basename element
2305 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2308 return EFI_OUT_OF_RESOURCES
;
2311 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2312 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2313 GPtr
->Next
= mGuidBaseNameList
;
2314 mGuidBaseNameList
= GPtr
;
2317 // Some sort of error. Just continue.
2328 FreeGuidBaseNameList (
2333 Routine Description:
2335 GC_TODO: Add function description
2343 EFI_SUCCESS - GC_TODO: Add description for return value
2347 GUID_TO_BASENAME
*Next
;
2349 while (mGuidBaseNameList
!= NULL
) {
2350 Next
= mGuidBaseNameList
->Next
;
2351 free (mGuidBaseNameList
);
2352 mGuidBaseNameList
= Next
;
2361 LoadGuidedSectionToolsTxt (
2362 IN CHAR8
* FirmwareVolumeFilename
2365 CHAR8
* PeerFilename
;
2372 Places
[0] = FirmwareVolumeFilename
;
2373 //Places[1] = mUtilityFilename;
2375 mParsedGuidedSectionTools
= NULL
;
2377 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2378 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2379 //printf("Loading %s...\n", PeerFilename);
2380 if (OsPathExists (PeerFilename
)) {
2381 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2383 free (PeerFilename
);
2384 if (mParsedGuidedSectionTools
!= NULL
) {
2397 Routine Description:
2399 GC_TODO: Add function description
2407 GC_TODO: add return values
2414 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2417 // Copyright declaration
2419 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
2420 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2425 fprintf (stdout
, "optional arguments:\n");
2426 fprintf (stdout
, " -h, --help\n\
2427 Show this help message and exit\n");
2428 fprintf (stdout
, " --version\n\
2429 Show program's version number and exit\n");
2430 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2431 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2432 fprintf (stdout
, " -v, --verbose\n\
2433 Print informational statements\n");
2434 fprintf (stdout
, " -q, --quiet\n\
2435 Returns the exit code, error messages will be displayed\n");
2436 fprintf (stdout
, " -s, --silent\n\
2437 Returns only the exit code; informational and error\n\
2438 messages are not displayed\n");
2439 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2440 Parse the basename to file-guid cross reference file(s)\n");
2441 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2442 The offset from the start of the input file to start \n\
2443 processing an FV\n");
2444 fprintf (stdout
, " --hash\n\
2445 Generate HASH value of the entire PE image\n");
2446 fprintf (stdout
, " --sfo\n\
2447 Reserved for future use\n");