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 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1
) {
915 printf (" EFI_FVB2_ALIGNMENT_1\n");
918 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
919 printf (" EFI_FVB2_ALIGNMENT_2\n");
922 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
923 printf (" EFI_FVB2_ALIGNMENT_4\n");
926 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
927 printf (" EFI_FVB2_ALIGNMENT_8\n");
930 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
931 printf (" EFI_FVB2_ALIGNMENT_16\n");
934 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
935 printf (" EFI_FVB2_ALIGNMENT_32\n");
938 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
939 printf (" EFI_FVB2_ALIGNMENT_64\n");
942 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
943 printf (" EFI_FVB2_ALIGNMENT_128\n");
946 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
947 printf (" EFI_FVB2_ALIGNMENT_256\n");
950 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
951 printf (" EFI_FVB2_ALIGNMENT_512\n");
954 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
955 printf (" EFI_FVB2_ALIGNMENT_1K\n");
958 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
959 printf (" EFI_FVB2_ALIGNMENT_2K\n");
962 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
963 printf (" EFI_FVB2_ALIGNMENT_4K\n");
966 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
967 printf (" EFI_FVB2_ALIGNMENT_8K\n");
970 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
971 printf (" EFI_FVB2_ALIGNMENT_16K\n");
974 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
975 printf (" EFI_FVB2_ALIGNMENT_32K\n");
978 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
979 printf (" EFI_FVB2_ALIGNMENT_64K\n");
982 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128K
) {
983 printf (" EFI_FVB2_ALIGNMENT_128K\n");
986 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256K
) {
987 printf (" EFI_FVB2_ALIGNMENT_256K\n");
990 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512K
) {
991 printf (" EFI_FVB2_ALIGNMENT_512K\n");
994 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1M
) {
995 printf (" EFI_FVB2_ALIGNMENT_1M\n");
998 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2M
) {
999 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1002 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4M
) {
1003 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1006 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8M
) {
1007 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1010 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16M
) {
1011 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1014 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32M
) {
1015 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1018 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1019 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1022 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1023 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1026 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1027 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1030 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1031 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1034 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256M
) {
1035 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1038 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512M
) {
1039 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1042 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1G
) {
1043 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1046 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2G
) {
1047 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1051 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1052 printf ("File System ID: ");
1053 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1057 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1060 ReadSize
= fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1061 if (ReadSize
!= 1) {
1064 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1066 if (BlockMap
.NumBlocks
!= 0) {
1067 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1068 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1069 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1072 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1074 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1075 printf ("ERROR: Header length not consistent with Block Maps!\n");
1079 if (VolumeHeader
.FvLength
!= Size
) {
1080 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
1084 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1089 // rewind (InputFile);
1097 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1098 EFI_FFS_FILE_HEADER
*FileHeader
,
1099 BOOLEAN ErasePolarity
1103 Routine Description:
1105 GC_TODO: Add function description
1109 FvImage - GC_TODO: add argument description
1110 FileHeader - GC_TODO: add argument description
1111 ErasePolarity - GC_TODO: add argument description
1115 EFI_SUCCESS - GC_TODO: Add description for return value
1116 EFI_ABORTED - GC_TODO: Add description for return value
1123 EFI_FFS_FILE_HEADER2 BlankHeader
;
1125 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1127 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1131 // Check if we have free space
1133 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1134 if (ErasePolarity
) {
1135 memset (&BlankHeader
, -1, HeaderSize
);
1137 memset (&BlankHeader
, 0, HeaderSize
);
1140 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1144 // Print file information.
1146 printf ("============================================================\n");
1148 printf ("File Name: ");
1149 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1150 printf ("%s ", GuidBuffer
);
1151 PrintGuidName (GuidBuffer
);
1155 // PrintGuid (&FileHeader->Name);
1158 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1159 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1160 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1161 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1162 printf ("File State: 0x%02X\n", FileHeader
->State
);
1167 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1169 switch (FileState
) {
1171 case EFI_FILE_HEADER_CONSTRUCTION
:
1172 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1175 case EFI_FILE_HEADER_INVALID
:
1176 printf (" EFI_FILE_HEADER_INVALID\n");
1179 case EFI_FILE_HEADER_VALID
:
1180 printf (" EFI_FILE_HEADER_VALID\n");
1181 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1182 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1183 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1184 if (Checksum
!= 0) {
1185 printf ("ERROR: Header checksum invalid.\n");
1191 case EFI_FILE_DELETED
:
1192 printf (" EFI_FILE_DELETED\n");
1194 case EFI_FILE_MARKED_FOR_UPDATE
:
1195 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1197 case EFI_FILE_DATA_VALID
:
1198 printf (" EFI_FILE_DATA_VALID\n");
1201 // Calculate header checksum
1203 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1204 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1205 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1206 if (Checksum
!= 0) {
1207 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1211 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1213 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1215 // Calculate file checksum
1217 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1218 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1219 if (Checksum
!= 0) {
1220 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1224 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1225 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
);
1229 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1231 // Verify tail if present
1233 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1235 // Verify tail is complement of integrity check field in the header.
1237 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1238 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1239 Error (NULL
, 0, 0003, "error parsing FFS file", \
1240 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1248 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1252 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1254 switch (FileHeader
->Type
) {
1256 case EFI_FV_FILETYPE_RAW
:
1257 printf ("EFI_FV_FILETYPE_RAW\n");
1260 case EFI_FV_FILETYPE_FREEFORM
:
1261 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1264 case EFI_FV_FILETYPE_SECURITY_CORE
:
1265 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1268 case EFI_FV_FILETYPE_PEI_CORE
:
1269 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1272 case EFI_FV_FILETYPE_DXE_CORE
:
1273 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1276 case EFI_FV_FILETYPE_PEIM
:
1277 printf ("EFI_FV_FILETYPE_PEIM\n");
1280 case EFI_FV_FILETYPE_DRIVER
:
1281 printf ("EFI_FV_FILETYPE_DRIVER\n");
1284 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1285 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1288 case EFI_FV_FILETYPE_APPLICATION
:
1289 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1292 case EFI_FV_FILETYPE_SMM
:
1293 printf ("EFI_FV_FILETYPE_SMM\n");
1296 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1297 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1300 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1301 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1304 case EFI_FV_FILETYPE_SMM_CORE
:
1305 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1308 case EFI_FV_FILETYPE_MM_STANDALONE
:
1309 printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
1312 case EFI_FV_FILETYPE_MM_CORE_STANDALONE
:
1313 printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
1316 case EFI_FV_FILETYPE_FFS_PAD
:
1317 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1321 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1326 switch (FileHeader
->Type
) {
1328 case EFI_FV_FILETYPE_ALL
:
1329 case EFI_FV_FILETYPE_RAW
:
1330 case EFI_FV_FILETYPE_FFS_PAD
:
1335 // All other files have sections
1337 Status
= ParseSection (
1338 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1339 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1341 if (EFI_ERROR (Status
)) {
1343 // printf ("ERROR: Parsing the FFS file.\n");
1355 IN VOID
*FileHandle
,
1356 IN UINTN FileOffset
,
1357 IN OUT UINT32
*ReadSize
,
1362 Routine Description:
1364 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1368 FileHandle - The handle to the PE/COFF file
1370 FileOffset - The offset, in bytes, into the file to read
1372 ReadSize - The number of bytes to read from the file starting at FileOffset
1374 Buffer - A pointer to the buffer to read the data into.
1378 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1382 CHAR8
*Destination8
;
1386 Destination8
= Buffer
;
1387 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1390 *(Destination8
++) = *(Source8
++);
1397 SetAddressToSectionHeader (
1399 IN OUT UINT8
*FileBuffer
,
1400 IN UINT64 NewPe32BaseAddress
1404 Routine Description:
1406 Set new base address into the section header of PeImage
1410 FileName - Name of file
1411 FileBuffer - Pointer to PeImage.
1412 NewPe32BaseAddress - New Base Address for PE image.
1416 EFI_SUCCESS Set new base address into this image successfully.
1421 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1423 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1424 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1427 // Initialize context
1429 memset (&ImageContext
, 0, sizeof (ImageContext
));
1430 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1431 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1432 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1433 if (EFI_ERROR (Status
)) {
1434 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1438 if (ImageContext
.RelocationsStripped
) {
1439 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1444 // Get PeHeader pointer
1446 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1449 // Get section header list
1451 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1454 sizeof (EFI_IMAGE_FILE_HEADER
) +
1455 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1459 // Set base address into the first section header that doesn't point to code section.
1461 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1462 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1463 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1469 // BaseAddress is set to section header.
1477 IN OUT UINT8
*FileBuffer
,
1478 IN UINT64 NewPe32BaseAddress
1482 Routine Description:
1484 Set new base address into PeImage, and fix up PeImage based on new address.
1488 FileName - Name of file
1489 FileBuffer - Pointer to PeImage.
1490 NewPe32BaseAddress - New Base Address for PE image.
1494 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1495 EFI_SUCCESS - Update PeImage is correctly.
1500 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1502 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1503 UINT8
*MemoryImagePointer
;
1504 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1507 // Initialize context
1509 memset (&ImageContext
, 0, sizeof (ImageContext
));
1510 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1511 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1512 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1513 if (EFI_ERROR (Status
)) {
1514 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1518 if (ImageContext
.RelocationsStripped
) {
1519 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1524 // Get PeHeader pointer
1526 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1529 // Load and Relocate Image Data
1531 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1532 if (MemoryImagePointer
== NULL
) {
1533 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1534 return EFI_OUT_OF_RESOURCES
;
1536 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1537 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1539 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1540 if (EFI_ERROR (Status
)) {
1541 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1542 free ((VOID
*) MemoryImagePointer
);
1546 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1547 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1548 if (EFI_ERROR (Status
)) {
1549 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1550 free ((VOID
*) MemoryImagePointer
);
1555 // Copy Relocated data to raw image file.
1557 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1560 sizeof (EFI_IMAGE_FILE_HEADER
) +
1561 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1564 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1566 FileBuffer
+ SectionHeader
->PointerToRawData
,
1567 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1568 SectionHeader
->SizeOfRawData
1572 free ((VOID
*) MemoryImagePointer
);
1575 // Update Image Base Address
1577 if (ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1578 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1579 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1580 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1582 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1583 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1590 // Set new base address into section header
1592 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1599 IN CHAR8
* DefaultPath
,
1600 IN CHAR8
* AppendPath
,
1604 UINT32 DefaultPathLen
;
1606 CHAR8 QuotesStr
[] = "\"";
1607 strcpy(NewPath
, QuotesStr
);
1608 DefaultPathLen
= strlen(DefaultPath
);
1609 strcat(NewPath
, DefaultPath
);
1611 for (; Index
< DefaultPathLen
+ 1; Index
++) {
1612 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1613 if (NewPath
[Index
+ 1] != '\0') {
1614 NewPath
[Index
] = '/';
1618 if (NewPath
[Index
-1] != '/') {
1619 NewPath
[Index
] = '/';
1620 NewPath
[Index
+ 1] = '\0';
1622 strcat(NewPath
, AppendPath
);
1623 strcat(NewPath
, QuotesStr
);
1629 IN UINT8
*SectionBuffer
,
1630 IN UINT32 BufferLength
1634 Routine Description:
1640 SectionBuffer - Buffer containing the section to parse.
1641 BufferLength - Length of SectionBuffer
1645 EFI_SECTION_ERROR - Problem with section parsing.
1646 (a) compression errors
1647 (b) unrecognized section
1648 EFI_UNSUPPORTED - Do not know how to parse the section.
1649 EFI_SUCCESS - Section successfully parsed.
1650 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1654 EFI_SECTION_TYPE Type
;
1656 UINT32 SectionLength
;
1657 UINT32 SectionHeaderLen
;
1660 UINT32 ParsedLength
;
1661 UINT8
*CompressedBuffer
;
1662 UINT32 CompressedLength
;
1663 UINT8
*UncompressedBuffer
;
1664 UINT32 UncompressedLength
;
1665 UINT8
*ToolOutputBuffer
;
1666 UINT32 ToolOutputLength
;
1667 UINT8 CompressionType
;
1670 UINT8
*ScratchBuffer
;
1671 DECOMPRESS_FUNCTION DecompressFunction
;
1672 GETINFO_FUNCTION GetInfoFunction
;
1674 CHAR8
*ExtractionTool
;
1675 CHAR8
*ToolInputFile
;
1676 CHAR8
*ToolOutputFile
;
1677 CHAR8
*SystemCommand
;
1682 CHAR8
*ToolInputFileName
;
1683 CHAR8
*ToolOutputFileName
;
1687 ToolInputFileName
= NULL
;
1688 ToolOutputFileName
= NULL
;
1690 while (ParsedLength
< BufferLength
) {
1691 Ptr
= SectionBuffer
+ ParsedLength
;
1693 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1694 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1697 // This is sort of an odd check, but is necessary because FFS files are
1698 // padded to a QWORD boundary, meaning there is potentially a whole section
1699 // header worth of 0xFF bytes.
1701 if (SectionLength
== 0xffffff && Type
== 0xff) {
1707 // Get real section file size
1709 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1710 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1712 SectionName
= SectionNameToStr (Type
);
1713 if (SectionName
!= NULL
) {
1714 printf ("------------------------------------------------------------\n");
1715 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1720 case EFI_SECTION_RAW
:
1721 case EFI_SECTION_PIC
:
1722 case EFI_SECTION_TE
:
1723 // default is no more information
1726 case EFI_SECTION_PE32
:
1728 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1729 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1730 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1733 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1734 SectionLength
- SectionHeaderLen
1737 SystemCommand
= malloc (
1738 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1739 strlen (OpenSslPath
) +
1740 strlen (ToolInputFileName
) +
1741 strlen (ToolOutputFileName
) +
1744 if (SystemCommand
== NULL
) {
1745 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1746 return EFI_OUT_OF_RESOURCES
;
1750 OPENSSL_COMMAND_FORMAT_STRING
,
1756 if (system (SystemCommand
) != EFI_SUCCESS
) {
1757 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1764 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1765 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1768 fseek(fp
,0,SEEK_SET
);
1769 fseek(fp
,0,SEEK_END
);
1770 nFileLen
= ftell(fp
);
1771 fseek(fp
,0,SEEK_SET
);
1772 StrLine
= malloc(nFileLen
);
1773 if (StrLine
== NULL
) {
1775 free (SystemCommand
);
1776 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1777 return EFI_OUT_OF_RESOURCES
;
1779 fgets(StrLine
, nFileLen
, fp
);
1780 NewStr
= strrchr (StrLine
, '=');
1781 printf (" SHA1: %s\n", NewStr
+ 1);
1786 remove(ToolInputFileName
);
1787 remove(ToolOutputFileName
);
1788 free (SystemCommand
);
1792 case EFI_SECTION_USER_INTERFACE
:
1793 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1794 if (UIFileName
== NULL
) {
1795 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1796 return EFI_OUT_OF_RESOURCES
;
1798 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1799 printf (" String: %s\n", UIFileName
);
1803 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1804 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1805 if (EFI_ERROR (Status
)) {
1806 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1807 return EFI_SECTION_ERROR
;
1811 case EFI_SECTION_COMPATIBILITY16
:
1812 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1814 // Section does not contain any further header information.
1818 case EFI_SECTION_PEI_DEPEX
:
1819 case EFI_SECTION_DXE_DEPEX
:
1820 case EFI_SECTION_SMM_DEPEX
:
1821 DumpDepexSection (Ptr
, SectionLength
);
1824 case EFI_SECTION_VERSION
:
1825 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1826 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1829 case EFI_SECTION_COMPRESSION
:
1830 UncompressedBuffer
= NULL
;
1831 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1832 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1833 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1834 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1836 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1837 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1838 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1840 CompressedLength
= SectionLength
- RealHdrLen
;
1841 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1843 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1844 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1845 if (CompressedLength
!= UncompressedLength
) {
1850 "file is not compressed, but the compressed length does not match the uncompressed length",
1853 return EFI_SECTION_ERROR
;
1856 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1857 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1858 GetInfoFunction
= EfiGetInfo
;
1859 DecompressFunction
= EfiDecompress
;
1860 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1862 CompressedBuffer
= Ptr
+ RealHdrLen
;
1864 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1865 if (EFI_ERROR (Status
)) {
1866 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1867 return EFI_SECTION_ERROR
;
1870 if (DstSize
!= UncompressedLength
) {
1871 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1872 return EFI_SECTION_ERROR
;
1875 ScratchBuffer
= malloc (ScratchSize
);
1876 if (ScratchBuffer
== NULL
) {
1877 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1878 return EFI_OUT_OF_RESOURCES
;
1880 UncompressedBuffer
= malloc (UncompressedLength
);
1881 if (UncompressedBuffer
== NULL
) {
1882 free (ScratchBuffer
);
1883 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1884 return EFI_OUT_OF_RESOURCES
;
1886 Status
= DecompressFunction (
1894 free (ScratchBuffer
);
1895 if (EFI_ERROR (Status
)) {
1896 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1897 free (UncompressedBuffer
);
1898 return EFI_SECTION_ERROR
;
1901 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1902 return EFI_SECTION_ERROR
;
1905 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1907 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1909 // We need to deallocate Buffer
1911 free (UncompressedBuffer
);
1914 if (EFI_ERROR (Status
)) {
1915 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1916 return EFI_SECTION_ERROR
;
1920 case EFI_SECTION_GUID_DEFINED
:
1921 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1922 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1923 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1924 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1926 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1927 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1928 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1930 printf (" SectionDefinitionGuid: ");
1931 PrintGuid (EfiGuid
);
1933 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1934 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1937 LookupGuidedSectionToolPath (
1938 mParsedGuidedSectionTools
,
1942 if (ExtractionTool
!= NULL
) {
1944 ToolInputFile
= CloneString (tmpnam (NULL
));
1945 ToolOutputFile
= CloneString (tmpnam (NULL
));
1947 char tmp1
[] = "/tmp/fileXXXXXX";
1948 char tmp2
[] = "/tmp/fileXXXXXX";
1951 fd1
= mkstemp(tmp1
);
1952 fd2
= mkstemp(tmp2
);
1953 ToolInputFile
= CloneString(tmp1
);
1954 ToolOutputFile
= CloneString(tmp2
);
1959 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1960 if (ToolInputFile
!= NULL
) {
1961 free (ToolInputFile
);
1963 if (ToolOutputFile
!= NULL
) {
1964 free (ToolOutputFile
);
1966 free (ExtractionTool
);
1968 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1969 return EFI_OUT_OF_RESOURCES
;
1973 // Construction 'system' command string
1975 SystemCommand
= malloc (
1976 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1977 strlen (ExtractionTool
) +
1978 strlen (ToolInputFile
) +
1979 strlen (ToolOutputFile
) +
1982 if (SystemCommand
== NULL
) {
1983 free (ToolInputFile
);
1984 free (ToolOutputFile
);
1985 free (ExtractionTool
);
1987 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1988 return EFI_OUT_OF_RESOURCES
;
1992 EXTRACT_COMMAND_FORMAT_STRING
,
1997 free (ExtractionTool
);
2002 (CHAR8
*) SectionBuffer
+ DataOffset
,
2003 BufferLength
- DataOffset
2006 system (SystemCommand
);
2007 remove (ToolInputFile
);
2008 free (ToolInputFile
);
2013 (CHAR8
**)&ToolOutputBuffer
,
2016 remove (ToolOutputFile
);
2017 free (ToolOutputFile
);
2018 free (SystemCommand
);
2019 if (EFI_ERROR (Status
)) {
2020 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2021 return EFI_SECTION_ERROR
;
2024 Status
= ParseSection (
2028 if (EFI_ERROR (Status
)) {
2029 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2030 return EFI_SECTION_ERROR
;
2034 // Check for CRC32 sections which we can handle internally if needed.
2036 } else if (!CompareGuid (
2038 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2042 // CRC32 guided section
2044 Status
= ParseSection (
2045 SectionBuffer
+ DataOffset
,
2046 BufferLength
- DataOffset
2048 if (EFI_ERROR (Status
)) {
2049 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2050 return EFI_SECTION_ERROR
;
2054 // We don't know how to parse it now.
2056 Error (NULL
, 0, 0003, "Error parsing section", \
2057 "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).");
2058 return EFI_UNSUPPORTED
;
2064 // Unknown section, return error
2066 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2067 return EFI_SECTION_ERROR
;
2070 ParsedLength
+= SectionLength
;
2072 // We make then next section begin on a 4-byte boundary
2074 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2077 if (ParsedLength
< BufferLength
) {
2078 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2079 return EFI_SECTION_ERROR
;
2088 IN UINT32 SectionLength
2092 Routine Description:
2094 GC_TODO: Add function description
2098 Ptr - GC_TODO: add argument description
2099 SectionLength - GC_TODO: add argument description
2103 EFI_SUCCESS - GC_TODO: Add description for return value
2107 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2110 // Need at least a section header + data
2112 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2116 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2117 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2118 while (SectionLength
> 0) {
2121 case EFI_DEP_BEFORE
:
2122 printf ("BEFORE\n");
2135 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2136 printf ("%s ", GuidBuffer
);
2137 PrintGuidName (GuidBuffer
);
2140 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2143 SectionLength
-= 17;
2177 printf ("END DEPEX\n");
2189 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2203 Routine Description:
2205 GC_TODO: Add function description
2209 GuidStr - GC_TODO: add argument description
2213 EFI_SUCCESS - GC_TODO: Add description for return value
2214 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2218 GUID_TO_BASENAME
*GPtr
;
2220 // If we have a list of guid-to-basenames, then go through the list to
2221 // look for a guid string match. If found, print the basename to stdout,
2222 // otherwise return a failure.
2224 GPtr
= mGuidBaseNameList
;
2225 while (GPtr
!= NULL
) {
2226 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2227 printf ("%s", GPtr
->BaseName
);
2234 return EFI_INVALID_PARAMETER
;
2238 ParseGuidBaseNameFile (
2243 Routine Description:
2245 GC_TODO: Add function description
2249 FileName - GC_TODO: add argument description
2253 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2254 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2255 EFI_SUCCESS - GC_TODO: Add description for return value
2260 CHAR8 Line
[MAX_LINE_LEN
];
2261 CHAR8 FormatString
[MAX_LINE_LEN
];
2262 GUID_TO_BASENAME
*GPtr
;
2264 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2265 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2266 return EFI_DEVICE_ERROR
;
2270 // Generate the format string for fscanf
2275 (unsigned) sizeof (GPtr
->Guid
) - 1,
2276 (unsigned) sizeof (GPtr
->BaseName
) - 1
2279 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2281 // Allocate space for another guid/basename element
2283 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2286 return EFI_OUT_OF_RESOURCES
;
2289 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2290 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2291 GPtr
->Next
= mGuidBaseNameList
;
2292 mGuidBaseNameList
= GPtr
;
2295 // Some sort of error. Just continue.
2306 FreeGuidBaseNameList (
2311 Routine Description:
2313 GC_TODO: Add function description
2321 EFI_SUCCESS - GC_TODO: Add description for return value
2325 GUID_TO_BASENAME
*Next
;
2327 while (mGuidBaseNameList
!= NULL
) {
2328 Next
= mGuidBaseNameList
->Next
;
2329 free (mGuidBaseNameList
);
2330 mGuidBaseNameList
= Next
;
2339 LoadGuidedSectionToolsTxt (
2340 IN CHAR8
* FirmwareVolumeFilename
2343 CHAR8
* PeerFilename
;
2350 Places
[0] = FirmwareVolumeFilename
;
2351 //Places[1] = mUtilityFilename;
2353 mParsedGuidedSectionTools
= NULL
;
2355 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2356 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2357 //printf("Loading %s...\n", PeerFilename);
2358 if (OsPathExists (PeerFilename
)) {
2359 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2361 free (PeerFilename
);
2362 if (mParsedGuidedSectionTools
!= NULL
) {
2375 Routine Description:
2377 GC_TODO: Add function description
2385 GC_TODO: add return values
2392 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2395 // Copyright declaration
2397 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
2398 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2403 fprintf (stdout
, "optional arguments:\n");
2404 fprintf (stdout
, " -h, --help\n\
2405 Show this help message and exit\n");
2406 fprintf (stdout
, " --version\n\
2407 Show program's version number and exit\n");
2408 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2409 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2410 fprintf (stdout
, " -v, --verbose\n\
2411 Print informational statements\n");
2412 fprintf (stdout
, " -q, --quiet\n\
2413 Returns the exit code, error messages will be displayed\n");
2414 fprintf (stdout
, " -s, --silent\n\
2415 Returns only the exit code; informational and error\n\
2416 messages are not displayed\n");
2417 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2418 Parse the basename to file-guid cross reference file(s)\n");
2419 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2420 The offset from the start of the input file to start \n\
2421 processing an FV\n");
2422 fprintf (stdout
, " --hash\n\
2423 Generate HASH value of the entire PE image\n");
2424 fprintf (stdout
, " --sfo\n\
2425 Reserved for future use\n");