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
;
334 OpenSslPath
= malloc(strlen(OpenSslEnv
)+strlen(OpenSslCommand
)+1);
335 if (OpenSslPath
== NULL
) {
336 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
337 return GetUtilityStatus ();
339 CombinePath(OpenSslEnv
, OpenSslCommand
, OpenSslPath
);
341 if (OpenSslPath
== NULL
){
342 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
343 return GetUtilityStatus ();
350 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
351 SetPrintLevel (VERBOSE_LOG_LEVEL
);
357 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
358 SetPrintLevel (KEY_LOG_LEVEL
);
364 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
365 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
366 if (EFI_ERROR (Status
)) {
367 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
371 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
374 SetPrintLevel (LogLevel
);
375 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
381 mUtilityFilename
= argv
[0];
387 // Open the file containing the FV
389 if (mUtilityFilename
== NULL
) {
390 Error (NULL
, 0, 1001, "Missing option", "Input files are not specified");
391 return GetUtilityStatus ();
393 InputFile
= fopen (LongFilePath (mUtilityFilename
), "rb");
394 if (InputFile
== NULL
) {
395 Error (NULL
, 0, 0001, "Error opening the input file", mUtilityFilename
);
396 return GetUtilityStatus ();
399 // Skip over pad bytes if specified. This is used if they prepend 0xff
400 // data to the FV image binary.
403 fseek (InputFile
, Offset
, SEEK_SET
);
406 // Determine size of FV
408 Status
= ReadHeader (InputFile
, &FvSize
, &ErasePolarity
);
409 if (EFI_ERROR (Status
)) {
410 Error (NULL
, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename
);
412 return GetUtilityStatus ();
415 // Allocate a buffer for the FV image
417 FvImage
= malloc (FvSize
);
418 if (FvImage
== NULL
) {
419 Error (NULL
, 0, 4001, "Resource: Memory can't be allocated", NULL
);
421 return GetUtilityStatus ();
424 // Seek to the start of the image, then read the entire FV to the buffer
426 fseek (InputFile
, Offset
, SEEK_SET
);
427 BytesRead
= fread (FvImage
, 1, FvSize
, InputFile
);
429 if ((unsigned int) BytesRead
!= FvSize
) {
430 Error (NULL
, 0, 0004, "error reading FvImage from", mUtilityFilename
);
432 return GetUtilityStatus ();
435 LoadGuidedSectionToolsTxt (mUtilityFilename
);
437 PrintFvInfo (FvImage
, FALSE
);
443 FreeGuidBaseNameList ();
444 return GetUtilityStatus ();
458 GC_TODO: Add function description
462 Fv - Firmware Volume to print information about
463 IsChildFv - Flag specifies whether the input FV is a child FV.
473 BOOLEAN ErasePolarity
;
475 EFI_FFS_FILE_HEADER
*CurrentFile
;
478 Status
= FvBufGetSize (Fv
, &FvSize
);
482 (((EFI_FIRMWARE_VOLUME_HEADER
*)Fv
)->Attributes
& EFI_FVB2_ERASE_POLARITY
) ?
486 // Get the first file
489 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
490 if (EFI_ERROR (Status
)) {
491 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
492 return GetUtilityStatus ();
495 // Display information about files found
497 while (CurrentFile
!= NULL
) {
499 // Increment the number of files counter
504 // Display info about this file
506 Status
= PrintFileInfo (Fv
, CurrentFile
, ErasePolarity
);
507 if (EFI_ERROR (Status
)) {
508 Error (NULL
, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
509 return GetUtilityStatus ();
514 Status
= FvBufFindNextFile (Fv
, &Key
, (VOID
**) &CurrentFile
);
515 if (Status
== EFI_NOT_FOUND
) {
517 } else if (EFI_ERROR (Status
)) {
518 Error (NULL
, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
519 return GetUtilityStatus ();
524 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles
);
526 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles
);
534 IN UINT32 ActualSize
,
541 This function returns the next larger size that meets the alignment
542 requirement specified.
547 Alignment The desired alignment.
551 EFI_SUCCESS Function completed successfully.
552 EFI_ABORTED The function encountered an error.
558 OccupiedSize
= ActualSize
;
559 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
569 IN EFI_SECTION_TYPE Type
575 Converts EFI Section names to Strings
579 Type - The EFI Section type
583 CHAR8* - Pointer to the String containing the section name.
588 CHAR8
*SectionTypeStringTable
[] = {
596 "EFI_SECTION_COMPRESSION",
600 "EFI_SECTION_GUID_DEFINED",
604 "Unknown section type - Reserved 0x03",
608 "Unknown section type - Reserved 0x04",
612 "Unknown section type - Reserved 0x05",
616 "Unknown section type - Reserved 0x06",
620 "Unknown section type - Reserved 0x07",
624 "Unknown section type - Reserved 0x08",
628 "Unknown section type - Reserved 0x09",
632 "Unknown section type - Reserved 0x0A",
636 "Unknown section type - Reserved 0x0B",
640 "Unknown section type - Reserved 0x0C",
644 "Unknown section type - Reserved 0x0D",
648 "Unknown section type - Reserved 0x0E",
652 "Unknown section type - Reserved 0x0E",
668 "EFI_SECTION_DXE_DEPEX",
672 "EFI_SECTION_VERSION",
676 "EFI_SECTION_USER_INTERFACE",
680 "EFI_SECTION_COMPATIBILITY16",
684 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
688 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
696 "Unknown section type - 0x1A",
700 "EFI_SECTION_PEI_DEPEX",
704 "EFI_SECTION_SMM_DEPEX",
708 "Unknown section type - Reserved - beyond last defined section"
711 if (Type
> EFI_SECTION_LAST_SECTION_TYPE
) {
712 Type
= EFI_SECTION_LAST_SECTION_TYPE
+ 1;
715 SectionStr
= malloc (100);
716 if (SectionStr
== NULL
) {
717 printf ("Error: Out of memory resources.\n");
720 strcpy (SectionStr
, SectionTypeStringTable
[Type
]);
729 OUT BOOLEAN
*ErasePolarity
735 This function determines the size of the FV and the erase polarity. The
736 erase polarity is the FALSE value for file state.
740 InputFile The file that contains the FV image.
741 FvSize The size of the FV.
742 ErasePolarity The FV erase polarity.
746 EFI_SUCCESS Function completed successfully.
747 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
748 EFI_ABORTED The function encountered an error.
752 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader
;
753 EFI_FV_BLOCK_MAP_ENTRY BlockMap
;
761 // Check input parameters
763 if (InputFile
== NULL
|| FvSize
== NULL
|| ErasePolarity
== NULL
) {
764 Error (__FILE__
, __LINE__
, 0, "application error", "invalid parameter to function");
765 return EFI_INVALID_PARAMETER
;
770 fread (&VolumeHeader
, sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
771 BytesRead
= sizeof (EFI_FIRMWARE_VOLUME_HEADER
) - sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
772 Signature
[0] = VolumeHeader
.Signature
;
776 // Print FV header information
778 printf ("Signature: %s (%X)\n", (char *) Signature
, (unsigned) VolumeHeader
.Signature
);
779 printf ("Attributes: %X\n", (unsigned) VolumeHeader
.Attributes
);
781 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_DISABLED_CAP
) {
782 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
785 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_ENABLED_CAP
) {
786 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
789 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_STATUS
) {
790 printf (" EFI_FVB2_READ_STATUS\n");
793 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_DISABLED_CAP
) {
794 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
797 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_ENABLED_CAP
) {
798 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
801 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_STATUS
) {
802 printf (" EFI_FVB2_WRITE_STATUS\n");
805 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_CAP
) {
806 printf (" EFI_FVB2_LOCK_CAP\n");
809 if (VolumeHeader
.Attributes
& EFI_FVB2_LOCK_STATUS
) {
810 printf (" EFI_FVB2_LOCK_STATUS\n");
813 if (VolumeHeader
.Attributes
& EFI_FVB2_STICKY_WRITE
) {
814 printf (" EFI_FVB2_STICKY_WRITE\n");
817 if (VolumeHeader
.Attributes
& EFI_FVB2_MEMORY_MAPPED
) {
818 printf (" EFI_FVB2_MEMORY_MAPPED\n");
821 if (VolumeHeader
.Attributes
& EFI_FVB2_ERASE_POLARITY
) {
822 printf (" EFI_FVB2_ERASE_POLARITY\n");
823 *ErasePolarity
= TRUE
;
826 #if (PI_SPECIFICATION_VERSION < 0x00010000)
827 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT
) {
828 printf (" EFI_FVB2_ALIGNMENT\n");
831 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
832 printf (" EFI_FVB2_ALIGNMENT_2\n");
835 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
836 printf (" EFI_FVB2_ALIGNMENT_4\n");
839 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
840 printf (" EFI_FVB2_ALIGNMENT_8\n");
843 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
844 printf (" EFI_FVB2_ALIGNMENT_16\n");
847 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
848 printf (" EFI_FVB2_ALIGNMENT_32\n");
851 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
852 printf (" EFI_FVB2_ALIGNMENT_64\n");
855 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
856 printf (" EFI_FVB2_ALIGNMENT_128\n");
859 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
860 printf (" EFI_FVB2_ALIGNMENT_256\n");
863 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
864 printf (" EFI_FVB2_ALIGNMENT_512\n");
867 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
868 printf (" EFI_FVB2_ALIGNMENT_1K\n");
871 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
872 printf (" EFI_FVB2_ALIGNMENT_2K\n");
875 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
876 printf (" EFI_FVB2_ALIGNMENT_4K\n");
879 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
880 printf (" EFI_FVB2_ALIGNMENT_8K\n");
883 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
884 printf (" EFI_FVB2_ALIGNMENT_16K\n");
887 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
888 printf (" EFI_FVB2_ALIGNMENT_32K\n");
891 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
892 printf (" EFI_FVB2_ALIGNMENT_64K\n");
897 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_CAP
) {
898 printf (" EFI_FVB2_READ_LOCK_CAP\n");
901 if (VolumeHeader
.Attributes
& EFI_FVB2_READ_LOCK_STATUS
) {
902 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
905 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_CAP
) {
906 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
909 if (VolumeHeader
.Attributes
& EFI_FVB2_WRITE_LOCK_STATUS
) {
910 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
913 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1
) {
914 printf (" EFI_FVB2_ALIGNMENT_1\n");
917 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2
) {
918 printf (" EFI_FVB2_ALIGNMENT_2\n");
921 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4
) {
922 printf (" EFI_FVB2_ALIGNMENT_4\n");
925 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8
) {
926 printf (" EFI_FVB2_ALIGNMENT_8\n");
929 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16
) {
930 printf (" EFI_FVB2_ALIGNMENT_16\n");
933 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32
) {
934 printf (" EFI_FVB2_ALIGNMENT_32\n");
937 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64
) {
938 printf (" EFI_FVB2_ALIGNMENT_64\n");
941 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128
) {
942 printf (" EFI_FVB2_ALIGNMENT_128\n");
945 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256
) {
946 printf (" EFI_FVB2_ALIGNMENT_256\n");
949 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512
) {
950 printf (" EFI_FVB2_ALIGNMENT_512\n");
953 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1K
) {
954 printf (" EFI_FVB2_ALIGNMENT_1K\n");
957 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2K
) {
958 printf (" EFI_FVB2_ALIGNMENT_2K\n");
961 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4K
) {
962 printf (" EFI_FVB2_ALIGNMENT_4K\n");
965 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8K
) {
966 printf (" EFI_FVB2_ALIGNMENT_8K\n");
969 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16K
) {
970 printf (" EFI_FVB2_ALIGNMENT_16K\n");
973 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32K
) {
974 printf (" EFI_FVB2_ALIGNMENT_32K\n");
977 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64K
) {
978 printf (" EFI_FVB2_ALIGNMENT_64K\n");
981 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128K
) {
982 printf (" EFI_FVB2_ALIGNMENT_128K\n");
985 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256K
) {
986 printf (" EFI_FVB2_ALIGNMENT_256K\n");
989 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512K
) {
990 printf (" EFI_FVB2_ALIGNMENT_512K\n");
993 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1M
) {
994 printf (" EFI_FVB2_ALIGNMENT_1M\n");
997 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2M
) {
998 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1001 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_4M
) {
1002 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1005 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_8M
) {
1006 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1009 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_16M
) {
1010 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1013 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_32M
) {
1014 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1017 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1018 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1021 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1022 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1025 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_64M
) {
1026 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1029 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_128M
) {
1030 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1033 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_256M
) {
1034 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1037 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_512M
) {
1038 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1041 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_1G
) {
1042 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1045 if (VolumeHeader
.Attributes
& EFI_FVB2_ALIGNMENT_2G
) {
1046 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1050 printf ("Header Length: 0x%08X\n", VolumeHeader
.HeaderLength
);
1051 printf ("File System ID: ");
1052 PrintGuid (&VolumeHeader
.FileSystemGuid
);
1056 printf ("Revision: 0x%04X\n", VolumeHeader
.Revision
);
1059 fread (&BlockMap
, sizeof (EFI_FV_BLOCK_MAP_ENTRY
), 1, InputFile
);
1060 BytesRead
+= sizeof (EFI_FV_BLOCK_MAP_ENTRY
);
1062 if (BlockMap
.NumBlocks
!= 0) {
1063 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap
.NumBlocks
);
1064 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap
.Length
);
1065 Size
+= BlockMap
.NumBlocks
* BlockMap
.Length
;
1068 } while (!(BlockMap
.NumBlocks
== 0 && BlockMap
.Length
== 0));
1070 if (BytesRead
!= VolumeHeader
.HeaderLength
) {
1071 printf ("ERROR: Header length not consistent with Block Maps!\n");
1075 if (VolumeHeader
.FvLength
!= Size
) {
1076 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
1080 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size
);
1085 // rewind (InputFile);
1093 EFI_FIRMWARE_VOLUME_HEADER
*FvImage
,
1094 EFI_FFS_FILE_HEADER
*FileHeader
,
1095 BOOLEAN ErasePolarity
1099 Routine Description:
1101 GC_TODO: Add function description
1105 FvImage - GC_TODO: add argument description
1106 FileHeader - GC_TODO: add argument description
1107 ErasePolarity - GC_TODO: add argument description
1111 EFI_SUCCESS - GC_TODO: Add description for return value
1112 EFI_ABORTED - GC_TODO: Add description for return value
1119 EFI_FFS_FILE_HEADER2 BlankHeader
;
1121 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
1123 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1127 // Check if we have free space
1129 HeaderSize
= FvBufGetFfsHeaderSize(FileHeader
);
1130 if (ErasePolarity
) {
1131 memset (&BlankHeader
, -1, HeaderSize
);
1133 memset (&BlankHeader
, 0, HeaderSize
);
1136 if (memcmp (&BlankHeader
, FileHeader
, HeaderSize
) == 0) {
1140 // Print file information.
1142 printf ("============================================================\n");
1144 printf ("File Name: ");
1145 PrintGuidToBuffer (&FileHeader
->Name
, GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
1146 printf ("%s ", GuidBuffer
);
1147 PrintGuidName (GuidBuffer
);
1151 // PrintGuid (&FileHeader->Name);
1154 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1155 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN
) FileHeader
- (UINTN
) FvImage
));
1156 printf ("File Length: 0x%08X\n", (unsigned) FileLength
);
1157 printf ("File Attributes: 0x%02X\n", FileHeader
->Attributes
);
1158 printf ("File State: 0x%02X\n", FileHeader
->State
);
1163 FileState
= GetFileState (ErasePolarity
, FileHeader
);
1165 switch (FileState
) {
1167 case EFI_FILE_HEADER_CONSTRUCTION
:
1168 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1171 case EFI_FILE_HEADER_INVALID
:
1172 printf (" EFI_FILE_HEADER_INVALID\n");
1175 case EFI_FILE_HEADER_VALID
:
1176 printf (" EFI_FILE_HEADER_VALID\n");
1177 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1178 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1179 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1180 if (Checksum
!= 0) {
1181 printf ("ERROR: Header checksum invalid.\n");
1187 case EFI_FILE_DELETED
:
1188 printf (" EFI_FILE_DELETED\n");
1190 case EFI_FILE_MARKED_FOR_UPDATE
:
1191 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1193 case EFI_FILE_DATA_VALID
:
1194 printf (" EFI_FILE_DATA_VALID\n");
1197 // Calculate header checksum
1199 Checksum
= CalculateSum8 ((UINT8
*) FileHeader
, HeaderSize
);
1200 Checksum
= (UINT8
) (Checksum
- FileHeader
->IntegrityCheck
.Checksum
.File
);
1201 Checksum
= (UINT8
) (Checksum
- FileHeader
->State
);
1202 if (Checksum
!= 0) {
1203 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer
);
1207 FileLength
= FvBufGetFfsFileSize (FileHeader
);
1209 if (FileHeader
->Attributes
& FFS_ATTRIB_CHECKSUM
) {
1211 // Calculate file checksum
1213 Checksum
= CalculateSum8 ((UINT8
*)FileHeader
+ HeaderSize
, FileLength
- HeaderSize
);
1214 Checksum
= Checksum
+ FileHeader
->IntegrityCheck
.Checksum
.File
;
1215 if (Checksum
!= 0) {
1216 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer
);
1220 if (FileHeader
->IntegrityCheck
.Checksum
.File
!= FFS_FIXED_CHECKSUM
) {
1221 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
);
1225 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1227 // Verify tail if present
1229 if (FileHeader
->Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
1231 // Verify tail is complement of integrity check field in the header.
1233 Tail
= (UINT16
*) ((UINTN
) FileHeader
+ GetLength (FileHeader
->Size
) - sizeof (EFI_FFS_INTEGRITY_CHECK
));
1234 if (FileHeader
->IntegrityCheck
.TailReference
!= (UINT16
)~(*Tail
)) {
1235 Error (NULL
, 0, 0003, "error parsing FFS file", \
1236 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer
);
1244 Error (NULL
, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer
);
1248 printf ("File Type: 0x%02X ", FileHeader
->Type
);
1250 switch (FileHeader
->Type
) {
1252 case EFI_FV_FILETYPE_RAW
:
1253 printf ("EFI_FV_FILETYPE_RAW\n");
1256 case EFI_FV_FILETYPE_FREEFORM
:
1257 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1260 case EFI_FV_FILETYPE_SECURITY_CORE
:
1261 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1264 case EFI_FV_FILETYPE_PEI_CORE
:
1265 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1268 case EFI_FV_FILETYPE_DXE_CORE
:
1269 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1272 case EFI_FV_FILETYPE_PEIM
:
1273 printf ("EFI_FV_FILETYPE_PEIM\n");
1276 case EFI_FV_FILETYPE_DRIVER
:
1277 printf ("EFI_FV_FILETYPE_DRIVER\n");
1280 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
1281 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1284 case EFI_FV_FILETYPE_APPLICATION
:
1285 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1288 case EFI_FV_FILETYPE_SMM
:
1289 printf ("EFI_FV_FILETYPE_SMM\n");
1292 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
1293 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1296 case EFI_FV_FILETYPE_COMBINED_SMM_DXE
:
1297 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1300 case EFI_FV_FILETYPE_SMM_CORE
:
1301 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1304 case EFI_FV_FILETYPE_FFS_PAD
:
1305 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1309 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader
->Type
);
1314 switch (FileHeader
->Type
) {
1316 case EFI_FV_FILETYPE_ALL
:
1317 case EFI_FV_FILETYPE_RAW
:
1318 case EFI_FV_FILETYPE_FFS_PAD
:
1323 // All other files have sections
1325 Status
= ParseSection (
1326 (UINT8
*) ((UINTN
) FileHeader
+ HeaderSize
),
1327 FvBufGetFfsFileSize (FileHeader
) - HeaderSize
1329 if (EFI_ERROR (Status
)) {
1331 // printf ("ERROR: Parsing the FFS file.\n");
1343 IN VOID
*FileHandle
,
1344 IN UINTN FileOffset
,
1345 IN OUT UINT32
*ReadSize
,
1350 Routine Description:
1352 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1356 FileHandle - The handle to the PE/COFF file
1358 FileOffset - The offset, in bytes, into the file to read
1360 ReadSize - The number of bytes to read from the file starting at FileOffset
1362 Buffer - A pointer to the buffer to read the data into.
1366 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1370 CHAR8
*Destination8
;
1374 Destination8
= Buffer
;
1375 Source8
= (CHAR8
*) ((UINTN
) FileHandle
+ FileOffset
);
1378 *(Destination8
++) = *(Source8
++);
1385 SetAddressToSectionHeader (
1387 IN OUT UINT8
*FileBuffer
,
1388 IN UINT64 NewPe32BaseAddress
1392 Routine Description:
1394 Set new base address into the section header of PeImage
1398 FileName - Name of file
1399 FileBuffer - Pointer to PeImage.
1400 NewPe32BaseAddress - New Base Address for PE image.
1404 EFI_SUCCESS Set new base address into this image successfully.
1409 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1411 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1412 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1415 // Initialize context
1417 memset (&ImageContext
, 0, sizeof (ImageContext
));
1418 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1419 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1420 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1421 if (EFI_ERROR (Status
)) {
1422 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1426 if (ImageContext
.RelocationsStripped
) {
1427 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1432 // Get PeHeader pointer
1434 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1437 // Get section header list
1439 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1442 sizeof (EFI_IMAGE_FILE_HEADER
) +
1443 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1447 // Set base address into the first section header that doesn't point to code section.
1449 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1450 if ((SectionHeader
->Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) == 0) {
1451 *(UINT64
*) &SectionHeader
->PointerToRelocations
= NewPe32BaseAddress
;
1457 // BaseAddress is set to section header.
1465 IN OUT UINT8
*FileBuffer
,
1466 IN UINT64 NewPe32BaseAddress
1470 Routine Description:
1472 Set new base address into PeImage, and fix up PeImage based on new address.
1476 FileName - Name of file
1477 FileBuffer - Pointer to PeImage.
1478 NewPe32BaseAddress - New Base Address for PE image.
1482 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1483 EFI_SUCCESS - Update PeImage is correctly.
1488 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext
;
1490 EFI_IMAGE_OPTIONAL_HEADER_UNION
*ImgHdr
;
1491 UINT8
*MemoryImagePointer
;
1492 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1495 // Initialize context
1497 memset (&ImageContext
, 0, sizeof (ImageContext
));
1498 ImageContext
.Handle
= (VOID
*) FileBuffer
;
1499 ImageContext
.ImageRead
= (PE_COFF_LOADER_READ_FILE
) RebaseImageRead
;
1500 Status
= PeCoffLoaderGetImageInfo (&ImageContext
);
1501 if (EFI_ERROR (Status
)) {
1502 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName
);
1506 if (ImageContext
.RelocationsStripped
) {
1507 Error (NULL
, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName
);
1512 // Get PeHeader pointer
1514 ImgHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)(FileBuffer
+ ImageContext
.PeCoffHeaderOffset
);
1517 // Load and Relocate Image Data
1519 MemoryImagePointer
= (UINT8
*) malloc ((UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1520 if (MemoryImagePointer
== NULL
) {
1521 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName
);
1522 return EFI_OUT_OF_RESOURCES
;
1524 memset ((VOID
*) MemoryImagePointer
, 0, (UINTN
) ImageContext
.ImageSize
+ ImageContext
.SectionAlignment
);
1525 ImageContext
.ImageAddress
= ((UINTN
) MemoryImagePointer
+ ImageContext
.SectionAlignment
- 1) & (~((INT64
)ImageContext
.SectionAlignment
- 1));
1527 Status
= PeCoffLoaderLoadImage (&ImageContext
);
1528 if (EFI_ERROR (Status
)) {
1529 Error (NULL
, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName
);
1530 free ((VOID
*) MemoryImagePointer
);
1534 ImageContext
.DestinationAddress
= NewPe32BaseAddress
;
1535 Status
= PeCoffLoaderRelocateImage (&ImageContext
);
1536 if (EFI_ERROR (Status
)) {
1537 Error (NULL
, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName
);
1538 free ((VOID
*) MemoryImagePointer
);
1543 // Copy Relocated data to raw image file.
1545 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1548 sizeof (EFI_IMAGE_FILE_HEADER
) +
1549 ImgHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
1552 for (Index
= 0; Index
< ImgHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++, SectionHeader
++) {
1554 FileBuffer
+ SectionHeader
->PointerToRawData
,
1555 (VOID
*) (UINTN
) (ImageContext
.ImageAddress
+ SectionHeader
->VirtualAddress
),
1556 SectionHeader
->SizeOfRawData
1560 free ((VOID
*) MemoryImagePointer
);
1563 // Update Image Base Address
1565 if ((ImgHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) && (ImgHdr
->Pe32
.FileHeader
.Machine
!= IMAGE_FILE_MACHINE_IA64
)) {
1566 ImgHdr
->Pe32
.OptionalHeader
.ImageBase
= (UINT32
) NewPe32BaseAddress
;
1567 } else if (ImgHdr
->Pe32Plus
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1568 ImgHdr
->Pe32Plus
.OptionalHeader
.ImageBase
= NewPe32BaseAddress
;
1570 Error (NULL
, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1571 ImgHdr
->Pe32
.OptionalHeader
.Magic
,
1578 // Set new base address into section header
1580 Status
= SetAddressToSectionHeader (FileName
, FileBuffer
, NewPe32BaseAddress
);
1587 IN CHAR8
* DefaultPath
,
1588 IN CHAR8
* AppendPath
,
1592 UINT32 DefaultPathLen
;
1595 DefaultPathLen
= strlen(DefaultPath
);
1596 strcpy(NewPath
, DefaultPath
);
1598 for (; Index
< DefaultPathLen
; Index
++) {
1599 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1600 if (NewPath
[Index
+ 1] != '\0') {
1601 NewPath
[Index
] = '/';
1605 if (NewPath
[Index
-1] != '/') {
1606 NewPath
[Index
] = '/';
1607 NewPath
[Index
+ 1] = '\0';
1609 strcat(NewPath
, AppendPath
);
1615 IN UINT8
*SectionBuffer
,
1616 IN UINT32 BufferLength
1620 Routine Description:
1626 SectionBuffer - Buffer containing the section to parse.
1627 BufferLength - Length of SectionBuffer
1631 EFI_SECTION_ERROR - Problem with section parsing.
1632 (a) compression errors
1633 (b) unrecognized section
1634 EFI_UNSUPPORTED - Do not know how to parse the section.
1635 EFI_SUCCESS - Section successfully parsed.
1636 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1640 EFI_SECTION_TYPE Type
;
1642 UINT32 SectionLength
;
1643 UINT32 SectionHeaderLen
;
1646 UINT32 ParsedLength
;
1647 UINT8
*CompressedBuffer
;
1648 UINT32 CompressedLength
;
1649 UINT8
*UncompressedBuffer
;
1650 UINT32 UncompressedLength
;
1651 UINT8
*ToolOutputBuffer
;
1652 UINT32 ToolOutputLength
;
1653 UINT8 CompressionType
;
1656 UINT8
*ScratchBuffer
;
1657 DECOMPRESS_FUNCTION DecompressFunction
;
1658 GETINFO_FUNCTION GetInfoFunction
;
1660 CHAR8
*ExtractionTool
;
1661 CHAR8
*ToolInputFile
;
1662 CHAR8
*ToolOutputFile
;
1663 CHAR8
*SystemCommand
;
1668 CHAR8
*ToolInputFileName
;
1669 CHAR8
*ToolOutputFileName
;
1673 ToolInputFileName
= NULL
;
1674 ToolOutputFileName
= NULL
;
1676 while (ParsedLength
< BufferLength
) {
1677 Ptr
= SectionBuffer
+ ParsedLength
;
1679 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1680 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1683 // This is sort of an odd check, but is necessary because FFS files are
1684 // padded to a QWORD boundary, meaning there is potentially a whole section
1685 // header worth of 0xFF bytes.
1687 if (SectionLength
== 0xffffff && Type
== 0xff) {
1693 // Get real section file size
1695 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1696 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1698 SectionName
= SectionNameToStr (Type
);
1699 if (SectionName
!= NULL
) {
1700 printf ("------------------------------------------------------------\n");
1701 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1706 case EFI_SECTION_RAW
:
1707 case EFI_SECTION_PIC
:
1708 case EFI_SECTION_TE
:
1709 // default is no more information
1712 case EFI_SECTION_PE32
:
1714 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1715 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1716 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1719 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1720 SectionLength
- SectionHeaderLen
1723 SystemCommand
= malloc (
1724 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1725 strlen (OpenSslPath
) +
1726 strlen (ToolInputFileName
) +
1727 strlen (ToolOutputFileName
) +
1730 if (SystemCommand
== NULL
) {
1731 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1732 return EFI_OUT_OF_RESOURCES
;
1736 OPENSSL_COMMAND_FORMAT_STRING
,
1742 if (system (SystemCommand
) != EFI_SUCCESS
) {
1743 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1750 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1751 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1754 fseek(fp
,0,SEEK_SET
);
1755 fseek(fp
,0,SEEK_END
);
1756 nFileLen
= ftell(fp
);
1757 fseek(fp
,0,SEEK_SET
);
1758 StrLine
= malloc(nFileLen
);
1759 if (StrLine
== NULL
) {
1761 free (SystemCommand
);
1762 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1763 return EFI_OUT_OF_RESOURCES
;
1765 fgets(StrLine
, nFileLen
, fp
);
1766 NewStr
= strrchr (StrLine
, '=');
1767 printf (" SHA1: %s\n", NewStr
+ 1);
1772 remove(ToolInputFileName
);
1773 remove(ToolOutputFileName
);
1774 free (SystemCommand
);
1778 case EFI_SECTION_USER_INTERFACE
:
1779 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1780 if (UIFileName
== NULL
) {
1781 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1782 return EFI_OUT_OF_RESOURCES
;
1784 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1785 printf (" String: %s\n", UIFileName
);
1789 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1790 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1791 if (EFI_ERROR (Status
)) {
1792 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1793 return EFI_SECTION_ERROR
;
1797 case EFI_SECTION_COMPATIBILITY16
:
1798 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1800 // Section does not contain any further header information.
1804 case EFI_SECTION_PEI_DEPEX
:
1805 case EFI_SECTION_DXE_DEPEX
:
1806 case EFI_SECTION_SMM_DEPEX
:
1807 DumpDepexSection (Ptr
, SectionLength
);
1810 case EFI_SECTION_VERSION
:
1811 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1812 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1815 case EFI_SECTION_COMPRESSION
:
1816 UncompressedBuffer
= NULL
;
1817 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1818 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1819 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1820 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1822 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1823 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1824 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1826 CompressedLength
= SectionLength
- RealHdrLen
;
1827 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1829 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1830 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1831 if (CompressedLength
!= UncompressedLength
) {
1836 "file is not compressed, but the compressed length does not match the uncompressed length",
1839 return EFI_SECTION_ERROR
;
1842 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1843 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1844 GetInfoFunction
= EfiGetInfo
;
1845 DecompressFunction
= EfiDecompress
;
1846 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1848 CompressedBuffer
= Ptr
+ RealHdrLen
;
1850 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1851 if (EFI_ERROR (Status
)) {
1852 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1853 return EFI_SECTION_ERROR
;
1856 if (DstSize
!= UncompressedLength
) {
1857 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1858 return EFI_SECTION_ERROR
;
1861 ScratchBuffer
= malloc (ScratchSize
);
1862 if (ScratchBuffer
== NULL
) {
1863 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1864 return EFI_OUT_OF_RESOURCES
;
1866 UncompressedBuffer
= malloc (UncompressedLength
);
1867 if (UncompressedBuffer
== NULL
) {
1868 free (ScratchBuffer
);
1869 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1870 return EFI_OUT_OF_RESOURCES
;
1872 Status
= DecompressFunction (
1880 free (ScratchBuffer
);
1881 if (EFI_ERROR (Status
)) {
1882 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1883 free (UncompressedBuffer
);
1884 return EFI_SECTION_ERROR
;
1887 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1888 return EFI_SECTION_ERROR
;
1891 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1893 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1895 // We need to deallocate Buffer
1897 free (UncompressedBuffer
);
1900 if (EFI_ERROR (Status
)) {
1901 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1902 return EFI_SECTION_ERROR
;
1906 case EFI_SECTION_GUID_DEFINED
:
1907 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1908 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1909 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1910 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1912 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1913 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1914 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1916 printf (" SectionDefinitionGuid: ");
1917 PrintGuid (EfiGuid
);
1919 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1920 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1923 LookupGuidedSectionToolPath (
1924 mParsedGuidedSectionTools
,
1928 if (ExtractionTool
!= NULL
) {
1930 ToolInputFile
= CloneString (tmpnam (NULL
));
1931 ToolOutputFile
= CloneString (tmpnam (NULL
));
1933 char tmp1
[] = "/tmp/fileXXXXXX";
1934 char tmp2
[] = "/tmp/fileXXXXXX";
1937 fd1
= mkstemp(tmp1
);
1938 fd2
= mkstemp(tmp2
);
1939 ToolInputFile
= CloneString(tmp1
);
1940 ToolOutputFile
= CloneString(tmp2
);
1945 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1946 if (ToolInputFile
!= NULL
) {
1947 free (ToolInputFile
);
1949 if (ToolOutputFile
!= NULL
) {
1950 free (ToolOutputFile
);
1952 free (ExtractionTool
);
1954 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1955 return EFI_OUT_OF_RESOURCES
;
1959 // Construction 'system' command string
1961 SystemCommand
= malloc (
1962 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1963 strlen (ExtractionTool
) +
1964 strlen (ToolInputFile
) +
1965 strlen (ToolOutputFile
) +
1968 if (SystemCommand
== NULL
) {
1969 free (ToolInputFile
);
1970 free (ToolOutputFile
);
1971 free (ExtractionTool
);
1973 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1974 return EFI_OUT_OF_RESOURCES
;
1978 EXTRACT_COMMAND_FORMAT_STRING
,
1983 free (ExtractionTool
);
1988 (CHAR8
*) SectionBuffer
+ DataOffset
,
1989 BufferLength
- DataOffset
1992 system (SystemCommand
);
1993 remove (ToolInputFile
);
1994 free (ToolInputFile
);
1999 (CHAR8
**)&ToolOutputBuffer
,
2002 remove (ToolOutputFile
);
2003 free (ToolOutputFile
);
2004 free (SystemCommand
);
2005 if (EFI_ERROR (Status
)) {
2006 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2007 return EFI_SECTION_ERROR
;
2010 Status
= ParseSection (
2014 if (EFI_ERROR (Status
)) {
2015 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2016 return EFI_SECTION_ERROR
;
2020 // Check for CRC32 sections which we can handle internally if needed.
2022 } else if (!CompareGuid (
2024 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2028 // CRC32 guided section
2030 Status
= ParseSection (
2031 SectionBuffer
+ DataOffset
,
2032 BufferLength
- DataOffset
2034 if (EFI_ERROR (Status
)) {
2035 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2036 return EFI_SECTION_ERROR
;
2040 // We don't know how to parse it now.
2042 Error (NULL
, 0, 0003, "Error parsing section", \
2043 "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).");
2044 return EFI_UNSUPPORTED
;
2050 // Unknown section, return error
2052 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2053 return EFI_SECTION_ERROR
;
2056 ParsedLength
+= SectionLength
;
2058 // We make then next section begin on a 4-byte boundary
2060 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2063 if (ParsedLength
< BufferLength
) {
2064 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2065 return EFI_SECTION_ERROR
;
2074 IN UINT32 SectionLength
2078 Routine Description:
2080 GC_TODO: Add function description
2084 Ptr - GC_TODO: add argument description
2085 SectionLength - GC_TODO: add argument description
2089 EFI_SUCCESS - GC_TODO: Add description for return value
2093 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2096 // Need at least a section header + data
2098 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2102 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2103 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2104 while (SectionLength
> 0) {
2107 case EFI_DEP_BEFORE
:
2108 printf ("BEFORE\n");
2121 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2122 printf ("%s ", GuidBuffer
);
2123 PrintGuidName (GuidBuffer
);
2126 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2129 SectionLength
-= 17;
2163 printf ("END DEPEX\n");
2175 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2189 Routine Description:
2191 GC_TODO: Add function description
2195 GuidStr - GC_TODO: add argument description
2199 EFI_SUCCESS - GC_TODO: Add description for return value
2200 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2204 GUID_TO_BASENAME
*GPtr
;
2206 // If we have a list of guid-to-basenames, then go through the list to
2207 // look for a guid string match. If found, print the basename to stdout,
2208 // otherwise return a failure.
2210 GPtr
= mGuidBaseNameList
;
2211 while (GPtr
!= NULL
) {
2212 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2213 printf ("%s", GPtr
->BaseName
);
2220 return EFI_INVALID_PARAMETER
;
2224 ParseGuidBaseNameFile (
2229 Routine Description:
2231 GC_TODO: Add function description
2235 FileName - GC_TODO: add argument description
2239 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2240 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2241 EFI_SUCCESS - GC_TODO: Add description for return value
2246 CHAR8 Line
[MAX_LINE_LEN
];
2247 CHAR8 FormatString
[MAX_LINE_LEN
];
2248 GUID_TO_BASENAME
*GPtr
;
2250 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2251 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2252 return EFI_DEVICE_ERROR
;
2256 // Generate the format string for fscanf
2261 (unsigned) sizeof (GPtr
->Guid
) - 1,
2262 (unsigned) sizeof (GPtr
->BaseName
) - 1
2265 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2267 // Allocate space for another guid/basename element
2269 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2272 return EFI_OUT_OF_RESOURCES
;
2275 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2276 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2277 GPtr
->Next
= mGuidBaseNameList
;
2278 mGuidBaseNameList
= GPtr
;
2281 // Some sort of error. Just continue.
2292 FreeGuidBaseNameList (
2297 Routine Description:
2299 GC_TODO: Add function description
2307 EFI_SUCCESS - GC_TODO: Add description for return value
2311 GUID_TO_BASENAME
*Next
;
2313 while (mGuidBaseNameList
!= NULL
) {
2314 Next
= mGuidBaseNameList
->Next
;
2315 free (mGuidBaseNameList
);
2316 mGuidBaseNameList
= Next
;
2325 LoadGuidedSectionToolsTxt (
2326 IN CHAR8
* FirmwareVolumeFilename
2329 CHAR8
* PeerFilename
;
2336 Places
[0] = FirmwareVolumeFilename
;
2337 //Places[1] = mUtilityFilename;
2339 mParsedGuidedSectionTools
= NULL
;
2341 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2342 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2343 //printf("Loading %s...\n", PeerFilename);
2344 if (OsPathExists (PeerFilename
)) {
2345 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2347 free (PeerFilename
);
2348 if (mParsedGuidedSectionTools
!= NULL
) {
2361 Routine Description:
2363 GC_TODO: Add function description
2371 GC_TODO: add return values
2378 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2381 // Copyright declaration
2383 fprintf (stdout
, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
2384 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2389 fprintf (stdout
, "optional arguments:\n");
2390 fprintf (stdout
, " -h, --help\n\
2391 Show this help message and exit\n");
2392 fprintf (stdout
, " --version\n\
2393 Show program's version number and exit\n");
2394 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2395 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2396 fprintf (stdout
, " -v, --verbose\n\
2397 Print informational statements\n");
2398 fprintf (stdout
, " -q, --quiet\n\
2399 Returns the exit code, error messages will be displayed\n");
2400 fprintf (stdout
, " -s, --silent\n\
2401 Returns only the exit code; informational and error\n\
2402 messages are not displayed\n");
2403 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2404 Parse the basename to file-guid cross reference file(s)\n");
2405 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2406 The offset from the start of the input file to start \n\
2407 processing an FV\n");
2408 fprintf (stdout
, " --hash\n\
2409 Generate HASH value of the entire PE image\n");
2410 fprintf (stdout
, " --sfo\n\
2411 Reserved for future use\n");