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
;
1593 DefaultPathLen
= strlen(DefaultPath
);
1594 strcpy(NewPath
, DefaultPath
);
1596 for (; Index
< DefaultPathLen
; Index
++) {
1597 if (NewPath
[Index
] == '\\' || NewPath
[Index
] == '/') {
1598 if (NewPath
[Index
+ 1] != '\0') {
1599 NewPath
[Index
] = '/';
1603 if (NewPath
[Index
-1] != '/') {
1604 NewPath
[Index
] = '/';
1605 NewPath
[Index
+ 1] = '\0';
1607 strcat(NewPath
, AppendPath
);
1613 IN UINT8
*SectionBuffer
,
1614 IN UINT32 BufferLength
1618 Routine Description:
1624 SectionBuffer - Buffer containing the section to parse.
1625 BufferLength - Length of SectionBuffer
1629 EFI_SECTION_ERROR - Problem with section parsing.
1630 (a) compression errors
1631 (b) unrecognized section
1632 EFI_UNSUPPORTED - Do not know how to parse the section.
1633 EFI_SUCCESS - Section successfully parsed.
1634 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1638 EFI_SECTION_TYPE Type
;
1640 UINT32 SectionLength
;
1641 UINT32 SectionHeaderLen
;
1644 UINT32 ParsedLength
;
1645 UINT8
*CompressedBuffer
;
1646 UINT32 CompressedLength
;
1647 UINT8
*UncompressedBuffer
;
1648 UINT32 UncompressedLength
;
1649 UINT8
*ToolOutputBuffer
;
1650 UINT32 ToolOutputLength
;
1651 UINT8 CompressionType
;
1654 UINT8
*ScratchBuffer
;
1655 DECOMPRESS_FUNCTION DecompressFunction
;
1656 GETINFO_FUNCTION GetInfoFunction
;
1658 CHAR8
*ExtractionTool
;
1659 CHAR8
*ToolInputFile
;
1660 CHAR8
*ToolOutputFile
;
1661 CHAR8
*SystemCommand
;
1666 CHAR8
*ToolInputFileName
;
1667 CHAR8
*ToolOutputFileName
;
1671 ToolInputFileName
= NULL
;
1672 ToolOutputFileName
= NULL
;
1674 while (ParsedLength
< BufferLength
) {
1675 Ptr
= SectionBuffer
+ ParsedLength
;
1677 SectionLength
= GetLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
1678 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
1681 // This is sort of an odd check, but is necessary because FFS files are
1682 // padded to a QWORD boundary, meaning there is potentially a whole section
1683 // header worth of 0xFF bytes.
1685 if (SectionLength
== 0xffffff && Type
== 0xff) {
1691 // Get real section file size
1693 SectionLength
= GetSectionFileLength ((EFI_COMMON_SECTION_HEADER
*) Ptr
);
1694 SectionHeaderLen
= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
1696 SectionName
= SectionNameToStr (Type
);
1697 if (SectionName
!= NULL
) {
1698 printf ("------------------------------------------------------------\n");
1699 printf (" Type: %s\n Size: 0x%08X\n", SectionName
, (unsigned) SectionLength
);
1704 case EFI_SECTION_RAW
:
1705 case EFI_SECTION_PIC
:
1706 case EFI_SECTION_TE
:
1707 // default is no more information
1710 case EFI_SECTION_PE32
:
1712 ToolInputFileName
= "edk2Temp_InputEfi.tmp";
1713 ToolOutputFileName
= "edk2Temp_OutputHash.tmp";
1714 RebaseImage(ToolInputFileName
, (UINT8
*)Ptr
+ SectionHeaderLen
, 0);
1717 (CHAR8
*)Ptr
+ SectionHeaderLen
,
1718 SectionLength
- SectionHeaderLen
1721 SystemCommand
= malloc (
1722 strlen (OPENSSL_COMMAND_FORMAT_STRING
) +
1723 strlen (OpenSslPath
) +
1724 strlen (ToolInputFileName
) +
1725 strlen (ToolOutputFileName
) +
1728 if (SystemCommand
== NULL
) {
1729 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1730 return EFI_OUT_OF_RESOURCES
;
1734 OPENSSL_COMMAND_FORMAT_STRING
,
1740 if (system (SystemCommand
) != EFI_SUCCESS
) {
1741 Error (NULL
, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL
);
1748 if((fp
= fopen(ToolOutputFileName
,"r")) == NULL
) {
1749 Error (NULL
, 0, 0004, "Hash the PE32 image failed.", NULL
);
1752 fseek(fp
,0,SEEK_SET
);
1753 fseek(fp
,0,SEEK_END
);
1754 nFileLen
= ftell(fp
);
1755 fseek(fp
,0,SEEK_SET
);
1756 StrLine
= malloc(nFileLen
);
1757 if (StrLine
== NULL
) {
1759 free (SystemCommand
);
1760 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1761 return EFI_OUT_OF_RESOURCES
;
1763 fgets(StrLine
, nFileLen
, fp
);
1764 NewStr
= strrchr (StrLine
, '=');
1765 printf (" SHA1: %s\n", NewStr
+ 1);
1770 remove(ToolInputFileName
);
1771 remove(ToolOutputFileName
);
1772 free (SystemCommand
);
1776 case EFI_SECTION_USER_INTERFACE
:
1777 UIFileName
= (CHAR8
*) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
) + 1);
1778 if (UIFileName
== NULL
) {
1779 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1780 return EFI_OUT_OF_RESOURCES
;
1782 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION
*) Ptr
)->FileNameString
, UIFileName
);
1783 printf (" String: %s\n", UIFileName
);
1787 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
1788 Status
= PrintFvInfo (Ptr
+ SectionHeaderLen
, TRUE
);
1789 if (EFI_ERROR (Status
)) {
1790 Error (NULL
, 0, 0003, "printing of FV section contents failed", NULL
);
1791 return EFI_SECTION_ERROR
;
1795 case EFI_SECTION_COMPATIBILITY16
:
1796 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
1798 // Section does not contain any further header information.
1802 case EFI_SECTION_PEI_DEPEX
:
1803 case EFI_SECTION_DXE_DEPEX
:
1804 case EFI_SECTION_SMM_DEPEX
:
1805 DumpDepexSection (Ptr
, SectionLength
);
1808 case EFI_SECTION_VERSION
:
1809 printf (" Build Number: 0x%02X\n", *(UINT16
*)(Ptr
+ SectionHeaderLen
));
1810 printf (" Version Strg: %s\n", (char*) (Ptr
+ SectionHeaderLen
+ sizeof (UINT16
)));
1813 case EFI_SECTION_COMPRESSION
:
1814 UncompressedBuffer
= NULL
;
1815 if (SectionHeaderLen
== sizeof (EFI_COMMON_SECTION_HEADER
)) {
1816 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION
);
1817 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->UncompressedLength
;
1818 CompressionType
= ((EFI_COMPRESSION_SECTION
*)Ptr
)->CompressionType
;
1820 RealHdrLen
= sizeof(EFI_COMPRESSION_SECTION2
);
1821 UncompressedLength
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->UncompressedLength
;
1822 CompressionType
= ((EFI_COMPRESSION_SECTION2
*)Ptr
)->CompressionType
;
1824 CompressedLength
= SectionLength
- RealHdrLen
;
1825 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength
);
1827 if (CompressionType
== EFI_NOT_COMPRESSED
) {
1828 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1829 if (CompressedLength
!= UncompressedLength
) {
1834 "file is not compressed, but the compressed length does not match the uncompressed length",
1837 return EFI_SECTION_ERROR
;
1840 UncompressedBuffer
= Ptr
+ RealHdrLen
;
1841 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1842 GetInfoFunction
= EfiGetInfo
;
1843 DecompressFunction
= EfiDecompress
;
1844 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1846 CompressedBuffer
= Ptr
+ RealHdrLen
;
1848 Status
= GetInfoFunction (CompressedBuffer
, CompressedLength
, &DstSize
, &ScratchSize
);
1849 if (EFI_ERROR (Status
)) {
1850 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
1851 return EFI_SECTION_ERROR
;
1854 if (DstSize
!= UncompressedLength
) {
1855 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
1856 return EFI_SECTION_ERROR
;
1859 ScratchBuffer
= malloc (ScratchSize
);
1860 if (ScratchBuffer
== NULL
) {
1861 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1862 return EFI_OUT_OF_RESOURCES
;
1864 UncompressedBuffer
= malloc (UncompressedLength
);
1865 if (UncompressedBuffer
== NULL
) {
1866 free (ScratchBuffer
);
1867 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1868 return EFI_OUT_OF_RESOURCES
;
1870 Status
= DecompressFunction (
1878 free (ScratchBuffer
);
1879 if (EFI_ERROR (Status
)) {
1880 Error (NULL
, 0, 0003, "decompress failed", NULL
);
1881 free (UncompressedBuffer
);
1882 return EFI_SECTION_ERROR
;
1885 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
1886 return EFI_SECTION_ERROR
;
1889 Status
= ParseSection (UncompressedBuffer
, UncompressedLength
);
1891 if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
1893 // We need to deallocate Buffer
1895 free (UncompressedBuffer
);
1898 if (EFI_ERROR (Status
)) {
1899 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
1900 return EFI_SECTION_ERROR
;
1904 case EFI_SECTION_GUID_DEFINED
:
1905 if (SectionHeaderLen
== sizeof(EFI_COMMON_SECTION_HEADER
)) {
1906 EfiGuid
= &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
;
1907 DataOffset
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
;
1908 Attributes
= ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->Attributes
;
1910 EfiGuid
= &((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->SectionDefinitionGuid
;
1911 DataOffset
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->DataOffset
;
1912 Attributes
= ((EFI_GUID_DEFINED_SECTION2
*) Ptr
)->Attributes
;
1914 printf (" SectionDefinitionGuid: ");
1915 PrintGuid (EfiGuid
);
1917 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset
);
1918 printf (" Attributes: 0x%04X\n", (unsigned) Attributes
);
1921 LookupGuidedSectionToolPath (
1922 mParsedGuidedSectionTools
,
1926 if (ExtractionTool
!= NULL
) {
1928 ToolInputFile
= CloneString (tmpnam (NULL
));
1929 ToolOutputFile
= CloneString (tmpnam (NULL
));
1931 char tmp1
[] = "/tmp/fileXXXXXX";
1932 char tmp2
[] = "/tmp/fileXXXXXX";
1935 fd1
= mkstemp(tmp1
);
1936 fd2
= mkstemp(tmp2
);
1937 ToolInputFile
= CloneString(tmp1
);
1938 ToolOutputFile
= CloneString(tmp2
);
1943 if ((ToolInputFile
== NULL
) || (ToolOutputFile
== NULL
)) {
1944 if (ToolInputFile
!= NULL
) {
1945 free (ToolInputFile
);
1947 if (ToolOutputFile
!= NULL
) {
1948 free (ToolOutputFile
);
1950 free (ExtractionTool
);
1952 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1953 return EFI_OUT_OF_RESOURCES
;
1957 // Construction 'system' command string
1959 SystemCommand
= malloc (
1960 strlen (EXTRACT_COMMAND_FORMAT_STRING
) +
1961 strlen (ExtractionTool
) +
1962 strlen (ToolInputFile
) +
1963 strlen (ToolOutputFile
) +
1966 if (SystemCommand
== NULL
) {
1967 free (ToolInputFile
);
1968 free (ToolOutputFile
);
1969 free (ExtractionTool
);
1971 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
1972 return EFI_OUT_OF_RESOURCES
;
1976 EXTRACT_COMMAND_FORMAT_STRING
,
1981 free (ExtractionTool
);
1986 (CHAR8
*) SectionBuffer
+ DataOffset
,
1987 BufferLength
- DataOffset
1990 system (SystemCommand
);
1991 remove (ToolInputFile
);
1992 free (ToolInputFile
);
1997 (CHAR8
**)&ToolOutputBuffer
,
2000 remove (ToolOutputFile
);
2001 free (ToolOutputFile
);
2002 free (SystemCommand
);
2003 if (EFI_ERROR (Status
)) {
2004 Error (NULL
, 0, 0004, "unable to read decoded GUIDED section", NULL
);
2005 return EFI_SECTION_ERROR
;
2008 Status
= ParseSection (
2012 if (EFI_ERROR (Status
)) {
2013 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
2014 return EFI_SECTION_ERROR
;
2018 // Check for CRC32 sections which we can handle internally if needed.
2020 } else if (!CompareGuid (
2022 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2026 // CRC32 guided section
2028 Status
= ParseSection (
2029 SectionBuffer
+ DataOffset
,
2030 BufferLength
- DataOffset
2032 if (EFI_ERROR (Status
)) {
2033 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
2034 return EFI_SECTION_ERROR
;
2038 // We don't know how to parse it now.
2040 Error (NULL
, 0, 0003, "Error parsing section", \
2041 "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).");
2042 return EFI_UNSUPPORTED
;
2048 // Unknown section, return error
2050 Error (NULL
, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type
);
2051 return EFI_SECTION_ERROR
;
2054 ParsedLength
+= SectionLength
;
2056 // We make then next section begin on a 4-byte boundary
2058 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
2061 if (ParsedLength
< BufferLength
) {
2062 Error (NULL
, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL
);
2063 return EFI_SECTION_ERROR
;
2072 IN UINT32 SectionLength
2076 Routine Description:
2078 GC_TODO: Add function description
2082 Ptr - GC_TODO: add argument description
2083 SectionLength - GC_TODO: add argument description
2087 EFI_SUCCESS - GC_TODO: Add description for return value
2091 UINT8 GuidBuffer
[PRINTED_GUID_BUFFER_SIZE
];
2094 // Need at least a section header + data
2096 if (SectionLength
<= sizeof (EFI_COMMON_SECTION_HEADER
)) {
2100 Ptr
+= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2101 SectionLength
-= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER
*)Ptr
);
2102 while (SectionLength
> 0) {
2105 case EFI_DEP_BEFORE
:
2106 printf ("BEFORE\n");
2119 PrintGuidToBuffer ((EFI_GUID
*) (Ptr
+ 1), GuidBuffer
, sizeof (GuidBuffer
), TRUE
);
2120 printf ("%s ", GuidBuffer
);
2121 PrintGuidName (GuidBuffer
);
2124 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2127 SectionLength
-= 17;
2161 printf ("END DEPEX\n");
2173 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr
);
2187 Routine Description:
2189 GC_TODO: Add function description
2193 GuidStr - GC_TODO: add argument description
2197 EFI_SUCCESS - GC_TODO: Add description for return value
2198 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2202 GUID_TO_BASENAME
*GPtr
;
2204 // If we have a list of guid-to-basenames, then go through the list to
2205 // look for a guid string match. If found, print the basename to stdout,
2206 // otherwise return a failure.
2208 GPtr
= mGuidBaseNameList
;
2209 while (GPtr
!= NULL
) {
2210 if (_stricmp ((CHAR8
*) GuidStr
, (CHAR8
*) GPtr
->Guid
) == 0) {
2211 printf ("%s", GPtr
->BaseName
);
2218 return EFI_INVALID_PARAMETER
;
2222 ParseGuidBaseNameFile (
2227 Routine Description:
2229 GC_TODO: Add function description
2233 FileName - GC_TODO: add argument description
2237 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2238 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2239 EFI_SUCCESS - GC_TODO: Add description for return value
2244 CHAR8 Line
[MAX_LINE_LEN
];
2245 CHAR8 FormatString
[MAX_LINE_LEN
];
2246 GUID_TO_BASENAME
*GPtr
;
2248 if ((Fptr
= fopen (LongFilePath (FileName
), "r")) == NULL
) {
2249 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName
);
2250 return EFI_DEVICE_ERROR
;
2254 // Generate the format string for fscanf
2259 (unsigned) sizeof (GPtr
->Guid
) - 1,
2260 (unsigned) sizeof (GPtr
->BaseName
) - 1
2263 while (fgets (Line
, sizeof (Line
), Fptr
) != NULL
) {
2265 // Allocate space for another guid/basename element
2267 GPtr
= malloc (sizeof (GUID_TO_BASENAME
));
2270 return EFI_OUT_OF_RESOURCES
;
2273 memset ((char *) GPtr
, 0, sizeof (GUID_TO_BASENAME
));
2274 if (sscanf (Line
, FormatString
, GPtr
->Guid
, GPtr
->BaseName
) == 2) {
2275 GPtr
->Next
= mGuidBaseNameList
;
2276 mGuidBaseNameList
= GPtr
;
2279 // Some sort of error. Just continue.
2290 FreeGuidBaseNameList (
2295 Routine Description:
2297 GC_TODO: Add function description
2305 EFI_SUCCESS - GC_TODO: Add description for return value
2309 GUID_TO_BASENAME
*Next
;
2311 while (mGuidBaseNameList
!= NULL
) {
2312 Next
= mGuidBaseNameList
->Next
;
2313 free (mGuidBaseNameList
);
2314 mGuidBaseNameList
= Next
;
2323 LoadGuidedSectionToolsTxt (
2324 IN CHAR8
* FirmwareVolumeFilename
2327 CHAR8
* PeerFilename
;
2334 Places
[0] = FirmwareVolumeFilename
;
2335 //Places[1] = mUtilityFilename;
2337 mParsedGuidedSectionTools
= NULL
;
2339 for (Index
= 0; Index
< (sizeof(Places
)/sizeof(Places
[0])); Index
++) {
2340 PeerFilename
= OsPathPeerFilePath (Places
[Index
], "GuidedSectionTools.txt");
2341 //printf("Loading %s...\n", PeerFilename);
2342 if (OsPathExists (PeerFilename
)) {
2343 mParsedGuidedSectionTools
= ParseGuidedSectionToolsFile (PeerFilename
);
2345 free (PeerFilename
);
2346 if (mParsedGuidedSectionTools
!= NULL
) {
2359 Routine Description:
2361 GC_TODO: Add function description
2369 GC_TODO: add return values
2376 fprintf (stdout
, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME
);
2379 // Copyright declaration
2381 fprintf (stdout
, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");
2382 fprintf (stdout
, " Display Tiano Firmware Volume FFS image information\n\n");
2387 fprintf (stdout
, "optional arguments:\n");
2388 fprintf (stdout
, " -h, --help\n\
2389 Show this help message and exit\n");
2390 fprintf (stdout
, " --version\n\
2391 Show program's version number and exit\n");
2392 fprintf (stdout
, " -d [DEBUG], --debug [DEBUG]\n\
2393 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2394 fprintf (stdout
, " -v, --verbose\n\
2395 Print informational statements\n");
2396 fprintf (stdout
, " -q, --quiet\n\
2397 Returns the exit code, error messages will be displayed\n");
2398 fprintf (stdout
, " -s, --silent\n\
2399 Returns only the exit code; informational and error\n\
2400 messages are not displayed\n");
2401 fprintf (stdout
, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2402 Parse the basename to file-guid cross reference file(s)\n");
2403 fprintf (stdout
, " -f OFFSET, --offset OFFSET\n\
2404 The offset from the start of the input file to start \n\
2405 processing an FV\n");
2406 fprintf (stdout
, " --hash\n\
2407 Generate HASH value of the entire PE image\n");
2408 fprintf (stdout
, " --sfo\n\
2409 Reserved for future use\n");