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)
54 #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable
57 // Structure to keep a list of guid-to-basenames
59 typedef struct _GUID_TO_BASENAME
{
60 struct _GUID_TO_BASENAME
*Next
;
61 INT8 Guid
[PRINTED_GUID_BUFFER_SIZE
];
62 INT8 BaseName
[MAX_BASENAME_LEN
];
65 static GUID_TO_BASENAME
*mGuidBaseNameList
= NULL
;
68 // Store GUIDed Section guid->tool mapping
70 EFI_HANDLE mParsedGuidedSectionTools
= NULL
;
72 CHAR8
* mUtilityFilename
= NULL
;
74 BOOLEAN EnableHash
= FALSE
;
75 CHAR8
*OpenSslPath
= NULL
;
78 ParseGuidBaseNameFile (
83 FreeGuidBaseNameList (
94 IN UINT8
*SectionBuffer
,
95 IN UINT32 BufferLength
101 IN UINT32 SectionLength
109 OUT BOOLEAN
*ErasePolarity
115 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
116 EFI_FFS_FILE_HEADER
*FileHeader
,
117 BOOLEAN ErasePolarity
129 LoadGuidedSectionToolsTxt (
130 IN CHAR8
* FirmwareVolumeFilename
135 IN CHAR8
* DefaultPath
,
136 IN CHAR8
* AppendPath
,
153 Returns the length of a null-terminated unicode string.
157 String - The pointer to a null-terminated unicode string.
167 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++) {
174 Unicode2AsciiString (
176 OUT CHAR8
*Destination
182 Convert a null-terminated unicode string to a null-terminated ascii string.
186 Source - The pointer to the null-terminated input unicode string.
187 Destination - The pointer to the null-terminated output ascii string.
195 while (*Source
!= '\0') {
196 *(Destination
++) = (CHAR8
) *(Source
++);
199 // End the ascii with a NULL.
213 GC_TODO: Add function description
217 argc - GC_TODO: add argument description
218 ] - GC_TODO: add argument description
222 GC_TODO: add return values
228 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
232 BOOLEAN ErasePolarity
;
235 CHAR8
*OpenSslCommand
;
237 SetUtilityName (UTILITY_NAME
);
239 // Print utility header
241 printf ("%s Version %d.%d Build %s\n",
243 UTILITY_MAJOR_VERSION
,
244 UTILITY_MINOR_VERSION
,
259 // Look for help options
261 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
262 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
264 return STATUS_SUCCESS
;
267 // Version has already be printed, so just return success
269 if (strcmp(argv
[0], "--version") == 0) {
270 return STATUS_SUCCESS
;
274 // If they specified -x xref guid/basename cross-reference files, process it.
275 // This will print the basename beside each file guid. To use it, specify
276 // -x xref_filename to processdsc, then use xref_filename as a parameter
280 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
281 ParseGuidBaseNameFile (argv
[1]);
282 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
287 if (strcmp(argv
[0], "--offset") == 0) {
291 if ((argv
[1][0] == '0') && (tolower ((int)argv
[1][1]) == 'x')) {
292 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
293 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
294 return GetUtilityStatus ();
297 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
298 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
299 return GetUtilityStatus ();
302 // See if they said something like "64K"
304 if (tolower ((int)argv
[1][strlen (argv
[1]) - 1]) == 'k') {
313 if ((stricmp (argv
[0], "--hash") == 0)) {
314 if (EnableHash
== TRUE
) {
316 // --hash already given in the option, ignore this one
323 OpenSslCommand
= "openssl";
324 OpenSslEnv
= getenv("OPENSSL_PATH");
325 if (OpenSslEnv
== NULL
) {
326 OpenSslPath
= OpenSslCommand
;
329 // We add quotes to the Openssl Path in case it has space characters
331 OpenSslPath
= malloc(2+strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
332 if (OpenSslPath
== NULL
) {
333 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
334 return GetUtilityStatus ();
336 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
338 if (OpenSslPath
== NULL
){
339 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
340 return GetUtilityStatus ();
347 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
348 SetPrintLevel (VERBOSE_LOG_LEVEL
);
354 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
355 SetPrintLevel (KEY_LOG_LEVEL
);
361 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
362 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
363 if (EFI_ERROR (Status
)) {
364 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
368 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
371 SetPrintLevel (LogLevel
);
372 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
378 mUtilityFilename
= argv
[0];
384 // Open the file containing the FV
386 if (mUtilityFilename
== NULL
) {
387 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
388 return GetUtilityStatus ();
390 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
391 if (InputFile
== NULL
) {
392 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
393 return GetUtilityStatus ();
396 // Skip over pad bytes if specified. This is used if they prepend 0xff
397 // data to the FV image binary.
400 fseek (InputFile
, Offset
, SEEK_SET
);
403 // Determine size of FV
405 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
406 if (EFI_ERROR (Status
)) {
407 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
409 return GetUtilityStatus ();
412 // Allocate a buffer for the FV image
414 FvImage
= malloc (FvSize
);
415 if (FvImage
== NULL
) {
416 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
418 return GetUtilityStatus ();
421 // Seek to the start of the image, then read the entire FV to the buffer
423 fseek (InputFile
, Offset
, SEEK_SET
);
424 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
426 if ((unsigned int) BytesRead
!= FvSize
) {
427 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
429 return GetUtilityStatus ();
432 LoadGuidedSectionToolsTxt (mUtilityFilename
);
434 PrintFvInfo (FvImage
, FALSE
);
440 FreeGuidBaseNameList ();
441 return GetUtilityStatus ();
455 GC_TODO: Add function description
459 Fv - Firmware Volume to print information about
460 IsChildFv - Flag specifies whether the input FV is a child FV.
470 BOOLEAN ErasePolarity
;
472 EFI_FFS_FILE_HEADER
*CurrentFile
;
475 Status
= FvBufGetSize (Fv
, &FvSize
);
479 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
483 // Get the first file
486 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
487 if (EFI_ERROR (Status
)) {
488 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
489 return GetUtilityStatus ();
492 // Display information about files found
494 while (CurrentFile
!= NULL
) {
496 // Increment the number of files counter
501 // Display info about this file
503 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
504 if (EFI_ERROR (Status
)) {
505 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
506 return GetUtilityStatus ();
511 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
512 if (Status
== EFI_NOT_FOUND
) {
514 } else if (EFI_ERROR (Status
)) {
515 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
516 return GetUtilityStatus ();
521 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
523 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
531 IN UINT32 ActualSize
,
538 This function returns the next larger size that meets the alignment
539 requirement specified.
544 Alignment The desired alignment.
548 EFI_SUCCESS Function completed successfully.
549 EFI_ABORTED The function encountered an error.
555 OccupiedSize
= ActualSize
;
556 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
566 IN EFI_SECTION_TYPE Type
572 Converts EFI Section names to Strings
576 Type - The EFI Section type
580 CHAR8* - Pointer to the String containing the section name.
585 CHAR8
*SectionTypeStringTable
[] = {
593 "EFI_SECTION_COMPRESSION",
597 "EFI_SECTION_GUID_DEFINED",
601 "Unknown section type - Reserved 0x03",
605 "Unknown section type - Reserved 0x04",
609 "Unknown section type - Reserved 0x05",
613 "Unknown section type - Reserved 0x06",
617 "Unknown section type - Reserved 0x07",
621 "Unknown section type - Reserved 0x08",
625 "Unknown section type - Reserved 0x09",
629 "Unknown section type - Reserved 0x0A",
633 "Unknown section type - Reserved 0x0B",
637 "Unknown section type - Reserved 0x0C",
641 "Unknown section type - Reserved 0x0D",
645 "Unknown section type - Reserved 0x0E",
649 "Unknown section type - Reserved 0x0E",
665 "EFI_SECTION_DXE_DEPEX",
669 "EFI_SECTION_VERSION",
673 "EFI_SECTION_USER_INTERFACE",
677 "EFI_SECTION_COMPATIBILITY16",
681 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
685 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
693 "Unknown section type - 0x1A",
697 "EFI_SECTION_PEI_DEPEX",
701 "EFI_SECTION_SMM_DEPEX",
705 "Unknown section type - Reserved - beyond last defined section"
708 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
709 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
712 SectionStr
= malloc (100);
713 if (SectionStr
== NULL
) {
714 printf ("Error: Out of memory resources.\n");
717 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
726 OUT BOOLEAN
*ErasePolarity
732 This function determines the size of the FV and the erase polarity. The
733 erase polarity is the FALSE value for file state.
737 InputFile The file that contains the FV image.
738 FvSize The size of the FV.
739 ErasePolarity The FV erase polarity.
743 EFI_SUCCESS Function completed successfully.
744 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
745 EFI_ABORTED The function encountered an error.
749 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
750 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
759 // Check input parameters
761 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
762 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
763 return EFI_INVALID_PARAMETER
;
768 ReadSize
= fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
772 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
773 Signature
[0] = VolumeHeader
.Signature
;
777 // Print FV header information
779 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
780 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
782 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
783 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
786 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
787 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
790 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
791 printf (" EFI_FVB2_READ_STATUS\n");
794 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
795 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
798 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
799 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
802 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
803 printf (" EFI_FVB2_WRITE_STATUS\n");
806 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
807 printf (" EFI_FVB2_LOCK_CAP\n");
810 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
811 printf (" EFI_FVB2_LOCK_STATUS\n");
814 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
815 printf (" EFI_FVB2_STICKY_WRITE\n");
818 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
819 printf (" EFI_FVB2_MEMORY_MAPPED\n");
822 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
823 printf (" EFI_FVB2_ERASE_POLARITY\n");
824 *ErasePolarity
= TRUE
;
827 #if (PI_SPECIFICATION_VERSION < 0x00010000)
828 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
829 printf (" EFI_FVB2_ALIGNMENT\n");
832 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
833 printf (" EFI_FVB2_ALIGNMENT_2\n");
836 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
837 printf (" EFI_FVB2_ALIGNMENT_4\n");
840 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
841 printf (" EFI_FVB2_ALIGNMENT_8\n");
844 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
845 printf (" EFI_FVB2_ALIGNMENT_16\n");
848 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
849 printf (" EFI_FVB2_ALIGNMENT_32\n");
852 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
853 printf (" EFI_FVB2_ALIGNMENT_64\n");
856 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
857 printf (" EFI_FVB2_ALIGNMENT_128\n");
860 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
861 printf (" EFI_FVB2_ALIGNMENT_256\n");
864 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
865 printf (" EFI_FVB2_ALIGNMENT_512\n");
868 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
869 printf (" EFI_FVB2_ALIGNMENT_1K\n");
872 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
873 printf (" EFI_FVB2_ALIGNMENT_2K\n");
876 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
877 printf (" EFI_FVB2_ALIGNMENT_4K\n");
880 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
881 printf (" EFI_FVB2_ALIGNMENT_8K\n");
884 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
885 printf (" EFI_FVB2_ALIGNMENT_16K\n");
888 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
889 printf (" EFI_FVB2_ALIGNMENT_32K\n");
892 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
893 printf (" EFI_FVB2_ALIGNMENT_64K\n");
898 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
899 printf (" EFI_FVB2_READ_LOCK_CAP\n");
902 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
903 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
906 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
907 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
910 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
911 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
914 switch (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
915 case EFI_FVB2_ALIGNMENT_1
:
916 printf (" EFI_FVB2_ALIGNMENT_1\n");
919 case EFI_FVB2_ALIGNMENT_2
:
920 printf (" EFI_FVB2_ALIGNMENT_2\n");
923 case EFI_FVB2_ALIGNMENT_4
:
924 printf (" EFI_FVB2_ALIGNMENT_4\n");
927 case EFI_FVB2_ALIGNMENT_8
:
928 printf (" EFI_FVB2_ALIGNMENT_8\n");
931 case EFI_FVB2_ALIGNMENT_16
:
932 printf (" EFI_FVB2_ALIGNMENT_16\n");
935 case EFI_FVB2_ALIGNMENT_32
:
936 printf (" EFI_FVB2_ALIGNMENT_32\n");
939 case EFI_FVB2_ALIGNMENT_64
:
940 printf (" EFI_FVB2_ALIGNMENT_64\n");
943 case EFI_FVB2_ALIGNMENT_128
:
944 printf (" EFI_FVB2_ALIGNMENT_128\n");
947 case EFI_FVB2_ALIGNMENT_256
:
948 printf (" EFI_FVB2_ALIGNMENT_256\n");
951 case EFI_FVB2_ALIGNMENT_512
:
952 printf (" EFI_FVB2_ALIGNMENT_512\n");
955 case EFI_FVB2_ALIGNMENT_1K
:
956 printf (" EFI_FVB2_ALIGNMENT_1K\n");
959 case EFI_FVB2_ALIGNMENT_2K
:
960 printf (" EFI_FVB2_ALIGNMENT_2K\n");
963 case EFI_FVB2_ALIGNMENT_4K
:
964 printf (" EFI_FVB2_ALIGNMENT_4K\n");
967 case EFI_FVB2_ALIGNMENT_8K
:
968 printf (" EFI_FVB2_ALIGNMENT_8K\n");
971 case EFI_FVB2_ALIGNMENT_16K
:
972 printf (" EFI_FVB2_ALIGNMENT_16K\n");
975 case EFI_FVB2_ALIGNMENT_32K
:
976 printf (" EFI_FVB2_ALIGNMENT_32K\n");
979 case EFI_FVB2_ALIGNMENT_64K
:
980 printf (" EFI_FVB2_ALIGNMENT_64K\n");
983 case EFI_FVB2_ALIGNMENT_128K
:
984 printf (" EFI_FVB2_ALIGNMENT_128K\n");
987 case EFI_FVB2_ALIGNMENT_256K
:
988 printf (" EFI_FVB2_ALIGNMENT_256K\n");
991 case EFI_FVB2_ALIGNMENT_512K
:
992 printf (" EFI_FVB2_ALIGNMENT_512K\n");
995 case EFI_FVB2_ALIGNMENT_1M
:
996 printf (" EFI_FVB2_ALIGNMENT_1M\n");
999 case EFI_FVB2_ALIGNMENT_2M
:
1000 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1003 case EFI_FVB2_ALIGNMENT_4M
:
1004 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1007 case EFI_FVB2_ALIGNMENT_8M
:
1008 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1011 case EFI_FVB2_ALIGNMENT_16M
:
1012 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1015 case EFI_FVB2_ALIGNMENT_32M
:
1016 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1019 case EFI_FVB2_ALIGNMENT_64M
:
1020 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1023 case EFI_FVB2_ALIGNMENT_128M
:
1024 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1027 case EFI_FVB2_ALIGNMENT_256M
:
1028 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1031 case EFI_FVB2_ALIGNMENT_512M
:
1032 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1035 case EFI_FVB2_ALIGNMENT_1G
:
1036 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1039 case EFI_FVB2_ALIGNMENT_2G
:
1040 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1045 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1046 printf ("File System ID: ");
1047 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1051 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1054 ReadSize
= fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1055 if (ReadSize
!= 1) {
1058 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1060 if (BlockMap
.NumBlocks
!= 0) {
1061 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1062 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1063 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1066 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1068 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1069 printf ("ERROR: Header length not consistent with Block Maps!\n");
1073 if (VolumeHeader
.FvLength
!= Size
) {
1074 printf ("ERROR: Volume Size not consistent with Block Maps!\n");
1078 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1083 // rewind (InputFile);
1091 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1092 EFI_FFS_FILE_HEADER
*FileHeader
,
1093 BOOLEAN ErasePolarity
1097 Routine Description:
1099 GC_TODO: Add function description
1103 FvImage - GC_TODO: add argument description
1104 FileHeader - GC_TODO: add argument description
1105 ErasePolarity - GC_TODO: add argument description
1109 EFI_SUCCESS - GC_TODO: Add description for return value
1110 EFI_ABORTED - GC_TODO: Add description for return value
1117 EFI_FFS_FILE_HEADER2 BlankHeader
;
1119 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1121 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1125 // Check if we have free space
1127 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1128 if (ErasePolarity
) {
1129 memset (&BlankHeader
, -1, HeaderSize
);
1131 memset (&BlankHeader
, 0, HeaderSize
);
1134 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1138 // Print file information.
1140 printf ("============================================================\n");
1142 printf ("File Name: ");
1143 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1144 printf ("%s ", GuidBuffer
);
1145 PrintGuidName (GuidBuffer
);
1149 // PrintGuid (&FileHeader->Name);
1152 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1153 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1154 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1155 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1156 printf ("File State: 0x%02X\n", FileHeader
->State
);
1161 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1163 switch (FileState
) {
1165 case EFI_FILE_HEADER_CONSTRUCTION
:
1166 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1169 case EFI_FILE_HEADER_INVALID
:
1170 printf (" EFI_FILE_HEADER_INVALID\n");
1173 case EFI_FILE_HEADER_VALID
:
1174 printf (" EFI_FILE_HEADER_VALID\n");
1175 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1176 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1177 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1178 if (Checksum
!= 0) {
1179 printf ("ERROR: Header checksum invalid.\n");
1185 case EFI_FILE_DELETED
:
1186 printf (" EFI_FILE_DELETED\n");
1188 case EFI_FILE_MARKED_FOR_UPDATE
:
1189 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1191 case EFI_FILE_DATA_VALID
:
1192 printf (" EFI_FILE_DATA_VALID\n");
1195 // Calculate header checksum
1197 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1198 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1199 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1200 if (Checksum
!= 0) {
1201 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1205 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1207 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1209 // Calculate file checksum
1211 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1212 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1213 if (Checksum
!= 0) {
1214 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1218 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1219 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
);
1223 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1225 // Verify tail if present
1227 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1229 // Verify tail is complement of integrity check field in the header.
1231 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1232 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1233 Error (NULL
, 0, 0003, "error parsing FFS file", \
1234 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1242 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1246 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1248 switch (FileHeader
->Type
) {
1250 case EFI_FV_FILETYPE_RAW
:
1251 printf ("EFI_FV_FILETYPE_RAW\n");
1254 case EFI_FV_FILETYPE_FREEFORM
:
1255 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1258 case EFI_FV_FILETYPE_SECURITY_CORE
:
1259 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1262 case EFI_FV_FILETYPE_PEI_CORE
:
1263 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1266 case EFI_FV_FILETYPE_DXE_CORE
:
1267 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1270 case EFI_FV_FILETYPE_PEIM
:
1271 printf ("EFI_FV_FILETYPE_PEIM\n");
1274 case EFI_FV_FILETYPE_DRIVER
:
1275 printf ("EFI_FV_FILETYPE_DRIVER\n");
1278 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1279 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1282 case EFI_FV_FILETYPE_APPLICATION
:
1283 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1286 case EFI_FV_FILETYPE_SMM
:
1287 printf ("EFI_FV_FILETYPE_SMM\n");
1290 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1291 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1294 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1295 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1298 case EFI_FV_FILETYPE_SMM_CORE
:
1299 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1302 case EFI_FV_FILETYPE_MM_STANDALONE
:
1303 printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
1306 case EFI_FV_FILETYPE_MM_CORE_STANDALONE
:
1307 printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
1310 case EFI_FV_FILETYPE_FFS_PAD
:
1311 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1315 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1320 switch (FileHeader
->Type
) {
1322 case EFI_FV_FILETYPE_ALL
:
1323 case EFI_FV_FILETYPE_RAW
:
1324 case EFI_FV_FILETYPE_FFS_PAD
:
1329 // All other files have sections
1331 Status
= ParseSection (
1332 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1333 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1335 if (EFI_ERROR (Status
)) {
1337 // printf ("ERROR: Parsing the FFS file.\n");
1349 IN VOID
*FileHandle
,
1350 IN UINTN FileOffset
,
1351 IN OUT UINT32
*ReadSize
,
1356 Routine Description:
1358 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1362 FileHandle - The handle to the PE/COFF file
1364 FileOffset - The offset, in bytes, into the file to read
1366 ReadSize - The number of bytes to read from the file starting at FileOffset
1368 Buffer - A pointer to the buffer to read the data into.
1372 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1376 CHAR8
*Destination8
;
1380 Destination8
= Buffer
;
1381 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1384 *(Destination8
++) = *(Source8
++);
1391 SetAddressToSectionHeader (
1393 IN OUT UINT8
*FileBuffer
,
1394 IN UINT64 NewPe32BaseAddress
1398 Routine Description:
1400 Set new base address into the section header of PeImage
1404 FileName - Name of file
1405 FileBuffer - Pointer to PeImage.
1406 NewPe32BaseAddress - New Base Address for PE image.
1410 EFI_SUCCESS Set new base address into this image successfully.
1415 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1417 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1418 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1421 // Initialize context
1423 memset (&ImageContext
, 0, sizeof (ImageContext
));
1424 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1425 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1426 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1427 if (EFI_ERROR (Status
)) {
1428 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1432 if (ImageContext
.RelocationsStripped
) {
1433 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1438 // Get PeHeader pointer
1440 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1443 // Get section header list
1445 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1448 sizeof (EFI_IMAGE_FILE_HEADER
) +
1449 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1453 // Set base address into the first section header that doesn't point to code section.
1455 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1456 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1457 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1463 // BaseAddress is set to section header.
1471 IN OUT UINT8
*FileBuffer
,
1472 IN UINT64 NewPe32BaseAddress
1476 Routine Description:
1478 Set new base address into PeImage, and fix up PeImage based on new address.
1482 FileName - Name of file
1483 FileBuffer - Pointer to PeImage.
1484 NewPe32BaseAddress - New Base Address for PE image.
1488 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1489 EFI_SUCCESS - Update PeImage is correctly.
1494 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1496 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1497 UINT8
*MemoryImagePointer
;
1498 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1501 // Initialize context
1503 memset (&ImageContext
, 0, sizeof (ImageContext
));
1504 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1505 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1506 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1507 if (EFI_ERROR (Status
)) {
1508 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1512 if (ImageContext
.RelocationsStripped
) {
1513 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1518 // Get PeHeader pointer
1520 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1523 // Load and Relocate Image Data
1525 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1526 if (MemoryImagePointer
== NULL
) {
1527 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1528 return EFI_OUT_OF_RESOURCES
;
1530 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1531 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1533 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1534 if (EFI_ERROR (Status
)) {
1535 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1536 free ((VOID
*) MemoryImagePointer
);
1540 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1541 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1542 if (EFI_ERROR (Status
)) {
1543 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1544 free ((VOID
*) MemoryImagePointer
);
1549 // Copy Relocated data to raw image file.
1551 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1554 sizeof (EFI_IMAGE_FILE_HEADER
) +
1555 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1558 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1560 FileBuffer
+ SectionHeader
->PointerToRawData
,
1561 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1562 SectionHeader
->SizeOfRawData
1566 free ((VOID
*) MemoryImagePointer
);
1569 // Update Image Base Address
1571 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1572 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1573 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1574 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1576 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1577 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1584 // Set new base address into section header
1586 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1593 IN CHAR8
* DefaultPath
,
1594 IN CHAR8
* AppendPath
,
1598 UINT32 DefaultPathLen
;
1600 CHAR8 QuotesStr
[] = "\"";
1601 strcpy(NewPath
, QuotesStr
);
1602 DefaultPathLen
= strlen(DefaultPath
);
1603 strcat(NewPath
, DefaultPath
);
1605 for (; Index
< DefaultPathLen
+ 1; Index
++) {
1606 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1607 if (NewPath
[Index
+ 1] != '\0') {
1608 NewPath
[Index
] = '/';
1612 if (NewPath
[Index
-1] != '/') {
1613 NewPath
[Index
] = '/';
1614 NewPath
[Index
+ 1] = '\0';
1616 strcat(NewPath
, AppendPath
);
1617 strcat(NewPath
, QuotesStr
);
1623 IN UINT8
*SectionBuffer
,
1624 IN UINT32 BufferLength
1628 Routine Description:
1634 SectionBuffer - Buffer containing the section to parse.
1635 BufferLength - Length of SectionBuffer
1639 EFI_SECTION_ERROR - Problem with section parsing.
1640 (a) compression errors
1641 (b) unrecognized section
1642 EFI_UNSUPPORTED - Do not know how to parse the section.
1643 EFI_SUCCESS - Section successfully parsed.
1644 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1648 EFI_SECTION_TYPE Type
;
1650 UINT32 SectionLength
;
1651 UINT32 SectionHeaderLen
;
1654 UINT32 ParsedLength
;
1655 UINT8
*CompressedBuffer
;
1656 UINT32 CompressedLength
;
1657 UINT8
*UncompressedBuffer
;
1658 UINT32 UncompressedLength
;
1659 UINT8
*ToolOutputBuffer
;
1660 UINT32 ToolOutputLength
;
1661 UINT8 CompressionType
;
1664 UINT8
*ScratchBuffer
;
1665 DECOMPRESS_FUNCTION DecompressFunction
;
1666 GETINFO_FUNCTION GetInfoFunction
;
1668 CHAR8
*ExtractionTool
;
1669 CHAR8
*ToolInputFile
;
1670 CHAR8
*ToolOutputFile
;
1671 CHAR8
*SystemCommand
;
1676 CHAR8
*ToolInputFileName
;
1677 CHAR8
*ToolOutputFileName
;
1679 CHAR8
*VersionString
;
1682 ToolInputFileName
= NULL
;
1683 ToolOutputFileName
= NULL
;
1685 while (ParsedLength
< BufferLength
) {
1686 Ptr
= SectionBuffer
+ ParsedLength
;
1688 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1689 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1692 // This is sort of an odd check, but is necessary because FFS files are
1693 // padded to a QWORD boundary, meaning there is potentially a whole section
1694 // header worth of 0xFF bytes.
1696 if (SectionLength
== 0xffffff && Type
== 0xff) {
1702 // Get real section file size
1704 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1705 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1707 SectionName
= SectionNameToStr (Type
);
1708 if (SectionName
!= NULL
) {
1709 printf ("------------------------------------------------------------\n");
1710 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1715 case EFI_SECTION_RAW
:
1716 case EFI_SECTION_PIC
:
1717 case EFI_SECTION_TE
:
1718 // default is no more information
1721 case EFI_SECTION_PE32
:
1723 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1724 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1725 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1728 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1729 SectionLength
- SectionHeaderLen
1732 SystemCommand
= malloc (
1733 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1734 strlen (OpenSslPath
) +
1735 strlen (ToolInputFileName
) +
1736 strlen (ToolOutputFileName
) +
1739 if (SystemCommand
== NULL
) {
1740 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1741 return EFI_OUT_OF_RESOURCES
;
1745 OPENSSL_COMMAND_FORMAT_STRING
,
1751 if (system (SystemCommand
) != EFI_SUCCESS
) {
1752 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1759 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1760 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1763 fseek(fp
,0,SEEK_SET
);
1764 fseek(fp
,0,SEEK_END
);
1765 nFileLen
= ftell(fp
);
1766 fseek(fp
,0,SEEK_SET
);
1767 StrLine
= malloc(nFileLen
);
1768 if (StrLine
== NULL
) {
1770 free (SystemCommand
);
1771 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1772 return EFI_OUT_OF_RESOURCES
;
1774 fgets(StrLine
, nFileLen
, fp
);
1775 NewStr
= strrchr (StrLine
, '=');
1776 printf (" SHA1: %s\n", NewStr
+ 1);
1781 remove(ToolInputFileName
);
1782 remove(ToolOutputFileName
);
1783 free (SystemCommand
);
1787 case EFI_SECTION_USER_INTERFACE
:
1788 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1789 if (UIFileName
== NULL
) {
1790 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1791 return EFI_OUT_OF_RESOURCES
;
1793 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1794 printf (" String: %s\n", UIFileName
);
1798 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1799 printf ("/------------ Firmware Volume section start ---------------\\\n");
1800 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1801 if (EFI_ERROR (Status
)) {
1802 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1803 return EFI_SECTION_ERROR
;
1805 printf ("\\------------ Firmware Volume section end -----------------/\n");
1808 case EFI_SECTION_COMPATIBILITY16
:
1810 // Section does not contain any further header information.
1814 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1816 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
))
1817 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION
*)Ptr
)->SubTypeGuid
);
1819 PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION2
*)Ptr
)->SubTypeGuid
);
1823 case EFI_SECTION_PEI_DEPEX
:
1824 case EFI_SECTION_DXE_DEPEX
:
1825 case EFI_SECTION_SMM_DEPEX
:
1826 DumpDepexSection (Ptr
, SectionLength
);
1829 case EFI_SECTION_VERSION
:
1830 printf (" Build Number: 0x%04X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1831 VersionString
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
) + 1);
1832 if (VersionString
== NULL
) {
1833 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1834 return EFI_OUT_OF_RESOURCES
;
1836 Unicode2AsciiString (((EFI_VERSION_SECTION
*) Ptr
)->VersionString
, VersionString
);
1837 printf (" Version String: %s\n", VersionString
);
1840 case EFI_SECTION_COMPRESSION
:
1841 UncompressedBuffer
= NULL
;
1842 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1843 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1844 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1845 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1847 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1848 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1849 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1851 CompressedLength
= SectionLength
- RealHdrLen
;
1852 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1854 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1855 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1856 if (CompressedLength
!= UncompressedLength
) {
1861 "file is not compressed, but the compressed length does not match the uncompressed length",
1864 return EFI_SECTION_ERROR
;
1867 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1868 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1869 GetInfoFunction
= EfiGetInfo
;
1870 DecompressFunction
= EfiDecompress
;
1871 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1873 CompressedBuffer
= Ptr
+ RealHdrLen
;
1875 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1876 if (EFI_ERROR (Status
)) {
1877 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1878 return EFI_SECTION_ERROR
;
1881 if (DstSize
!= UncompressedLength
) {
1882 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1883 return EFI_SECTION_ERROR
;
1886 ScratchBuffer
= malloc (ScratchSize
);
1887 if (ScratchBuffer
== NULL
) {
1888 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1889 return EFI_OUT_OF_RESOURCES
;
1891 UncompressedBuffer
= malloc (UncompressedLength
);
1892 if (UncompressedBuffer
== NULL
) {
1893 free (ScratchBuffer
);
1894 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1895 return EFI_OUT_OF_RESOURCES
;
1897 Status
= DecompressFunction (
1905 free (ScratchBuffer
);
1906 if (EFI_ERROR (Status
)) {
1907 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1908 free (UncompressedBuffer
);
1909 return EFI_SECTION_ERROR
;
1912 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1913 return EFI_SECTION_ERROR
;
1916 printf ("/------------ Encapsulation section start -----------------\\\n");
1917 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1918 printf ("\\------------ Encapsulation section end -------------------/\n");
1920 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1922 // We need to deallocate Buffer
1924 free (UncompressedBuffer
);
1927 if (EFI_ERROR (Status
)) {
1928 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1929 return EFI_SECTION_ERROR
;
1933 case EFI_SECTION_GUID_DEFINED
:
1934 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1935 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1936 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1937 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1939 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1940 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1941 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1943 printf (" SectionDefinitionGuid: ");
1944 PrintGuid (EfiGuid
);
1946 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1947 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1950 LookupGuidedSectionToolPath (
1951 mParsedGuidedSectionTools
,
1955 if (ExtractionTool
!= NULL
) {
1957 ToolInputFile
= CloneString (tmpnam (NULL
));
1958 ToolOutputFile
= CloneString (tmpnam (NULL
));
1960 char tmp1
[] = "/tmp/fileXXXXXX";
1961 char tmp2
[] = "/tmp/fileXXXXXX";
1964 fd1
= mkstemp(tmp1
);
1965 fd2
= mkstemp(tmp2
);
1966 ToolInputFile
= CloneString(tmp1
);
1967 ToolOutputFile
= CloneString(tmp2
);
1972 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1973 if (ToolInputFile
!= NULL
) {
1974 free (ToolInputFile
);
1976 if (ToolOutputFile
!= NULL
) {
1977 free (ToolOutputFile
);
1979 free (ExtractionTool
);
1981 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1982 return EFI_OUT_OF_RESOURCES
;
1986 // Construction 'system' command string
1988 SystemCommand
= malloc (
1989 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1990 strlen (ExtractionTool
) +
1991 strlen (ToolInputFile
) +
1992 strlen (ToolOutputFile
) +
1995 if (SystemCommand
== NULL
) {
1996 free (ToolInputFile
);
1997 free (ToolOutputFile
);
1998 free (ExtractionTool
);
2000 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
2001 return EFI_OUT_OF_RESOURCES
;
2005 EXTRACT_COMMAND_FORMAT_STRING
,
2010 free (ExtractionTool
);
2015 (CHAR8
*) SectionBuffer
+ DataOffset
,
2016 BufferLength
- DataOffset
2019 system (SystemCommand
);
2020 remove (ToolInputFile
);
2021 free (ToolInputFile
);
2026 (CHAR8
**)&ToolOutputBuffer
,
2029 remove (ToolOutputFile
);
2030 free (ToolOutputFile
);
2031 free (SystemCommand
);
2032 if (EFI_ERROR (Status
)) {
2033 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2034 return EFI_SECTION_ERROR
;
2037 printf ("/------------ Encapsulation section start -----------------\\\n");
2038 Status
= ParseSection (
2042 if (EFI_ERROR (Status
)) {
2043 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2044 return EFI_SECTION_ERROR
;
2046 printf ("\\------------ Encapsulation section end -------------------/\n");
2049 // Check for CRC32 sections which we can handle internally if needed.
2051 } else if (!CompareGuid (
2053 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2057 // CRC32 guided section
2059 printf ("/------------ Encapsulation section start -----------------\\\n");
2060 Status
= ParseSection (
2061 SectionBuffer
+ DataOffset
,
2062 BufferLength
- DataOffset
2064 if (EFI_ERROR (Status
)) {
2065 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2066 return EFI_SECTION_ERROR
;
2068 printf ("\\------------ Encapsulation section end -------------------/\n");
2071 // We don't know how to parse it now.
2073 Error (NULL
, 0, 0003, "Error parsing section", \
2074 "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).");
2075 return EFI_UNSUPPORTED
;
2081 // Unknown section, return error
2083 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2084 return EFI_SECTION_ERROR
;
2087 ParsedLength
+= SectionLength
;
2089 // We make then next section begin on a 4-byte boundary
2091 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2094 if (ParsedLength
< BufferLength
) {
2095 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2096 return EFI_SECTION_ERROR
;
2105 IN UINT32 SectionLength
2109 Routine Description:
2111 GC_TODO: Add function description
2115 Ptr - GC_TODO: add argument description
2116 SectionLength - GC_TODO: add argument description
2120 EFI_SUCCESS - GC_TODO: Add description for return value
2124 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2127 // Need at least a section header + data
2129 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2133 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2134 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2135 while (SectionLength
> 0) {
2138 case EFI_DEP_BEFORE
:
2139 printf ("BEFORE\n");
2152 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2153 printf ("%s ", GuidBuffer
);
2154 PrintGuidName (GuidBuffer
);
2157 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2160 SectionLength
-= 17;
2194 printf ("END DEPEX\n");
2206 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2220 Routine Description:
2222 GC_TODO: Add function description
2226 GuidStr - GC_TODO: add argument description
2230 EFI_SUCCESS - GC_TODO: Add description for return value
2231 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2235 GUID_TO_BASENAME
*GPtr
;
2237 // If we have a list of guid-to-basenames, then go through the list to
2238 // look for a guid string match. If found, print the basename to stdout,
2239 // otherwise return a failure.
2241 GPtr
= mGuidBaseNameList
;
2242 while (GPtr
!= NULL
) {
2243 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2244 printf ("%s", GPtr
->BaseName
);
2251 return EFI_INVALID_PARAMETER
;
2255 ParseGuidBaseNameFile (
2260 Routine Description:
2262 GC_TODO: Add function description
2266 FileName - GC_TODO: add argument description
2270 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2271 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2272 EFI_SUCCESS - GC_TODO: Add description for return value
2277 CHAR8 Line
[MAX_LINE_LEN
];
2278 CHAR8 FormatString
[MAX_LINE_LEN
];
2279 GUID_TO_BASENAME
*GPtr
;
2281 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2282 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2283 return EFI_DEVICE_ERROR
;
2287 // Generate the format string for fscanf
2292 (unsigned) sizeof (GPtr
->Guid
) - 1,
2293 (unsigned) sizeof (GPtr
->BaseName
) - 1
2296 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2298 // Allocate space for another guid/basename element
2300 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2303 return EFI_OUT_OF_RESOURCES
;
2306 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2307 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2308 GPtr
->Next
= mGuidBaseNameList
;
2309 mGuidBaseNameList
= GPtr
;
2312 // Some sort of error. Just continue.
2323 FreeGuidBaseNameList (
2328 Routine Description:
2330 GC_TODO: Add function description
2338 EFI_SUCCESS - GC_TODO: Add description for return value
2342 GUID_TO_BASENAME
*Next
;
2344 while (mGuidBaseNameList
!= NULL
) {
2345 Next
= mGuidBaseNameList
->Next
;
2346 free (mGuidBaseNameList
);
2347 mGuidBaseNameList
= Next
;
2356 LoadGuidedSectionToolsTxt (
2357 IN CHAR8
* FirmwareVolumeFilename
2360 CHAR8
* PeerFilename
;
2367 Places
[0] = FirmwareVolumeFilename
;
2368 //Places[1] = mUtilityFilename;
2370 mParsedGuidedSectionTools
= NULL
;
2372 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2373 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2374 //printf("Loading %s...\n", PeerFilename);
2375 if (OsPathExists (PeerFilename
)) {
2376 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2378 free (PeerFilename
);
2379 if (mParsedGuidedSectionTools
!= NULL
) {
2392 Routine Description:
2394 GC_TODO: Add function description
2402 GC_TODO: add return values
2409 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2412 // Copyright declaration
2414 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
2415 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2420 fprintf (stdout
, "optional arguments:\n");
2421 fprintf (stdout
, " -h, --help\n\
2422 Show this help message and exit\n");
2423 fprintf (stdout
, " --version\n\
2424 Show program's version number and exit\n");
2425 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2426 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2427 fprintf (stdout
, " -v, --verbose\n\
2428 Print informational statements\n");
2429 fprintf (stdout
, " -q, --quiet\n\
2430 Returns the exit code, error messages will be displayed\n");
2431 fprintf (stdout
, " -s, --silent\n\
2432 Returns only the exit code; informational and error\n\
2433 messages are not displayed\n");
2434 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2435 Parse the basename to file-guid cross reference file(s)\n");
2436 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2437 The offset from the start of the input file to start \n\
2438 processing an FV\n");
2439 fprintf (stdout
, " --hash\n\
2440 Generate HASH value of the entire PE image\n");
2441 fprintf (stdout
, " --sfo\n\
2442 Reserved for future use\n");