--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ CreateMtFile.c\r
+\r
+Abstract:\r
+\r
+ Simple utility to create a pad file containing fixed data.\r
+ \r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "TianoCommon.h"\r
+\r
+#define PROGRAM_NAME "CreateMtFile"\r
+\r
+typedef struct {\r
+ INT8 *OutFileName;\r
+ INT8 ByteValue;\r
+ UINT32 FileSize;\r
+} OPTIONS;\r
+\r
+static\r
+EFI_STATUS\r
+ProcessArgs (\r
+ IN INT32 Argc,\r
+ IN INT8 *Argv[],\r
+ IN OUT OPTIONS *Options\r
+ );\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+int\r
+main (\r
+ IN INT32 Argc,\r
+ IN INT8 *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Main entry point for this utility.\r
+\r
+Arguments:\r
+\r
+ Standard C entry point args Argc and Argv\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS if good to go\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment\r
+{\r
+ FILE *OutFptr;\r
+ OPTIONS Options;\r
+\r
+ //\r
+ // Process the command-line arguments.\r
+ //\r
+ if (ProcessArgs (Argc, Argv, &Options) != EFI_SUCCESS) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Open the output file\r
+ //\r
+ if ((OutFptr = fopen (Options.OutFileName, "wb")) == NULL) {\r
+ fprintf (\r
+ stdout,\r
+ PROGRAM_NAME " ERROR: Could not open output file '%s' for writing\n",\r
+ Options.OutFileName\r
+ );\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ //\r
+ // Write the pad bytes. Do it the slow way (one at a time) for now.\r
+ //\r
+ while (Options.FileSize > 0) {\r
+ if (fwrite (&Options.ByteValue, 1, 1, OutFptr) != 1) {\r
+ fclose (OutFptr);\r
+ fprintf (stdout, PROGRAM_NAME " ERROR: Failed to write to output file\n");\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Options.FileSize--;\r
+ }\r
+ //\r
+ // Close the file\r
+ //\r
+ fclose (OutFptr);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+ProcessArgs (\r
+ IN INT32 Argc,\r
+ IN INT8 *Argv[],\r
+ IN OUT OPTIONS *Options\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Process the command line arguments.\r
+\r
+Arguments:\r
+\r
+ Argc - argument count as passed in to the entry point function\r
+ Argv - array of arguments as passed in to the entry point function\r
+ Options - stucture of where to put the values of the parsed arguments\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS if everything looks good\r
+ EFI_INVALID_PARAMETER otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ UINT32 Multiplier;\r
+\r
+ //\r
+ // Clear the options\r
+ //\r
+ memset ((char *) Options, 0, sizeof (OPTIONS));\r
+\r
+ //\r
+ // Skip program name\r
+ //\r
+ Argv++;\r
+ Argc--;\r
+ if (Argc < 2) {\r
+ Usage ();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // If first arg is dash-option, then print usage.\r
+ //\r
+ if (Argv[0][0] == '-') {\r
+ Usage ();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // First arg is file name\r
+ //\r
+ Options->OutFileName = Argv[0];\r
+ Argc--;\r
+ Argv++;\r
+\r
+ //\r
+ // Second arg is file size. Allow 0x1000, 0x100K, 1024, 1K\r
+ //\r
+ Multiplier = 1;\r
+ if ((Argv[0][strlen (Argv[0]) - 1] == 'k') || (Argv[0][strlen (Argv[0]) - 1] == 'K')) {\r
+ Multiplier = 1024;\r
+ }\r
+ //\r
+ // Look for 0x prefix on file size\r
+ //\r
+ if ((Argv[0][0] == '0') && ((Argv[0][1] == 'x') || (Argv[0][1] == 'X'))) {\r
+ if (sscanf (Argv[0], "%x", &Options->FileSize) != 1) {\r
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);\r
+ Usage ();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Otherwise must be a decimal number\r
+ //\r
+ } else {\r
+ if (sscanf (Argv[0], "%d", &Options->FileSize) != 1) {\r
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);\r
+ Usage ();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ Options->FileSize *= Multiplier;\r
+ //\r
+ // Assume byte value of 0xff\r
+ //\r
+ Options->ByteValue = (INT8) (UINT8) 0xFF;\r
+ return EFI_SUCCESS;\r
+}\r
+//\r
+// Print utility usage info\r
+//\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ UINT32 Index;\r
+ static const INT8 *Text[] = {\r
+ " ",\r
+ "Usage: "PROGRAM_NAME " OutFileName FileSize",\r
+ " where:",\r
+ " OutFileName is the name of the output file to generate",\r
+ " FileSize is the size of the file to create",\r
+ " Examples:",\r
+ " "PROGRAM_NAME " OutFile.bin 32K",\r
+ " "PROGRAM_NAME " OutFile.bin 0x1000",\r
+ " ",\r
+ NULL\r
+ };\r
+\r
+ for (Index = 0; Text[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Text[Index]);\r
+ }\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 1999 - 2001 Intel Corporation. All rights reserved\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+# \r
+# \r
+# Module Name:\r
+# \r
+# Makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the CreateMtFile utility.\r
+# \r
+# Revision History\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = CreateMtFile\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj\r
+ \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj : $(TARGET_SRC_DIR)\CreateMtFile.c\r
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\CreateMtFile.c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ EfiCompressMain.c\r
+\r
+Abstract:\r
+\r
+ The main function for the compression utility.\r
+ \r
+--*/\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include "TianoCommon.h"\r
+#include "EfiCompress.h"\r
+\r
+int\r
+main (\r
+ INT32 argc,\r
+ CHAR8 *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Compresses the input files\r
+\r
+Arguments:\r
+\r
+ argc - number of arguments passed into the command line.\r
+ argv[] - files to compress and files to output compressed data to.\r
+\r
+Returns:\r
+\r
+ int: 0 for successful execution of the function.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ FILE *infile;\r
+ FILE *outfile;\r
+ UINT32 SrcSize;\r
+ UINT32 DstSize;\r
+ UINT8 *SrcBuffer;\r
+ UINT8 *DstBuffer;\r
+ UINT8 Buffer[8];\r
+\r
+ //\r
+ // Added for makefile debug - KCE\r
+ //\r
+ INT32 arg_counter;\r
+ printf ("\n\n");\r
+ for (arg_counter = 0; arg_counter < argc; arg_counter++) {\r
+ printf ("%s ", argv[arg_counter]);\r
+ }\r
+\r
+ printf ("\n\n");\r
+\r
+ SrcBuffer = DstBuffer = NULL;\r
+\r
+ infile = outfile = NULL;\r
+\r
+ if (argc != 3) {\r
+ printf ("Usage: EFICOMPRESS <infile> <outfile>\n");\r
+ goto Done;\r
+ }\r
+\r
+ if ((outfile = fopen (argv[2], "wb")) == NULL) {\r
+ printf ("Can't open output file\n");\r
+ goto Done;\r
+ }\r
+\r
+ if ((infile = fopen (argv[1], "rb")) == NULL) {\r
+ printf ("Can't open input file\n");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Get the size of source file\r
+ //\r
+ SrcSize = 0;\r
+ while (fread (Buffer, 1, 1, infile)) {\r
+ SrcSize++;\r
+\r
+ }\r
+ //\r
+ // Read in the source data\r
+ //\r
+ if ((SrcBuffer = malloc (SrcSize)) == NULL) {\r
+ printf ("Can't allocate memory\n");\r
+ goto Done;\r
+ }\r
+\r
+ rewind (infile);\r
+ if (fread (SrcBuffer, 1, SrcSize, infile) != SrcSize) {\r
+ printf ("Can't read from source\n");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Get destination data size and do the compression\r
+ //\r
+ DstSize = 0;\r
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ if ((DstBuffer = malloc (DstSize)) == NULL) {\r
+ printf ("Can't allocate memory\n");\r
+ goto Done;\r
+ }\r
+\r
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ printf ("Compress Error\n");\r
+ goto Done;\r
+ }\r
+\r
+ printf ("\nOrig Size = %ld\n", SrcSize);\r
+ printf ("Comp Size = %ld\n", DstSize);\r
+\r
+ if (DstBuffer == NULL) {\r
+ printf ("No destination to write to.\n");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Write out the result\r
+ //\r
+ if (fwrite (DstBuffer, 1, DstSize, outfile) != DstSize) {\r
+ printf ("Can't write to destination file\n");\r
+ }\r
+\r
+Done:\r
+ if (SrcBuffer) {\r
+ free (SrcBuffer);\r
+ }\r
+\r
+ if (DstBuffer) {\r
+ free (DstBuffer);\r
+ }\r
+\r
+ if (infile) {\r
+ fclose (infile);\r
+ }\r
+\r
+ if (outfile) {\r
+ fclose (outfile);\r
+ }\r
+\r
+ return 0;\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# BUGBUG: Override standard flags, cannot be built without warnings.\r
+#\r
+\r
+C_FLAGS=/nologo /W4 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c \r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=EfiCompress\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\EfiCompressMain.c"\r
+TARGET_EXE_INCLUDE = "$(COMMON_SOURCE)\EfiCompress.h"\r
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib"\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_LIB) $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ EfiRom.c\r
+ \r
+Abstract:\r
+\r
+ Utility program to create an EFI option ROM image from binary and \r
+ EFI PE32 files.\r
+\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+//\r
+// Includes for EFI 1.1 build\r
+//\r
+// #include "Tiano.h" // required defines for Compress.h\r
+// #include "EfiImage.h" // for PE32 structure definitions\r
+// #include "Compress.h" // for compression function\r
+// Includes for Tiano build\r
+//\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiCompress.h"\r
+\r
+//\r
+// END include differences\r
+//\r
+#include "Pci22.h" // for option ROM header structures\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_VERSION "v2.5"\r
+\r
+//\r
+// Define some status return values\r
+//\r
+#define STATUS_SUCCESS 0\r
+#define STATUS_WARNING 1\r
+#define STATUS_ERROR 2\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH 200\r
+\r
+#define DEFAULT_OUTPUT_EXTENSION ".rom"\r
+\r
+//\r
+// Max size for an option ROM image\r
+//\r
+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB\r
+//\r
+// Values for the indicator field in the PCI data structure\r
+//\r
+#define INDICATOR_LAST 0x80 // last file in series of files\r
+//\r
+// Masks for the FILE_LIST.FileFlags field\r
+//\r
+#define FILE_FLAG_BINARY 0x01\r
+#define FILE_FLAG_EFI 0x02\r
+#define FILE_FLAG_COMPRESS 0x04\r
+\r
+//\r
+// Use this linked list structure to keep track of all the filenames\r
+// specified on the command line.\r
+//\r
+typedef struct _FILE_LIST {\r
+ struct _FILE_LIST *Next;\r
+ INT8 *FileName;\r
+ UINT32 FileFlags;\r
+ UINT32 ClassCode;\r
+ UINT16 CodeRevision;\r
+} FILE_LIST;\r
+\r
+//\r
+// Use this to track our command-line options\r
+//\r
+typedef struct {\r
+ INT8 OutFileName[MAX_PATH];\r
+ INT8 NoLast;\r
+ INT8 Verbose;\r
+ INT8 DumpOption;\r
+ UINT8 DevIdValid;\r
+ UINT8 VendIdValid;\r
+ UINT16 VendId;\r
+ UINT16 DevId;\r
+ FILE_LIST *FileList;\r
+} OPTIONS;\r
+\r
+//\r
+// Make a global structure to keep track of command-line options\r
+//\r
+static OPTIONS mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+ UINT16 Value;\r
+ char *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP mMachineTypes[] = {\r
+ EFI_IMAGE_MACHINE_IA32,\r
+ "IA32",\r
+ EFI_IMAGE_MACHINE_IA64,\r
+ "IA64",\r
+ EFI_IMAGE_MACHINE_EBC,\r
+ "EBC",\r
+ 0,\r
+ NULL\r
+};\r
+\r
+static STRING_LOOKUP mSubsystemTypes[] = {\r
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+ "EFI application",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+ "EFI boot service driver",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+ "EFI runtime driver",\r
+ 0,\r
+ NULL\r
+};\r
+//\r
+// Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[],\r
+ OPTIONS *Options\r
+ );\r
+\r
+static\r
+int\r
+CheckPE32File (\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ );\r
+\r
+static\r
+int\r
+ProcessEfiFile (\r
+ FILE *OutFptr,\r
+ FILE_LIST *InFile,\r
+ UINT16 VendId,\r
+ UINT16 DevId,\r
+ UINT32 *Size\r
+ );\r
+\r
+static\r
+int\r
+ProcessBinFile (\r
+ FILE *OutFptr,\r
+ FILE_LIST *InFile,\r
+ UINT32 *Size\r
+ );\r
+\r
+static\r
+void\r
+DumpImage (\r
+ FILE_LIST *InFile\r
+ );\r
+\r
+char *\r
+GetMachineTypeStr (\r
+ UINT16 MachineType\r
+ );\r
+\r
+static\r
+char *\r
+GetSubsystemTypeStr (\r
+ UINT16 SubsystemType\r
+ );\r
+\r
+main (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given an EFI image filename, create a ROM-able image by creating an option \r
+ ROM header and PCI data structure, filling them in, and then writing the\r
+ option ROM header + PCI data structure + EFI image out to the output file.\r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+\r
+ Argv - standard C main() argument list\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ INT8 *Ext;\r
+ FILE *FptrOut;\r
+ UINT32 Status;\r
+ FILE_LIST *FList;\r
+ UINT32 TotalSize;\r
+ UINT32 Size;\r
+\r
+ Status = STATUS_SUCCESS;\r
+ FptrOut = NULL;\r
+\r
+ //\r
+ // Parse the command line arguments\r
+ //\r
+ if (ParseCommandLine (Argc, Argv, &mOptions)) {\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If dumping an image, then do that and quit\r
+ //\r
+ if (mOptions.DumpOption) {\r
+ DumpImage (mOptions.FileList);\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Determine the output filename. Either what they specified on\r
+ // the command line, or the first input filename with a different extension.\r
+ //\r
+ if (!mOptions.OutFileName[0]) {\r
+ strcpy (mOptions.OutFileName, mOptions.FileList->FileName);\r
+ //\r
+ // Find the last . on the line and replace the filename extension with\r
+ // the default\r
+ //\r
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
+ Ext--\r
+ )\r
+ ;\r
+ //\r
+ // If dot here, then insert extension here, otherwise append\r
+ //\r
+ if (*Ext != '.') {\r
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+ }\r
+\r
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+ }\r
+ //\r
+ // Make sure we don't have the same filename for input and output files\r
+ //\r
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
+ if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {\r
+ Status = STATUS_ERROR;\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Input and output file names must be different - %s = %s\n",\r
+ FList->FileName,\r
+ mOptions.OutFileName\r
+ );\r
+ goto BailOut;\r
+ }\r
+ }\r
+ //\r
+ // Now open our output file\r
+ //\r
+ if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {\r
+ fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Process all our files\r
+ //\r
+ TotalSize = 0;\r
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
+ Size = 0;\r
+ if (FList->FileFlags & FILE_FLAG_EFI) {\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, "Processing EFI file %s\n", FList->FileName);\r
+ }\r
+\r
+ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);\r
+ } else if (FList->FileFlags & FILE_FLAG_BINARY) {\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, "Processing binary file %s\n", FList->FileName);\r
+ }\r
+\r
+ Status = ProcessBinFile (FptrOut, FList, &Size);\r
+ } else {\r
+ fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);\r
+ Status = STATUS_ERROR;\r
+ }\r
+\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " Output size = 0x%X\n", Size);\r
+ }\r
+\r
+ if (Status != STATUS_SUCCESS) {\r
+ break;\r
+ }\r
+\r
+ TotalSize += Size;\r
+ }\r
+ //\r
+ // Check total size\r
+ //\r
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",\r
+ MAX_OPTION_ROM_SIZE\r
+ );\r
+ Status = STATUS_ERROR;\r
+ }\r
+\r
+BailOut:\r
+ if (FptrOut != NULL) {\r
+ fclose (FptrOut);\r
+ }\r
+ //\r
+ // Clean up our file list\r
+ //\r
+ while (mOptions.FileList != NULL) {\r
+ FList = mOptions.FileList->Next;\r
+ free (mOptions.FileList);\r
+ mOptions.FileList = FList;\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+int\r
+ProcessBinFile (\r
+ FILE *OutFptr,\r
+ FILE_LIST *InFile,\r
+ UINT32 *Size\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Process a binary input file.\r
+\r
+Arguments:\r
+\r
+ OutFptr - file pointer to output binary ROM image file we're creating\r
+ InFile - structure contains information on the binary file to process\r
+ Size - pointer to where to return the size added to the output file\r
+\r
+Returns:\r
+\r
+ 0 - successful\r
+\r
+--*/\r
+{\r
+ FILE *InFptr;\r
+ UINT32 TotalSize;\r
+ UINT32 FileSize;\r
+ UINT8 *Buffer;\r
+ UINT32 Status;\r
+ PCI_EXPANSION_ROM_HEADER *RomHdr;\r
+ PCI_DATA_STRUCTURE *PciDs;\r
+ UINT32 Index;\r
+ UINT8 ByteCheckSum;\r
+\r
+ Status = STATUS_SUCCESS;\r
+\r
+ //\r
+ // Try to open the input file\r
+ //\r
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Seek to the end of the input file and get the file size. Then allocate\r
+ // a buffer to read it in to.\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " File size = 0x%X\n", FileSize);\r
+ }\r
+\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ Buffer = (INT8 *) malloc (FileSize);\r
+ if (Buffer == NULL) {\r
+ fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Total size must be an even multiple of 512 bytes, and can't exceed\r
+ // the option ROM image size.\r
+ //\r
+ TotalSize = FileSize;\r
+ if (TotalSize & 0x1FF) {\r
+ TotalSize = (TotalSize + 0x200) &~0x1ff;\r
+ }\r
+\r
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
+ InFile->FileName,\r
+ MAX_OPTION_ROM_SIZE\r
+ );\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Return the size to the caller so they can keep track of the running total.\r
+ //\r
+ *Size = TotalSize;\r
+\r
+ //\r
+ // Crude check to make sure it's a legitimate ROM image\r
+ //\r
+ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;\r
+ if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+ fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Make sure the pointer to the PCI data structure is within the size of the image.\r
+ // Then check it for valid signature.\r
+ //\r
+ if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {\r
+ fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);\r
+ if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
+ fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // If this is the last image, then set the LAST bit unless requested not\r
+ // to via the command-line -l argument. Otherwise, make sure you clear it.\r
+ //\r
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
+ PciDs->Indicator = INDICATOR_LAST;\r
+ } else {\r
+ PciDs->Indicator = 0;\r
+ }\r
+\r
+ ByteCheckSum = 0;\r
+ for (Index = 0; Index < FileSize - 1; Index++) {\r
+ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
+ }\r
+\r
+ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
+ fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);\r
+\r
+ //\r
+ // Now copy the input file contents out to the output file\r
+ //\r
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ TotalSize -= FileSize;\r
+ //\r
+ // Pad the rest of the image to make it a multiple of 512 bytes\r
+ //\r
+ while (TotalSize > 0) {\r
+ putc (~0, OutFptr);\r
+ TotalSize--;\r
+ }\r
+\r
+BailOut:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+ //\r
+ // Print the file name if errors occurred\r
+ //\r
+ if (Status != STATUS_SUCCESS) {\r
+ fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+int\r
+ProcessEfiFile (\r
+ FILE *OutFptr,\r
+ FILE_LIST *InFile,\r
+ UINT16 VendId,\r
+ UINT16 DevId,\r
+ UINT32 *Size\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Process a PE32 EFI file.\r
+\r
+Arguments:\r
+\r
+ OutFptr - file pointer to output binary ROM image file we're creating\r
+ InFile - structure contains information on the PE32 file to process\r
+ VendId - vendor ID as required in the option ROM header\r
+ DevId - device ID as required in the option ROM header\r
+ Size - pointer to where to return the size added to the output file\r
+\r
+Returns:\r
+\r
+ 0 - successful\r
+\r
+--*/\r
+{\r
+ UINT32 Status;\r
+ FILE *InFptr;\r
+ EFI_PCI_EXPANSION_ROM_HEADER RomHdr;\r
+ PCI_DATA_STRUCTURE PciDs;\r
+ UINT32 FileSize;\r
+ UINT32 CompressedFileSize;\r
+ UINT8 *Buffer;\r
+ UINT8 *CompressedBuffer;\r
+ UINT8 *TempBufferPtr;\r
+ UINT32 TotalSize;\r
+ UINT32 HeaderSize;\r
+ UINT16 MachineType;\r
+ UINT16 SubSystem;\r
+ UINT32 HeaderPadBytes;\r
+\r
+ //\r
+ // Try to open the input file\r
+ //\r
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Initialize our buffer pointers to null.\r
+ //\r
+ Buffer = NULL;\r
+ CompressedBuffer = NULL;\r
+\r
+ //\r
+ // Double-check the file to make sure it's what we expect it to be\r
+ //\r
+ Status = CheckPE32File (InFptr, &MachineType, &SubSystem);\r
+ if (Status != STATUS_SUCCESS) {\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Seek to the end of the input file and get the file size\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+\r
+ //\r
+ // Get the size of the headers we're going to put in front of the image. The\r
+ // EFI header must be aligned on a 4-byte boundary, so pad accordingly.\r
+ //\r
+ if (sizeof (RomHdr) & 0x03) {\r
+ HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);\r
+ } else {\r
+ HeaderPadBytes = 0;\r
+ }\r
+\r
+ HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " File size = 0x%X\n", FileSize);\r
+ }\r
+ //\r
+ // Allocate memory for the entire file (in case we have to compress), then\r
+ // seek back to the beginning of the file and read it into our buffer.\r
+ //\r
+ Buffer = (INT8 *) malloc (FileSize);\r
+ if (Buffer == NULL) {\r
+ fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Now determine the size of the final output file. It's either the header size\r
+ // plus the file's size, or the header size plus the compressed file size.\r
+ //\r
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {\r
+ //\r
+ // Allocate a buffer into which we can compress the image, compress it,\r
+ // and use that size as the new size.\r
+ //\r
+ CompressedBuffer = (INT8 *) malloc (FileSize);\r
+ if (CompressedBuffer == NULL) {\r
+ fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ CompressedFileSize = FileSize;\r
+ Status = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);\r
+ if (Status != STATUS_SUCCESS) {\r
+ fprintf (stdout, "ERROR: Compression failed\n");\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Now compute the size, then swap buffer pointers.\r
+ //\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " Comp size = 0x%X\n", CompressedFileSize);\r
+ }\r
+\r
+ TotalSize = CompressedFileSize + HeaderSize;\r
+ FileSize = CompressedFileSize;\r
+ TempBufferPtr = Buffer;\r
+ Buffer = CompressedBuffer;\r
+ CompressedBuffer = TempBufferPtr;\r
+ } else {\r
+ TotalSize = FileSize + HeaderSize;\r
+ }\r
+ //\r
+ // Total size must be an even multiple of 512 bytes\r
+ //\r
+ if (TotalSize & 0x1FF) {\r
+ TotalSize = (TotalSize + 0x200) &~0x1ff;\r
+ }\r
+ //\r
+ // Check size\r
+ //\r
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
+ InFile->FileName,\r
+ MAX_OPTION_ROM_SIZE\r
+ );\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Return the size to the caller so they can keep track of the running total.\r
+ //\r
+ *Size = TotalSize;\r
+\r
+ //\r
+ // Now fill in the ROM header. These values come from chapter 18 of the\r
+ // EFI 1.02 specification.\r
+ //\r
+ memset (&RomHdr, 0, sizeof (RomHdr));\r
+ RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;\r
+ RomHdr.InitializationSize = (UINT16) (TotalSize / 512);\r
+ RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;\r
+ RomHdr.EfiSubsystem = SubSystem;\r
+ RomHdr.EfiMachineType = MachineType;\r
+ RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;\r
+ RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);\r
+ //\r
+ // Set image as compressed or not\r
+ //\r
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {\r
+ RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;\r
+ }\r
+ //\r
+ // Fill in the PCI data structure\r
+ //\r
+ memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE));\r
+\r
+ PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE;\r
+ PciDs.VendorId = VendId;\r
+ PciDs.DeviceId = DevId;\r
+ PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE);\r
+ PciDs.Revision = 0;\r
+ //\r
+ // Class code and code revision from the command line (optional)\r
+ //\r
+ PciDs.ClassCode[0] = (UINT8) InFile->ClassCode;\r
+ PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);\r
+ PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);\r
+ PciDs.ImageLength = RomHdr.InitializationSize;\r
+ PciDs.CodeRevision = InFile->CodeRevision;\r
+ PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE;\r
+\r
+ //\r
+ // If this is the last image, then set the LAST bit unless requested not\r
+ // to via the command-line -l argument.\r
+ //\r
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
+ PciDs.Indicator = INDICATOR_LAST;\r
+ }\r
+ //\r
+ // Write the ROM header to the output file\r
+ //\r
+ if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ //\r
+ // Write pad bytes to align the PciDs\r
+ //\r
+ while (HeaderPadBytes > 0) {\r
+ if (putc (0, OutFptr) == EOF) {\r
+ fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ HeaderPadBytes--;\r
+ }\r
+ //\r
+ // Write the PCI data structure header to the output file\r
+ //\r
+ if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Keep track of how many bytes left to write\r
+ //\r
+ TotalSize -= HeaderSize;\r
+\r
+ //\r
+ // Now dump the input file's contents to the output file\r
+ //\r
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ TotalSize -= FileSize;\r
+ //\r
+ // Pad the rest of the image to make it a multiple of 512 bytes\r
+ //\r
+ while (TotalSize > 0) {\r
+ if (putc (~0, OutFptr) == EOF) {\r
+ fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ TotalSize--;\r
+ }\r
+\r
+BailOut:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ //\r
+ // Free up our buffers\r
+ //\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+\r
+ if (CompressedBuffer != NULL) {\r
+ free (CompressedBuffer);\r
+ }\r
+ //\r
+ // Print the file name if errors occurred\r
+ //\r
+ if (Status != STATUS_SUCCESS) {\r
+ fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+int\r
+CheckPE32File (\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Fptr - GC_TODO: add argument description\r
+ MachineType - GC_TODO: add argument description\r
+ SubSystem - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ /*++\r
+\r
+Routine Description:\r
+ \r
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+ PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+ Fptr File pointer to the already-opened PE32 file\r
+ MachineType Location to stuff the machine type of the PE32 file. This is needed\r
+ because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_FILE_HEADER FileHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+ UINT32 PESig;\r
+\r
+ //\r
+ // Position to the start of the file\r
+ //\r
+ fseek (Fptr, 0, SEEK_SET);\r
+\r
+ //\r
+ // Read the DOS header\r
+ //\r
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Check the magic number (0x5A4D)\r
+ //\r
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Position into the file and check the PE signature\r
+ //\r
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Check the PE signature in the header "PE\0\0"\r
+ //\r
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Read the file header and stuff their MachineType\r
+ //\r
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memcpy ((char *) MachineType, &FileHdr.Machine, 2);\r
+\r
+ //\r
+ // Read the optional header so we can get the subsystem\r
+ //\r
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ *SubSystem = OptionalHdr.Subsystem;\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);\r
+ }\r
+ //\r
+ // Good to go\r
+ //\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[],\r
+ OPTIONS *Options\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+ parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+ Argv[] - standard C main() argument list\r
+ Options - pointer to a structure to store the options in\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS success\r
+ non-zero otherwise\r
+\r
+--*/\r
+//\r
+{\r
+ FILE_LIST *FileList;\r
+\r
+ FILE_LIST *PrevFileList;\r
+ UINT32 FileFlags;\r
+ UINT32 ClassCode;\r
+ UINT32 CodeRevision;\r
+\r
+ FileFlags = 0;\r
+\r
+ //\r
+ // Clear out the options\r
+ //\r
+ memset ((char *) Options, 0, sizeof (OPTIONS));\r
+\r
+ //\r
+ // To avoid compile warnings\r
+ //\r
+ FileList = PrevFileList = NULL;\r
+\r
+ ClassCode = 0;\r
+ CodeRevision = 0;\r
+ //\r
+ // Skip over the program name\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+\r
+ //\r
+ // If no arguments, assume they want usage info\r
+ //\r
+ if (Argc == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Process until no more arguments\r
+ //\r
+ while (Argc > 0) {\r
+ if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {\r
+ //\r
+ // To simplify string comparisons, replace slashes with dashes\r
+ //\r
+ Argv[0][0] = '-';\r
+\r
+ //\r
+ // Vendor ID specified with -v\r
+ //\r
+ if (stricmp (Argv[0], "-v") == 0) {\r
+ //\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ Options->VendId = (UINT16) strtol (Argv[1], NULL, 16);\r
+ Options->VendIdValid = 1;\r
+ } else {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Missing Vendor ID with %s\n\n",\r
+ Argv[0]\r
+ );\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else if (stricmp (Argv[0], "-d") == 0) {\r
+ //\r
+ // Device ID specified with -d\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ Options->DevId = (UINT16) strtol (Argv[1], NULL, 16);\r
+ Options->DevIdValid = 1;\r
+ } else {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Missing Device ID with %s\n\n",\r
+ Argv[0]\r
+ );\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else if (stricmp (Argv[0], "-o") == 0) {\r
+ //\r
+ // Output filename specified with -o\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ strcpy (Options->OutFileName, Argv[1]);\r
+ } else {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Missing output file name with %s\n\n",\r
+ Argv[0]\r
+ );\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+ //\r
+ // Help option\r
+ //\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ } else if (stricmp (Argv[0], "-b") == 0) {\r
+ //\r
+ // Specify binary files with -b\r
+ //\r
+ FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;\r
+ } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {\r
+ //\r
+ // Specify EFI files with -e. Specify EFI-compressed with -ec.\r
+ //\r
+ FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI;\r
+ if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {\r
+ FileFlags |= FILE_FLAG_COMPRESS;\r
+ }\r
+ //\r
+ // Specify not to set the LAST bit in the last file with -l\r
+ //\r
+ } else if (stricmp (Argv[0], "-l") == 0) {\r
+ Options->NoLast = 1;\r
+ } else if (stricmp (Argv[0], "-p") == 0) {\r
+ //\r
+ // -v for verbose would have been nicer, but it's already used. Let's use\r
+ // -p for prolix (wordy) output\r
+ //\r
+ Options->Verbose = 1;\r
+ } else if (stricmp (Argv[0], "-dump") == 0) {\r
+ //\r
+ // -dump for dumping a ROM image. In this case, say that the device id\r
+ // and vendor id are valid so we don't have to specify bogus ones on the\r
+ // command line.\r
+ //\r
+ Options->DumpOption = 1;\r
+\r
+ Options->VendIdValid = 1;\r
+ Options->DevIdValid = 1;\r
+ FileFlags = FILE_FLAG_BINARY;\r
+ } else if (stricmp (Argv[0], "-cc") == 0) {\r
+ //\r
+ // Class code value for the next file in the list.\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ //\r
+ // No error checking on the return value. Could check for LONG_MAX,\r
+ // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)\r
+ // at least.\r
+ //\r
+ ClassCode = (UINT32) strtol (Argv[1], NULL, 16);\r
+ if (ClassCode & 0xFF000000) {\r
+ fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]);\r
+ return STATUS_ERROR;\r
+ }\r
+ } else {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Missing class code value with %s\n\n",\r
+ Argv[0]\r
+ );\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else if (stricmp (Argv[0], "-rev") == 0) {\r
+ //\r
+ // Code revision in the PCI data structure. The value is for the next\r
+ // file in the list.\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ //\r
+ // No error checking on the return value. Could check for LONG_MAX,\r
+ // LONG_MIN, or 0 value if desired. Check range (2 bytes)\r
+ // at least.\r
+ //\r
+ CodeRevision = (UINT32) strtol (Argv[1], NULL, 16);\r
+ if (CodeRevision & 0xFFFF0000) {\r
+ fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]);\r
+ return STATUS_ERROR;\r
+ }\r
+ } else {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Missing code revision value with %s\n\n",\r
+ Argv[0]\r
+ );\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else {\r
+ fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]);\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ } else {\r
+ //\r
+ // Not a slash-option argument. Must be a file name. Make sure they've specified\r
+ // -e or -b already.\r
+ //\r
+ if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {\r
+ fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Create a new file structure\r
+ //\r
+ FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
+ if (FileList == NULL) {\r
+ fprintf (stdout, "ERROR: Memory allocation failure\n");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memset ((char *) FileList, 0, sizeof (FILE_LIST));\r
+ FileList->FileName = Argv[0];\r
+ FileList->FileFlags = FileFlags;\r
+ if (Options->FileList == NULL) {\r
+ Options->FileList = FileList;\r
+ } else {\r
+ if (PrevFileList == NULL) {\r
+ PrevFileList = FileList;\r
+ } else { \r
+ PrevFileList->Next = FileList;\r
+ }\r
+ }\r
+\r
+ PrevFileList = FileList;\r
+ //\r
+ // Set the class code and code revision for this file, then reset the values.\r
+ //\r
+ FileList->ClassCode = ClassCode;\r
+ FileList->CodeRevision = (UINT16) CodeRevision;\r
+ ClassCode = 0;\r
+ CodeRevision = 0;\r
+ }\r
+ //\r
+ // Next argument\r
+ //\r
+ Argv++;\r
+ Argc--;\r
+ }\r
+ //\r
+ // Make sure they specified a device ID and vendor ID\r
+ //\r
+ if (!Options->VendIdValid) {\r
+ fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n");\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (!Options->DevIdValid) {\r
+ fprintf (stdout, "ERROR: Missing Device ID on command line\n\n");\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Must have specified some files\r
+ //\r
+ if (Options->FileList == NULL) {\r
+ fprintf (stdout, "ERROR: Missing input file name\n");\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ int Index;\r
+ static const char *Msg[] = {\r
+ "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility",\r
+ " Copyright (C), 1999-2002 Intel Coproration\n",\r
+ " Create an option ROM image from a list of input files",\r
+ " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",\r
+ " [-e|-b] [FileName(s)]",\r
+ " where:",\r
+ " VendorId - required hex PCI Vendor ID for the device",\r
+ " DeviceId - required hex PCI Device ID for the device",\r
+ " OutFileName - optional output file name. Default is the first input",\r
+ " file name with a "DEFAULT_OUTPUT_EXTENSION " file extension",\r
+ " FileNames - input PE32 or binary file name(s)",\r
+ " BinFileName - input binary file name(s)",\r
+ " -p - for verbose output",\r
+ " -l - to not automatically set the LAST bit on the last file",\r
+ " -b - following FileNames are binary files",\r
+ " -e - following FileNames are EFI PE32 image files",\r
+ " -ec - following FileNames are EFI PE32 image files, and should",\r
+ " be compressed by this utility",\r
+ " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",\r
+ " the following FileName",\r
+ " -rev Revision - to use hex Revision in the PCI data structure header for",\r
+ " the following FileName",\r
+ " -dump - to dump the headers of an existing option ROM image",\r
+ "",\r
+ "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",\r
+ "",\r
+ NULL\r
+ };\r
+\r
+ for (Index = 0; Msg[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Msg[Index]);\r
+ }\r
+}\r
+\r
+static\r
+void\r
+DumpImage (\r
+ FILE_LIST *InFile\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ InFile - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ PCI_EXPANSION_ROM_HEADER PciRomHdr;\r
+ FILE *InFptr;\r
+ UINT32 ImageStart;\r
+ UINT32 ImageCount;\r
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;\r
+ PCI_DATA_STRUCTURE PciDs;\r
+\r
+ //\r
+ // Open the input file\r
+ //\r
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Could not open input file %s\n",\r
+ InFile->FileName\r
+ );\r
+ return ;\r
+ }\r
+ //\r
+ // Go through the image and dump the header stuff for each\r
+ //\r
+ ImageCount = 0;\r
+ for (;;) {\r
+ //\r
+ // Save our postition in the file, since offsets in the headers\r
+ // are relative to the particular image.\r
+ //\r
+ ImageStart = ftell (InFptr);\r
+ ImageCount++;\r
+\r
+ //\r
+ // Read the option ROM header. Have to assume a raw binary image for now.\r
+ //\r
+ if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n");\r
+ goto BailOut;\r
+ }\r
+\r
+ //\r
+ // Dump the contents of the header\r
+ //\r
+ fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart);\r
+ fprintf (stdout, " ROM header contents\n");\r
+ fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature);\r
+ fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset);\r
+ //\r
+ // Find PCI data structure\r
+ //\r
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {\r
+ fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n");\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Read and dump the PCI data structure\r
+ //\r
+ if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n");\r
+ goto BailOut;\r
+ }\r
+\r
+ fprintf (stdout, " PCI Data Structure\n");\r
+ fprintf (\r
+ stdout,\r
+ " Signature %c%c%c%c\n",\r
+ (char) PciDs.Signature,\r
+ (char) (PciDs.Signature >> 8),\r
+ (char) (PciDs.Signature >> 16),\r
+ (char) (PciDs.Signature >> 24)\r
+ );\r
+ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId);\r
+ fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId);\r
+ fprintf (\r
+ stdout,\r
+ " Class Code 0x%06X\n",\r
+ (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))\r
+ );\r
+ fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512);\r
+ fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision);\r
+ fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator);\r
+ //\r
+ // Print the indicator, used to flag the last image\r
+ //\r
+ if (PciDs.Indicator == INDICATOR_LAST) {\r
+ fprintf (stdout, " (last image)\n");\r
+ } else {\r
+ fprintf (stdout, "\n");\r
+ }\r
+ //\r
+ // Print the code type. If EFI code, then we can provide more info.\r
+ //\r
+ fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType);\r
+ if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+ fprintf (stdout, " (EFI image)\n");\r
+ //\r
+ // Re-read the header as an EFI ROM header, then dump more info\r
+ //\r
+ fprintf (stdout, " EFI ROM header contents\n");\r
+ if (fseek (InFptr, ImageStart, SEEK_SET)) {\r
+ fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");\r
+ goto BailOut;\r
+ }\r
+\r
+ if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Now dump more info\r
+ //\r
+ fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature);\r
+ fprintf (\r
+ stdout,\r
+ " Compression Type 0x%04X ",\r
+ (UINT32) EfiRomHdr.CompressionType\r
+ );\r
+ if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+ fprintf (stdout, "(compressed)\n");\r
+ } else {\r
+ fprintf (stdout, "(not compressed)\n");\r
+ }\r
+\r
+ fprintf (\r
+ stdout,\r
+ " Machine type 0x%04X (%s)\n",\r
+ EfiRomHdr.EfiMachineType,\r
+ GetMachineTypeStr (EfiRomHdr.EfiMachineType)\r
+ );\r
+ fprintf (\r
+ stdout,\r
+ " Subsystem 0x%04X (%s)\n",\r
+ EfiRomHdr.EfiSubsystem,\r
+ GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)\r
+ );\r
+ fprintf (\r
+ stdout,\r
+ " EFI image offset 0x%04X (@0x%X)\n",\r
+ (UINT32) EfiRomHdr.EfiImageHeaderOffset,\r
+ (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)\r
+ );\r
+\r
+ } else {\r
+ //\r
+ // Not an EFI image\r
+ //\r
+ fprintf (stdout, "\n");\r
+ }\r
+ //\r
+ // If code type is EFI image, then dump it as well?\r
+ //\r
+ // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+ // }\r
+ //\r
+ // If last image, then we're done\r
+ //\r
+ if (PciDs.Indicator == INDICATOR_LAST) {\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Seek to the start of the next image\r
+ //\r
+ if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) {\r
+ fprintf (stdout, "ERROR: Failed to seek to next image\n");\r
+ goto BailOut;\r
+ }\r
+ }\r
+\r
+BailOut:\r
+ fclose (InFptr);\r
+}\r
+\r
+char *\r
+GetMachineTypeStr (\r
+ UINT16 MachineType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ MachineType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ int Index;\r
+\r
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {\r
+ if (mMachineTypes[Index].Value == MachineType) {\r
+ return mMachineTypes[Index].Name;\r
+ }\r
+ }\r
+\r
+ return "unknown";\r
+}\r
+\r
+static\r
+char *\r
+GetSubsystemTypeStr (\r
+ UINT16 SubsystemType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ SubsystemType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ int Index;\r
+\r
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {\r
+ if (mSubsystemTypes[Index].Value == SubsystemType) {\r
+ return mSubsystemTypes[Index].Name;\r
+ }\r
+ }\r
+\r
+ return "unknown";\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name:\r
+# \r
+# makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the EfiRom utility.\r
+# \r
+# Revision History\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = EfiRom\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\EfiRom.exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\EfiRom.obj \\r
+ $(TIANO_TOOLS_OUTPUT)\EfiCompress.obj\r
+ \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiRom.obj : $(TARGET_SRC_DIR)\EfiRom.c\r
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\EfiRom.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiCompress.obj : $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c\r
+ $(CC) $(C_FLAGS) $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c /Fo$@\r
+ \r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004-2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ FlashDefFile.c\r
+\r
+Abstract:\r
+\r
+ Utility for flash management in the Intel Platform Innovation Framework\r
+ for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "FlashDefFile.h"\r
+#include "SimpleFileParsing.h"\r
+#include "Symbols.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+\r
+//\r
+// #include "TrackMallocFree.h"\r
+//\r
+#define WCHAR_T char\r
+#define MAX_STRING_LEN 256\r
+#define MAX_NAME_LEN 128\r
+#define BUFFER_SIZE 1024\r
+#define MAX_ATTR_LEN 128\r
+#define MAX_AREATYPE_LEN 128\r
+#define COLUMN2_START 60\r
+#define COLUMN3_START 70\r
+//\r
+// Information for each subregions defined in the fdf file will be saved in these\r
+//\r
+typedef struct _FLASH_SUBREGION_DESCRIPTION {\r
+ struct _FLASH_SUBREGION_DESCRIPTION *Next;\r
+ int CreateHob; // to add to the auto-created HOB array\r
+ WCHAR_T Name[MAX_NAME_LEN]; // each subregion within a region must have a unique name\r
+ unsigned int Size; // size, in bytes, of this subregion\r
+ unsigned int SizeLeft; // used when creating the image\r
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // subregion attributes used in the output HOB\r
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB\r
+ EFI_GUID NameGuid; // used in the output HOB\r
+ WCHAR_T NameGuidString[MAX_NAME_LEN];\r
+ EFI_GUID AreaTypeGuid; // used in the output HOB\r
+ WCHAR_T AreaTypeGuidString[MAX_NAME_LEN];\r
+ EFI_GUID FileSystemGuid; // used in the output HOB\r
+ WCHAR_T FileSystemGuidString[MAX_NAME_LEN];\r
+} FLASH_SUBREGION_DESCRIPTION;\r
+\r
+//\r
+// Information for each block in a flash device will be saved in one of these.\r
+// We'll also use it for region definitions.\r
+//\r
+typedef struct _FLASH_BLOCK_DESCRIPTION {\r
+ struct _FLASH_BLOCK_DESCRIPTION *Next; // next block in the linked list\r
+ WCHAR_T Name[MAX_NAME_LEN]; // each block must have a unique name\r
+ unsigned int Size; // size, in bytes, of this block\r
+ unsigned int SizeLeft; // for use when creating image\r
+ unsigned int Flags; // user-defined flags for the block\r
+ unsigned int Alignment; // power of 2 alignment\r
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // only used for Region definitions\r
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions\r
+ FLASH_SUBREGION_DESCRIPTION *Subregions;\r
+ FLASH_SUBREGION_DESCRIPTION *LastSubregion;\r
+} FLASH_BLOCK_DESCRIPTION;\r
+\r
+//\r
+// Information for each flash device will be saved in one of these\r
+//\r
+typedef struct _FLASH_DEVICE_DESCRIPTION {\r
+ struct _FLASH_DEVICE_DESCRIPTION *Next; // next flash device in our linked list\r
+ int ErasePolarity; // erase polarity of the flash device\r
+ unsigned int BaseAddress; // base address of the flash device\r
+ unsigned int Size; // total size, in bytes, of the flash device\r
+ WCHAR_T Name[MAX_NAME_LEN]; // name of the flash device\r
+ FLASH_BLOCK_DESCRIPTION *PBlocks; // linked list of physical block descriptors\r
+ FLASH_BLOCK_DESCRIPTION *LastPBlock; // last block in the linked list\r
+ FLASH_BLOCK_DESCRIPTION *Regions; // linked list of flash region descriptors\r
+ FLASH_BLOCK_DESCRIPTION *LastRegion; // last region in the linked list\r
+} FLASH_DEVICE_DESCRIPTION;\r
+\r
+//\r
+// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.\r
+//\r
+typedef struct _IMAGE_DEFINITION_ENTRY {\r
+ struct _IMAGE_DEFINITION_ENTRY *Next;\r
+ WCHAR_T RegionName[MAX_NAME_LEN];\r
+ WCHAR_T SubregionName[MAX_NAME_LEN];\r
+ WCHAR_T Name[MAX_NAME_LEN]; // file or data name\r
+ int IsRawData; // non-zero if raw data bytes\r
+ unsigned int RawDataSize;\r
+ char *RawData;\r
+ int Optional; // optional file (don't include if it doesn't exist)\r
+} IMAGE_DEFINITION_ENTRY;\r
+\r
+//\r
+// When we parse an image definition, save all the data for each in one of these\r
+//\r
+typedef struct _IMAGE_DEFINITION {\r
+ struct _IMAGE_DEFINITION *Next;\r
+ WCHAR_T Name[MAX_NAME_LEN];\r
+ IMAGE_DEFINITION_ENTRY *Entries;\r
+ IMAGE_DEFINITION_ENTRY *LastEntry;\r
+} IMAGE_DEFINITION;\r
+\r
+typedef struct {\r
+ char *BufferStart;\r
+ char *BufferEnd;\r
+ char *BufferPos;\r
+} BUFFER_DATA;\r
+\r
+static const char *CIncludeHeader = "/*++\n\n"\r
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"\r
+"#define _FLASH_MAP_H_\n\n";\r
+//\r
+// "#include \"EfiFlashMap.h\"\n\n";\r
+//\r
+static const char *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";\r
+\r
+static const char *CFlashMapDataFileHeader = "/*++\n\n"\r
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";\r
+\r
+static FLASH_DEVICE_DESCRIPTION *mFlashDevices = NULL;\r
+static IMAGE_DEFINITION *mImageDefinitions = NULL;\r
+\r
+//\r
+// Local function prototypes\r
+//\r
+static\r
+BUFFER_DATA *\r
+CreateBufferData (\r
+ VOID\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+AddBufferDataByte (\r
+ BUFFER_DATA *Buffer,\r
+ char Data\r
+ );\r
+\r
+static\r
+void\r
+FreeBufferData (\r
+ BUFFER_DATA *Buffer,\r
+ BOOLEAN FreeData\r
+ );\r
+\r
+static\r
+char *\r
+GetBufferData (\r
+ BUFFER_DATA *Buffer,\r
+ int *BufferSize\r
+ );\r
+\r
+static\r
+FLASH_SUBREGION_DESCRIPTION *\r
+ParseSubregionDefinition (\r
+ unsigned int SizeLeft\r
+ );\r
+\r
+void\r
+FDFConstructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Initialization routine for the services that operate on a flash\r
+ definition file.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ mFlashDevices = NULL;\r
+ mImageDefinitions = NULL;\r
+}\r
+\r
+void\r
+FDFDestructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Finalization/cleanup routine for the services that operate on a flash\r
+ definition file.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ FLASH_BLOCK_DESCRIPTION *FBNext;\r
+ FLASH_DEVICE_DESCRIPTION *FDNext;\r
+ IMAGE_DEFINITION *IDNext;\r
+ IMAGE_DEFINITION_ENTRY *IDENext;\r
+ FLASH_SUBREGION_DESCRIPTION *SubNext;\r
+ //\r
+ // Go through all our flash devices and free the memory\r
+ //\r
+ while (mFlashDevices != NULL) {\r
+ //\r
+ // Free the physical block definitions\r
+ //\r
+ while (mFlashDevices->PBlocks != NULL) {\r
+ FBNext = mFlashDevices->PBlocks->Next;\r
+ _free (mFlashDevices->PBlocks);\r
+ mFlashDevices->PBlocks = FBNext;\r
+ }\r
+ //\r
+ // Free the region definitions\r
+ //\r
+ while (mFlashDevices->Regions != NULL) {\r
+ FBNext = mFlashDevices->Regions->Next;\r
+ //\r
+ // First free the subregion definitions\r
+ //\r
+ while (mFlashDevices->Regions->Subregions != NULL) {\r
+ SubNext = mFlashDevices->Regions->Subregions->Next;\r
+ _free (mFlashDevices->Regions->Subregions);\r
+ mFlashDevices->Regions->Subregions = SubNext;\r
+ }\r
+\r
+ _free (mFlashDevices->Regions);\r
+ mFlashDevices->Regions = FBNext;\r
+ }\r
+\r
+ FDNext = mFlashDevices->Next;\r
+ _free (mFlashDevices);\r
+ mFlashDevices = FDNext;\r
+ }\r
+ //\r
+ // Free up the image definitions, and the data\r
+ //\r
+ while (mImageDefinitions != NULL) {\r
+ //\r
+ // Free the entries\r
+ //\r
+ while (mImageDefinitions->Entries != NULL) {\r
+ IDENext = mImageDefinitions->Entries->Next;\r
+ if (mImageDefinitions->Entries->RawData != NULL) {\r
+ _free (mImageDefinitions->Entries->RawData);\r
+ }\r
+\r
+ _free (mImageDefinitions->Entries);\r
+ mImageDefinitions->Entries = IDENext;\r
+ }\r
+\r
+ IDNext = mImageDefinitions->Next;\r
+ _free (mImageDefinitions);\r
+ mImageDefinitions = IDNext;\r
+ }\r
+}\r
+\r
+STATUS\r
+FDFParseFile (\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Parse the specified flash definition file, saving the definitions in\r
+ file-static variables for use by other functions.\r
+ \r
+Arguments:\r
+ FileName - name of the input flash definition text file.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - file parsed with no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered while parsing\r
+ STATUS_ERROR - errors were encountered while parsing\r
+ \r
+--*/\r
+{\r
+ FILE *Fptr;\r
+ STATUS Status;\r
+ unsigned int Num;\r
+ FLASH_DEVICE_DESCRIPTION *FDDesc;\r
+ FLASH_BLOCK_DESCRIPTION *FBlockDesc;\r
+ FLASH_BLOCK_DESCRIPTION *TempBlockDesc;\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ FLASH_SUBREGION_DESCRIPTION *TempSubregion;\r
+ unsigned int BlockSizeLeft;\r
+ unsigned int RegionSizeLeft;\r
+ unsigned int SubregionSizeLeft;\r
+ int ErrorCount;\r
+ int WarningCount;\r
+ IMAGE_DEFINITION *ImageDef;\r
+ IMAGE_DEFINITION_ENTRY *ImageDefEntry;\r
+ IMAGE_DEFINITION_ENTRY *TempImageDefEntry;\r
+ BUFFER_DATA *BufferData;\r
+ char Str[100];\r
+ BOOLEAN PreviousComma;\r
+\r
+ if ((Fptr = fopen (FileName, "r")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ fclose (Fptr);\r
+ Status = STATUS_SUCCESS;\r
+ ErrorCount = 0;\r
+ WarningCount = 0;\r
+ //\r
+ // Initialize the simple-file-parsing routines\r
+ //\r
+ SFPInit ();\r
+ //\r
+ // Open the file\r
+ //\r
+ if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Parse the file. Should start with a series of these:\r
+ // FlashDevice {\r
+ // Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,\r
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }\r
+ // Block { Name = "BLOCK2", Size = 0x1004, Flags = 0x0002 }\r
+ // Region { Name = "REGION_NAME", Size = 0x2004, Align= 4 }\r
+ // }\r
+ //\r
+ while (SFPIsKeyword ("FlashDevice")) {\r
+ //\r
+ // Allocate memory for new flash device description block\r
+ //\r
+ FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));\r
+ if (FDDesc == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "DeviceName",\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Size = 0x20000,\r
+ //\r
+ if (!SFPIsKeyword ("Size")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FDDesc->Size)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Check for 0 size\r
+ //\r
+ if (FDDesc->Size == 0) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ SFPIsToken (",");\r
+ //\r
+ // Parse: BaseAddress = 0xFFF0000,\r
+ //\r
+ if (!SFPIsKeyword ("BaseAddress")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FDDesc->BaseAddress)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: ErasePolarity = 1,\r
+ //\r
+ if (!SFPIsKeyword ("ErasePolarity")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ FDDesc->ErasePolarity = Num;\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse array of:\r
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }\r
+ //\r
+ // Keep track of size to make sure the sum of the physical blocks and region sizes do not\r
+ // exceed the size of the flash device.\r
+ //\r
+ BlockSizeLeft = FDDesc->Size;\r
+ RegionSizeLeft = FDDesc->Size;\r
+ while (SFPIsKeyword ("Block")) {\r
+ //\r
+ // Allocate memory for a new physical block descriptor\r
+ //\r
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));\r
+ if (FBlockDesc == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "BlockName",\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Make sure there are no other physical block names with this same name\r
+ //\r
+ for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {\r
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ TempBlockDesc->Name,\r
+ "physical block with this name already defined"\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Size = 0x2000,\r
+ //\r
+ if (!SFPIsKeyword ("Size")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FBlockDesc->Size)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Make sure the sum of physical blocks so far does not exceed flash device size\r
+ //\r
+ if (BlockSizeLeft < FBlockDesc->Size) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ "sum of physical block sizes exceeds flash device size",\r
+ NULL\r
+ );\r
+ ErrorCount++;\r
+ }\r
+\r
+ BlockSizeLeft -= FBlockDesc->Size;\r
+ SFPIsToken (",");\r
+ //\r
+ // Optional parse: Flags = 0xFFF0000,\r
+ //\r
+ if (SFPIsKeyword ("Flags")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (!SFPIsToken ("}")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Add the physical block descriptor to the end of the linked list\r
+ //\r
+ if (FDDesc->LastPBlock != NULL) {\r
+ FDDesc->LastPBlock->Next = FBlockDesc;\r
+ } else {\r
+ FDDesc->PBlocks = FBlockDesc;\r
+ }\r
+\r
+ FDDesc->LastPBlock = FBlockDesc;\r
+ }\r
+ //\r
+ // Make sure sum of sizes of physical blocks added up to size of flash device\r
+ //\r
+ if (BlockSizeLeft != 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ NULL,\r
+ "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",\r
+ FDDesc->Size - BlockSizeLeft,\r
+ FDDesc->Size,\r
+ BlockSizeLeft\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ //\r
+ // Parse array of:\r
+ // Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }\r
+ //\r
+ while (SFPIsKeyword ("Region")) {\r
+ //\r
+ // Allocate memory for a new physical block descriptor\r
+ //\r
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));\r
+ if (FBlockDesc == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "BlockName",\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Make sure there are no other region names with this same name\r
+ //\r
+ for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {\r
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ TempBlockDesc->Name,\r
+ "Region with this name already defined"\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Size = 0x2000,\r
+ //\r
+ if (!SFPIsKeyword ("Size")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FBlockDesc->Size)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+ }\r
+ //\r
+ // Make sure the sum of regions so far does not exceed flash device size\r
+ //\r
+ if (RegionSizeLeft < FBlockDesc->Size) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);\r
+ ErrorCount++;\r
+ }\r
+\r
+ RegionSizeLeft -= FBlockDesc->Size;\r
+ //\r
+ // Optional parse: Flags = 0xFFF0000,\r
+ //\r
+ if (SFPIsKeyword ("Flags")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // comma\r
+ //\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+ }\r
+ }\r
+ //\r
+ // Optional parse: Alignment = 4\r
+ //\r
+ if (SFPIsKeyword ("Alignment")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&FBlockDesc->Alignment)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // comma\r
+ //\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+ }\r
+ }\r
+ //\r
+ // Parse: Attributes = "String",\r
+ //\r
+ if (!SFPIsKeyword ("Attributes")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+ }\r
+ //\r
+ // Parse: AreaType = "String",\r
+ //\r
+ if (!SFPIsKeyword ("AreaType")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ PreviousComma = SFPIsToken (",");\r
+ //\r
+ // Parse optional Subregion definitions\r
+ //\r
+ SubregionSizeLeft = FBlockDesc->Size;\r
+ while (SFPIsToken ("Subregion")) {\r
+ if (!PreviousComma) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);\r
+ WarningCount++;\r
+ PreviousComma = TRUE;\r
+ }\r
+\r
+ Subregion = ParseSubregionDefinition (SubregionSizeLeft);\r
+ if (Subregion == NULL) {\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ SubregionSizeLeft -= Subregion->Size;\r
+ //\r
+ // Add it to the end of our list\r
+ //\r
+ if (FBlockDesc->Subregions == NULL) {\r
+ FBlockDesc->Subregions = Subregion;\r
+ } else {\r
+ FBlockDesc->LastSubregion->Next = Subregion;\r
+ }\r
+\r
+ FBlockDesc->LastSubregion = Subregion;\r
+ //\r
+ // Make sure all subregion names are unique. We do this each time\r
+ // through so that we catch the error immediately after it happens, in\r
+ // which case the reported line number is at least close to where the\r
+ // problem lies. We don't exit on the error because we can continue parsing\r
+ // the script to perhaps catch other errors or warnings.\r
+ //\r
+ for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {\r
+ if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");\r
+ ErrorCount++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!SFPIsToken ("}")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Add the region descriptor to the end of the linked list\r
+ //\r
+ if (FDDesc->LastRegion != NULL) {\r
+ FDDesc->LastRegion->Next = FBlockDesc;\r
+ } else {\r
+ FDDesc->Regions = FBlockDesc;\r
+ }\r
+\r
+ FDDesc->LastRegion = FBlockDesc;\r
+ }\r
+ //\r
+ // Make sure sum of sizes of regions adds up to size of flash device\r
+ //\r
+ if (RegionSizeLeft != 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ NULL,\r
+ "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",\r
+ FDDesc->Size - RegionSizeLeft,\r
+ FDDesc->Size,\r
+ RegionSizeLeft\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ //\r
+ // Look for closing brace\r
+ //\r
+ if (!SFPIsToken ("}")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Add this flash description to the list\r
+ //\r
+ FDDesc->Next = mFlashDevices;\r
+ mFlashDevices = FDDesc;\r
+ }\r
+\r
+ while (SFPIsKeyword ("FlashDeviceImage")) {\r
+ //\r
+ // Allocate memory for a new FD image definition\r
+ //\r
+ ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));\r
+ if (ImageDef == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "ImageName",\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ while (1) {\r
+ //\r
+ // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }\r
+ //\r
+ if (SFPIsKeyword ("File")) {\r
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));\r
+ if (ImageDefEntry == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "FileName.txt"\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Region = "REGION_NAME"\r
+ //\r
+ if (!SFPIsKeyword ("Region")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse optional: Subregion = "SUBREGION_NAME"\r
+ //\r
+ if (SFPIsKeyword ("Subregion")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // For a given region, you can only place data using the region name, or the subregion names.\r
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that\r
+ // here by checking that any previous entries with the same Region name had a Subregion specified\r
+ // as well.\r
+ //\r
+ for (TempImageDefEntry = ImageDef->Entries;\r
+ TempImageDefEntry != NULL;\r
+ TempImageDefEntry = TempImageDefEntry->Next\r
+ ) {\r
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {\r
+ if (TempImageDefEntry->SubregionName[0] == 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ TempImageDefEntry->RegionName,\r
+ "data already placed on a region-basis in the region, can't place data using subregions"\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Optional parse: Optional = TRUE | FALSE\r
+ //\r
+ if (SFPIsKeyword ("Optional")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPIsKeyword ("TRUE")) {\r
+ ImageDefEntry->Optional = 1;\r
+ } else if (SFPIsKeyword ("FALSE")) {\r
+ //\r
+ // Already set to 0\r
+ //\r
+ } else {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ SFPIsToken (",");\r
+ }\r
+ //\r
+ // Closing brace\r
+ //\r
+ if (!SFPIsToken ("}")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Add the entry to the end of the list\r
+ //\r
+ if (ImageDef->LastEntry != NULL) {\r
+ ImageDef->LastEntry->Next = ImageDefEntry;\r
+ } else {\r
+ ImageDef->Entries = ImageDefEntry;\r
+ }\r
+\r
+ ImageDef->LastEntry = ImageDefEntry;\r
+ } else if (SFPIsKeyword ("RawData")) {\r
+ //\r
+ // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}\r
+ //\r
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));\r
+ if (ImageDefEntry == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));\r
+ ImageDefEntry->IsRawData = 1;\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ "expected '{' opening brace for RawData definition",\r
+ NULL\r
+ );\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "PadBytes"\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Region = "REGION_NAME"\r
+ //\r
+ if (!SFPIsKeyword ("Region")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse optional: Subregion = "SUBREGION_NAME"\r
+ //\r
+ if (SFPIsKeyword ("Subregion")) {\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // For a given region, you can only place data using the region name, or the subregion names.\r
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that\r
+ // here by checking that any previous entries with the same Region name had a Subregion specified\r
+ // as well.\r
+ //\r
+ for (TempImageDefEntry = ImageDef->Entries;\r
+ TempImageDefEntry != NULL;\r
+ TempImageDefEntry = TempImageDefEntry->Next\r
+ ) {\r
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {\r
+ if (TempImageDefEntry->SubregionName[0] == 0) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ TempImageDefEntry->RegionName,\r
+ "data already placed on a region-basis in the region, can't place data using subregions"\r
+ );\r
+ ErrorCount++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Parse: Data = { 0x78, 0x56, 0x34, 0x12 }\r
+ //\r
+ if (!SFPIsKeyword ("Data")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if ((BufferData = CreateBufferData ()) == NULL) {\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Read bytes from input file until closing brace\r
+ //\r
+ while (!SFPIsToken ("}")) {\r
+ if (!SFPGetNumber (&Num)) {\r
+ SFPGetNextToken (Str, sizeof (Str));\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);\r
+ ErrorCount++;\r
+ FreeBufferData (BufferData, TRUE);\r
+ goto Done;\r
+ } else {\r
+ //\r
+ // Only allow bytes\r
+ //\r
+ if (Num > 0xFF) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);\r
+ ErrorCount++;\r
+ FreeBufferData (BufferData, TRUE);\r
+ goto Done;\r
+ }\r
+\r
+ AddBufferDataByte (BufferData, (char) Num);\r
+ SFPIsToken (",");\r
+ }\r
+ }\r
+ //\r
+ // Now get the data and save it in our image entry\r
+ //\r
+ ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);\r
+ FreeBufferData (BufferData, 0);\r
+ //\r
+ // Closing brace for RawData {}\r
+ //\r
+ if (!SFPIsToken ("}")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Add the entry to the end of the list\r
+ //\r
+ if (ImageDef->LastEntry != NULL) {\r
+ ImageDef->LastEntry->Next = ImageDefEntry;\r
+ } else {\r
+ ImageDef->Entries = ImageDefEntry;\r
+ }\r
+\r
+ ImageDef->LastEntry = ImageDefEntry;\r
+ } else if (SFPIsToken ("}")) {\r
+ //\r
+ // Closing brace for FDImage {}\r
+ //\r
+ break;\r
+ } else {\r
+ SFPGetNextToken (Str, sizeof (Str));\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ }\r
+ //\r
+ // Add this image definition to our global list\r
+ //\r
+ ImageDef->Next = mImageDefinitions;\r
+ mImageDefinitions = ImageDef;\r
+ }\r
+ //\r
+ // Check for end-of-file\r
+ //\r
+ if (!SFPIsEOF ()) {\r
+ SFPGetNextToken (Str, sizeof (Str));\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);\r
+ ErrorCount++;\r
+ }\r
+\r
+Done:\r
+ SFPCloseFile ();\r
+ if (ErrorCount != 0) {\r
+ return STATUS_ERROR;\r
+ } else if (WarningCount != 0) {\r
+ return STATUS_WARNING;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+FLASH_SUBREGION_DESCRIPTION *\r
+ParseSubregionDefinition (\r
+ unsigned int SizeLeft\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ Parse Subregion definitions from the input flash definition file. Format:\r
+\r
+ Subregion {\r
+ CreateHob = TRUE,\r
+ Name = "FOO",\r
+ Size = 0xA000,\r
+ Attributes = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",\r
+ AreaType = "EFI_FLASH_AREA_EFI_VARIABLES",\r
+ NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),\r
+ AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)\r
+ FileSystemGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)\r
+ }\r
+\r
+ NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.\r
+\r
+Arguments:\r
+ \r
+ SizeLeft - in the flash definition file, a Region can be broken up into\r
+ one or more subregions. As we parse the subregion definitions,\r
+ the caller keeps track of how much space is left in the region\r
+ that we're parsing subregions for. SizeLeft is that size, and\r
+ so the size of the subregion we're now parsing better not\r
+ exceed the size left.\r
+ Returns:\r
+\r
+ NULL - unrecoverable errors detected while parsing the subregion definition\r
+\r
+ pointer to a subregion definition created from the parsed subregion\r
+\r
+--*/\r
+{\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ int ErrorCount;\r
+ int WarningCount;\r
+ unsigned int Number;\r
+ BOOLEAN PreviousComma;\r
+ //\r
+ // Allocate memory for the new subregion descriptor\r
+ //\r
+ ErrorCount = 0;\r
+ WarningCount = 0;\r
+ Subregion = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));\r
+ if (Subregion == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));\r
+ //\r
+ // Open brace -- warning if not there\r
+ //\r
+ if (!SFPIsToken ("{")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: CreateHob = TRUE | FALSE,\r
+ //\r
+ if (!SFPIsKeyword ("CreateHob")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (SFPIsToken ("TRUE")) {\r
+ Subregion->CreateHob = 1;\r
+ } else if (SFPIsToken ("FALSE")) {\r
+ //\r
+ // Subregion->CreateHob = 0; -- not required since we did a memset earlier\r
+ //\r
+ } else {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Name = "Name",\r
+ //\r
+ if (!SFPIsKeyword ("Name")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Parse: Size = 0x2000,\r
+ //\r
+ if (!SFPIsKeyword ("Size")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPGetNumber (&Subregion->Size)) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check that the size does not exceed the size left passed in\r
+ //\r
+ if (Subregion->Size > SizeLeft) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);\r
+ }\r
+ //\r
+ // Parse: Attributes = Number | "String",\r
+ //\r
+ if (!SFPIsKeyword ("Attributes")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (SFPGetNumber (&Number)) {\r
+ sprintf (Subregion->Attributes, "0x%X", Number);\r
+ } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+ }\r
+ //\r
+ // Parse: AreaType = Number | "String",\r
+ // AreaType is a UINT8, so error if it exceeds the size\r
+ //\r
+ if (!SFPIsKeyword ("AreaType")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (SFPGetNumber (&Number)) {\r
+ if (Number > 0xFF) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);\r
+ ErrorCount++;\r
+ }\r
+\r
+ sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);\r
+ } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken (",")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);\r
+ }\r
+ //\r
+ // Parse the three GUIDs (last two are optional)\r
+ //\r
+ // NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")\r
+ // AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")\r
+ // FileSysteGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")\r
+ //\r
+ if (!SFPIsKeyword ("NameGuid")) {\r
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string\r
+ //\r
+ if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {\r
+ //\r
+ // Nothing else to do\r
+ //\r
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+ NULL\r
+ );\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid\r
+ //\r
+ PreviousComma = SFPIsToken (",");\r
+ if (SFPIsKeyword ("AreaTypeGuid")) {\r
+ //\r
+ // Check for preceeding comma now\r
+ //\r
+ if (!PreviousComma) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {\r
+ //\r
+ // Nothing else to do\r
+ //\r
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+ NULL\r
+ );\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ PreviousComma = SFPIsToken (",");\r
+ }\r
+\r
+ if (SFPIsKeyword ("FileSystemGuid")) {\r
+ //\r
+ // Check for preceeding comma now\r
+ //\r
+ if (!PreviousComma) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+ if (!SFPIsToken ("=")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+ WarningCount++;\r
+ }\r
+ //\r
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string\r
+ //\r
+ if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {\r
+ //\r
+ // Nothing else to do\r
+ //\r
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {\r
+ Error (\r
+ SFPGetFileName (),\r
+ SFPGetLineNumber (),\r
+ 0,\r
+ "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+ NULL\r
+ );\r
+ ErrorCount++;\r
+ goto Done;\r
+ }\r
+\r
+ SFPIsToken (",");\r
+ }\r
+ //\r
+ // Look for subregion closing brace\r
+ //\r
+ if (!SFPIsToken ("}")) {\r
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);\r
+ WarningCount++;\r
+ }\r
+\r
+Done:\r
+ //\r
+ // If any errors were encountered, then delete the subregion definition\r
+ //\r
+ if (ErrorCount != 0) {\r
+ _free (Subregion);\r
+ Subregion = NULL;\r
+ }\r
+\r
+ return Subregion;\r
+}\r
+\r
+STATUS\r
+FDFCreateCIncludeFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Create a header file with #define definitions per an already-parsed\r
+ flash definition file.\r
+\r
+Arguments:\r
+ FlashDeviceName - name of flash device (from the flash definition file)\r
+ to use\r
+ FileName - name of output file to create\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ FILE *OutFptr;\r
+ FLASH_BLOCK_DESCRIPTION *FBlock;\r
+ FLASH_DEVICE_DESCRIPTION *FDev;\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ unsigned int Offset;\r
+ unsigned int SubregionOffset;\r
+ int CreateHobs;\r
+ //\r
+ // Find the definition we're supposed to use\r
+ //\r
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FDev == NULL) {\r
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Write a header\r
+ //\r
+ fprintf (OutFptr, CIncludeHeader);\r
+ //\r
+ // Write flash block base and size defines\r
+ //\r
+ fprintf (OutFptr, "#define FLASH_BASE 0x%08X\n", FDev->BaseAddress);\r
+ fprintf (OutFptr, "#define FLASH_SIZE 0x%08X\n\n", FDev->Size);\r
+ //\r
+ // Write flash regions base, size and offset defines\r
+ //\r
+ Offset = 0;\r
+ CreateHobs = 0;\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_BASE %*c0x%08X\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ Offset + FDev->BaseAddress\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_SIZE %*c0x%08X\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ FBlock->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_OFFSET %*c0x%08X\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ Offset\r
+ );\r
+ //\r
+ // Create defines for any subregions\r
+ //\r
+ SubregionOffset = 0;\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_SUBREGION_%s_BASE %*c0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ FDev->BaseAddress + Offset + SubregionOffset\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_SUBREGION_%s_SIZE %*c0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Subregion->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Offset + SubregionOffset\r
+ );\r
+ SubregionOffset += Subregion->Size;\r
+ if (Subregion->CreateHob != 0) {\r
+ CreateHobs = 1;\r
+ }\r
+ }\r
+\r
+ Offset += FBlock->Size;\r
+ }\r
+ //\r
+ // Now create a #define for the flash map data definition\r
+ //\r
+ fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");\r
+ //\r
+ // Emit entry for each region\r
+ //\r
+ Offset = 0;\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ fprintf (OutFptr, " /* %s region */\\\n", FBlock->Name);\r
+ fprintf (OutFptr, " {\\\n");\r
+ fprintf (OutFptr, " FLASH_REGION_%s_BASE,\\\n", FBlock->Name);\r
+ fprintf (OutFptr, " FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);\r
+ fprintf (OutFptr, " %s,\\\n", FBlock->Attributes);\r
+ fprintf (OutFptr, " %s,\\\n },\\\n", FBlock->AreaType);\r
+ }\r
+\r
+ fprintf (OutFptr, "\n\n");\r
+ //\r
+ // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\r
+ //\r
+ if (CreateHobs != 0) {\r
+ fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");\r
+ fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ //\r
+ // See if the block has subregions, and that the CreateHobs flag is set\r
+ // for any of them.\r
+ //\r
+ CreateHobs = 0;\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ if (Subregion->CreateHob != 0) {\r
+ CreateHobs = 1;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // If any of the subregions had the CreateHobs flag set, then create the entries in the\r
+ // output file\r
+ //\r
+ if (CreateHobs != 0) {\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ if (Subregion->CreateHob != 0) {\r
+ fprintf (OutFptr, " \\\n");\r
+ fprintf (OutFptr, " /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);\r
+ fprintf (OutFptr, " {\\\n");\r
+ fprintf (OutFptr, " EFI_HOB_TYPE_GUID_EXTENSION,\\\n");\r
+ fprintf (OutFptr, " sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");\r
+ fprintf (OutFptr, " 0,\\\n");\r
+ //\r
+ // The NameGuid may have been specified in the input flash definition file as a GUID, or\r
+ // as a quoted string. Do the right one.\r
+ //\r
+ if (Subregion->NameGuidString[0] != 0) {\r
+ fprintf (OutFptr, " %s, \\\n", Subregion->NameGuidString);\r
+ } else {\r
+ fprintf (\r
+ OutFptr,\r
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+ Subregion->NameGuid.Data1,\r
+ (unsigned int) Subregion->NameGuid.Data2,\r
+ (unsigned int) Subregion->NameGuid.Data3,\r
+ (unsigned int) Subregion->NameGuid.Data4[0],\r
+ (unsigned int) Subregion->NameGuid.Data4[1],\r
+ (unsigned int) Subregion->NameGuid.Data4[2],\r
+ (unsigned int) Subregion->NameGuid.Data4[3],\r
+ (unsigned int) Subregion->NameGuid.Data4[4],\r
+ (unsigned int) Subregion->NameGuid.Data4[5],\r
+ (unsigned int) Subregion->NameGuid.Data4[6],\r
+ (unsigned int) Subregion->NameGuid.Data4[7]\r
+ );\r
+ }\r
+\r
+ fprintf (OutFptr, " 0, 0, 0,\\\n");\r
+ fprintf (OutFptr, " %s,\\\n", Subregion->AreaType);\r
+ //\r
+ // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or\r
+ // as a quoted string. Do the right one.\r
+ //\r
+ if (Subregion->AreaTypeGuidString[0] != 0) {\r
+ fprintf (OutFptr, " %s, \\\n", Subregion->AreaTypeGuidString);\r
+ } else {\r
+ fprintf (\r
+ OutFptr,\r
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+ Subregion->AreaTypeGuid.Data1,\r
+ (unsigned int) Subregion->AreaTypeGuid.Data2,\r
+ (unsigned int) Subregion->AreaTypeGuid.Data3,\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[0],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[1],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[2],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[3],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[4],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[5],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[6],\r
+ (unsigned int) Subregion->AreaTypeGuid.Data4[7]\r
+ );\r
+ }\r
+\r
+ fprintf (OutFptr, " 1,\\\n");\r
+ fprintf (OutFptr, " {\\\n");\r
+ fprintf (OutFptr, " %s,\\\n", Subregion->Attributes);\r
+ fprintf (OutFptr, " 0,\\\n");\r
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);\r
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);\r
+ //\r
+ // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or\r
+ // as a quoted string. Do the right one.\r
+ //\r
+ if (Subregion->FileSystemGuidString[0] != 0) {\r
+ fprintf (OutFptr, " %s, \\\n", Subregion->FileSystemGuidString);\r
+ } else {\r
+ fprintf (\r
+ OutFptr,\r
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+ Subregion->FileSystemGuid.Data1,\r
+ (unsigned int) Subregion->FileSystemGuid.Data2,\r
+ (unsigned int) Subregion->FileSystemGuid.Data3,\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[0],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[1],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[2],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[3],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[4],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[5],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[6],\r
+ (unsigned int) Subregion->FileSystemGuid.Data4[7]\r
+ );\r
+ }\r
+\r
+ fprintf (OutFptr, " },\\\n");\r
+ fprintf (OutFptr, " },");\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ fprintf (OutFptr, "\n\n");\r
+ }\r
+\r
+ //\r
+ // Write the file's closing #endif\r
+ //\r
+ fprintf (OutFptr, CIncludeFooter);\r
+ fclose (OutFptr);\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateAsmIncludeFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Create an assembly header file with equate definitions per an already-parsed\r
+ flash definition file.\r
+\r
+Arguments:\r
+ FlashDeviceName - name of flash device (from the flash definition file)\r
+ to use\r
+ FileName - name of output file to create\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ FILE *OutFptr;\r
+ FLASH_BLOCK_DESCRIPTION *FBlock;\r
+ FLASH_DEVICE_DESCRIPTION *FDev;\r
+ unsigned int Offset;\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ unsigned int SubregionOffset;\r
+ //\r
+ // Find the definition we're supposed to use\r
+ //\r
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FDev == NULL) {\r
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Write a header\r
+ //\r
+ fprintf (OutFptr, "\n\n");\r
+ //\r
+ // Write flash block size and offset defines\r
+ //\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_BASE %*cequ 0%08Xh\n",\r
+ COLUMN2_START - 40,\r
+ ' ',\r
+ FDev->BaseAddress\r
+ );\r
+ fprintf (OutFptr, "FLASH_SIZE %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);\r
+ //\r
+ // Write flash region size and offset defines\r
+ //\r
+ fprintf (OutFptr, "\n");\r
+ Offset = 0;\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_BASE %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 20 - strlen (FBlock->Name),\r
+ ' ',\r
+ FDev->BaseAddress + Offset\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SIZE %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 20 - strlen (FBlock->Name),\r
+ ' ',\r
+ FBlock->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 20 - strlen (FBlock->Name),\r
+ ' ',\r
+ Offset\r
+ );\r
+ //\r
+ // Create defines for any subregions\r
+ //\r
+ SubregionOffset = 0;\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ FDev->BaseAddress + Offset + SubregionOffset\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Subregion->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*cequ 0%08Xh\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Offset + SubregionOffset\r
+ );\r
+ SubregionOffset += Subregion->Size;\r
+ }\r
+\r
+ Offset += FBlock->Size;\r
+ }\r
+\r
+ //\r
+ // Write closing \n\r
+ //\r
+ fprintf (OutFptr, "\n\n");\r
+ fclose (OutFptr);\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateSymbols (\r
+ char *FlashDeviceName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Using the given flash device name, add symbols to the global symbol table. This\r
+ allows other functions to use the symbol definitions for other purposes.\r
+\r
+Arguments:\r
+ FlashDeviceName - name of flash device (from the flash definition file)\r
+ to use\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ FLASH_BLOCK_DESCRIPTION *FBlock;\r
+ FLASH_DEVICE_DESCRIPTION *FDev;\r
+ unsigned int Offset;\r
+ char SymName[120];\r
+ char SymValue[120];\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ unsigned int SubregionOffset;\r
+ //\r
+ // Find the definition we're supposed to use\r
+ //\r
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FDev == NULL) {\r
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress);\r
+ SymbolAdd ("FLASH_BASE", SymValue, 0);\r
+ sprintf (SymValue, "0x%08X", FDev->Size);\r
+ SymbolAdd ("FLASH_SIZE", SymValue, 0);\r
+ //\r
+ // Add flash block size and offset defines\r
+ //\r
+ // Offset = 0;\r
+ // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {\r
+ // sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);\r
+ // sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);\r
+ // SymbolAdd (SymName, SymValue, 0);\r
+ // sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);\r
+ // sprintf (SymValue, "0x%08X", FBlock->Size);\r
+ // SymbolAdd (SymName, SymValue, 0);\r
+ // sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);\r
+ // sprintf (SymValue, "0x%08X", Offset);\r
+ // SymbolAdd (SymName, SymValue, 0);\r
+ // Offset += FBlock->Size;\r
+ // }\r
+ //\r
+ // Add flash region block base, size, and offset defines\r
+ //\r
+ Offset = 0;\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);\r
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);\r
+ sprintf (SymValue, "0x%08X", FBlock->Size);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);\r
+ sprintf (SymValue, "0x%08X", Offset);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ //\r
+ // Add subregion symbols\r
+ //\r
+ if (FBlock->Subregions != NULL) {\r
+ SubregionOffset = 0;\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);\r
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);\r
+ sprintf (SymValue, "0x%08X", Subregion->Size);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);\r
+ sprintf (SymValue, "0x%08X", Offset + SubregionOffset);\r
+ SymbolAdd (SymName, SymValue, 0);\r
+ SubregionOffset += Subregion->Size;\r
+ }\r
+ }\r
+\r
+ Offset += FBlock->Size;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateImage (\r
+ char *FlashDeviceName,\r
+ char *ImageName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Create a flash image using the given device and image names.\r
+\r
+Arguments:\r
+ FlashDeviceName - name of flash device (from the flash definition file)\r
+ to use\r
+ ImageName - name of image (from the flash definition file) to create\r
+ FileName - name of output file to create\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ FILE *OutFptr;\r
+ FLASH_BLOCK_DESCRIPTION *RegionDef;\r
+ FLASH_DEVICE_DESCRIPTION *FDev;\r
+ IMAGE_DEFINITION *ImageDef;\r
+ unsigned int Offset;\r
+ char *Buffer;\r
+ FILE *InFptr;\r
+ long FileSize;\r
+ IMAGE_DEFINITION_ENTRY *IDefEntry;\r
+ FLASH_SUBREGION_DESCRIPTION *SubregionDef;\r
+ //\r
+ // Find the flash definition we're supposed to use\r
+ //\r
+ InFptr = NULL;\r
+ Status = STATUS_ERROR;\r
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FDev == NULL) {\r
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Find the image name we're supposed to create\r
+ //\r
+ for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {\r
+ if (strcmp (ImageDef->Name, ImageName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (ImageDef == NULL) {\r
+ Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Open the output file\r
+ //\r
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Allocate a buffer to copy the input data to\r
+ //\r
+ Buffer = (char *) _malloc (FDev->Size);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);\r
+ goto Done;\r
+ }\r
+ //\r
+ // Set contents of buffer to the erased value\r
+ //\r
+ if (FDev->ErasePolarity) {\r
+ memset (Buffer, 0xFF, FDev->Size);\r
+ } else {\r
+ memset (Buffer, 0, FDev->Size);\r
+ }\r
+ //\r
+ // Set all region and subregion size-left fields to the size of the region/subregion\r
+ //\r
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {\r
+ RegionDef->SizeLeft = RegionDef->Size;\r
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {\r
+ SubregionDef->SizeLeft = SubregionDef->Size;\r
+ }\r
+ }\r
+ //\r
+ // Now go through the image list, read files into the buffer.\r
+ //\r
+ for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {\r
+ //\r
+ // If it's a file name, open the file, get the size, find the corresponding\r
+ // flash region it's in, and copy the data.\r
+ //\r
+ if (IDefEntry->IsRawData == 0) {\r
+ if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");\r
+ goto Done;\r
+ }\r
+\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ } else {\r
+ FileSize = IDefEntry->RawDataSize;\r
+ }\r
+ //\r
+ // Find the region/subregion it's in, see if we have space left\r
+ //\r
+ Offset = 0;\r
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {\r
+ if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {\r
+ break;\r
+ }\r
+\r
+ Offset += RegionDef->Size;\r
+ }\r
+\r
+ if (RegionDef == NULL) {\r
+ Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check for subregion\r
+ //\r
+ if (IDefEntry->SubregionName[0] != 0) {\r
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {\r
+ if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {\r
+ break;\r
+ }\r
+\r
+ Offset += SubregionDef->Size;\r
+ }\r
+\r
+ if (SubregionDef == NULL) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ IDefEntry->SubregionName,\r
+ "Subregion name not found in FlashDevice %s.%s Region definition",\r
+ FDev->Name,\r
+ RegionDef->Name\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Enough space in the subregion?\r
+ //\r
+ if (SubregionDef->SizeLeft < (unsigned int) FileSize) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ IDefEntry->Name,\r
+ "insufficient space in Subregion (at least 0x%X additional bytes required)",\r
+ FileSize - SubregionDef->SizeLeft\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data\r
+ //\r
+ if (IDefEntry->IsRawData == 0) {\r
+ if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");\r
+ goto Done;\r
+ }\r
+\r
+ fclose (InFptr);\r
+ InFptr = NULL;\r
+ } else {\r
+ memcpy (\r
+ Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),\r
+ IDefEntry->RawData,\r
+ IDefEntry->RawDataSize\r
+ );\r
+ }\r
+\r
+ SubregionDef->SizeLeft -= FileSize;\r
+ //\r
+ // Align based on the Region alignment requirements.\r
+ //\r
+ if (RegionDef->Alignment != 0) {\r
+ while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {\r
+ if (SubregionDef->SizeLeft == 0) {\r
+ break;\r
+ }\r
+\r
+ SubregionDef->SizeLeft--;\r
+ }\r
+ }\r
+ } else {\r
+ //\r
+ // Placing data in a region. Check for enough space in the region left.\r
+ //\r
+ if (RegionDef->SizeLeft < (unsigned int) FileSize) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ IDefEntry->Name,\r
+ "insufficient space in Region (at least 0x%X additional bytes required)",\r
+ FileSize - RegionDef->SizeLeft\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data\r
+ //\r
+ if (IDefEntry->IsRawData == 0) {\r
+ if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");\r
+ goto Done;\r
+ }\r
+\r
+ fclose (InFptr);\r
+ InFptr = NULL;\r
+ } else {\r
+ memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);\r
+ }\r
+\r
+ RegionDef->SizeLeft -= FileSize;\r
+ //\r
+ // Align\r
+ //\r
+ if (RegionDef->Alignment != 0) {\r
+ while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {\r
+ if (RegionDef->SizeLeft == 0) {\r
+ break;\r
+ }\r
+\r
+ RegionDef->SizeLeft--;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ if (Buffer != NULL) {\r
+ _free (Buffer);\r
+ }\r
+\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ if (Status == STATUS_ERROR) {\r
+ remove (FileName);\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+STATUS\r
+FDFCreateDscFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Create a DSC-style output file with equates for flash management.\r
+\r
+Arguments:\r
+ FlashDeviceName - name of flash device (from the flash definition file)\r
+ to use\r
+ FileName - name of output file to create\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ FILE *OutFptr;\r
+ FLASH_BLOCK_DESCRIPTION *FBlock;\r
+ FLASH_DEVICE_DESCRIPTION *FDev;\r
+ unsigned int Offset;\r
+ FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+ unsigned int SubregionOffset;\r
+ //\r
+ // Find the definition we're supposed to use\r
+ //\r
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (FDev == NULL) {\r
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Write the flash base address and size\r
+ //\r
+ fprintf (OutFptr, "\n");\r
+ fprintf (OutFptr, "FLASH_BASE = 0x%08X\n", FDev->BaseAddress);\r
+ fprintf (OutFptr, "FLASH_SIZE = 0x%08X\n\n", FDev->Size);\r
+ //\r
+ // Write flash block size and offset defines\r
+ //\r
+ Offset = 0;\r
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_BASE %*c= 0x%08X\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ Offset + FDev->BaseAddress\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SIZE %*c= 0x%08X\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ FBlock->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SIZE_BLOCKS %*c= 0x%x\n",\r
+ FBlock->Name,\r
+ COLUMN2_START - 40 - strlen (FBlock->Name),\r
+ ' ',\r
+ (FBlock->Size)/(FDev->PBlocks->Size)\r
+ ); \r
+ //\r
+ // Create defines for any subregions\r
+ //\r
+ SubregionOffset = 0;\r
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*c= 0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ FDev->BaseAddress + Offset + SubregionOffset\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*c= 0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Subregion->Size\r
+ );\r
+ fprintf (\r
+ OutFptr,\r
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c= 0x%08X\n",\r
+ FBlock->Name,\r
+ Subregion->Name,\r
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+ ' ',\r
+ Offset + SubregionOffset\r
+ );\r
+\r
+ SubregionOffset += Subregion->Size;\r
+ }\r
+\r
+ Offset += FBlock->Size;\r
+ }\r
+ //\r
+ // Close file\r
+ //\r
+ fprintf (OutFptr, "\n");\r
+ fclose (OutFptr);\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+ The following buffer management routines are used to encapsulate functionality\r
+ for managing a growable data buffer.\r
+\r
+Arguments:\r
+ BUFFER_DATA - structure that is used to maintain a data buffer\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+static\r
+BUFFER_DATA *\r
+CreateBufferData (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Create a growable data buffer with default buffer length.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ NULL - error occured during data buffer creation\r
+ Not NULL - the pointer to the newly created data buffer\r
+\r
+--*/\r
+{\r
+ BUFFER_DATA *BD;\r
+ BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));\r
+ if (BD == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ return NULL;\r
+ }\r
+\r
+ memset (BD, 0, sizeof (BUFFER_DATA));\r
+ BD->BufferStart = (char *) _malloc (BUFFER_SIZE);\r
+ if (BD->BufferStart == NULL) {\r
+ _free (BD);\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ return NULL;\r
+ }\r
+\r
+ BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;\r
+ BD->BufferPos = BD->BufferStart;\r
+ return BD;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+AddBufferDataByte (\r
+ BUFFER_DATA *Buffer,\r
+ char Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Add a single byte to a growable data buffer, growing the buffer if required.\r
+\r
+Arguments:\r
+\r
+ Buffer - pointer to the growable data buffer to add a single byte to\r
+ Data - value of the single byte data to be added\r
+\r
+Returns:\r
+\r
+ TRUE - the single byte data was successfully added\r
+ FALSE - error occurred, the single byte data was not added\r
+\r
+--*/\r
+{\r
+ int Size;\r
+ char *NewBuffer;\r
+ //\r
+ // See if we have to grow the buffer\r
+ //\r
+ if (Buffer->BufferPos >= Buffer->BufferEnd) {\r
+ Size = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;\r
+ NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);\r
+ if (NewBuffer == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+ return FALSE;\r
+ }\r
+\r
+ memcpy (NewBuffer, Buffer->BufferStart, Size);\r
+ _free (Buffer->BufferStart);\r
+ Buffer->BufferStart = NewBuffer;\r
+ Buffer->BufferPos = Buffer->BufferStart + Size;\r
+ Buffer->BufferEnd = Buffer->BufferStart + Size + BUFFER_SIZE;\r
+ }\r
+\r
+ *Buffer->BufferPos = Data;\r
+ Buffer->BufferPos++;\r
+ return TRUE;\r
+}\r
+\r
+static\r
+void\r
+FreeBufferData (\r
+ BUFFER_DATA *Buffer,\r
+ BOOLEAN FreeData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Free memory used to manage a growable data buffer.\r
+\r
+Arguments:\r
+\r
+ Buffer - pointer to the growable data buffer to be destructed\r
+ FreeData - TRUE, free memory containing the buffered data\r
+ FALSE, do not free the buffered data memory\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ if (Buffer != NULL) {\r
+ if (FreeData && (Buffer->BufferStart != NULL)) {\r
+ _free (Buffer->BufferStart);\r
+ }\r
+\r
+ _free (Buffer);\r
+ }\r
+}\r
+\r
+static\r
+char *\r
+GetBufferData (\r
+ BUFFER_DATA *Buffer,\r
+ int *BufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Return a pointer and size of the data in a growable data buffer.\r
+\r
+Arguments:\r
+\r
+ Buffer - pointer to the growable data buffer\r
+ BufferSize - size of the data in the growable data buffer\r
+\r
+Returns:\r
+\r
+ pointer of the data in the growable data buffer\r
+\r
+--*/\r
+{\r
+ *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;\r
+ return Buffer->BufferStart;\r
+}\r
+\r
+STATUS\r
+FDDiscover (\r
+ char *FDFileName,\r
+ unsigned int BaseAddr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Walk a binary image and see if you find anything that looks like a\r
+ firmware volume.\r
+\r
+Arguments:\r
+ FDFileName - name of input FD image to parse\r
+ BaseAddr - base address of input FD image\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_WARNING - warnings, but no errors, were encountered\r
+ STATUS_ERROR - errors were encountered\r
+\r
+NOTE:\r
+ This routine is used for debug purposes only.\r
+\r
+--*/\r
+{\r
+ FILE *InFptr;\r
+ long FileSize;\r
+ long Offset;\r
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;\r
+ EFI_GUID\r
+ FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };\r
+\r
+ if ((InFptr = fopen (FDFileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FDFileName, "failed to open file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ Offset = 0;\r
+ while (Offset < FileSize) {\r
+ fseek (InFptr, Offset, SEEK_SET);\r
+ //\r
+ // Read the contents of the file, see if it's an FV header\r
+ //\r
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {\r
+ //\r
+ // Check version and GUID\r
+ //\r
+ if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {\r
+ fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);\r
+ if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {\r
+ fprintf (stdout, "standard FFS file system\n");\r
+ } else {\r
+ fprintf (stdout, "non-standard FFS file system\n");\r
+ }\r
+ }\r
+ }\r
+\r
+ Offset += 16 * 1024;\r
+ }\r
+\r
+ fclose (InFptr);\r
+ return STATUS_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ FlashDefFile.h\r
+\r
+Abstract:\r
+\r
+ Header file for flash management utility in the Intel Platform \r
+ Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#ifndef _FLASH_DEF_FILE_H_\r
+#define _FLASH_DEF_FILE_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+void\r
+FDFConstructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+FDFDestructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFParseFile (\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateCIncludeFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateCFlashMapDataFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateAsmIncludeFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFParseFile (\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateImage (\r
+ char *FlashDeviceName,\r
+ char *ImageName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+ ImageName - GC_TODO: add argument description\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateDscFile (\r
+ char *FlashDeviceName,\r
+ char *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+ FileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateSymbols (\r
+ char *FlashDeviceName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FlashDeviceName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDDiscover (\r
+ char *FDFileName,\r
+ unsigned int BaseAddr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FDFileName - GC_TODO: add argument description\r
+ BaseAddr - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // #ifndef _FLASH_DEF_FILE_H_\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004-2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ FlashMap.c\r
+\r
+Abstract:\r
+\r
+ Utility for flash management in the Intel Platform Innovation Framework\r
+ for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"\r
+\r
+#ifndef INT8\r
+#define INT8 char\r
+#endif\r
+\r
+#include "EfiUtilityMsgs.h"\r
+#include "Microcode.h"\r
+#include "FlashDefFile.h"\r
+#include "Symbols.h"\r
+\r
+#define UTILITY_NAME "FlashMap"\r
+\r
+typedef struct _STRING_LIST {\r
+ struct _STRING_LIST *Next;\r
+ char *Str;\r
+} STRING_LIST;\r
+\r
+//\r
+// Keep our globals in one of these structures\r
+//\r
+static struct {\r
+ char *CIncludeFileName;\r
+ char *FlashDevice;\r
+ char *FlashDeviceImage;\r
+ char *MCIFileName;\r
+ char *MCOFileName;\r
+ char *ImageOutFileName;\r
+ char *DscFileName;\r
+ char *AsmIncludeFileName;\r
+ char *FlashDefinitionFileName;\r
+ char *StringReplaceInFileName;\r
+ char *StringReplaceOutFileName;\r
+ char *DiscoverFDImageName;\r
+ char MicrocodePadByteValue;\r
+ unsigned int MicrocodeAlignment;\r
+ STRING_LIST *MCIFileNames;\r
+ STRING_LIST *LastMCIFileNames;\r
+ unsigned int BaseAddress;\r
+} mGlobals;\r
+\r
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF\r
+#define DEFAULT_MC_ALIGNMENT 16\r
+\r
+static\r
+STATUS\r
+ProcessCommandLine (\r
+ int argc,\r
+ char *argv[]\r
+ );\r
+\r
+static\r
+STATUS\r
+MergeMicrocodeFiles (\r
+ char *OutFileName,\r
+ STRING_LIST *FileNames,\r
+ unsigned int Alignment,\r
+ char PadByteValue\r
+ );\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+int\r
+main (\r
+ int argc,\r
+ char *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Parse the command line arguments and then call worker functions to do the work\r
+ \r
+Arguments:\r
+ argc - number of elements in argv\r
+ argv - array of command-line arguments\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no problems encountered while processing\r
+ STATUS_WARNING - warnings, but no errors, were encountered while processing\r
+ STATUS_ERROR - errors were encountered while processing\r
+ \r
+--*/\r
+{\r
+ STATUS Status;\r
+\r
+ SetUtilityName (UTILITY_NAME);\r
+ Status = ProcessCommandLine (argc, argv);\r
+ if (Status != STATUS_SUCCESS) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Check for discovery of an FD (command line option)\r
+ //\r
+ if (mGlobals.DiscoverFDImageName != NULL) {\r
+ Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress);\r
+ goto Done;\r
+ }\r
+ //\r
+ // If they're doing microcode file parsing, then do that\r
+ //\r
+ if (mGlobals.MCIFileName != NULL) {\r
+ MicrocodeConstructor ();\r
+ MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName);\r
+ MicrocodeDestructor ();\r
+ }\r
+ //\r
+ // If they're doing microcode file merging, then do that now\r
+ //\r
+ if (mGlobals.MCIFileNames != NULL) {\r
+ MergeMicrocodeFiles (\r
+ mGlobals.MCOFileName,\r
+ mGlobals.MCIFileNames,\r
+ mGlobals.MicrocodeAlignment,\r
+ mGlobals.MicrocodePadByteValue\r
+ );\r
+ }\r
+ //\r
+ // If using a flash definition file, then process that and return\r
+ //\r
+ if (mGlobals.FlashDefinitionFileName != NULL) {\r
+ FDFConstructor ();\r
+ SymbolsConstructor ();\r
+ Status = FDFParseFile (mGlobals.FlashDefinitionFileName);\r
+ if (GetUtilityStatus () != STATUS_ERROR) {\r
+ //\r
+ // If they want us to do a string-replace on a file, then add the symbol definitions to\r
+ // the symbol table, and then do the string replace.\r
+ //\r
+ if (mGlobals.StringReplaceInFileName != NULL) {\r
+ Status = FDFCreateSymbols (mGlobals.FlashDevice);\r
+ Status = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName);\r
+ }\r
+ //\r
+ // If they want us to create a .h defines file or .c flashmap data file, then do so now\r
+ //\r
+ if (mGlobals.CIncludeFileName != NULL) {\r
+ Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName);\r
+ }\r
+ if (mGlobals.AsmIncludeFileName != NULL) {\r
+ Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName);\r
+ }\r
+ //\r
+ // If they want us to create an image, do that now\r
+ //\r
+ if (mGlobals.ImageOutFileName != NULL) {\r
+ Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName);\r
+ }\r
+ //\r
+ // If they want to create an output DSC file, do that now\r
+ //\r
+ if (mGlobals.DscFileName != NULL) {\r
+ Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName);\r
+ }\r
+ }\r
+ SymbolsDestructor ();\r
+ FDFDestructor ();\r
+ }\r
+Done:\r
+ //\r
+ // Free up memory\r
+ //\r
+ while (mGlobals.MCIFileNames != NULL) {\r
+ mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next;\r
+ _free (mGlobals.MCIFileNames);\r
+ mGlobals.MCIFileNames = mGlobals.LastMCIFileNames;\r
+ }\r
+ return GetUtilityStatus ();\r
+}\r
+\r
+static\r
+STATUS\r
+MergeMicrocodeFiles (\r
+ char *OutFileName,\r
+ STRING_LIST *FileNames,\r
+ unsigned int Alignment,\r
+ char PadByteValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Merge binary microcode files into a single file, taking into consideration\r
+ the alignment and pad value.\r
+\r
+Arguments:\r
+\r
+ OutFileName - name of the output file to create\r
+ FileNames - linked list of input microcode files to merge\r
+ Alignment - alignment for each microcode file in the output image\r
+ PadByteValue - value to use when padding to meet alignment requirements\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - merge completed successfully or with acceptable warnings\r
+ STATUS_ERROR - merge failed, output file not created\r
+\r
+--*/\r
+{\r
+ long FileSize;\r
+ long TotalFileSize;\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ char *Buffer;\r
+ STATUS Status;\r
+\r
+ //\r
+ // Open the output file\r
+ //\r
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Walk the list of files\r
+ //\r
+ Status = STATUS_ERROR;\r
+ Buffer = NULL;\r
+ InFptr = NULL;\r
+ TotalFileSize = 0;\r
+ while (FileNames != NULL) {\r
+ //\r
+ // Open the file, determine the size, then read it in and write\r
+ // it back out.\r
+ //\r
+ if ((InFptr = fopen (FileNames->Str, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FileNames->Str, "failed to open input file for reading");\r
+ goto Done;\r
+ }\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ if (FileSize != 0) {\r
+ Buffer = (char *) _malloc (FileSize);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ goto Done;\r
+ }\r
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileNames->Str, "failed to read file contents");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Align\r
+ //\r
+ if (Alignment != 0) {\r
+ while ((TotalFileSize % Alignment) != 0) {\r
+ if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file");\r
+ goto Done;\r
+ }\r
+ TotalFileSize++;\r
+ }\r
+ }\r
+ TotalFileSize += FileSize;\r
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to write to output file");\r
+ goto Done;\r
+ }\r
+ _free (Buffer);\r
+ Buffer = NULL;\r
+ } else {\r
+ Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered");\r
+ }\r
+ fclose (InFptr);\r
+ InFptr = NULL;\r
+ FileNames = FileNames->Next;\r
+ }\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ fclose (OutFptr);\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+ if (Buffer != NULL) {\r
+ _free (Buffer);\r
+ }\r
+ if (Status == STATUS_ERROR) {\r
+ remove (OutFileName);\r
+ }\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessCommandLine (\r
+ int argc,\r
+ char *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Process the command line arguments\r
+ \r
+Arguments:\r
+ argc - Standard C entry point arguments\r
+ argv[] - Standard C entry point arguments\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no problems encountered while processing\r
+ STATUS_WARNING - warnings, but no errors, were encountered while processing\r
+ STATUS_ERROR - errors were encountered while processing\r
+ \r
+--*/\r
+{\r
+ int ThingsToDo;\r
+ unsigned int Temp;\r
+ STRING_LIST *Str;\r
+ //\r
+ // Skip program name arg, process others\r
+ //\r
+ argc--;\r
+ argv++;\r
+ if (argc == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Clear out our globals, then start walking the arguments\r
+ //\r
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
+ mGlobals.MicrocodePadByteValue = DEFAULT_MC_PAD_BYTE_VALUE;\r
+ mGlobals.MicrocodeAlignment = DEFAULT_MC_ALIGNMENT;\r
+ ThingsToDo = 0;\r
+ while (argc > 0) {\r
+ if (strcmp (argv[0], "-?") == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ } else if (strcmp (argv[0], "-hfile") == 0) {\r
+ //\r
+ // -hfile FileName\r
+ //\r
+ // Used to specify an output C #include file to create that contains\r
+ // #define statements for all the flashmap region offsets and sizes.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an output file name");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.CIncludeFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-flashdevice") == 0) {\r
+ //\r
+ // -flashdevice FLASH_DEVICE_NAME\r
+ //\r
+ // Used to select which flash device definition to operate on.\r
+ // Check for additional argument\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires a flash device name to use");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.FlashDevice = argv[0];\r
+ } else if (strcmp (argv[0], "-mco") == 0) {\r
+ //\r
+ // -mco OutFileName\r
+ //\r
+ // Used to specify a microcode output binary file to create.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.MCOFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-asmincfile") == 0) {\r
+ //\r
+ // -asmincfile FileName\r
+ //\r
+ // Used to specify the name of the output assembly include file that contains\r
+ // equates for the flash region addresses and sizes.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.AsmIncludeFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-mci") == 0) {\r
+ //\r
+ // -mci FileName\r
+ //\r
+ // Used to specify an input microcode text file to parse.\r
+ // Check for additional argument\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.MCIFileName = argv[0];\r
+ } else if (strcmp (argv[0], "-flashdeviceimage") == 0) {\r
+ //\r
+ // -flashdeviceimage FlashDeviceImage\r
+ //\r
+ // Used to specify which flash device image definition from the input flash definition file\r
+ // to create.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.FlashDeviceImage = argv[0];\r
+ } else if (strcmp (argv[0], "-imageout") == 0) {\r
+ //\r
+ // -imageout FileName\r
+ //\r
+ // Used to specify the name of the output FD image file to create.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an output image filename to create");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.ImageOutFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-dsc") == 0) {\r
+ //\r
+ // -dsc FileName\r
+ //\r
+ // Used to specify the name of the output DSC file to create.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.DscFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-fdf") == 0) {\r
+ //\r
+ // -fdf FileName\r
+ //\r
+ // Used to specify the name of the input flash definition file.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.FlashDefinitionFileName = argv[0];\r
+ } else if (strcmp (argv[0], "-discover") == 0) {\r
+ //\r
+ // -discover FDFileName\r
+ //\r
+ // Debug functionality used to scan an existing FD image, trying to find\r
+ // firmware volumes at 64K boundaries.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an input FD image file name");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.DiscoverFDImageName = argv[0];\r
+ ThingsToDo++;\r
+ } else if (strcmp (argv[0], "-baseaddr") == 0) {\r
+ //\r
+ // -baseaddr Addr\r
+ //\r
+ // Used to specify a base address when doing a discover of an FD image.\r
+ // Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires a base address");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ if (tolower (argv[0][1]) == 'x') {\r
+ sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress);\r
+ } else {\r
+ sscanf (argv[0], "%d", &mGlobals.BaseAddress);\r
+ }\r
+ } else if (strcmp (argv[0], "-padvalue") == 0) {\r
+ //\r
+ // -padvalue Value\r
+ //\r
+ // Used to specify the value to pad with when aligning data while\r
+ // creating an FD image. Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires a byte value");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ if (tolower (argv[0][1]) == 'x') {\r
+ sscanf (argv[0] + 2, "%x", &Temp);\r
+ mGlobals.MicrocodePadByteValue = (char) Temp;\r
+ } else {\r
+ sscanf (argv[0], "%d", &Temp);\r
+ mGlobals.MicrocodePadByteValue = (char) Temp;\r
+ }\r
+ } else if (strcmp (argv[0], "-align") == 0) {\r
+ //\r
+ // -align Alignment\r
+ //\r
+ // Used to specify how each data file is aligned in the region\r
+ // when creating an FD image. Check for additional argument.\r
+ //\r
+ if (argc < 2) {\r
+ Error (NULL, 0, 0, argv[0], "option requires an alignment");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ if (tolower (argv[0][1]) == 'x') {\r
+ sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment);\r
+ } else {\r
+ sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment);\r
+ }\r
+ } else if (strcmp (argv[0], "-mcmerge") == 0) {\r
+ //\r
+ // -mcmerge FileName(s)\r
+ //\r
+ // Used to concatenate multiple microde binary files. Can specify\r
+ // multiple file names with the one -mcmerge flag. Check for additional argument.\r
+ //\r
+ if ((argc < 2) || (argv[1][0] == '-')) {\r
+ Error (NULL, 0, 0, argv[0], "option requires one or more input file names");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Take input files until another option or end of list\r
+ //\r
+ ThingsToDo++;\r
+ while ((argc > 1) && (argv[1][0] != '-')) {\r
+ Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST));\r
+ if (Str == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ memset (Str, 0, sizeof (STRING_LIST));\r
+ Str->Str = argv[1];\r
+ if (mGlobals.MCIFileNames == NULL) {\r
+ mGlobals.MCIFileNames = Str;\r
+ } else {\r
+ mGlobals.LastMCIFileNames->Next = Str;\r
+ }\r
+ mGlobals.LastMCIFileNames = Str;\r
+ argc--;\r
+ argv++;\r
+ }\r
+ } else if (strcmp (argv[0], "-strsub") == 0) {\r
+ //\r
+ // -strsub SrcFile DestFile\r
+ //\r
+ // Used to perform string substitutions on a file, writing the result to a new\r
+ // file. Check for two additional arguments.\r
+ //\r
+ if (argc < 3) {\r
+ Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ mGlobals.StringReplaceInFileName = argv[0];\r
+ argc--;\r
+ argv++;\r
+ mGlobals.StringReplaceOutFileName = argv[0];\r
+ ThingsToDo++;\r
+ } else {\r
+ Error (NULL, 0, 0, argv[0], "invalid option");\r
+ return STATUS_ERROR;\r
+ }\r
+ argc--;\r
+ argv++;\r
+ }\r
+ //\r
+ // If no outputs requested, then report an error\r
+ //\r
+ if (ThingsToDo == 0) {\r
+ Error (NULL, 0, 0, "nothing to do", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If they want an asm file, #include file, or C file to be created, then they have to specify a\r
+ // flash device name and flash definition file name.\r
+ //\r
+ if ((mGlobals.CIncludeFileName != NULL) &&\r
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {\r
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ if ((mGlobals.AsmIncludeFileName != NULL) &&\r
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {\r
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If they want a dsc file to be created, then they have to specify a\r
+ // flash device name and a flash definition file name\r
+ //\r
+ if (mGlobals.DscFileName != NULL) {\r
+ if (mGlobals.FlashDevice == NULL) {\r
+ Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ if (mGlobals.FlashDefinitionFileName == NULL) {\r
+ Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ }\r
+ //\r
+ // If they specified an output microcode file name, then they have to specify an input\r
+ // file name, and vice versa.\r
+ //\r
+ if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) {\r
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) {\r
+ Error (NULL, 0, 0, "must specify input microcode file name", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If doing merge, then have to specify output file name\r
+ //\r
+ if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) {\r
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If they want an output image to be created, then they have to specify\r
+ // the flash device and the flash device image to use.\r
+ //\r
+ if (mGlobals.ImageOutFileName != NULL) {\r
+ if (mGlobals.FlashDevice == NULL) {\r
+ Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ if (mGlobals.FlashDeviceImage == NULL) {\r
+ Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ if (mGlobals.FlashDefinitionFileName == NULL) {\r
+ Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ }\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Print utility command line help\r
+ \r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ NA\r
+\r
+--*/\r
+{\r
+ int i;\r
+ char *Msg[] = {\r
+ "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",\r
+ " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",\r
+ " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",\r
+ " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",\r
+ " -baseaddr BaseAddr -align Alignment -padvalue PadValue",\r
+ " -mcmerge MCIFile(s)",\r
+ " where",\r
+ " FlashDefFile - input Flash Definition File",\r
+ " FlashDevice - flash device to use (from flash definition file)",\r
+ " FlashDeviceImage - flash device image to use (from flash definition file)",\r
+ " MCIFile - input microcode file to parse",\r
+ " MCOFile - output binary microcode image to create from MCIFile",\r
+ " HFile - output #include file to create",\r
+ " FDImage - name of input FDImage file to scan",\r
+ " ImageOutFile - output image file to create",\r
+ " DscFile - output DSC file to create",\r
+ " AsmIncFile - output ASM include file to create",\r
+ " InStrFile - input file to replace symbol names, writing result to OutStrFile",\r
+ " BaseAddr - base address of FDImage (used with -discover)",\r
+ " Alignment - alignment to use when merging microcode binaries",\r
+ " PadValue - byte value to use as pad value when aligning microcode binaries",\r
+ " MCIFile(s) - one or more microcode binary files to merge/concatenate",\r
+ "",\r
+ NULL\r
+ };\r
+ for (i = 0; Msg[i] != NULL; i++) {\r
+ fprintf (stdout, "%s\n", Msg[i]);\r
+ }\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2004 Intel Corporation. All rights reserved\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+# \r
+# \r
+# Module Name:\r
+# \r
+# Makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the FlashMap utility\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+INCLUDE_PATHS = -I $(TIANO_TOOLS_SOURCE)\Common\r
+\r
+#\r
+# Target specific information\r
+#\r
+TARGET_NAME = FlashMap\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\FlashMap.exe\r
+LIBS = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib"\r
+\r
+#\r
+# Build targets\r
+#\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\FlashMap.obj \\r
+ $(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj \\r
+ $(TIANO_TOOLS_OUTPUT)\Symbols.obj \\r
+ $(TIANO_TOOLS_OUTPUT)\Microcode.obj \r
+ \r
+# $(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj \r
+ \r
+#C_FLAGS = $(C_FLAGS) /D TRACK_MALLOC_FREE\r
+C_FLAGS = $(C_FLAGS) /D _malloc=malloc /D _free=free\r
+ \r
+#\r
+# Compile each source file\r
+#\r
+$(TIANO_TOOLS_OUTPUT)\FlashMap.obj : $(TARGET_SRC_DIR)\FlashMap.c $(TARGET_SRC_DIR)\Symbols.h $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\FlashMap.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\Symbols.obj : $(TARGET_SRC_DIR)\Symbols.c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\Symbols.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\Microcode.obj : $(TARGET_SRC_DIR)\Microcode.c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\Microcode.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj : $(TARGET_SRC_DIR)\FlashDefFile.c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\FlashDefFile.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj : $(TARGET_SRC_DIR)\TrackMallocFree.c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\TrackMallocFree.c /Fo$@\r
+\r
+#\r
+# Link the object files together to create the final executable\r
+#\r
+$(TARGET_EXE) : $(OBJECTS) $(LIBS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ Microcode.c\r
+\r
+Abstract:\r
+\r
+ Utility for working with microcode patch files in the Intel \r
+ Platform Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h> // for memset()\r
+#include <ctype.h>\r
+#include <stdlib.h> // for malloc()\r
+#define INT8 char\r
+#define UINT32 unsigned int\r
+\r
+#include "EfiUtilityMsgs.h"\r
+#include "Microcode.h"\r
+\r
+#define MAX_LINE_LEN 256\r
+\r
+//\r
+// Structure definition for a microcode header\r
+//\r
+typedef struct {\r
+ unsigned int HeaderVersion;\r
+ unsigned int PatchId;\r
+ unsigned int Date;\r
+ unsigned int CpuId;\r
+ unsigned int Checksum;\r
+ unsigned int LoaderVersion;\r
+ unsigned int PlatformId;\r
+ unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
+ unsigned int TotalSize; // number of bytes\r
+ unsigned int Reserved[3];\r
+} MICROCODE_IMAGE_HEADER;\r
+\r
+static\r
+STATUS\r
+MicrocodeReadData (\r
+ FILE *InFptr,\r
+ unsigned int *Data\r
+ );\r
+\r
+void\r
+MicrocodeConstructor (\r
+ void\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Constructor of module Microcode\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+}\r
+\r
+void\r
+MicrocodeDestructor (\r
+ void\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Destructor of module Microcode\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+}\r
+\r
+static\r
+STATUS\r
+MicrocodeReadData (\r
+ FILE *InFptr,\r
+ unsigned int *Data\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
+\r
+Arguments:\r
+ InFptr - file pointer to input text file\r
+ Data - pointer to where to return the data parsed\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings, Data contains valid information\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ char Line[MAX_LINE_LEN];\r
+ char *cptr;\r
+\r
+ Line[MAX_LINE_LEN - 1] = 0;\r
+ *Data = 0;\r
+ if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If it was a binary file, then it may have overwritten our null terminator\r
+ //\r
+ if (Line[MAX_LINE_LEN - 1] != 0) {\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Look for\r
+ // dd 000000001h ; comment\r
+ // dd XXXXXXXX\r
+ // DD XXXXXXXXX\r
+ // DD XXXXXXXXX\r
+ //\r
+ for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
+ }\r
+ if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
+ //\r
+ // Skip blanks and look for a hex digit\r
+ //\r
+ cptr += 3;\r
+ for (; *cptr && isspace(*cptr); cptr++) {\r
+ }\r
+ if (isxdigit (*cptr)) {\r
+ if (sscanf (cptr, "%X", Data) != 1) {\r
+ return STATUS_ERROR;\r
+ }\r
+ }\r
+ return STATUS_SUCCESS;\r
+ }\r
+ return STATUS_ERROR;\r
+}\r
+\r
+STATUS\r
+MicrocodeParseFile (\r
+ char *InFileName,\r
+ char *OutFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Parse a microcode text file, and write the binary results to an output file.\r
+\r
+Arguments:\r
+ InFileName - input text file to parse\r
+ OutFileName - output file to write raw binary data from parsed input file\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+{\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ STATUS Status;\r
+ MICROCODE_IMAGE_HEADER *Header;\r
+ unsigned int Size;\r
+ unsigned int Size2;\r
+ unsigned int Data;\r
+ unsigned int Checksum;\r
+ char *Buffer;\r
+ char *Ptr;\r
+ unsigned int TotalSize;\r
+\r
+ Status = STATUS_ERROR;\r
+ InFptr = NULL;\r
+ OutFptr = NULL;\r
+ Buffer = NULL;\r
+ //\r
+ // Open the input text file\r
+ //\r
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
+ Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Make two passes on the input file. The first pass is to determine how\r
+ // much data is in the file so we can allocate a working buffer. Then\r
+ // we'll allocate a buffer and re-read the file into the buffer for processing.\r
+ //\r
+ Size = 0;\r
+ do {\r
+ Status = MicrocodeReadData (InFptr, &Data);\r
+ if (Status == STATUS_SUCCESS) {\r
+ Size += sizeof (Data);\r
+ }\r
+ } while (Status == STATUS_SUCCESS);\r
+ //\r
+ // Error if no data.\r
+ //\r
+ if (Size == 0) {\r
+ Error (NULL, 0, 0, InFileName, "no parse-able data found in file");\r
+ goto Done;\r
+ }\r
+ if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {\r
+ Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Allocate a buffer for the data\r
+ //\r
+ Buffer = (char *) _malloc (Size);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ goto Done;\r
+ }\r
+ //\r
+ // Re-read the file, storing the data into our buffer\r
+ //\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ Ptr = Buffer;\r
+ do {\r
+ Status = MicrocodeReadData (InFptr, &Data);\r
+ if (Status == STATUS_SUCCESS) {\r
+ *(unsigned int *) Ptr = Data;\r
+ Ptr += sizeof (Data);\r
+ }\r
+ } while (Status == STATUS_SUCCESS);\r
+ //\r
+ // Can't do much checking on the header because, per the spec, the\r
+ // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
+ // and the TotalSize field is invalid (actually missing). Thus we can't\r
+ // even verify the Reserved fields are 0.\r
+ //\r
+ Header = (MICROCODE_IMAGE_HEADER *) Buffer;\r
+ if (Header->DataSize == 0) {\r
+ TotalSize = 2048;\r
+ } else {\r
+ TotalSize = Header->TotalSize;\r
+ }\r
+ if (TotalSize != Size) {\r
+ Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);\r
+ goto Done;\r
+ }\r
+ //\r
+ // Checksum the contents\r
+ //\r
+ Ptr = Buffer;\r
+ Checksum = 0;\r
+ Size2 = 0;\r
+ while (Size2 < Size) {\r
+ Checksum += *(unsigned int *) Ptr;\r
+ Ptr += 4;\r
+ Size2 += 4;\r
+ }\r
+ if (Checksum != 0) {\r
+ Error (NULL, 0, 0, InFileName, "checksum failed on file contents");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Open the output file and write the buffer contents\r
+ //\r
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");\r
+ goto Done;\r
+ }\r
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");\r
+ goto Done;\r
+ }\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ if (Status == STATUS_ERROR) {\r
+ remove (OutFileName);\r
+ }\r
+ }\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ Microcode.h\r
+\r
+Abstract:\r
+\r
+ Header file for flash management utility in the Intel Platform \r
+ Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#ifndef _MICROCODE_H_\r
+#define _MICROCODE_H_\r
+\r
+void\r
+MicrocodeConstructor (\r
+ void\r
+ );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Constructor of module Microcode\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+\r
+void\r
+MicrocodeDestructor (\r
+ void\r
+ );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Destructor of module Microcode\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+\r
+STATUS\r
+MicrocodeParseFile (\r
+ char *InFileName,\r
+ char *OutFileName\r
+ );\r
+/*++\r
+\r
+Routine Description:\r
+ Parse a microcode text file, and write the binary results to an output file.\r
+\r
+Arguments:\r
+ InFileName - input text file to parse\r
+ OutFileName - output file to write raw binary data from parsed input file\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no errors or warnings\r
+ STATUS_ERROR - errors were encountered\r
+\r
+--*/\r
+\r
+\r
+#endif // #ifndef _MICROCODE_H_\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ Symbol.c\r
+\r
+Abstract:\r
+\r
+ Class-like implementation for a symbol table.\r
+\r
+--*/\r
+\r
+// GC_TODO: fix comment to set correct module name: Symbols.c\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+//\r
+// for isspace()\r
+//\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "Symbols.h"\r
+\r
+#define MAX_LINE_LEN 512\r
+\r
+//\r
+// Linked list to keep track of all symbols\r
+//\r
+typedef struct _SYMBOL {\r
+ struct _SYMBOL *Next;\r
+ int Type;\r
+ char *Name;\r
+ char *Value;\r
+} SYMBOL;\r
+\r
+static\r
+SYMBOL *\r
+FreeSymbols (\r
+ SYMBOL *Syms\r
+ );\r
+\r
+static\r
+int\r
+ExpandMacros (\r
+ char *SourceLine,\r
+ char *DestLine,\r
+ int LineLen\r
+ );\r
+\r
+static SYMBOL *mSymbolTable = NULL;\r
+\r
+void\r
+SymbolsConstructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ SymbolsDestructor ();\r
+}\r
+\r
+void\r
+SymbolsDestructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ mSymbolTable = FreeSymbols (mSymbolTable);\r
+}\r
+\r
+char *\r
+GetSymbolValue (\r
+ char *SymbolName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Look up a symbol in our symbol table.\r
+\r
+Arguments:\r
+\r
+ SymbolName\r
+\r
+Returns:\r
+\r
+ Pointer to the value of the symbol if found\r
+ NULL if the symbol is not found\r
+\r
+--*/\r
+// GC_TODO: SymbolName - add argument and description to function comment\r
+{\r
+ SYMBOL *Symbol;\r
+ //\r
+ // Walk the symbol table\r
+ //\r
+ Symbol = mSymbolTable;\r
+ while (Symbol) {\r
+ if (stricmp (SymbolName, Symbol->Name) == 0) {\r
+ return Symbol->Value;\r
+ }\r
+\r
+ Symbol = Symbol->Next;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+int\r
+SymbolAdd (\r
+ char *Name,\r
+ char *Value,\r
+ int Mode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Add a symbol name/value to the symbol table\r
+\r
+Arguments:\r
+\r
+ Name - name of symbol to add\r
+ Value - value of symbol to add\r
+ Mode - currrently unused\r
+\r
+Returns:\r
+\r
+ Length of symbol added.\r
+\r
+Notes:\r
+ If Value == NULL, then this routine will assume that the Name field\r
+ looks something like "MySymName = MySymValue", and will try to parse\r
+ it that way and add the symbol name/pair from the string.\r
+\r
+--*/\r
+{\r
+ SYMBOL *Symbol;\r
+\r
+ SYMBOL *NewSymbol;\r
+ int Len;\r
+ char *Start;\r
+ char *Cptr;\r
+ char CSave;\r
+ char *SaveCptr;\r
+\r
+ Len = 0;\r
+ SaveCptr = NULL;\r
+ CSave = 0;\r
+ //\r
+ // If value pointer is null, then they passed us a line something like:\r
+ // varname = value, or simply var =\r
+ //\r
+ if (Value == NULL) {\r
+ Start = Name;\r
+ while (*Name && isspace (*Name)) {\r
+ Name++;\r
+ }\r
+\r
+ if (Name == NULL) {\r
+ return -1;\r
+ }\r
+ //\r
+ // Find the end of the name. Either space or a '='.\r
+ //\r
+ for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
+ ;\r
+ if (Value == NULL) {\r
+ return -1;\r
+ }\r
+ //\r
+ // Look for the '='\r
+ //\r
+ Cptr = Value;\r
+ while (*Value && (*Value != '=')) {\r
+ Value++;\r
+ }\r
+\r
+ if (Value == NULL) {\r
+ return -1;\r
+ }\r
+ //\r
+ // Now truncate the name\r
+ //\r
+ *Cptr = 0;\r
+ //\r
+ // Skip over the = and then any spaces\r
+ //\r
+ Value++;\r
+ while (*Value && isspace (*Value)) {\r
+ Value++;\r
+\r
+ }\r
+ //\r
+ // Find end of string, checking for quoted string\r
+ //\r
+ if (*Value == '\"') {\r
+ Value++;\r
+ for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
+ ;\r
+ } else {\r
+ for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
+ ;\r
+ }\r
+ //\r
+ // Null terminate the value string\r
+ //\r
+ CSave = *Cptr;\r
+ SaveCptr = Cptr;\r
+ *Cptr = 0;\r
+ Len = (int) (Cptr - Start);\r
+ }\r
+ //\r
+ // We now have a symbol name and a value. Look for an existing variable\r
+ // and overwrite it.\r
+ //\r
+ Symbol = mSymbolTable;\r
+ while (Symbol) {\r
+ //\r
+ // Check for symbol name match\r
+ //\r
+ if (stricmp (Name, Symbol->Name) == 0) {\r
+ _free (Symbol->Value);\r
+ Symbol->Value = (char *) _malloc (strlen (Value) + 1);\r
+ if (Symbol->Value == NULL) {\r
+ Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
+ return -1;\r
+ }\r
+\r
+ strcpy (Symbol->Value, Value);\r
+ //\r
+ // If value == "NULL", then make it a 0-length string\r
+ //\r
+ if (stricmp (Symbol->Value, "NULL") == 0) {\r
+ Symbol->Value[0] = 0;\r
+ }\r
+\r
+ return Len;\r
+ }\r
+\r
+ Symbol = Symbol->Next;\r
+ }\r
+ //\r
+ // Does not exist, create a new one\r
+ //\r
+ NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));\r
+ if (NewSymbol == NULL) {\r
+ Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+ return -1;\r
+ }\r
+\r
+ memset ((char *) NewSymbol, 0, sizeof (SYMBOL));\r
+ NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);\r
+ if (NewSymbol->Name == NULL) {\r
+ Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+ _free (NewSymbol);\r
+ return -1;\r
+ }\r
+\r
+ NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);\r
+ if (NewSymbol->Value == NULL) {\r
+ Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+ _free (NewSymbol->Name);\r
+ _free (NewSymbol);\r
+ return -1;\r
+ }\r
+\r
+ strcpy (NewSymbol->Name, Name);\r
+ strcpy (NewSymbol->Value, Value);\r
+ //\r
+ // Remove trailing spaces\r
+ //\r
+ Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;\r
+ while (Cptr > NewSymbol->Value) {\r
+ if (isspace (*Cptr)) {\r
+ *Cptr = 0;\r
+ Cptr--;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Add it to the head of the list.\r
+ //\r
+ NewSymbol->Next = mSymbolTable;\r
+ mSymbolTable = NewSymbol;\r
+ //\r
+ // If value == "NULL", then make it a 0-length string\r
+ //\r
+ if (stricmp (NewSymbol->Value, "NULL") == 0) {\r
+ NewSymbol->Value[0] = 0;\r
+ }\r
+ //\r
+ // Restore the terminator we inserted if they passed in var=value\r
+ //\r
+ if (SaveCptr != NULL) {\r
+ *SaveCptr = CSave;\r
+ }\r
+ _free (NewSymbol->Value);\r
+ _free (NewSymbol->Name);\r
+ _free (NewSymbol);\r
+ return Len;\r
+}\r
+\r
+static\r
+STATUS\r
+RemoveSymbol (\r
+ char *Name,\r
+ char SymbolType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Remove a symbol name/value from the symbol table\r
+\r
+Arguments:\r
+\r
+ Name - name of symbol to remove\r
+ SymbolType - type of symbol to remove\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - matching symbol found and removed\r
+ STATUS_ERROR - matching symbol not found in symbol table\r
+\r
+--*/\r
+{\r
+ SYMBOL *Symbol;\r
+\r
+ SYMBOL *PrevSymbol;\r
+\r
+ PrevSymbol = NULL;\r
+ Symbol = mSymbolTable;\r
+ //\r
+ // Walk the linked list of symbols in the symbol table looking\r
+ // for a match of both symbol name and type.\r
+ //\r
+ while (Symbol) {\r
+ if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {\r
+ //\r
+ // If the symbol has a value associated with it, free the memory\r
+ // allocated for the value.\r
+ // Then free the memory allocated for the symbols string name.\r
+ //\r
+ if (Symbol->Value) {\r
+ _free (Symbol->Value);\r
+ }\r
+\r
+ _free (Symbol->Name);\r
+ //\r
+ // Link the previous symbol to the next symbol to effectively\r
+ // remove this symbol from the linked list.\r
+ //\r
+ if (PrevSymbol) {\r
+ PrevSymbol->Next = Symbol->Next;\r
+ } else {\r
+ mSymbolTable = Symbol->Next;\r
+ }\r
+\r
+ _free (Symbol);\r
+ return STATUS_SUCCESS;\r
+ }\r
+\r
+ PrevSymbol = Symbol;\r
+ Symbol = Symbol->Next;\r
+ }\r
+\r
+ return STATUS_WARNING;\r
+}\r
+\r
+static\r
+SYMBOL *\r
+FreeSymbols (\r
+ SYMBOL *Syms\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Syms - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ SYMBOL *Next;\r
+ while (Syms) {\r
+ if (Syms->Name != NULL) {\r
+ _free (Syms->Name);\r
+ }\r
+\r
+ if (Syms->Value != NULL) {\r
+ _free (Syms->Value);\r
+ }\r
+\r
+ Next = Syms->Next;\r
+ _free (Syms);\r
+ Syms = Next;\r
+ }\r
+\r
+ return Syms;\r
+}\r
+\r
+static\r
+int\r
+ExpandMacros (\r
+ char *SourceLine,\r
+ char *DestLine,\r
+ int LineLen\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given a line of text, replace all variables of format $(NAME) with values\r
+ from our symbol table.\r
+\r
+Arguments:\r
+\r
+ SourceLine - input line of text to do symbol replacements on\r
+ DestLine - on output, SourceLine with symbols replaced\r
+ LineLen - length of DestLine, so we don't exceed its allocated length\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - no problems encountered\r
+ STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine\r
+ STATUS_ERROR - memory allocation failure\r
+\r
+--*/\r
+{\r
+ static int NestDepth = 0;\r
+ char *FromPtr;\r
+ char *ToPtr;\r
+ char *SaveStart;\r
+ char *Cptr;\r
+ char *value;\r
+ int Expanded;\r
+ int ExpandedCount;\r
+ INT8 *LocalDestLine;\r
+ STATUS Status;\r
+ int LocalLineLen;\r
+\r
+ NestDepth++;\r
+ Status = STATUS_SUCCESS;\r
+ LocalDestLine = (char *) _malloc (LineLen);\r
+ if (LocalDestLine == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ FromPtr = SourceLine;\r
+ ToPtr = LocalDestLine;\r
+ //\r
+ // Walk the entire line, replacing $(MACRO_NAME).\r
+ //\r
+ LocalLineLen = LineLen;\r
+ ExpandedCount = 0;\r
+ while (*FromPtr && (LocalLineLen > 0)) {\r
+ if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {\r
+ //\r
+ // Save the start in case it's undefined, in which case we copy it as-is.\r
+ //\r
+ SaveStart = FromPtr;\r
+ Expanded = 0;\r
+ //\r
+ // Macro expansion time. Find the end (no spaces allowed)\r
+ //\r
+ FromPtr += 2;\r
+ for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)\r
+ ;\r
+ if (*Cptr) {\r
+ //\r
+ // Truncate the string at the closing parenthesis for ease-of-use.\r
+ // Then copy the string directly to the destination line in case we don't find\r
+ // a definition for it.\r
+ //\r
+ *Cptr = 0;\r
+ strcpy (ToPtr, SaveStart);\r
+ if ((value = GetSymbolValue (FromPtr)) != NULL) {\r
+ strcpy (ToPtr, value);\r
+ LocalLineLen -= strlen (value);\r
+ ToPtr += strlen (value);\r
+ Expanded = 1;\r
+ ExpandedCount++;\r
+ }\r
+\r
+ if (!Expanded) {\r
+ //\r
+ // Restore closing parenthesis, and advance to next character\r
+ //\r
+ *Cptr = ')';\r
+ FromPtr = SaveStart + 1;\r
+ ToPtr++;\r
+ } else {\r
+ FromPtr = Cptr + 1;\r
+ }\r
+ } else {\r
+ Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");\r
+ strcpy (ToPtr, FromPtr);\r
+ Status = STATUS_WARNING;\r
+ goto Done;\r
+ }\r
+ } else {\r
+ *ToPtr = *FromPtr;\r
+ FromPtr++;\r
+ ToPtr++;\r
+ LocalLineLen--;\r
+ }\r
+ }\r
+\r
+ if (*FromPtr == 0) {\r
+ *ToPtr = 0;\r
+ }\r
+\r
+ //\r
+ // If we expanded at least one string successfully, then make a recursive call to try again.\r
+ //\r
+ if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {\r
+ Status = ExpandMacros (LocalDestLine, DestLine, LineLen);\r
+ _free (LocalDestLine);\r
+ NestDepth = 0;\r
+ return Status;\r
+ }\r
+\r
+Done:\r
+ if (Status != STATUS_ERROR) {\r
+ strcpy (DestLine, LocalDestLine);\r
+ }\r
+\r
+ NestDepth = 0;\r
+ _free (LocalDestLine);\r
+ return Status;\r
+}\r
+\r
+STATUS\r
+SymbolsFileStringsReplace (\r
+ char *InFileName,\r
+ char *OutFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given input and output file names, read in the input file, replace variable\r
+ references of format $(NAME) with appropriate values from our symbol table,\r
+ and write the result out to the output file.\r
+\r
+Arguments:\r
+\r
+ InFileName - name of input text file to replace variable references\r
+ OutFileName - name of output text file to write results to\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - no problems encountered\r
+ STATUS_ERROR - failed to open input or output file\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ char Line[MAX_LINE_LEN];\r
+ char OutLine[MAX_LINE_LEN];\r
+\r
+ Status = STATUS_ERROR;\r
+ //\r
+ // Open input and output files\r
+ //\r
+ InFptr = NULL;\r
+ OutFptr = NULL;\r
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+ goto Done;\r
+ }\r
+\r
+ if ((OutFptr = fopen (OutFileName, "w")) == NULL) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Read lines from input file until done\r
+ //\r
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
+ ExpandMacros (Line, OutLine, sizeof (OutLine));\r
+ fprintf (OutFptr, OutLine);\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ }\r
+\r
+ return Status;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ Symbols.h\r
+\r
+Abstract:\r
+\r
+ Defines and prototypes for a class-like symbol table service.\r
+\r
+--*/\r
+\r
+#ifndef _SYMBOLS_H_\r
+#define _SYMBOLS_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+int\r
+SymbolAdd (\r
+ char *Name,\r
+ char *Value,\r
+ int Mode\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Name - GC_TODO: add argument description\r
+ Value - GC_TODO: add argument description\r
+ Mode - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+SymbolsFileStringsReplace (\r
+ char *InFileName,\r
+ char *OutFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ InFileName - GC_TODO: add argument description\r
+ OutFileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+SymbolsConstructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+SymbolsDestructor (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // #ifndef _SYMBOLS_H_\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ GenAcpiTable.c\r
+ \r
+Abstract:\r
+\r
+ A utility that extracts the .DATA section from a PE/COFF image.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiUtilityMsgs.h"\r
+\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_NAME "GenAcpiTable"\r
+#define UTILITY_VERSION "v0.11"\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH 256\r
+#define DEFAULT_OUTPUT_EXTENSION ".acpi"\r
+\r
+//\r
+// Use this to track our command-line options and globals\r
+//\r
+struct {\r
+ INT8 OutFileName[MAX_PATH];\r
+ INT8 InFileName[MAX_PATH];\r
+} mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+ UINT16 Value;\r
+ INT8 *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP mMachineTypes[] = {\r
+ EFI_IMAGE_MACHINE_IA32,\r
+ "IA32",\r
+ EFI_IMAGE_MACHINE_IA64,\r
+ "IA64",\r
+ EFI_IMAGE_MACHINE_EBC,\r
+ "EBC",\r
+ 0,\r
+ NULL\r
+};\r
+\r
+static STRING_LOOKUP mSubsystemTypes[] = {\r
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+ "EFI application",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+ "EFI boot service driver",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+ "EFI runtime driver",\r
+ 0,\r
+ NULL\r
+};\r
+//\r
+// Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[]\r
+ );\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+ INT8 *FileName,\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ );\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+ INT8 *InFileName,\r
+ INT8 *OutFileName\r
+ );\r
+\r
+static\r
+void\r
+DumpImage (\r
+ INT8 *FileName\r
+ );\r
+\r
+main (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+\r
+ Argv - standard C main() argument list\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ UINT32 Status;\r
+\r
+ SetUtilityName (UTILITY_NAME);\r
+ //\r
+ // Parse the command line arguments\r
+ //\r
+ if (ParseCommandLine (Argc, Argv)) {\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Make sure we don't have the same filename for input and output files\r
+ //\r
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Process the file\r
+ //\r
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
+Finish:\r
+ Status = GetUtilityStatus ();\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+ INT8 *InFileName,\r
+ INT8 *OutFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Process a PE32 EFI file.\r
+\r
+Arguments:\r
+\r
+ InFileName - Name of the PE32 EFI file to process.\r
+ OutFileName - Name of the output file for the processed data.\r
+\r
+Returns:\r
+\r
+ 0 - successful\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ UINTN Index;\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ UINT16 MachineType;\r
+ UINT16 SubSystem;\r
+ UINT32 PESigOffset;\r
+ EFI_IMAGE_FILE_HEADER FileHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
+ EFI_IMAGE_SECTION_HEADER SectionHeader;\r
+ UINT8 *Buffer;\r
+ long SaveFilePosition;\r
+\r
+ InFptr = NULL;\r
+ OutFptr = NULL;\r
+ Buffer = NULL;\r
+ Status = STATUS_ERROR;\r
+ //\r
+ // Try to open the input file\r
+ //\r
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Double-check the file to make sure it's what we expect it to be\r
+ //\r
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
+ // offset (from the start of the file) to the PE signature, which always\r
+ // follows the MSDOS stub. The PE signature is immediately followed by the\r
+ // COFF file header.\r
+ //\r
+ //\r
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
+ goto Finish;\r
+ }\r
+\r
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // We should now be at the COFF file header. Read it in and verify it's\r
+ // of an image type we support.\r
+ //\r
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
+ goto Finish;\r
+ }\r
+\r
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {\r
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
+ //\r
+ SaveFilePosition = ftell (InFptr);\r
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+ goto Finish;\r
+ }\r
+ }\r
+ //\r
+ // Search for the ".data" section\r
+ //\r
+ for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {\r
+ if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (strcmp (SectionHeader.Name, ".data") == 0) {\r
+ if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
+ goto Finish;\r
+ }\r
+\r
+ Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);\r
+ if (Buffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Finish;\r
+ }\r
+ if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to .data section");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Now open our output file\r
+ //\r
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to write .data section");\r
+ goto Finish;\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+ goto Finish;\r
+ }\r
+ }\r
+\r
+ Status = STATUS_ERROR;\r
+\r
+Finish:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+ //\r
+ // Close the output file. If there was an error, delete the output file so\r
+ // that a subsequent build will rebuild it.\r
+ //\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ if (GetUtilityStatus () == STATUS_ERROR) {\r
+ remove (OutFileName);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free up our buffer\r
+ //\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+ INT8 *FileName,\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileName - GC_TODO: add argument description\r
+ Fptr - GC_TODO: add argument description\r
+ MachineType - GC_TODO: add argument description\r
+ SubSystem - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ /*++\r
+\r
+Routine Description:\r
+ \r
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+ PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+ Fptr File pointer to the already-opened PE32 file\r
+ MachineType Location to stuff the machine type of the PE32 file. This is needed\r
+ because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_FILE_HEADER FileHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+ UINT32 PESig;\r
+ STATUS Status;\r
+\r
+ Status = STATUS_ERROR;\r
+ //\r
+ // Position to the start of the file\r
+ //\r
+ fseek (Fptr, 0, SEEK_SET);\r
+ //\r
+ // Read the DOS header\r
+ //\r
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Check the magic number (0x5A4D)\r
+ //\r
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Position into the file and check the PE signature\r
+ //\r
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Check the PE signature in the header "PE\0\0"\r
+ //\r
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read the file header\r
+ //\r
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read the optional header so we can get the subsystem\r
+ //\r
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ *SubSystem = OptionalHdr.Subsystem;\r
+ //\r
+ // Good to go\r
+ //\r
+ Status = STATUS_SUCCESS;\r
+Finish:\r
+ fseek (Fptr, 0, SEEK_SET);\r
+ return Status;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+ parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+ Argv - standard C main() argument list\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS success\r
+ non-zero otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ //\r
+ // Clear out the options\r
+ //\r
+ memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+ //\r
+ // Skip over the program name\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc != 2) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ strcpy (mOptions.InFileName, Argv[0]);\r
+ //\r
+ // Next argument\r
+ //\r
+ Argv++;\r
+ Argc--;\r
+\r
+ strcpy (mOptions.OutFileName, Argv[0]);\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ int Index;\r
+ static const char *Msg[] = {\r
+ UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",\r
+ " Generate an ACPI Table image from an EFI PE32 image",\r
+ " Usage: "UTILITY_NAME " InFileName OutFileName",\r
+ " where:",\r
+ " InFileName - name of the input PE32 file",\r
+ " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
+ "",\r
+ NULL\r
+ };\r
+ for (Index = 0; Msg[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Msg[Index]);\r
+ }\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2002 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name:\r
+# \r
+# makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the GenAcpiTable utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = GenAcpiTable\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj \r
+\r
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+INC_DEPS = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h\r
+ \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2003 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ CreateGuid.c \r
+\r
+Abstract:\r
+\r
+ Library routine to create a GUID\r
+\r
+--*/\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+void\r
+CreateGuid (\r
+ GUID *Guid\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Guid - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ CoCreateGuid (Guid);\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2002 - 2005, Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ GenCapsuleHdr.c \r
+\r
+Abstract:\r
+\r
+ Generate a capsule header for a file, and optionally prepend the\r
+ header to a file or list of files.\r
+\r
+--*/\r
+\r
+#define _UNICODE\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h" // need a guid definition\r
+#include "EfiUtilityMsgs.h"\r
+#include "EfiCapsule.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+#include "EfiFirmwareFileSystem.h" // for FV header GUID\r
+#define MAX_PATH 256\r
+#define PROGRAM_NAME "GenCapsuleHdr"\r
+\r
+#define UNICODE_BACKSLASH L'\\'\r
+#define UNICODE_FILE_START 0xFEFF\r
+#define UNICODE_CR 0x000D\r
+#define UNICODE_LF 0x000A\r
+#define UNICODE_NULL 0x0000\r
+#define UNICODE_SPACE L' '\r
+#define UNICODE_SLASH L'/'\r
+#define UNICODE_DOUBLE_QUOTE L'"'\r
+#define UNICODE_A L'A'\r
+#define UNICODE_F L'F'\r
+#define UNICODE_Z L'Z'\r
+#define UNICODE_a L'a'\r
+#define UNICODE_f L'f'\r
+#define UNICODE_z L'z'\r
+#define UNICODE_0 L'0'\r
+#define UNICODE_9 L'9'\r
+#define UNICODE_TAB L'\t'\r
+\r
+#define OEM_HEADER_STRING L"OemHeader"\r
+#define AUTHOR_INFO_STRING L"AuthorInfo"\r
+#define REVISION_INFO_STRING L"RevisionInfo"\r
+#define SHORT_DESCRIPTION_STRING L"ShortDescription"\r
+#define LONG_DESCRIPTION_STRING L"LongDescription"\r
+#define EQUAL_STRING L"="\r
+#define OPEN_BRACE_STRING L"{"\r
+#define CLOSE_BRACE_STRING L"}"\r
+#define GUID_STRING L"GUID"\r
+#define DATA_STRING L"DATA"\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+#define UEFI_CAPSULE_HEADER_NO_FALAGS 0\r
+#define UEFI_CAPSULE_HEADER_RESET_FALAGS CAPSULE_FLAGS_PERSIST_ACROSS_RESET\r
+#define UEFI_CAPSULE_HEADER_ALL_FALAGS (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)\r
+#endif\r
+\r
+typedef wchar_t WCHAR;\r
+\r
+typedef struct _FILE_LIST {\r
+ struct _FILE_LIST *Next;\r
+ INT8 FileName[MAX_PATH];\r
+} FILE_LIST;\r
+\r
+typedef struct _SIZE_LIST {\r
+ struct _SIZE_LIST *Next;\r
+ UINT32 Size;\r
+} SIZE_LIST;\r
+\r
+typedef struct {\r
+ INT8 FileName[MAX_PATH];\r
+ WCHAR *FileBuffer;\r
+ WCHAR *FileBufferPtr;\r
+ UINT32 FileSize;\r
+ FILE *FilePtr;\r
+ BOOLEAN EndOfFile;\r
+ UINT32 LineNum;\r
+} SOURCE_FILE;\r
+\r
+//\r
+// Here's all our globals.\r
+//\r
+static struct {\r
+ BOOLEAN Dump;\r
+ BOOLEAN Verbose;\r
+ BOOLEAN JoinMode;\r
+ INT8 ScriptFileName[MAX_PATH];\r
+ INT8 OutputFileName[MAX_PATH];\r
+ FILE_LIST *FileList;\r
+ FILE *OutFptr;\r
+ SIZE_LIST *SizeList;\r
+ SIZE_LIST *LastSize;\r
+ SIZE_LIST *CurrentSize;\r
+} mOptions;\r
+\r
+static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;\r
+\r
+void\r
+CreateGuid (\r
+ EFI_GUID *Guid\r
+ );\r
+\r
+static\r
+STATUS\r
+ProcessArgs (\r
+ int Argc,\r
+ char *Argv[]\r
+ );\r
+\r
+static\r
+void\r
+SkipWhiteSpace (\r
+ SOURCE_FILE *SourceFile\r
+ );\r
+\r
+static\r
+STATUS\r
+GetHexValue (\r
+ SOURCE_FILE *SourceFile,\r
+ UINT32 *Value,\r
+ UINT32 NumDigits\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+GetSplitFileName (\r
+ INT8 *BaseFileName,\r
+ INT8 *NewFileName,\r
+ UINT32 SequenceNumber\r
+ );\r
+\r
+static\r
+STATUS\r
+SplitCapsule (\r
+ INT8 *CapsuleFileName\r
+ );\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+static\r
+void\r
+DumpCapsule (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+JoinCapsule (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+DumpCapsuleHeaderStrings (\r
+ UINT8 *SectionName,\r
+ WCHAR *Buffer\r
+ );\r
+\r
+static\r
+STATUS\r
+CheckFirmwareVolumeHeader (\r
+ INT8 *FileName,\r
+ INT8 *Buffer,\r
+ UINT32 BufferSize\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+IsToken (\r
+ SOURCE_FILE *File,\r
+ WCHAR *Token\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+GetNumber (\r
+ INT8 *Str,\r
+ UINT32 *Value\r
+ );\r
+\r
+static\r
+STATUS\r
+ProcessScriptFile (\r
+ INT8 *ScriptFileName,\r
+ FILE *OutFptr,\r
+ EFI_CAPSULE_HEADER *CapsuleHeader\r
+ );\r
+\r
+static\r
+STATUS\r
+ParseCapsuleInfo (\r
+ SOURCE_FILE *SourceFile,\r
+ FILE *OutFptr,\r
+ WCHAR *SectionName\r
+ );\r
+\r
+static\r
+STATUS\r
+CreateCapsule (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+ParseOemInfo (\r
+ SOURCE_FILE *SourceFile,\r
+ FILE *OutFptr\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+ WCHAR Char\r
+ );\r
+\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+ SOURCE_FILE *File\r
+ );\r
+\r
+int\r
+main (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Call the routine to process the command-line arguments, then\r
+ dispatch to the appropriate function.\r
+ \r
+Arguments:\r
+ Standard C main() argc and argv.\r
+\r
+Returns:\r
+ 0 if successful\r
+ nonzero otherwise\r
+ \r
+--*/\r
+// GC_TODO: Argc - add argument and description to function comment\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ STATUS Status;\r
+ FILE_LIST *NextFile;\r
+ //\r
+ // Specify our program name to the error printing routines.\r
+ //\r
+ SetUtilityName (PROGRAM_NAME);\r
+ //\r
+ // Process the command-line arguments\r
+ //\r
+ Status = ProcessArgs (Argc, Argv);\r
+ if (Status == STATUS_SUCCESS) {\r
+ if (mOptions.Dump) {\r
+ DumpCapsule ();\r
+ } else if (mOptions.JoinMode) {\r
+ JoinCapsule ();\r
+ } else {\r
+ CreateCapsule ();\r
+ }\r
+ }\r
+ //\r
+ // Cleanup\r
+ //\r
+ while (mOptions.FileList != NULL) {\r
+ NextFile = mOptions.FileList->Next;\r
+ free (mOptions.FileList);\r
+ mOptions.FileList = NextFile;\r
+ }\r
+\r
+ while (mOptions.SizeList != NULL) {\r
+ mOptions.CurrentSize = mOptions.SizeList->Next;\r
+ free (mOptions.SizeList);\r
+ mOptions.SizeList = mOptions.CurrentSize;\r
+ }\r
+\r
+ return GetUtilityStatus ();\r
+}\r
+\r
+static\r
+STATUS\r
+CreateCapsule (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ FILE *InFptr;\r
+ FILE_LIST *FileList;\r
+ INT8 *Buffer;\r
+ UINT32 Size;\r
+ EFI_CAPSULE_HEADER CapsuleHeader;\r
+ UINT8 Zero;\r
+ UINT8 FirstFile;\r
+ UINT32 CapsuleHeaderSize;\r
+ long InsertedBlockMapEntryOffset;\r
+ EFI_FV_BLOCK_MAP_ENTRY InsertedBlockMapEntry;\r
+ UINT64 FirmwareVolumeSize;\r
+ long FileSize;\r
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;\r
+\r
+ Buffer = NULL;\r
+ InFptr = NULL;\r
+ FirmwareVolumeSize = 0;\r
+ CapsuleHeaderSize = 0;\r
+ InsertedBlockMapEntryOffset = 0;\r
+ memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY));\r
+ memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+\r
+ if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader));\r
+ memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID));\r
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);\r
+ CapsuleHeader.CapsuleImageSize = sizeof (EFI_CAPSULE_HEADER);\r
+ if (mOptions.ScriptFileName[0] != 0) {\r
+ if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ } else {\r
+ //\r
+ // Insert a default capsule header\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);\r
+ CapsuleHeader.Flags = UEFI_CAPSULE_HEADER_ALL_FALAGS;\r
+#endif\r
+ CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER);\r
+\r
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody;\r
+ //\r
+ // Now copy the contents of any other files specified on the command\r
+ // line to the output file. Files must be FFS files, which are aligned\r
+ // on 8-byte boundaries. Don't align the first file, since it's the start\r
+ // of the image once the capsule header has been removed.\r
+ //\r
+ FileList = mOptions.FileList;\r
+ FirstFile = 1;\r
+ Zero = 0;\r
+ while (FileList != NULL) {\r
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+ goto Done;\r
+ }\r
+ //\r
+ // Allocate a buffer into which we can read the file.\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ Size = ftell (InFptr);\r
+ rewind (InFptr);\r
+ Buffer = (char *) malloc (Size);\r
+ if (Buffer == NULL) {\r
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");\r
+ goto Done;\r
+ }\r
+\r
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");\r
+ goto Done;\r
+ }\r
+\r
+ if (Size > 0) {\r
+ //\r
+ // Align the write of the first bytes from the file if not the first file\r
+ //\r
+ if (FirstFile) {\r
+ //\r
+ // First file must be a firmware volume. Double-check, and then insert\r
+ // an additional block map entry so we can add more files from the command line\r
+ //\r
+ if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Save a copy of the firmware volume header for later\r
+ //\r
+ memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+ FirmwareVolumeSize = FVHeader.FvLength;\r
+ if (FileList->Next != NULL) {\r
+ //\r
+ // Copy the firmware volume header\r
+ //\r
+ InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength;\r
+ if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+\r
+ if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+\r
+ if (fwrite (\r
+ Buffer + FVHeader.HeaderLength,\r
+ Size - FVHeader.HeaderLength,\r
+ 1,\r
+ mOptions.OutFptr\r
+ ) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+ } else {\r
+ //\r
+ // Copy the file contents as-is\r
+ //\r
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+ }\r
+ } else {\r
+ while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) {\r
+ if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ FirstFile = 0;\r
+ }\r
+\r
+ free (Buffer);\r
+ Buffer = NULL;\r
+ fclose (InFptr);\r
+ InFptr = NULL;\r
+ FileList = FileList->Next;\r
+ }\r
+\r
+Done:\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+ //\r
+ // If we inserted an additional block map entry, then fix it up. Fix up the\r
+ // FV header as well to reflect our new size.\r
+ //\r
+ if (InsertedBlockMapEntryOffset != 0) {\r
+ FileSize = ftell (mOptions.OutFptr);\r
+ InsertedBlockMapEntry.NumBlocks = 1;\r
+ InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY));\r
+ fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET);\r
+ fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);\r
+ //\r
+ // Fix up the firmware volume header and write it out\r
+ //\r
+ fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET);\r
+ FVHeader.FvLength = FileSize - CapsuleHeaderSize;\r
+ FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+ fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);\r
+ //\r
+ // Reposition to the end of the file\r
+ //\r
+ }\r
+ //\r
+ // Close files and free the global string lists we allocated memory for\r
+ //\r
+ if (mOptions.OutFptr != NULL) {\r
+ //\r
+ // We should now know the full capsule image size. Update the header and write it again.\r
+ //\r
+ fseek (mOptions.OutFptr, 0, SEEK_END);\r
+ Size = ftell (mOptions.OutFptr);\r
+ CapsuleHeader.CapsuleImageSize = Size;\r
+ fseek (mOptions.OutFptr, 0, SEEK_SET);\r
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ }\r
+\r
+ fseek (mOptions.OutFptr, 0, SEEK_END);\r
+ fclose (mOptions.OutFptr);\r
+ mOptions.OutFptr = NULL;\r
+ }\r
+ //\r
+ // If they are doing split capsule output, then split it up now.\r
+ //\r
+ if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) {\r
+ SplitCapsule (mOptions.OutputFileName);\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessScriptFile (\r
+ INT8 *ScriptFileName,\r
+ FILE *OutFptr,\r
+ EFI_CAPSULE_HEADER *CapsuleHeader\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Parse a capsule header script file.\r
+\r
+Arguments:\r
+ ScriptFileName - name of script file to parse\r
+ OutFptr - output to dump binary data\r
+ CapsuleHeader - capsule header to update with size info\r
+ of parsed fields in the script file\r
+\r
+Returns:\r
+ STATUS_SUCCESS - if all went well\r
+\r
+--*/\r
+{\r
+#if 0\r
+ STATUS Status;\r
+ SOURCE_FILE SourceFile;\r
+ WCHAR *WScriptFileName;\r
+ BOOLEAN InComment;\r
+\r
+ if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write capsule header to output file", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memset (&SourceFile, 0, sizeof (SOURCE_FILE));\r
+ strcpy (SourceFile.FileName, ScriptFileName);\r
+\r
+ Status = STATUS_ERROR;\r
+ //\r
+ // Open the input unicode script file and read it into a buffer\r
+ //\r
+ WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR));\r
+ if (WScriptFileName == NULL) {\r
+ Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ swprintf (WScriptFileName, L"%S", ScriptFileName);\r
+ if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) {\r
+ free (WScriptFileName);\r
+ Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading");\r
+ goto Done;\r
+ }\r
+\r
+ free (WScriptFileName);\r
+ fseek (SourceFile.FilePtr, 0, SEEK_END);\r
+ SourceFile.FileSize = ftell (SourceFile.FilePtr);\r
+ rewind (SourceFile.FilePtr);\r
+ SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR));\r
+ if (SourceFile.FileBuffer == NULL) {\r
+ Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents");\r
+ goto Done;\r
+ }\r
+\r
+ if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) {\r
+ Error (NULL, 0, 0, ScriptFileName, "failed to read file contents");\r
+ goto Done;\r
+ }\r
+\r
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;\r
+ SourceFile.LineNum = 1;\r
+ if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) {\r
+ Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ SourceFile.FileBufferPtr++;\r
+ SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0;\r
+ //\r
+ // Walk the source file buffer and replace all carriage returns with 0 so\r
+ // we can print from the file contents on parse errors.\r
+ //\r
+ InComment = 0;\r
+ while (!EndOfFile (&SourceFile)) {\r
+ if (SourceFile.FileBufferPtr[0] == UNICODE_CR) {\r
+ SourceFile.FileBufferPtr[0] = 0;\r
+ InComment = 0;\r
+ } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) {\r
+ InComment = 0;\r
+ } else if (InComment) {\r
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;\r
+ } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) {\r
+ InComment = 1;\r
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;\r
+ }\r
+\r
+ SourceFile.FileBufferPtr++;\r
+ }\r
+ //\r
+ // Reposition to the start of the file, but skip over the unicode file start\r
+ //\r
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;\r
+ SourceFile.FileBufferPtr++;\r
+ SourceFile.EndOfFile = 0;\r
+ CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr);\r
+ //\r
+ // Parse the OEM bytes\r
+ //\r
+ if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Parse the author information\r
+ //\r
+ CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr);\r
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Parse the revision information\r
+ //\r
+ CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr);\r
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Parse the short description\r
+ //\r
+ CapsuleHeader->OffsetToShortDescription = ftell (OutFptr);\r
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Parse the long description\r
+ //\r
+ CapsuleHeader->OffsetToLongDescription = ftell (OutFptr);\r
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ //\r
+ // Better be end of contents\r
+ //\r
+ SkipWhiteSpace (&SourceFile);\r
+ if (!EndOfFile (&SourceFile)) {\r
+ Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr);\r
+ goto Done;\r
+ }\r
+\r
+ CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr);\r
+ rewind (OutFptr);\r
+ fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr);\r
+ fseek (OutFptr, 0, SEEK_END);\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ if (SourceFile.FilePtr != NULL) {\r
+ fclose (SourceFile.FilePtr);\r
+ }\r
+\r
+ if (SourceFile.FileBuffer != NULL) {\r
+ free (SourceFile.FileBuffer);\r
+ }\r
+\r
+ return Status;\r
+\r
+#endif\r
+ return STATUS_SUCCESS;\r
+}\r
+//\r
+// Parse the OEM data of format:\r
+// OemInfo {\r
+// GUID = 12345676-1234-1234-123456789ABC\r
+// DATA = 0x01, 0x02, 0x03...\r
+// }\r
+//\r
+static\r
+STATUS\r
+ParseOemInfo (\r
+ SOURCE_FILE *SourceFile,\r
+ FILE *OutFptr\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ SourceFile - GC_TODO: add argument description\r
+ OutFptr - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ long OemHeaderOffset;\r
+ UINT32 Data;\r
+ EFI_CAPSULE_OEM_HEADER OemHeader;\r
+ STATUS Status;\r
+ UINT32 DigitCount;\r
+ WCHAR *SaveFilePos;\r
+ UINT8 ByteData;\r
+\r
+ Status = STATUS_ERROR;\r
+ memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER));\r
+ OemHeaderOffset = ftell (OutFptr);\r
+ OemHeader.HeaderSize = sizeof (EFI_CAPSULE_OEM_HEADER);\r
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, OEM_HEADER_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ OEM_HEADER_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ EQUAL_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ OPEN_BRACE_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Look for: GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx\r
+ //\r
+ if (!IsToken (SourceFile, GUID_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ GUID_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ EQUAL_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID\r
+ //\r
+ SkipWhiteSpace (SourceFile);\r
+ if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) {\r
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ OemHeader.OemGuid.Data1 = Data;\r
+ if (!IsToken (SourceFile, L"-")) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected dash in GUID, not %S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Get 3 word values\r
+ //\r
+ for (DigitCount = 0; DigitCount < 3; DigitCount++) {\r
+ if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) {\r
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ switch (DigitCount) {\r
+ case 0:\r
+ OemHeader.OemGuid.Data2 = (UINT16) Data;\r
+ break;\r
+\r
+ case 1:\r
+ OemHeader.OemGuid.Data3 = (UINT16) Data;\r
+ break;\r
+\r
+ case 2:\r
+ OemHeader.OemGuid.Data4[1] = (UINT8) Data;\r
+ OemHeader.OemGuid.Data4[0] = (UINT8) (Data >> 8);\r
+ break;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, L"-")) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected dash in GUID, not %S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ }\r
+ //\r
+ // Pick up the last 6 bytes of the GUID\r
+ //\r
+ SaveFilePos = SourceFile->FileBufferPtr;\r
+ for (DigitCount = 0; DigitCount < 6; DigitCount++) {\r
+ if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) {\r
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data;\r
+ }\r
+ //\r
+ // Now read raw OEM data bytes. May or may not be present.\r
+ // DATA = 0x01, 0x02, 0x02...\r
+ //\r
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+ Status = STATUS_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, DATA_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ DATA_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ EQUAL_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ while (!EndOfFile (SourceFile)) {\r
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+ Status = STATUS_SUCCESS;\r
+ goto Done;\r
+ }\r
+\r
+ if (IsToken (SourceFile, L"0x")) {\r
+ if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected hex byte value, not %.20S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (Data &~0xFF) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected byte hex byte value at %.20S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // Skip over the hex digits, then write the data\r
+ //\r
+ while (iswxdigit (SourceFile->FileBufferPtr[0])) {\r
+ SourceFile->FileBufferPtr++;\r
+ }\r
+\r
+ ByteData = (UINT8) Data;\r
+ if (fwrite (&ByteData, 1, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write OEM data to output file", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ OemHeader.HeaderSize++;\r
+ //\r
+ // Optional comma\r
+ //\r
+ IsToken (SourceFile, L",");\r
+ } else {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected hex OEM data, not %.20S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (EndOfFile (SourceFile)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S close to OEM header data",\r
+ CLOSE_BRACE_STRING\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ //\r
+ // re-write the oem header if no errors\r
+ //\r
+ if (Status == STATUS_SUCCESS) {\r
+ fseek (OutFptr, OemHeaderOffset, SEEK_SET);\r
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ fseek (OutFptr, 0, SEEK_END);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ParseCapsuleInfo (\r
+ SOURCE_FILE *SourceFile,\r
+ FILE *OutFptr,\r
+ WCHAR *SectionName\r
+ )\r
+// GC_TODO: function comment should start with '/*++'\r
+//\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: SourceFile - add argument and description to function comment\r
+// GC_TODO: OutFptr - add argument and description to function comment\r
+// GC_TODO: SectionName - add argument and description to function comment\r
+// Parse: eng "string " "parts"\r
+// spa "string " "parts"\r
+// Write out: "eng string parts\0spa string parts\0\0\r
+//\r
+{\r
+ STATUS Status;\r
+ int StringCount;\r
+ WCHAR Zero;\r
+ WCHAR Spacebar;\r
+\r
+ Status = STATUS_ERROR;\r
+ Zero = 0;\r
+ Spacebar = UNICODE_SPACE;\r
+\r
+ if (!IsToken (SourceFile, SectionName)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ SectionName,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ EQUAL_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %S, not %.20S",\r
+ OPEN_BRACE_STRING,\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ while (!EndOfFile (SourceFile)) {\r
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+ break;\r
+ }\r
+ //\r
+ // Look for language identifier (3 lowercase chars)\r
+ //\r
+ if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) &&\r
+ (SourceFile->FileBufferPtr[0] <= UNICODE_z) &&\r
+ (SourceFile->FileBufferPtr[1] >= UNICODE_a) &&\r
+ (SourceFile->FileBufferPtr[1] <= UNICODE_z) &&\r
+ (SourceFile->FileBufferPtr[2] >= UNICODE_a) &&\r
+ (SourceFile->FileBufferPtr[2] <= UNICODE_z) &&\r
+ IsWhiteSpace (SourceFile->FileBufferPtr[3])\r
+ ) {\r
+ //\r
+ // Write the 3 chars followed by a spacebar, and then look for opening quote\r
+ //\r
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+ SourceFile->FileBufferPtr++;\r
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+ SourceFile->FileBufferPtr++;\r
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+ SourceFile->FileBufferPtr++;\r
+ fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr);\r
+ StringCount = 0;\r
+ while (IsToken (SourceFile, L"\"")) {\r
+ StringCount++;\r
+ while (!EndOfFile (SourceFile)) {\r
+ if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {\r
+ SourceFile->FileBufferPtr++;\r
+ break;\r
+ } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) {\r
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL);\r
+ goto Done;\r
+ } else {\r
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+ SourceFile->FileBufferPtr++;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (StringCount == 0) {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected quoted string, not %.20S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // This string's null terminator\r
+ //\r
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);\r
+ } else {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected valid language identifer, not %.20S",\r
+ SourceFile->FileBufferPtr\r
+ );\r
+ goto Done;\r
+ }\r
+ }\r
+ //\r
+ // Double null terminator\r
+ //\r
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);\r
+ Status = STATUS_SUCCESS;\r
+Done:\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+SplitCapsule (\r
+ INT8 *CapsuleFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ We've created an entire capsule image. Now split it up into the \r
+ size pieces they requested.\r
+\r
+Arguments:\r
+ CapsuleFileName - name of an existing capsule file on disk\r
+\r
+Returns:\r
+ STATUS_SUCCESS - if no problems\r
+\r
+Notes:\r
+ This implementation reads in the entire capsule image from\r
+ disk, then overwrites the original file with the first\r
+ in the series.\r
+\r
+--*/\r
+{\r
+#if 0\r
+ EFI_CAPSULE_HEADER *CapHdr;\r
+\r
+ EFI_CAPSULE_HEADER Hdr;\r
+ FILE *CapFptr;\r
+ FILE *OutFptr;\r
+ UINT32 SizeLeft;\r
+ UINT32 CurrentSize;\r
+ UINT32 DataSize;\r
+ UINT32 SequenceNumber;\r
+ INT8 *Buffer;\r
+ INT8 FileName[MAX_PATH];\r
+ STATUS Status;\r
+ UINT32 FileSize;\r
+ //\r
+ // Figure out the total size, then rewind the input file and\r
+ // read the entire thing in\r
+ //\r
+ if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ OutFptr = NULL;\r
+ Status = STATUS_SUCCESS;\r
+ fseek (CapFptr, 0, SEEK_END);\r
+ SizeLeft = ftell (CapFptr);\r
+ fseek (CapFptr, 0, SEEK_SET);\r
+ CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft);\r
+ if (CapHdr == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ goto FailDone;\r
+ }\r
+\r
+ if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to read capsule contents", "split failed");\r
+ goto FailDone;\r
+ }\r
+\r
+ fclose (CapFptr);\r
+ CapFptr = NULL;\r
+ //\r
+ // Get a GUID to fill in the InstanceId GUID in the header\r
+ //\r
+ CreateGuid (&CapHdr->InstanceId);\r
+ SequenceNumber = 0;\r
+ //\r
+ // If the split size is larger than the original capsule image, then\r
+ // we're done.\r
+ //\r
+ if (mOptions.SizeList->Size >= SizeLeft) {\r
+ mOptions.SizeList->Size = SizeLeft;\r
+ goto Done;\r
+ }\r
+ //\r
+ // First size has to be big enough for the original header\r
+ //\r
+ if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) {\r
+ Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL);\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Initialize the header we'll use on all but the first part\r
+ //\r
+ memset (&Hdr, 0, sizeof (Hdr));\r
+ Hdr.CapsuleGuid = CapHdr->CapsuleGuid;\r
+ Hdr.HeaderSize = sizeof (Hdr);\r
+ Hdr.Flags = CapHdr->Flags;\r
+ Hdr.InstanceId = CapHdr->InstanceId;\r
+ Hdr.CapsuleImageSize = CapHdr->CapsuleImageSize;\r
+ Hdr.OffsetToCapsuleBody = Hdr.HeaderSize;\r
+ Hdr.SequenceNumber = 1;\r
+ //\r
+ // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size);\r
+ //\r
+ Buffer = (UINT8 *) CapHdr;\r
+ //\r
+ // Walk the list of sizes and write out a capsule header, and\r
+ // then the raw capsule data.\r
+ //\r
+ // SizeLeft -= mOptions.SizeList->Size;\r
+ //\r
+ mOptions.CurrentSize = mOptions.SizeList;\r
+ while (SizeLeft) {\r
+ CurrentSize = mOptions.CurrentSize->Size;\r
+ GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber);\r
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open split file for writing");\r
+ goto FailDone;\r
+ }\r
+\r
+ if (Buffer == (UINT8 *) CapHdr) {\r
+ //\r
+ // First part -- write out original header and data\r
+ //\r
+ if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to write to split image file");\r
+ goto FailDone;\r
+ }\r
+\r
+ SizeLeft -= CurrentSize;\r
+ Buffer += CurrentSize;\r
+ DataSize = CurrentSize;\r
+ FileSize = CurrentSize;\r
+ } else {\r
+ //\r
+ // Not the first part. Write the default header, and then the raw bytes from the\r
+ // original image.\r
+ //\r
+ if (CurrentSize <= sizeof (Hdr)) {\r
+ Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize);\r
+ goto FailDone;\r
+ }\r
+\r
+ DataSize = CurrentSize - sizeof (Hdr);\r
+ if (DataSize > SizeLeft) {\r
+ DataSize = SizeLeft;\r
+ }\r
+\r
+ if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to write capsule header to output file");\r
+ fclose (OutFptr);\r
+ goto FailDone;\r
+ }\r
+\r
+ if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to write capsule data to output file");\r
+ fclose (OutFptr);\r
+ goto FailDone;\r
+ }\r
+\r
+ Hdr.SequenceNumber++;\r
+ Buffer += DataSize;\r
+ SizeLeft -= DataSize;\r
+ FileSize = DataSize + sizeof (Hdr);\r
+ }\r
+ //\r
+ // Next size in list if there is one\r
+ //\r
+ if (mOptions.CurrentSize->Next != NULL) {\r
+ mOptions.CurrentSize = mOptions.CurrentSize->Next;\r
+ }\r
+\r
+ SequenceNumber++;\r
+ fclose (OutFptr);\r
+ OutFptr = NULL;\r
+ printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize);\r
+ }\r
+\r
+ goto Done;\r
+FailDone:\r
+ Status = STATUS_ERROR;\r
+Done:\r
+ if (CapHdr != NULL) {\r
+ free (CapHdr);\r
+ }\r
+\r
+ if (CapFptr != NULL) {\r
+ fclose (CapFptr);\r
+ }\r
+\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ }\r
+\r
+ return Status;\r
+\r
+#endif\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+GetSplitFileName (\r
+ INT8 *BaseFileName,\r
+ INT8 *NewFileName,\r
+ UINT32 SequenceNumber\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ BaseFileName - GC_TODO: add argument description\r
+ NewFileName - GC_TODO: add argument description\r
+ SequenceNumber - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ /*++\r
+\r
+Routine Description:\r
+ Given an initial split capsule file name and a sequence number,\r
+ create an appropriate file name for this split of a capsule image.\r
+\r
+Arguments:\r
+ BaseFileName - name of of the first split file in the series\r
+ NewFileName - output name of the split file\r
+ SequenceNumber - 0-based sequence number of split images\r
+\r
+Returns:\r
+ TRUE - name created successfully\r
+ FALSE - otherwise\r
+\r
+--*/\r
+ INT8 *Ptr;\r
+ INT8 *Part2Start;\r
+ UINT32 Digits;\r
+ UINT32 Len;\r
+ UINT32 BaseOffset;\r
+ //\r
+ // Work back from the end of the file name and see if there is a number somewhere\r
+ //\r
+ for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--)\r
+ ;\r
+ if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) {\r
+ //\r
+ // Found no number, so just add it to the end\r
+ //\r
+ sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber);\r
+ return TRUE;\r
+ } else {\r
+ //\r
+ // Found a number. Look back to find the first digit.\r
+ //\r
+ Part2Start = Ptr + 1;\r
+ for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++)\r
+ ;\r
+ if (!isdigit (*Ptr)) {\r
+ Ptr++;\r
+ Digits--;\r
+ }\r
+\r
+ BaseOffset = atoi (Ptr);\r
+ SequenceNumber = SequenceNumber + BaseOffset;\r
+ if (Digits > 1) {\r
+ //\r
+ // Copy the first part of the original file name to the new filename\r
+ // This is the path for filenames with format path\name001.cap\r
+ //\r
+ Len = (UINT32) Ptr - (UINT32) BaseFileName;\r
+ strncpy (NewFileName, BaseFileName, Len);\r
+ sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber);\r
+ strcat (NewFileName, Part2Start);\r
+ return TRUE;\r
+ } else {\r
+ //\r
+ // Only one digit found. This is the path for filenames with\r
+ // format path\name1.cap\r
+ //\r
+ Len = (UINT32) Ptr - (UINT32) BaseFileName + 1;\r
+ strncpy (NewFileName, BaseFileName, Len);\r
+ sprintf (NewFileName + Len - 1, "%d", SequenceNumber);\r
+ strcat (NewFileName, Part2Start);\r
+ return TRUE;\r
+ }\r
+ }\r
+}\r
+\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+ WCHAR Char\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Char - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ switch (Char) {\r
+ case UNICODE_SPACE:\r
+ case UNICODE_TAB:\r
+ case UNICODE_NULL:\r
+ case UNICODE_CR:\r
+ case UNICODE_LF:\r
+ return TRUE;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+}\r
+\r
+static\r
+BOOLEAN\r
+IsToken (\r
+ SOURCE_FILE *File,\r
+ WCHAR *Token\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ File - GC_TODO: add argument description\r
+ Token - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ SkipWhiteSpace (File);\r
+ if (EndOfFile (File)) {\r
+ return FALSE;\r
+ }\r
+\r
+ if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) {\r
+ File->FileBufferPtr += wcslen (Token);\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckFirmwareVolumeHeader (\r
+ INT8 *FileName,\r
+ INT8 *Buffer,\r
+ UINT32 BufferSize\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileName - GC_TODO: add argument description\r
+ Buffer - GC_TODO: add argument description\r
+ BufferSize - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER *Hdr;\r
+ EFI_GUID FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;\r
+\r
+ Hdr = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
+ if (Hdr->Signature != EFI_FVH_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (Hdr->Revision != EFI_FVH_REVISION) {\r
+ Error (NULL, 0, 0, FileName, "unsupported firmware volume header version");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (Hdr->FvLength > BufferSize) {\r
+ Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+ Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+DumpCapsule (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+#if 0\r
+ FILE *InFptr;\r
+ FILE_LIST *FileList;\r
+ EFI_CAPSULE_HEADER CapsuleHeader;\r
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;\r
+ EFI_CAPSULE_OEM_HEADER *OemHeader;\r
+ UINT8 *BPtr;\r
+ UINT32 FileSize;\r
+ UINT32 CapsuleHeaderDataSize;\r
+ UINT8 ByteCount;\r
+ UINT8 *CapsuleHeaderData;\r
+ BOOLEAN SplitImage;\r
+\r
+ InFptr = NULL;\r
+ CapsuleHeaderData = NULL;\r
+ FileList = mOptions.FileList;\r
+ while (FileList != NULL) {\r
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+ goto Done;\r
+ }\r
+\r
+ if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header");\r
+ goto Done;\r
+ }\r
+\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ if (CapsuleHeader.CapsuleImageSize > FileSize) {\r
+ SplitImage = TRUE;\r
+ } else {\r
+ SplitImage = FALSE;\r
+ }\r
+\r
+ printf (\r
+ "Capsule %s Size=0x%X CargoSize=0x%X\n",\r
+ FileList->FileName,\r
+ FileSize,\r
+ FileSize - CapsuleHeader.OffsetToCapsuleBody\r
+ );\r
+ printf (\r
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+ CapsuleHeader.CapsuleGuid.Data1,\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data2,\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data3,\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[0],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[1],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[2],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[3],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[4],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[5],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[6],\r
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[7]\r
+ );\r
+ if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+ printf (" INVALID GUID");\r
+ }\r
+\r
+ printf ("\n");\r
+ printf (" Header size 0x%08X\n", CapsuleHeader.HeaderSize);\r
+ printf (" Flags 0x%08X\n", CapsuleHeader.Flags);\r
+ if (!SplitImage) {\r
+ printf (" Capsule image size 0x%08X\n", CapsuleHeader.CapsuleImageSize);\r
+ } else {\r
+ printf (" Capsule image size 0x%08X (split)\n", CapsuleHeader.CapsuleImageSize);\r
+ }\r
+\r
+ printf (" Sequence number %d\n", CapsuleHeader.SequenceNumber);\r
+ printf (\r
+ " InstanceId %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+ CapsuleHeader.InstanceId.Data1,\r
+ (UINT32) CapsuleHeader.InstanceId.Data2,\r
+ (UINT32) CapsuleHeader.InstanceId.Data3,\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[0],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[1],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[2],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[3],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[4],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[5],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[6],\r
+ (UINT32) CapsuleHeader.InstanceId.Data4[7]\r
+ );\r
+ printf (" Offset to capsule 0x%X\n", CapsuleHeader.OffsetToCapsuleBody);\r
+ //\r
+ // Dump header data if there\r
+ //\r
+ CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize;\r
+ if (CapsuleHeaderDataSize != 0) {\r
+ CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize);\r
+ if (CapsuleHeaderData == NULL) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "failed to allocate memory to read in capsule header data",\r
+ "0x%X bytes",\r
+ CapsuleHeaderDataSize\r
+ );\r
+ goto Done;\r
+ }\r
+\r
+ fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET);\r
+ if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "failed to read capsule header data contents from file",\r
+ "0x%X bytes",\r
+ CapsuleHeaderDataSize\r
+ );\r
+ goto Done;\r
+ }\r
+ //\r
+ // ************************************************************************\r
+ //\r
+ // OEM HEADER\r
+ //\r
+ // ************************************************************************\r
+ //\r
+ if (CapsuleHeader.OffsetToOemDefinedHeader != 0) {\r
+ OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize);\r
+ printf (" OEM Header\n");\r
+ printf (\r
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+ OemHeader->OemGuid.Data1,\r
+ (UINT32) OemHeader->OemGuid.Data2,\r
+ (UINT32) OemHeader->OemGuid.Data3,\r
+ (UINT32) OemHeader->OemGuid.Data4[0],\r
+ (UINT32) OemHeader->OemGuid.Data4[1],\r
+ (UINT32) OemHeader->OemGuid.Data4[2],\r
+ (UINT32) OemHeader->OemGuid.Data4[3],\r
+ (UINT32) OemHeader->OemGuid.Data4[4],\r
+ (UINT32) OemHeader->OemGuid.Data4[5],\r
+ (UINT32) OemHeader->OemGuid.Data4[6],\r
+ (UINT32) OemHeader->OemGuid.Data4[7]\r
+ );\r
+ printf (" Header size: 0x%X\n", OemHeader->HeaderSize);\r
+ printf (" OEM data");\r
+ BPtr = (UINT8 *) (OemHeader + 1);\r
+ for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) {\r
+ if ((ByteCount & 0x7) == 0) {\r
+ printf ("\n ");\r
+ }\r
+\r
+ printf ("%02X ", (UINT32) *BPtr);\r
+ BPtr++;\r
+ }\r
+\r
+ printf ("\n");\r
+ }\r
+ //\r
+ // ************************************************************************\r
+ //\r
+ // Author, revision, short description, and long description information\r
+ //\r
+ // ************************************************************************\r
+ //\r
+ if (CapsuleHeader.OffsetToAuthorInformation != 0) {\r
+ if (DumpCapsuleHeaderStrings (\r
+ "Author information",\r
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize)\r
+ ) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (CapsuleHeader.OffsetToRevisionInformation != 0) {\r
+ if (DumpCapsuleHeaderStrings (\r
+ "Revision information",\r
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize)\r
+ ) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (CapsuleHeader.OffsetToShortDescription != 0) {\r
+ if (DumpCapsuleHeaderStrings (\r
+ "Short description",\r
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize)\r
+ ) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ if (CapsuleHeader.OffsetToLongDescription != 0) {\r
+ if (DumpCapsuleHeaderStrings (\r
+ "Long description",\r
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize)\r
+ ) != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // If it's not a split image, or it is a split image and this is the first in the series, then\r
+ // dump the cargo volume.\r
+ //\r
+ if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) {\r
+ printf (" Cargo FV dump\n");\r
+ fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET);\r
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header");\r
+ goto Done;\r
+ }\r
+\r
+ printf (" FV length 0x%X", FVHeader.FvLength);\r
+ if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) {\r
+ if (!SplitImage) {\r
+ printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody);\r
+ }\r
+ }\r
+\r
+ printf ("\n");\r
+ printf (" Signature 0x%X ", FVHeader.Signature);\r
+ if (FVHeader.Signature == EFI_FVH_SIGNATURE) {\r
+ printf ("_FVH\n");\r
+ } else {\r
+ printf ("INVALID\n");\r
+ }\r
+\r
+ printf (" FV header length 0x%X\n", (UINT32) FVHeader.HeaderLength);\r
+ printf (" Revision 0x%X\n", (UINT32) FVHeader.Revision);\r
+ printf ("\n");\r
+ }\r
+\r
+ FileList = FileList->Next;\r
+ }\r
+\r
+Done:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ if (CapsuleHeaderData != NULL) {\r
+ free (CapsuleHeaderData);\r
+ }\r
+#endif\r
+}\r
+\r
+static\r
+STATUS\r
+JoinCapsule (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Join split capsule images into a single image. This is the\r
+ support function for the -j command-line option.\r
+\r
+Arguments:\r
+ None.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - no problems encountered\r
+\r
+--*/\r
+{\r
+#if 0\r
+ UINT32 Size;\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ INT8 *Buffer;\r
+ FILE_LIST *FileList;\r
+ STATUS Status;\r
+ EFI_CAPSULE_HEADER CapHdr;\r
+ EFI_CAPSULE_HEADER *CapHdrPtr;\r
+ UINT32 SizeLeft;\r
+ UINT32 SequenceNumber;\r
+ //\r
+ // Must have at least two files for join mode\r
+ //\r
+ if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) {\r
+ Error (NULL, 0, 0, "must specify at least two file names to join", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Open the output file\r
+ //\r
+ if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ FileList = mOptions.FileList;\r
+ Buffer = NULL;\r
+ SequenceNumber = 0;\r
+ InFptr = NULL;\r
+ SizeLeft = 0;\r
+ while (FileList != NULL) {\r
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Allocate a buffer into which we can read the file.\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ Size = ftell (InFptr);\r
+ rewind (InFptr);\r
+ Buffer = (char *) malloc (Size);\r
+ if (Buffer == NULL) {\r
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");\r
+ goto FailDone;\r
+ }\r
+\r
+ CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer;\r
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Check the header for validity. Check size first.\r
+ //\r
+ if (Size < sizeof (EFI_CAPSULE_HEADER)) {\r
+ Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header");\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Check GUID\r
+ //\r
+ if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+ Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID");\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Check sequence number\r
+ //\r
+ if (CapHdrPtr->SequenceNumber != SequenceNumber) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ FileList->FileName,\r
+ "invalid sequence number %d (expected %d)",\r
+ CapHdrPtr->SequenceNumber,\r
+ SequenceNumber\r
+ );\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // If the first file, read save the capsule header\r
+ //\r
+ if (SequenceNumber == 0) {\r
+ memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER));\r
+ //\r
+ // Erase the InstanceId GUID\r
+ //\r
+ memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID));\r
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file");\r
+ goto FailDone;\r
+ }\r
+\r
+ if (CapHdr.CapsuleImageSize < Size) {\r
+ Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size");\r
+ goto FailDone;\r
+ }\r
+\r
+ SizeLeft = CapHdr.CapsuleImageSize - Size;\r
+ } else {\r
+ //\r
+ // Check the GUID against the first file's GUID\r
+ //\r
+ if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) {\r
+ Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID");\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // Make sure we're not throwing out any header info\r
+ //\r
+ if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) {\r
+ //\r
+ // Could be the split information, so just emit a warning\r
+ //\r
+ Warning (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ FileList->FileName,\r
+ "image appears to have additional capsule header information -- ignoring"\r
+ );\r
+ } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) {\r
+ Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient");\r
+ goto FailDone;\r
+ }\r
+\r
+ if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+ goto FailDone;\r
+ }\r
+\r
+ if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) {\r
+ Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL);\r
+ goto FailDone;\r
+ }\r
+ //\r
+ // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody);\r
+ //\r
+ SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody);\r
+ }\r
+ //\r
+ // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft);\r
+ //\r
+ fclose (InFptr);\r
+ InFptr = NULL;\r
+ free (Buffer);\r
+ Buffer = NULL;\r
+ FileList = FileList->Next;\r
+ SequenceNumber++;\r
+ }\r
+\r
+ if (SizeLeft) {\r
+ Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft);\r
+ goto FailDone;\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+ goto Done;\r
+FailDone:\r
+ Status = STATUS_ERROR;\r
+Done:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ }\r
+\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+\r
+ return Status;\r
+\r
+#endif\r
+return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+DumpCapsuleHeaderStrings (\r
+ UINT8 *SectionName,\r
+ WCHAR *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Given a pointer to string data from a capsule header, dump\r
+ the strings.\r
+\r
+Arguments:\r
+ SectionName - name of the capsule header section to which\r
+ the string data pertains\r
+ Buffer - pointer to string data from a capsule header\r
+\r
+Returns:\r
+ STATUS_SUCCESS - all went well\r
+\r
+--*/\r
+{\r
+ printf (" %s\n", SectionName);\r
+ while (*Buffer) {\r
+ printf (" Language: %S\n", Buffer);\r
+ while (*Buffer) {\r
+ Buffer++;\r
+ }\r
+\r
+ Buffer++;\r
+ while (*Buffer) {\r
+ if (wcslen (Buffer) > 60) {\r
+ printf (" %.60S\n", Buffer);\r
+ Buffer += 60;\r
+ } else {\r
+ printf (" %S\n", Buffer);\r
+ Buffer += wcslen (Buffer);\r
+ }\r
+ }\r
+\r
+ Buffer++;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+GetHexValue (\r
+ SOURCE_FILE *SourceFile,\r
+ UINT32 *Value,\r
+ UINT32 NumDigits\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ Scan a hex value from the input stream.\r
+ \r
+Arguments:\r
+ SourceFile - input file contents\r
+ Value - returned value\r
+ NumDigits - number of digits to read\r
+\r
+Returns:\r
+ STATUS_SUCCESS - if NumDigits were read from the file\r
+ STATUS_ERROR - otherwise\r
+\r
+ \r
+--*/\r
+{\r
+ WCHAR *SaveFilePos;\r
+ UINT32 Digits;\r
+ WCHAR Nibble;\r
+\r
+ SaveFilePos = SourceFile->FileBufferPtr;\r
+ *Value = 0;\r
+ Digits = NumDigits;\r
+ while (Digits > 0) {\r
+ Nibble = SourceFile->FileBufferPtr[0];\r
+ if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) {\r
+ *Value = (*Value << 4) | (Nibble - UNICODE_0);\r
+ } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) {\r
+ *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10);\r
+ } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) {\r
+ *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10);\r
+ } else {\r
+ Error (\r
+ SourceFile->FileName,\r
+ SourceFile->LineNum,\r
+ 0,\r
+ NULL,\r
+ "expected %d valid hex nibbles at %.20S",\r
+ NumDigits,\r
+ SaveFilePos\r
+ );\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ SourceFile->FileBufferPtr++;\r
+ Digits--;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+ SOURCE_FILE *File\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ File - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) {\r
+ File->EndOfFile = TRUE;\r
+ }\r
+ //\r
+ // Reposition to the end of the file if we went beyond\r
+ //\r
+ if (File->EndOfFile) {\r
+ File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR);\r
+ }\r
+\r
+ return File->EndOfFile;\r
+}\r
+\r
+static\r
+void\r
+SkipWhiteSpace (\r
+ SOURCE_FILE *SourceFile\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ SourceFile - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ while (!EndOfFile (SourceFile)) {\r
+ switch (*SourceFile->FileBufferPtr) {\r
+ case UNICODE_NULL:\r
+ case UNICODE_CR:\r
+ case UNICODE_SPACE:\r
+ case UNICODE_TAB:\r
+ SourceFile->FileBufferPtr++;\r
+ break;\r
+\r
+ case UNICODE_LF:\r
+ SourceFile->FileBufferPtr++;\r
+ SourceFile->LineNum++;\r
+ break;\r
+\r
+ default:\r
+ return ;\r
+ }\r
+ }\r
+}\r
+//\r
+// Parse a number. Possible format:\r
+// 1234\r
+// 1234k\r
+// 1234K\r
+// 1M\r
+// 1m\r
+// 0x100\r
+//\r
+static\r
+BOOLEAN\r
+GetNumber (\r
+ INT8 *Str,\r
+ UINT32 *Value\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ Str - GC_TODO: add argument description\r
+ Value - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ UINT32 LValue;\r
+\r
+ *Value = 0;\r
+ LValue = 0;\r
+ if (!isdigit (Str[0])) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // Look for hex number\r
+ //\r
+ if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) {\r
+ Str += 2;\r
+ if (Str[0] == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ while (Str[0]) {\r
+ if ((Str[0] >= '0') && (Str[0] <= '9')) {\r
+ LValue = (LValue << 4) | (Str[0] - '0');\r
+ } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) {\r
+ LValue = (LValue << 4) | (Str[0] - 'A' + 0x10);\r
+ } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) {\r
+ LValue = (LValue << 4) | (Str[0] - 'a' + 0x10);\r
+ } else {\r
+ break;\r
+ }\r
+\r
+ Str++;\r
+ }\r
+ } else {\r
+ LValue = atoi (Str);\r
+ while (isdigit (*Str)) {\r
+ Str++;\r
+ }\r
+ }\r
+ //\r
+ // If string left over, better be one character we recognize\r
+ //\r
+ if (Str[0]) {\r
+ if (Str[1]) {\r
+ return FALSE;\r
+ }\r
+\r
+ switch (Str[0]) {\r
+ case 'k':\r
+ case 'K':\r
+ LValue *= 1024;\r
+ break;\r
+\r
+ case 'm':\r
+ case 'M':\r
+ LValue *= 1024 * 1024;\r
+ break;\r
+\r
+ default:\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ *Value = LValue;\r
+ return TRUE;\r
+}\r
+//\r
+// Process the command-line arguments\r
+//\r
+static\r
+STATUS\r
+ProcessArgs (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Processes command line arguments.\r
+\r
+Arguments:\r
+\r
+ Argc - Number of command line arguments\r
+ Argv[] - Array of files input on command line \r
+\r
+Returns:\r
+\r
+ STATUS_ERROR - Function exited with an error\r
+ STATUS_SUCCESS - Function executed successfully\r
+\r
+--*/\r
+{\r
+ FILE_LIST *NewFile;\r
+\r
+ FILE_LIST *LastFile;\r
+ SIZE_LIST *NewSize;\r
+ \r
+ NewFile = NULL;\r
+ NewSize = NULL;\r
+ \r
+ //\r
+ // Clear our globals\r
+ //\r
+ memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+\r
+ //\r
+ // Skip program name\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Process until no more options\r
+ //\r
+ while ((Argc > 0) && (Argv[0][0] == '-')) {\r
+ if (stricmp (Argv[0], "-script") == 0) {\r
+ //\r
+ // Check for one more arg\r
+ //\r
+ if (Argc > 1) {\r
+ //\r
+ // Save the file name\r
+ //\r
+ if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) {\r
+ Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size");\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ strcpy (mOptions.ScriptFileName, Argv[1]);\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "missing script file name with option");\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ } \r
+\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argc--;\r
+ Argv++;\r
+ //\r
+ // -o outfilename -- specify output file name (required)\r
+ //\r
+ } else if (stricmp (Argv[0], "-o") == 0) {\r
+ //\r
+ // check for one more arg\r
+ //\r
+ if (Argc > 1) {\r
+ //\r
+ // Try to open the file\r
+ //\r
+ // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) {\r
+ // Error (NULL, 0, 0, Argv[1], "failed to open output file for writing");\r
+ // return STATUS_ERROR;\r
+ // }\r
+ //\r
+ strcpy (mOptions.OutputFileName, Argv[1]);\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "missing output filename with option");\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argc--;\r
+ Argv++;\r
+ } else if (stricmp (Argv[0], "-j") == 0) {\r
+ mOptions.JoinMode = TRUE;\r
+ //\r
+ // -split <size> option (multiple allowed)\r
+ //\r
+ } else if (stricmp (Argv[0], "-split") == 0) {\r
+ if (Argc > 1) {\r
+ NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST));\r
+ if (NewSize == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+\r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memset (NewSize, 0, sizeof (SIZE_LIST));\r
+ //\r
+ // Get the size from the next arg, and then add this size\r
+ // to our size list\r
+ //\r
+ if (!GetNumber (Argv[1], &NewSize->Size)) {\r
+ Error (NULL, 0, 0, Argv[1], "invalid split size argument");\r
+\r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ } \r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (mOptions.SizeList == NULL) {\r
+ mOptions.SizeList = NewSize;\r
+ mOptions.CurrentSize = NewSize;\r
+ } else {\r
+ mOptions.LastSize->Next = NewSize;\r
+ }\r
+\r
+ mOptions.LastSize = NewSize;\r
+ free (NewSize);\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "missing size parameter with option");\r
+ Usage ();\r
+\r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argc--;\r
+ Argv++; \r
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ //\r
+ // Default minimum header\r
+ //\r
+ } else if (stricmp (Argv[0], "-dump") == 0) {\r
+ mOptions.Dump = TRUE;\r
+ } else if (stricmp (Argv[0], "-v") == 0) {\r
+ mOptions.Verbose = TRUE;\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argc--;\r
+ Argv++;\r
+ }\r
+ //\r
+ // Can't -j join files and -s split output capsule\r
+ //\r
+ if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) {\r
+ Error (NULL, 0, 0, "cannot specify both -j and -size", NULL);\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Must have specified an output file name if not -dump\r
+ //\r
+ if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) {\r
+ Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified");\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Rest of arguments are input files. The first one is a firmware\r
+ // volume image, and the rest are FFS files that are to be inserted\r
+ // into the firmware volume.\r
+ //\r
+ LastFile = NULL;\r
+ while (Argc > 0) {\r
+ NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
+ if (NewFile == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+\r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ memset ((char *) NewFile, 0, sizeof (FILE_LIST));\r
+ strcpy (NewFile->FileName, Argv[0]);\r
+ if (mOptions.FileList == NULL) {\r
+ mOptions.FileList = NewFile;\r
+ } else {\r
+ if (LastFile == NULL) {\r
+ LastFile = NewFile;\r
+ } else {\r
+ LastFile->Next = NewFile;\r
+ } \r
+ }\r
+\r
+ LastFile = NewFile;\r
+ Argc--;\r
+ Argv++;\r
+ }\r
+\r
+ //\r
+ // Must have provided at least one file name\r
+ //\r
+ if (mOptions.FileList == NULL) {\r
+ Error (NULL, 0, 0, "must specify at least one file name", NULL);\r
+ Usage ();\r
+ \r
+ if (NewFile != NULL) {\r
+ free (NewFile);\r
+ }\r
+ if (NewSize != NULL) {\r
+ free (NewSize);\r
+ }\r
+ \r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Print usage information for this utility.\r
+ \r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+ \r
+--*/\r
+{\r
+ int Index;\r
+ static const char *Str[] = {\r
+ PROGRAM_NAME " -- create a capsule header",\r
+ " Usage: "PROGRAM_NAME " {options} [CapsuleFV]",\r
+ //\r
+ // {FfsFileNames}",\r
+ //\r
+ " Options include:",\r
+ " -h or -? for this help information",\r
+ " -script fname to take capsule header info from unicode script",\r
+ " file fname",\r
+ " -o fname write output to file fname (required)",\r
+ " -split size split capsule image into multiple output files",\r
+ " -dump to dump a capsule header",\r
+ " -v for verbose output\n",\r
+ " -j to join split capsule images into a single image",\r
+ "",\r
+ " CapsuleFV is the name of an existing well-formed Tiano firmware",\r
+ " volume file.",\r
+ //\r
+ // FfsFileNames are the names of one or more Tiano FFS files to",\r
+ // " insert into the output capsule image.",\r
+ //\r
+ NULL\r
+ };\r
+ for (Index = 0; Str[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Str[Index]);\r
+ }\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2002 Intel Corporation. All rights reserved\r
+# This software and associated documentation (if any) is furnished\r
+# under a license and may only be used or copied in accordance\r
+# with the terms of the license. Except as permitted by such\r
+# license, no part of this software or documentation may be\r
+# reproduced, stored in a retrieval system, or transmitted in any\r
+# form or by any means without the express written consent of\r
+# Intel Corporation.\r
+# \r
+# \r
+# Module Name:\r
+# \r
+# Makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for the GenCapsuleHdr utility.\r
+# \r
+#--*/ \r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+\r
+TARGET_NAME = GenCapsuleHdr\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+SRC = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+ETO = $(TIANO_TOOLS_OUTPUT)\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+LIBS = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib" ole32.lib\r
+\r
+OBJECTS = $(ETO)\$(TARGET_NAME).obj \\r
+ $(ETO)\CreateGuid.obj\r
+\r
+#\r
+# Compile each source file\r
+#\r
+$(ETO)\$(TARGET_NAME).obj : $(SRC)\$(TARGET_NAME).c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(SRC)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(ETO)\CreateGuid.obj : $(SRC)\CreateGuid.c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(SRC)\CreateGuid.c /Fo$@\r
+\r
+#\r
+# Link the object files together\r
+#\r
+$(TARGET_EXE) : $(OBJECTS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ GenFdImage.h\r
+\r
+Abstract:\r
+\r
+ This file contains the relevant declarations required\r
+ to generate the Firmware Device\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standard\r
+//\r
+#ifndef _EFI_GEN_FD_IMAGE_H\r
+#define _EFI_GEN_FD_IMAGE_H\r
+\r
+//\r
+// Included Header files\r
+//\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <io.h>\r
+#include <assert.h>\r
+#include "TianoCommon.h"\r
+#include "ParseInf.h"\r
+#include "GenFvImage.h"\r
+\r
+//\r
+// Defines\r
+//\r
+#define FILE_NAME_SIZE 256\r
+\r
+//\r
+// Type Definition\r
+//\r
+typedef struct {\r
+ UINT64 FdSize;\r
+ UINT64 FdBaseAddress;\r
+ UINT8 PadValue;\r
+ CHAR8 OutFileName[FILE_NAME_SIZE];\r
+} FDINFO;\r
+\r
+//\r
+// Exported Function Prototype\r
+//\r
+EFI_STATUS\r
+GenerateFdImage (\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Size,\r
+ IN UINT8 PadByte,\r
+ IN CHAR8 *OutFile,\r
+ IN CHAR8 **FileList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ BaseAddress - GC_TODO: add argument description\r
+ Size - GC_TODO: add argument description\r
+ PadByte - GC_TODO: add argument description\r
+ OutFile - GC_TODO: add argument description\r
+ FileList - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+ Module Name: \r
+ GenFdImageDll.C\r
+\r
+ Abstarct:\r
+ This file contains the relevant functions required to complete\r
+ the API to generate Firmware Device\r
+--*/\r
+\r
+// GC_TODO: fix comment to add: Abstract:\r
+//\r
+// This tells the compiler to export the DLL functions\r
+//\r
+#define GEN_FD_IMAGE_EXPORTS\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <io.h>\r
+#include <assert.h>\r
+#include "TianoCommon.h"\r
+#include "GenFdImage.h"\r
+#include "GenFvImage.h"\r
+#include "ParseInf.h"\r
+\r
+//\r
+// Global declaration\r
+//\r
+UINTN ValidLineNum = 0;\r
+\r
+UINTN NumFvFiles = 0;\r
+static UINT64 LastAddress = 0;\r
+\r
+CHAR8 **TokenStr;\r
+CHAR8 **OrgStrTokPtr;\r
+\r
+FDINFO *FdInfo;\r
+FDINFO *OrgFdInfoPtr;\r
+\r
+FVINFO **FvInfo;\r
+FVINFO **OrgFvInfoPtr;\r
+\r
+//\r
+// Global function declarations\r
+//\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+ IN UINT64 FvBaseAddress,\r
+ IN CHAR8 *FvFileName,\r
+ IN CHAR8 *FdFileName\r
+ );\r
+\r
+INTN\r
+CompareItems (\r
+ IN const VOID *Arg1,\r
+ IN const VOID *Arg2\r
+ )\r
+/*++\r
+Description:\r
+\r
+ This function is used by qsort to sort the Fv list based on FvBaseAddress\r
+\r
+Input:\r
+ Arg1\r
+ Arg2\r
+\r
+Return:\r
+\r
+ None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: Arg1 - add argument and description to function comment\r
+// GC_TODO: Arg2 - add argument and description to function comment\r
+{\r
+ if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+ return 1;\r
+ } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+ return -1;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+VOID\r
+BuildTokenList (\r
+ IN CHAR8 *Token\r
+ )\r
+/*++\r
+Description:\r
+\r
+ This function builds the token list in an array which will be parsed later\r
+\r
+Input:\r
+ Token String,\r
+\r
+Return:\r
+\r
+ None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: Token - add argument and description to function comment\r
+{\r
+\r
+ strcpy (*TokenStr, Token);\r
+ TokenStr++;\r
+}\r
+\r
+VOID\r
+TrimLine (\r
+ IN CHAR8 *Line\r
+ )\r
+/*++\r
+Description:\r
+\r
+ This function cleans up the line by removing all whitespace and \r
+ comments\r
+\r
+Input:\r
+\r
+ Line String,\r
+\r
+Return:\r
+ None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: Line - add argument and description to function comment\r
+{\r
+ CHAR8 TmpLine[FILE_NAME_SIZE];\r
+ CHAR8 c;\r
+ CHAR8 *Ptr0;\r
+ UINTN i;\r
+ UINTN j;\r
+\r
+ //\r
+ // Change '#' to '//' for Comment style\r
+ //\r
+ // if((Ptr0=strchr(Line, '#')) != NULL) {\r
+ //\r
+ if ((Ptr0 = strstr (Line, "//")) != NULL) {\r
+ Line[Ptr0 - Line] = 0;\r
+ }\r
+\r
+ i = j = 0;\r
+\r
+ while ((c = Line[i]) != 0) {\r
+ if ((c != ' ') && (c != '\t') && (c != '\n')) {\r
+ TmpLine[j++] = c;\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ TmpLine[j] = 0;\r
+ strcpy (Line, TmpLine);\r
+}\r
+\r
+VOID\r
+ValidLineCount (\r
+ IN FILE *Fp\r
+ )\r
+/*++\r
+\r
+Description:\r
+\r
+ This function calculated number of valid lines in a input file.\r
+ \r
+Input:\r
+\r
+ Fp Pointer to a file handle which has been opened.\r
+\r
+Return:\r
+\r
+ None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: Fp - add argument and description to function comment\r
+{\r
+ CHAR8 Buff[FILE_NAME_SIZE];\r
+\r
+ while (fgets (Buff, sizeof (Buff), Fp)) {\r
+ TrimLine (Buff);\r
+ if (Buff[0] == 0) {\r
+ continue;\r
+ }\r
+\r
+ ValidLineNum++;\r
+ }\r
+}\r
+\r
+VOID\r
+ParseInputFile (\r
+ IN FILE *Fp\r
+ )\r
+/*++\r
+ \r
+Description:\r
+\r
+ This function parses the input file and tokenize the string\r
+ \r
+Input:\r
+\r
+ Fp Pointer to a file handle which has been opened.\r
+ \r
+Return:\r
+\r
+ None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: Fp - add argument and description to function comment\r
+{\r
+ CHAR8 *Token;\r
+ CHAR8 Buff[FILE_NAME_SIZE];\r
+ CHAR8 OrgLine[FILE_NAME_SIZE];\r
+ CHAR8 Str[FILE_NAME_SIZE];\r
+ CHAR8 Delimit[] = "=";\r
+\r
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
+ strcpy (OrgLine, Buff);\r
+ TrimLine (Buff);\r
+\r
+ if (Buff[0] == 0) {\r
+ continue;\r
+ }\r
+\r
+ Token = strtok (Buff, Delimit);\r
+\r
+ while (Token != NULL) {\r
+ strcpy (Str, Token);\r
+ BuildTokenList (Str);\r
+ Token = strtok (NULL, Delimit);\r
+ }\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeComps (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Description:\r
+\r
+ This function intializes the relevant global variable which is being\r
+ used to store the information retrieved from INF file.\r
+ \r
+Input:\r
+\r
+ None\r
+\r
+Return:\r
+\r
+ EFI_STATUS\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ UINTN Index;\r
+\r
+ FdInfo = malloc (sizeof (FDINFO));\r
+\r
+ if (FdInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrgFdInfoPtr = FdInfo;\r
+\r
+ FvInfo = malloc (sizeof (int) * NumFvFiles);\r
+\r
+ if (FvInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrgFvInfoPtr = FvInfo;\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ *FvInfo = malloc (sizeof (FVINFO));\r
+\r
+ if (*FvInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ memset (*FvInfo, 0, sizeof (FVINFO));\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitializeInFileInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Description:\r
+\r
+ This function intializes the relevant global variable which is being\r
+ used to store the information retrieved from INF file.\r
+\r
+Input:\r
+\r
+ NONE\r
+\r
+Return:\r
+\r
+ NONE\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+{\r
+ UINTN OptionFlag;\r
+ UINT64 StringValue;\r
+\r
+ OptionFlag = 0;\r
+ TokenStr = OrgStrTokPtr;\r
+\r
+ while (*TokenStr != NULL) {\r
+ if (stricmp (*TokenStr, "[options]") == 0) {\r
+ OptionFlag = 1;\r
+ }\r
+\r
+ if (OptionFlag) {\r
+ if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {\r
+ *TokenStr++;\r
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
+ printf ("\nERROR: Cannot determine the FV base address.");\r
+ return ;\r
+ }\r
+ (*FvInfo)->FvBaseAddress = StringValue;\r
+ } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {\r
+ *TokenStr++;\r
+ strcpy ((*FvInfo)->FvFile, *TokenStr);\r
+ }\r
+ }\r
+\r
+ TokenStr++;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+GetFvRelatedInfoFromInfFile (\r
+ IN CHAR8 *FileName\r
+ )\r
+/*++\r
+ \r
+Description:\r
+\r
+ This function reads the input file, parse it and create a list of tokens\r
+ which is parsed and used, to intialize the data related to Firmware Volume.\r
+ \r
+Input:\r
+\r
+ FileName FileName which needed to be read to parse data\r
+\r
+Return:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: FileName - add argument and description to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+ UINTN Index;\r
+\r
+ Fp = fopen (FileName, "r");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("Error in opening %s file\n", FileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ ValidLineCount (Fp);\r
+\r
+ if (ValidLineNum == 0) {\r
+ printf ("\nFile doesn't contain any valid informations");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));\r
+ memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));\r
+ OrgStrTokPtr = TokenStr;\r
+\r
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
+ *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
+ memset (*TokenStr, 0, FILE_NAME_SIZE);\r
+ TokenStr++;\r
+ }\r
+\r
+ *TokenStr = NULL;\r
+ TokenStr = OrgStrTokPtr;\r
+ fseek (Fp, 0L, SEEK_SET);\r
+\r
+ ParseInputFile (Fp);\r
+ InitializeInFileInfo ();\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+WriteFwBinary (\r
+ IN CHAR8 *FileName,\r
+ IN UINT64 StartAddress,\r
+ IN UINT64 Size,\r
+ IN UINT8 *Buffer\r
+ )\r
+/*++\r
+ \r
+Description:\r
+\r
+ This function reads the input file, parse it and create a list of tokens\r
+ which is parsed and used, to intialize the data related to Firmware Volume.\r
+ \r
+Input:\r
+\r
+ FileName FileName which needed to be read to parse data\r
+ StartAddress This will set the file position.\r
+ Size Size in bytes needed to be written\r
+ Buffer Buffer needed to e written\r
+\r
+Return:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: FileName - add argument and description to function comment\r
+// GC_TODO: StartAddress - add argument and description to function comment\r
+// GC_TODO: Size - add argument and description to function comment\r
+// GC_TODO: Buffer - add argument and description to function comment\r
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+ UINTN NumByte;\r
+\r
+ Fp = fopen (FileName, "a+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Error in opening file %s ", FileName);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ fseek (Fp, (UINTN) StartAddress, SEEK_SET);\r
+ NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);\r
+\r
+ //\r
+ // Check to ensure that buffer has been copied successfully\r
+ //\r
+ if (NumByte != Size) {\r
+ printf ("\nERROR: Error in copying the buffer into file");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+ IN UINT64 FvBaseAddress,\r
+ IN CHAR8 *FvFileName,\r
+ IN CHAR8 *FdFileName\r
+ )\r
+/*++\r
+ \r
+Description:\r
+\r
+ This function reads the input file, parse it and create a list of tokens\r
+ which is parsed and used, to intialize the data related to Firmware Volume.\r
+ \r
+Input:\r
+\r
+ FvBaseAddress Base Address. This info is retrieved from INF file\r
+ FvFileName InputFileName\r
+ FdFileName Output File Name\r
+\r
+Return:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: FvBaseAddress - add argument and description to function comment\r
+// GC_TODO: FvFileName - add argument and description to function comment\r
+// GC_TODO: FdFileName - add argument and description to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+ UINT64 FileSize;\r
+ UINT64 NumByteRead;\r
+ UINT64 PadByteSize;\r
+ UINTN Index;\r
+ UINT64 BaseAddress;\r
+ UINT8 *Buffer;\r
+ EFI_STATUS Status;\r
+ static UINT64 StartAddress = 0;\r
+\r
+ Fp = fopen (FvFileName, "r+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Error in opening file %s", FvFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ BaseAddress = FdInfo->FdBaseAddress;\r
+\r
+ //\r
+ // Check if Base Address of Firmware Volume falls below the Base Address\r
+ // Firmware Device, if yes, then abort this process.\r
+ //\r
+ if (FvBaseAddress < BaseAddress) {\r
+ printf ("\nERROR: Firmware Volume Base Address falls below Firmware Device Address.\n");\r
+ return EFI_ABORTED;\r
+ }\r
+ //\r
+ // Check if there are any hole between two Firmware Volumes. If any hole\r
+ // exists, fill the hole with PadByte data.\r
+ //\r
+ if (FvBaseAddress > LastAddress) {\r
+ PadByteSize = (FvBaseAddress - LastAddress);\r
+ Buffer = malloc ((UINTN) PadByteSize);\r
+\r
+ for (Index = 0; Index < PadByteSize; Index++) {\r
+ *Buffer = FdInfo->PadValue;\r
+ Buffer++;\r
+ }\r
+\r
+ Buffer -= PadByteSize;\r
+ Status = WriteFwBinary (FdFileName, StartAddress, (UINT64) PadByteSize, Buffer);\r
+\r
+ if (Buffer) {\r
+ free (Buffer);\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error in writing the binary image to file");\r
+ return Status;\r
+ }\r
+\r
+ StartAddress += PadByteSize;\r
+ LastAddress += PadByteSize;\r
+ }\r
+ //\r
+ // Proceed with next Firmware Volume updates\r
+ //\r
+ FileSize = _filelength (fileno (Fp));\r
+\r
+ if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {\r
+ printf (\r
+ "\nERROR:Unable to update Firmware Device. File %s is larger than \\r
+ available space.",\r
+ FvFileName\r
+ );\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Buffer = malloc ((UINTN) FileSize);\r
+\r
+ if (Buffer == NULL) {\r
+ printf ("Error in allocating buffer to read specific file\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
+\r
+ Status = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);\r
+\r
+ if (Buffer) {\r
+ free ((VOID *) Buffer);\r
+ }\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error in writing the binary image to file");\r
+ return Status;\r
+ }\r
+\r
+ StartAddress += NumByteRead;\r
+ LastAddress += FileSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CleanUpMemory (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Description:\r
+\r
+ This function cleans up any allocated buffer\r
+ \r
+Input:\r
+\r
+ NONE\r
+\r
+Return:\r
+ \r
+ NONE\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+{\r
+ UINTN Index;\r
+\r
+ if (FdInfo) {\r
+ free (FdInfo);\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ if (FvInfo) {\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ if (*FvInfo) {\r
+ free (*FvInfo);\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+ free (FvInfo);\r
+ }\r
+}\r
+\r
+GEN_FD_IMAGE_API\r
+EFI_STATUS\r
+GenerateFdImage (\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Size,\r
+ IN UINT8 PadByte,\r
+ IN CHAR8 *OutFile,\r
+ IN CHAR8 **FileList\r
+ )\r
+/*++\r
+ \r
+Description:\r
+\r
+ This function reads the input file, parse it and create a list of tokens\r
+ which is parsed and used, to intialize the data related to Firmware Volume.\r
+ \r
+Input:\r
+\r
+ BaseAddress Base Address for this Firmware Device\r
+ Size, Total Size of the Firmware Device\r
+ PadByte Pad byte data\r
+ OutFile Output File Name\r
+ FileList File List pointer to INF file names.\r
+\r
+Return:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO: BaseAddress - add argument and description to function comment\r
+// GC_TODO: Size - add argument and description to function comment\r
+// GC_TODO: PadByte - add argument and description to function comment\r
+// GC_TODO: OutFile - add argument and description to function comment\r
+// GC_TODO: FileList - add argument and description to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN PadSize;\r
+ UINTN FileSize;\r
+ CHAR8 **InFile;\r
+ FILE *Fp;\r
+ UINT8 *Buffer;\r
+ UINTN NumByte;\r
+\r
+ //\r
+ // Ensure, if there are any previous Firmware Device exists,\r
+ // If yes, make it to 0 bytes\r
+ //\r
+ if ((Fp = fopen (OutFile, "w")) != NULL) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ InFile = FileList;\r
+\r
+ while (*InFile != NULL) {\r
+ NumFvFiles++;\r
+ InFile++;\r
+ }\r
+\r
+ InitializeComps ();\r
+\r
+ //\r
+ // Restore the orginal pointers\r
+ //\r
+ FvInfo = OrgFvInfoPtr;\r
+ InFile = FileList;\r
+\r
+ while (*InFile != NULL) {\r
+ strcpy ((*FvInfo)->FvInfoFile, *InFile);\r
+ Status = GetFvRelatedInfoFromInfFile (*InFile);\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error occurred in processsing INF file");\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ InFile++;\r
+ FvInfo++;\r
+ }\r
+\r
+ FdInfo->FdSize = Size;\r
+ FdInfo->FdBaseAddress = BaseAddress;\r
+ FdInfo->PadValue = PadByte;\r
+ FvInfo = OrgFvInfoPtr;\r
+ strcpy (FdInfo->OutFileName, OutFile);\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ Status = GenerateFvImage ((*FvInfo)->FvInfoFile);\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ //\r
+ // Sort the Firmware Volume informations. Firmware Volume with lower\r
+ // base addresses will be processed first and hiher base address one\r
+ // will be processed later.\r
+ //\r
+ qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);\r
+\r
+ LastAddress = (*FvInfo)->FvBaseAddress;\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ Status = BuildFirmwareDeviceBinaryFromFwVolumes (\r
+ (*FvInfo)->FvBaseAddress,\r
+ (*FvInfo)->FvFile,\r
+ FdInfo->OutFileName\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+ //\r
+ // Check if any space left after copying data from all Firmware Volumes\r
+ // If yes, then fill those location with PadValue.\r
+ //\r
+ if ((FdInfo->FdBaseAddress + Size) > LastAddress) {\r
+\r
+ PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);\r
+ Buffer = malloc (PadSize);\r
+\r
+ if (Buffer == NULL) {\r
+ CleanUpMemory ();\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < PadSize; Index++) {\r
+ *Buffer = FdInfo->PadValue;\r
+ Buffer++;\r
+ }\r
+\r
+ Buffer -= PadSize;\r
+\r
+ Fp = fopen (OutFile, "a+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Opening file %s", OutFile);\r
+ CleanUpMemory ();\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ FileSize = _filelength (fileno (Fp));\r
+ fseek (Fp, FileSize, SEEK_SET);\r
+ NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);\r
+\r
+ if (Buffer) {\r
+ free (Buffer);\r
+ }\r
+\r
+ fclose (Fp);\r
+\r
+ if (NumByte != (sizeof (UINT8) * PadSize)) {\r
+ printf ("\nERROR: Copying data from buffer to File %s ", OutFile);\r
+ CleanUpMemory ();\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ //\r
+ // Clean up all the memory which has been allocated so far.\r
+ //\r
+ CleanUpMemory ();\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ GenFdImageExe.c\r
+\r
+Abstract:\r
+\r
+ This contains all code necessary to build the GenFdImage.exe utility.\r
+ This utility relies heavily on the GenFdImage Lib. Definitions for both \r
+ can be found in the GenFdImage Utility Specification, review draft.\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standards\r
+//\r
+//\r
+// Include files\r
+//\r
+#include "GenFdImage.h"\r
+#include "GenFdImageExe.h"\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "%s, EFI 2.0 Firmware Device Image Generation Utility. ""Version %i.%i, %s.\n\n",\r
+ UTILITY_NAME,\r
+ UTILITY_MAJOR_VERSION,\r
+ UTILITY_MINOR_VERSION,\r
+ UTILITY_DATE\r
+ );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "Usage: %s -B BaseAddress -S Size -F FillByte"" [-I FvInfFileName] -O OutputFileName \n",\r
+ UTILITY_NAME\r
+ );\r
+ printf (" Where:\n");\r
+ printf ("\tBaseAddress is the starting address of the FD Image\n\n");\r
+ printf ("\tSize is the size of the FD Image.\n\n");\r
+ printf ("\tFillByte is the desired value of free space in the Image\n\n");\r
+ printf ("\tFvInfFileName is the name of an FV Image description file.\n\n");\r
+ printf ("\tOutputFileName is the desired output file name.\n\n");\r
+}\r
+\r
+EFI_STATUS\r
+main (\r
+ IN INTN argc,\r
+ IN CHAR8 **argv\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This utility uses GenFdImage.lib to build a Firmware Device Image\r
+ which will include several Firmware Volume Images.\r
+\r
+Arguments:\r
+\r
+ Base Address Base Address of the firmware volume..\r
+ Size Size of the Firmware Volume\r
+ FillByte The byte value which would be needed to pad\r
+ between various Firmware Volumes\r
+ FvInfFile Fv inf file\r
+ OutputFileName The name of output file which would be created\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS No error conditions detected.\r
+ EFI_INVALID_PARAMETER One or more of the input parameters is invalid.\r
+ EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable. \r
+ Most commonly this will be memory allocation or \r
+ file creation.\r
+ EFI_LOAD_ERROR GenFvImage.lib could not be loaded.\r
+ EFI_ABORTED Error executing the GenFvImage lib.\r
+\r
+--*/\r
+// GC_TODO: argc - add argument and description to function comment\r
+// GC_TODO: argv - add argument and description to function comment\r
+{\r
+ UINTN Index;\r
+ UINTN FvFilesCount;\r
+\r
+ UINT8 i;\r
+\r
+ UINT64 StartAddress;\r
+ UINT64 Size;\r
+ UINT64 FillByteVal;\r
+\r
+ CHAR8 **FvInfFileList;\r
+ CHAR8 **OrgFvInfFileList;\r
+ CHAR8 OutputFileName[_MAX_PATH];\r
+\r
+ EFI_STATUS Status;\r
+\r
+ INTN arg_counter;\r
+\r
+ //\r
+ // Echo for makefile debug\r
+ //\r
+ printf ("\n\n");\r
+ for (arg_counter = 0; arg_counter < argc; arg_counter++) {\r
+ printf ("%s ", argv[arg_counter]);\r
+ }\r
+\r
+ printf ("\n\n");\r
+\r
+ //\r
+ // Display utility information\r
+ //\r
+ PrintUtilityInfo ();\r
+\r
+ //\r
+ // Verify the correct number of arguments\r
+ //\r
+ if (argc < MIN_ARGS) {\r
+ printf ("ERROR: missing 1 or more input arguments.\n\n");\r
+ PrintUsage ();\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Initialize variables\r
+ //\r
+ StartAddress = 0;\r
+ Size = 0;\r
+ FillByteVal = 0;\r
+ FvFilesCount = 0;\r
+\r
+ for (i = 1; i < argc; i++) {\r
+ if (stricmp (argv[i], "-I") == 0) {\r
+ FvFilesCount++;\r
+ }\r
+ }\r
+\r
+ FvInfFileList = malloc (sizeof (UINTN) * (FvFilesCount + 1));\r
+ if (FvInfFileList == NULL) {\r
+ printf ("ERROR: allocating memory for FvInfFileList in -main- function.\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ memset (FvInfFileList, 0, sizeof (UINTN) * (FvFilesCount + 1));\r
+\r
+ OrgFvInfFileList = FvInfFileList;\r
+\r
+ for (Index = 0; Index < FvFilesCount; Index++) {\r
+ *FvInfFileList = malloc (_MAX_PATH);\r
+ memset (*FvInfFileList, 0, _MAX_PATH);\r
+ FvInfFileList++;\r
+ }\r
+\r
+ strcpy (OutputFileName, "");\r
+\r
+ //\r
+ // Parse the command line arguments\r
+ //\r
+ FvInfFileList = OrgFvInfFileList;\r
+\r
+ for (i = 1; i < argc; i += 2) {\r
+ //\r
+ // Make sure argument pair begin with - or /\r
+ //\r
+ if (argv[i][0] != '-' && argv[i][0] != '/') {\r
+ PrintUsage ();\r
+ printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Make sure argument specifier is only one letter\r
+ //\r
+ if (argv[i][2] != 0) {\r
+ PrintUsage ();\r
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Determine argument to read\r
+ //\r
+ switch (argv[i][1]) {\r
+\r
+ case 'I':\r
+ case 'i':\r
+ if ((FvInfFileList != NULL) && (strlen (*FvInfFileList) == 0)) {\r
+ strcpy (*FvInfFileList, argv[i + 1]);\r
+ FvInfFileList++;\r
+ } else {\r
+ printf ("ERROR: FvInfFile Name is more than specifed.\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case 'O':\r
+ case 'o':\r
+ if (strlen (OutputFileName) == 0) {\r
+ strcpy (OutputFileName, argv[i + 1]);\r
+ } else {\r
+ PrintUsage ();\r
+ printf ("ERROR: OutputFileName may only be specified once.\n");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case 'B':\r
+ case 'b':\r
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &StartAddress);\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Bad FD Image start address specified");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case 'S':\r
+ case 's':\r
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &Size);\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Bad FD Image size specified");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ case 'F':\r
+ case 'f':\r
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &FillByteVal);\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Not a recognized Fill Byte value");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ PrintUsage ();\r
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);\r
+ return EFI_INVALID_PARAMETER;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Call the GenFdImage Lib\r
+ //\r
+ FvInfFileList = OrgFvInfFileList;\r
+\r
+ Status = GenerateFdImage (\r
+ StartAddress,\r
+ Size,\r
+ (UINT8) FillByteVal,\r
+ OutputFileName,\r
+ FvInfFileList\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ switch (Status) {\r
+\r
+ case EFI_INVALID_PARAMETER:\r
+ printf ("\nERROR: Invalid parameter passed to GenFdImage lib.\n");\r
+ break;\r
+\r
+ case EFI_ABORTED:\r
+ printf ("\nERROR: Error detected while creating the file image.\n");\r
+ break;\r
+\r
+ case EFI_OUT_OF_RESOURCES:\r
+ printf ("\nERROR: GenFdImage Lib could not allocate required resources.\n");\r
+ break;\r
+\r
+ case EFI_VOLUME_CORRUPTED:\r
+ printf ("\nERROR: No base address was specified \n");\r
+ break;\r
+\r
+ case EFI_LOAD_ERROR:\r
+ printf ("\nERROR: An error occurred loading one of the required support Lib.\n");\r
+ break;\r
+\r
+ default:\r
+ printf ("\nERROR: GenFdImage lib returned unknown status %X.\n", Status);\r
+ break;\r
+ }\r
+\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ GenFdImageExe.h\r
+\r
+Abstract:\r
+\r
+ Definitions for the Boot Strap File Image generation utility.\r
+\r
+--*/\r
+\r
+#ifndef _EFI_GEN_FD_IMAGE_EXE_H\r
+#define _EFI_GEN_FD_IMAGE_EXE_H\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME "GenFdImage"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 0\r
+#define UTILITY_DATE __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MIN_ARGS 10\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ GenFdImageLib.C\r
+\r
+Abstract:\r
+\r
+ This file contains the functions required to generate \r
+ the Firmware Device\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standards\r
+//\r
+//\r
+// Include file in build\r
+//\r
+#include "GenFdImage.h"\r
+\r
+//\r
+// Global declarations\r
+//\r
+UINTN ValidLineNum = 0;\r
+UINTN NumFvFiles = 0;\r
+\r
+static UINT64 LastAddress = 0;\r
+\r
+CHAR8 **TokenStr;\r
+CHAR8 **OrgStrTokPtr;\r
+\r
+FDINFO *FdInfo;\r
+FDINFO *OrgFdInfoPtr;\r
+\r
+FVINFO **FvInfo;\r
+FVINFO **OrgFvInfoPtr;\r
+\r
+//\r
+// Internal Functions\r
+//\r
+INTN\r
+CompareItems (\r
+ IN const VOID *Arg1,\r
+ IN const VOID *Arg2\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function is used by qsort to sort the Fv list based on FvBaseAddress \r
+\r
+Arguments:\r
+\r
+ Arg1\r
+ Arg2\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+// GC_TODO: Arg1 - add argument and description to function comment\r
+// GC_TODO: Arg2 - add argument and description to function comment\r
+{\r
+ if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+ return 1;\r
+ } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+ return -1;\r
+ } else {\r
+ return 0;\r
+ }\r
+}\r
+\r
+VOID\r
+BuildTokenList (\r
+ IN CHAR8 *Token\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function builds the token list in an array which will be parsed later\r
+\r
+Arguments:\r
+\r
+ Token String,\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ strcpy (*TokenStr, Token);\r
+ TokenStr++;\r
+}\r
+\r
+VOID\r
+TrimLine (\r
+ IN CHAR8 *Line\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function cleans up the line by removing all whitespace and \r
+ comments.\r
+\r
+Arguments:\r
+\r
+ Line String,\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ CHAR8 TmpLine[FILE_NAME_SIZE];\r
+ CHAR8 c;\r
+ CHAR8 *Ptr0;\r
+\r
+ UINTN i;\r
+ UINTN j;\r
+\r
+ //\r
+ // Change '#' to '//' for Comment style\r
+ //\r
+ // if((Ptr0=strchr(Line, '#')) != NULL) {\r
+ //\r
+ if ((Ptr0 = strstr (Line, "//")) != NULL) {\r
+ Line[Ptr0 - Line] = 0;\r
+ }\r
+\r
+ i = 0;\r
+ j = 0;\r
+ while ((c = Line[i]) != 0) {\r
+ if ((c != ' ') && (c != '\t') && (c != '\n')) {\r
+ TmpLine[j++] = c;\r
+ }\r
+\r
+ i++;\r
+ }\r
+\r
+ TmpLine[j] = 0;\r
+ strcpy (Line, TmpLine);\r
+}\r
+\r
+VOID\r
+ValidLineCount (\r
+ IN FILE *Fp\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function calculates number of valid lines in a input file.\r
+ \r
+Arguments:\r
+\r
+ Fp Pointer to a file handle which has been opened.\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ CHAR8 Buff[FILE_NAME_SIZE];\r
+\r
+ while (fgets (Buff, sizeof (Buff), Fp)) {\r
+ TrimLine (Buff);\r
+ if (Buff[0] == 0) {\r
+ continue;\r
+ }\r
+\r
+ ValidLineNum++;\r
+ }\r
+}\r
+\r
+VOID\r
+ParseInputFile (\r
+ IN FILE *Fp\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ This function parses the input file and tokenizes the string\r
+ \r
+Arguments:\r
+\r
+ Fp Pointer to a file handle which has been opened.\r
+ \r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ CHAR8 *Token;\r
+ CHAR8 Buff[FILE_NAME_SIZE];\r
+ CHAR8 OrgLine[FILE_NAME_SIZE];\r
+ CHAR8 Str[FILE_NAME_SIZE];\r
+ CHAR8 Delimit[] = "=";\r
+\r
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
+ strcpy (OrgLine, Buff);\r
+ TrimLine (Buff);\r
+\r
+ if (Buff[0] == 0) {\r
+ continue;\r
+ }\r
+\r
+ Token = strtok (Buff, Delimit);\r
+\r
+ while (Token != NULL) {\r
+ strcpy (Str, Token);\r
+ BuildTokenList (Str);\r
+ Token = strtok (NULL, Delimit);\r
+ }\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeComps (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function intializes the relevant global variable \r
+ used to store the information retrieved from the INF file.\r
+ \r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+\r
+--*/\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ UINTN Index;\r
+\r
+ FdInfo = malloc (sizeof (FDINFO));\r
+\r
+ if (FdInfo == NULL) {\r
+ printf ("ERROR: allocating memory (struct FDINFO) in"" function InitializeComps.\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrgFdInfoPtr = FdInfo;\r
+\r
+ FvInfo = malloc (sizeof (INTN) * NumFvFiles);\r
+\r
+ if (FvInfo == NULL) {\r
+ printf ("ERROR: allocating memory (INTN * NumFvFiles) in"" function InitializeComps.\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ OrgFvInfoPtr = FvInfo;\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ *FvInfo = malloc (sizeof (FVINFO));\r
+\r
+ if (*FvInfo == NULL) {\r
+ printf ("ERROR: allocating memory (FVINFO) in"" function InitializeComps.\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ memset (*FvInfo, 0, sizeof (FVINFO));\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitializeInFileInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function intializes the relevant global variable \r
+ used to store the information retrieved from the INF file.\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN OptionFlag;\r
+\r
+ UINT64 StringValue;\r
+\r
+ OptionFlag = 0;\r
+ TokenStr = OrgStrTokPtr;\r
+\r
+ while (*TokenStr != NULL) {\r
+ if (stricmp (*TokenStr, "[options]") == 0) {\r
+ OptionFlag = 1;\r
+ }\r
+\r
+ if (OptionFlag) {\r
+ if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {\r
+ *TokenStr++;\r
+ if (AsciiStringToUint64 (\r
+ *TokenStr,\r
+ FALSE,\r
+ &StringValue\r
+ ) != EFI_SUCCESS) {\r
+ printf ("\nERROR: Cannot determine the FV base address.");\r
+ return ;\r
+ }\r
+ (*FvInfo)->FvBaseAddress = StringValue;\r
+ } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {\r
+ *TokenStr++;\r
+ strcpy ((*FvInfo)->FvFile, *TokenStr);\r
+ }\r
+ }\r
+\r
+ TokenStr++;\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+GetFvRelatedInfoFromInfFile (\r
+ IN CHAR8 *FileName\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ This function reads the input file, parses it and create a list of tokens\r
+ which are parsed and used, to intialize the data related to the Firmware \r
+ Volume.\r
+ \r
+Arguments:\r
+\r
+ FileName FileName which needed to be read to parse data\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+\r
+ UINTN Index;\r
+\r
+ Fp = fopen (FileName, "r");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("Error in opening %s file\n", FileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ ValidLineCount (Fp);\r
+\r
+ if (ValidLineNum == 0) {\r
+ printf ("\nFile doesn't contain any valid informations");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));\r
+ memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));\r
+ OrgStrTokPtr = TokenStr;\r
+\r
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
+ *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
+ memset (*TokenStr, 0, FILE_NAME_SIZE);\r
+ TokenStr++;\r
+ }\r
+\r
+ *TokenStr = NULL;\r
+ TokenStr = OrgStrTokPtr;\r
+ fseek (Fp, 0L, SEEK_SET);\r
+\r
+ ParseInputFile (Fp);\r
+ InitializeInFileInfo ();\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+WriteFwBinary (\r
+ IN CHAR8 *FileName,\r
+ IN UINT64 StartAddress,\r
+ IN UINT64 Size,\r
+ IN UINT8 *Buffer\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ This function reads the input file, parses it and creates a list of tokens\r
+ which are parsed and used to intialize the data related to the Firmware \r
+ Volume.\r
+ \r
+Arguments:\r
+\r
+ FileName FileName which needed to be read to parse data\r
+ StartAddress This will set the file position.\r
+ Size Size in bytes needed to be written\r
+ Buffer Buffer needed to e written\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+\r
+ UINTN NumByte;\r
+\r
+ Fp = fopen (FileName, "a+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Error in opening file %s ", FileName);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ fseek (Fp, (UINTN) StartAddress, SEEK_SET);\r
+ NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);\r
+\r
+ //\r
+ // Check to ensure that buffer has been copied successfully\r
+ //\r
+ if (NumByte != Size) {\r
+ printf ("\nERROR: Error in copying the buffer into file");\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+ IN UINT64 FvBaseAddress,\r
+ IN CHAR8 *FvFileName,\r
+ IN CHAR8 *FdFileName\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ This function reads the input file, parses it and creates a list of tokens\r
+ which are parsed and used to intialize the data related to the Firmware \r
+ Volume.\r
+ \r
+Arguments:\r
+\r
+ FvBaseAddress Base Address. This info is retrieved from INF file\r
+ FvFileName InputFileName\r
+ FdFileName Output File Name\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ FILE *Fp;\r
+\r
+ UINT64 FileSize;\r
+ UINT64 NumByteRead;\r
+ UINT64 PadByteSize;\r
+ UINT64 BaseAddress;\r
+\r
+ UINTN Index;\r
+\r
+ UINT8 *Buffer;\r
+\r
+ EFI_STATUS Status;\r
+\r
+ static UINT64 StartAddress = 0;\r
+\r
+ Fp = fopen (FvFileName, "r+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Error in opening file %s", FvFileName);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ BaseAddress = FdInfo->FdBaseAddress;\r
+\r
+ //\r
+ // Check if Base Address of Firmware Volume falls below the Base Address\r
+ // Firmware Device, if yes, then abort this process.\r
+ //\r
+ if (FvBaseAddress < BaseAddress) {\r
+ printf ("\nERROR: Firmware Volume Base Address falls below Firmware ""Device Address.\n");\r
+ return EFI_ABORTED;\r
+ }\r
+ //\r
+ // Check if there are any holes between two Firmware Volumes. If any holes\r
+ // exist, fill the hole with PadByted data.\r
+ //\r
+ if (FvBaseAddress > LastAddress) {\r
+ PadByteSize = (FvBaseAddress - LastAddress);\r
+ Buffer = malloc ((UINTN) PadByteSize);\r
+ if (Buffer == NULL) {\r
+ printf ("ERROR: allocating (Buffer) memory in"" function BuildFirmwareDeviceBinaryFromFwVolumes.\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < PadByteSize; Index++) {\r
+ *Buffer = FdInfo->PadValue;\r
+ Buffer++;\r
+ }\r
+\r
+ Buffer -= PadByteSize;\r
+ Status = WriteFwBinary (\r
+ FdFileName,\r
+ StartAddress,\r
+ (UINT64) PadByteSize,\r
+ Buffer\r
+ );\r
+\r
+ if (Buffer) {\r
+ free (Buffer);\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error in writing the binary image to file");\r
+ return Status;\r
+ }\r
+\r
+ StartAddress += PadByteSize;\r
+ LastAddress += PadByteSize;\r
+ }\r
+ //\r
+ // Proceed with next Firmware Volume updates\r
+ //\r
+ FileSize = _filelength (fileno (Fp));\r
+\r
+ if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {\r
+ printf (\r
+ "\nERROR:Unable to update Firmware Device. File %s is larger than \\r
+ available space.",\r
+ FvFileName\r
+ );\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Buffer = malloc ((UINTN) FileSize);\r
+\r
+ if (Buffer == NULL) {\r
+ printf ("Error in allocating buffer to read specific file\n");\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
+\r
+ Status = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);\r
+\r
+ if (Buffer) {\r
+ free ((VOID *) Buffer);\r
+ }\r
+\r
+ if (Fp) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error in writing the binary image to file");\r
+ return Status;\r
+ }\r
+\r
+ StartAddress += NumByteRead;\r
+ LastAddress += FileSize;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CleanUpMemory (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function cleans up any allocated buffer\r
+ \r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+ \r
+ None\r
+\r
+--*/\r
+{\r
+ UINTN Index;\r
+\r
+ if (FdInfo) {\r
+ free (FdInfo);\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ if (FvInfo) {\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ if (*FvInfo) {\r
+ free (*FvInfo);\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+ free (FvInfo);\r
+ }\r
+}\r
+\r
+EFI_STATUS\r
+GenerateFdImage (\r
+ IN UINT64 BaseAddress,\r
+ IN UINT64 Size,\r
+ IN UINT8 PadByte,\r
+ IN CHAR8 *OutFile,\r
+ IN CHAR8 **FileList\r
+ )\r
+/*++\r
+ \r
+Routine Description:\r
+\r
+ This function reads the input file, parses it and creates a list of tokens\r
+ which are parsed and used to intialize the data related to the Firmware \r
+ Volume.\r
+ \r
+Arguments:\r
+\r
+ BaseAddress Base Address for this Firmware Device\r
+ Size, Total Size of the Firmware Device\r
+ PadByte Pad byte data\r
+ OutFile Output File Name\r
+ FileList File List pointer to INF file names.\r
+\r
+Returns:\r
+\r
+ EFI_STATUS\r
+ \r
+--*/\r
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_ABORTED - add return value to function comment\r
+// GC_TODO: EFI_SUCCESS - add return value to function comment\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ UINTN Index;\r
+ UINTN PadSize;\r
+ UINTN FileSize;\r
+ UINTN NumByte;\r
+\r
+ CHAR8 **InFile;\r
+\r
+ FILE *Fp;\r
+\r
+ UINT8 *Buffer;\r
+\r
+ //\r
+ // If any previous Firmware Device existed,\r
+ // make it to 0 bytes\r
+ //\r
+ if ((Fp = fopen (OutFile, "w")) != NULL) {\r
+ fclose (Fp);\r
+ }\r
+\r
+ InFile = FileList;\r
+\r
+ while (*InFile != NULL) {\r
+ NumFvFiles++;\r
+ InFile++;\r
+ }\r
+\r
+ InitializeComps ();\r
+\r
+ //\r
+ // Restore the orginal pointers\r
+ //\r
+ FvInfo = OrgFvInfoPtr;\r
+ InFile = FileList;\r
+\r
+ while (*InFile != NULL) {\r
+ strcpy ((*FvInfo)->FvInfoFile, *InFile);\r
+ Status = GetFvRelatedInfoFromInfFile (*InFile);\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ printf ("\nERROR: Error occurred in processsing INF file");\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ InFile++;\r
+ FvInfo++;\r
+ }\r
+\r
+ FdInfo->FdSize = Size;\r
+ FdInfo->FdBaseAddress = BaseAddress;\r
+ FdInfo->PadValue = PadByte;\r
+ FvInfo = OrgFvInfoPtr;\r
+ strcpy (FdInfo->OutFileName, OutFile);\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ Status = GenerateFvImage ((*FvInfo)->FvInfoFile);\r
+\r
+ if (Status != EFI_SUCCESS) {\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+\r
+ FvInfo = OrgFvInfoPtr;\r
+\r
+ //\r
+ // Sort the Firmware Volume information. Firmware Volume with lower\r
+ // base addresses will be processed first and higher base address one\r
+ // will be processed later.\r
+ //\r
+ qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);\r
+\r
+ LastAddress = (*FvInfo)->FvBaseAddress;\r
+\r
+ for (Index = 0; Index < NumFvFiles; Index++) {\r
+ Status = BuildFirmwareDeviceBinaryFromFwVolumes (\r
+ (*FvInfo)->FvBaseAddress,\r
+ (*FvInfo)->FvFile,\r
+ FdInfo->OutFileName\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ CleanUpMemory ();\r
+ return Status;\r
+ }\r
+\r
+ FvInfo++;\r
+ }\r
+ //\r
+ // Check if any space left after copying data from all Firmware Volumes\r
+ // If yes, then fill those location with PadValue.\r
+ //\r
+ if ((FdInfo->FdBaseAddress + Size) > LastAddress) {\r
+\r
+ PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);\r
+ Buffer = malloc (PadSize);\r
+\r
+ if (Buffer == NULL) {\r
+ printf ("\nERROR: allocating PadSize memory in function GenerateFdImage.\n");\r
+ CleanUpMemory ();\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < PadSize; Index++) {\r
+ *Buffer = FdInfo->PadValue;\r
+ Buffer++;\r
+ }\r
+\r
+ Buffer -= PadSize;\r
+\r
+ Fp = fopen (OutFile, "a+b");\r
+\r
+ if (Fp == NULL) {\r
+ printf ("\nERROR:Opening file %s", OutFile);\r
+ CleanUpMemory ();\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ FileSize = _filelength (fileno (Fp));\r
+ fseek (Fp, FileSize, SEEK_SET);\r
+ NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);\r
+\r
+ if (Buffer) {\r
+ free (Buffer);\r
+ }\r
+\r
+ fclose (Fp);\r
+\r
+ if (NumByte != (sizeof (UINT8) * PadSize)) {\r
+ printf ("\nERROR: Copying data from buffer to File %s ", OutFile);\r
+ CleanUpMemory ();\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ //\r
+ // Clean up all the memory which has been allocated so far.\r
+ //\r
+ CleanUpMemory ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC) \\r
+ -I "$(TIANO_TOOLS_SOURCE)\GenFvImage"\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=GenFdImage\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_LIB = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).lib\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.c"\r
+TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.h" \\r
+ "$(TARGET_SOURCE_DIR)\GenFdImage.h" \\r
+ "$(COMMON_SOURCE)\ParseInf.h" \\r
+ "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"\r
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \\r
+ "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \\r
+ "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"\r
+\r
+TARGET_LIB_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageLib.c"\r
+TARGET_LIB_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImage.h" \\r
+ "$(TIANO_TOOLS_SOURCE)\GenFvImage\GenFvImage.h" \\r
+ "$(COMMON_SOURCE)\ParseInf.h" \\r
+ "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"\r
+TARGET_LIB_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \\r
+ "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \\r
+ "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"\r
+\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_LIB) $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_LIB)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)\r
+\r
+#\r
+# Build LIB\r
+#\r
+\r
+$(TARGET_LIB): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj $(TARGET_LIB_LIBS)\r
+ $(LIB) $(LIB_FLAGS) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj /OUT:$(TARGET_LIB)\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj: $(TARGET_LIB_SOURCE) $(TARGET_LIB_INCLUDE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_LIB_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj\r
+\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* > NUL\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999-2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+ GenTEImage.c\r
+ \r
+Abstract:\r
+\r
+ Utility program to shrink a PE32 image down by replacing\r
+ the DOS, PE, and optional headers with a minimal header.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiUtilityMsgs.h"\r
+\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_NAME "GenTEImage"\r
+#define UTILITY_VERSION "v0.11"\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH 256\r
+#define DEFAULT_OUTPUT_EXTENSION ".te"\r
+\r
+//\r
+// Use this to track our command-line options and globals\r
+//\r
+struct {\r
+ INT8 OutFileName[MAX_PATH];\r
+ INT8 InFileName[MAX_PATH];\r
+ INT8 Verbose;\r
+ INT8 Dump;\r
+} mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+ UINT16 Value;\r
+ INT8 *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP mMachineTypes[] = {\r
+ EFI_IMAGE_MACHINE_IA32,\r
+ "IA32",\r
+ EFI_IMAGE_MACHINE_IA64,\r
+ "IA64",\r
+ EFI_IMAGE_MACHINE_EBC,\r
+ "EBC",\r
+ 0,\r
+ NULL\r
+};\r
+\r
+static STRING_LOOKUP mSubsystemTypes[] = {\r
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+ "EFI application",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+ "EFI boot service driver",\r
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+ "EFI runtime driver",\r
+ 0,\r
+ NULL\r
+};\r
+//\r
+// Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[]\r
+ );\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+ INT8 *FileName,\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ );\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+ INT8 *InFileName,\r
+ INT8 *OutFileName\r
+ );\r
+\r
+static\r
+void\r
+DumpImage (\r
+ INT8 *FileName\r
+ );\r
+\r
+static\r
+INT8 *\r
+GetMachineTypeStr (\r
+ UINT16 MachineType\r
+ );\r
+\r
+static\r
+INT8 *\r
+GetSubsystemTypeStr (\r
+ UINT16 SubsystemType\r
+ );\r
+\r
+main (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+\r
+ Argv - standard C main() argument list\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ INT8 *Ext;\r
+ UINT32 Status;\r
+\r
+ SetUtilityName (UTILITY_NAME);\r
+ //\r
+ // Parse the command line arguments\r
+ //\r
+ if (ParseCommandLine (Argc, Argv)) {\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // If dumping an image, then do that and quit\r
+ //\r
+ if (mOptions.Dump) {\r
+ DumpImage (mOptions.InFileName);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Determine the output filename. Either what they specified on\r
+ // the command line, or the first input filename with a different extension.\r
+ //\r
+ if (!mOptions.OutFileName[0]) {\r
+ strcpy (mOptions.OutFileName, mOptions.InFileName);\r
+ //\r
+ // Find the last . on the line and replace the filename extension with\r
+ // the default\r
+ //\r
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
+ Ext--\r
+ )\r
+ ;\r
+ //\r
+ // If dot here, then insert extension here, otherwise append\r
+ //\r
+ if (*Ext != '.') {\r
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+ }\r
+\r
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+ }\r
+ //\r
+ // Make sure we don't have the same filename for input and output files\r
+ //\r
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Process the file\r
+ //\r
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
+Finish:\r
+ Status = GetUtilityStatus ();\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+ INT8 *InFileName,\r
+ INT8 *OutFileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Process a PE32 EFI file.\r
+\r
+Arguments:\r
+ \r
+ InFileName - the file name pointer to the input file\r
+ OutFileName - the file name pointer to the output file\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - the process has been finished successfully\r
+ STATUS_ERROR - error occured during the processing\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ FILE *InFptr;\r
+ FILE *OutFptr;\r
+ UINT16 MachineType;\r
+ UINT16 SubSystem;\r
+ EFI_TE_IMAGE_HEADER TEImageHeader;\r
+ UINT32 PESigOffset;\r
+ EFI_IMAGE_FILE_HEADER FileHeader;\r
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;\r
+ UINT32 BytesStripped;\r
+ UINT32 FileSize;\r
+ UINT8 *Buffer;\r
+ long SaveFilePosition;\r
+\r
+ InFptr = NULL;\r
+ OutFptr = NULL;\r
+ Buffer = NULL;\r
+ Status = STATUS_ERROR;\r
+\r
+ //\r
+ // Try to open the input file\r
+ //\r
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Double-check the file to make sure it's what we expect it to be\r
+ //\r
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Initialize our new header\r
+ //\r
+ memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
+\r
+ //\r
+ // Seek to the end to get the file size\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ FileSize = ftell (InFptr);\r
+ fseek (InFptr, 0, SEEK_SET);\r
+\r
+ //\r
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
+ // offset (from the start of the file) to the PE signature, which always\r
+ // follows the MSDOS stub. The PE signature is immediately followed by the\r
+ // COFF file header.\r
+ //\r
+ //\r
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
+ goto Finish;\r
+ }\r
+\r
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // We should now be at the COFF file header. Read it in and verify it's\r
+ // of an image type we support.\r
+ //\r
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
+ goto Finish;\r
+ }\r
+\r
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {\r
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Calculate the total number of bytes we're going to strip off. The '4' is for the\r
+ // PE signature PE\0\0. Then sanity check the size.\r
+ //\r
+ BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;\r
+ if (BytesStripped >= FileSize) {\r
+ Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");\r
+ goto Finish;\r
+ }\r
+\r
+ if (BytesStripped &~0xFFFF) {\r
+ Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);\r
+ goto Finish;\r
+ }\r
+\r
+ TEImageHeader.StrippedSize = (UINT16) BytesStripped;\r
+\r
+ //\r
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
+ //\r
+ SaveFilePosition = ftell (InFptr);\r
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ //\r
+ // Fill in our new header with required data directory entries\r
+ //\r
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;\r
+ //\r
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);\r
+ //\r
+ // We're going to pack the subsystem into 1 byte. Make sure it fits\r
+ //\r
+ if (OptionalHeader32.Subsystem &~0xFF) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ InFileName,\r
+ NULL,\r
+ "image subsystem 0x%X cannot be packed into 1 byte",\r
+ (UINT32) OptionalHeader32.Subsystem\r
+ );\r
+ goto Finish;\r
+ }\r
+\r
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem;\r
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;\r
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+ }\r
+\r
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+ }\r
+ } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ //\r
+ // Rewind and re-read the optional header\r
+ //\r
+ fseek (InFptr, SaveFilePosition, SEEK_SET);\r
+ if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;\r
+ //\r
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);\r
+ //\r
+ // We're going to pack the subsystem into 1 byte. Make sure it fits\r
+ //\r
+ if (OptionalHeader64.Subsystem &~0xFF) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ InFileName,\r
+ NULL,\r
+ "image subsystem 0x%X cannot be packed into 1 byte",\r
+ (UINT32) OptionalHeader64.Subsystem\r
+ );\r
+ goto Finish;\r
+ }\r
+\r
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem;\r
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;\r
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+ }\r
+\r
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+ }\r
+ } else {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ InFileName,\r
+ "unsupported magic number 0x%X found in optional header",\r
+ (UINT32) OptionalHeader32.Magic\r
+ );\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Fill in the remainder of our new image header\r
+ //\r
+ TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
+ TEImageHeader.Machine = FileHeader.Machine;\r
+ //\r
+ // We're going to pack the number of sections into a single byte. Make sure it fits.\r
+ //\r
+ if (FileHeader.NumberOfSections &~0xFF) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ InFileName,\r
+ NULL,\r
+ "image's number of sections 0x%X cannot be packed into 1 byte",\r
+ (UINT32) FileHeader.NumberOfSections\r
+ );\r
+ goto Finish;\r
+ }\r
+\r
+ TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;\r
+\r
+ //\r
+ // Now open our output file\r
+ //\r
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Write the TE header\r
+ //\r
+ if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, "failed to write image header to output file", NULL);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Position into the input file, read the part we're not stripping, and\r
+ // write it out.\r
+ //\r
+ fseek (InFptr, BytesStripped, SEEK_SET);\r
+ Buffer = (UINT8 *) malloc (FileSize - BytesStripped);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, "application error", "failed to allocate memory");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {\r
+ Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");\r
+ goto Finish;\r
+ }\r
+\r
+ Status = STATUS_SUCCESS;\r
+\r
+Finish:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+ //\r
+ // Close the output file. If there was an error, delete the output file so\r
+ // that a subsequent build will rebuild it.\r
+ //\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ if (GetUtilityStatus () == STATUS_ERROR) {\r
+ remove (OutFileName);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free up our buffer\r
+ //\r
+ if (Buffer != NULL) {\r
+ free (Buffer);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+ INT8 *FileName,\r
+ FILE *Fptr,\r
+ UINT16 *MachineType,\r
+ UINT16 *SubSystem\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileName - GC_TODO: add argument description\r
+ Fptr - GC_TODO: add argument description\r
+ MachineType - GC_TODO: add argument description\r
+ SubSystem - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ /*++\r
+\r
+Routine Description:\r
+ \r
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+ PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+ Fptr File pointer to the already-opened PE32 file\r
+ MachineType Location to stuff the machine type of the PE32 file. This is needed\r
+ because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+ 0 success\r
+ non-zero otherwise\r
+\r
+--*/\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_FILE_HEADER FileHdr;\r
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+ UINT32 PESig;\r
+ STATUS Status;\r
+\r
+ Status = STATUS_ERROR;\r
+ //\r
+ // Position to the start of the file\r
+ //\r
+ fseek (Fptr, 0, SEEK_SET);\r
+ //\r
+ // Read the DOS header\r
+ //\r
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Check the magic number (0x5A4D)\r
+ //\r
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Position into the file and check the PE signature\r
+ //\r
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Check the PE signature in the header "PE\0\0"\r
+ //\r
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read the file header\r
+ //\r
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read the optional header so we can get the subsystem\r
+ //\r
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ *SubSystem = OptionalHdr.Subsystem;\r
+ if (mOptions.Verbose) {\r
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);\r
+ }\r
+ //\r
+ // Good to go\r
+ //\r
+ Status = STATUS_SUCCESS;\r
+Finish:\r
+ fseek (Fptr, 0, SEEK_SET);\r
+ return Status;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+ parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+ Argc - standard C main() argument count\r
+ Argv - standard C main() argument list\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS success\r
+ non-zero otherwise\r
+\r
+--*/\r
+// GC_TODO: ] - add argument and description to function comment\r
+{\r
+ //\r
+ // Clear out the options\r
+ //\r
+ memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+ //\r
+ // Skip over the program name\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+ //\r
+ // If no arguments, assume they want usage info\r
+ //\r
+ if (Argc == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Process until no more arguments\r
+ //\r
+ while ((Argc > 0) && ((Argv[0][0] == '-') || (Argv[0][0] == '/'))) {\r
+ //\r
+ // To simplify string comparisons, replace slashes with dashes\r
+ //\r
+ Argv[0][0] = '-';\r
+ if (stricmp (Argv[0], "-o") == 0) {\r
+ //\r
+ // Output filename specified with -o\r
+ // Make sure there's another parameter\r
+ //\r
+ if (Argc > 1) {\r
+ strcpy (mOptions.OutFileName, Argv[1]);\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "missing output file name with option");\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Argv++;\r
+ Argc--;\r
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+ //\r
+ // Help option\r
+ //\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ } else if (stricmp (Argv[0], "-v") == 0) {\r
+ //\r
+ // -v for verbose\r
+ //\r
+ mOptions.Verbose = 1;\r
+ } else if (stricmp (Argv[0], "-dump") == 0) {\r
+ //\r
+ // -dump for dumping an image\r
+ //\r
+ mOptions.Dump = 1;\r
+ } else {\r
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Next argument\r
+ //\r
+ Argv++;\r
+ Argc--;\r
+ }\r
+ //\r
+ // Better be one more arg for input file name\r
+ //\r
+ if (Argc == 0) {\r
+ Error (NULL, 0, 0, "input file name required", NULL);\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (Argc != 1) {\r
+ Error (NULL, 0, 0, Argv[1], "extra arguments on command line");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ strcpy (mOptions.InFileName, Argv[0]);\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ int Index;\r
+ static const char *Msg[] = {\r
+ UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",\r
+ " Generate a TE image from an EFI PE32 image",\r
+ " Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",\r
+ " [-e|-b] [FileName(s)]",\r
+ " where:",\r
+ " -v - for verbose output",\r
+ " -dump - to dump the input file to a text file",\r
+ " -h -? - for this help information",\r
+ " -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
+ " InFileName - name of the input PE32 file",\r
+ "",\r
+ NULL\r
+ };\r
+ for (Index = 0; Msg[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Msg[Index]);\r
+ }\r
+}\r
+\r
+static\r
+VOID\r
+DumpImage (\r
+ INT8 *FileName\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Dump a specified image information\r
+\r
+Arguments:\r
+ \r
+ FileName - File name pointer to the image to dump\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ FILE *InFptr;\r
+ EFI_TE_IMAGE_HEADER TEImageHeader;\r
+ INT8 *NamePtr;\r
+\r
+ //\r
+ // Open the input file\r
+ //\r
+ InFptr = NULL;\r
+\r
+ if ((InFptr = fopen (FileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, FileName, "failed to open input file for reading");\r
+ return ;\r
+ }\r
+\r
+ if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 0, FileName, "failed to read image header from input file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+ Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Dump the header\r
+ //\r
+ fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));\r
+ fprintf (stdout, " Signature: 0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);\r
+ NamePtr = GetMachineTypeStr (TEImageHeader.Machine);\r
+ fprintf (stdout, " Machine: 0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);\r
+ NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);\r
+ fprintf (stdout, " Subsystem: 0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);\r
+ fprintf (stdout, " Number of sections 0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);\r
+ fprintf (stdout, " Stripped size: 0x%04X\n", (UINT32) TEImageHeader.StrippedSize);\r
+ fprintf (stdout, " Entry point: 0x%08X\n", TEImageHeader.AddressOfEntryPoint);\r
+ fprintf (stdout, " Base of code: 0x%08X\n", TEImageHeader.BaseOfCode);\r
+ fprintf (stdout, " Data directories:\n");\r
+ fprintf (\r
+ stdout,\r
+ " %8X [%8X] RVA [size] of Base Relocation Directory\n",\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size\r
+ );\r
+ fprintf (\r
+ stdout,\r
+ " %8X [%8X] RVA [size] of Debug Directory\n",\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,\r
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size\r
+ );\r
+\r
+Finish:\r
+ if (InFptr != NULL) {\r
+ fclose (InFptr);\r
+ }\r
+}\r
+\r
+static\r
+INT8 *\r
+GetMachineTypeStr (\r
+ UINT16 MachineType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ MachineType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ int Index;\r
+\r
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {\r
+ if (mMachineTypes[Index].Value == MachineType) {\r
+ return mMachineTypes[Index].Name;\r
+ }\r
+ }\r
+\r
+ return "unknown";\r
+}\r
+\r
+static\r
+INT8 *\r
+GetSubsystemTypeStr (\r
+ UINT16 SubsystemType\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ SubsystemType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ int Index;\r
+\r
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {\r
+ if (mSubsystemTypes[Index].Value == SubsystemType) {\r
+ return mSubsystemTypes[Index].Name;\r
+ }\r
+ }\r
+\r
+ return "unknown";\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2002 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name:\r
+# \r
+# makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the GenTEImage utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = GenTEImage\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj \r
+\r
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+INC_DEPS = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h\r
+ \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ PeiRebaseExe.c\r
+\r
+Abstract:\r
+\r
+ This contains all code necessary to build the PeiRebase.exe utility.\r
+ This utility relies heavily on the PeiRebase DLL. Definitions for both\r
+ can be found in the PEI Rebase Utility Specification, review draft.\r
+\r
+--*/\r
+\r
+#include "PeiRebaseExe.h"\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "CommonLib.h"\r
+#include "ParseInf.h"\r
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)\r
+#include "FvLib.h"\r
+\r
+#include "EfiUtilityMsgs.h"\r
+\r
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;\r
+\r
+EFI_STATUS\r
+ReadHeader (\r
+ IN FILE *InputFile,\r
+ OUT UINT32 *FvSize,\r
+ OUT BOOLEAN *ErasePolarity\r
+ );\r
+\r
+int\r
+main (\r
+ int argc,\r
+ char **argv\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This utility relocates PEI XIP PE32s in a FV.\r
+\r
+Arguments:\r
+\r
+ argc - Number of command line arguments\r
+ argv[]:\r
+ BaseAddress The base address to use for rebasing the FV. The correct \r
+ format is a hex number preceded by 0x.\r
+ InputFileName The name of the input FV file.\r
+ OutputFileName The name of the output FV file.\r
+\r
+ Arguments come in pair in any order.\r
+ -I InputFileName \r
+ -O OutputFileName\r
+ -B BaseAddress \r
+\r
+Returns:\r
+\r
+ 0 No error conditions detected.\r
+ 1 One or more of the input parameters is invalid.\r
+ 2 A resource required by the utility was unavailable. \r
+ Most commonly this will be memory allocation or file creation.\r
+ 3 PeiRebase.dll could not be loaded.\r
+ 4 Error executing the PEI rebase.\r
+\r
+--*/\r
+{\r
+ UINT8 Index;\r
+ CHAR8 InputFileName[_MAX_PATH];\r
+ CHAR8 OutputFileName[_MAX_PATH];\r
+ EFI_PHYSICAL_ADDRESS BaseAddress;\r
+ BOOLEAN BaseAddressSet;\r
+ EFI_STATUS Status;\r
+ FILE *InputFile;\r
+ FILE *OutputFile;\r
+ UINT64 FvOffset;\r
+ UINT32 FileCount;\r
+ int BytesRead;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
+ UINT32 FvSize;\r
+ EFI_FFS_FILE_HEADER *CurrentFile;\r
+ BOOLEAN ErasePolarity;\r
+ EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;\r
+\r
+ ErasePolarity = FALSE;\r
+ //\r
+ // Set utility name for error/warning reporting purposes.\r
+ //\r
+ SetUtilityName (UTILITY_NAME);\r
+ //\r
+ // Verify the correct number of arguments\r
+ //\r
+ if (argc != MAX_ARGS) {\r
+ PrintUsage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Initialize variables\r
+ //\r
+ InputFileName[0] = 0;\r
+ OutputFileName[0] = 0;\r
+ BaseAddress = 0;\r
+ BaseAddressSet = FALSE;\r
+ FvOffset = 0;\r
+ FileCount = 0;\r
+ ErasePolarity = FALSE;\r
+ InputFile = NULL;\r
+ OutputFile = NULL;\r
+ FvImage = NULL;\r
+ //\r
+ // Parse the command line arguments\r
+ //\r
+ for (Index = 1; Index < MAX_ARGS; Index += 2) {\r
+ //\r
+ // Make sure argument pair begin with - or /\r
+ //\r
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Make sure argument specifier is only one letter\r
+ //\r
+ if (argv[Index][2] != 0) {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");\r
+ return STATUS_ERROR;\r
+ } \r
+ //\r
+ // Determine argument to read\r
+ //\r
+ switch (argv[Index][1]) {\r
+ case 'I':\r
+ case 'i':\r
+ if (strlen (InputFileName) == 0) {\r
+ strcpy (InputFileName, argv[Index + 1]);\r
+ } else {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");\r
+ return STATUS_ERROR;\r
+ }\r
+ break;\r
+\r
+ case 'O':\r
+ case 'o':\r
+ if (strlen (OutputFileName) == 0) {\r
+ strcpy (OutputFileName, argv[Index + 1]);\r
+ } else {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");\r
+ return STATUS_ERROR;\r
+ }\r
+ break;\r
+\r
+ case 'B':\r
+ case 'b':\r
+ if (!BaseAddressSet) {\r
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ BaseAddressSet = TRUE;\r
+ } else {\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");\r
+ return STATUS_ERROR;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ PrintUsage ();\r
+ Error (NULL, 0, 0, argv[Index], "unrecognized argument");\r
+ return STATUS_ERROR;\r
+ break;\r
+ }\r
+ }\r
+ //\r
+ // Open the file containing the FV\r
+ //\r
+ InputFile = fopen (InputFileName, "rb");\r
+ if (InputFile == NULL) {\r
+ Error (NULL, 0, 0, InputFileName, "could not open input file for reading");\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Determine size of FV\r
+ //\r
+ Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "could not parse the FV header", NULL);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Allocate a buffer for the FV image\r
+ //\r
+ FvImage = malloc (FvSize);\r
+ if (FvImage == NULL) {\r
+ Error (NULL, 0, 0, "application error", "memory allocation failed");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Read the entire FV to the buffer\r
+ //\r
+ BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
+ fclose (InputFile);\r
+ InputFile = NULL;\r
+ if ((unsigned int) BytesRead != FvSize) {\r
+ Error (NULL, 0, 0, InputFileName, "failed to read from file");\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Prepare to walk the FV image\r
+ //\r
+ InitializeFvLib (FvImage, FvSize);\r
+ //\r
+ // Get the first file\r
+ //\r
+ Status = GetNextFile (NULL, &CurrentFile);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Check if each file should be rebased\r
+ //\r
+ while (CurrentFile != NULL) {\r
+ //\r
+ // Rebase this file\r
+ //\r
+ CurrentFileBaseAddress = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);\r
+ Status = FfsRebase (CurrentFile, CurrentFileBaseAddress);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ switch (Status) {\r
+\r
+ case EFI_INVALID_PARAMETER:\r
+ Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);\r
+ break;\r
+\r
+ case EFI_ABORTED:\r
+ Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);\r
+ break;\r
+\r
+ case EFI_OUT_OF_RESOURCES:\r
+ Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);\r
+ break;\r
+\r
+ case EFI_NOT_FOUND:\r
+ Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);\r
+ break;\r
+\r
+ default:\r
+ Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);\r
+ break;\r
+ }\r
+\r
+ goto Finish;\r
+ }\r
+ //\r
+ // Get the next file\r
+ //\r
+ Status = GetNextFile (CurrentFile, &CurrentFile);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);\r
+ goto Finish;\r
+ }\r
+ }\r
+ //\r
+ // Open the output file\r
+ //\r
+ OutputFile = fopen (OutputFileName, "wb");\r
+ if (OutputFile == NULL) {\r
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file");\r
+ goto Finish;\r
+ }\r
+\r
+ if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {\r
+ Error (NULL, 0, 0, "failed to write to output file", 0);\r
+ goto Finish;\r
+ }\r
+\r
+Finish:\r
+ if (InputFile != NULL) {\r
+ fclose (InputFile);\r
+ }\r
+ //\r
+ // If we created an output file, and there was an error, remove it so\r
+ // subsequent builds will rebuild it.\r
+ //\r
+ if (OutputFile != NULL) {\r
+ if (GetUtilityStatus () == STATUS_ERROR) {\r
+ remove (OutputFileName);\r
+ }\r
+\r
+ fclose (OutputFile);\r
+ }\r
+\r
+ if (FvImage != NULL) {\r
+ free (FvImage);\r
+ }\r
+\r
+ return GetUtilityStatus ();\r
+}\r
+\r
+EFI_STATUS\r
+ReadHeader (\r
+ IN FILE *InputFile,\r
+ OUT UINT32 *FvSize,\r
+ OUT BOOLEAN *ErasePolarity\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function determines the size of the FV and the erase polarity. The \r
+ erase polarity is the FALSE value for file state.\r
+\r
+Arguments:\r
+\r
+ InputFile The file that contains the FV image.\r
+ FvSize The size of the FV.\r
+ ErasePolarity The FV erase polarity.\r
+ \r
+Returns:\r
+ \r
+ EFI_SUCCESS Function completed successfully.\r
+ EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.\r
+ EFI_ABORTED The function encountered an error.\r
+\r
+--*/\r
+{\r
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;\r
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap;\r
+ UINTN Signature[2];\r
+ UINTN BytesRead;\r
+ UINT32 Size;\r
+\r
+ BytesRead = 0;\r
+ Size = 0;\r
+ //\r
+ // Check input parameters\r
+ //\r
+ if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {\r
+ Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Read the header\r
+ //\r
+ fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+ BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+ Signature[0] = VolumeHeader.Signature;\r
+ Signature[1] = 0;\r
+\r
+ //\r
+ // Get erase polarity\r
+ //\r
+ if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {\r
+ *ErasePolarity = TRUE;\r
+ }\r
+\r
+ do {\r
+ fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+ BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+\r
+ if (BlockMap.NumBlocks != 0) {\r
+ Size += BlockMap.NumBlocks * BlockMap.BlockLength;\r
+ }\r
+\r
+ } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));\r
+\r
+ if (VolumeHeader.FvLength != Size) {\r
+ Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ *FvSize = Size;\r
+\r
+ rewind (InputFile);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",\r
+ UTILITY_NAME,\r
+ UTILITY_MAJOR_VERSION,\r
+ UTILITY_MINOR_VERSION,\r
+ UTILITY_DATE\r
+ );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",\r
+ UTILITY_NAME\r
+ );\r
+ printf (" Where:\n");\r
+ printf (" InputFileName is the name of the EFI FV file to rebase.\n");\r
+ printf (" OutputFileName is the desired output file name.\n");\r
+ printf (" BaseAddress is the FV base address to rebase agains.\n");\r
+ printf (" Argument pair may be in any order.\n\n");\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebase (\r
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ This function determines if a file is XIP and should be rebased. It will \r
+ rebase any PE32 sections found in the file using the base address.\r
+ \r
+Arguments:\r
+\r
+ FfsFile A pointer to Ffs file image.\r
+ BaseAddress The base address to use for rebasing the file image.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS The image was properly rebased.\r
+ EFI_INVALID_PARAMETER An input parameter is invalid.\r
+ EFI_ABORTED An error occurred while rebasing the input file image.\r
+ EFI_OUT_OF_RESOURCES Could not allocate a required resource.\r
+ EFI_NOT_FOUND No compressed sections could be found.\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ UINTN MemoryImagePointer;\r
+ UINTN MemoryImagePointerAligned;\r
+ EFI_PHYSICAL_ADDRESS ImageAddress;\r
+ UINT64 ImageSize;\r
+ EFI_PHYSICAL_ADDRESS EntryPoint;\r
+ UINT32 Pe32ImageSize;\r
+ UINT32 NewPe32BaseAddress;\r
+ UINTN Index;\r
+ EFI_FILE_SECTION_POINTER CurrentPe32Section;\r
+ EFI_FFS_FILE_STATE SavedState;\r
+ EFI_IMAGE_NT_HEADERS *PeHdr;\r
+ UINT32 *PeHdrSizeOfImage;\r
+ UINT32 *PeHdrChecksum;\r
+ UINT32 FoundCount;\r
+ EFI_TE_IMAGE_HEADER *TEImageHeader;\r
+ UINT8 *TEBuffer;\r
+ EFI_IMAGE_DOS_HEADER *DosHeader;\r
+ UINT8 FileGuidString[80];\r
+ UINT32 TailSize;\r
+ EFI_FFS_FILE_TAIL TailValue;\r
+\r
+ //\r
+ // Verify input parameters\r
+ //\r
+ if (FfsFile == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Convert the GUID to a string so we can at least report which file\r
+ // if we find an error.\r
+ //\r
+ PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+ } else {\r
+ TailSize = 0;\r
+ }\r
+ //\r
+ // Do some cursory checks on the FFS file contents\r
+ //\r
+ Status = VerifyFfsFile (FfsFile);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ //\r
+ // Check if XIP file type. If not XIP, don't rebase.\r
+ //\r
+ if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+ ) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ //\r
+ // Rebase each PE32 section\r
+ //\r
+ Status = EFI_SUCCESS;\r
+ FoundCount = 0;\r
+ for (Index = 1;; Index++) {\r
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ FoundCount++;\r
+\r
+ //\r
+ // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
+ //\r
+ NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);\r
+\r
+ //\r
+ // Initialize context\r
+ //\r
+ memset (&ImageContext, 0, sizeof (ImageContext));\r
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+ Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);\r
+ return Status;\r
+ }\r
+ //\r
+ // Allocate a buffer for the image to be loaded into.\r
+ //\r
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);\r
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
+ if (MemoryImagePointer == 0) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+ \r
+\r
+ ImageContext.ImageAddress = MemoryImagePointerAligned;\r
+\r
+ Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);\r
+ free ((VOID *) MemoryImagePointer);\r
+ return Status;\r
+ }\r
+\r
+ ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+ Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);\r
+ free ((VOID *) MemoryImagePointer);\r
+ return Status;\r
+ }\r
+\r
+ ImageAddress = ImageContext.ImageAddress;\r
+ ImageSize = ImageContext.ImageSize;\r
+ EntryPoint = ImageContext.EntryPoint;\r
+\r
+ if (ImageSize > Pe32ImageSize) {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "rebased image is larger than original PE32 image",\r
+ "0x%X > 0x%X, file %s",\r
+ ImageSize,\r
+ Pe32ImageSize,\r
+ FileGuidString\r
+ );\r
+ free ((VOID *) MemoryImagePointer);\r
+ return EFI_ABORTED;\r
+ }\r
+ //\r
+ // Since we may have updated the Codeview RVA, we need to insure the PE\r
+ // header indicates the image is large enough to contain the Codeview data\r
+ // so it will be loaded properly later if the PEIM is reloaded into memory...\r
+ //\r
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ } else {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "unknown machine type in PE32 image",\r
+ "machine type=0x%X, file=%s",\r
+ (UINT32) PeHdr->FileHeader.Machine,\r
+ FileGuidString\r
+ );\r
+ free ((VOID *) MemoryImagePointer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {\r
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;\r
+ if (*PeHdrChecksum) {\r
+ *PeHdrChecksum = 0;\r
+ }\r
+ }\r
+\r
+ memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);\r
+\r
+ free ((VOID *) MemoryImagePointer);\r
+\r
+ //\r
+ // Now update file checksum\r
+ //\r
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+ } else {\r
+ TailSize = 0;\r
+ }\r
+\r
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ SavedState = FfsFile->State;\r
+ FfsFile->IntegrityCheck.Checksum.File = 0;\r
+ FfsFile->State = 0;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *) FfsFile,\r
+ GetLength (FfsFile->Size) - TailSize\r
+ );\r
+ } else {\r
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+ }\r
+\r
+ FfsFile->State = SavedState;\r
+ }\r
+ //\r
+ // Update tail if present\r
+ //\r
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));\r
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+ }\r
+ }\r
+ //\r
+ // Now process TE sections\r
+ //\r
+ for (Index = 1;; Index++) {\r
+ Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+\r
+ FoundCount++;\r
+\r
+ //\r
+ // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
+ // by GenTEImage\r
+ //\r
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
+\r
+ NewPe32BaseAddress = ((UINT32) BaseAddress) +\r
+ (\r
+ (UINTN) CurrentPe32Section.Pe32Section +\r
+ sizeof (EFI_COMMON_SECTION_HEADER) +\r
+ sizeof (EFI_TE_IMAGE_HEADER) -\r
+ TEImageHeader->StrippedSize -\r
+ (UINTN) FfsFile\r
+ );\r
+\r
+ //\r
+ // Allocate a buffer to unshrink the image into.\r
+ //\r
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+ sizeof (EFI_TE_IMAGE_HEADER);\r
+ Pe32ImageSize += TEImageHeader->StrippedSize;\r
+ TEBuffer = (UINT8 *) malloc (Pe32ImageSize);\r
+ if (TEBuffer == NULL) {\r
+ Error (NULL, 0, 0, "failed to allocate memory", NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // Expand the image into our buffer and fill in critical fields in the DOS header\r
+ // Fill in fields required by the loader.\r
+ // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value\r
+ // itself.\r
+ //\r
+ memset (TEBuffer, 0, Pe32ImageSize);\r
+ DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;\r
+ DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
+ *(UINT32 *) (TEBuffer + 0x3C) = 0x40;\r
+ PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);\r
+ PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;\r
+ PeHdr->FileHeader.Machine = TEImageHeader->Machine;\r
+ PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;\r
+\r
+ //\r
+ // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and\r
+ // the 0x40 bytes for our DOS header.\r
+ //\r
+ PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));\r
+ PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+ PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;\r
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+ PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *\r
+ sizeof (EFI_IMAGE_SECTION_HEADER) - 12;\r
+\r
+ //\r
+ // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image\r
+ //\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)\r
+ ) {\r
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+ }\r
+\r
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||\r
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)\r
+ ) {\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {\r
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;\r
+ }\r
+ }\r
+ //\r
+ // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility\r
+ //\r
+ PeHdr->OptionalHeader.SectionAlignment = 0x10;\r
+\r
+ //\r
+ // Copy the rest of the image to its original offset\r
+ //\r
+ memcpy (\r
+ TEBuffer + TEImageHeader->StrippedSize,\r
+ (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),\r
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+ sizeof (EFI_TE_IMAGE_HEADER)\r
+ );\r
+\r
+ //\r
+ // Initialize context\r
+ //\r
+ memset (&ImageContext, 0, sizeof (ImageContext));\r
+ ImageContext.Handle = (VOID *) TEBuffer;\r
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+ Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);\r
+ free (TEBuffer);\r
+ return Status;\r
+ }\r
+ //\r
+ // Allocate a buffer for the image to be loaded into.\r
+ //\r
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
+ if (MemoryImagePointer == 0) {\r
+ Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);\r
+ free (TEBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+ \r
+\r
+ ImageContext.ImageAddress = MemoryImagePointerAligned;\r
+ Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);\r
+ free (TEBuffer);\r
+ free ((VOID *) MemoryImagePointer);\r
+ return Status;\r
+ }\r
+\r
+ ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+ Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);\r
+ free ((VOID *) MemoryImagePointer);\r
+ free (TEBuffer);\r
+ return Status;\r
+ }\r
+\r
+ ImageAddress = ImageContext.ImageAddress;\r
+ ImageSize = ImageContext.ImageSize;\r
+ EntryPoint = ImageContext.EntryPoint;\r
+\r
+ //\r
+ // Since we may have updated the Codeview RVA, we need to insure the PE\r
+ // header indicates the image is large enough to contain the Codeview data\r
+ // so it will be loaded properly later if the PEIM is reloaded into memory...\r
+ //\r
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+ } else {\r
+ Error (\r
+ NULL,\r
+ 0,\r
+ 0,\r
+ "unknown machine type in TE image",\r
+ "machine type=0x%X, file=%s",\r
+ (UINT32) PeHdr->FileHeader.Machine,\r
+ FileGuidString\r
+ );\r
+ free ((VOID *) MemoryImagePointer);\r
+ free (TEBuffer);\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {\r
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;\r
+ if (*PeHdrChecksum) {\r
+ *PeHdrChecksum = 0;\r
+ }\r
+ }\r
+\r
+ TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+ memcpy (\r
+ (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),\r
+ (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),\r
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+ sizeof (EFI_TE_IMAGE_HEADER)\r
+ );\r
+ free ((VOID *) MemoryImagePointer);\r
+ free (TEBuffer);\r
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+ } else {\r
+ TailSize = 0;\r
+ }\r
+ //\r
+ // Now update file checksum\r
+ //\r
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ SavedState = FfsFile->State;\r
+ FfsFile->IntegrityCheck.Checksum.File = 0;\r
+ FfsFile->State = 0;\r
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+ (UINT8 *) FfsFile,\r
+ GetLength (FfsFile->Size) - TailSize\r
+ );\r
+ } else {\r
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+ }\r
+\r
+ FfsFile->State = SavedState;\r
+ }\r
+ //\r
+ // Update tail if present\r
+ //\r
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));\r
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+ }\r
+ }\r
+ //\r
+ // If we found no files, then emit an error if no compressed sections either\r
+ //\r
+ if (FoundCount == 0) {\r
+ Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINT32 *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+ FileHandle - The handle to the PE/COFF file\r
+\r
+ FileOffset - The offset, in bytes, into the file to read\r
+\r
+ ReadSize - The number of bytes to read from the file starting at FileOffset\r
+\r
+ Buffer - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+ CHAR8 *Destination8;\r
+ CHAR8 *Source8;\r
+ UINT32 Length;\r
+\r
+ Destination8 = Buffer;\r
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+ Length = *ReadSize;\r
+ while (Length--) {\r
+ *(Destination8++) = *(Source8++);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ PeiRebaseExe.h\r
+\r
+Abstract:\r
+\r
+ Definitions for the PeiRebase exe utility.\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PEIM_FIXUP_EXE_H\r
+#define _EFI_PEIM_FIXUP_EXE_H\r
+\r
+#include "Efi2WinNt.h"\r
+#include "EfiFirmwareFileSystem.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME "PeiRebase"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS 7\r
+\r
+//\r
+// The file copy buffer size\r
+//\r
+#define FILE_COPY_BUFFER_SIZE 512\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// Internal function declarations\r
+//\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINT32 *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FileHandle - GC_TODO: add argument description\r
+ FileOffset - GC_TODO: add argument description\r
+ ReadSize - GC_TODO: add argument description\r
+ Buffer - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+FfsRebase (\r
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FfsFile - GC_TODO: add argument description\r
+ BaseAddress - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name:\r
+# \r
+# makefile\r
+# \r
+# Abstract:\r
+# \r
+# makefile for building the PeiRebase utility.\r
+# \r
+# Revision History\r
+# \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = PeiRebase\r
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\PeiRebase.exe\r
+TARGET_EXE_LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\PeiRebase.obj \r
+\r
+#\r
+# Compile each source file\r
+#\r
+$(TIANO_TOOLS_OUTPUT)\PeiRebase.obj : $(TARGET_SRC_DIR)\PeiRebaseExe.c $(INC_DEPS) $(TARGET_EXE_LIBS)\r
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\PeiRebaseExe.c /Fo$@\r
+\r
+#\r
+# Link the object files together\r
+#\r
+$(TARGET_EXE) : $(OBJECTS) $(TARGET_EXE_LIBS)\r
+ @echo LINKING\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2005 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = SecApResetVectorFixup\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+TARGET_EXE_SOURCE = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib \r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)\r
+\r
+clean:\r
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ SecApResetVectorFixup.c\r
+\r
+Abstract:\r
+\r
+ This utility is part of build process for IA32 Fvrecovery.fv whose total size\r
+ is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset \r
+ vector at the zero vector of Fv header.\r
+ \r
+ PEI FV after using the tool\r
+ \r
+ -------------------------\r
+ |zzz |\r
+ | |\r
+ | |\r
+ | FFS |\r
+ | |\r
+ | |\r
+ | |\r
+ |---------------------- |\r
+ | PAD |\r
+ | |\r
+ |.......................| --- \r
+ | | |\r
+ |xxx | | 128K \r
+ |---------------------- | | \r
+ | VTF (SEC) | |\r
+ ------------------------- ---\r
+ \r
+ 1. zzz --> Zero vector, which is beyond the 128K limited address space\r
+ 2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD\r
+ file area.\r
+ 3. After the build process ,the PAD guid is changed to a new GUID to avoid \r
+ the PAD definition confusing. If there is some problem, try to disable\r
+ UpdatePadFileGuid\r
+ \r
+ \r
+ \r
+--*/\r
+\r
+#include "SecApResetVectorFixup.h"\r
+\r
+\r
+EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };\r
+EFI_GUID NewFvPadFileNameGuid = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };\r
+\r
+//\r
+// jmp 0xf000:0xffd0 (0xFFFFFFD0)\r
+//\r
+UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "%s - Tiano IA32 SEC Ap Reset Vector Fixup Utility."" Version %i.%i\n\n",\r
+ UTILITY_NAME,\r
+ UTILITY_MAJOR_VERSION,\r
+ UTILITY_MINOR_VERSION\r
+ );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf ("Usage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);\r
+ printf (" Where:\n");\r
+ printf ("\tInputFvrecoveryFile - Name of the IA32 input Fvrecovery.fv file.\n");\r
+ printf ("\tOutputFvrecoveryFile - Name of the IA32 output Fvrecovery.fv file.\n");\r
+}\r
+\r
+\r
+VOID \r
+UpdatePadFileGuid (\r
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,\r
+ IN EFI_FFS_FILE_HEADER *FileHeader,\r
+ IN UINT32 FileLength,\r
+ IN OUT EFI_GUID *Guid\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Update the Pad File Guid to change it to other guid and update\r
+ the checksum\r
+\r
+Arguments:\r
+ FvHeader - EFI_FIRMWARE_VOLUME_HEADER \r
+ FileHeader - The FFS PAD file header.\r
+ FileLength - The FFS PAD file length.\r
+ Guid - The Guid to compare and if it is PAD Guid, update it to new Guid\r
+Returns:\r
+ VOID\r
+--*/\r
+\r
+{\r
+ if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
+ //\r
+ // Set new Pad file guid\r
+ // \r
+ memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));\r
+\r
+\r
+\r
+ FileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;\r
+ FileHeader->Attributes = 0;\r
+ //\r
+ // Fill in checksums and state, must be zero during checksum calculation.\r
+ //\r
+ FileHeader->IntegrityCheck.Checksum.Header = 0;\r
+ FileHeader->IntegrityCheck.Checksum.File = 0;\r
+ FileHeader->State = 0;\r
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+ if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);\r
+ } else {\r
+ FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+ }\r
+\r
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+\r
+ if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
+ FileHeader->State = (UINT8)~(FileHeader->State);\r
+ } \r
+ }\r
+ \r
+}\r
+\r
+\r
+STATUS\r
+main (\r
+ IN INTN argc,\r
+ IN CHAR8 **argv\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Main function.\r
+\r
+Arguments:\r
+\r
+ argc - Number of command line parameters.\r
+ argv - Array of pointers to parameter strings.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - Utility exits successfully.\r
+ STATUS_ERROR - Some error occurred during execution.\r
+\r
+--*/\r
+{\r
+ FILE *FpIn;\r
+ FILE *FpOut;\r
+ UINT32 FvrecoveryFileSize;\r
+ UINT8 *FileBuffer;\r
+ UINT8 *FileBufferRaw;\r
+ UINT64 FvLength;\r
+ UINT32 Offset;\r
+ UINT32 FileLength;\r
+ UINT32 FileOccupiedSize;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;\r
+ EFI_FFS_FILE_HEADER *FileHeader;\r
+ EFI_GUID *TempGuid;\r
+ UINT8 *FixPoint;\r
+ UINT32 TempResult;\r
+ UINT32 Index;\r
+ UINT32 IpiVector;\r
+\r
+ TempGuid = NULL;\r
+ SetUtilityName (UTILITY_NAME);\r
+\r
+ //\r
+ // Display utility information\r
+ //\r
+ PrintUtilityInfo ();\r
+\r
+ //\r
+ // Verify the correct number of arguments\r
+ //\r
+ if (argc != MAX_ARGS) {\r
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);\r
+ PrintUsage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Open the Input Fvrecovery.fv file\r
+ //\r
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {\r
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Get the Input Fvrecovery.fv file size\r
+ //\r
+ fseek (FpIn, 0, SEEK_END);\r
+ FvrecoveryFileSize = ftell (FpIn);\r
+ //\r
+ // Read the contents of input file to memory buffer\r
+ //\r
+ FileBuffer = NULL;\r
+ FileBufferRaw = NULL;\r
+ FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);\r
+ if (NULL == FileBufferRaw) {\r
+ Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);\r
+ fclose (FpIn);\r
+ return STATUS_ERROR;\r
+ }\r
+ TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);\r
+ FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);\r
+ fseek (FpIn, 0, SEEK_SET);\r
+ TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);\r
+ if (TempResult != FvrecoveryFileSize) {\r
+ Error (NULL, 0, 0, "Read input file error!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ fclose (FpIn);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Close the input Fvrecovery.fv file\r
+ //\r
+ fclose (FpIn);\r
+ //\r
+ // Find the pad FFS file\r
+ //\r
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;\r
+ FvLength = FvHeader->FvLength;\r
+ FileHeader = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);\r
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;\r
+ \r
+ while (Offset < FvLength) {\r
+ TempGuid = (EFI_GUID *)&(FileHeader->Name);\r
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
+ if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
+ break;\r
+ }\r
+ FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);\r
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;\r
+ }\r
+\r
+ if (Offset >= FvLength) {\r
+ Error (NULL, 0, 0, "No pad file found!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Find the position to place Ap reset vector, the offset\r
+ // between the position and the end of Fvrecovery.fv file\r
+ // should not exceed 128kB to prevent Ap reset vector from\r
+ // outside legacy E and F segment\r
+ //\r
+ FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
+ TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);\r
+ FixPoint +=TempResult;\r
+ if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {\r
+ Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR; \r
+ }\r
+ while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {\r
+ FixPoint += 0x1000;\r
+ }\r
+ FixPoint -= 0x1000;\r
+ if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {\r
+ Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR; \r
+ } \r
+ //\r
+ // Fix up Ap reset vector and calculate the IPI vector\r
+ //\r
+ for (Index = 0; Index < 5; Index++) {\r
+ FixPoint[Index] = ApResetVector[Index];\r
+ } \r
+ TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);\r
+ TempResult >>= 12;\r
+ IpiVector = TempResult & 0x0FF;\r
+ \r
+ \r
+ UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);\r
+\r
+ //\r
+ // Open the output Fvrecovery.fv file\r
+ //\r
+ if ((FpOut = fopen (argv[2], "w+b")) == NULL) {\r
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Write the output Fvrecovery.fv file\r
+ //\r
+ if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {\r
+ Error (NULL, 0, 0, "Write output file error!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR; \r
+ }\r
+ //\r
+ //\r
+ //\r
+ fseek (FpOut, -8, SEEK_END);\r
+ if ((fwrite (&IpiVector, 1, sizeof(UINT32), FpOut)) != sizeof(UINT32)) {\r
+ Error (NULL, 0, 0, "Write output file error!", NULL);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_ERROR;\r
+ } \r
+ //\r
+ // Close the output Fvrecovery.fv file\r
+ //\r
+ fclose (FpOut);\r
+ free ((VOID *)FileBufferRaw);\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ SecApResetVectorFixup.h\r
+\r
+Abstract:\r
+\r
+ Definitions for the SecApResetVectorFixup utility.\r
+\r
+--*/\r
+\r
+#ifndef _SEC_AP_RESET_VECTOR_FIXUP_H\r
+#define _SEC_AP_RESET_VECTOR_FIXUP_H\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "EfiCommon.h"\r
+#include "EfiImage.h"\r
+#include "EfiImageFormat.h"\r
+#include "EfiFirmwareFileSystem.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+#include "EfiUtilityMsgs.c"\r
+#include "CommonLib.h"\r
+\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME "SecApResetVectorFixup"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS 3\r
+#define BUF_SIZE (8 * 1024)\r
+\r
+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \\r
+ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
+\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+;\r
+\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME = SecFixup\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+TARGET_EXE_SOURCE = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj \r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)\r
+ $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)\r
+\r
+clean:\r
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ SecFixup.c\r
+\r
+Abstract:\r
+\r
+ This utility is part of build process for IA32 SEC FFS file.\r
+ \r
+ It fixup the reset vector data. The reset vector data binary file\r
+ will be wrapped as a RAW section and be located immediately after\r
+ the PE/TE section.\r
+\r
+ The SEC EXE file can be either PE or TE file.\r
+ \r
+--*/\r
+\r
+#include <stdio.h>\r
+\r
+#include "EfiCommon.h"\r
+#include "EfiImage.h"\r
+#include "EfiImageFormat.h"\r
+#include "EfiUtilityMsgs.c"\r
+\r
+#include "SecFixup.h"\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",\r
+ UTILITY_NAME,\r
+ UTILITY_MAJOR_VERSION,\r
+ UTILITY_MINOR_VERSION\r
+ );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ None\r
+\r
+--*/\r
+{\r
+ printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);\r
+ printf (" Where:\n");\r
+ printf ("\tSecExeFile - Name of the IA32 SEC EXE file.\n");\r
+ printf ("\tResetVectorDataFile - Name of the reset vector data binary file.\n");\r
+ printf ("\tOutputFileName - Name of the output file.\n\n");\r
+}\r
+\r
+STATUS\r
+main (\r
+ IN INTN argc,\r
+ IN CHAR8 **argv\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Main function.\r
+\r
+Arguments:\r
+\r
+ argc - Number of command line parameters.\r
+ argv - Array of pointers to parameter strings.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - Utility exits successfully.\r
+ STATUS_ERROR - Some error occurred during execution.\r
+\r
+--*/\r
+{\r
+ FILE *FpIn;\r
+\r
+ FILE *FpOut;\r
+ UINT32 AddressOfEntryPoint;\r
+ INT32 DestRel;\r
+ STATUS Status;\r
+ UINT32 SecFileSize;\r
+\r
+ SetUtilityName (UTILITY_NAME);\r
+\r
+ //\r
+ // Display utility information\r
+ //\r
+ PrintUtilityInfo ();\r
+\r
+ //\r
+ // Verify the correct number of arguments\r
+ //\r
+ if (argc != MAX_ARGS) {\r
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);\r
+ PrintUsage ();\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Open the SEC exe file\r
+ //\r
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {\r
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Get the entry point of the EXE file\r
+ //\r
+ Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);\r
+ if (Status != STATUS_SUCCESS) {\r
+ fclose (FpIn);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Get the SEC file size\r
+ //\r
+ fseek (FpIn, 0, SEEK_END);\r
+ SecFileSize = ftell (FpIn);\r
+\r
+ //\r
+ // Close the SEC file\r
+ //\r
+ fclose (FpIn);\r
+\r
+ //\r
+ // Open the reset vector data file\r
+ //\r
+ if ((FpIn = fopen (argv[2], "rb")) == NULL) {\r
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Open the output file\r
+ //\r
+ if ((FpOut = fopen (argv[3], "w+b")) == NULL) {\r
+ Error (NULL, 0, 0, "Unable to open file", argv[3]);\r
+ fclose (FpIn);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Copy the input file to the output file\r
+ //\r
+ if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {\r
+ fclose (FpIn);\r
+ fclose (FpOut);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Close the reset vector data file\r
+ //\r
+ fclose (FpIn);\r
+\r
+ //\r
+ // Fix the destination relative in the jmp instruction\r
+ // in the reset vector data structure\r
+ //\r
+ fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);\r
+ DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);\r
+ if (DestRel <= -65536) {\r
+ Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);\r
+ fclose (FpOut);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {\r
+ Error (NULL, 0, 0, "Failed to write to the output file", NULL);\r
+ fclose (FpOut);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Close the output file\r
+ //\r
+ fclose (FpOut);\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+GetEntryPoint (\r
+ IN FILE *ExeFile,\r
+ OUT UINT32 *EntryPoint\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Get the address of the entry point of a PE/TE file.\r
+\r
+Arguments:\r
+\r
+ PeFile - File pointer to the specified PE/TE file.\r
+ EntryPoint - Buffer for the address of the entry point to be returned.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - Function completed successfully.\r
+ STATUS_ERROR - Error occured.\r
+\r
+--*/\r
+// GC_TODO: ExeFile - add argument and description to function comment\r
+{\r
+ EFI_IMAGE_DOS_HEADER DosHeader;\r
+ EFI_IMAGE_NT_HEADERS32 NtHeader;\r
+ EFI_TE_IMAGE_HEADER TeHeader;\r
+\r
+ //\r
+ // Check if it is a TE file\r
+ //\r
+ fseek (ExeFile, 0, SEEK_SET);\r
+ //\r
+ // Attempt to read the TE header\r
+ //\r
+ if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {\r
+ if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+ if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {\r
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;\r
+ return STATUS_SUCCESS;\r
+ }\r
+ }\r
+ //\r
+ // Check if it is a PE file\r
+ //\r
+ fseek (ExeFile, 0, SEEK_SET);\r
+ //\r
+ // Attempt to read the DOS header\r
+ //\r
+ if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {\r
+ goto InvalidFile;\r
+ }\r
+ //\r
+ // Check the magic number\r
+ //\r
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+ goto InvalidFile;\r
+ }\r
+ //\r
+ // Position into the file and read the NT PE header\r
+ //\r
+ fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);\r
+ if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {\r
+ goto InvalidFile;\r
+ }\r
+ //\r
+ // Check the PE signature in the header\r
+ //\r
+ if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+ goto InvalidFile;\r
+ }\r
+ //\r
+ // Make sure the PE file is PE32 for IA32\r
+ //\r
+ if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||\r
+ NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+ ) {\r
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+ //\r
+ // Get the entry point from the optional header\r
+ //\r
+ *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;\r
+ return STATUS_SUCCESS;\r
+\r
+InvalidFile:\r
+ Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);\r
+ return STATUS_ERROR;\r
+}\r
+\r
+STATUS\r
+CopyFile (\r
+ FILE *FpIn,\r
+ FILE *FpOut\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Copy file.\r
+\r
+Arguments:\r
+\r
+ FpIn - File pointer to the source file.\r
+ FpOut - File pointer to the destination file.\r
+\r
+Returns:\r
+ STATUS_SUCCESS - Function completed successfully.\r
+ STATUS_ERROR - Error occured.\r
+\r
+--*/\r
+{\r
+ INTN FileSize;\r
+\r
+ INTN Offset;\r
+\r
+ INTN Length;\r
+ UINT8 Buffer[BUF_SIZE];\r
+\r
+ fseek (FpIn, 0, SEEK_END);\r
+ FileSize = ftell (FpIn);\r
+\r
+ fseek (FpIn, 0, SEEK_SET);\r
+ fseek (FpOut, 0, SEEK_SET);\r
+\r
+ Offset = 0;\r
+ while (Offset < FileSize) {\r
+ Length = sizeof (Buffer);\r
+ if (FileSize - Offset < Length) {\r
+ Length = FileSize - Offset;\r
+ }\r
+\r
+ if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {\r
+ Error (NULL, 0, 0, "Copy file error", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ Offset += Length;\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ \r
+ SecFixup.h\r
+\r
+Abstract:\r
+\r
+ Definitions for the SecFixup utility.\r
+\r
+--*/\r
+\r
+#ifndef _SEC_FIXUP_H\r
+#define _SEC_FIXUP_H\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME "SecFixup"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS 4\r
+\r
+#define DEST_REL_OFFSET 13\r
+#define BUF_SIZE (8 * 1024)\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ None\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that gets the entry point of a PE/TE file.\r
+//\r
+STATUS\r
+GetEntryPoint (\r
+ IN FILE *ExeFile,\r
+ OUT UINT32 *EntryPoint\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ ExeFile - GC_TODO: add argument description\r
+ EntryPoint - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that copies a file.\r
+//\r
+STATUS\r
+CopyFile (\r
+ FILE *FpIn,\r
+ FILE *FpOut\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ FpIn - GC_TODO: add argument description\r
+ FpOut - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=SplitFile\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\SplitFile.c"\r
+TARGET_EXE_INCLUDE = \r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+*/\r
+\r
+// GC_TODO: fix comment to start with /*++\r
+#include "stdio.h"\r
+#include "string.h"\r
+#include "stdlib.h"\r
+\r
+void\r
+helpmsg (\r
+ void\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ printf (\r
+ "SplitFile Filename Offset\n"" Filename = Input file to split\n"" Offset = offset at which to split file\n"\r
+ "\n\n""SplitFile will break a file in two pieces at the requested offset\n"\r
+ " outputting Filename1 and Filename2\n"\r
+ );\r
+}\r
+\r
+int\r
+main (\r
+ int argc,\r
+ char*argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+ argc - GC_TODO: add argument description\r
+ ] - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+ GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+ FILE *In;\r
+\r
+ FILE *Out1;\r
+\r
+ FILE *Out2;\r
+ char OutName1[512];\r
+ char OutName2[512];\r
+ unsigned long Index;\r
+ unsigned long splitpoint;\r
+ char CharC;\r
+\r
+ if (argc != 3) {\r
+ helpmsg ();\r
+ return -1;\r
+ }\r
+\r
+ In = fopen (argv[1], "rb");\r
+ if (In == NULL) {\r
+ printf ("Unable to open file \"%s\"\n", argv[1]);\r
+ return -1;\r
+ }\r
+\r
+ strncpy (OutName1, argv[1], 510);\r
+ strncpy (OutName2, argv[1], 510);\r
+ strcat (OutName1, "1");\r
+ strcat (OutName2, "2");\r
+\r
+ Out1 = fopen (OutName1, "wb");\r
+ if (Out1 == NULL) {\r
+ printf ("Unable to open file \"%s\"\n", OutName1);\r
+ return -1;\r
+ }\r
+\r
+ Out2 = fopen (OutName2, "wb");\r
+ if (Out2 == NULL) {\r
+ printf ("Unable to open file \"%s\"\n", OutName2);\r
+ return -1;\r
+ }\r
+\r
+ splitpoint = atoi (argv[2]);\r
+\r
+ for (Index = 0; Index < splitpoint; Index++) {\r
+ CharC = (char) fgetc (In);\r
+ if (feof (In)) {\r
+ break;\r
+ }\r
+\r
+ fputc (CharC, Out1);\r
+ }\r
+\r
+ for (;;) {\r
+ CharC = (char) fgetc (In);\r
+ if (feof (In)) {\r
+ break;\r
+ }\r
+\r
+ fputc (CharC, Out2);\r
+ }\r
+\r
+ fclose (In);\r
+ fclose (Out1);\r
+ fclose (Out2);\r
+\r
+ return 0;\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation. All rights reserved.\r
+#\r
+# This software and associated documentation (if any) is furnished under \r
+# a license and may only be used or copied in accordance with the terms \r
+# of the license. Except as permitted by such license, no part of this \r
+# software or documentation may be reproduced, stored in a retrieval \r
+# system, or transmitted in any form or by any means without the express \r
+# written consent of Intel Corporation.\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=Strip\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\Strip.c"\r
+TARGET_EXE_INCLUDE = \r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+ Strip.c\r
+\r
+Abstract:\r
+\r
+ Quick Exe2Bin equivalent.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <string.h>\r
+#include <malloc.h>\r
+\r
+int\r
+main (\r
+ int argc,\r
+ char *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Converts executable files to binary files.\r
+\r
+Arguments:\r
+\r
+ argc - Number of command line arguments\r
+ argv[] - Array of pointers to the command line arguments\r
+\r
+Returns:\r
+\r
+ Zero - Function completed successfully.\r
+ Non-zero - Function exited with errors. \r
+\r
+--*/\r
+{\r
+ FILE *InFile;\r
+ FILE *OutFile;\r
+ int Index;\r
+ int FileSize;\r
+ char *Buffer;\r
+ char *Ptrx;\r
+\r
+ if (argc < 3) {\r
+ printf ("Need more args, such as file name to convert and output name\n");\r
+ return -1;\r
+ }\r
+\r
+ InFile = fopen (argv[1], "rb");\r
+ OutFile = fopen (argv[2], "wb");\r
+\r
+ if (!InFile) {\r
+ printf ("no file, exit\n");\r
+ return -1;\r
+ }\r
+\r
+ if (OutFile == NULL) {\r
+ printf ("Unable to open output file.\n");\r
+ return -1;\r
+ }\r
+\r
+ fseek (InFile, 0, SEEK_END);\r
+ FileSize = ftell (InFile);\r
+\r
+ if (FileSize < 0x200) {\r
+ printf ("%d is not a legal size, exit\n", FileSize);\r
+ return -1;\r
+ }\r
+\r
+ fseek (InFile, 0, SEEK_SET);\r
+\r
+ Buffer = malloc (FileSize);\r
+ if (Buffer == NULL) {\r
+ printf ("Error: Out of resources.\n");\r
+ return -1;\r
+ }\r
+\r
+ fread (Buffer, 1, FileSize, InFile);\r
+\r
+ Ptrx = Buffer + 0x200;\r
+\r
+ Index = FileSize - 0x200;\r
+\r
+ fwrite (Ptrx, Index, 1, OutFile);\r
+\r
+ fclose (InFile);\r
+ fclose (OutFile);\r
+ free (Buffer);\r
+\r
+ return 0;\r
+}\r
--- /dev/null
+#/*++\r
+# \r
+# Copyright (c) 2001 Intel Corporation\r
+# \r
+# Module Name: makefile\r
+# \r
+# Abstract:\r
+# \r
+# This file is used to build the EFI utility.\r
+# \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=ZeroDebugData\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\ZeroDebugData.c"\r
+TARGET_EXE_INCLUDE =\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE)\r
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).*\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2001 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+ ZeroDebugData.c\r
+\r
+Abstract:\r
+ Zero the Debug Data Fields of Portable Executable (PE) format file.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+\r
+void\r
+PrintUsage (\r
+ void\r
+ )\r
+/*++\r
+Routine Description:\r
+ print usage of ZeroDebugData command\r
+\r
+Arguments:\r
+ None\r
+\r
+Returns:\r
+ None\r
+--*/\r
+// GC_TODO: void - add argument and description to function comment\r
+{\r
+ //\r
+ // print usage of command\r
+ //\r
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");\r
+}\r
+\r
+int\r
+ReadFromFile (\r
+ FILE *fp,\r
+ long offset,\r
+ void *buffer,\r
+ int size\r
+ )\r
+/*++\r
+Routine Description:\r
+ read data from a specified location of file\r
+\r
+Arguments:\r
+ fp - file pointer\r
+ offset - number of bytes from beginning of file\r
+ buffer - buffer used to store data\r
+ size - size of buffer\r
+\r
+Returns:\r
+ = 0 - Success\r
+ = -1 - Failed\r
+--*/\r
+{\r
+ //\r
+ // set file pointer to the specified location of file\r
+ //\r
+ if (fseek (fp, offset, SEEK_SET) != 0) {\r
+ printf ("Error: Cannot move the current location of the file.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // read data from the file\r
+ //\r
+ if (fread (buffer, size, 1, fp) != 1) {\r
+ printf ("Error: Cannot read data from the file.\n");\r
+ return -1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int\r
+ZeroDebugData (\r
+ FILE *fp,\r
+ FILE *fpData\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Zero the debug data fields of the file\r
+\r
+Arguments:\r
+\r
+ fp - file pointer\r
+ fpData - pointer to output file that ZeroDebugData progress is written to\r
+\r
+Returns:\r
+\r
+ = 0 - Success\r
+ = -1 - Failed\r
+\r
+--*/\r
+{\r
+ unsigned char header[4];\r
+ unsigned long offset;\r
+ unsigned long NumberOfRvaAndSizes;\r
+ unsigned int nvalue;\r
+ unsigned long lvalue;\r
+ unsigned long Size;\r
+ unsigned long Pointer;\r
+ unsigned char *Buffer;\r
+ unsigned long Index;\r
+\r
+ //\r
+ // read the header of file\r
+ //\r
+ if (ReadFromFile (fp, 0, header, 2) != 0) {\r
+ printf ("Error: open image file\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // "MZ" -- the header of image file (PE)\r
+ //\r
+ if (strncmp ((char *) header, "MZ", 2) != 0) {\r
+ printf ("Error: Invalid Image file.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // At location 0x3C, the stub has the file offset to the\r
+ // PE signature.\r
+ //\r
+ if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {\r
+ return -1;\r
+ }\r
+ //\r
+ // read the header of optional\r
+ //\r
+ if (ReadFromFile (fp, offset, header, 4) != 0) {\r
+ return -1;\r
+ }\r
+ //\r
+ // "PE\0\0" -- the signature of optional header\r
+ //\r
+ if (strncmp ((char *) header, "PE\0\0", 4) != 0) {\r
+ printf ("Error: Invalid PE format file.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // Add 16 to skip COFF file header, and get to optional header.\r
+ //\r
+ offset += 24;\r
+\r
+ //\r
+ // Check the magic field, 0x10B for PE32 and 0x20B for PE32+\r
+ //\r
+ if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {\r
+ return -1;\r
+ }\r
+ //\r
+ // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.\r
+ // Else it is 108.\r
+ //\r
+ switch (nvalue & 0xFFFF) {\r
+ case 0x10B:\r
+ offset += 92;\r
+ printf ("Info: Image is PE32. ");\r
+ break;\r
+\r
+ case 0x20B:\r
+ offset += 108;\r
+ printf ("Info: Image is PE32+. ");\r
+ break;\r
+\r
+ default:\r
+ printf ("Error: Magic value is unknown.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // get the value of NumberOfRvaAndSizes\r
+ //\r
+ if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {\r
+ printf ("Error: read NumberOfRvaAndSizes error.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes);\r
+ //\r
+ //\r
+ // Finding Debug Table, offset of Debug Table\r
+ // is 4 + 6 * 8 = 52.\r
+ //\r
+ if (NumberOfRvaAndSizes >= 7) {\r
+ if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {\r
+ return -1;\r
+ }\r
+ //\r
+ // Read the SizeOfData(16) and PointerToRawData(24)\r
+ //\r
+ if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) {\r
+ printf ("error: Size = %d\n", Size);\r
+ return -1;\r
+ }\r
+\r
+ printf ("Debug data: size = %xh, ", Size);\r
+ fprintf (fpData, "Debug data: size = %xh, ", Size);\r
+\r
+ if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) {\r
+ printf ("error: LoadOffset = %xh\n", Pointer);\r
+ return -1;\r
+ }\r
+ //\r
+ // printf ("LoadOffset = %xh, ", Pointer);\r
+ //\r
+ fprintf (fpData, "LoadOffset = %xh, ", Pointer);\r
+\r
+ if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) {\r
+ printf ("error: FileOffset = %xh\n", Pointer);\r
+ return -1;\r
+ }\r
+\r
+ printf ("FileOffset = %xh, ", Pointer);\r
+ fprintf (fpData, "FileOffset = %xh, \n", Pointer);\r
+\r
+ if ((lvalue != 0) && (Pointer != 0)) {\r
+ //\r
+ // prepare buffer\r
+ //\r
+ Buffer = malloc (Size + 1);\r
+ if (Buffer == NULL) {\r
+ printf ("Error: Cannot allocate memory.\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // set file pointer to the specified location of file\r
+ //\r
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {\r
+ printf ("Error: Cannot move the current location of the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+ //\r
+ // read data from PE file\r
+ //\r
+ if (fread (Buffer, Size, 1, fp) != 1) {\r
+ printf ("Error: Cannot read data from the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+ //\r
+ // write to data file\r
+ //\r
+ for (Index = 0; Index < Size;) {\r
+ fprintf (fpData, "%02x ", Buffer[Index]);\r
+\r
+ Index++;\r
+ if (Index % 8 == 0) {\r
+ fprintf (fpData, "\n");\r
+ }\r
+ }\r
+\r
+ fprintf (fpData, "\n");\r
+\r
+ //\r
+ // zero buffer and write back to PE file\r
+ //\r
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {\r
+ printf ("Error: Cannot move the current location of the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+\r
+ memset (Buffer, 0, Size);\r
+ if (fwrite (Buffer, Size, 1, fp) != 1) {\r
+ perror ("Error: Cannot write zero to the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+ //\r
+ // set file pointer to the specified location of file\r
+ //\r
+ if (fseek (fp, lvalue + 4, SEEK_SET) != 0) {\r
+ printf ("Error: Cannot move the current location of the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+\r
+ if (fwrite (Buffer, 4, 1, fp) != 1) {\r
+ perror ("Error: Cannot write zero to the file.\n");\r
+ free (Buffer);\r
+ return -1;\r
+ }\r
+\r
+ free (Buffer);\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int\r
+main (\r
+ int argc,\r
+ char *argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Prints the zero debug data of the PE file to the DebugData file.\r
+ Executes the ZeroDebugData function.\r
+\r
+Arguments:\r
+\r
+ argc - Standard C argument, number of command line arguments.\r
+ argv[] - Standard C argument, array of pointers to the input files,\r
+ such as the PE and DebugData files.\r
+\r
+Returns:\r
+\r
+ zero - success\r
+ nonzero - failure\r
+\r
+--*/\r
+{\r
+ FILE *fp;\r
+ FILE *fpData;\r
+ char DataFile[1024] = "";\r
+\r
+ //\r
+ // check the number of parameters\r
+ //\r
+ if (argc < 2) {\r
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // open the DebugData file, if not exists, return\r
+ //\r
+ if (argc >= 3) {\r
+ strcpy (DataFile, argv[2]);\r
+ } else {\r
+ strcpy (DataFile, "DebugData.dat");\r
+ }\r
+\r
+ fpData = fopen (DataFile, "a+");\r
+ if (fpData == NULL) {\r
+ fpData = fopen (DataFile, "w");\r
+ if (fpData == NULL) {\r
+ printf ("Error: Cannot open the data file!\n");\r
+ return -1;\r
+ }\r
+ }\r
+ //\r
+ // open the PE file\r
+ //\r
+ fp = fopen (argv[1], "r+b");\r
+ if (fp == NULL) {\r
+ printf ("Error: Cannot open the PE file!\n");\r
+ return -1;\r
+ }\r
+ //\r
+ // Zero the Debug Data to the PE file\r
+ //\r
+ printf ("Zero Debug Data to file %s:\n", argv[1]);\r
+ fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]);\r
+ if ((int *) ZeroDebugData (fp, fpData) != 0) {\r
+ printf ("Error: Zero Debug Data PE file\n");\r
+ fclose (fp);\r
+ return -1;\r
+ }\r
+\r
+ printf (" success\n");\r
+\r
+ //\r
+ // close the PE file\r
+ //\r
+ fflush (fpData);\r
+ fflush (fp);\r
+ fclose (fpData);\r
+ fclose (fp);\r
+\r
+ return 0;\r
+}\r