Change SMM to MM in naming according to the recent PI specifications. Remove trailing whitespaces in some strings. Signed-off-by: Konstantin Aladyshev <aladyshev22@gmail.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn> Reviewed-by: Bob Feng <bob.c.feng@intel.com>
		
			
				
	
	
		
			2525 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2525 lines
		
	
	
		
			66 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| The tool dumps the contents of a firmware volume
 | |
| 
 | |
| Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| Copyright (c) 2022, Konstantin Aladyshev <aladyshev22@gmail.com><BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <ctype.h>
 | |
| #include <assert.h>
 | |
| #ifdef __GNUC__
 | |
| #include <unistd.h>
 | |
| #else
 | |
| #include <direct.h>
 | |
| #endif
 | |
| 
 | |
| #include <FvLib.h>
 | |
| #include <Common/UefiBaseTypes.h>
 | |
| #include <Common/UefiCapsule.h>
 | |
| #include <Common/PiFirmwareFile.h>
 | |
| #include <Common/PiFirmwareVolume.h>
 | |
| #include <Guid/PiFirmwareFileSystem.h>
 | |
| #include <IndustryStandard/PeImage.h>
 | |
| #include <Protocol/GuidedSectionExtraction.h>
 | |
| 
 | |
| #include "Compress.h"
 | |
| #include "Decompress.h"
 | |
| #include "VolInfo.h"
 | |
| #include "CommonLib.h"
 | |
| #include "EfiUtilityMsgs.h"
 | |
| #include "FirmwareVolumeBufferLib.h"
 | |
| #include "OsPath.h"
 | |
| #include "ParseGuidedSectionTools.h"
 | |
| #include "StringFuncs.h"
 | |
| #include "ParseInf.h"
 | |
| #include "PeCoffLib.h"
 | |
| 
 | |
| //
 | |
| // Utility global variables
 | |
| //
 | |
| 
 | |
| EFI_GUID  gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
 | |
| EFI_GUID  gPeiAprioriFileNameGuid = { 0x1b45cc0a, 0x156a, 0x428a, { 0XAF, 0x62,  0x49, 0x86, 0x4d, 0xa0, 0xe6, 0xe6 }};
 | |
| EFI_GUID  gAprioriGuid = { 0xFC510EE7, 0xFFDC, 0x11D4, { 0xBD, 0x41, 0x00, 0x80, 0xC7, 0x3C, 0x88, 0x81 }};
 | |
| 
 | |
| #define UTILITY_MAJOR_VERSION      1
 | |
| #define UTILITY_MINOR_VERSION      0
 | |
| 
 | |
| #define UTILITY_NAME         "VolInfo"
 | |
| 
 | |
| #define EFI_SECTION_ERROR EFIERR (100)
 | |
| 
 | |
| //
 | |
| // Structure to keep a list of guid-to-basenames
 | |
| //
 | |
| typedef struct _GUID_TO_BASENAME {
 | |
|   struct _GUID_TO_BASENAME  *Next;
 | |
|   INT8                      Guid[PRINTED_GUID_BUFFER_SIZE];
 | |
|   INT8                      BaseName[MAX_LINE_LEN];
 | |
| } GUID_TO_BASENAME;
 | |
| 
 | |
| static GUID_TO_BASENAME *mGuidBaseNameList = NULL;
 | |
| 
 | |
| //
 | |
| // Store GUIDed Section guid->tool mapping
 | |
| //
 | |
| EFI_HANDLE mParsedGuidedSectionTools = NULL;
 | |
| 
 | |
| CHAR8* mUtilityFilename = NULL;
 | |
| 
 | |
| BOOLEAN EnableHash = FALSE;
 | |
| CHAR8 *OpenSslPath = NULL;
 | |
| 
 | |
| EFI_STATUS
 | |
