2 The tool dumps the contents of a firmware volume
4 Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/UefiCapsule.h>
29 #include <Common/PiFirmwareFile.h>
30 #include <Common/PiFirmwareVolume.h>
31 #include <Guid/PiFirmwareFileSystem.h>
32 #include <IndustryStandard/PeImage.h>
33 #include <Protocol/GuidedSectionExtraction.h>
36 #include "Decompress.h"
38 #include "CommonLib.h"
39 #include "EfiUtilityMsgs.h"
40 #include "FirmwareVolumeBufferLib.h"
42 #include "ParseGuidedSectionTools.h"
43 #include "StringFuncs.h"
45 #include "PeCoffLib.h"
48 // Utility global variables
51 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
53 #define UTILITY_MAJOR_VERSION 1
54 #define UTILITY_MINOR_VERSION 0
56 #define UTILITY_NAME "VolInfo"
58 #define EFI_SECTION_ERROR EFIERR (100)
60 #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable
63 // Structure to keep a list of guid-to-basenames
65 typedef struct _GUID_TO_BASENAME
{
66 struct _GUID_TO_BASENAME
*Next
;
67 INT8 Guid
[PRINTED_GUID_BUFFER_SIZE
];
68 INT8 BaseName
[MAX_BASENAME_LEN
];
71 static GUID_TO_BASENAME
*mGuidBaseNameList
= NULL
;
74 // Store GUIDed Section guid->tool mapping
76 EFI_HANDLE mParsedGuidedSectionTools
= NULL
;
78 CHAR8
* mUtilityFilename
= NULL
;
80 BOOLEAN EnableHash
= FALSE
;
81 CHAR8
*OpenSslPath
= NULL
;
84 ParseGuidBaseNameFile (
89 FreeGuidBaseNameList (
100 IN UINT8
*SectionBuffer
,
101 IN UINT32 BufferLength
107 IN UINT32 SectionLength
115 OUT BOOLEAN
*ErasePolarity
121 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
122 EFI_FFS_FILE_HEADER
*FileHeader
,
123 BOOLEAN ErasePolarity
135 LoadGuidedSectionToolsTxt (
136 IN CHAR8
* FirmwareVolumeFilename
141 IN CHAR8
* DefaultPath
,
142 IN CHAR8
* AppendPath
,
159 Returns the length of a null-terminated unicode string.
163 String - The pointer to a null-terminated unicode string.
173 for (Length
= 0; *String
!= L
'\0'; String
++, Length
++) {
180 Unicode2AsciiString (
182 OUT CHAR8
*Destination
188 Convert a null-terminated unicode string to a null-terminated ascii string.
192 Source - The pointer to the null-terminated input unicode string.
193 Destination - The pointer to the null-terminated output ascii string.
201 while (*Source
!= '\0') {
202 *(Destination
++) = (CHAR8
) *(Source
++);
205 // End the ascii with a NULL.
219 GC_TODO: Add function description
223 argc - GC_TODO: add argument description
224 ] - GC_TODO: add argument description
228 GC_TODO: add return values
234 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
;
238 BOOLEAN ErasePolarity
;
241 CHAR8
*OpenSslCommand
;
243 SetUtilityName (UTILITY_NAME
);
245 // Print utility header
247 printf ("%s Version %d.%d Build %s\n",
249 UTILITY_MAJOR_VERSION
,
250 UTILITY_MINOR_VERSION
,
265 // Look for help options
267 if ((strcmp(argv
[0], "-h") == 0) || (strcmp(argv
[0], "--help") == 0) ||
268 (strcmp(argv
[0], "-?") == 0) || (strcmp(argv
[0], "/?") == 0)) {
270 return STATUS_SUCCESS
;
273 // Version has already be printed, so just return success
275 if (strcmp(argv
[0], "--version") == 0) {
276 return STATUS_SUCCESS
;
280 // If they specified -x xref guid/basename cross-reference files, process it.
281 // This will print the basename beside each file guid. To use it, specify
282 // -x xref_filename to processdsc, then use xref_filename as a parameter
286 if ((strcmp(argv
[0], "-x") == 0) || (strcmp(argv
[0], "--xref") == 0)) {
287 ParseGuidBaseNameFile (argv
[1]);
288 printf("ParseGuidBaseNameFile: %s\n", argv
[1]);
293 if (strcmp(argv
[0], "--offset") == 0) {
297 if ((argv
[1][0] == '0') && (tolower ((int)argv
[1][1]) == 'x')) {
298 if (sscanf (argv
[1], "%x", &Offset
) != 1) {
299 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
300 return GetUtilityStatus ();
303 if (sscanf (argv
[1], "%d", &Offset
) != 1) {
304 Error (NULL
, 0, 1003, "Invalid option value", "Offset = %s", argv
[1]);
305 return GetUtilityStatus ();
308 // See if they said something like "64K"
310 if (tolower ((int)argv
[1][strlen (argv
[1]) - 1]) == 'k') {
319 if ((stricmp (argv
[0], "--hash") == 0)) {
320 if (EnableHash
== TRUE
) {
322 // --hash already given in the option, ignore this one
329 OpenSslCommand
= "openssl";
330 OpenSslEnv
= getenv("OPENSSL_PATH");
331 if (OpenSslEnv
== NULL
) {
332 OpenSslPath
= OpenSslCommand
;
335 // We add quotes to the Openssl Path in case it has space characters
337 OpenSslPath
= malloc(2+strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
338 if (OpenSslPath
== NULL
) {
339 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
340 return GetUtilityStatus ();
342 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
344 if (OpenSslPath
== NULL
){
345 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
346 return GetUtilityStatus ();
353 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
354 SetPrintLevel (VERBOSE_LOG_LEVEL
);
360 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
361 SetPrintLevel (KEY_LOG_LEVEL
);
367 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
368 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
369 if (EFI_ERROR (Status
)) {
370 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
374 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
377 SetPrintLevel (LogLevel
);
378 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
384 mUtilityFilename
= argv
[0];
390 // Open the file containing the FV
392 if (mUtilityFilename
== NULL
) {
393 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
394 return GetUtilityStatus ();
396 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
397 if (InputFile
== NULL
) {
398 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
399 return GetUtilityStatus ();
402 // Skip over pad bytes if specified. This is used if they prepend 0xff
403 // data to the FV image binary.
406 fseek (InputFile
, Offset
, SEEK_SET
);
409 // Determine size of FV
411 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
412 if (EFI_ERROR (Status
)) {
413 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
415 return GetUtilityStatus ();
418 // Allocate a buffer for the FV image
420 FvImage
= malloc (FvSize
);
421 if (FvImage
== NULL
) {
422 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
424 return GetUtilityStatus ();
427 // Seek to the start of the image, then read the entire FV to the buffer
429 fseek (InputFile
, Offset
, SEEK_SET
);
430 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
432 if ((unsigned int) BytesRead
!= FvSize
) {
433 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
435 return GetUtilityStatus ();
438 LoadGuidedSectionToolsTxt (mUtilityFilename
);
440 PrintFvInfo (FvImage
, FALSE
);
446 FreeGuidBaseNameList ();
447 return GetUtilityStatus ();
461 GC_TODO: Add function description
465 Fv - Firmware Volume to print information about
466 IsChildFv - Flag specifies whether the input FV is a child FV.
476 BOOLEAN ErasePolarity
;
478 EFI_FFS_FILE_HEADER
*CurrentFile
;
481 Status
= FvBufGetSize (Fv
, &FvSize
);
485 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
489 // Get the first file
492 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
493 if (EFI_ERROR (Status
)) {
494 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
495 return GetUtilityStatus ();
498 // Display information about files found
500 while (CurrentFile
!= NULL
) {
502 // Increment the number of files counter
507 // Display info about this file
509 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
510 if (EFI_ERROR (Status
)) {
511 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
512 return GetUtilityStatus ();
517 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
518 if (Status
== EFI_NOT_FOUND
) {
520 } else if (EFI_ERROR (Status
)) {
521 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
522 return GetUtilityStatus ();
527 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
529 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
537 IN UINT32 ActualSize
,
544 This function returns the next larger size that meets the alignment
545 requirement specified.
550 Alignment The desired alignment.
554 EFI_SUCCESS Function completed successfully.
555 EFI_ABORTED The function encountered an error.
561 OccupiedSize
= ActualSize
;
562 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
572 IN EFI_SECTION_TYPE Type
578 Converts EFI Section names to Strings
582 Type - The EFI Section type
586 CHAR8* - Pointer to the String containing the section name.
591 CHAR8
*SectionTypeStringTable
[] = {
599 "EFI_SECTION_COMPRESSION",
603 "EFI_SECTION_GUID_DEFINED",
607 "Unknown section type - Reserved 0x03",
611 "Unknown section type - Reserved 0x04",
615 "Unknown section type - Reserved 0x05",
619 "Unknown section type - Reserved 0x06",
623 "Unknown section type - Reserved 0x07",
627 "Unknown section type - Reserved 0x08",
631 "Unknown section type - Reserved 0x09",
635 "Unknown section type - Reserved 0x0A",
639 "Unknown section type - Reserved 0x0B",
643 "Unknown section type - Reserved 0x0C",
647 "Unknown section type - Reserved 0x0D",
651 "Unknown section type - Reserved 0x0E",
655 "Unknown section type - Reserved 0x0E",
671 "EFI_SECTION_DXE_DEPEX",
675 "EFI_SECTION_VERSION",
679 "EFI_SECTION_USER_INTERFACE",
683 "EFI_SECTION_COMPATIBILITY16",
687 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
691 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
699 "Unknown section type - 0x1A",
703 "EFI_SECTION_PEI_DEPEX",
707 "EFI_SECTION_SMM_DEPEX",
711 "Unknown section type - Reserved - beyond last defined section"
714 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
715 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
718 SectionStr
= malloc (100);
719 if (SectionStr
== NULL
) {
720 printf ("Error: Out of memory resources.\n");
723 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
732 OUT BOOLEAN
*ErasePolarity
738 This function determines the size of the FV and the erase polarity. The
739 erase polarity is the FALSE value for file state.
743 InputFile The file that contains the FV image.
744 FvSize The size of the FV.
745 ErasePolarity The FV erase polarity.
749 EFI_SUCCESS Function completed successfully.
750 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
751 EFI_ABORTED The function encountered an error.
755 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
756 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
764 // Check input parameters
766 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
767 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
768 return EFI_INVALID_PARAMETER
;
773 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
774 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
775 Signature
[0] = VolumeHeader
.Signature
;
779 // Print FV header information
781 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
782 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
784 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
785 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
788 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
789 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
792 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
793 printf (" EFI_FVB2_READ_STATUS\n");
796 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
797 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
800 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
801 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
804 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
805 printf (" EFI_FVB2_WRITE_STATUS\n");
808 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
809 printf (" EFI_FVB2_LOCK_CAP\n");
812 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
813 printf (" EFI_FVB2_LOCK_STATUS\n");
816 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
817 printf (" EFI_FVB2_STICKY_WRITE\n");
820 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
821 printf (" EFI_FVB2_MEMORY_MAPPED\n");
824 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
825 printf (" EFI_FVB2_ERASE_POLARITY\n");
826 *ErasePolarity
= TRUE
;
829 #if (PI_SPECIFICATION_VERSION < 0x00010000)
830 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
831 printf (" EFI_FVB2_ALIGNMENT\n");
834 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
835 printf (" EFI_FVB2_ALIGNMENT_2\n");
838 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
839 printf (" EFI_FVB2_ALIGNMENT_4\n");
842 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
843 printf (" EFI_FVB2_ALIGNMENT_8\n");
846 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
847 printf (" EFI_FVB2_ALIGNMENT_16\n");
850 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
851 printf (" EFI_FVB2_ALIGNMENT_32\n");
854 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
855 printf (" EFI_FVB2_ALIGNMENT_64\n");
858 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
859 printf (" EFI_FVB2_ALIGNMENT_128\n");
862 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
863 printf (" EFI_FVB2_ALIGNMENT_256\n");
866 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
867 printf (" EFI_FVB2_ALIGNMENT_512\n");
870 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
871 printf (" EFI_FVB2_ALIGNMENT_1K\n");
874 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
875 printf (" EFI_FVB2_ALIGNMENT_2K\n");
878 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
879 printf (" EFI_FVB2_ALIGNMENT_4K\n");
882 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
883 printf (" EFI_FVB2_ALIGNMENT_8K\n");
886 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
887 printf (" EFI_FVB2_ALIGNMENT_16K\n");
890 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
891 printf (" EFI_FVB2_ALIGNMENT_32K\n");
894 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
895 printf (" EFI_FVB2_ALIGNMENT_64K\n");
900 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
901 printf (" EFI_FVB2_READ_LOCK_CAP\n");
904 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
905 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
908 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
909 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
912 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
913 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
916 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1
) {
917 printf (" EFI_FVB2_ALIGNMENT_1\n");
920 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
921 printf (" EFI_FVB2_ALIGNMENT_2\n");
924 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
925 printf (" EFI_FVB2_ALIGNMENT_4\n");
928 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
929 printf (" EFI_FVB2_ALIGNMENT_8\n");
932 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
933 printf (" EFI_FVB2_ALIGNMENT_16\n");
936 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
937 printf (" EFI_FVB2_ALIGNMENT_32\n");
940 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
941 printf (" EFI_FVB2_ALIGNMENT_64\n");
944 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
945 printf (" EFI_FVB2_ALIGNMENT_128\n");
948 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
949 printf (" EFI_FVB2_ALIGNMENT_256\n");
952 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
953 printf (" EFI_FVB2_ALIGNMENT_512\n");
956 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
957 printf (" EFI_FVB2_ALIGNMENT_1K\n");
960 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
961 printf (" EFI_FVB2_ALIGNMENT_2K\n");
964 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
965 printf (" EFI_FVB2_ALIGNMENT_4K\n");
968 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
969 printf (" EFI_FVB2_ALIGNMENT_8K\n");
972 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
973 printf (" EFI_FVB2_ALIGNMENT_16K\n");
976 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
977 printf (" EFI_FVB2_ALIGNMENT_32K\n");
980 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
981 printf (" EFI_FVB2_ALIGNMENT_64K\n");
984 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128K
) {
985 printf (" EFI_FVB2_ALIGNMENT_128K\n");
988 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256K
) {
989 printf (" EFI_FVB2_ALIGNMENT_256K\n");
992 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512K
) {
993 printf (" EFI_FVB2_ALIGNMENT_512K\n");
996 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1M
) {
997 printf (" EFI_FVB2_ALIGNMENT_1M\n");
1000 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2M
) {
1001 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1004 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4M
) {
1005 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1008 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8M
) {
1009 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1012 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16M
) {
1013 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1016 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32M
) {
1017 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1020 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1021 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1024 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1025 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1028 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1029 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1032 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1033 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1036 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256M
) {
1037 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1040 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512M
) {
1041 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1044 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1G
) {
1045 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1048 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2G
) {
1049 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1053 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1054 printf ("File System ID: ");
1055 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1059 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1062 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1063 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1065 if (BlockMap
.NumBlocks
!= 0) {
1066 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1067 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1068 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1071 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1073 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1074 printf ("ERROR: Header length not consistent with Block Maps!\n");
1078 if (VolumeHeader
.FvLength
!= Size
) {
1079 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
1083 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1088 // rewind (InputFile);
1096 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1097 EFI_FFS_FILE_HEADER
*FileHeader
,
1098 BOOLEAN ErasePolarity
1102 Routine Description:
1104 GC_TODO: Add function description
1108 FvImage - GC_TODO: add argument description
1109 FileHeader - GC_TODO: add argument description
1110 ErasePolarity - GC_TODO: add argument description
1114 EFI_SUCCESS - GC_TODO: Add description for return value
1115 EFI_ABORTED - GC_TODO: Add description for return value
1122 EFI_FFS_FILE_HEADER2 BlankHeader
;
1124 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1126 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1130 // Check if we have free space
1132 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1133 if (ErasePolarity
) {
1134 memset (&BlankHeader
, -1, HeaderSize
);
1136 memset (&BlankHeader
, 0, HeaderSize
);
1139 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1143 // Print file information.
1145 printf ("============================================================\n");
1147 printf ("File Name: ");
1148 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1149 printf ("%s ", GuidBuffer
);
1150 PrintGuidName (GuidBuffer
);
1154 // PrintGuid (&FileHeader->Name);
1157 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1158 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1159 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1160 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1161 printf ("File State: 0x%02X\n", FileHeader
->State
);
1166 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1168 switch (FileState
) {
1170 case EFI_FILE_HEADER_CONSTRUCTION
:
1171 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1174 case EFI_FILE_HEADER_INVALID
:
1175 printf (" EFI_FILE_HEADER_INVALID\n");
1178 case EFI_FILE_HEADER_VALID
:
1179 printf (" EFI_FILE_HEADER_VALID\n");
1180 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1181 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1182 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1183 if (Checksum
!= 0) {
1184 printf ("ERROR: Header checksum invalid.\n");
1190 case EFI_FILE_DELETED
:
1191 printf (" EFI_FILE_DELETED\n");
1193 case EFI_FILE_MARKED_FOR_UPDATE
:
1194 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1196 case EFI_FILE_DATA_VALID
:
1197 printf (" EFI_FILE_DATA_VALID\n");
1200 // Calculate header checksum
1202 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1203 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1204 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1205 if (Checksum
!= 0) {
1206 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1210 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1212 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1214 // Calculate file checksum
1216 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1217 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1218 if (Checksum
!= 0) {
1219 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1223 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1224 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
);
1228 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1230 // Verify tail if present
1232 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1234 // Verify tail is complement of integrity check field in the header.
1236 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1237 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1238 Error (NULL
, 0, 0003, "error parsing FFS file", \
1239 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1247 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1251 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1253 switch (FileHeader
->Type
) {
1255 case EFI_FV_FILETYPE_RAW
:
1256 printf ("EFI_FV_FILETYPE_RAW\n");
1259 case EFI_FV_FILETYPE_FREEFORM
:
1260 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1263 case EFI_FV_FILETYPE_SECURITY_CORE
:
1264 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1267 case EFI_FV_FILETYPE_PEI_CORE
:
1268 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1271 case EFI_FV_FILETYPE_DXE_CORE
:
1272 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1275 case EFI_FV_FILETYPE_PEIM
:
1276 printf ("EFI_FV_FILETYPE_PEIM\n");
1279 case EFI_FV_FILETYPE_DRIVER
:
1280 printf ("EFI_FV_FILETYPE_DRIVER\n");
1283 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1284 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1287 case EFI_FV_FILETYPE_APPLICATION
:
1288 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1291 case EFI_FV_FILETYPE_SMM
:
1292 printf ("EFI_FV_FILETYPE_SMM\n");
1295 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1296 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1299 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1300 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1303 case EFI_FV_FILETYPE_SMM_CORE
:
1304 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1307 case EFI_FV_FILETYPE_FFS_PAD
:
1308 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1312 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1317 switch (FileHeader
->Type
) {
1319 case EFI_FV_FILETYPE_ALL
:
1320 case EFI_FV_FILETYPE_RAW
:
1321 case EFI_FV_FILETYPE_FFS_PAD
:
1326 // All other files have sections
1328 Status
= ParseSection (
1329 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1330 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1332 if (EFI_ERROR (Status
)) {
1334 // printf ("ERROR: Parsing the FFS file.\n");
1346 IN VOID
*FileHandle
,
1347 IN UINTN FileOffset
,
1348 IN OUT UINT32
*ReadSize
,
1353 Routine Description:
1355 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1359 FileHandle - The handle to the PE/COFF file
1361 FileOffset - The offset, in bytes, into the file to read
1363 ReadSize - The number of bytes to read from the file starting at FileOffset
1365 Buffer - A pointer to the buffer to read the data into.
1369 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1373 CHAR8
*Destination8
;
1377 Destination8
= Buffer
;
1378 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1381 *(Destination8
++) = *(Source8
++);
1388 SetAddressToSectionHeader (
1390 IN OUT UINT8
*FileBuffer
,
1391 IN UINT64 NewPe32BaseAddress
1395 Routine Description:
1397 Set new base address into the section header of PeImage
1401 FileName - Name of file
1402 FileBuffer - Pointer to PeImage.
1403 NewPe32BaseAddress - New Base Address for PE image.
1407 EFI_SUCCESS Set new base address into this image successfully.
1412 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1414 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1415 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1418 // Initialize context
1420 memset (&ImageContext
, 0, sizeof (ImageContext
));
1421 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1422 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1423 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1424 if (EFI_ERROR (Status
)) {
1425 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1429 if (ImageContext
.RelocationsStripped
) {
1430 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1435 // Get PeHeader pointer
1437 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1440 // Get section header list
1442 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1445 sizeof (EFI_IMAGE_FILE_HEADER
) +
1446 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1450 // Set base address into the first section header that doesn't point to code section.
1452 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1453 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1454 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1460 // BaseAddress is set to section header.
1468 IN OUT UINT8
*FileBuffer
,
1469 IN UINT64 NewPe32BaseAddress
1473 Routine Description:
1475 Set new base address into PeImage, and fix up PeImage based on new address.
1479 FileName - Name of file
1480 FileBuffer - Pointer to PeImage.
1481 NewPe32BaseAddress - New Base Address for PE image.
1485 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1486 EFI_SUCCESS - Update PeImage is correctly.
1491 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1493 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1494 UINT8
*MemoryImagePointer
;
1495 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1498 // Initialize context
1500 memset (&ImageContext
, 0, sizeof (ImageContext
));
1501 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1502 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1503 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1504 if (EFI_ERROR (Status
)) {
1505 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1509 if (ImageContext
.RelocationsStripped
) {
1510 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1515 // Get PeHeader pointer
1517 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1520 // Load and Relocate Image Data
1522 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1523 if (MemoryImagePointer
== NULL
) {
1524 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1525 return EFI_OUT_OF_RESOURCES
;
1527 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1528 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1530 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1531 if (EFI_ERROR (Status
)) {
1532 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1533 free ((VOID
*) MemoryImagePointer
);
1537 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1538 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1539 if (EFI_ERROR (Status
)) {
1540 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1541 free ((VOID
*) MemoryImagePointer
);
1546 // Copy Relocated data to raw image file.
1548 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1551 sizeof (EFI_IMAGE_FILE_HEADER
) +
1552 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1555 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1557 FileBuffer
+ SectionHeader
->PointerToRawData
,
1558 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1559 SectionHeader
->SizeOfRawData
1563 free ((VOID
*) MemoryImagePointer
);
1566 // Update Image Base Address
1568 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1569 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1570 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1571 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1573 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1574 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1581 // Set new base address into section header
1583 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1590 IN CHAR8
* DefaultPath
,
1591 IN CHAR8
* AppendPath
,
1595 UINT32 DefaultPathLen
;
1597 CHAR8 QuotesStr
[] = "\"";
1598 strcpy(NewPath
, QuotesStr
);
1599 DefaultPathLen
= strlen(DefaultPath
);
1600 strcat(NewPath
, DefaultPath
);
1602 for (; Index
< DefaultPathLen
+ 1; Index
++) {
1603 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1604 if (NewPath
[Index
+ 1] != '\0') {
1605 NewPath
[Index
] = '/';
1609 if (NewPath
[Index
-1] != '/') {
1610 NewPath
[Index
] = '/';
1611 NewPath
[Index
+ 1] = '\0';
1613 strcat(NewPath
, AppendPath
);
1614 strcat(NewPath
, QuotesStr
);
1620 IN UINT8
*SectionBuffer
,
1621 IN UINT32 BufferLength
1625 Routine Description:
1631 SectionBuffer - Buffer containing the section to parse.
1632 BufferLength - Length of SectionBuffer
1636 EFI_SECTION_ERROR - Problem with section parsing.
1637 (a) compression errors
1638 (b) unrecognized section
1639 EFI_UNSUPPORTED - Do not know how to parse the section.
1640 EFI_SUCCESS - Section successfully parsed.
1641 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1645 EFI_SECTION_TYPE Type
;
1647 UINT32 SectionLength
;
1648 UINT32 SectionHeaderLen
;
1651 UINT32 ParsedLength
;
1652 UINT8
*CompressedBuffer
;
1653 UINT32 CompressedLength
;
1654 UINT8
*UncompressedBuffer
;
1655 UINT32 UncompressedLength
;
1656 UINT8
*ToolOutputBuffer
;
1657 UINT32 ToolOutputLength
;
1658 UINT8 CompressionType
;
1661 UINT8
*ScratchBuffer
;
1662 DECOMPRESS_FUNCTION DecompressFunction
;
1663 GETINFO_FUNCTION GetInfoFunction
;
1665 CHAR8
*ExtractionTool
;
1666 CHAR8
*ToolInputFile
;
1667 CHAR8
*ToolOutputFile
;
1668 CHAR8
*SystemCommand
;
1673 CHAR8
*ToolInputFileName
;
1674 CHAR8
*ToolOutputFileName
;
1678 ToolInputFileName
= NULL
;
1679 ToolOutputFileName
= NULL
;
1681 while (ParsedLength
< BufferLength
) {
1682 Ptr
= SectionBuffer
+ ParsedLength
;
1684 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1685 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1688 // This is sort of an odd check, but is necessary because FFS files are
1689 // padded to a QWORD boundary, meaning there is potentially a whole section
1690 // header worth of 0xFF bytes.
1692 if (SectionLength
== 0xffffff && Type
== 0xff) {
1698 // Get real section file size
1700 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1701 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1703 SectionName
= SectionNameToStr (Type
);
1704 if (SectionName
!= NULL
) {
1705 printf ("------------------------------------------------------------\n");
1706 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1711 case EFI_SECTION_RAW
:
1712 case EFI_SECTION_PIC
:
1713 case EFI_SECTION_TE
:
1714 // default is no more information
1717 case EFI_SECTION_PE32
:
1719 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1720 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1721 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1724 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1725 SectionLength
- SectionHeaderLen
1728 SystemCommand
= malloc (
1729 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1730 strlen (OpenSslPath
) +
1731 strlen (ToolInputFileName
) +
1732 strlen (ToolOutputFileName
) +
1735 if (SystemCommand
== NULL
) {
1736 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1737 return EFI_OUT_OF_RESOURCES
;
1741 OPENSSL_COMMAND_FORMAT_STRING
,
1747 if (system (SystemCommand
) != EFI_SUCCESS
) {
1748 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1755 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1756 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1759 fseek(fp
,0,SEEK_SET
);
1760 fseek(fp
,0,SEEK_END
);
1761 nFileLen
= ftell(fp
);
1762 fseek(fp
,0,SEEK_SET
);
1763 StrLine
= malloc(nFileLen
);
1764 if (StrLine
== NULL
) {
1766 free (SystemCommand
);
1767 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1768 return EFI_OUT_OF_RESOURCES
;
1770 fgets(StrLine
, nFileLen
, fp
);
1771 NewStr
= strrchr (StrLine
, '=');
1772 printf (" SHA1: %s\n", NewStr
+ 1);
1777 remove(ToolInputFileName
);
1778 remove(ToolOutputFileName
);
1779 free (SystemCommand
);
1783 case EFI_SECTION_USER_INTERFACE
:
1784 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1785 if (UIFileName
== NULL
) {
1786 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1787 return EFI_OUT_OF_RESOURCES
;
1789 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1790 printf (" String: %s\n", UIFileName
);
1794 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1795 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1796 if (EFI_ERROR (Status
)) {
1797 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1798 return EFI_SECTION_ERROR
;
1802 case EFI_SECTION_COMPATIBILITY16
:
1803 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1805 // Section does not contain any further header information.
1809 case EFI_SECTION_PEI_DEPEX
:
1810 case EFI_SECTION_DXE_DEPEX
:
1811 case EFI_SECTION_SMM_DEPEX
:
1812 DumpDepexSection (Ptr
, SectionLength
);
1815 case EFI_SECTION_VERSION
:
1816 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1817 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1820 case EFI_SECTION_COMPRESSION
:
1821 UncompressedBuffer
= NULL
;
1822 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1823 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1824 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1825 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1827 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1828 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1829 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1831 CompressedLength
= SectionLength
- RealHdrLen
;
1832 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1834 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1835 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1836 if (CompressedLength
!= UncompressedLength
) {
1841 "file is not compressed, but the compressed length does not match the uncompressed length",
1844 return EFI_SECTION_ERROR
;
1847 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1848 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1849 GetInfoFunction
= EfiGetInfo
;
1850 DecompressFunction
= EfiDecompress
;
1851 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1853 CompressedBuffer
= Ptr
+ RealHdrLen
;
1855 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1856 if (EFI_ERROR (Status
)) {
1857 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1858 return EFI_SECTION_ERROR
;
1861 if (DstSize
!= UncompressedLength
) {
1862 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1863 return EFI_SECTION_ERROR
;
1866 ScratchBuffer
= malloc (ScratchSize
);
1867 if (ScratchBuffer
== NULL
) {
1868 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1869 return EFI_OUT_OF_RESOURCES
;
1871 UncompressedBuffer
= malloc (UncompressedLength
);
1872 if (UncompressedBuffer
== NULL
) {
1873 free (ScratchBuffer
);
1874 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1875 return EFI_OUT_OF_RESOURCES
;
1877 Status
= DecompressFunction (
1885 free (ScratchBuffer
);
1886 if (EFI_ERROR (Status
)) {
1887 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1888 free (UncompressedBuffer
);
1889 return EFI_SECTION_ERROR
;
1892 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1893 return EFI_SECTION_ERROR
;
1896 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1898 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1900 // We need to deallocate Buffer
1902 free (UncompressedBuffer
);
1905 if (EFI_ERROR (Status
)) {
1906 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1907 return EFI_SECTION_ERROR
;
1911 case EFI_SECTION_GUID_DEFINED
:
1912 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1913 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1914 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1915 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1917 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1918 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1919 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1921 printf (" SectionDefinitionGuid: ");
1922 PrintGuid (EfiGuid
);
1924 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1925 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1928 LookupGuidedSectionToolPath (
1929 mParsedGuidedSectionTools
,
1933 if (ExtractionTool
!= NULL
) {
1935 ToolInputFile
= CloneString (tmpnam (NULL
));
1936 ToolOutputFile
= CloneString (tmpnam (NULL
));
1938 char tmp1
[] = "/tmp/fileXXXXXX";
1939 char tmp2
[] = "/tmp/fileXXXXXX";
1942 fd1
= mkstemp(tmp1
);
1943 fd2
= mkstemp(tmp2
);
1944 ToolInputFile
= CloneString(tmp1
);
1945 ToolOutputFile
= CloneString(tmp2
);
1950 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1951 if (ToolInputFile
!= NULL
) {
1952 free (ToolInputFile
);
1954 if (ToolOutputFile
!= NULL
) {
1955 free (ToolOutputFile
);
1957 free (ExtractionTool
);
1959 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1960 return EFI_OUT_OF_RESOURCES
;
1964 // Construction 'system' command string
1966 SystemCommand
= malloc (
1967 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1968 strlen (ExtractionTool
) +
1969 strlen (ToolInputFile
) +
1970 strlen (ToolOutputFile
) +
1973 if (SystemCommand
== NULL
) {
1974 free (ToolInputFile
);
1975 free (ToolOutputFile
);
1976 free (ExtractionTool
);
1978 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1979 return EFI_OUT_OF_RESOURCES
;
1983 EXTRACT_COMMAND_FORMAT_STRING
,
1988 free (ExtractionTool
);
1993 (CHAR8
*) SectionBuffer
+ DataOffset
,
1994 BufferLength
- DataOffset
1997 system (SystemCommand
);
1998 remove (ToolInputFile
);
1999 free (ToolInputFile
);
2004 (CHAR8
**)&ToolOutputBuffer
,
2007 remove (ToolOutputFile
);
2008 free (ToolOutputFile
);
2009 free (SystemCommand
);
2010 if (EFI_ERROR (Status
)) {
2011 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2012 return EFI_SECTION_ERROR
;
2015 Status
= ParseSection (
2019 if (EFI_ERROR (Status
)) {
2020 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2021 return EFI_SECTION_ERROR
;
2025 // Check for CRC32 sections which we can handle internally if needed.
2027 } else if (!CompareGuid (
2029 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2033 // CRC32 guided section
2035 Status
= ParseSection (
2036 SectionBuffer
+ DataOffset
,
2037 BufferLength
- DataOffset
2039 if (EFI_ERROR (Status
)) {
2040 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2041 return EFI_SECTION_ERROR
;
2045 // We don't know how to parse it now.
2047 Error (NULL
, 0, 0003, "Error parsing section", \
2048 "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).");
2049 return EFI_UNSUPPORTED
;
2055 // Unknown section, return error
2057 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2058 return EFI_SECTION_ERROR
;
2061 ParsedLength
+= SectionLength
;
2063 // We make then next section begin on a 4-byte boundary
2065 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2068 if (ParsedLength
< BufferLength
) {
2069 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2070 return EFI_SECTION_ERROR
;
2079 IN UINT32 SectionLength
2083 Routine Description:
2085 GC_TODO: Add function description
2089 Ptr - GC_TODO: add argument description
2090 SectionLength - GC_TODO: add argument description
2094 EFI_SUCCESS - GC_TODO: Add description for return value
2098 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2101 // Need at least a section header + data
2103 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2107 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2108 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2109 while (SectionLength
> 0) {
2112 case EFI_DEP_BEFORE
:
2113 printf ("BEFORE\n");
2126 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2127 printf ("%s ", GuidBuffer
);
2128 PrintGuidName (GuidBuffer
);
2131 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2134 SectionLength
-= 17;
2168 printf ("END DEPEX\n");
2180 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2194 Routine Description:
2196 GC_TODO: Add function description
2200 GuidStr - GC_TODO: add argument description
2204 EFI_SUCCESS - GC_TODO: Add description for return value
2205 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2209 GUID_TO_BASENAME
*GPtr
;
2211 // If we have a list of guid-to-basenames, then go through the list to
2212 // look for a guid string match. If found, print the basename to stdout,
2213 // otherwise return a failure.
2215 GPtr
= mGuidBaseNameList
;
2216 while (GPtr
!= NULL
) {
2217 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2218 printf ("%s", GPtr
->BaseName
);
2225 return EFI_INVALID_PARAMETER
;
2229 ParseGuidBaseNameFile (
2234 Routine Description:
2236 GC_TODO: Add function description
2240 FileName - GC_TODO: add argument description
2244 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2245 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2246 EFI_SUCCESS - GC_TODO: Add description for return value
2251 CHAR8 Line
[MAX_LINE_LEN
];
2252 CHAR8 FormatString
[MAX_LINE_LEN
];
2253 GUID_TO_BASENAME
*GPtr
;
2255 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2256 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2257 return EFI_DEVICE_ERROR
;
2261 // Generate the format string for fscanf
2266 (unsigned) sizeof (GPtr
->Guid
) - 1,
2267 (unsigned) sizeof (GPtr
->BaseName
) - 1
2270 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2272 // Allocate space for another guid/basename element
2274 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2277 return EFI_OUT_OF_RESOURCES
;
2280 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2281 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2282 GPtr
->Next
= mGuidBaseNameList
;
2283 mGuidBaseNameList
= GPtr
;
2286 // Some sort of error. Just continue.
2297 FreeGuidBaseNameList (
2302 Routine Description:
2304 GC_TODO: Add function description
2312 EFI_SUCCESS - GC_TODO: Add description for return value
2316 GUID_TO_BASENAME
*Next
;
2318 while (mGuidBaseNameList
!= NULL
) {
2319 Next
= mGuidBaseNameList
->Next
;
2320 free (mGuidBaseNameList
);
2321 mGuidBaseNameList
= Next
;
2330 LoadGuidedSectionToolsTxt (
2331 IN CHAR8
* FirmwareVolumeFilename
2334 CHAR8
* PeerFilename
;
2341 Places
[0] = FirmwareVolumeFilename
;
2342 //Places[1] = mUtilityFilename;
2344 mParsedGuidedSectionTools
= NULL
;
2346 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2347 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2348 //printf("Loading %s...\n", PeerFilename);
2349 if (OsPathExists (PeerFilename
)) {
2350 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2352 free (PeerFilename
);
2353 if (mParsedGuidedSectionTools
!= NULL
) {
2366 Routine Description:
2368 GC_TODO: Add function description
2376 GC_TODO: add return values
2383 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2386 // Copyright declaration
2388 fprintf (stdout
, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
2389 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2394 fprintf (stdout
, "optional arguments:\n");
2395 fprintf (stdout
, " -h, --help\n\
2396 Show this help message and exit\n");
2397 fprintf (stdout
, " --version\n\
2398 Show program's version number and exit\n");
2399 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2400 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2401 fprintf (stdout
, " -v, --verbose\n\
2402 Print informational statements\n");
2403 fprintf (stdout
, " -q, --quiet\n\
2404 Returns the exit code, error messages will be displayed\n");
2405 fprintf (stdout
, " -s, --silent\n\
2406 Returns only the exit code; informational and error\n\
2407 messages are not displayed\n");
2408 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2409 Parse the basename to file-guid cross reference file(s)\n");
2410 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2411 The offset from the start of the input file to start \n\
2412 processing an FV\n");
2413 fprintf (stdout
, " --hash\n\
2414 Generate HASH value of the entire PE image\n");
2415 fprintf (stdout
, " --sfo\n\
2416 Reserved for future use\n");