| ParseGuidBaseNameFile (
 | |
|   CHAR8    *FileName
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| FreeGuidBaseNameList (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| PrintGuidName (
 | |
|   IN UINT8    *GuidStr
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| ParseSection (
 | |
|   IN UINT8  *SectionBuffer,
 | |
|   IN UINT32 BufferLength
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| DumpDepexSection (
 | |
|   IN UINT8    *Ptr,
 | |
|   IN UINT32   SectionLength
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReadHeader (
 | |
|   IN FILE       *InputFile,
 | |
|   OUT UINT32    *FvSize,
 | |
|   OUT BOOLEAN   *ErasePolarity
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| PrintAprioriFile (
 | |
|   EFI_FFS_FILE_HEADER         *FileHeader
 | |
|   );
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| PrintFileInfo (
 | |
|   EFI_FIRMWARE_VOLUME_HEADER  *FvImage,
 | |
|   EFI_FFS_FILE_HEADER         *FileHeader,
 | |
|   BOOLEAN                     ErasePolarity
 | |
|   );
 | |
| 
 | |
| static
 | |
| EFI_STATUS
 | |
| PrintFvInfo (
 | |
|   IN VOID                         *Fv,
 | |
|   IN BOOLEAN                      IsChildFv
 | |
|   );
 | |
| 
 | |
| static
 | |
| VOID
 | |
| LoadGuidedSectionToolsTxt (
 | |
|   IN CHAR8* FirmwareVolumeFilename
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| CombinePath (
 | |
|   IN  CHAR8* DefaultPath,
 | |
|   IN  CHAR8* AppendPath,
 | |
|   OUT CHAR8* NewPath
 | |
| );
 | |
| 
 | |
| void
 | |
| Usage (
 | |
|   VOID
 | |
|   );
 | |
| 
 | |
| UINT32
 | |
| UnicodeStrLen (
 | |
|   IN CHAR16 *String
 | |
|   )
 | |
|   /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|   Returns the length of a null-terminated unicode string.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     String - The pointer to a null-terminated unicode string.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     N/A
 | |
| 
 | |
|   --*/
 | |
| {
 | |
|   UINT32  Length;
 | |
| 
 | |
|   for (Length = 0; *String != L'\0'; String++, Length++) {
 | |
|     ;
 | |
|   }
 | |
|   return Length;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Unicode2AsciiString (
 | |
|   IN  CHAR16 *Source,
 | |
|   OUT CHAR8  *Destination
 | |
|   )
 | |
|   /*++
 | |
| 
 | |
|   Routine Description:
 | |
| 
 | |
|   Convert a null-terminated unicode string to a null-terminated ascii string.
 | |
| 
 | |
|   Arguments:
 | |
| 
 | |
|     Source      - The pointer to the null-terminated input unicode string.
 | |
|     Destination - The pointer to the null-terminated output ascii string.
 | |
| 
 | |
|   Returns:
 | |
| 
 | |
|     N/A
 | |
| 
 | |
|   --*/
 | |
| {
 | |
|   while (*Source != '\0') {
 | |
|     *(Destination++) = (CHAR8) *(Source++);
 | |
|   }
 | |
|   //
 | |
|   // End the ascii with a NULL.
 | |
|   //
 | |
|   *Destination = '\0';
 | |
| }
 | |
| 
 | |
| int
 | |
| main (
 | |
|   int       argc,
 | |
|   char      *argv[]
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   argc  - GC_TODO: add argument description
 | |
|   ]     - GC_TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   GC_TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   FILE                        *InputFile;
 | |
|   int                         BytesRead;
 | |
|   EFI_FIRMWARE_VOLUME_HEADER  *FvImage;
 | |
|   UINT32                      FvSize;
 | |
|   EFI_STATUS                  Status;
 | |
|   int                         Offset;
 | |
|   BOOLEAN                     ErasePolarity;
 | |
|   UINT64                      LogLevel;
 | |
|   CHAR8                       *OpenSslEnv;
 | |
|   CHAR8                       *OpenSslCommand;
 | |
| 
 | |
|   SetUtilityName (UTILITY_NAME);
 | |
|   //
 | |
|   // Print utility header
 | |
|   //
 | |
|   printf ("%s Version %d.%d Build %s\n",
 | |
|     UTILITY_NAME,
 | |
|     UTILITY_MAJOR_VERSION,
 | |
|     UTILITY_MINOR_VERSION,
 | |
|     __BUILD_VERSION
 | |
|     );
 | |
| 
 | |
|   if (argc == 1) {
 | |
|     Usage ();
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   argc--;
 | |
|   argv++;
 | |
|   LogLevel = 0;
 | |
|   Offset = 0;
 | |
| 
 | |
|   //
 | |
|   // Look for help options
 | |
|   //
 | |
|   if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) ||
 | |
|       (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) {
 | |
|     Usage();
 | |
|     return  STATUS_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Version has already be printed, so just return success
 | |
|   //
 | |
|   if (strcmp(argv[0], "--version") == 0) {
 | |
|     return  STATUS_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If they specified -x xref guid/basename cross-reference files, process it.
 | |
|   // This will print the basename beside each file guid. To use it, specify
 | |
|   // -x xref_filename to processdsc, then use xref_filename as a parameter
 | |
|   // here.
 | |
|   //
 | |
|   while (argc > 0) {
 | |
|     if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) {
 | |
|       ParseGuidBaseNameFile (argv[1]);
 | |
|       printf("ParseGuidBaseNameFile: %s\n", argv[1]);
 | |
|       argc -= 2;
 | |
|       argv += 2;
 | |
|       continue;
 | |
|     }
 | |
|     if (strcmp(argv[0], "--offset") == 0) {
 | |
|       //
 | |
|       // Hex or decimal?
 | |
|       //
 | |
|       if ((argv[1][0] == '0') && (tolower ((int)argv[1][1]) == 'x')) {
 | |
|         if (sscanf (argv[1], "%x", &Offset) != 1) {
 | |
|           Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]);
 | |
|           return GetUtilityStatus ();
 | |
|         }
 | |
|       } else {
 | |
|         if (sscanf (argv[1], "%d", &Offset) != 1) {
 | |
|           Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]);
 | |
|           return GetUtilityStatus ();
 | |
|         }
 | |
|         //
 | |
|         // See if they said something like "64K"
 | |
|         //
 | |
|         if (tolower ((int)argv[1][strlen (argv[1]) - 1]) == 'k') {
 | |
|           Offset *= 1024;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       argc -= 2;
 | |
|       argv += 2;
 | |
|       continue;
 | |
|     }
 | |
|     if ((stricmp (argv[0], "--hash") == 0)) {
 | |
|       if (EnableHash == TRUE) {
 | |
|         //
 | |
|         // --hash already given in the option, ignore this one
 | |
|         //
 | |
|         argc --;
 | |
|         argv ++;
 | |
|         continue;
 | |
|       }
 | |
|       EnableHash = TRUE;
 | |
|       OpenSslCommand = "openssl";
 | |
|       OpenSslEnv = getenv("OPENSSL_PATH");
 | |
|       if (OpenSslEnv == NULL) {
 | |
|         OpenSslPath = OpenSslCommand;
 | |
|       } else {
 | |
|         //
 | |
|         // We add quotes to the Openssl Path in case it has space characters
 | |
|         //
 | |
|         OpenSslPath = malloc(2+strlen(OpenSslEnv)+strlen(OpenSslCommand)+1);
 | |
|         if (OpenSslPath == NULL) {
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return GetUtilityStatus ();
 | |
|         }
 | |
|         CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath);
 | |
|       }
 | |
|       if (OpenSslPath == NULL){
 | |
|         Error (NULL, 0, 3000, "Open SSL command not available.  Please verify PATH or set OPENSSL_PATH.", NULL);
 | |
|         return GetUtilityStatus ();
 | |
|       }
 | |
|       argc --;
 | |
|       argv ++;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
 | |
|       SetPrintLevel (VERBOSE_LOG_LEVEL);
 | |
|       argc --;
 | |
|       argv ++;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
 | |
|       SetPrintLevel (KEY_LOG_LEVEL);
 | |
|       argc --;
 | |
|       argv ++;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
 | |
|       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
 | |
|         return -1;
 | |
|       }
 | |
|       if (LogLevel > 9) {
 | |
|         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
 | |
|         return -1;
 | |
|       }
 | |
|       SetPrintLevel (LogLevel);
 | |
|       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
 | |
|       argc -= 2;
 | |
|       argv += 2;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     mUtilityFilename = argv[0];
 | |
|     argc --;
 | |
|     argv ++;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Open the file containing the FV
 | |
|   //
 | |
|   if (mUtilityFilename == NULL) {
 | |
|     Error (NULL, 0, 1001, "Missing option", "Input files are not specified");
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
|   InputFile = fopen (LongFilePath (mUtilityFilename), "rb");
 | |
|   if (InputFile == NULL) {
 | |
|     Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename);
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
|   //
 | |
|   // Skip over pad bytes if specified. This is used if they prepend 0xff
 | |
|   // data to the FV image binary.
 | |
|   //
 | |
|   if (Offset != 0) {
 | |
|     fseek (InputFile, Offset, SEEK_SET);
 | |
|   }
 | |
|   //
 | |
|   // Determine size of FV
 | |
|   //
 | |
|   Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename);
 | |
|     fclose (InputFile);
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
|   //
 | |
|   // Allocate a buffer for the FV image
 | |
|   //
 | |
|   FvImage = malloc (FvSize);
 | |
|   if (FvImage == NULL) {
 | |
|     Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);
 | |
|     fclose (InputFile);
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
|   //
 | |
|   // Seek to the start of the image, then read the entire FV to the buffer
 | |
|   //
 | |
|   fseek (InputFile, Offset, SEEK_SET);
 | |
|   BytesRead = fread (FvImage, 1, FvSize, InputFile);
 | |
|   fclose (InputFile);
 | |
|   if ((unsigned int) BytesRead != FvSize) {
 | |
|     Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename);
 | |
|     free (FvImage);
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
| 
 | |
|   LoadGuidedSectionToolsTxt (mUtilityFilename);
 | |
| 
 | |
|   PrintFvInfo (FvImage, FALSE);
 | |
| 
 | |
|   //
 | |
|   // Clean up
 | |
|   //
 | |
|   free (FvImage);
 | |
|   FreeGuidBaseNameList ();
 | |
|   return GetUtilityStatus ();
 | |
| }
 | |
| 
 | |
| 
 | |
| static
 | |
| EFI_STATUS
 | |
| PrintFvInfo (
 | |
|   IN VOID                         *Fv,
 | |
|   IN BOOLEAN                      IsChildFv
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Fv            - Firmware Volume to print information about
 | |
|   IsChildFv     - Flag specifies whether the input FV is a child FV.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_STATUS
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       NumberOfFiles;
 | |
|   BOOLEAN                     ErasePolarity;
 | |
|   UINTN                       FvSize;
 | |
|   EFI_FFS_FILE_HEADER         *CurrentFile;
 | |
|   UINTN                       Key;
 | |
| 
 | |
|   Status = FvBufGetSize (Fv, &FvSize);
 | |
| 
 | |
|   NumberOfFiles = 0;
 | |
|   ErasePolarity =
 | |
|     (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ?
 | |
|       TRUE : FALSE;
 | |
| 
 | |
|   //
 | |
|   // Get the first file
 | |
|   //
 | |
|   Key = 0;
 | |
|   Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");
 | |
|     return GetUtilityStatus ();
 | |
|   }
 | |
|   //
 | |
|   // Display information about files found
 | |
|   //
 | |
|   while (CurrentFile != NULL) {
 | |
|     //
 | |
|     // Increment the number of files counter
 | |
|     //
 | |
|     NumberOfFiles++;
 | |
| 
 | |
|     //
 | |
|     // Display info about this file
 | |
|     //
 | |
|     Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");
 | |
|       return GetUtilityStatus ();
 | |
|     }
 | |
|     //
 | |
|     // Get the next file
 | |
|     //
 | |
|     Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);
 | |
|     if (Status == EFI_NOT_FOUND) {
 | |
|       CurrentFile = NULL;
 | |
|     } else if (EFI_ERROR (Status)) {
 | |
|       Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");
 | |
|       return GetUtilityStatus ();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (IsChildFv) {
 | |
|     printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles);
 | |
|   } else {
 | |
|     printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| UINT32
 | |
| GetOccupiedSize (
 | |
|   IN UINT32  ActualSize,
 | |
|   IN UINT32  Alignment
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   This function returns the next larger size that meets the alignment
 | |
|   requirement specified.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ActualSize      The size.
 | |
|   Alignment       The desired alignment.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             Function completed successfully.
 | |
|   EFI_ABORTED             The function encountered an error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT32  OccupiedSize;
 | |
| 
 | |
|   OccupiedSize = ActualSize;
 | |
|   while ((OccupiedSize & (Alignment - 1)) != 0) {
 | |
|     OccupiedSize++;
 | |
|   }
 | |
| 
 | |
|   return OccupiedSize;
 | |
| }
 | |
| 
 | |
| static
 | |
| CHAR8 *
 | |
| SectionNameToStr (
 | |
|   IN EFI_SECTION_TYPE   Type
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Converts EFI Section names to Strings
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Type  - The EFI Section type
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   CHAR8* - Pointer to the String containing the section name.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR8 *SectionStr;
 | |
|   CHAR8 *SectionTypeStringTable[] = {
 | |
|     //
 | |
|     // 0X00
 | |
|     //
 | |
|     "EFI_SECTION_ALL",
 | |
|     //
 | |
|     // 0x01
 | |
|     //
 | |
|     "EFI_SECTION_COMPRESSION",
 | |
|     //
 | |
|     // 0x02
 | |
|     //
 | |
|     "EFI_SECTION_GUID_DEFINED",
 | |
|     //
 | |
|     // 0x03
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x03",
 | |
|     //
 | |
|     // 0x04
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x04",
 | |
|     //
 | |
|     // 0x05
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x05",
 | |
|     //
 | |
|     // 0x06
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x06",
 | |
|     //
 | |
|     // 0x07
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x07",
 | |
|     //
 | |
|     // 0x08
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x08",
 | |
|     //
 | |
|     // 0x09
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x09",
 | |
|     //
 | |
|     // 0x0A
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0A",
 | |
|     //
 | |
|     // 0x0B
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0B",
 | |
|     //
 | |
|     // 0x0C
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0C",
 | |
|     //
 | |
|     // 0x0D
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0D",
 | |
|     //
 | |
|     // 0x0E
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0E",
 | |
|     //
 | |
|     // 0x0F
 | |
|     //
 | |
|     "Unknown section type - Reserved 0x0E",
 | |
|     //
 | |
|     // 0x10
 | |
|     //
 | |
|     "EFI_SECTION_PE32",
 | |
|     //
 | |
|     // 0x11
 | |
|     //
 | |
|     "EFI_SECTION_PIC",
 | |
|     //
 | |
|     // 0x12
 | |
|     //
 | |
|     "EFI_SECTION_TE",
 | |
|     //
 | |
|     // 0x13
 | |
|     //
 | |
|     "EFI_SECTION_DXE_DEPEX",
 | |
|     //
 | |
|     // 0x14
 | |
|     //
 | |
|     "EFI_SECTION_VERSION",
 | |
|     //
 | |
|     // 0x15
 | |
|     //
 | |
|     "EFI_SECTION_USER_INTERFACE",
 | |
|     //
 | |
|     // 0x16
 | |
|     //
 | |
|     "EFI_SECTION_COMPATIBILITY16",
 | |
|     //
 | |
|     // 0x17
 | |
|     //
 | |
|     "EFI_SECTION_FIRMWARE_VOLUME_IMAGE",
 | |
|     //
 | |
|     // 0x18
 | |
|     //
 | |
|     "EFI_SECTION_FREEFORM_SUBTYPE_GUID",
 | |
|     //
 | |
|     // 0x19
 | |
|     //
 | |
|     "EFI_SECTION_RAW",
 | |
|     //
 | |
|     // 0x1A
 | |
|     //
 | |
|     "Unknown section type - 0x1A",
 | |
|     //
 | |
|     // 0x1B
 | |
|     //
 | |
|     "EFI_SECTION_PEI_DEPEX",
 | |
|     //
 | |
|     // 0x1C
 | |
|     //
 | |
|     "EFI_SECTION_MM_DEPEX",
 | |
|     //
 | |
|     // 0x1C+
 | |
|     //
 | |
|     "Unknown section type - Reserved - beyond last defined section"
 | |
|   };
 | |
| 
 | |
|   if (Type > EFI_SECTION_LAST_SECTION_TYPE) {
 | |
|     Type = EFI_SECTION_LAST_SECTION_TYPE + 1;
 | |
|   }
 | |
| 
 | |
|   SectionStr = malloc (100);
 | |
|   if (SectionStr == NULL) {
 | |
|     printf ("Error: Out of memory resources.\n");
 | |
|     return SectionStr;
 | |
|   }
 | |
|   strcpy (SectionStr, SectionTypeStringTable[Type]);
 | |
|   return SectionStr;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ReadHeader (
 | |
|   IN FILE       *InputFile,
 | |
|   OUT UINT32    *FvSize,
 | |
|   OUT BOOLEAN   *ErasePolarity
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   This function determines the size of the FV and the erase polarity.  The
 | |
|   erase polarity is the FALSE value for file state.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   InputFile       The file that contains the FV image.
 | |
|   FvSize          The size of the FV.
 | |
|   ErasePolarity   The FV erase polarity.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             Function completed successfully.
 | |
|   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.
 | |
|   EFI_ABORTED             The function encountered an error.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;
 | |
|   EFI_FV_BLOCK_MAP_ENTRY      BlockMap;
 | |
|   UINTN                       Signature[2];
 | |
|   UINTN                       BytesRead;
 | |
|   UINT32                      Size;
 | |
|   size_t                      ReadSize;
 | |
| 
 | |
|   BytesRead = 0;
 | |
|   Size      = 0;
 | |
|   //
 | |
|   // Check input parameters
 | |
|   //
 | |
|   if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) {
 | |
|     Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function");
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // Read the header
 | |
|   //
 | |
|   ReadSize = fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
 | |
|   if (ReadSize != 1) {
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
|   BytesRead     = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
 | |
|   Signature[0]  = VolumeHeader.Signature;
 | |
|   Signature[1]  = 0;
 | |
| 
 | |
|   //
 | |
|   // Print FV header information
 | |
|   //
 | |
|   printf ("Signature:        %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature);
 | |
|   printf ("Attributes:       %X\n", (unsigned) VolumeHeader.Attributes);
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) {
 | |
|     printf ("       EFI_FVB2_READ_DISABLED_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) {
 | |
|     printf ("       EFI_FVB2_READ_ENABLED_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) {
 | |
|     printf ("       EFI_FVB2_READ_STATUS\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) {
 | |
|     printf ("       EFI_FVB2_WRITE_DISABLED_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) {
 | |
|     printf ("       EFI_FVB2_WRITE_ENABLED_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) {
 | |
|     printf ("       EFI_FVB2_WRITE_STATUS\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) {
 | |
|     printf ("       EFI_FVB2_LOCK_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) {
 | |
|     printf ("       EFI_FVB2_LOCK_STATUS\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) {
 | |
|     printf ("       EFI_FVB2_STICKY_WRITE\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) {
 | |
|     printf ("       EFI_FVB2_MEMORY_MAPPED\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) {
 | |
|     printf ("       EFI_FVB2_ERASE_POLARITY\n");
 | |
|     *ErasePolarity = TRUE;
 | |
|   }
 | |
| 
 | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000)
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_2\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_4\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_8\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_16\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_32\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_64\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_128\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_256\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_512\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_1K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_2K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_4K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_8K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_16K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_32K\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {
 | |
|     printf ("        EFI_FVB2_ALIGNMENT_64K\n");
 | |
|   }
 | |
| 
 | |
| #else
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {
 | |
|     printf ("       EFI_FVB2_READ_LOCK_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) {
 | |
|     printf ("       EFI_FVB2_READ_LOCK_STATUS\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) {
 | |
|     printf ("       EFI_FVB2_WRITE_LOCK_CAP\n");
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) {
 | |
|     printf ("       EFI_FVB2_WRITE_LOCK_STATUS\n");
 | |
|   }
 | |
| 
 | |
|   switch (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {
 | |
|     case EFI_FVB2_ALIGNMENT_1:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_1\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_2:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_2\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_4:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_4\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_8:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_8\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_16:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_16\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_32:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_32\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_64:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_64\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_128:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_128\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_256:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_256\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_512:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_512\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_1K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_1K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_2K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_2K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_4K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_4K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_8K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_8K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_16K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_16K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_32K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_32K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_64K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_64K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_128K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_128K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_256K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_256K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_512K:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_512K\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_1M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_1M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_2M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_2M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_4M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_4M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_8M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_8M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_16M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_16M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_32M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_32M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_64M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_64M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_128M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_128M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_256M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_256M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_512M:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_512M\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_1G:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_1G\n");
 | |
|     break;
 | |
| 
 | |
|     case EFI_FVB2_ALIGNMENT_2G:
 | |
|     printf ("       EFI_FVB2_ALIGNMENT_2G\n");
 | |
|     break;
 | |
|   }
 | |
| 
 | |
| #endif
 | |
|   printf ("Header Length:         0x%08X\n", VolumeHeader.HeaderLength);
 | |
|   printf ("File System ID:        ");
 | |
|   PrintGuid (&VolumeHeader.FileSystemGuid);
 | |
|   //
 | |
|   // printf ("\n");
 | |
|   //
 | |
|   printf ("Revision:              0x%04X\n", VolumeHeader.Revision);
 | |
| 
 | |
|   do {
 | |
|     ReadSize = fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
 | |
|     if (ReadSize != 1) {
 | |
|       return EFI_ABORTED;
 | |
|     }
 | |
|     BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
 | |
| 
 | |
|     if (BlockMap.NumBlocks != 0) {
 | |
|       printf ("Number of Blocks:      0x%08X\n", (unsigned) BlockMap.NumBlocks);
 | |
|       printf ("Block Length:          0x%08X\n", (unsigned) BlockMap.Length);
 | |
|       Size += BlockMap.NumBlocks * BlockMap.Length;
 | |
|     }
 | |
| 
 | |
|   } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));
 | |
| 
 | |
|   if (BytesRead != VolumeHeader.HeaderLength) {
 | |
|     printf ("ERROR: Header length not consistent with Block Maps!\n");
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   if (VolumeHeader.FvLength != Size) {
 | |
|     printf ("ERROR: Volume Size not consistent with Block Maps!\n");
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   printf ("Total Volume Size:     0x%08X\n", (unsigned) Size);
 | |
| 
 | |
|   *FvSize = Size;
 | |
| 
 | |
|   //
 | |
|   // rewind (InputFile);
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| PrintAprioriFile (
 | |
|   EFI_FFS_FILE_HEADER         *FileHeader
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Print GUIDs from the APRIORI file
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FileHeader - The file header
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS       - The APRIORI file was parsed correctly
 | |
|   EFI_SECTION_ERROR - Problem with file parsing
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
 | |
|   UINT32              HeaderSize;
 | |
| 
 | |
|   HeaderSize = FvBufGetFfsHeaderSize (FileHeader);
 | |
| 
 | |
|   if (FileHeader->Type != EFI_FV_FILETYPE_FREEFORM)
 | |
|     return EFI_SECTION_ERROR;
 | |
| 
 | |
|   EFI_COMMON_SECTION_HEADER* SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) FileHeader + HeaderSize);
 | |
|   if (SectionHeader->Type != EFI_SECTION_RAW)
 | |
|     return EFI_SECTION_ERROR;
 | |
| 
 | |
|   UINT32 SectionLength = GetSectionFileLength (SectionHeader);
 | |
|   EFI_GUID* FileName = (EFI_GUID *) ((UINT8 *) SectionHeader + sizeof (EFI_COMMON_SECTION_HEADER));
 | |
|   while (((UINT8 *) FileName) < ((UINT8 *) SectionHeader + SectionLength)) {
 | |
|     PrintGuidToBuffer (FileName, GuidBuffer, sizeof (GuidBuffer), TRUE);
 | |
|     printf ("%s  ", GuidBuffer);
 | |
|     PrintGuidName (GuidBuffer);
 | |
|     printf ("\n");
 | |
|     FileName++;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| PrintFileInfo (
 | |
|   EFI_FIRMWARE_VOLUME_HEADER  *FvImage,
 | |
|   EFI_FFS_FILE_HEADER         *FileHeader,
 | |
|   BOOLEAN                     ErasePolarity
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FvImage       - GC_TODO: add argument description
 | |
|   FileHeader    - GC_TODO: add argument description
 | |
|   ErasePolarity - GC_TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - GC_TODO: Add description for return value
 | |
|   EFI_ABORTED - GC_TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT32              FileLength;
 | |
|   UINT8               FileState;
 | |
|   UINT8               Checksum;
 | |
|   EFI_FFS_FILE_HEADER2 BlankHeader;
 | |
|   EFI_STATUS          Status;
 | |
|   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
 | |
|   UINT32              HeaderSize;
 | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000)
 | |
|   UINT16              *Tail;
 | |
| #endif
 | |
|   //
 | |
|   // Check if we have free space
 | |
|   //
 | |
|   HeaderSize = FvBufGetFfsHeaderSize(FileHeader);
 | |
|   if (ErasePolarity) {
 | |
|     memset (&BlankHeader, -1, HeaderSize);
 | |
|   } else {
 | |
|     memset (&BlankHeader, 0, HeaderSize);
 | |
|   }
 | |
| 
 | |
|   if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // Print file information.
 | |
|   //
 | |
|   printf ("============================================================\n");
 | |
| 
 | |
|   printf ("File Name:        ");
 | |
|   PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE);
 | |
|   printf ("%s  ", GuidBuffer);
 | |
|   PrintGuidName (GuidBuffer);
 | |
|   printf ("\n");
 | |
| 
 | |
|   //
 | |
|   //  PrintGuid (&FileHeader->Name);
 | |
|   //  printf ("\n");
 | |
|   //
 | |
|   FileLength = FvBufGetFfsFileSize (FileHeader);
 | |
|   printf ("File Offset:      0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));
 | |
|   printf ("File Length:      0x%08X\n", (unsigned) FileLength);
 | |
|   printf ("File Attributes:  0x%02X\n", FileHeader->Attributes);
 | |
|   printf ("File State:       0x%02X\n", FileHeader->State);
 | |
| 
 | |
|   //
 | |
|   // Print file state
 | |
|   //
 | |
|   FileState = GetFileState (ErasePolarity, FileHeader);
 | |
| 
 | |
|   switch (FileState) {
 | |
| 
 | |
|   case EFI_FILE_HEADER_CONSTRUCTION:
 | |
|     printf ("        EFI_FILE_HEADER_CONSTRUCTION\n");
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   case EFI_FILE_HEADER_INVALID:
 | |
|     printf ("        EFI_FILE_HEADER_INVALID\n");
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   case EFI_FILE_HEADER_VALID:
 | |
|     printf ("        EFI_FILE_HEADER_VALID\n");
 | |
|     Checksum  = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);
 | |
|     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
 | |
|     Checksum  = (UINT8) (Checksum - FileHeader->State);
 | |
|     if (Checksum != 0) {
 | |
|       printf ("ERROR: Header checksum invalid.\n");
 | |
|       return EFI_ABORTED;
 | |
|     }
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
| 
 | |
|   case EFI_FILE_DELETED:
 | |
|     printf ("        EFI_FILE_DELETED\n");
 | |
| 
 | |
|   case EFI_FILE_MARKED_FOR_UPDATE:
 | |
|     printf ("        EFI_FILE_MARKED_FOR_UPDATE\n");
 | |
| 
 | |
|   case EFI_FILE_DATA_VALID:
 | |
|     printf ("        EFI_FILE_DATA_VALID\n");
 | |
| 
 | |
|     //
 | |
|     // Calculate header checksum
 | |
|     //
 | |
|     Checksum  = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);
 | |
|     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
 | |
|     Checksum  = (UINT8) (Checksum - FileHeader->State);
 | |
|     if (Checksum != 0) {
 | |
|       Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);
 | |
|       return EFI_ABORTED;
 | |
|     }
 | |
| 
 | |
|     FileLength = FvBufGetFfsFileSize (FileHeader);
 | |
| 
 | |
|     if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
 | |
|       //
 | |
|       // Calculate file checksum
 | |
|       //
 | |
|       Checksum  = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize);
 | |
|       Checksum  = Checksum + FileHeader->IntegrityCheck.Checksum.File;
 | |
|       if (Checksum != 0) {
 | |
|         Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
|     } else {
 | |
|       if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
 | |
|         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);
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
|     }
 | |
| #if (PI_SPECIFICATION_VERSION < 0x00010000)
 | |
|     //
 | |
|     // Verify tail if present
 | |
|     //
 | |
|     if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
 | |
|       //
 | |
|       // Verify tail is complement of integrity check field in the header.
 | |
|       //
 | |
|       Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK));
 | |
|       if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) {
 | |
|         Error (NULL, 0, 0003, "error parsing FFS file", \
 | |
|         "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer);
 | |
|         return EFI_ABORTED;
 | |
|       }
 | |
|     }
 | |
|  #endif
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   printf ("File Type:        0x%02X  ", FileHeader->Type);
 | |
| 
 | |
|   switch (FileHeader->Type) {
 | |
| 
 | |
|   case EFI_FV_FILETYPE_RAW:
 | |
|     printf ("EFI_FV_FILETYPE_RAW\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_FREEFORM:
 | |
|     printf ("EFI_FV_FILETYPE_FREEFORM\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_SECURITY_CORE:
 | |
|     printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_PEI_CORE:
 | |
|     printf ("EFI_FV_FILETYPE_PEI_CORE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_DXE_CORE:
 | |
|     printf ("EFI_FV_FILETYPE_DXE_CORE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_PEIM:
 | |
|     printf ("EFI_FV_FILETYPE_PEIM\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_DRIVER:
 | |
|     printf ("EFI_FV_FILETYPE_DRIVER\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
 | |
|     printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_APPLICATION:
 | |
|     printf ("EFI_FV_FILETYPE_APPLICATION\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_SMM:
 | |
|     printf ("EFI_FV_FILETYPE_MM\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
 | |
|     printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_COMBINED_SMM_DXE:
 | |
|     printf ("EFI_FV_FILETYPE_COMBINED_MM_DXE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_SMM_CORE:
 | |
|     printf ("EFI_FV_FILETYPE_MM_CORE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_MM_STANDALONE:
 | |
|     printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_MM_CORE_STANDALONE:
 | |
|     printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
 | |
|     break;
 | |
| 
 | |
|   case EFI_FV_FILETYPE_FFS_PAD:
 | |
|     printf ("EFI_FV_FILETYPE_FFS_PAD\n");
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type);
 | |
|     return EFI_ABORTED;
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   switch (FileHeader->Type) {
 | |
| 
 | |
|   case EFI_FV_FILETYPE_ALL:
 | |
|   case EFI_FV_FILETYPE_RAW:
 | |
|   case EFI_FV_FILETYPE_FFS_PAD:
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     //
 | |
|     // All other files have sections
 | |
|     //
 | |
|     Status = ParseSection (
 | |
|               (UINT8 *) ((UINTN) FileHeader + HeaderSize),
 | |
|               FvBufGetFfsFileSize (FileHeader) - HeaderSize
 | |
|               );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // printf ("ERROR: Parsing the FFS file.\n");
 | |
|       //
 | |
|       return EFI_ABORTED;
 | |
|     }
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (!CompareGuid (
 | |
|        &FileHeader->Name,
 | |
|        &gPeiAprioriFileNameGuid
 | |
|        ))
 | |
|   {
 | |
|     printf("\n");
 | |
|     printf("PEI APRIORI FILE:\n");
 | |
|     return PrintAprioriFile (FileHeader);
 | |
|   }
 | |
|   if (!CompareGuid (
 | |
|        &FileHeader->Name,
 | |
|        &gAprioriGuid
 | |
|        ))
 | |
|   {
 | |
|     printf("\n");
 | |
|     printf("DXE APRIORI FILE:\n");
 | |
|     return PrintAprioriFile (FileHeader);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| RebaseImageRead (
 | |
|   IN     VOID    *FileHandle,
 | |
|   IN     UINTN   FileOffset,
 | |
|   IN OUT UINT32  *ReadSize,
 | |
|   OUT    VOID    *Buffer
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FileHandle - The handle to the PE/COFF file
 | |
| 
 | |
|   FileOffset - The offset, in bytes, into the file to read
 | |
| 
 | |
|   ReadSize   - The number of bytes to read from the file starting at FileOffset
 | |
| 
 | |
|   Buffer     - A pointer to the buffer to read the data into.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR8   *Destination8;
 | |
|   CHAR8   *Source8;
 | |
|   UINT32  Length;
 | |
| 
 | |
|   Destination8  = Buffer;
 | |
|   Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
 | |
|   Length        = *ReadSize;
 | |
|   while (Length--) {
 | |
|     *(Destination8++) = *(Source8++);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| SetAddressToSectionHeader (
 | |
|   IN     CHAR8   *FileName,
 | |
|   IN OUT UINT8   *FileBuffer,
 | |
|   IN     UINT64  NewPe32BaseAddress
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set new base address into the section header of PeImage
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FileName           - Name of file
 | |
|   FileBuffer         - Pointer to PeImage.
 | |
|   NewPe32BaseAddress - New Base Address for PE image.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS          Set new base address into this image successfully.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                            Status;
 | |
|   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
 | |
|   UINTN                                 Index;
 | |
|   EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;
 | |
|   EFI_IMAGE_SECTION_HEADER              *SectionHeader;
 | |
| 
 | |
|   //
 | |
|   // Initialize context
 | |
|   //
 | |
|   memset (&ImageContext, 0, sizeof (ImageContext));
 | |
|   ImageContext.Handle     = (VOID *) FileBuffer;
 | |
|   ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
 | |
|   Status                  = PeCoffLoaderGetImageInfo (&ImageContext);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (ImageContext.RelocationsStripped) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get PeHeader pointer
 | |
|   //
 | |
|   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
 | |
| 
 | |
|   //
 | |
|   // Get section header list
 | |
|   //
 | |
|   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
 | |
|     (UINTN) ImgHdr +
 | |
|     sizeof (UINT32) +
 | |
|     sizeof (EFI_IMAGE_FILE_HEADER) +
 | |
|     ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Set base address into the first section header that doesn't point to code section.
 | |
|   //
 | |
|   for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
 | |
|     if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
 | |
|       *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // BaseAddress is set to section header.
 | |
|   //
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| RebaseImage (
 | |
|   IN     CHAR8   *FileName,
 | |
|   IN OUT UINT8   *FileBuffer,
 | |
|   IN     UINT64  NewPe32BaseAddress
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Set new base address into PeImage, and fix up PeImage based on new address.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FileName           - Name of file
 | |
|   FileBuffer         - Pointer to PeImage.
 | |
|   NewPe32BaseAddress - New Base Address for PE image.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_INVALID_PARAMETER   - BaseAddress is not valid.
 | |
|   EFI_SUCCESS             - Update PeImage is correctly.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                            Status;
 | |
|   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;
 | |
|   UINTN                                 Index;
 | |
|   EFI_IMAGE_OPTIONAL_HEADER_UNION       *ImgHdr;
 | |
|   UINT8                                 *MemoryImagePointer;
 | |
|   EFI_IMAGE_SECTION_HEADER              *SectionHeader;
 | |
| 
 | |
|   //
 | |
|   // Initialize context
 | |
|   //
 | |
|   memset (&ImageContext, 0, sizeof (ImageContext));
 | |
|   ImageContext.Handle     = (VOID *) FileBuffer;
 | |
|   ImageContext.ImageRead  = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
 | |
|   Status                  = PeCoffLoaderGetImageInfo (&ImageContext);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (ImageContext.RelocationsStripped) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get PeHeader pointer
 | |
|   //
 | |
|   ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
 | |
| 
 | |
|   //
 | |
|   // Load and Relocate Image Data
 | |
|   //
 | |
|   MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
 | |
|   if (MemoryImagePointer == NULL) {
 | |
|     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
|   memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
 | |
|   ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
 | |
| 
 | |
|   Status =  PeCoffLoaderLoadImage (&ImageContext);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
 | |
|     free ((VOID *) MemoryImagePointer);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   ImageContext.DestinationAddress = NewPe32BaseAddress;
 | |
|   Status                          = PeCoffLoaderRelocateImage (&ImageContext);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
 | |
|     free ((VOID *) MemoryImagePointer);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Copy Relocated data to raw image file.
 | |
|   //
 | |
|   SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
 | |
|     (UINTN) ImgHdr +
 | |
|     sizeof (UINT32) +
 | |
|     sizeof (EFI_IMAGE_FILE_HEADER) +
 | |
|     ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
 | |
|     );
 | |
| 
 | |
|   for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
 | |
|     CopyMem (
 | |
|       FileBuffer + SectionHeader->PointerToRawData,
 | |
|       (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
 | |
|       SectionHeader->SizeOfRawData
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   free ((VOID *) MemoryImagePointer);
 | |
| 
 | |
|   //
 | |
|   // Update Image Base Address
 | |
|   //
 | |
|   if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
 | |
|     ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
 | |
|   } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
 | |
|     ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
 | |
|   } else {
 | |
|     Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
 | |
|       ImgHdr->Pe32.OptionalHeader.Magic,
 | |
|       FileName
 | |
|       );
 | |
|     return EFI_ABORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set new base address into section header
 | |
|   //
 | |
|   Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| CombinePath (
 | |
|   IN  CHAR8* DefaultPath,
 | |
|   IN  CHAR8* AppendPath,
 | |
|   OUT CHAR8* NewPath
 | |
| )
 | |
| {
 | |
|   UINT32 DefaultPathLen;
 | |
|   UINT64 Index;
 | |
|   CHAR8  QuotesStr[] = "\"";
 | |
|   strcpy(NewPath, QuotesStr);
 | |
|   DefaultPathLen = strlen(DefaultPath);
 | |
|   strcat(NewPath, DefaultPath);
 | |
|   Index = 0;
 | |
|   for (; Index < DefaultPathLen + 1; Index ++) {
 | |
|     if (NewPath[Index] == '\\' || NewPath[Index] == '/') {
 | |
|       if (NewPath[Index + 1] != '\0') {
 | |
|         NewPath[Index] = '/';
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   if (NewPath[Index -1] != '/') {
 | |
|     NewPath[Index] = '/';
 | |
|     NewPath[Index + 1] = '\0';
 | |
|   }
 | |
|   strcat(NewPath, AppendPath);
 | |
|   strcat(NewPath, QuotesStr);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ParseSection (
 | |
|   IN UINT8  *SectionBuffer,
 | |
|   IN UINT32 BufferLength
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Parses EFI Sections
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SectionBuffer - Buffer containing the section to parse.
 | |
|   BufferLength  - Length of SectionBuffer
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SECTION_ERROR - Problem with section parsing.
 | |
|                       (a) compression errors
 | |
|                       (b) unrecognized section
 | |
|   EFI_UNSUPPORTED - Do not know how to parse the section.
 | |
|   EFI_SUCCESS - Section successfully parsed.
 | |
|   EFI_OUT_OF_RESOURCES - Memory allocation failed.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_SECTION_TYPE    Type;
 | |
|   UINT8               *Ptr;
 | |
|   UINT32              SectionLength;
 | |
|   UINT32              SectionHeaderLen;
 | |
|   CHAR8               *SectionName;
 | |
|   EFI_STATUS          Status;
 | |
|   UINT32              ParsedLength;
 | |
|   UINT8               *CompressedBuffer;
 | |
|   UINT32              CompressedLength;
 | |
|   UINT8               *UncompressedBuffer;
 | |
|   UINT32              UncompressedLength;
 | |
|   UINT8               *ToolOutputBuffer;
 | |
|   UINT32              ToolOutputLength;
 | |
|   UINT8               CompressionType;
 | |
|   UINT32              DstSize;
 | |
|   UINT32              ScratchSize;
 | |
|   UINT8               *ScratchBuffer;
 | |
|   DECOMPRESS_FUNCTION DecompressFunction;
 | |
|   GETINFO_FUNCTION    GetInfoFunction;
 | |
|   // CHAR16              *name;
 | |
|   CHAR8               *ExtractionTool;
 | |
|   CHAR8               *ToolInputFile;
 | |
|   CHAR8               *ToolOutputFile;
 | |
|   CHAR8               *SystemCommand;
 | |
|   EFI_GUID            *EfiGuid;
 | |
|   UINT16              DataOffset;
 | |
|   UINT16              Attributes;
 | |
|   UINT32              RealHdrLen;
 | |
|   CHAR8               *ToolInputFileName;
 | |
|   CHAR8               *ToolOutputFileName;
 | |
|   CHAR8               *UIFileName;
 | |
|   CHAR8               *VersionString;
 | |
| 
 | |
|   ParsedLength = 0;
 | |
|   ToolInputFileName = NULL;
 | |
|   ToolOutputFileName = NULL;
 | |
| 
 | |
|   while (ParsedLength < BufferLength) {
 | |
|     Ptr           = SectionBuffer + ParsedLength;
 | |
| 
 | |
|     SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);
 | |
|     Type          = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;
 | |
| 
 | |
|     //
 | |
|     // This is sort of an odd check, but is necessary because FFS files are
 | |
|     // padded to a QWORD boundary, meaning there is potentially a whole section
 | |
|     // header worth of 0xFF bytes.
 | |
|     //
 | |
|     if (SectionLength == 0xffffff && Type == 0xff) {
 | |
|       ParsedLength += 4;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Get real section file size
 | |
|     //
 | |
|     SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr);
 | |
|     SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
 | |
| 
 | |
|     SectionName = SectionNameToStr (Type);
 | |
|     if (SectionName != NULL) {
 | |
|       printf ("------------------------------------------------------------\n");
 | |
|       printf ("  Type:  %s\n  Size:  0x%08X\n", SectionName, (unsigned) SectionLength);
 | |
|       free (SectionName);
 | |
|     }
 | |
| 
 | |
|     switch (Type) {
 | |
|     case EFI_SECTION_RAW:
 | |
|     case EFI_SECTION_PIC:
 | |
|     case EFI_SECTION_TE:
 | |
|       // default is no more information
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_PE32:
 | |
|       if (EnableHash) {
 | |
|         ToolInputFileName  = "edk2Temp_InputEfi.tmp";
 | |
|         ToolOutputFileName = "edk2Temp_OutputHash.tmp";
 | |
|         RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);
 | |
|         PutFileImage (
 | |
|           ToolInputFileName,
 | |
|           (CHAR8*)Ptr + SectionHeaderLen,
 | |
|           SectionLength - SectionHeaderLen
 | |
|           );
 | |
| 
 | |
|         SystemCommand = malloc (
 | |
|           strlen (OPENSSL_COMMAND_FORMAT_STRING) +
 | |
|           strlen (OpenSslPath) +
 | |
|           strlen (ToolInputFileName) +
 | |
|           strlen (ToolOutputFileName) +
 | |
|           1
 | |
|           );
 | |
|         if (SystemCommand == NULL) {
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
|         sprintf (
 | |
|           SystemCommand,
 | |
|           OPENSSL_COMMAND_FORMAT_STRING,
 | |
|           OpenSslPath,
 | |
|           ToolOutputFileName,
 | |
|           ToolInputFileName
 | |
|           );
 | |
| 
 | |
|         if (system (SystemCommand) != EFI_SUCCESS) {
 | |
|           Error (NULL, 0, 3000, "Open SSL command not available.  Please verify PATH or set OPENSSL_PATH.", NULL);
 | |
|         }
 | |
|         else {
 | |
|           FILE *fp;
 | |
|           CHAR8 *StrLine;
 | |
|           CHAR8 *NewStr;
 | |
|           UINT32 nFileLen;
 | |
|           if((fp = fopen(ToolOutputFileName,"r")) == NULL) {
 | |
|             Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);
 | |
|           }
 | |
|           else {
 | |
|             fseek(fp,0,SEEK_SET);
 | |
|             fseek(fp,0,SEEK_END);
 | |
|             nFileLen = ftell(fp);
 | |
|             fseek(fp,0,SEEK_SET);
 | |
|             StrLine = malloc(nFileLen);
 | |
|             if (StrLine == NULL) {
 | |
|               fclose(fp);
 | |
|               free (SystemCommand);
 | |
|               Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|               return EFI_OUT_OF_RESOURCES;
 | |
|             }
 | |
|             fgets(StrLine, nFileLen, fp);
 | |
|             NewStr = strrchr (StrLine, '=');
 | |
|             printf ("  SHA1: %s\n", NewStr + 1);
 | |
|             free (StrLine);
 | |
|             fclose(fp);
 | |
|           }
 | |
|         }
 | |
|         remove(ToolInputFileName);
 | |
|         remove(ToolOutputFileName);
 | |
|         free (SystemCommand);
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_USER_INTERFACE:
 | |
|       UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1);
 | |
|       if (UIFileName == NULL) {
 | |
|         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
|       Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName);
 | |
|       printf ("  String: %s\n", UIFileName);
 | |
|       free (UIFileName);
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
 | |
|       printf ("/------------ Firmware Volume section start ---------------\\\n");
 | |
|       Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);
 | |
|         return EFI_SECTION_ERROR;
 | |
|       }
 | |
|       printf ("\\------------ Firmware Volume section end -----------------/\n");
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_COMPATIBILITY16:
 | |
|       //
 | |
|       // Section does not contain any further header information.
 | |
|       //
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
 | |
|       printf ("  Guid:  ");
 | |
|       if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER))
 | |
|         PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION *)Ptr)->SubTypeGuid);
 | |
|       else
 | |
|         PrintGuid (&((EFI_FREEFORM_SUBTYPE_GUID_SECTION2 *)Ptr)->SubTypeGuid);
 | |
|       printf ("\n");
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_PEI_DEPEX:
 | |
|     case EFI_SECTION_DXE_DEPEX:
 | |
|     case EFI_SECTION_SMM_DEPEX:
 | |
|       DumpDepexSection (Ptr, SectionLength);
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_VERSION:
 | |
|       printf ("  Build Number:  0x%04X\n", *(UINT16 *)(Ptr + SectionHeaderLen));
 | |
|       VersionString = (CHAR8 *) malloc (UnicodeStrLen (((EFI_VERSION_SECTION *) Ptr)->VersionString) + 1);
 | |
|       if (VersionString == NULL) {
 | |
|         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|         return EFI_OUT_OF_RESOURCES;
 | |
|       }
 | |
|       Unicode2AsciiString (((EFI_VERSION_SECTION *) Ptr)->VersionString, VersionString);
 | |
|       printf ("  Version String:  %s\n", VersionString);
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_COMPRESSION:
 | |
|       UncompressedBuffer  = NULL;
 | |
|       if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) {
 | |
|         RealHdrLen = sizeof(EFI_COMPRESSION_SECTION);
 | |
|         UncompressedLength  = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength;
 | |
|         CompressionType     = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType;
 | |
|       } else {
 | |
|         RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2);
 | |
|         UncompressedLength  = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength;
 | |
|         CompressionType     = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType;
 | |
|       }
 | |
|       CompressedLength    = SectionLength - RealHdrLen;
 | |
|       printf ("  Uncompressed Length:  0x%08X\n", (unsigned) UncompressedLength);
 | |
| 
 | |
|       if (CompressionType == EFI_NOT_COMPRESSED) {
 | |
|         printf ("  Compression Type:  EFI_NOT_COMPRESSED\n");
 | |
|         if (CompressedLength != UncompressedLength) {
 | |
|           Error (
 | |
|             NULL,
 | |
|             0,
 | |
|             0,
 | |
|             "file is not compressed, but the compressed length does not match the uncompressed length",
 | |
|             NULL
 | |
|             );
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
| 
 | |
|         UncompressedBuffer = Ptr + RealHdrLen;
 | |
|       } else if (CompressionType == EFI_STANDARD_COMPRESSION) {
 | |
|         GetInfoFunction     = EfiGetInfo;
 | |
|         DecompressFunction  = EfiDecompress;
 | |
|         printf ("  Compression Type:  EFI_STANDARD_COMPRESSION\n");
 | |
| 
 | |
|         CompressedBuffer  = Ptr + RealHdrLen;
 | |
| 
 | |
|         Status            = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
| 
 | |
|         if (DstSize != UncompressedLength) {
 | |
|           Error (NULL, 0, 0003, "compression error in the compression section", NULL);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
| 
 | |
|         ScratchBuffer       = malloc (ScratchSize);
 | |
|         if (ScratchBuffer == NULL) {
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
|         UncompressedBuffer  = malloc (UncompressedLength);
 | |
|         if (UncompressedBuffer == NULL) {
 | |
|           free (ScratchBuffer);
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
|         Status = DecompressFunction (
 | |
|                   CompressedBuffer,
 | |
|                   CompressedLength,
 | |
|                   UncompressedBuffer,
 | |
|                   UncompressedLength,
 | |
|                   ScratchBuffer,
 | |
|                   ScratchSize
 | |
|                   );
 | |
|         free (ScratchBuffer);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 0003, "decompress failed", NULL);
 | |
|           free (UncompressedBuffer);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
|       } else {
 | |
|         Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);
 | |
|         return EFI_SECTION_ERROR;
 | |
|       }
 | |
| 
 | |
|       printf ("/------------ Encapsulation section start -----------------\\\n");
 | |
|       Status = ParseSection (UncompressedBuffer, UncompressedLength);
 | |
|       printf ("\\------------ Encapsulation section end -------------------/\n");
 | |
| 
 | |
|       if (CompressionType == EFI_STANDARD_COMPRESSION) {
 | |
|         //
 | |
|         // We need to deallocate Buffer
 | |
|         //
 | |
|         free (UncompressedBuffer);
 | |
|       }
 | |
| 
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         Error (NULL, 0, 0003, "failed to parse section", NULL);
 | |
|         return EFI_SECTION_ERROR;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     case EFI_SECTION_GUID_DEFINED:
 | |
|       if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) {
 | |
|         EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid;
 | |
|         DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset;
 | |
|         Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes;
 | |
|       } else {
 | |
|         EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid;
 | |
|         DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset;
 | |
|         Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes;
 | |
|       }
 | |
|       printf ("  SectionDefinitionGuid:  ");
 | |
|       PrintGuid (EfiGuid);
 | |
|       printf ("\n");
 | |
|       printf ("  DataOffset:             0x%04X\n", (unsigned) DataOffset);
 | |
|       printf ("  Attributes:             0x%04X\n", (unsigned) Attributes);
 | |
| 
 | |
|       ExtractionTool =
 | |
|         LookupGuidedSectionToolPath (
 | |
|           mParsedGuidedSectionTools,
 | |
|           EfiGuid
 | |
|           );
 | |
| 
 | |
|       if (ExtractionTool != NULL) {
 | |
|        #ifndef __GNUC__
 | |
|         ToolInputFile = CloneString (tmpnam (NULL));
 | |
|         ToolOutputFile = CloneString (tmpnam (NULL));
 | |
|        #else
 | |
|         char tmp1[] = "/tmp/fileXXXXXX";
 | |
|         char tmp2[] = "/tmp/fileXXXXXX";
 | |
|         int fd1;
 | |
|         int fd2;
 | |
|         fd1 = mkstemp(tmp1);
 | |
|         fd2 = mkstemp(tmp2);
 | |
|         ToolInputFile = CloneString(tmp1);
 | |
|         ToolOutputFile = CloneString(tmp2);
 | |
|         close(fd1);
 | |
|         close(fd2);
 | |
|        #endif
 | |
| 
 | |
|         if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) {
 | |
|           if (ToolInputFile != NULL) {
 | |
|             free (ToolInputFile);
 | |
|           }
 | |
|           if (ToolOutputFile != NULL) {
 | |
|             free (ToolOutputFile);
 | |
|           }
 | |
|           free (ExtractionTool);
 | |
| 
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Construction 'system' command string
 | |
|         //
 | |
|         SystemCommand = malloc (
 | |
|           strlen (EXTRACT_COMMAND_FORMAT_STRING) +
 | |
|           strlen (ExtractionTool) +
 | |
|           strlen (ToolInputFile) +
 | |
|           strlen (ToolOutputFile) +
 | |
|           1
 | |
|           );
 | |
|         if (SystemCommand == NULL) {
 | |
|           free (ToolInputFile);
 | |
|           free (ToolOutputFile);
 | |
|           free (ExtractionTool);
 | |
| 
 | |
|           Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|           return EFI_OUT_OF_RESOURCES;
 | |
|         }
 | |
|         sprintf (
 | |
|           SystemCommand,
 | |
|           EXTRACT_COMMAND_FORMAT_STRING,
 | |
|           ExtractionTool,
 | |
|           ToolOutputFile,
 | |
|           ToolInputFile
 | |
|           );
 | |
|         free (ExtractionTool);
 | |
| 
 | |
|         if (!CompareGuid (
 | |
|                EfiGuid,
 | |
|                &gEfiCrc32GuidedSectionExtractionProtocolGuid
 | |
|                )
 | |
|            ) {
 | |
|           DataOffset -= 4;
 | |
|         }
 | |
|         Status =
 | |
|           PutFileImage (
 | |
|             ToolInputFile,
 | |
|             (CHAR8*)Ptr + DataOffset,
 | |
|             SectionLength - DataOffset
 | |
|             );
 | |
| 
 | |
|         system (SystemCommand);
 | |
|         remove (ToolInputFile);
 | |
|         free (ToolInputFile);
 | |
| 
 | |
|         Status =
 | |
|           GetFileImage (
 | |
|             ToolOutputFile,
 | |
|             (CHAR8 **)&ToolOutputBuffer,
 | |
|             &ToolOutputLength
 | |
|             );
 | |
|         remove (ToolOutputFile);
 | |
|         free (ToolOutputFile);
 | |
|         free (SystemCommand);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
| 
 | |
|         printf ("/------------ Encapsulation section start -----------------\\\n");
 | |
|         Status = ParseSection (
 | |
|                   ToolOutputBuffer,
 | |
|                   ToolOutputLength
 | |
|                   );
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
|         printf ("\\------------ Encapsulation section end -------------------/\n");
 | |
| 
 | |
|       //
 | |
|       // Check for CRC32 sections which we can handle internally if needed.
 | |
|       //
 | |
|       } else if (!CompareGuid (
 | |
|                    EfiGuid,
 | |
|                    &gEfiCrc32GuidedSectionExtractionProtocolGuid
 | |
|                    )
 | |
|           ) {
 | |
|         //
 | |
|         // CRC32 guided section
 | |
|         //
 | |
|         printf ("/------------ Encapsulation section start -----------------\\\n");
 | |
|         Status = ParseSection (
 | |
|                   Ptr + DataOffset,
 | |
|                   SectionLength - DataOffset
 | |
|                   );
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);
 | |
|           return EFI_SECTION_ERROR;
 | |
|         }
 | |
|         printf ("\\------------ Encapsulation section end -------------------/\n");
 | |
|       } else {
 | |
|         //
 | |
|         // We don't know how to parse it now.
 | |
|         //
 | |
|         Error (NULL, 0, 0003, "Error parsing section", \
 | |
|         "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).");
 | |
|         return EFI_UNSUPPORTED;
 | |
|       }
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       //
 | |
|       // Unknown section, return error
 | |
|       //
 | |
|       Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type);
 | |
|       return EFI_SECTION_ERROR;
 | |
|     }
 | |
| 
 | |
|     ParsedLength += SectionLength;
 | |
|     //
 | |
|     // We make then next section begin on a 4-byte boundary
 | |
|     //
 | |
|     ParsedLength = GetOccupiedSize (ParsedLength, 4);
 | |
|   }
 | |
| 
 | |
|   if (ParsedLength < BufferLength) {
 | |
|     Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);
 | |
|     return EFI_SECTION_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| DumpDepexSection (
 | |
|   IN UINT8    *Ptr,
 | |
|   IN UINT32   SectionLength
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Ptr           - GC_TODO: add argument description
 | |
|   SectionLength - GC_TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - GC_TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
 | |
| 
 | |
|   //
 | |
|   // Need at least a section header + data
 | |
|   //
 | |
|   if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
 | |
|   SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
 | |
|   while (SectionLength > 0) {
 | |
|     printf ("        ");
 | |
|     switch (*Ptr) {
 | |
|     case EFI_DEP_BEFORE:
 | |
|       printf ("BEFORE\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_AFTER:
 | |
|       printf ("AFTER\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_PUSH:
 | |
|       printf ("PUSH\n        ");
 | |
|       PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE);
 | |
|       printf ("%s  ", GuidBuffer);
 | |
|       PrintGuidName (GuidBuffer);
 | |
|       printf ("\n");
 | |
|       //
 | |
|       // PrintGuid ((EFI_GUID *)(Ptr + 1));
 | |
|       //
 | |
|       Ptr += 17;
 | |
|       SectionLength -= 17;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_AND:
 | |
|       printf ("AND\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_OR:
 | |
|       printf ("OR\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_NOT:
 | |
|       printf ("NOT\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_TRUE:
 | |
|       printf ("TRUE\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_FALSE:
 | |
|       printf ("FALSE\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_END:
 | |
|       printf ("END DEPEX\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     case EFI_DEP_SOR:
 | |
|       printf ("SOR\n");
 | |
|       Ptr++;
 | |
|       SectionLength--;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       printf ("Unrecognized byte in depex: 0x%X\n", *Ptr);
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| PrintGuidName (
 | |
|   IN UINT8    *GuidStr
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   GuidStr - GC_TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - GC_TODO: Add description for return value
 | |
|   EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   GUID_TO_BASENAME  *GPtr;
 | |
|   //
 | |
|   // If we have a list of guid-to-basenames, then go through the list to
 | |
|   // look for a guid string match. If found, print the basename to stdout,
 | |
|   // otherwise return a failure.
 | |
|   //
 | |
|   GPtr = mGuidBaseNameList;
 | |
|   while (GPtr != NULL) {
 | |
|     if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) {
 | |
|       printf ("%s", GPtr->BaseName);
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     GPtr = GPtr->Next;
 | |
|   }
 | |
| 
 | |
|   return EFI_INVALID_PARAMETER;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| ParseGuidBaseNameFile (
 | |
|   CHAR8    *FileName
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   FileName  - GC_TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_DEVICE_ERROR - GC_TODO: Add description for return value
 | |
|   EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
 | |
|   EFI_SUCCESS - GC_TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   FILE              *Fptr;
 | |
|   CHAR8             Line[MAX_LINE_LEN];
 | |
|   CHAR8             FormatString[MAX_LINE_LEN];
 | |
|   GUID_TO_BASENAME  *GPtr;
 | |
| 
 | |
|   if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) {
 | |
|     printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Generate the format string for fscanf
 | |
|   //
 | |
|   sprintf (
 | |
|     FormatString,
 | |
|     "%%%us %%%us",
 | |
|     (unsigned) sizeof (GPtr->Guid) - 1,
 | |
|     (unsigned) sizeof (GPtr->BaseName) - 1
 | |
|     );
 | |
| 
 | |
|   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
 | |
|     //
 | |
|     // Allocate space for another guid/basename element
 | |
|     //
 | |
|     GPtr = malloc (sizeof (GUID_TO_BASENAME));
 | |
|     if (GPtr == NULL) {
 | |
|       fclose (Fptr);
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));
 | |
|     if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) {
 | |
|       GPtr->Next        = mGuidBaseNameList;
 | |
|       mGuidBaseNameList = GPtr;
 | |
|     } else {
 | |
|       //
 | |
|       // Some sort of error. Just continue.
 | |
|       //
 | |
|       free (GPtr);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   fclose (Fptr);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| FreeGuidBaseNameList (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS - GC_TODO: Add description for return value
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   GUID_TO_BASENAME  *Next;
 | |
| 
 | |
|   while (mGuidBaseNameList != NULL) {
 | |
|     Next = mGuidBaseNameList->Next;
 | |
|     free (mGuidBaseNameList);
 | |
|     mGuidBaseNameList = Next;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| 
 | |
| static
 | |
| VOID
 | |
| LoadGuidedSectionToolsTxt (
 | |
|   IN CHAR8* FirmwareVolumeFilename
 | |
|   )
 | |
| {
 | |
|   CHAR8* PeerFilename;
 | |
|   CHAR8* Places[] = {
 | |
|     NULL,
 | |
|     //NULL,
 | |
|     };
 | |
|   UINTN Index;
 | |
| 
 | |
|   Places[0] = FirmwareVolumeFilename;
 | |
|   //Places[1] = mUtilityFilename;
 | |
| 
 | |
|   mParsedGuidedSectionTools = NULL;
 | |
| 
 | |
|   for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) {
 | |
|     PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt");
 | |
|     //printf("Loading %s...\n", PeerFilename);
 | |
|     if (OsPathExists (PeerFilename)) {
 | |
|       mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename);
 | |
|     }
 | |
|     free (PeerFilename);
 | |
|     if (mParsedGuidedSectionTools != NULL) {
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| Usage (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   GC_TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   GC_TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // Summary usage
 | |
|   //
 | |
|   fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME);
 | |
| 
 | |
|   //
 | |
|   // Copyright declaration
 | |
|   //
 | |
|   fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
 | |
|   fprintf (stdout, "  Display Tiano Firmware Volume FFS image information\n\n");
 | |
| 
 | |
|   //
 | |
|   // Details Option
 | |
|   //
 | |
|   fprintf (stdout, "optional arguments:\n");
 | |
|   fprintf (stdout, "  -h, --help\n\
 | |
|             Show this help message and exit\n");
 | |
|   fprintf (stdout, "  --version\n\
 | |
|            Show program's version number and exit\n");
 | |
|   fprintf (stdout, "  -d [DEBUG], --debug [DEBUG]\n\
 | |
|             Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
 | |
|   fprintf (stdout, "  -v, --verbose\n\
 | |
|             Print informational statements\n");
 | |
|   fprintf (stdout, "  -q, --quiet\n\
 | |
|             Returns the exit code, error messages will be displayed\n");
 | |
|   fprintf (stdout, "  -s, --silent\n\
 | |
|             Returns only the exit code; informational and error\n\
 | |
|             messages are not displayed\n");
 | |
|   fprintf (stdout, "  -x XREF_FILENAME, --xref XREF_FILENAME\n\
 | |
|             Parse the basename to file-guid cross reference file(s)\n");
 | |
|   fprintf (stdout, "  -f OFFSET, --offset OFFSET\n\
 | |
|             The offset from the start of the input file to start \n\
 | |
|             processing an FV\n");
 | |
|   fprintf (stdout, "  --hash\n\
 | |
|             Generate HASH value of the entire PE image\n");
 | |
|   fprintf (stdout, "  --sfo\n\
 | |
|             Reserved for future use\n");
 | |
| }
 | |
| 
 |