summaryrefslogtreecommitdiff
path: root/Tools/Source/TianoTools
diff options
context:
space:
mode:
authorlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>2006-05-19 02:38:56 +0000
committerlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>2006-05-19 02:38:56 +0000
commitd25c4bf080b9820d15b7c329cf42775010dbcc56 (patch)
treefddbcf8d4a8d5a7730f9dc5a44b09efba8d50e33 /Tools/Source/TianoTools
parent291a871a27d0bbcebede5b62a5e23d03f20a54fc (diff)
downloadedk2-d25c4bf080b9820d15b7c329cf42775010dbcc56.zip
edk2-d25c4bf080b9820d15b7c329cf42775010dbcc56.tar.gz
edk2-d25c4bf080b9820d15b7c329cf42775010dbcc56.tar.bz2
Adding Additional Tools that are needed for Platform Image creation.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@198 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'Tools/Source/TianoTools')
-rw-r--r--Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c246
-rw-r--r--Tools/Source/TianoTools/CreateMtFile/Makefile67
-rw-r--r--Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c163
-rw-r--r--Tools/Source/TianoTools/EfiCompress/makefile77
-rw-r--r--Tools/Source/TianoTools/EfiRom/EfiRom.c1543
-rw-r--r--Tools/Source/TianoTools/EfiRom/Makefile70
-rw-r--r--Tools/Source/TianoTools/FlashMap/FlashDefFile.c2787
-rw-r--r--Tools/Source/TianoTools/FlashMap/FlashDefFile.h281
-rw-r--r--Tools/Source/TianoTools/FlashMap/FlashMap.c745
-rw-r--r--Tools/Source/TianoTools/FlashMap/Makefile81
-rw-r--r--Tools/Source/TianoTools/FlashMap/Microcode.c306
-rw-r--r--Tools/Source/TianoTools/FlashMap/Microcode.h87
-rw-r--r--Tools/Source/TianoTools/FlashMap/Symbols.c647
-rw-r--r--Tools/Source/TianoTools/FlashMap/Symbols.h125
-rw-r--r--Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c542
-rw-r--r--Tools/Source/TianoTools/GenAcpiTable/Makefile68
-rw-r--r--Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c50
-rw-r--r--Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c2667
-rw-r--r--Tools/Source/TianoTools/GenCapsuleHdr/Makefile75
-rw-r--r--Tools/Source/TianoTools/GenFdImage/GenFdImage.h89
-rw-r--r--Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c864
-rw-r--r--Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c330
-rw-r--r--Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h91
-rw-r--r--Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c848
-rw-r--r--Tools/Source/TianoTools/GenFdImage/Makefile100
-rw-r--r--Tools/Source/TianoTools/GenTEImage/GenTEImage.c919
-rw-r--r--Tools/Source/TianoTools/GenTEImage/Makefile68
-rw-r--r--Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c973
-rw-r--r--Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h153
-rw-r--r--Tools/Source/TianoTools/PeiRebase/makefile71
-rw-r--r--Tools/Source/TianoTools/SecApResetVectorFixup/Makefile58
-rw-r--r--Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c363
-rw-r--r--Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h102
-rw-r--r--Tools/Source/TianoTools/SecFixup/Makefile57
-rw-r--r--Tools/Source/TianoTools/SecFixup/SecFixup.c362
-rw-r--r--Tools/Source/TianoTools/SecFixup/SecFixup.h146
-rw-r--r--Tools/Source/TianoTools/SplitFile/Makefile70
-rw-r--r--Tools/Source/TianoTools/SplitFile/SplitFile.c131
-rw-r--r--Tools/Source/TianoTools/Strip/Makefile70
-rw-r--r--Tools/Source/TianoTools/Strip/Strip.c105
-rw-r--r--Tools/Source/TianoTools/ZeroDebugData/Makefile63
-rw-r--r--Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c390
42 files changed, 17050 insertions, 0 deletions
diff --git a/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c b/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c
new file mode 100644
index 0000000..e769b88
--- /dev/null
+++ b/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c
@@ -0,0 +1,246 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ CreateMtFile.c
+
+Abstract:
+
+ Simple utility to create a pad file containing fixed data.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "TianoCommon.h"
+
+#define PROGRAM_NAME "CreateMtFile"
+
+typedef struct {
+ INT8 *OutFileName;
+ INT8 ByteValue;
+ UINT32 FileSize;
+} OPTIONS;
+
+static
+EFI_STATUS
+ProcessArgs (
+ IN INT32 Argc,
+ IN INT8 *Argv[],
+ IN OUT OPTIONS *Options
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+int
+main (
+ IN INT32 Argc,
+ IN INT8 *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main entry point for this utility.
+
+Arguments:
+
+ Standard C entry point args Argc and Argv
+
+Returns:
+
+ EFI_SUCCESS if good to go
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+// GC_TODO: EFI_DEVICE_ERROR - add return value to function comment
+{
+ FILE *OutFptr;
+ OPTIONS Options;
+
+ //
+ // Process the command-line arguments.
+ //
+ if (ProcessArgs (Argc, Argv, &Options) != EFI_SUCCESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (Options.OutFileName, "wb")) == NULL) {
+ fprintf (
+ stdout,
+ PROGRAM_NAME " ERROR: Could not open output file '%s' for writing\n",
+ Options.OutFileName
+ );
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Write the pad bytes. Do it the slow way (one at a time) for now.
+ //
+ while (Options.FileSize > 0) {
+ if (fwrite (&Options.ByteValue, 1, 1, OutFptr) != 1) {
+ fclose (OutFptr);
+ fprintf (stdout, PROGRAM_NAME " ERROR: Failed to write to output file\n");
+ return EFI_DEVICE_ERROR;
+ }
+
+ Options.FileSize--;
+ }
+ //
+ // Close the file
+ //
+ fclose (OutFptr);
+ return EFI_SUCCESS;
+}
+
+static
+EFI_STATUS
+ProcessArgs (
+ IN INT32 Argc,
+ IN INT8 *Argv[],
+ IN OUT OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Process the command line arguments.
+
+Arguments:
+
+ Argc - argument count as passed in to the entry point function
+ Argv - array of arguments as passed in to the entry point function
+ Options - stucture of where to put the values of the parsed arguments
+
+Returns:
+
+ EFI_SUCCESS if everything looks good
+ EFI_INVALID_PARAMETER otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ UINT32 Multiplier;
+
+ //
+ // Clear the options
+ //
+ memset ((char *) Options, 0, sizeof (OPTIONS));
+
+ //
+ // Skip program name
+ //
+ Argv++;
+ Argc--;
+ if (Argc < 2) {
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // If first arg is dash-option, then print usage.
+ //
+ if (Argv[0][0] == '-') {
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // First arg is file name
+ //
+ Options->OutFileName = Argv[0];
+ Argc--;
+ Argv++;
+
+ //
+ // Second arg is file size. Allow 0x1000, 0x100K, 1024, 1K
+ //
+ Multiplier = 1;
+ if ((Argv[0][strlen (Argv[0]) - 1] == 'k') || (Argv[0][strlen (Argv[0]) - 1] == 'K')) {
+ Multiplier = 1024;
+ }
+ //
+ // Look for 0x prefix on file size
+ //
+ if ((Argv[0][0] == '0') && ((Argv[0][1] == 'x') || (Argv[0][1] == 'X'))) {
+ if (sscanf (Argv[0], "%x", &Options->FileSize) != 1) {
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Otherwise must be a decimal number
+ //
+ } else {
+ if (sscanf (Argv[0], "%d", &Options->FileSize) != 1) {
+ fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);
+ Usage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Options->FileSize *= Multiplier;
+ //
+ // Assume byte value of 0xff
+ //
+ Options->ByteValue = (INT8) (UINT8) 0xFF;
+ return EFI_SUCCESS;
+}
+//
+// Print utility usage info
+//
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 Index;
+ static const INT8 *Text[] = {
+ " ",
+ "Usage: "PROGRAM_NAME " OutFileName FileSize",
+ " where:",
+ " OutFileName is the name of the output file to generate",
+ " FileSize is the size of the file to create",
+ " Examples:",
+ " "PROGRAM_NAME " OutFile.bin 32K",
+ " "PROGRAM_NAME " OutFile.bin 0x1000",
+ " ",
+ NULL
+ };
+
+ for (Index = 0; Text[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Text[Index]);
+ }
+}
diff --git a/Tools/Source/TianoTools/CreateMtFile/Makefile b/Tools/Source/TianoTools/CreateMtFile/Makefile
new file mode 100644
index 0000000..d6574fc
--- /dev/null
+++ b/Tools/Source/TianoTools/CreateMtFile/Makefile
@@ -0,0 +1,67 @@
+#/*++
+#
+# Copyright (c) 1999 - 2001 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+#
+# Module Name:
+#
+# Makefile
+#
+# Abstract:
+#
+# makefile for building the CreateMtFile utility.
+#
+# Revision History
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Define the toolchain which is used to set build options and toolchain paths
+#
+TOOLCHAIN = TOOLCHAIN_MSVC
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = CreateMtFile
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj
+
+#
+# Build the EXE by compiling the source files, then linking the resultant
+# object files together.
+#
+
+$(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj : $(TARGET_SRC_DIR)\CreateMtFile.c
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\CreateMtFile.c /Fo$@
+
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c b/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c
new file mode 100644
index 0000000..db3e184
--- /dev/null
+++ b/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c
@@ -0,0 +1,163 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ EfiCompressMain.c
+
+Abstract:
+
+ The main function for the compression utility.
+
+--*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "TianoCommon.h"
+#include "EfiCompress.h"
+
+int
+main (
+ INT32 argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Compresses the input files
+
+Arguments:
+
+ argc - number of arguments passed into the command line.
+ argv[] - files to compress and files to output compressed data to.
+
+Returns:
+
+ int: 0 for successful execution of the function.
+
+--*/
+{
+ EFI_STATUS Status;
+ FILE *infile;
+ FILE *outfile;
+ UINT32 SrcSize;
+ UINT32 DstSize;
+ UINT8 *SrcBuffer;
+ UINT8 *DstBuffer;
+ UINT8 Buffer[8];
+
+ //
+ // Added for makefile debug - KCE
+ //
+ INT32 arg_counter;
+ printf ("\n\n");
+ for (arg_counter = 0; arg_counter < argc; arg_counter++) {
+ printf ("%s ", argv[arg_counter]);
+ }
+
+ printf ("\n\n");
+
+ SrcBuffer = DstBuffer = NULL;
+
+ infile = outfile = NULL;
+
+ if (argc != 3) {
+ printf ("Usage: EFICOMPRESS <infile> <outfile>\n");
+ goto Done;
+ }
+
+ if ((outfile = fopen (argv[2], "wb")) == NULL) {
+ printf ("Can't open output file\n");
+ goto Done;
+ }
+
+ if ((infile = fopen (argv[1], "rb")) == NULL) {
+ printf ("Can't open input file\n");
+ goto Done;
+ }
+ //
+ // Get the size of source file
+ //
+ SrcSize = 0;
+ while (fread (Buffer, 1, 1, infile)) {
+ SrcSize++;
+
+ }
+ //
+ // Read in the source data
+ //
+ if ((SrcBuffer = malloc (SrcSize)) == NULL) {
+ printf ("Can't allocate memory\n");
+ goto Done;
+ }
+
+ rewind (infile);
+ if (fread (SrcBuffer, 1, SrcSize, infile) != SrcSize) {
+ printf ("Can't read from source\n");
+ goto Done;
+ }
+ //
+ // Get destination data size and do the compression
+ //
+ DstSize = 0;
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ if ((DstBuffer = malloc (DstSize)) == NULL) {
+ printf ("Can't allocate memory\n");
+ goto Done;
+ }
+
+ Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);
+ }
+
+ if (EFI_ERROR (Status)) {
+ printf ("Compress Error\n");
+ goto Done;
+ }
+
+ printf ("\nOrig Size = %ld\n", SrcSize);
+ printf ("Comp Size = %ld\n", DstSize);
+
+ if (DstBuffer == NULL) {
+ printf ("No destination to write to.\n");
+ goto Done;
+ }
+ //
+ // Write out the result
+ //
+ if (fwrite (DstBuffer, 1, DstSize, outfile) != DstSize) {
+ printf ("Can't write to destination file\n");
+ }
+
+Done:
+ if (SrcBuffer) {
+ free (SrcBuffer);
+ }
+
+ if (DstBuffer) {
+ free (DstBuffer);
+ }
+
+ if (infile) {
+ fclose (infile);
+ }
+
+ if (outfile) {
+ fclose (outfile);
+ }
+
+ return 0;
+}
diff --git a/Tools/Source/TianoTools/EfiCompress/makefile b/Tools/Source/TianoTools/EfiCompress/makefile
new file mode 100644
index 0000000..b20a219
--- /dev/null
+++ b/Tools/Source/TianoTools/EfiCompress/makefile
@@ -0,0 +1,77 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Define some macros we use here. Should get rid of them someday and
+# get rid of the extra level of indirection.
+#
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)
+
+#
+# BUGBUG: Override standard flags, cannot be built without warnings.
+#
+
+C_FLAGS=/nologo /W4 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c
+
+#
+# Common information
+#
+
+INC=$(INC)
+
+#
+# Target specific information
+#
+
+TARGET_NAME=EfiCompress
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\EfiCompressMain.c"
+TARGET_EXE_INCLUDE = "$(COMMON_SOURCE)\EfiCompress.h"
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib"
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj
+
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_EXE_LIBS) $(TARGET_DLL)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_LIB) $(TARGET_EXE_LIBS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* > NUL
diff --git a/Tools/Source/TianoTools/EfiRom/EfiRom.c b/Tools/Source/TianoTools/EfiRom/EfiRom.c
new file mode 100644
index 0000000..fc168ed
--- /dev/null
+++ b/Tools/Source/TianoTools/EfiRom/EfiRom.c
@@ -0,0 +1,1543 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ EfiRom.c
+
+Abstract:
+
+ Utility program to create an EFI option ROM image from binary and
+ EFI PE32 files.
+
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+//
+// Includes for EFI 1.1 build
+//
+// #include "Tiano.h" // required defines for Compress.h
+// #include "EfiImage.h" // for PE32 structure definitions
+// #include "Compress.h" // for compression function
+// Includes for Tiano build
+//
+#include "TianoCommon.h"
+#include "EfiImage.h" // for PE32 structure definitions
+#include "EfiCompress.h"
+
+//
+// END include differences
+//
+#include "Pci22.h" // for option ROM header structures
+//
+// Version of this utility
+//
+#define UTILITY_VERSION "v2.5"
+
+//
+// Define some status return values
+//
+#define STATUS_SUCCESS 0
+#define STATUS_WARNING 1
+#define STATUS_ERROR 2
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 200
+
+#define DEFAULT_OUTPUT_EXTENSION ".rom"
+
+//
+// Max size for an option ROM image
+//
+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB
+//
+// Values for the indicator field in the PCI data structure
+//
+#define INDICATOR_LAST 0x80 // last file in series of files
+//
+// Masks for the FILE_LIST.FileFlags field
+//
+#define FILE_FLAG_BINARY 0x01
+#define FILE_FLAG_EFI 0x02
+#define FILE_FLAG_COMPRESS 0x04
+
+//
+// Use this linked list structure to keep track of all the filenames
+// specified on the command line.
+//
+typedef struct _FILE_LIST {
+ struct _FILE_LIST *Next;
+ INT8 *FileName;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT16 CodeRevision;
+} FILE_LIST;
+
+//
+// Use this to track our command-line options
+//
+typedef struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 NoLast;
+ INT8 Verbose;
+ INT8 DumpOption;
+ UINT8 DevIdValid;
+ UINT8 VendIdValid;
+ UINT16 VendId;
+ UINT16 DevId;
+ FILE_LIST *FileList;
+} OPTIONS;
+
+//
+// Make a global structure to keep track of command-line options
+//
+static OPTIONS mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ char *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ );
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ );
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ );
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ );
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ );
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given an EFI image filename, create a ROM-able image by creating an option
+ ROM header and PCI data structure, filling them in, and then writing the
+ option ROM header + PCI data structure + EFI image out to the output file.
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ INT8 *Ext;
+ FILE *FptrOut;
+ UINT32 Status;
+ FILE_LIST *FList;
+ UINT32 TotalSize;
+ UINT32 Size;
+
+ Status = STATUS_SUCCESS;
+ FptrOut = NULL;
+
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv, &mOptions)) {
+ return STATUS_ERROR;
+ }
+ //
+ // If dumping an image, then do that and quit
+ //
+ if (mOptions.DumpOption) {
+ DumpImage (mOptions.FileList);
+ goto BailOut;
+ }
+ //
+ // Determine the output filename. Either what they specified on
+ // the command line, or the first input filename with a different extension.
+ //
+ if (!mOptions.OutFileName[0]) {
+ strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
+ //
+ // Find the last . on the line and replace the filename extension with
+ // the default
+ //
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
+ Ext--
+ )
+ ;
+ //
+ // If dot here, then insert extension here, otherwise append
+ //
+ if (*Ext != '.') {
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
+ }
+
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {
+ Status = STATUS_ERROR;
+ fprintf (
+ stdout,
+ "ERROR: Input and output file names must be different - %s = %s\n",
+ FList->FileName,
+ mOptions.OutFileName
+ );
+ goto BailOut;
+ }
+ }
+ //
+ // Now open our output file
+ //
+ if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);
+ goto BailOut;
+ }
+ //
+ // Process all our files
+ //
+ TotalSize = 0;
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ Size = 0;
+ if (FList->FileFlags & FILE_FLAG_EFI) {
+ if (mOptions.Verbose) {
+ fprintf (stdout, "Processing EFI file %s\n", FList->FileName);
+ }
+
+ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
+ } else if (FList->FileFlags & FILE_FLAG_BINARY) {
+ if (mOptions.Verbose) {
+ fprintf (stdout, "Processing binary file %s\n", FList->FileName);
+ }
+
+ Status = ProcessBinFile (FptrOut, FList, &Size);
+ } else {
+ fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);
+ Status = STATUS_ERROR;
+ }
+
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Output size = 0x%X\n", Size);
+ }
+
+ if (Status != STATUS_SUCCESS) {
+ break;
+ }
+
+ TotalSize += Size;
+ }
+ //
+ // Check total size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ }
+
+BailOut:
+ if (FptrOut != NULL) {
+ fclose (FptrOut);
+ }
+ //
+ // Clean up our file list
+ //
+ while (mOptions.FileList != NULL) {
+ FList = mOptions.FileList->Next;
+ free (mOptions.FileList);
+ mOptions.FileList = FList;
+ }
+
+ return Status;
+}
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a binary input file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the binary file to process
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ FILE *InFptr;
+ UINT32 TotalSize;
+ UINT32 FileSize;
+ UINT8 *Buffer;
+ UINT32 Status;
+ PCI_EXPANSION_ROM_HEADER *RomHdr;
+ PCI_DATA_STRUCTURE *PciDs;
+ UINT32 Index;
+ UINT8 ByteCheckSum;
+
+ Status = STATUS_SUCCESS;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Seek to the end of the input file and get the file size. Then allocate
+ // a buffer to read it in to.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ if (mOptions.Verbose) {
+ fprintf (stdout, " File size = 0x%X\n", FileSize);
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ Buffer = (INT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes, and can't exceed
+ // the option ROM image size.
+ //
+ TotalSize = FileSize;
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
+ InFile->FileName,
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Crude check to make sure it's a legitimate ROM image
+ //
+ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;
+ if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Make sure the pointer to the PCI data structure is within the size of the image.
+ // Then check it for valid signature.
+ //
+ if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
+ fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
+ if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -l argument. Otherwise, make sure you clear it.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ PciDs->Indicator = INDICATOR_LAST;
+ } else {
+ PciDs->Indicator = 0;
+ }
+
+ ByteCheckSum = 0;
+ for (Index = 0; Index < FileSize - 1; Index++) {
+ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
+ }
+
+ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
+ fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);
+
+ //
+ // Now copy the input file contents out to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize -= FileSize;
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (TotalSize > 0) {
+ putc (~0, OutFptr);
+ TotalSize--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the PE32 file to process
+ VendId - vendor ID as required in the option ROM header
+ DevId - device ID as required in the option ROM header
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ UINT32 Status;
+ FILE *InFptr;
+ EFI_PCI_EXPANSION_ROM_HEADER RomHdr;
+ PCI_DATA_STRUCTURE PciDs;
+ UINT32 FileSize;
+ UINT32 CompressedFileSize;
+ UINT8 *Buffer;
+ UINT8 *CompressedBuffer;
+ UINT8 *TempBufferPtr;
+ UINT32 TotalSize;
+ UINT32 HeaderSize;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ UINT32 HeaderPadBytes;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Initialize our buffer pointers to null.
+ //
+ Buffer = NULL;
+ CompressedBuffer = NULL;
+
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
+ if (Status != STATUS_SUCCESS) {
+ goto BailOut;
+ }
+ //
+ // Seek to the end of the input file and get the file size
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+
+ //
+ // Get the size of the headers we're going to put in front of the image. The
+ // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
+ //
+ if (sizeof (RomHdr) & 0x03) {
+ HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
+ } else {
+ HeaderPadBytes = 0;
+ }
+
+ HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
+ if (mOptions.Verbose) {
+ fprintf (stdout, " File size = 0x%X\n", FileSize);
+ }
+ //
+ // Allocate memory for the entire file (in case we have to compress), then
+ // seek back to the beginning of the file and read it into our buffer.
+ //
+ Buffer = (INT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Now determine the size of the final output file. It's either the header size
+ // plus the file's size, or the header size plus the compressed file size.
+ //
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
+ //
+ // Allocate a buffer into which we can compress the image, compress it,
+ // and use that size as the new size.
+ //
+ CompressedBuffer = (INT8 *) malloc (FileSize);
+ if (CompressedBuffer == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failed\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ CompressedFileSize = FileSize;
+ Status = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "ERROR: Compression failed\n");
+ goto BailOut;
+ }
+ //
+ // Now compute the size, then swap buffer pointers.
+ //
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Comp size = 0x%X\n", CompressedFileSize);
+ }
+
+ TotalSize = CompressedFileSize + HeaderSize;
+ FileSize = CompressedFileSize;
+ TempBufferPtr = Buffer;
+ Buffer = CompressedBuffer;
+ CompressedBuffer = TempBufferPtr;
+ } else {
+ TotalSize = FileSize + HeaderSize;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes
+ //
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+ //
+ // Check size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ fprintf (
+ stdout,
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
+ InFile->FileName,
+ MAX_OPTION_ROM_SIZE
+ );
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Now fill in the ROM header. These values come from chapter 18 of the
+ // EFI 1.02 specification.
+ //
+ memset (&RomHdr, 0, sizeof (RomHdr));
+ RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
+ RomHdr.InitializationSize = (UINT16) (TotalSize / 512);
+ RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
+ RomHdr.EfiSubsystem = SubSystem;
+ RomHdr.EfiMachineType = MachineType;
+ RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;
+ RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);
+ //
+ // Set image as compressed or not
+ //
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
+ RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
+ }
+ //
+ // Fill in the PCI data structure
+ //
+ memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE));
+
+ PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ PciDs.VendorId = VendId;
+ PciDs.DeviceId = DevId;
+ PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE);
+ PciDs.Revision = 0;
+ //
+ // Class code and code revision from the command line (optional)
+ //
+ PciDs.ClassCode[0] = (UINT8) InFile->ClassCode;
+ PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
+ PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
+ PciDs.ImageLength = RomHdr.InitializationSize;
+ PciDs.CodeRevision = InFile->CodeRevision;
+ PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
+
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -l argument.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ PciDs.Indicator = INDICATOR_LAST;
+ }
+ //
+ // Write the ROM header to the output file
+ //
+ if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ //
+ // Write pad bytes to align the PciDs
+ //
+ while (HeaderPadBytes > 0) {
+ if (putc (0, OutFptr) == EOF) {
+ fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ HeaderPadBytes--;
+ }
+ //
+ // Write the PCI data structure header to the output file
+ //
+ if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Keep track of how many bytes left to write
+ //
+ TotalSize -= HeaderSize;
+
+ //
+ // Now dump the input file's contents to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize -= FileSize;
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (TotalSize > 0) {
+ if (putc (~0, OutFptr) == EOF) {
+ fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ //
+ // Free up our buffers
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ if (CompressedBuffer != NULL) {
+ free (CompressedBuffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");
+ return STATUS_ERROR;
+ }
+ //
+ // Read the file header and stuff their MachineType
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");
+ return STATUS_ERROR;
+ }
+
+ memcpy ((char *) MachineType, &FileHdr.Machine, 2);
+
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");
+ return STATUS_ERROR;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);
+ }
+ //
+ // Good to go
+ //
+ return STATUS_SUCCESS;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv[] - standard C main() argument list
+ Options - pointer to a structure to store the options in
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+//
+{
+ FILE_LIST *FileList;
+
+ FILE_LIST *PrevFileList;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT32 CodeRevision;
+
+ FileFlags = 0;
+
+ //
+ // Clear out the options
+ //
+ memset ((char *) Options, 0, sizeof (OPTIONS));
+
+ //
+ // To avoid compile warnings
+ //
+ FileList = PrevFileList = NULL;
+
+ ClassCode = 0;
+ CodeRevision = 0;
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+
+ //
+ // If no arguments, assume they want usage info
+ //
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more arguments
+ //
+ while (Argc > 0) {
+ if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {
+ //
+ // To simplify string comparisons, replace slashes with dashes
+ //
+ Argv[0][0] = '-';
+
+ //
+ // Vendor ID specified with -v
+ //
+ if (stricmp (Argv[0], "-v") == 0) {
+ //
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ Options->VendId = (UINT16) strtol (Argv[1], NULL, 16);
+ Options->VendIdValid = 1;
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing Vendor ID with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-d") == 0) {
+ //
+ // Device ID specified with -d
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ Options->DevId = (UINT16) strtol (Argv[1], NULL, 16);
+ Options->DevIdValid = 1;
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing Device ID with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // Output filename specified with -o
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ strcpy (Options->OutFileName, Argv[1]);
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing output file name with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ //
+ // Help option
+ //
+ Usage ();
+ return STATUS_ERROR;
+ } else if (stricmp (Argv[0], "-b") == 0) {
+ //
+ // Specify binary files with -b
+ //
+ FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;
+ } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
+ //
+ // Specify EFI files with -e. Specify EFI-compressed with -ec.
+ //
+ FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI;
+ if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {
+ FileFlags |= FILE_FLAG_COMPRESS;
+ }
+ //
+ // Specify not to set the LAST bit in the last file with -l
+ //
+ } else if (stricmp (Argv[0], "-l") == 0) {
+ Options->NoLast = 1;
+ } else if (stricmp (Argv[0], "-p") == 0) {
+ //
+ // -v for verbose would have been nicer, but it's already used. Let's use
+ // -p for prolix (wordy) output
+ //
+ Options->Verbose = 1;
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ //
+ // -dump for dumping a ROM image. In this case, say that the device id
+ // and vendor id are valid so we don't have to specify bogus ones on the
+ // command line.
+ //
+ Options->DumpOption = 1;
+
+ Options->VendIdValid = 1;
+ Options->DevIdValid = 1;
+ FileFlags = FILE_FLAG_BINARY;
+ } else if (stricmp (Argv[0], "-cc") == 0) {
+ //
+ // Class code value for the next file in the list.
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ //
+ // No error checking on the return value. Could check for LONG_MAX,
+ // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)
+ // at least.
+ //
+ ClassCode = (UINT32) strtol (Argv[1], NULL, 16);
+ if (ClassCode & 0xFF000000) {
+ fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]);
+ return STATUS_ERROR;
+ }
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing class code value with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-rev") == 0) {
+ //
+ // Code revision in the PCI data structure. The value is for the next
+ // file in the list.
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ //
+ // No error checking on the return value. Could check for LONG_MAX,
+ // LONG_MIN, or 0 value if desired. Check range (2 bytes)
+ // at least.
+ //
+ CodeRevision = (UINT32) strtol (Argv[1], NULL, 16);
+ if (CodeRevision & 0xFFFF0000) {
+ fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]);
+ return STATUS_ERROR;
+ }
+ } else {
+ fprintf (
+ stdout,
+ "ERROR: Missing code revision value with %s\n\n",
+ Argv[0]
+ );
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else {
+ fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]);
+ Usage ();
+ return STATUS_ERROR;
+ }
+ } else {
+ //
+ // Not a slash-option argument. Must be a file name. Make sure they've specified
+ // -e or -b already.
+ //
+ if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {
+ fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]);
+ return STATUS_ERROR;
+ }
+ //
+ // Create a new file structure
+ //
+ FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
+ if (FileList == NULL) {
+ fprintf (stdout, "ERROR: Memory allocation failure\n");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) FileList, 0, sizeof (FILE_LIST));
+ FileList->FileName = Argv[0];
+ FileList->FileFlags = FileFlags;
+ if (Options->FileList == NULL) {
+ Options->FileList = FileList;
+ } else {
+ if (PrevFileList == NULL) {
+ PrevFileList = FileList;
+ } else {
+ PrevFileList->Next = FileList;
+ }
+ }
+
+ PrevFileList = FileList;
+ //
+ // Set the class code and code revision for this file, then reset the values.
+ //
+ FileList->ClassCode = ClassCode;
+ FileList->CodeRevision = (UINT16) CodeRevision;
+ ClassCode = 0;
+ CodeRevision = 0;
+ }
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+ }
+ //
+ // Make sure they specified a device ID and vendor ID
+ //
+ if (!Options->VendIdValid) {
+ fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (!Options->DevIdValid) {
+ fprintf (stdout, "ERROR: Missing Device ID on command line\n\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Must have specified some files
+ //
+ if (Options->FileList == NULL) {
+ fprintf (stdout, "ERROR: Missing input file name\n");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ return 0;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility",
+ " Copyright (C), 1999-2002 Intel Coproration\n",
+ " Create an option ROM image from a list of input files",
+ " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",
+ " [-e|-b] [FileName(s)]",
+ " where:",
+ " VendorId - required hex PCI Vendor ID for the device",
+ " DeviceId - required hex PCI Device ID for the device",
+ " OutFileName - optional output file name. Default is the first input",
+ " file name with a "DEFAULT_OUTPUT_EXTENSION " file extension",
+ " FileNames - input PE32 or binary file name(s)",
+ " BinFileName - input binary file name(s)",
+ " -p - for verbose output",
+ " -l - to not automatically set the LAST bit on the last file",
+ " -b - following FileNames are binary files",
+ " -e - following FileNames are EFI PE32 image files",
+ " -ec - following FileNames are EFI PE32 image files, and should",
+ " be compressed by this utility",
+ " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",
+ " the following FileName",
+ " -rev Revision - to use hex Revision in the PCI data structure header for",
+ " the following FileName",
+ " -dump - to dump the headers of an existing option ROM image",
+ "",
+ "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",
+ "",
+ NULL
+ };
+
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ InFile - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ PCI_EXPANSION_ROM_HEADER PciRomHdr;
+ FILE *InFptr;
+ UINT32 ImageStart;
+ UINT32 ImageCount;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;
+ PCI_DATA_STRUCTURE PciDs;
+
+ //
+ // Open the input file
+ //
+ if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
+ fprintf (
+ stdout,
+ "ERROR: Could not open input file %s\n",
+ InFile->FileName
+ );
+ return ;
+ }
+ //
+ // Go through the image and dump the header stuff for each
+ //
+ ImageCount = 0;
+ for (;;) {
+ //
+ // Save our postition in the file, since offsets in the headers
+ // are relative to the particular image.
+ //
+ ImageStart = ftell (InFptr);
+ ImageCount++;
+
+ //
+ // Read the option ROM header. Have to assume a raw binary image for now.
+ //
+ if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n");
+ goto BailOut;
+ }
+
+ //
+ // Dump the contents of the header
+ //
+ fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart);
+ fprintf (stdout, " ROM header contents\n");
+ fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature);
+ fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset);
+ //
+ // Find PCI data structure
+ //
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n");
+ goto BailOut;
+ }
+ //
+ // Read and dump the PCI data structure
+ //
+ if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n");
+ goto BailOut;
+ }
+
+ fprintf (stdout, " PCI Data Structure\n");
+ fprintf (
+ stdout,
+ " Signature %c%c%c%c\n",
+ (char) PciDs.Signature,
+ (char) (PciDs.Signature >> 8),
+ (char) (PciDs.Signature >> 16),
+ (char) (PciDs.Signature >> 24)
+ );
+ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId);
+ fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId);
+ fprintf (
+ stdout,
+ " Class Code 0x%06X\n",
+ (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))
+ );
+ fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512);
+ fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision);
+ fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator);
+ //
+ // Print the indicator, used to flag the last image
+ //
+ if (PciDs.Indicator == INDICATOR_LAST) {
+ fprintf (stdout, " (last image)\n");
+ } else {
+ fprintf (stdout, "\n");
+ }
+ //
+ // Print the code type. If EFI code, then we can provide more info.
+ //
+ fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType);
+ if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ fprintf (stdout, " (EFI image)\n");
+ //
+ // Re-read the header as an EFI ROM header, then dump more info
+ //
+ fprintf (stdout, " EFI ROM header contents\n");
+ if (fseek (InFptr, ImageStart, SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");
+ goto BailOut;
+ }
+
+ if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
+ fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");
+ goto BailOut;
+ }
+ //
+ // Now dump more info
+ //
+ fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature);
+ fprintf (
+ stdout,
+ " Compression Type 0x%04X ",
+ (UINT32) EfiRomHdr.CompressionType
+ );
+ if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ fprintf (stdout, "(compressed)\n");
+ } else {
+ fprintf (stdout, "(not compressed)\n");
+ }
+
+ fprintf (
+ stdout,
+ " Machine type 0x%04X (%s)\n",
+ EfiRomHdr.EfiMachineType,
+ GetMachineTypeStr (EfiRomHdr.EfiMachineType)
+ );
+ fprintf (
+ stdout,
+ " Subsystem 0x%04X (%s)\n",
+ EfiRomHdr.EfiSubsystem,
+ GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)
+ );
+ fprintf (
+ stdout,
+ " EFI image offset 0x%04X (@0x%X)\n",
+ (UINT32) EfiRomHdr.EfiImageHeaderOffset,
+ (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)
+ );
+
+ } else {
+ //
+ // Not an EFI image
+ //
+ fprintf (stdout, "\n");
+ }
+ //
+ // If code type is EFI image, then dump it as well?
+ //
+ // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ // }
+ //
+ // If last image, then we're done
+ //
+ if (PciDs.Indicator == INDICATOR_LAST) {
+ goto BailOut;
+ }
+ //
+ // Seek to the start of the next image
+ //
+ if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) {
+ fprintf (stdout, "ERROR: Failed to seek to next image\n");
+ goto BailOut;
+ }
+ }
+
+BailOut:
+ fclose (InFptr);
+}
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
+ if (mMachineTypes[Index].Value == MachineType) {
+ return mMachineTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
+ if (mSubsystemTypes[Index].Value == SubsystemType) {
+ return mSubsystemTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
diff --git a/Tools/Source/TianoTools/EfiRom/Makefile b/Tools/Source/TianoTools/EfiRom/Makefile
new file mode 100644
index 0000000..5ba3607
--- /dev/null
+++ b/Tools/Source/TianoTools/EfiRom/Makefile
@@ -0,0 +1,70 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name:
+#
+# makefile
+#
+# Abstract:
+#
+# makefile for building the EfiRom utility.
+#
+# Revision History
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Define the toolchain which is used to set build options and toolchain paths
+#
+TOOLCHAIN = TOOLCHAIN_MSVC
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = EfiRom
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\EfiRom.exe
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\EfiRom.obj \
+ $(TIANO_TOOLS_OUTPUT)\EfiCompress.obj
+
+#
+# Build the EXE by compiling the source files, then linking the resultant
+# object files together.
+#
+
+$(TIANO_TOOLS_OUTPUT)\EfiRom.obj : $(TARGET_SRC_DIR)\EfiRom.c
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\EfiRom.c /Fo$@
+
+$(TIANO_TOOLS_OUTPUT)\EfiCompress.obj : $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c
+ $(CC) $(C_FLAGS) $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c /Fo$@
+
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/FlashMap/FlashDefFile.c b/Tools/Source/TianoTools/FlashMap/FlashDefFile.c
new file mode 100644
index 0000000..fa31863
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/FlashDefFile.c
@@ -0,0 +1,2787 @@
+/*++
+
+Copyright (c) 2004-2005 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ FlashDefFile.c
+
+Abstract:
+
+ Utility for flash management in the Intel Platform Innovation Framework
+ for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Tiano.h"
+#include "EfiUtilityMsgs.h"
+#include "FlashDefFile.h"
+#include "SimpleFileParsing.h"
+#include "Symbols.h"
+#include "EfiFirmwareVolumeHeader.h"
+
+//
+// #include "TrackMallocFree.h"
+//
+#define WCHAR_T char
+#define MAX_STRING_LEN 256
+#define MAX_NAME_LEN 128
+#define BUFFER_SIZE 1024
+#define MAX_ATTR_LEN 128
+#define MAX_AREATYPE_LEN 128
+#define COLUMN2_START 60
+#define COLUMN3_START 70
+//
+// Information for each subregions defined in the fdf file will be saved in these
+//
+typedef struct _FLASH_SUBREGION_DESCRIPTION {
+ struct _FLASH_SUBREGION_DESCRIPTION *Next;
+ int CreateHob; // to add to the auto-created HOB array
+ WCHAR_T Name[MAX_NAME_LEN]; // each subregion within a region must have a unique name
+ unsigned int Size; // size, in bytes, of this subregion
+ unsigned int SizeLeft; // used when creating the image
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // subregion attributes used in the output HOB
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB
+ EFI_GUID NameGuid; // used in the output HOB
+ WCHAR_T NameGuidString[MAX_NAME_LEN];
+ EFI_GUID AreaTypeGuid; // used in the output HOB
+ WCHAR_T AreaTypeGuidString[MAX_NAME_LEN];
+ EFI_GUID FileSystemGuid; // used in the output HOB
+ WCHAR_T FileSystemGuidString[MAX_NAME_LEN];
+} FLASH_SUBREGION_DESCRIPTION;
+
+//
+// Information for each block in a flash device will be saved in one of these.
+// We'll also use it for region definitions.
+//
+typedef struct _FLASH_BLOCK_DESCRIPTION {
+ struct _FLASH_BLOCK_DESCRIPTION *Next; // next block in the linked list
+ WCHAR_T Name[MAX_NAME_LEN]; // each block must have a unique name
+ unsigned int Size; // size, in bytes, of this block
+ unsigned int SizeLeft; // for use when creating image
+ unsigned int Flags; // user-defined flags for the block
+ unsigned int Alignment; // power of 2 alignment
+ WCHAR_T Attributes[MAX_ATTR_LEN]; // only used for Region definitions
+ WCHAR_T AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions
+ FLASH_SUBREGION_DESCRIPTION *Subregions;
+ FLASH_SUBREGION_DESCRIPTION *LastSubregion;
+} FLASH_BLOCK_DESCRIPTION;
+
+//
+// Information for each flash device will be saved in one of these
+//
+typedef struct _FLASH_DEVICE_DESCRIPTION {
+ struct _FLASH_DEVICE_DESCRIPTION *Next; // next flash device in our linked list
+ int ErasePolarity; // erase polarity of the flash device
+ unsigned int BaseAddress; // base address of the flash device
+ unsigned int Size; // total size, in bytes, of the flash device
+ WCHAR_T Name[MAX_NAME_LEN]; // name of the flash device
+ FLASH_BLOCK_DESCRIPTION *PBlocks; // linked list of physical block descriptors
+ FLASH_BLOCK_DESCRIPTION *LastPBlock; // last block in the linked list
+ FLASH_BLOCK_DESCRIPTION *Regions; // linked list of flash region descriptors
+ FLASH_BLOCK_DESCRIPTION *LastRegion; // last region in the linked list
+} FLASH_DEVICE_DESCRIPTION;
+
+//
+// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.
+//
+typedef struct _IMAGE_DEFINITION_ENTRY {
+ struct _IMAGE_DEFINITION_ENTRY *Next;
+ WCHAR_T RegionName[MAX_NAME_LEN];
+ WCHAR_T SubregionName[MAX_NAME_LEN];
+ WCHAR_T Name[MAX_NAME_LEN]; // file or data name
+ int IsRawData; // non-zero if raw data bytes
+ unsigned int RawDataSize;
+ char *RawData;
+ int Optional; // optional file (don't include if it doesn't exist)
+} IMAGE_DEFINITION_ENTRY;
+
+//
+// When we parse an image definition, save all the data for each in one of these
+//
+typedef struct _IMAGE_DEFINITION {
+ struct _IMAGE_DEFINITION *Next;
+ WCHAR_T Name[MAX_NAME_LEN];
+ IMAGE_DEFINITION_ENTRY *Entries;
+ IMAGE_DEFINITION_ENTRY *LastEntry;
+} IMAGE_DEFINITION;
+
+typedef struct {
+ char *BufferStart;
+ char *BufferEnd;
+ char *BufferPos;
+} BUFFER_DATA;
+
+static const char *CIncludeHeader = "/*++\n\n"
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"
+"#define _FLASH_MAP_H_\n\n";
+//
+// "#include \"EfiFlashMap.h\"\n\n";
+//
+static const char *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";
+
+static const char *CFlashMapDataFileHeader = "/*++\n\n"
+" DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";
+
+static FLASH_DEVICE_DESCRIPTION *mFlashDevices = NULL;
+static IMAGE_DEFINITION *mImageDefinitions = NULL;
+
+//
+// Local function prototypes
+//
+static
+BUFFER_DATA *
+CreateBufferData (
+ VOID
+ );
+
+static
+BOOLEAN
+AddBufferDataByte (
+ BUFFER_DATA *Buffer,
+ char Data
+ );
+
+static
+void
+FreeBufferData (
+ BUFFER_DATA *Buffer,
+ BOOLEAN FreeData
+ );
+
+static
+char *
+GetBufferData (
+ BUFFER_DATA *Buffer,
+ int *BufferSize
+ );
+
+static
+FLASH_SUBREGION_DESCRIPTION *
+ParseSubregionDefinition (
+ unsigned int SizeLeft
+ );
+
+void
+FDFConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Initialization routine for the services that operate on a flash
+ definition file.
+
+Arguments:
+ None.
+
+Returns:
+ NA
+
+--*/
+{
+ mFlashDevices = NULL;
+ mImageDefinitions = NULL;
+}
+
+void
+FDFDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Finalization/cleanup routine for the services that operate on a flash
+ definition file.
+
+Arguments:
+ None.
+
+Returns:
+ NA
+
+--*/
+{
+ FLASH_BLOCK_DESCRIPTION *FBNext;
+ FLASH_DEVICE_DESCRIPTION *FDNext;
+ IMAGE_DEFINITION *IDNext;
+ IMAGE_DEFINITION_ENTRY *IDENext;
+ FLASH_SUBREGION_DESCRIPTION *SubNext;
+ //
+ // Go through all our flash devices and free the memory
+ //
+ while (mFlashDevices != NULL) {
+ //
+ // Free the physical block definitions
+ //
+ while (mFlashDevices->PBlocks != NULL) {
+ FBNext = mFlashDevices->PBlocks->Next;
+ _free (mFlashDevices->PBlocks);
+ mFlashDevices->PBlocks = FBNext;
+ }
+ //
+ // Free the region definitions
+ //
+ while (mFlashDevices->Regions != NULL) {
+ FBNext = mFlashDevices->Regions->Next;
+ //
+ // First free the subregion definitions
+ //
+ while (mFlashDevices->Regions->Subregions != NULL) {
+ SubNext = mFlashDevices->Regions->Subregions->Next;
+ _free (mFlashDevices->Regions->Subregions);
+ mFlashDevices->Regions->Subregions = SubNext;
+ }
+
+ _free (mFlashDevices->Regions);
+ mFlashDevices->Regions = FBNext;
+ }
+
+ FDNext = mFlashDevices->Next;
+ _free (mFlashDevices);
+ mFlashDevices = FDNext;
+ }
+ //
+ // Free up the image definitions, and the data
+ //
+ while (mImageDefinitions != NULL) {
+ //
+ // Free the entries
+ //
+ while (mImageDefinitions->Entries != NULL) {
+ IDENext = mImageDefinitions->Entries->Next;
+ if (mImageDefinitions->Entries->RawData != NULL) {
+ _free (mImageDefinitions->Entries->RawData);
+ }
+
+ _free (mImageDefinitions->Entries);
+ mImageDefinitions->Entries = IDENext;
+ }
+
+ IDNext = mImageDefinitions->Next;
+ _free (mImageDefinitions);
+ mImageDefinitions = IDNext;
+ }
+}
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Parse the specified flash definition file, saving the definitions in
+ file-static variables for use by other functions.
+
+Arguments:
+ FileName - name of the input flash definition text file.
+
+Returns:
+ STATUS_SUCCESS - file parsed with no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered while parsing
+ STATUS_ERROR - errors were encountered while parsing
+
+--*/
+{
+ FILE *Fptr;
+ STATUS Status;
+ unsigned int Num;
+ FLASH_DEVICE_DESCRIPTION *FDDesc;
+ FLASH_BLOCK_DESCRIPTION *FBlockDesc;
+ FLASH_BLOCK_DESCRIPTION *TempBlockDesc;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ FLASH_SUBREGION_DESCRIPTION *TempSubregion;
+ unsigned int BlockSizeLeft;
+ unsigned int RegionSizeLeft;
+ unsigned int SubregionSizeLeft;
+ int ErrorCount;
+ int WarningCount;
+ IMAGE_DEFINITION *ImageDef;
+ IMAGE_DEFINITION_ENTRY *ImageDefEntry;
+ IMAGE_DEFINITION_ENTRY *TempImageDefEntry;
+ BUFFER_DATA *BufferData;
+ char Str[100];
+ BOOLEAN PreviousComma;
+
+ if ((Fptr = fopen (FileName, "r")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");
+ return STATUS_ERROR;
+ }
+
+ fclose (Fptr);
+ Status = STATUS_SUCCESS;
+ ErrorCount = 0;
+ WarningCount = 0;
+ //
+ // Initialize the simple-file-parsing routines
+ //
+ SFPInit ();
+ //
+ // Open the file
+ //
+ if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Parse the file. Should start with a series of these:
+ // FlashDevice {
+ // Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
+ // Block { Name = "BLOCK2", Size = 0x1004, Flags = 0x0002 }
+ // Region { Name = "REGION_NAME", Size = 0x2004, Align= 4 }
+ // }
+ //
+ while (SFPIsKeyword ("FlashDevice")) {
+ //
+ // Allocate memory for new flash device description block
+ //
+ FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));
+ if (FDDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "DeviceName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x20000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FDDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Check for 0 size
+ //
+ if (FDDesc->Size == 0) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ //
+ // Parse: BaseAddress = 0xFFF0000,
+ //
+ if (!SFPIsKeyword ("BaseAddress")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FDDesc->BaseAddress)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: ErasePolarity = 1,
+ //
+ if (!SFPIsKeyword ("ErasePolarity")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ FDDesc->ErasePolarity = Num;
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse array of:
+ // Block { Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }
+ //
+ // Keep track of size to make sure the sum of the physical blocks and region sizes do not
+ // exceed the size of the flash device.
+ //
+ BlockSizeLeft = FDDesc->Size;
+ RegionSizeLeft = FDDesc->Size;
+ while (SFPIsKeyword ("Block")) {
+ //
+ // Allocate memory for a new physical block descriptor
+ //
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
+ if (FBlockDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "BlockName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure there are no other physical block names with this same name
+ //
+ for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempBlockDesc->Name,
+ "physical block with this name already defined"
+ );
+ ErrorCount++;
+ }
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure the sum of physical blocks so far does not exceed flash device size
+ //
+ if (BlockSizeLeft < FBlockDesc->Size) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "sum of physical block sizes exceeds flash device size",
+ NULL
+ );
+ ErrorCount++;
+ }
+
+ BlockSizeLeft -= FBlockDesc->Size;
+ SFPIsToken (",");
+ //
+ // Optional parse: Flags = 0xFFF0000,
+ //
+ if (SFPIsKeyword ("Flags")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ }
+
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add the physical block descriptor to the end of the linked list
+ //
+ if (FDDesc->LastPBlock != NULL) {
+ FDDesc->LastPBlock->Next = FBlockDesc;
+ } else {
+ FDDesc->PBlocks = FBlockDesc;
+ }
+
+ FDDesc->LastPBlock = FBlockDesc;
+ }
+ //
+ // Make sure sum of sizes of physical blocks added up to size of flash device
+ //
+ if (BlockSizeLeft != 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ NULL,
+ "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
+ FDDesc->Size - BlockSizeLeft,
+ FDDesc->Size,
+ BlockSizeLeft
+ );
+ ErrorCount++;
+ }
+ //
+ // Parse array of:
+ // Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }
+ //
+ while (SFPIsKeyword ("Region")) {
+ //
+ // Allocate memory for a new physical block descriptor
+ //
+ FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));
+ if (FBlockDesc == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "BlockName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Make sure there are no other region names with this same name
+ //
+ for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {
+ if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempBlockDesc->Name,
+ "Region with this name already defined"
+ );
+ ErrorCount++;
+ }
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Make sure the sum of regions so far does not exceed flash device size
+ //
+ if (RegionSizeLeft < FBlockDesc->Size) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);
+ ErrorCount++;
+ }
+
+ RegionSizeLeft -= FBlockDesc->Size;
+ //
+ // Optional parse: Flags = 0xFFF0000,
+ //
+ if (SFPIsKeyword ("Flags")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Flags)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // comma
+ //
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ }
+ //
+ // Optional parse: Alignment = 4
+ //
+ if (SFPIsKeyword ("Alignment")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&FBlockDesc->Alignment)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // comma
+ //
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ }
+ //
+ // Parse: Attributes = "String",
+ //
+ if (!SFPIsKeyword ("Attributes")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Parse: AreaType = "String",
+ //
+ if (!SFPIsKeyword ("AreaType")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ PreviousComma = SFPIsToken (",");
+ //
+ // Parse optional Subregion definitions
+ //
+ SubregionSizeLeft = FBlockDesc->Size;
+ while (SFPIsToken ("Subregion")) {
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);
+ WarningCount++;
+ PreviousComma = TRUE;
+ }
+
+ Subregion = ParseSubregionDefinition (SubregionSizeLeft);
+ if (Subregion == NULL) {
+ ErrorCount++;
+ goto Done;
+ }
+
+ SubregionSizeLeft -= Subregion->Size;
+ //
+ // Add it to the end of our list
+ //
+ if (FBlockDesc->Subregions == NULL) {
+ FBlockDesc->Subregions = Subregion;
+ } else {
+ FBlockDesc->LastSubregion->Next = Subregion;
+ }
+
+ FBlockDesc->LastSubregion = Subregion;
+ //
+ // Make sure all subregion names are unique. We do this each time
+ // through so that we catch the error immediately after it happens, in
+ // which case the reported line number is at least close to where the
+ // problem lies. We don't exit on the error because we can continue parsing
+ // the script to perhaps catch other errors or warnings.
+ //
+ for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {
+ if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");
+ ErrorCount++;
+ }
+ }
+ }
+ }
+
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add the region descriptor to the end of the linked list
+ //
+ if (FDDesc->LastRegion != NULL) {
+ FDDesc->LastRegion->Next = FBlockDesc;
+ } else {
+ FDDesc->Regions = FBlockDesc;
+ }
+
+ FDDesc->LastRegion = FBlockDesc;
+ }
+ //
+ // Make sure sum of sizes of regions adds up to size of flash device
+ //
+ if (RegionSizeLeft != 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ NULL,
+ "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",
+ FDDesc->Size - RegionSizeLeft,
+ FDDesc->Size,
+ RegionSizeLeft
+ );
+ ErrorCount++;
+ }
+ //
+ // Look for closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);
+ WarningCount++;
+ }
+ //
+ // Add this flash description to the list
+ //
+ FDDesc->Next = mFlashDevices;
+ mFlashDevices = FDDesc;
+ }
+
+ while (SFPIsKeyword ("FlashDeviceImage")) {
+ //
+ // Allocate memory for a new FD image definition
+ //
+ ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));
+ if (ImageDef == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "ImageName",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);
+ WarningCount++;
+ }
+
+ while (1) {
+ //
+ // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }
+ //
+ if (SFPIsKeyword ("File")) {
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
+ if (ImageDefEntry == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "FileName.txt"
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Region = "REGION_NAME"
+ //
+ if (!SFPIsKeyword ("Region")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse optional: Subregion = "SUBREGION_NAME"
+ //
+ if (SFPIsKeyword ("Subregion")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
+ WarningCount++;
+ }
+ //
+ // For a given region, you can only place data using the region name, or the subregion names.
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
+ // here by checking that any previous entries with the same Region name had a Subregion specified
+ // as well.
+ //
+ for (TempImageDefEntry = ImageDef->Entries;
+ TempImageDefEntry != NULL;
+ TempImageDefEntry = TempImageDefEntry->Next
+ ) {
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
+ if (TempImageDefEntry->SubregionName[0] == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempImageDefEntry->RegionName,
+ "data already placed on a region-basis in the region, can't place data using subregions"
+ );
+ ErrorCount++;
+ }
+ }
+ }
+ }
+ //
+ // Optional parse: Optional = TRUE | FALSE
+ //
+ if (SFPIsKeyword ("Optional")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsKeyword ("TRUE")) {
+ ImageDefEntry->Optional = 1;
+ } else if (SFPIsKeyword ("FALSE")) {
+ //
+ // Already set to 0
+ //
+ } else {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ }
+ //
+ // Closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Add the entry to the end of the list
+ //
+ if (ImageDef->LastEntry != NULL) {
+ ImageDef->LastEntry->Next = ImageDefEntry;
+ } else {
+ ImageDef->Entries = ImageDefEntry;
+ }
+
+ ImageDef->LastEntry = ImageDefEntry;
+ } else if (SFPIsKeyword ("RawData")) {
+ //
+ // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}
+ //
+ ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));
+ if (ImageDefEntry == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));
+ ImageDefEntry->IsRawData = 1;
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected '{' opening brace for RawData definition",
+ NULL
+ );
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "PadBytes"
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Region = "REGION_NAME"
+ //
+ if (!SFPIsKeyword ("Region")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse optional: Subregion = "SUBREGION_NAME"
+ //
+ if (SFPIsKeyword ("Subregion")) {
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);
+ WarningCount++;
+ }
+ //
+ // For a given region, you can only place data using the region name, or the subregion names.
+ // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that
+ // here by checking that any previous entries with the same Region name had a Subregion specified
+ // as well.
+ //
+ for (TempImageDefEntry = ImageDef->Entries;
+ TempImageDefEntry != NULL;
+ TempImageDefEntry = TempImageDefEntry->Next
+ ) {
+ if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {
+ if (TempImageDefEntry->SubregionName[0] == 0) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ TempImageDefEntry->RegionName,
+ "data already placed on a region-basis in the region, can't place data using subregions"
+ );
+ ErrorCount++;
+ }
+ }
+ }
+ }
+ //
+ // Parse: Data = { 0x78, 0x56, 0x34, 0x12 }
+ //
+ if (!SFPIsKeyword ("Data")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);
+ WarningCount++;
+ }
+
+ if ((BufferData = CreateBufferData ()) == NULL) {
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Read bytes from input file until closing brace
+ //
+ while (!SFPIsToken ("}")) {
+ if (!SFPGetNumber (&Num)) {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);
+ ErrorCount++;
+ FreeBufferData (BufferData, TRUE);
+ goto Done;
+ } else {
+ //
+ // Only allow bytes
+ //
+ if (Num > 0xFF) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);
+ ErrorCount++;
+ FreeBufferData (BufferData, TRUE);
+ goto Done;
+ }
+
+ AddBufferDataByte (BufferData, (char) Num);
+ SFPIsToken (",");
+ }
+ }
+ //
+ // Now get the data and save it in our image entry
+ //
+ ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);
+ FreeBufferData (BufferData, 0);
+ //
+ // Closing brace for RawData {}
+ //
+ if (!SFPIsToken ("}")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Add the entry to the end of the list
+ //
+ if (ImageDef->LastEntry != NULL) {
+ ImageDef->LastEntry->Next = ImageDefEntry;
+ } else {
+ ImageDef->Entries = ImageDefEntry;
+ }
+
+ ImageDef->LastEntry = ImageDefEntry;
+ } else if (SFPIsToken ("}")) {
+ //
+ // Closing brace for FDImage {}
+ //
+ break;
+ } else {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);
+ ErrorCount++;
+ goto Done;
+ }
+ }
+ //
+ // Add this image definition to our global list
+ //
+ ImageDef->Next = mImageDefinitions;
+ mImageDefinitions = ImageDef;
+ }
+ //
+ // Check for end-of-file
+ //
+ if (!SFPIsEOF ()) {
+ SFPGetNextToken (Str, sizeof (Str));
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);
+ ErrorCount++;
+ }
+
+Done:
+ SFPCloseFile ();
+ if (ErrorCount != 0) {
+ return STATUS_ERROR;
+ } else if (WarningCount != 0) {
+ return STATUS_WARNING;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+FLASH_SUBREGION_DESCRIPTION *
+ParseSubregionDefinition (
+ unsigned int SizeLeft
+ )
+/*++
+
+Routine Description:
+
+ Parse Subregion definitions from the input flash definition file. Format:
+
+ Subregion {
+ CreateHob = TRUE,
+ Name = "FOO",
+ Size = 0xA000,
+ Attributes = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",
+ AreaType = "EFI_FLASH_AREA_EFI_VARIABLES",
+ NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),
+ AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
+ FileSystemGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)
+ }
+
+ NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.
+
+Arguments:
+
+ SizeLeft - in the flash definition file, a Region can be broken up into
+ one or more subregions. As we parse the subregion definitions,
+ the caller keeps track of how much space is left in the region
+ that we're parsing subregions for. SizeLeft is that size, and
+ so the size of the subregion we're now parsing better not
+ exceed the size left.
+ Returns:
+
+ NULL - unrecoverable errors detected while parsing the subregion definition
+
+ pointer to a subregion definition created from the parsed subregion
+
+--*/
+{
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ int ErrorCount;
+ int WarningCount;
+ unsigned int Number;
+ BOOLEAN PreviousComma;
+ //
+ // Allocate memory for the new subregion descriptor
+ //
+ ErrorCount = 0;
+ WarningCount = 0;
+ Subregion = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));
+ if (Subregion == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));
+ //
+ // Open brace -- warning if not there
+ //
+ if (!SFPIsToken ("{")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: CreateHob = TRUE | FALSE,
+ //
+ if (!SFPIsKeyword ("CreateHob")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ Subregion->CreateHob = 1;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Subregion->CreateHob = 0; -- not required since we did a memset earlier
+ //
+ } else {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Name = "Name",
+ //
+ if (!SFPIsKeyword ("Name")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);
+ WarningCount++;
+ }
+ //
+ // Parse: Size = 0x2000,
+ //
+ if (!SFPIsKeyword ("Size")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPGetNumber (&Subregion->Size)) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ //
+ // Check that the size does not exceed the size left passed in
+ //
+ if (Subregion->Size > SizeLeft) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);
+ }
+ //
+ // Parse: Attributes = Number | "String",
+ //
+ if (!SFPIsKeyword ("Attributes")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetNumber (&Number)) {
+ sprintf (Subregion->Attributes, "0x%X", Number);
+ } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);
+ }
+ //
+ // Parse: AreaType = Number | "String",
+ // AreaType is a UINT8, so error if it exceeds the size
+ //
+ if (!SFPIsKeyword ("AreaType")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetNumber (&Number)) {
+ if (Number > 0xFF) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);
+ ErrorCount++;
+ }
+
+ sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);
+ } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken (",")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);
+ }
+ //
+ // Parse the three GUIDs (last two are optional)
+ //
+ // NameGuid = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")
+ // AreaTypeGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
+ // FileSysteGuid = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")
+ //
+ if (!SFPIsKeyword ("NameGuid")) {
+ Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);
+ ErrorCount++;
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+ //
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string
+ //
+ if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+ //
+ // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid
+ //
+ PreviousComma = SFPIsToken (",");
+ if (SFPIsKeyword ("AreaTypeGuid")) {
+ //
+ // Check for preceeding comma now
+ //
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+
+ if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+
+ PreviousComma = SFPIsToken (",");
+ }
+
+ if (SFPIsKeyword ("FileSystemGuid")) {
+ //
+ // Check for preceeding comma now
+ //
+ if (!PreviousComma) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);
+ WarningCount++;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);
+ WarningCount++;
+ }
+ //
+ // Allow a GUID or a quoted string identifier, which we'll just copy as a string
+ //
+ if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {
+ //
+ // Nothing else to do
+ //
+ } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {
+ Error (
+ SFPGetFileName (),
+ SFPGetLineNumber (),
+ 0,
+ "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",
+ NULL
+ );
+ ErrorCount++;
+ goto Done;
+ }
+
+ SFPIsToken (",");
+ }
+ //
+ // Look for subregion closing brace
+ //
+ if (!SFPIsToken ("}")) {
+ Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);
+ WarningCount++;
+ }
+
+Done:
+ //
+ // If any errors were encountered, then delete the subregion definition
+ //
+ if (ErrorCount != 0) {
+ _free (Subregion);
+ Subregion = NULL;
+ }
+
+ return Subregion;
+}
+
+STATUS
+FDFCreateCIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a header file with #define definitions per an already-parsed
+ flash definition file.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int Offset;
+ unsigned int SubregionOffset;
+ int CreateHobs;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write a header
+ //
+ fprintf (OutFptr, CIncludeHeader);
+ //
+ // Write flash block base and size defines
+ //
+ fprintf (OutFptr, "#define FLASH_BASE 0x%08X\n", FDev->BaseAddress);
+ fprintf (OutFptr, "#define FLASH_SIZE 0x%08X\n\n", FDev->Size);
+ //
+ // Write flash regions base, size and offset defines
+ //
+ Offset = 0;
+ CreateHobs = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_BASE %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset + FDev->BaseAddress
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SIZE %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_OFFSET %*c0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_BASE %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_SIZE %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+ SubregionOffset += Subregion->Size;
+ if (Subregion->CreateHob != 0) {
+ CreateHobs = 1;
+ }
+ }
+
+ Offset += FBlock->Size;
+ }
+ //
+ // Now create a #define for the flash map data definition
+ //
+ fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");
+ //
+ // Emit entry for each region
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (OutFptr, " /* %s region */\\\n", FBlock->Name);
+ fprintf (OutFptr, " {\\\n");
+ fprintf (OutFptr, " FLASH_REGION_%s_BASE,\\\n", FBlock->Name);
+ fprintf (OutFptr, " FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);
+ fprintf (OutFptr, " %s,\\\n", FBlock->Attributes);
+ fprintf (OutFptr, " %s,\\\n },\\\n", FBlock->AreaType);
+ }
+
+ fprintf (OutFptr, "\n\n");
+ //
+ // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition
+ //
+ if (CreateHobs != 0) {
+ fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");
+ fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ //
+ // See if the block has subregions, and that the CreateHobs flag is set
+ // for any of them.
+ //
+ CreateHobs = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ if (Subregion->CreateHob != 0) {
+ CreateHobs = 1;
+ break;
+ }
+ }
+ //
+ // If any of the subregions had the CreateHobs flag set, then create the entries in the
+ // output file
+ //
+ if (CreateHobs != 0) {
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ if (Subregion->CreateHob != 0) {
+ fprintf (OutFptr, " \\\n");
+ fprintf (OutFptr, " /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);
+ fprintf (OutFptr, " {\\\n");
+ fprintf (OutFptr, " EFI_HOB_TYPE_GUID_EXTENSION,\\\n");
+ fprintf (OutFptr, " sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");
+ fprintf (OutFptr, " 0,\\\n");
+ //
+ // The NameGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->NameGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->NameGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",
+ Subregion->NameGuid.Data1,
+ (unsigned int) Subregion->NameGuid.Data2,
+ (unsigned int) Subregion->NameGuid.Data3,
+ (unsigned int) Subregion->NameGuid.Data4[0],
+ (unsigned int) Subregion->NameGuid.Data4[1],
+ (unsigned int) Subregion->NameGuid.Data4[2],
+ (unsigned int) Subregion->NameGuid.Data4[3],
+ (unsigned int) Subregion->NameGuid.Data4[4],
+ (unsigned int) Subregion->NameGuid.Data4[5],
+ (unsigned int) Subregion->NameGuid.Data4[6],
+ (unsigned int) Subregion->NameGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " 0, 0, 0,\\\n");
+ fprintf (OutFptr, " %s,\\\n", Subregion->AreaType);
+ //
+ // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->AreaTypeGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->AreaTypeGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",
+ Subregion->AreaTypeGuid.Data1,
+ (unsigned int) Subregion->AreaTypeGuid.Data2,
+ (unsigned int) Subregion->AreaTypeGuid.Data3,
+ (unsigned int) Subregion->AreaTypeGuid.Data4[0],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[1],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[2],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[3],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[4],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[5],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[6],
+ (unsigned int) Subregion->AreaTypeGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " 1,\\\n");
+ fprintf (OutFptr, " {\\\n");
+ fprintf (OutFptr, " %s,\\\n", Subregion->Attributes);
+ fprintf (OutFptr, " 0,\\\n");
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);
+ fprintf (OutFptr, " FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);
+ //
+ // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or
+ // as a quoted string. Do the right one.
+ //
+ if (Subregion->FileSystemGuidString[0] != 0) {
+ fprintf (OutFptr, " %s, \\\n", Subregion->FileSystemGuidString);
+ } else {
+ fprintf (
+ OutFptr,
+ " { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",
+ Subregion->FileSystemGuid.Data1,
+ (unsigned int) Subregion->FileSystemGuid.Data2,
+ (unsigned int) Subregion->FileSystemGuid.Data3,
+ (unsigned int) Subregion->FileSystemGuid.Data4[0],
+ (unsigned int) Subregion->FileSystemGuid.Data4[1],
+ (unsigned int) Subregion->FileSystemGuid.Data4[2],
+ (unsigned int) Subregion->FileSystemGuid.Data4[3],
+ (unsigned int) Subregion->FileSystemGuid.Data4[4],
+ (unsigned int) Subregion->FileSystemGuid.Data4[5],
+ (unsigned int) Subregion->FileSystemGuid.Data4[6],
+ (unsigned int) Subregion->FileSystemGuid.Data4[7]
+ );
+ }
+
+ fprintf (OutFptr, " },\\\n");
+ fprintf (OutFptr, " },");
+ }
+ }
+ }
+ }
+
+ fprintf (OutFptr, "\n\n");
+ }
+
+ //
+ // Write the file's closing #endif
+ //
+ fprintf (OutFptr, CIncludeFooter);
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateAsmIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create an assembly header file with equate definitions per an already-parsed
+ flash definition file.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write a header
+ //
+ fprintf (OutFptr, "\n\n");
+ //
+ // Write flash block size and offset defines
+ //
+ fprintf (
+ OutFptr,
+ "FLASH_BASE %*cequ 0%08Xh\n",
+ COLUMN2_START - 40,
+ ' ',
+ FDev->BaseAddress
+ );
+ fprintf (OutFptr, "FLASH_SIZE %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);
+ //
+ // Write flash region size and offset defines
+ //
+ fprintf (OutFptr, "\n");
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_BASE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ FDev->BaseAddress + Offset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",
+ FBlock->Name,
+ COLUMN2_START - 20 - strlen (FBlock->Name),
+ ' ',
+ Offset
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*cequ 0%08Xh\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+ SubregionOffset += Subregion->Size;
+ }
+
+ Offset += FBlock->Size;
+ }
+
+ //
+ // Write closing \n
+ //
+ fprintf (OutFptr, "\n\n");
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateSymbols (
+ char *FlashDeviceName
+ )
+/*++
+
+Routine Description:
+ Using the given flash device name, add symbols to the global symbol table. This
+ allows other functions to use the symbol definitions for other purposes.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ char SymName[120];
+ char SymValue[120];
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress);
+ SymbolAdd ("FLASH_BASE", SymValue, 0);
+ sprintf (SymValue, "0x%08X", FDev->Size);
+ SymbolAdd ("FLASH_SIZE", SymValue, 0);
+ //
+ // Add flash block size and offset defines
+ //
+ // Offset = 0;
+ // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {
+ // sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
+ // SymbolAdd (SymName, SymValue, 0);
+ // sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", FBlock->Size);
+ // SymbolAdd (SymName, SymValue, 0);
+ // sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);
+ // sprintf (SymValue, "0x%08X", Offset);
+ // SymbolAdd (SymName, SymValue, 0);
+ // Offset += FBlock->Size;
+ // }
+ //
+ // Add flash region block base, size, and offset defines
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);
+ sprintf (SymValue, "0x%08X", FBlock->Size);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);
+ sprintf (SymValue, "0x%08X", Offset);
+ SymbolAdd (SymName, SymValue, 0);
+ //
+ // Add subregion symbols
+ //
+ if (FBlock->Subregions != NULL) {
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", Subregion->Size);
+ SymbolAdd (SymName, SymValue, 0);
+ sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);
+ sprintf (SymValue, "0x%08X", Offset + SubregionOffset);
+ SymbolAdd (SymName, SymValue, 0);
+ SubregionOffset += Subregion->Size;
+ }
+ }
+
+ Offset += FBlock->Size;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+STATUS
+FDFCreateImage (
+ char *FlashDeviceName,
+ char *ImageName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a flash image using the given device and image names.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ ImageName - name of image (from the flash definition file) to create
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ STATUS Status;
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *RegionDef;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ IMAGE_DEFINITION *ImageDef;
+ unsigned int Offset;
+ char *Buffer;
+ FILE *InFptr;
+ long FileSize;
+ IMAGE_DEFINITION_ENTRY *IDefEntry;
+ FLASH_SUBREGION_DESCRIPTION *SubregionDef;
+ //
+ // Find the flash definition we're supposed to use
+ //
+ InFptr = NULL;
+ Status = STATUS_ERROR;
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+ //
+ // Find the image name we're supposed to create
+ //
+ for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {
+ if (strcmp (ImageDef->Name, ImageName) == 0) {
+ break;
+ }
+ }
+
+ if (ImageDef == NULL) {
+ Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Allocate a buffer to copy the input data to
+ //
+ Buffer = (char *) _malloc (FDev->Size);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);
+ goto Done;
+ }
+ //
+ // Set contents of buffer to the erased value
+ //
+ if (FDev->ErasePolarity) {
+ memset (Buffer, 0xFF, FDev->Size);
+ } else {
+ memset (Buffer, 0, FDev->Size);
+ }
+ //
+ // Set all region and subregion size-left fields to the size of the region/subregion
+ //
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
+ RegionDef->SizeLeft = RegionDef->Size;
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
+ SubregionDef->SizeLeft = SubregionDef->Size;
+ }
+ }
+ //
+ // Now go through the image list, read files into the buffer.
+ //
+ for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {
+ //
+ // If it's a file name, open the file, get the size, find the corresponding
+ // flash region it's in, and copy the data.
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");
+ goto Done;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ } else {
+ FileSize = IDefEntry->RawDataSize;
+ }
+ //
+ // Find the region/subregion it's in, see if we have space left
+ //
+ Offset = 0;
+ for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {
+ if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {
+ break;
+ }
+
+ Offset += RegionDef->Size;
+ }
+
+ if (RegionDef == NULL) {
+ Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);
+ goto Done;
+ }
+
+ //
+ // Check for subregion
+ //
+ if (IDefEntry->SubregionName[0] != 0) {
+ for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {
+ if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {
+ break;
+ }
+
+ Offset += SubregionDef->Size;
+ }
+
+ if (SubregionDef == NULL) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->SubregionName,
+ "Subregion name not found in FlashDevice %s.%s Region definition",
+ FDev->Name,
+ RegionDef->Name
+ );
+ goto Done;
+ }
+ //
+ // Enough space in the subregion?
+ //
+ if (SubregionDef->SizeLeft < (unsigned int) FileSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->Name,
+ "insufficient space in Subregion (at least 0x%X additional bytes required)",
+ FileSize - SubregionDef->SizeLeft
+ );
+ goto Done;
+ }
+
+ //
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
+ goto Done;
+ }
+
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ memcpy (
+ Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),
+ IDefEntry->RawData,
+ IDefEntry->RawDataSize
+ );
+ }
+
+ SubregionDef->SizeLeft -= FileSize;
+ //
+ // Align based on the Region alignment requirements.
+ //
+ if (RegionDef->Alignment != 0) {
+ while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
+ if (SubregionDef->SizeLeft == 0) {
+ break;
+ }
+
+ SubregionDef->SizeLeft--;
+ }
+ }
+ } else {
+ //
+ // Placing data in a region. Check for enough space in the region left.
+ //
+ if (RegionDef->SizeLeft < (unsigned int) FileSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ IDefEntry->Name,
+ "insufficient space in Region (at least 0x%X additional bytes required)",
+ FileSize - RegionDef->SizeLeft
+ );
+ goto Done;
+ }
+
+ //
+ // Read the file into the buffer if it's a file. Otherwise copy the raw data
+ //
+ if (IDefEntry->IsRawData == 0) {
+ if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");
+ goto Done;
+ }
+
+ fclose (InFptr);
+ InFptr = NULL;
+ } else {
+ memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);
+ }
+
+ RegionDef->SizeLeft -= FileSize;
+ //
+ // Align
+ //
+ if (RegionDef->Alignment != 0) {
+ while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {
+ if (RegionDef->SizeLeft == 0) {
+ break;
+ }
+
+ RegionDef->SizeLeft--;
+ }
+ }
+ }
+ }
+
+ if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);
+ goto Done;
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (Buffer != NULL) {
+ _free (Buffer);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (Status == STATUS_ERROR) {
+ remove (FileName);
+ }
+ }
+
+ return Status;
+}
+
+STATUS
+FDFCreateDscFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+ Create a DSC-style output file with equates for flash management.
+
+Arguments:
+ FlashDeviceName - name of flash device (from the flash definition file)
+ to use
+ FileName - name of output file to create
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *OutFptr;
+ FLASH_BLOCK_DESCRIPTION *FBlock;
+ FLASH_DEVICE_DESCRIPTION *FDev;
+ unsigned int Offset;
+ FLASH_SUBREGION_DESCRIPTION *Subregion;
+ unsigned int SubregionOffset;
+ //
+ // Find the definition we're supposed to use
+ //
+ for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {
+ if (strcmp (FDev->Name, FlashDeviceName) == 0) {
+ break;
+ }
+ }
+
+ if (FDev == NULL) {
+ Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");
+ return STATUS_ERROR;
+ }
+
+ if ((OutFptr = fopen (FileName, "w")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Write the flash base address and size
+ //
+ fprintf (OutFptr, "\n");
+ fprintf (OutFptr, "FLASH_BASE = 0x%08X\n", FDev->BaseAddress);
+ fprintf (OutFptr, "FLASH_SIZE = 0x%08X\n\n", FDev->Size);
+ //
+ // Write flash block size and offset defines
+ //
+ Offset = 0;
+ for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_BASE %*c= 0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ Offset + FDev->BaseAddress
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE %*c= 0x%08X\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ FBlock->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SIZE_BLOCKS %*c= 0x%x\n",
+ FBlock->Name,
+ COLUMN2_START - 40 - strlen (FBlock->Name),
+ ' ',
+ (FBlock->Size)/(FDev->PBlocks->Size)
+ );
+ //
+ // Create defines for any subregions
+ //
+ SubregionOffset = 0;
+ for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_BASE %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ FDev->BaseAddress + Offset + SubregionOffset
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_SIZE %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Subregion->Size
+ );
+ fprintf (
+ OutFptr,
+ "FLASH_REGION_%s_SUBREGION_%s_OFFSET %*c= 0x%08X\n",
+ FBlock->Name,
+ Subregion->Name,
+ COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),
+ ' ',
+ Offset + SubregionOffset
+ );
+
+ SubregionOffset += Subregion->Size;
+ }
+
+ Offset += FBlock->Size;
+ }
+ //
+ // Close file
+ //
+ fprintf (OutFptr, "\n");
+ fclose (OutFptr);
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+ The following buffer management routines are used to encapsulate functionality
+ for managing a growable data buffer.
+
+Arguments:
+ BUFFER_DATA - structure that is used to maintain a data buffer
+
+Returns:
+ NA
+
+--*/
+static
+BUFFER_DATA *
+CreateBufferData (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Create a growable data buffer with default buffer length.
+
+Arguments:
+
+ None
+
+Returns:
+
+ NULL - error occured during data buffer creation
+ Not NULL - the pointer to the newly created data buffer
+
+--*/
+{
+ BUFFER_DATA *BD;
+ BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));
+ if (BD == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return NULL;
+ }
+
+ memset (BD, 0, sizeof (BUFFER_DATA));
+ BD->BufferStart = (char *) _malloc (BUFFER_SIZE);
+ if (BD->BufferStart == NULL) {
+ _free (BD);
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return NULL;
+ }
+
+ BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;
+ BD->BufferPos = BD->BufferStart;
+ return BD;
+}
+
+static
+BOOLEAN
+AddBufferDataByte (
+ BUFFER_DATA *Buffer,
+ char Data
+ )
+/*++
+
+Routine Description:
+
+ Add a single byte to a growable data buffer, growing the buffer if required.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer to add a single byte to
+ Data - value of the single byte data to be added
+
+Returns:
+
+ TRUE - the single byte data was successfully added
+ FALSE - error occurred, the single byte data was not added
+
+--*/
+{
+ int Size;
+ char *NewBuffer;
+ //
+ // See if we have to grow the buffer
+ //
+ if (Buffer->BufferPos >= Buffer->BufferEnd) {
+ Size = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;
+ NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);
+ if (NewBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
+ return FALSE;
+ }
+
+ memcpy (NewBuffer, Buffer->BufferStart, Size);
+ _free (Buffer->BufferStart);
+ Buffer->BufferStart = NewBuffer;
+ Buffer->BufferPos = Buffer->BufferStart + Size;
+ Buffer->BufferEnd = Buffer->BufferStart + Size + BUFFER_SIZE;
+ }
+
+ *Buffer->BufferPos = Data;
+ Buffer->BufferPos++;
+ return TRUE;
+}
+
+static
+void
+FreeBufferData (
+ BUFFER_DATA *Buffer,
+ BOOLEAN FreeData
+ )
+/*++
+
+Routine Description:
+
+ Free memory used to manage a growable data buffer.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer to be destructed
+ FreeData - TRUE, free memory containing the buffered data
+ FALSE, do not free the buffered data memory
+
+Returns:
+
+ None
+
+--*/
+{
+ if (Buffer != NULL) {
+ if (FreeData && (Buffer->BufferStart != NULL)) {
+ _free (Buffer->BufferStart);
+ }
+
+ _free (Buffer);
+ }
+}
+
+static
+char *
+GetBufferData (
+ BUFFER_DATA *Buffer,
+ int *BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Return a pointer and size of the data in a growable data buffer.
+
+Arguments:
+
+ Buffer - pointer to the growable data buffer
+ BufferSize - size of the data in the growable data buffer
+
+Returns:
+
+ pointer of the data in the growable data buffer
+
+--*/
+{
+ *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;
+ return Buffer->BufferStart;
+}
+
+STATUS
+FDDiscover (
+ char *FDFileName,
+ unsigned int BaseAddr
+ )
+/*++
+
+Routine Description:
+ Walk a binary image and see if you find anything that looks like a
+ firmware volume.
+
+Arguments:
+ FDFileName - name of input FD image to parse
+ BaseAddr - base address of input FD image
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_WARNING - warnings, but no errors, were encountered
+ STATUS_ERROR - errors were encountered
+
+NOTE:
+ This routine is used for debug purposes only.
+
+--*/
+{
+ FILE *InFptr;
+ long FileSize;
+ long Offset;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+ EFI_GUID
+ FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };
+
+ if ((InFptr = fopen (FDFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FDFileName, "failed to open file for reading");
+ return STATUS_ERROR;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ Offset = 0;
+ while (Offset < FileSize) {
+ fseek (InFptr, Offset, SEEK_SET);
+ //
+ // Read the contents of the file, see if it's an FV header
+ //
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {
+ //
+ // Check version and GUID
+ //
+ if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {
+ fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);
+ if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {
+ fprintf (stdout, "standard FFS file system\n");
+ } else {
+ fprintf (stdout, "non-standard FFS file system\n");
+ }
+ }
+ }
+
+ Offset += 16 * 1024;
+ }
+
+ fclose (InFptr);
+ return STATUS_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/FlashMap/FlashDefFile.h b/Tools/Source/TianoTools/FlashMap/FlashDefFile.h
new file mode 100644
index 0000000..1ffbfb1
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/FlashDefFile.h
@@ -0,0 +1,281 @@
+/*++
+
+Copyright (c) 2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ FlashDefFile.h
+
+Abstract:
+
+ Header file for flash management utility in the Intel Platform
+ Innovation Framework for EFI build environment.
+
+--*/
+
+#ifndef _FLASH_DEF_FILE_H_
+#define _FLASH_DEF_FILE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void
+FDFConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+FDFDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateCIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateCFlashMapDataFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateAsmIncludeFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFParseFile (
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateImage (
+ char *FlashDeviceName,
+ char *ImageName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ ImageName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateDscFile (
+ char *FlashDeviceName,
+ char *FileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+ FileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDFCreateSymbols (
+ char *FlashDeviceName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FlashDeviceName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+FDDiscover (
+ char *FDFileName,
+ unsigned int BaseAddr
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FDFileName - GC_TODO: add argument description
+ BaseAddr - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _FLASH_DEF_FILE_H_
diff --git a/Tools/Source/TianoTools/FlashMap/FlashMap.c b/Tools/Source/TianoTools/FlashMap/FlashMap.c
new file mode 100644
index 0000000..86e26b6
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/FlashMap.c
@@ -0,0 +1,745 @@
+/*++
+
+Copyright (c) 2004-2005 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ FlashMap.c
+
+Abstract:
+
+ Utility for flash management in the Intel Platform Innovation Framework
+ for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "Tiano.h"
+
+#ifndef INT8
+#define INT8 char
+#endif
+
+#include "EfiUtilityMsgs.h"
+#include "Microcode.h"
+#include "FlashDefFile.h"
+#include "Symbols.h"
+
+#define UTILITY_NAME "FlashMap"
+
+typedef struct _STRING_LIST {
+ struct _STRING_LIST *Next;
+ char *Str;
+} STRING_LIST;
+
+//
+// Keep our globals in one of these structures
+//
+static struct {
+ char *CIncludeFileName;
+ char *FlashDevice;
+ char *FlashDeviceImage;
+ char *MCIFileName;
+ char *MCOFileName;
+ char *ImageOutFileName;
+ char *DscFileName;
+ char *AsmIncludeFileName;
+ char *FlashDefinitionFileName;
+ char *StringReplaceInFileName;
+ char *StringReplaceOutFileName;
+ char *DiscoverFDImageName;
+ char MicrocodePadByteValue;
+ unsigned int MicrocodeAlignment;
+ STRING_LIST *MCIFileNames;
+ STRING_LIST *LastMCIFileNames;
+ unsigned int BaseAddress;
+} mGlobals;
+
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
+#define DEFAULT_MC_ALIGNMENT 16
+
+static
+STATUS
+ProcessCommandLine (
+ int argc,
+ char *argv[]
+ );
+
+static
+STATUS
+MergeMicrocodeFiles (
+ char *OutFileName,
+ STRING_LIST *FileNames,
+ unsigned int Alignment,
+ char PadByteValue
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+ Parse the command line arguments and then call worker functions to do the work
+
+Arguments:
+ argc - number of elements in argv
+ argv - array of command-line arguments
+
+Returns:
+ STATUS_SUCCESS - no problems encountered while processing
+ STATUS_WARNING - warnings, but no errors, were encountered while processing
+ STATUS_ERROR - errors were encountered while processing
+
+--*/
+{
+ STATUS Status;
+
+ SetUtilityName (UTILITY_NAME);
+ Status = ProcessCommandLine (argc, argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+ //
+ // Check for discovery of an FD (command line option)
+ //
+ if (mGlobals.DiscoverFDImageName != NULL) {
+ Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress);
+ goto Done;
+ }
+ //
+ // If they're doing microcode file parsing, then do that
+ //
+ if (mGlobals.MCIFileName != NULL) {
+ MicrocodeConstructor ();
+ MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName);
+ MicrocodeDestructor ();
+ }
+ //
+ // If they're doing microcode file merging, then do that now
+ //
+ if (mGlobals.MCIFileNames != NULL) {
+ MergeMicrocodeFiles (
+ mGlobals.MCOFileName,
+ mGlobals.MCIFileNames,
+ mGlobals.MicrocodeAlignment,
+ mGlobals.MicrocodePadByteValue
+ );
+ }
+ //
+ // If using a flash definition file, then process that and return
+ //
+ if (mGlobals.FlashDefinitionFileName != NULL) {
+ FDFConstructor ();
+ SymbolsConstructor ();
+ Status = FDFParseFile (mGlobals.FlashDefinitionFileName);
+ if (GetUtilityStatus () != STATUS_ERROR) {
+ //
+ // If they want us to do a string-replace on a file, then add the symbol definitions to
+ // the symbol table, and then do the string replace.
+ //
+ if (mGlobals.StringReplaceInFileName != NULL) {
+ Status = FDFCreateSymbols (mGlobals.FlashDevice);
+ Status = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName);
+ }
+ //
+ // If they want us to create a .h defines file or .c flashmap data file, then do so now
+ //
+ if (mGlobals.CIncludeFileName != NULL) {
+ Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName);
+ }
+ if (mGlobals.AsmIncludeFileName != NULL) {
+ Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName);
+ }
+ //
+ // If they want us to create an image, do that now
+ //
+ if (mGlobals.ImageOutFileName != NULL) {
+ Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName);
+ }
+ //
+ // If they want to create an output DSC file, do that now
+ //
+ if (mGlobals.DscFileName != NULL) {
+ Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName);
+ }
+ }
+ SymbolsDestructor ();
+ FDFDestructor ();
+ }
+Done:
+ //
+ // Free up memory
+ //
+ while (mGlobals.MCIFileNames != NULL) {
+ mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next;
+ _free (mGlobals.MCIFileNames);
+ mGlobals.MCIFileNames = mGlobals.LastMCIFileNames;
+ }
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+MergeMicrocodeFiles (
+ char *OutFileName,
+ STRING_LIST *FileNames,
+ unsigned int Alignment,
+ char PadByteValue
+ )
+/*++
+
+Routine Description:
+
+ Merge binary microcode files into a single file, taking into consideration
+ the alignment and pad value.
+
+Arguments:
+
+ OutFileName - name of the output file to create
+ FileNames - linked list of input microcode files to merge
+ Alignment - alignment for each microcode file in the output image
+ PadByteValue - value to use when padding to meet alignment requirements
+
+Returns:
+
+ STATUS_SUCCESS - merge completed successfully or with acceptable warnings
+ STATUS_ERROR - merge failed, output file not created
+
+--*/
+{
+ long FileSize;
+ long TotalFileSize;
+ FILE *InFptr;
+ FILE *OutFptr;
+ char *Buffer;
+ STATUS Status;
+
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+ //
+ // Walk the list of files
+ //
+ Status = STATUS_ERROR;
+ Buffer = NULL;
+ InFptr = NULL;
+ TotalFileSize = 0;
+ while (FileNames != NULL) {
+ //
+ // Open the file, determine the size, then read it in and write
+ // it back out.
+ //
+ if ((InFptr = fopen (FileNames->Str, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileNames->Str, "failed to open input file for reading");
+ goto Done;
+ }
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+ if (FileSize != 0) {
+ Buffer = (char *) _malloc (FileSize);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto Done;
+ }
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileNames->Str, "failed to read file contents");
+ goto Done;
+ }
+ //
+ // Align
+ //
+ if (Alignment != 0) {
+ while ((TotalFileSize % Alignment) != 0) {
+ if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file");
+ goto Done;
+ }
+ TotalFileSize++;
+ }
+ }
+ TotalFileSize += FileSize;
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write to output file");
+ goto Done;
+ }
+ _free (Buffer);
+ Buffer = NULL;
+ } else {
+ Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered");
+ }
+ fclose (InFptr);
+ InFptr = NULL;
+ FileNames = FileNames->Next;
+ }
+ Status = STATUS_SUCCESS;
+Done:
+ fclose (OutFptr);
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ if (Buffer != NULL) {
+ _free (Buffer);
+ }
+ if (Status == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ return Status;
+}
+
+static
+STATUS
+ProcessCommandLine (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command line arguments
+
+Arguments:
+ argc - Standard C entry point arguments
+ argv[] - Standard C entry point arguments
+
+Returns:
+ STATUS_SUCCESS - no problems encountered while processing
+ STATUS_WARNING - warnings, but no errors, were encountered while processing
+ STATUS_ERROR - errors were encountered while processing
+
+--*/
+{
+ int ThingsToDo;
+ unsigned int Temp;
+ STRING_LIST *Str;
+ //
+ // Skip program name arg, process others
+ //
+ argc--;
+ argv++;
+ if (argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Clear out our globals, then start walking the arguments
+ //
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ mGlobals.MicrocodePadByteValue = DEFAULT_MC_PAD_BYTE_VALUE;
+ mGlobals.MicrocodeAlignment = DEFAULT_MC_ALIGNMENT;
+ ThingsToDo = 0;
+ while (argc > 0) {
+ if (strcmp (argv[0], "-?") == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ } else if (strcmp (argv[0], "-hfile") == 0) {
+ //
+ // -hfile FileName
+ //
+ // Used to specify an output C #include file to create that contains
+ // #define statements for all the flashmap region offsets and sizes.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.CIncludeFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-flashdevice") == 0) {
+ //
+ // -flashdevice FLASH_DEVICE_NAME
+ //
+ // Used to select which flash device definition to operate on.
+ // Check for additional argument
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a flash device name to use");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDevice = argv[0];
+ } else if (strcmp (argv[0], "-mco") == 0) {
+ //
+ // -mco OutFileName
+ //
+ // Used to specify a microcode output binary file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.MCOFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-asmincfile") == 0) {
+ //
+ // -asmincfile FileName
+ //
+ // Used to specify the name of the output assembly include file that contains
+ // equates for the flash region addresses and sizes.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.AsmIncludeFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-mci") == 0) {
+ //
+ // -mci FileName
+ //
+ // Used to specify an input microcode text file to parse.
+ // Check for additional argument
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.MCIFileName = argv[0];
+ } else if (strcmp (argv[0], "-flashdeviceimage") == 0) {
+ //
+ // -flashdeviceimage FlashDeviceImage
+ //
+ // Used to specify which flash device image definition from the input flash definition file
+ // to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDeviceImage = argv[0];
+ } else if (strcmp (argv[0], "-imageout") == 0) {
+ //
+ // -imageout FileName
+ //
+ // Used to specify the name of the output FD image file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output image filename to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.ImageOutFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-dsc") == 0) {
+ //
+ // -dsc FileName
+ //
+ // Used to specify the name of the output DSC file to create.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.DscFileName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-fdf") == 0) {
+ //
+ // -fdf FileName
+ //
+ // Used to specify the name of the input flash definition file.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.FlashDefinitionFileName = argv[0];
+ } else if (strcmp (argv[0], "-discover") == 0) {
+ //
+ // -discover FDFileName
+ //
+ // Debug functionality used to scan an existing FD image, trying to find
+ // firmware volumes at 64K boundaries.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an input FD image file name");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.DiscoverFDImageName = argv[0];
+ ThingsToDo++;
+ } else if (strcmp (argv[0], "-baseaddr") == 0) {
+ //
+ // -baseaddr Addr
+ //
+ // Used to specify a base address when doing a discover of an FD image.
+ // Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a base address");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress);
+ } else {
+ sscanf (argv[0], "%d", &mGlobals.BaseAddress);
+ }
+ } else if (strcmp (argv[0], "-padvalue") == 0) {
+ //
+ // -padvalue Value
+ //
+ // Used to specify the value to pad with when aligning data while
+ // creating an FD image. Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires a byte value");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &Temp);
+ mGlobals.MicrocodePadByteValue = (char) Temp;
+ } else {
+ sscanf (argv[0], "%d", &Temp);
+ mGlobals.MicrocodePadByteValue = (char) Temp;
+ }
+ } else if (strcmp (argv[0], "-align") == 0) {
+ //
+ // -align Alignment
+ //
+ // Used to specify how each data file is aligned in the region
+ // when creating an FD image. Check for additional argument.
+ //
+ if (argc < 2) {
+ Error (NULL, 0, 0, argv[0], "option requires an alignment");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ if (tolower (argv[0][1]) == 'x') {
+ sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment);
+ } else {
+ sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment);
+ }
+ } else if (strcmp (argv[0], "-mcmerge") == 0) {
+ //
+ // -mcmerge FileName(s)
+ //
+ // Used to concatenate multiple microde binary files. Can specify
+ // multiple file names with the one -mcmerge flag. Check for additional argument.
+ //
+ if ((argc < 2) || (argv[1][0] == '-')) {
+ Error (NULL, 0, 0, argv[0], "option requires one or more input file names");
+ return STATUS_ERROR;
+ }
+ //
+ // Take input files until another option or end of list
+ //
+ ThingsToDo++;
+ while ((argc > 1) && (argv[1][0] != '-')) {
+ Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST));
+ if (Str == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+ memset (Str, 0, sizeof (STRING_LIST));
+ Str->Str = argv[1];
+ if (mGlobals.MCIFileNames == NULL) {
+ mGlobals.MCIFileNames = Str;
+ } else {
+ mGlobals.LastMCIFileNames->Next = Str;
+ }
+ mGlobals.LastMCIFileNames = Str;
+ argc--;
+ argv++;
+ }
+ } else if (strcmp (argv[0], "-strsub") == 0) {
+ //
+ // -strsub SrcFile DestFile
+ //
+ // Used to perform string substitutions on a file, writing the result to a new
+ // file. Check for two additional arguments.
+ //
+ if (argc < 3) {
+ Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ mGlobals.StringReplaceInFileName = argv[0];
+ argc--;
+ argv++;
+ mGlobals.StringReplaceOutFileName = argv[0];
+ ThingsToDo++;
+ } else {
+ Error (NULL, 0, 0, argv[0], "invalid option");
+ return STATUS_ERROR;
+ }
+ argc--;
+ argv++;
+ }
+ //
+ // If no outputs requested, then report an error
+ //
+ if (ThingsToDo == 0) {
+ Error (NULL, 0, 0, "nothing to do", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want an asm file, #include file, or C file to be created, then they have to specify a
+ // flash device name and flash definition file name.
+ //
+ if ((mGlobals.CIncludeFileName != NULL) &&
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL);
+ return STATUS_ERROR;
+ }
+ if ((mGlobals.AsmIncludeFileName != NULL) &&
+ ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {
+ Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want a dsc file to be created, then they have to specify a
+ // flash device name and a flash definition file name
+ //
+ if (mGlobals.DscFileName != NULL) {
+ if (mGlobals.FlashDevice == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDefinitionFileName == NULL) {
+ Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL);
+ return STATUS_ERROR;
+ }
+ }
+ //
+ // If they specified an output microcode file name, then they have to specify an input
+ // file name, and vice versa.
+ //
+ if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) {
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) {
+ Error (NULL, 0, 0, "must specify input microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If doing merge, then have to specify output file name
+ //
+ if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) {
+ Error (NULL, 0, 0, "must specify output microcode file name", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // If they want an output image to be created, then they have to specify
+ // the flash device and the flash device image to use.
+ //
+ if (mGlobals.ImageOutFileName != NULL) {
+ if (mGlobals.FlashDevice == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDeviceImage == NULL) {
+ Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ if (mGlobals.FlashDefinitionFileName == NULL) {
+ Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL);
+ return STATUS_ERROR;
+ }
+ }
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Print utility command line help
+
+Arguments:
+ None
+
+Returns:
+ NA
+
+--*/
+{
+ int i;
+ char *Msg[] = {
+ "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",
+ " -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",
+ " -discover FDImage -dsc DscFile -asmincfile AsmIncFile",
+ " -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",
+ " -baseaddr BaseAddr -align Alignment -padvalue PadValue",
+ " -mcmerge MCIFile(s)",
+ " where",
+ " FlashDefFile - input Flash Definition File",
+ " FlashDevice - flash device to use (from flash definition file)",
+ " FlashDeviceImage - flash device image to use (from flash definition file)",
+ " MCIFile - input microcode file to parse",
+ " MCOFile - output binary microcode image to create from MCIFile",
+ " HFile - output #include file to create",
+ " FDImage - name of input FDImage file to scan",
+ " ImageOutFile - output image file to create",
+ " DscFile - output DSC file to create",
+ " AsmIncFile - output ASM include file to create",
+ " InStrFile - input file to replace symbol names, writing result to OutStrFile",
+ " BaseAddr - base address of FDImage (used with -discover)",
+ " Alignment - alignment to use when merging microcode binaries",
+ " PadValue - byte value to use as pad value when aligning microcode binaries",
+ " MCIFile(s) - one or more microcode binary files to merge/concatenate",
+ "",
+ NULL
+ };
+ for (i = 0; Msg[i] != NULL; i++) {
+ fprintf (stdout, "%s\n", Msg[i]);
+ }
+}
diff --git a/Tools/Source/TianoTools/FlashMap/Makefile b/Tools/Source/TianoTools/FlashMap/Makefile
new file mode 100644
index 0000000..6b6d011
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/Makefile
@@ -0,0 +1,81 @@
+#/*++
+#
+# Copyright (c) 2004 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+#
+# Module Name:
+#
+# Makefile
+#
+# Abstract:
+#
+# makefile for building the FlashMap utility
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+
+!INCLUDE PlatformTools.env
+
+INCLUDE_PATHS = -I $(TIANO_TOOLS_SOURCE)\Common
+
+#
+# Target specific information
+#
+TARGET_NAME = FlashMap
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\FlashMap.exe
+LIBS = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib"
+
+#
+# Build targets
+#
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\FlashMap.obj \
+ $(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj \
+ $(TIANO_TOOLS_OUTPUT)\Symbols.obj \
+ $(TIANO_TOOLS_OUTPUT)\Microcode.obj
+
+# $(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj
+
+#C_FLAGS = $(C_FLAGS) /D TRACK_MALLOC_FREE
+C_FLAGS = $(C_FLAGS) /D _malloc=malloc /D _free=free
+
+#
+# Compile each source file
+#
+$(TIANO_TOOLS_OUTPUT)\FlashMap.obj : $(TARGET_SRC_DIR)\FlashMap.c $(TARGET_SRC_DIR)\Symbols.h $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\FlashMap.c /Fo$@
+
+$(TIANO_TOOLS_OUTPUT)\Symbols.obj : $(TARGET_SRC_DIR)\Symbols.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\Symbols.c /Fo$@
+
+$(TIANO_TOOLS_OUTPUT)\Microcode.obj : $(TARGET_SRC_DIR)\Microcode.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\Microcode.c /Fo$@
+
+$(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj : $(TARGET_SRC_DIR)\FlashDefFile.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\FlashDefFile.c /Fo$@
+
+$(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj : $(TARGET_SRC_DIR)\TrackMallocFree.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\TrackMallocFree.c /Fo$@
+
+#
+# Link the object files together to create the final executable
+#
+$(TARGET_EXE) : $(OBJECTS) $(LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
diff --git a/Tools/Source/TianoTools/FlashMap/Microcode.c b/Tools/Source/TianoTools/FlashMap/Microcode.c
new file mode 100644
index 0000000..51ae20e
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/Microcode.c
@@ -0,0 +1,306 @@
+/*++
+
+Copyright (c) 2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ Microcode.c
+
+Abstract:
+
+ Utility for working with microcode patch files in the Intel
+ Platform Innovation Framework for EFI build environment.
+
+--*/
+
+#include <stdio.h>
+#include <string.h> // for memset()
+#include <ctype.h>
+#include <stdlib.h> // for malloc()
+#define INT8 char
+#define UINT32 unsigned int
+
+#include "EfiUtilityMsgs.h"
+#include "Microcode.h"
+
+#define MAX_LINE_LEN 256
+
+//
+// Structure definition for a microcode header
+//
+typedef struct {
+ unsigned int HeaderVersion;
+ unsigned int PatchId;
+ unsigned int Date;
+ unsigned int CpuId;
+ unsigned int Checksum;
+ unsigned int LoaderVersion;
+ unsigned int PlatformId;
+ unsigned int DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
+ unsigned int TotalSize; // number of bytes
+ unsigned int Reserved[3];
+} MICROCODE_IMAGE_HEADER;
+
+static
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ unsigned int *Data
+ );
+
+void
+MicrocodeConstructor (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Constructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+}
+
+void
+MicrocodeDestructor (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Destructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+}
+
+static
+STATUS
+MicrocodeReadData (
+ FILE *InFptr,
+ unsigned int *Data
+ )
+/*++
+
+Routine Description:
+ Read a 32-bit microcode data value from a text file and convert to raw binary form.
+
+Arguments:
+ InFptr - file pointer to input text file
+ Data - pointer to where to return the data parsed
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings, Data contains valid information
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ char Line[MAX_LINE_LEN];
+ char *cptr;
+
+ Line[MAX_LINE_LEN - 1] = 0;
+ *Data = 0;
+ if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
+ return STATUS_ERROR;
+ }
+ //
+ // If it was a binary file, then it may have overwritten our null terminator
+ //
+ if (Line[MAX_LINE_LEN - 1] != 0) {
+ return STATUS_ERROR;
+ }
+ //
+ // Look for
+ // dd 000000001h ; comment
+ // dd XXXXXXXX
+ // DD XXXXXXXXX
+ // DD XXXXXXXXX
+ //
+ for (cptr = Line; *cptr && isspace(*cptr); cptr++) {
+ }
+ if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {
+ //
+ // Skip blanks and look for a hex digit
+ //
+ cptr += 3;
+ for (; *cptr && isspace(*cptr); cptr++) {
+ }
+ if (isxdigit (*cptr)) {
+ if (sscanf (cptr, "%X", Data) != 1) {
+ return STATUS_ERROR;
+ }
+ }
+ return STATUS_SUCCESS;
+ }
+ return STATUS_ERROR;
+}
+
+STATUS
+MicrocodeParseFile (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+ Parse a microcode text file, and write the binary results to an output file.
+
+Arguments:
+ InFileName - input text file to parse
+ OutFileName - output file to write raw binary data from parsed input file
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_ERROR - errors were encountered
+
+--*/
+{
+ FILE *InFptr;
+ FILE *OutFptr;
+ STATUS Status;
+ MICROCODE_IMAGE_HEADER *Header;
+ unsigned int Size;
+ unsigned int Size2;
+ unsigned int Data;
+ unsigned int Checksum;
+ char *Buffer;
+ char *Ptr;
+ unsigned int TotalSize;
+
+ Status = STATUS_ERROR;
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ //
+ // Open the input text file
+ //
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Make two passes on the input file. The first pass is to determine how
+ // much data is in the file so we can allocate a working buffer. Then
+ // we'll allocate a buffer and re-read the file into the buffer for processing.
+ //
+ Size = 0;
+ do {
+ Status = MicrocodeReadData (InFptr, &Data);
+ if (Status == STATUS_SUCCESS) {
+ Size += sizeof (Data);
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // Error if no data.
+ //
+ if (Size == 0) {
+ Error (NULL, 0, 0, InFileName, "no parse-able data found in file");
+ goto Done;
+ }
+ if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {
+ Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");
+ goto Done;
+ }
+ //
+ // Allocate a buffer for the data
+ //
+ Buffer = (char *) _malloc (Size);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto Done;
+ }
+ //
+ // Re-read the file, storing the data into our buffer
+ //
+ fseek (InFptr, 0, SEEK_SET);
+ Ptr = Buffer;
+ do {
+ Status = MicrocodeReadData (InFptr, &Data);
+ if (Status == STATUS_SUCCESS) {
+ *(unsigned int *) Ptr = Data;
+ Ptr += sizeof (Data);
+ }
+ } while (Status == STATUS_SUCCESS);
+ //
+ // Can't do much checking on the header because, per the spec, the
+ // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
+ // and the TotalSize field is invalid (actually missing). Thus we can't
+ // even verify the Reserved fields are 0.
+ //
+ Header = (MICROCODE_IMAGE_HEADER *) Buffer;
+ if (Header->DataSize == 0) {
+ TotalSize = 2048;
+ } else {
+ TotalSize = Header->TotalSize;
+ }
+ if (TotalSize != Size) {
+ Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);
+ goto Done;
+ }
+ //
+ // Checksum the contents
+ //
+ Ptr = Buffer;
+ Checksum = 0;
+ Size2 = 0;
+ while (Size2 < Size) {
+ Checksum += *(unsigned int *) Ptr;
+ Ptr += 4;
+ Size2 += 4;
+ }
+ if (Checksum != 0) {
+ Error (NULL, 0, 0, InFileName, "checksum failed on file contents");
+ goto Done;
+ }
+ //
+ // Open the output file and write the buffer contents
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");
+ goto Done;
+ }
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");
+ goto Done;
+ }
+ Status = STATUS_SUCCESS;
+Done:
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (Status == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+ return Status;
+}
diff --git a/Tools/Source/TianoTools/FlashMap/Microcode.h b/Tools/Source/TianoTools/FlashMap/Microcode.h
new file mode 100644
index 0000000..5f5a13e
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/Microcode.h
@@ -0,0 +1,87 @@
+/*++
+
+Copyright (c) 2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ Microcode.h
+
+Abstract:
+
+ Header file for flash management utility in the Intel Platform
+ Innovation Framework for EFI build environment.
+
+--*/
+
+#ifndef _MICROCODE_H_
+#define _MICROCODE_H_
+
+void
+MicrocodeConstructor (
+ void
+ );
+/*++
+
+Routine Description:
+
+ Constructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+void
+MicrocodeDestructor (
+ void
+ );
+/*++
+
+Routine Description:
+
+ Destructor of module Microcode
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+
+STATUS
+MicrocodeParseFile (
+ char *InFileName,
+ char *OutFileName
+ );
+/*++
+
+Routine Description:
+ Parse a microcode text file, and write the binary results to an output file.
+
+Arguments:
+ InFileName - input text file to parse
+ OutFileName - output file to write raw binary data from parsed input file
+
+Returns:
+ STATUS_SUCCESS - no errors or warnings
+ STATUS_ERROR - errors were encountered
+
+--*/
+
+
+#endif // #ifndef _MICROCODE_H_
diff --git a/Tools/Source/TianoTools/FlashMap/Symbols.c b/Tools/Source/TianoTools/FlashMap/Symbols.c
new file mode 100644
index 0000000..471128a
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/Symbols.c
@@ -0,0 +1,647 @@
+/*++
+
+Copyright (c) 2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ Symbol.c
+
+Abstract:
+
+ Class-like implementation for a symbol table.
+
+--*/
+
+// GC_TODO: fix comment to set correct module name: Symbols.c
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+//
+// for isspace()
+//
+#include <ctype.h>
+
+#include "Tiano.h"
+#include "EfiUtilityMsgs.h"
+#include "Symbols.h"
+
+#define MAX_LINE_LEN 512
+
+//
+// Linked list to keep track of all symbols
+//
+typedef struct _SYMBOL {
+ struct _SYMBOL *Next;
+ int Type;
+ char *Name;
+ char *Value;
+} SYMBOL;
+
+static
+SYMBOL *
+FreeSymbols (
+ SYMBOL *Syms
+ );
+
+static
+int
+ExpandMacros (
+ char *SourceLine,
+ char *DestLine,
+ int LineLen
+ );
+
+static SYMBOL *mSymbolTable = NULL;
+
+void
+SymbolsConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SymbolsDestructor ();
+}
+
+void
+SymbolsDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ mSymbolTable = FreeSymbols (mSymbolTable);
+}
+
+char *
+GetSymbolValue (
+ char *SymbolName
+ )
+/*++
+
+Routine Description:
+
+ Look up a symbol in our symbol table.
+
+Arguments:
+
+ SymbolName
+
+Returns:
+
+ Pointer to the value of the symbol if found
+ NULL if the symbol is not found
+
+--*/
+// GC_TODO: SymbolName - add argument and description to function comment
+{
+ SYMBOL *Symbol;
+ //
+ // Walk the symbol table
+ //
+ Symbol = mSymbolTable;
+ while (Symbol) {
+ if (stricmp (SymbolName, Symbol->Name) == 0) {
+ return Symbol->Value;
+ }
+
+ Symbol = Symbol->Next;
+ }
+
+ return NULL;
+}
+
+int
+SymbolAdd (
+ char *Name,
+ char *Value,
+ int Mode
+ )
+/*++
+
+Routine Description:
+
+ Add a symbol name/value to the symbol table
+
+Arguments:
+
+ Name - name of symbol to add
+ Value - value of symbol to add
+ Mode - currrently unused
+
+Returns:
+
+ Length of symbol added.
+
+Notes:
+ If Value == NULL, then this routine will assume that the Name field
+ looks something like "MySymName = MySymValue", and will try to parse
+ it that way and add the symbol name/pair from the string.
+
+--*/
+{
+ SYMBOL *Symbol;
+
+ SYMBOL *NewSymbol;
+ int Len;
+ char *Start;
+ char *Cptr;
+ char CSave;
+ char *SaveCptr;
+
+ Len = 0;
+ SaveCptr = NULL;
+ CSave = 0;
+ //
+ // If value pointer is null, then they passed us a line something like:
+ // varname = value, or simply var =
+ //
+ if (Value == NULL) {
+ Start = Name;
+ while (*Name && isspace (*Name)) {
+ Name++;
+ }
+
+ if (Name == NULL) {
+ return -1;
+ }
+ //
+ // Find the end of the name. Either space or a '='.
+ //
+ for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)
+ ;
+ if (Value == NULL) {
+ return -1;
+ }
+ //
+ // Look for the '='
+ //
+ Cptr = Value;
+ while (*Value && (*Value != '=')) {
+ Value++;
+ }
+
+ if (Value == NULL) {
+ return -1;
+ }
+ //
+ // Now truncate the name
+ //
+ *Cptr = 0;
+ //
+ // Skip over the = and then any spaces
+ //
+ Value++;
+ while (*Value && isspace (*Value)) {
+ Value++;
+
+ }
+ //
+ // Find end of string, checking for quoted string
+ //
+ if (*Value == '\"') {
+ Value++;
+ for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)
+ ;
+ } else {
+ for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)
+ ;
+ }
+ //
+ // Null terminate the value string
+ //
+ CSave = *Cptr;
+ SaveCptr = Cptr;
+ *Cptr = 0;
+ Len = (int) (Cptr - Start);
+ }
+ //
+ // We now have a symbol name and a value. Look for an existing variable
+ // and overwrite it.
+ //
+ Symbol = mSymbolTable;
+ while (Symbol) {
+ //
+ // Check for symbol name match
+ //
+ if (stricmp (Name, Symbol->Name) == 0) {
+ _free (Symbol->Value);
+ Symbol->Value = (char *) _malloc (strlen (Value) + 1);
+ if (Symbol->Value == NULL) {
+ Error (NULL, 0, 0, NULL, "failed to allocate memory");
+ return -1;
+ }
+
+ strcpy (Symbol->Value, Value);
+ //
+ // If value == "NULL", then make it a 0-length string
+ //
+ if (stricmp (Symbol->Value, "NULL") == 0) {
+ Symbol->Value[0] = 0;
+ }
+
+ return Len;
+ }
+
+ Symbol = Symbol->Next;
+ }
+ //
+ // Does not exist, create a new one
+ //
+ NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));
+ if (NewSymbol == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ return -1;
+ }
+
+ memset ((char *) NewSymbol, 0, sizeof (SYMBOL));
+ NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);
+ if (NewSymbol->Name == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ _free (NewSymbol);
+ return -1;
+ }
+
+ NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);
+ if (NewSymbol->Value == NULL) {
+ Error (NULL, 0, 0, NULL, "memory allocation failure");
+ _free (NewSymbol->Name);
+ _free (NewSymbol);
+ return -1;
+ }
+
+ strcpy (NewSymbol->Name, Name);
+ strcpy (NewSymbol->Value, Value);
+ //
+ // Remove trailing spaces
+ //
+ Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;
+ while (Cptr > NewSymbol->Value) {
+ if (isspace (*Cptr)) {
+ *Cptr = 0;
+ Cptr--;
+ } else {
+ break;
+ }
+ }
+ //
+ // Add it to the head of the list.
+ //
+ NewSymbol->Next = mSymbolTable;
+ mSymbolTable = NewSymbol;
+ //
+ // If value == "NULL", then make it a 0-length string
+ //
+ if (stricmp (NewSymbol->Value, "NULL") == 0) {
+ NewSymbol->Value[0] = 0;
+ }
+ //
+ // Restore the terminator we inserted if they passed in var=value
+ //
+ if (SaveCptr != NULL) {
+ *SaveCptr = CSave;
+ }
+ _free (NewSymbol->Value);
+ _free (NewSymbol->Name);
+ _free (NewSymbol);
+ return Len;
+}
+
+static
+STATUS
+RemoveSymbol (
+ char *Name,
+ char SymbolType
+ )
+/*++
+
+Routine Description:
+
+ Remove a symbol name/value from the symbol table
+
+Arguments:
+
+ Name - name of symbol to remove
+ SymbolType - type of symbol to remove
+
+Returns:
+
+ STATUS_SUCCESS - matching symbol found and removed
+ STATUS_ERROR - matching symbol not found in symbol table
+
+--*/
+{
+ SYMBOL *Symbol;
+
+ SYMBOL *PrevSymbol;
+
+ PrevSymbol = NULL;
+ Symbol = mSymbolTable;
+ //
+ // Walk the linked list of symbols in the symbol table looking
+ // for a match of both symbol name and type.
+ //
+ while (Symbol) {
+ if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {
+ //
+ // If the symbol has a value associated with it, free the memory
+ // allocated for the value.
+ // Then free the memory allocated for the symbols string name.
+ //
+ if (Symbol->Value) {
+ _free (Symbol->Value);
+ }
+
+ _free (Symbol->Name);
+ //
+ // Link the previous symbol to the next symbol to effectively
+ // remove this symbol from the linked list.
+ //
+ if (PrevSymbol) {
+ PrevSymbol->Next = Symbol->Next;
+ } else {
+ mSymbolTable = Symbol->Next;
+ }
+
+ _free (Symbol);
+ return STATUS_SUCCESS;
+ }
+
+ PrevSymbol = Symbol;
+ Symbol = Symbol->Next;
+ }
+
+ return STATUS_WARNING;
+}
+
+static
+SYMBOL *
+FreeSymbols (
+ SYMBOL *Syms
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Syms - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SYMBOL *Next;
+ while (Syms) {
+ if (Syms->Name != NULL) {
+ _free (Syms->Name);
+ }
+
+ if (Syms->Value != NULL) {
+ _free (Syms->Value);
+ }
+
+ Next = Syms->Next;
+ _free (Syms);
+ Syms = Next;
+ }
+
+ return Syms;
+}
+
+static
+int
+ExpandMacros (
+ char *SourceLine,
+ char *DestLine,
+ int LineLen
+ )
+/*++
+
+Routine Description:
+
+ Given a line of text, replace all variables of format $(NAME) with values
+ from our symbol table.
+
+Arguments:
+
+ SourceLine - input line of text to do symbol replacements on
+ DestLine - on output, SourceLine with symbols replaced
+ LineLen - length of DestLine, so we don't exceed its allocated length
+
+Returns:
+
+ STATUS_SUCCESS - no problems encountered
+ STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine
+ STATUS_ERROR - memory allocation failure
+
+--*/
+{
+ static int NestDepth = 0;
+ char *FromPtr;
+ char *ToPtr;
+ char *SaveStart;
+ char *Cptr;
+ char *value;
+ int Expanded;
+ int ExpandedCount;
+ INT8 *LocalDestLine;
+ STATUS Status;
+ int LocalLineLen;
+
+ NestDepth++;
+ Status = STATUS_SUCCESS;
+ LocalDestLine = (char *) _malloc (LineLen);
+ if (LocalDestLine == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);
+ return STATUS_ERROR;
+ }
+
+ FromPtr = SourceLine;
+ ToPtr = LocalDestLine;
+ //
+ // Walk the entire line, replacing $(MACRO_NAME).
+ //
+ LocalLineLen = LineLen;
+ ExpandedCount = 0;
+ while (*FromPtr && (LocalLineLen > 0)) {
+ if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {
+ //
+ // Save the start in case it's undefined, in which case we copy it as-is.
+ //
+ SaveStart = FromPtr;
+ Expanded = 0;
+ //
+ // Macro expansion time. Find the end (no spaces allowed)
+ //
+ FromPtr += 2;
+ for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)
+ ;
+ if (*Cptr) {
+ //
+ // Truncate the string at the closing parenthesis for ease-of-use.
+ // Then copy the string directly to the destination line in case we don't find
+ // a definition for it.
+ //
+ *Cptr = 0;
+ strcpy (ToPtr, SaveStart);
+ if ((value = GetSymbolValue (FromPtr)) != NULL) {
+ strcpy (ToPtr, value);
+ LocalLineLen -= strlen (value);
+ ToPtr += strlen (value);
+ Expanded = 1;
+ ExpandedCount++;
+ }
+
+ if (!Expanded) {
+ //
+ // Restore closing parenthesis, and advance to next character
+ //
+ *Cptr = ')';
+ FromPtr = SaveStart + 1;
+ ToPtr++;
+ } else {
+ FromPtr = Cptr + 1;
+ }
+ } else {
+ Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");
+ strcpy (ToPtr, FromPtr);
+ Status = STATUS_WARNING;
+ goto Done;
+ }
+ } else {
+ *ToPtr = *FromPtr;
+ FromPtr++;
+ ToPtr++;
+ LocalLineLen--;
+ }
+ }
+
+ if (*FromPtr == 0) {
+ *ToPtr = 0;
+ }
+
+ //
+ // If we expanded at least one string successfully, then make a recursive call to try again.
+ //
+ if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {
+ Status = ExpandMacros (LocalDestLine, DestLine, LineLen);
+ _free (LocalDestLine);
+ NestDepth = 0;
+ return Status;
+ }
+
+Done:
+ if (Status != STATUS_ERROR) {
+ strcpy (DestLine, LocalDestLine);
+ }
+
+ NestDepth = 0;
+ _free (LocalDestLine);
+ return Status;
+}
+
+STATUS
+SymbolsFileStringsReplace (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Given input and output file names, read in the input file, replace variable
+ references of format $(NAME) with appropriate values from our symbol table,
+ and write the result out to the output file.
+
+Arguments:
+
+ InFileName - name of input text file to replace variable references
+ OutFileName - name of output text file to write results to
+
+Returns:
+
+ STATUS_SUCCESS - no problems encountered
+ STATUS_ERROR - failed to open input or output file
+
+--*/
+{
+ STATUS Status;
+ FILE *InFptr;
+ FILE *OutFptr;
+ char Line[MAX_LINE_LEN];
+ char OutLine[MAX_LINE_LEN];
+
+ Status = STATUS_ERROR;
+ //
+ // Open input and output files
+ //
+ InFptr = NULL;
+ OutFptr = NULL;
+ if ((InFptr = fopen (InFileName, "r")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ goto Done;
+ }
+
+ if ((OutFptr = fopen (OutFileName, "w")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Done;
+ }
+ //
+ // Read lines from input file until done
+ //
+ while (fgets (Line, sizeof (Line), InFptr) != NULL) {
+ ExpandMacros (Line, OutLine, sizeof (OutLine));
+ fprintf (OutFptr, OutLine);
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ return Status;
+}
diff --git a/Tools/Source/TianoTools/FlashMap/Symbols.h b/Tools/Source/TianoTools/FlashMap/Symbols.h
new file mode 100644
index 0000000..1d93910
--- /dev/null
+++ b/Tools/Source/TianoTools/FlashMap/Symbols.h
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ Symbols.h
+
+Abstract:
+
+ Defines and prototypes for a class-like symbol table service.
+
+--*/
+
+#ifndef _SYMBOLS_H_
+#define _SYMBOLS_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int
+SymbolAdd (
+ char *Name,
+ char *Value,
+ int Mode
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Name - GC_TODO: add argument description
+ Value - GC_TODO: add argument description
+ Mode - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+SymbolsFileStringsReplace (
+ char *InFileName,
+ char *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ InFileName - GC_TODO: add argument description
+ OutFileName - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+SymbolsConstructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+void
+SymbolsDestructor (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef _SYMBOLS_H_
diff --git a/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c b/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c
new file mode 100644
index 0000000..6c1ec5f
--- /dev/null
+++ b/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c
@@ -0,0 +1,542 @@
+/*++
+
+Copyright (c) 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ GenAcpiTable.c
+
+Abstract:
+
+ A utility that extracts the .DATA section from a PE/COFF image.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Tiano.h"
+#include "TianoCommon.h"
+#include "EfiImage.h" // for PE32 structure definitions
+#include "EfiUtilityMsgs.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenAcpiTable"
+#define UTILITY_VERSION "v0.11"
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 256
+#define DEFAULT_OUTPUT_EXTENSION ".acpi"
+
+//
+// Use this to track our command-line options and globals
+//
+struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 InFileName[MAX_PATH];
+} mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ INT8 *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+STATUS
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ );
+
+static
+void
+DumpImage (
+ INT8 *FileName
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ UINT32 Status;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv)) {
+ return STATUS_ERROR;
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");
+ goto Finish;
+ }
+ //
+ // Process the file
+ //
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);
+Finish:
+ Status = GetUtilityStatus ();
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ InFileName - Name of the PE32 EFI file to process.
+ OutFileName - Name of the output file for the processed data.
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ STATUS Status;
+ UINTN Index;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ UINT32 PESigOffset;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
+ EFI_IMAGE_SECTION_HEADER SectionHeader;
+ UINT8 *Buffer;
+ long SaveFilePosition;
+
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ Status = STATUS_ERROR;
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ //
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
+ // offset (from the start of the file) to the PE signature, which always
+ // follows the MSDOS stub. The PE signature is immediately followed by the
+ // COFF file header.
+ //
+ //
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);
+ goto Finish;
+ }
+
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");
+ goto Finish;
+ }
+
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");
+ goto Finish;
+ }
+ //
+ // We should now be at the COFF file header. Read it in and verify it's
+ // of an image type we support.
+ //
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");
+ goto Finish;
+ }
+
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);
+ goto Finish;
+ }
+ //
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
+ //
+ SaveFilePosition = ftell (InFptr);
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");
+ goto Finish;
+ }
+
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+ }
+ //
+ // Search for the ".data" section
+ //
+ for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {
+ if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (strcmp (SectionHeader.Name, ".data") == 0) {
+ if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to .data section");
+ goto Finish;
+ }
+
+ Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Finish;
+ }
+ if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to .data section");
+ goto Finish;
+ }
+ //
+ // Now open our output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Finish;
+ }
+
+ if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write .data section");
+ goto Finish;
+ }
+
+ Status = STATUS_SUCCESS;
+ goto Finish;
+ }
+ }
+
+ Status = STATUS_ERROR;
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // Close the output file. If there was an error, delete the output file so
+ // that a subsequent build will rebuild it.
+ //
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+
+ //
+ // Free up our buffer
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+ STATUS Status;
+
+ Status = STATUS_ERROR;
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");
+ goto Finish;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");
+ goto Finish;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");
+ goto Finish;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");
+ goto Finish;
+ }
+ //
+ // Read the file header
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");
+ goto Finish;
+ }
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");
+ goto Finish;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ //
+ // Good to go
+ //
+ Status = STATUS_SUCCESS;
+Finish:
+ fseek (Fptr, 0, SEEK_SET);
+ return Status;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv - standard C main() argument list
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ //
+ // Clear out the options
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc != 2) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.InFileName, Argv[0]);
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+
+ strcpy (mOptions.OutFileName, Argv[0]);
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",
+ " Generate an ACPI Table image from an EFI PE32 image",
+ " Usage: "UTILITY_NAME " InFileName OutFileName",
+ " where:",
+ " InFileName - name of the input PE32 file",
+ " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,
+ "",
+ NULL
+ };
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
diff --git a/Tools/Source/TianoTools/GenAcpiTable/Makefile b/Tools/Source/TianoTools/GenAcpiTable/Makefile
new file mode 100644
index 0000000..c4df9bc
--- /dev/null
+++ b/Tools/Source/TianoTools/GenAcpiTable/Makefile
@@ -0,0 +1,68 @@
+#/*++
+#
+# Copyright (c) 2002 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name:
+#
+# makefile
+#
+# Abstract:
+#
+# makefile for building the GenAcpiTable utility.
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Define the toolchain which is used to set build options and toolchain paths
+#
+TOOLCHAIN = TOOLCHAIN_MSVC
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = GenAcpiTable
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib
+
+INC_DEPS = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h
+
+#
+# Build the EXE by compiling the source files, then linking the resultant
+# object files together.
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@
+
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c b/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c
new file mode 100644
index 0000000..05234e8
--- /dev/null
+++ b/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 2003 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ CreateGuid.c
+
+Abstract:
+
+ Library routine to create a GUID
+
+--*/
+
+#include <windows.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+void
+CreateGuid (
+ GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Guid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ CoCreateGuid (Guid);
+}
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c b/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c
new file mode 100644
index 0000000..87195e7
--- /dev/null
+++ b/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c
@@ -0,0 +1,2667 @@
+/*++
+
+Copyright (c) 2002 - 2005, Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenCapsuleHdr.c
+
+Abstract:
+
+ Generate a capsule header for a file, and optionally prepend the
+ header to a file or list of files.
+
+--*/
+
+#define _UNICODE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "Tiano.h" // need a guid definition
+#include "EfiUtilityMsgs.h"
+#include "EfiCapsule.h"
+#include "EfiFirmwareVolumeHeader.h"
+#include "EfiFirmwareFileSystem.h" // for FV header GUID
+#define MAX_PATH 256
+#define PROGRAM_NAME "GenCapsuleHdr"
+
+#define UNICODE_BACKSLASH L'\\'
+#define UNICODE_FILE_START 0xFEFF
+#define UNICODE_CR 0x000D
+#define UNICODE_LF 0x000A
+#define UNICODE_NULL 0x0000
+#define UNICODE_SPACE L' '
+#define UNICODE_SLASH L'/'
+#define UNICODE_DOUBLE_QUOTE L'"'
+#define UNICODE_A L'A'
+#define UNICODE_F L'F'
+#define UNICODE_Z L'Z'
+#define UNICODE_a L'a'
+#define UNICODE_f L'f'
+#define UNICODE_z L'z'
+#define UNICODE_0 L'0'
+#define UNICODE_9 L'9'
+#define UNICODE_TAB L'\t'
+
+#define OEM_HEADER_STRING L"OemHeader"
+#define AUTHOR_INFO_STRING L"AuthorInfo"
+#define REVISION_INFO_STRING L"RevisionInfo"
+#define SHORT_DESCRIPTION_STRING L"ShortDescription"
+#define LONG_DESCRIPTION_STRING L"LongDescription"
+#define EQUAL_STRING L"="
+#define OPEN_BRACE_STRING L"{"
+#define CLOSE_BRACE_STRING L"}"
+#define GUID_STRING L"GUID"
+#define DATA_STRING L"DATA"
+
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+#define UEFI_CAPSULE_HEADER_NO_FALAGS 0
+#define UEFI_CAPSULE_HEADER_RESET_FALAGS CAPSULE_FLAGS_PERSIST_ACROSS_RESET
+#define UEFI_CAPSULE_HEADER_ALL_FALAGS (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)
+#endif
+
+typedef wchar_t WCHAR;
+
+typedef struct _FILE_LIST {
+ struct _FILE_LIST *Next;
+ INT8 FileName[MAX_PATH];
+} FILE_LIST;
+
+typedef struct _SIZE_LIST {
+ struct _SIZE_LIST *Next;
+ UINT32 Size;
+} SIZE_LIST;
+
+typedef struct {
+ INT8 FileName[MAX_PATH];
+ WCHAR *FileBuffer;
+ WCHAR *FileBufferPtr;
+ UINT32 FileSize;
+ FILE *FilePtr;
+ BOOLEAN EndOfFile;
+ UINT32 LineNum;
+} SOURCE_FILE;
+
+//
+// Here's all our globals.
+//
+static struct {
+ BOOLEAN Dump;
+ BOOLEAN Verbose;
+ BOOLEAN JoinMode;
+ INT8 ScriptFileName[MAX_PATH];
+ INT8 OutputFileName[MAX_PATH];
+ FILE_LIST *FileList;
+ FILE *OutFptr;
+ SIZE_LIST *SizeList;
+ SIZE_LIST *LastSize;
+ SIZE_LIST *CurrentSize;
+} mOptions;
+
+static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;
+
+void
+CreateGuid (
+ EFI_GUID *Guid
+ );
+
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+void
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+STATUS
+GetHexValue (
+ SOURCE_FILE *SourceFile,
+ UINT32 *Value,
+ UINT32 NumDigits
+ );
+
+static
+BOOLEAN
+GetSplitFileName (
+ INT8 *BaseFileName,
+ INT8 *NewFileName,
+ UINT32 SequenceNumber
+ );
+
+static
+STATUS
+SplitCapsule (
+ INT8 *CapsuleFileName
+ );
+
+static
+void
+Usage (
+ VOID
+ );
+
+static
+void
+DumpCapsule (
+ VOID
+ );
+
+static
+STATUS
+JoinCapsule (
+ VOID
+ );
+
+static
+STATUS
+DumpCapsuleHeaderStrings (
+ UINT8 *SectionName,
+ WCHAR *Buffer
+ );
+
+static
+STATUS
+CheckFirmwareVolumeHeader (
+ INT8 *FileName,
+ INT8 *Buffer,
+ UINT32 BufferSize
+ );
+
+static
+BOOLEAN
+IsToken (
+ SOURCE_FILE *File,
+ WCHAR *Token
+ );
+
+static
+BOOLEAN
+GetNumber (
+ INT8 *Str,
+ UINT32 *Value
+ );
+
+static
+STATUS
+ProcessScriptFile (
+ INT8 *ScriptFileName,
+ FILE *OutFptr,
+ EFI_CAPSULE_HEADER *CapsuleHeader
+ );
+
+static
+STATUS
+ParseCapsuleInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr,
+ WCHAR *SectionName
+ );
+
+static
+STATUS
+CreateCapsule (
+ VOID
+ );
+
+static
+STATUS
+ParseOemInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ WCHAR Char
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *File
+ );
+
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Call the routine to process the command-line arguments, then
+ dispatch to the appropriate function.
+
+Arguments:
+ Standard C main() argc and argv.
+
+Returns:
+ 0 if successful
+ nonzero otherwise
+
+--*/
+// GC_TODO: Argc - add argument and description to function comment
+// GC_TODO: ] - add argument and description to function comment
+{
+ STATUS Status;
+ FILE_LIST *NextFile;
+ //
+ // Specify our program name to the error printing routines.
+ //
+ SetUtilityName (PROGRAM_NAME);
+ //
+ // Process the command-line arguments
+ //
+ Status = ProcessArgs (Argc, Argv);
+ if (Status == STATUS_SUCCESS) {
+ if (mOptions.Dump) {
+ DumpCapsule ();
+ } else if (mOptions.JoinMode) {
+ JoinCapsule ();
+ } else {
+ CreateCapsule ();
+ }
+ }
+ //
+ // Cleanup
+ //
+ while (mOptions.FileList != NULL) {
+ NextFile = mOptions.FileList->Next;
+ free (mOptions.FileList);
+ mOptions.FileList = NextFile;
+ }
+
+ while (mOptions.SizeList != NULL) {
+ mOptions.CurrentSize = mOptions.SizeList->Next;
+ free (mOptions.SizeList);
+ mOptions.SizeList = mOptions.CurrentSize;
+ }
+
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+CreateCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ FILE *InFptr;
+ FILE_LIST *FileList;
+ INT8 *Buffer;
+ UINT32 Size;
+ EFI_CAPSULE_HEADER CapsuleHeader;
+ UINT8 Zero;
+ UINT8 FirstFile;
+ UINT32 CapsuleHeaderSize;
+ long InsertedBlockMapEntryOffset;
+ EFI_FV_BLOCK_MAP_ENTRY InsertedBlockMapEntry;
+ UINT64 FirmwareVolumeSize;
+ long FileSize;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+
+ Buffer = NULL;
+ InFptr = NULL;
+ FirmwareVolumeSize = 0;
+ CapsuleHeaderSize = 0;
+ InsertedBlockMapEntryOffset = 0;
+ memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY));
+ memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+
+ if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader));
+ memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID));
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
+ CapsuleHeader.CapsuleImageSize = sizeof (EFI_CAPSULE_HEADER);
+ if (mOptions.ScriptFileName[0] != 0) {
+ if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ } else {
+ //
+ // Insert a default capsule header
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
+ CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
+ CapsuleHeader.Flags = UEFI_CAPSULE_HEADER_ALL_FALAGS;
+#endif
+ CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER);
+
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody;
+ //
+ // Now copy the contents of any other files specified on the command
+ // line to the output file. Files must be FFS files, which are aligned
+ // on 8-byte boundaries. Don't align the first file, since it's the start
+ // of the image once the capsule header has been removed.
+ //
+ FileList = mOptions.FileList;
+ FirstFile = 1;
+ Zero = 0;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto Done;
+ }
+ //
+ // Allocate a buffer into which we can read the file.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ Size = ftell (InFptr);
+ rewind (InFptr);
+ Buffer = (char *) malloc (Size);
+ if (Buffer == NULL) {
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");
+ goto Done;
+ }
+
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");
+ goto Done;
+ }
+
+ if (Size > 0) {
+ //
+ // Align the write of the first bytes from the file if not the first file
+ //
+ if (FirstFile) {
+ //
+ // First file must be a firmware volume. Double-check, and then insert
+ // an additional block map entry so we can add more files from the command line
+ //
+ if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Save a copy of the firmware volume header for later
+ //
+ memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER));
+ FirmwareVolumeSize = FVHeader.FvLength;
+ if (FileList->Next != NULL) {
+ //
+ // Copy the firmware volume header
+ //
+ InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength;
+ if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+
+ if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+
+ if (fwrite (
+ Buffer + FVHeader.HeaderLength,
+ Size - FVHeader.HeaderLength,
+ 1,
+ mOptions.OutFptr
+ ) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ } else {
+ //
+ // Copy the file contents as-is
+ //
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+ } else {
+ while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) {
+ if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto Done;
+ }
+ }
+
+ FirstFile = 0;
+ }
+
+ free (Buffer);
+ Buffer = NULL;
+ fclose (InFptr);
+ InFptr = NULL;
+ FileList = FileList->Next;
+ }
+
+Done:
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // If we inserted an additional block map entry, then fix it up. Fix up the
+ // FV header as well to reflect our new size.
+ //
+ if (InsertedBlockMapEntryOffset != 0) {
+ FileSize = ftell (mOptions.OutFptr);
+ InsertedBlockMapEntry.NumBlocks = 1;
+ InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY));
+ fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET);
+ fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);
+ //
+ // Fix up the firmware volume header and write it out
+ //
+ fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET);
+ FVHeader.FvLength = FileSize - CapsuleHeaderSize;
+ FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);
+ //
+ // Reposition to the end of the file
+ //
+ }
+ //
+ // Close files and free the global string lists we allocated memory for
+ //
+ if (mOptions.OutFptr != NULL) {
+ //
+ // We should now know the full capsule image size. Update the header and write it again.
+ //
+ fseek (mOptions.OutFptr, 0, SEEK_END);
+ Size = ftell (mOptions.OutFptr);
+ CapsuleHeader.CapsuleImageSize = Size;
+ fseek (mOptions.OutFptr, 0, SEEK_SET);
+ if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ }
+
+ fseek (mOptions.OutFptr, 0, SEEK_END);
+ fclose (mOptions.OutFptr);
+ mOptions.OutFptr = NULL;
+ }
+ //
+ // If they are doing split capsule output, then split it up now.
+ //
+ if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) {
+ SplitCapsule (mOptions.OutputFileName);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+ProcessScriptFile (
+ INT8 *ScriptFileName,
+ FILE *OutFptr,
+ EFI_CAPSULE_HEADER *CapsuleHeader
+ )
+/*++
+
+Routine Description:
+ Parse a capsule header script file.
+
+Arguments:
+ ScriptFileName - name of script file to parse
+ OutFptr - output to dump binary data
+ CapsuleHeader - capsule header to update with size info
+ of parsed fields in the script file
+
+Returns:
+ STATUS_SUCCESS - if all went well
+
+--*/
+{
+#if 0
+ STATUS Status;
+ SOURCE_FILE SourceFile;
+ WCHAR *WScriptFileName;
+ BOOLEAN InComment;
+
+ if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write capsule header to output file", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset (&SourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (SourceFile.FileName, ScriptFileName);
+
+ Status = STATUS_ERROR;
+ //
+ // Open the input unicode script file and read it into a buffer
+ //
+ WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR));
+ if (WScriptFileName == NULL) {
+ Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);
+ return STATUS_ERROR;
+ }
+
+ swprintf (WScriptFileName, L"%S", ScriptFileName);
+ if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) {
+ free (WScriptFileName);
+ Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading");
+ goto Done;
+ }
+
+ free (WScriptFileName);
+ fseek (SourceFile.FilePtr, 0, SEEK_END);
+ SourceFile.FileSize = ftell (SourceFile.FilePtr);
+ rewind (SourceFile.FilePtr);
+ SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR));
+ if (SourceFile.FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents");
+ goto Done;
+ }
+
+ if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) {
+ Error (NULL, 0, 0, ScriptFileName, "failed to read file contents");
+ goto Done;
+ }
+
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;
+ SourceFile.LineNum = 1;
+ if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) {
+ Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL);
+ goto Done;
+ }
+
+ SourceFile.FileBufferPtr++;
+ SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0;
+ //
+ // Walk the source file buffer and replace all carriage returns with 0 so
+ // we can print from the file contents on parse errors.
+ //
+ InComment = 0;
+ while (!EndOfFile (&SourceFile)) {
+ if (SourceFile.FileBufferPtr[0] == UNICODE_CR) {
+ SourceFile.FileBufferPtr[0] = 0;
+ InComment = 0;
+ } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) {
+ InComment = 0;
+ } else if (InComment) {
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;
+ } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) {
+ InComment = 1;
+ SourceFile.FileBufferPtr[0] = UNICODE_SPACE;
+ }
+
+ SourceFile.FileBufferPtr++;
+ }
+ //
+ // Reposition to the start of the file, but skip over the unicode file start
+ //
+ SourceFile.FileBufferPtr = SourceFile.FileBuffer;
+ SourceFile.FileBufferPtr++;
+ SourceFile.EndOfFile = 0;
+ CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr);
+ //
+ // Parse the OEM bytes
+ //
+ if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the author information
+ //
+ CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the revision information
+ //
+ CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the short description
+ //
+ CapsuleHeader->OffsetToShortDescription = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Parse the long description
+ //
+ CapsuleHeader->OffsetToLongDescription = ftell (OutFptr);
+ if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ //
+ // Better be end of contents
+ //
+ SkipWhiteSpace (&SourceFile);
+ if (!EndOfFile (&SourceFile)) {
+ Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr);
+ goto Done;
+ }
+
+ CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr);
+ rewind (OutFptr);
+ fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr);
+ fseek (OutFptr, 0, SEEK_END);
+ Status = STATUS_SUCCESS;
+Done:
+ if (SourceFile.FilePtr != NULL) {
+ fclose (SourceFile.FilePtr);
+ }
+
+ if (SourceFile.FileBuffer != NULL) {
+ free (SourceFile.FileBuffer);
+ }
+
+ return Status;
+
+#endif
+ return STATUS_SUCCESS;
+}
+//
+// Parse the OEM data of format:
+// OemInfo {
+// GUID = 12345676-1234-1234-123456789ABC
+// DATA = 0x01, 0x02, 0x03...
+// }
+//
+static
+STATUS
+ParseOemInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SourceFile - GC_TODO: add argument description
+ OutFptr - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ long OemHeaderOffset;
+ UINT32 Data;
+ EFI_CAPSULE_OEM_HEADER OemHeader;
+ STATUS Status;
+ UINT32 DigitCount;
+ WCHAR *SaveFilePos;
+ UINT8 ByteData;
+
+ Status = STATUS_ERROR;
+ memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER));
+ OemHeaderOffset = ftell (OutFptr);
+ OemHeader.HeaderSize = sizeof (EFI_CAPSULE_OEM_HEADER);
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OEM_HEADER_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OEM_HEADER_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OPEN_BRACE_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Look for: GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx
+ //
+ if (!IsToken (SourceFile, GUID_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ GUID_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID
+ //
+ SkipWhiteSpace (SourceFile);
+ if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ OemHeader.OemGuid.Data1 = Data;
+ if (!IsToken (SourceFile, L"-")) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected dash in GUID, not %S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Get 3 word values
+ //
+ for (DigitCount = 0; DigitCount < 3; DigitCount++) {
+ if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ switch (DigitCount) {
+ case 0:
+ OemHeader.OemGuid.Data2 = (UINT16) Data;
+ break;
+
+ case 1:
+ OemHeader.OemGuid.Data3 = (UINT16) Data;
+ break;
+
+ case 2:
+ OemHeader.OemGuid.Data4[1] = (UINT8) Data;
+ OemHeader.OemGuid.Data4[0] = (UINT8) (Data >> 8);
+ break;
+ }
+
+ if (!IsToken (SourceFile, L"-")) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected dash in GUID, not %S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+ //
+ // Pick up the last 6 bytes of the GUID
+ //
+ SaveFilePos = SourceFile->FileBufferPtr;
+ for (DigitCount = 0; DigitCount < 6; DigitCount++) {
+ if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);
+ goto Done;
+ }
+
+ OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data;
+ }
+ //
+ // Now read raw OEM data bytes. May or may not be present.
+ // DATA = 0x01, 0x02, 0x02...
+ //
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ Status = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, DATA_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ DATA_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ while (!EndOfFile (SourceFile)) {
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ Status = STATUS_SUCCESS;
+ goto Done;
+ }
+
+ if (IsToken (SourceFile, L"0x")) {
+ if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected hex byte value, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (Data &~0xFF) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected byte hex byte value at %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // Skip over the hex digits, then write the data
+ //
+ while (iswxdigit (SourceFile->FileBufferPtr[0])) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ ByteData = (UINT8) Data;
+ if (fwrite (&ByteData, 1, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM data to output file", NULL);
+ goto Done;
+ }
+
+ OemHeader.HeaderSize++;
+ //
+ // Optional comma
+ //
+ IsToken (SourceFile, L",");
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected hex OEM data, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+
+ if (EndOfFile (SourceFile)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S close to OEM header data",
+ CLOSE_BRACE_STRING
+ );
+ goto Done;
+ }
+
+ Status = STATUS_SUCCESS;
+Done:
+ //
+ // re-write the oem header if no errors
+ //
+ if (Status == STATUS_SUCCESS) {
+ fseek (OutFptr, OemHeaderOffset, SEEK_SET);
+ if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);
+ goto Done;
+ }
+
+ fseek (OutFptr, 0, SEEK_END);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ParseCapsuleInfo (
+ SOURCE_FILE *SourceFile,
+ FILE *OutFptr,
+ WCHAR *SectionName
+ )
+// GC_TODO: function comment should start with '/*++'
+//
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: SourceFile - add argument and description to function comment
+// GC_TODO: OutFptr - add argument and description to function comment
+// GC_TODO: SectionName - add argument and description to function comment
+// Parse: eng "string " "parts"
+// spa "string " "parts"
+// Write out: "eng string parts\0spa string parts\0\0
+//
+{
+ STATUS Status;
+ int StringCount;
+ WCHAR Zero;
+ WCHAR Spacebar;
+
+ Status = STATUS_ERROR;
+ Zero = 0;
+ Spacebar = UNICODE_SPACE;
+
+ if (!IsToken (SourceFile, SectionName)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ SectionName,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, EQUAL_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ EQUAL_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %S, not %.20S",
+ OPEN_BRACE_STRING,
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+
+ while (!EndOfFile (SourceFile)) {
+ if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {
+ break;
+ }
+ //
+ // Look for language identifier (3 lowercase chars)
+ //
+ if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[0] <= UNICODE_z) &&
+ (SourceFile->FileBufferPtr[1] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[1] <= UNICODE_z) &&
+ (SourceFile->FileBufferPtr[2] >= UNICODE_a) &&
+ (SourceFile->FileBufferPtr[2] <= UNICODE_z) &&
+ IsWhiteSpace (SourceFile->FileBufferPtr[3])
+ ) {
+ //
+ // Write the 3 chars followed by a spacebar, and then look for opening quote
+ //
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr);
+ StringCount = 0;
+ while (IsToken (SourceFile, L"\"")) {
+ StringCount++;
+ while (!EndOfFile (SourceFile)) {
+ if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL);
+ goto Done;
+ } else {
+ fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ }
+
+ if (StringCount == 0) {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected quoted string, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ //
+ // This string's null terminator
+ //
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected valid language identifer, not %.20S",
+ SourceFile->FileBufferPtr
+ );
+ goto Done;
+ }
+ }
+ //
+ // Double null terminator
+ //
+ fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);
+ Status = STATUS_SUCCESS;
+Done:
+ return Status;
+}
+
+static
+STATUS
+SplitCapsule (
+ INT8 *CapsuleFileName
+ )
+/*++
+
+Routine Description:
+ We've created an entire capsule image. Now split it up into the
+ size pieces they requested.
+
+Arguments:
+ CapsuleFileName - name of an existing capsule file on disk
+
+Returns:
+ STATUS_SUCCESS - if no problems
+
+Notes:
+ This implementation reads in the entire capsule image from
+ disk, then overwrites the original file with the first
+ in the series.
+
+--*/
+{
+#if 0
+ EFI_CAPSULE_HEADER *CapHdr;
+
+ EFI_CAPSULE_HEADER Hdr;
+ FILE *CapFptr;
+ FILE *OutFptr;
+ UINT32 SizeLeft;
+ UINT32 CurrentSize;
+ UINT32 DataSize;
+ UINT32 SequenceNumber;
+ INT8 *Buffer;
+ INT8 FileName[MAX_PATH];
+ STATUS Status;
+ UINT32 FileSize;
+ //
+ // Figure out the total size, then rewind the input file and
+ // read the entire thing in
+ //
+ if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading");
+ return STATUS_ERROR;
+ }
+
+ OutFptr = NULL;
+ Status = STATUS_SUCCESS;
+ fseek (CapFptr, 0, SEEK_END);
+ SizeLeft = ftell (CapFptr);
+ fseek (CapFptr, 0, SEEK_SET);
+ CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft);
+ if (CapHdr == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ goto FailDone;
+ }
+
+ if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) {
+ Error (NULL, 0, 0, "failed to read capsule contents", "split failed");
+ goto FailDone;
+ }
+
+ fclose (CapFptr);
+ CapFptr = NULL;
+ //
+ // Get a GUID to fill in the InstanceId GUID in the header
+ //
+ CreateGuid (&CapHdr->InstanceId);
+ SequenceNumber = 0;
+ //
+ // If the split size is larger than the original capsule image, then
+ // we're done.
+ //
+ if (mOptions.SizeList->Size >= SizeLeft) {
+ mOptions.SizeList->Size = SizeLeft;
+ goto Done;
+ }
+ //
+ // First size has to be big enough for the original header
+ //
+ if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) {
+ Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL);
+ goto FailDone;
+ }
+ //
+ // Initialize the header we'll use on all but the first part
+ //
+ memset (&Hdr, 0, sizeof (Hdr));
+ Hdr.CapsuleGuid = CapHdr->CapsuleGuid;
+ Hdr.HeaderSize = sizeof (Hdr);
+ Hdr.Flags = CapHdr->Flags;
+ Hdr.InstanceId = CapHdr->InstanceId;
+ Hdr.CapsuleImageSize = CapHdr->CapsuleImageSize;
+ Hdr.OffsetToCapsuleBody = Hdr.HeaderSize;
+ Hdr.SequenceNumber = 1;
+ //
+ // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size);
+ //
+ Buffer = (UINT8 *) CapHdr;
+ //
+ // Walk the list of sizes and write out a capsule header, and
+ // then the raw capsule data.
+ //
+ // SizeLeft -= mOptions.SizeList->Size;
+ //
+ mOptions.CurrentSize = mOptions.SizeList;
+ while (SizeLeft) {
+ CurrentSize = mOptions.CurrentSize->Size;
+ GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber);
+ if ((OutFptr = fopen (FileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open split file for writing");
+ goto FailDone;
+ }
+
+ if (Buffer == (UINT8 *) CapHdr) {
+ //
+ // First part -- write out original header and data
+ //
+ if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write to split image file");
+ goto FailDone;
+ }
+
+ SizeLeft -= CurrentSize;
+ Buffer += CurrentSize;
+ DataSize = CurrentSize;
+ FileSize = CurrentSize;
+ } else {
+ //
+ // Not the first part. Write the default header, and then the raw bytes from the
+ // original image.
+ //
+ if (CurrentSize <= sizeof (Hdr)) {
+ Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize);
+ goto FailDone;
+ }
+
+ DataSize = CurrentSize - sizeof (Hdr);
+ if (DataSize > SizeLeft) {
+ DataSize = SizeLeft;
+ }
+
+ if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write capsule header to output file");
+ fclose (OutFptr);
+ goto FailDone;
+ }
+
+ if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to write capsule data to output file");
+ fclose (OutFptr);
+ goto FailDone;
+ }
+
+ Hdr.SequenceNumber++;
+ Buffer += DataSize;
+ SizeLeft -= DataSize;
+ FileSize = DataSize + sizeof (Hdr);
+ }
+ //
+ // Next size in list if there is one
+ //
+ if (mOptions.CurrentSize->Next != NULL) {
+ mOptions.CurrentSize = mOptions.CurrentSize->Next;
+ }
+
+ SequenceNumber++;
+ fclose (OutFptr);
+ OutFptr = NULL;
+ printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize);
+ }
+
+ goto Done;
+FailDone:
+ Status = STATUS_ERROR;
+Done:
+ if (CapHdr != NULL) {
+ free (CapHdr);
+ }
+
+ if (CapFptr != NULL) {
+ fclose (CapFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ return Status;
+
+#endif
+ return STATUS_SUCCESS;
+}
+
+static
+BOOLEAN
+GetSplitFileName (
+ INT8 *BaseFileName,
+ INT8 *NewFileName,
+ UINT32 SequenceNumber
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BaseFileName - GC_TODO: add argument description
+ NewFileName - GC_TODO: add argument description
+ SequenceNumber - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+ Given an initial split capsule file name and a sequence number,
+ create an appropriate file name for this split of a capsule image.
+
+Arguments:
+ BaseFileName - name of of the first split file in the series
+ NewFileName - output name of the split file
+ SequenceNumber - 0-based sequence number of split images
+
+Returns:
+ TRUE - name created successfully
+ FALSE - otherwise
+
+--*/
+ INT8 *Ptr;
+ INT8 *Part2Start;
+ UINT32 Digits;
+ UINT32 Len;
+ UINT32 BaseOffset;
+ //
+ // Work back from the end of the file name and see if there is a number somewhere
+ //
+ for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--)
+ ;
+ if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) {
+ //
+ // Found no number, so just add it to the end
+ //
+ sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber);
+ return TRUE;
+ } else {
+ //
+ // Found a number. Look back to find the first digit.
+ //
+ Part2Start = Ptr + 1;
+ for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++)
+ ;
+ if (!isdigit (*Ptr)) {
+ Ptr++;
+ Digits--;
+ }
+
+ BaseOffset = atoi (Ptr);
+ SequenceNumber = SequenceNumber + BaseOffset;
+ if (Digits > 1) {
+ //
+ // Copy the first part of the original file name to the new filename
+ // This is the path for filenames with format path\name001.cap
+ //
+ Len = (UINT32) Ptr - (UINT32) BaseFileName;
+ strncpy (NewFileName, BaseFileName, Len);
+ sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber);
+ strcat (NewFileName, Part2Start);
+ return TRUE;
+ } else {
+ //
+ // Only one digit found. This is the path for filenames with
+ // format path\name1.cap
+ //
+ Len = (UINT32) Ptr - (UINT32) BaseFileName + 1;
+ strncpy (NewFileName, BaseFileName, Len);
+ sprintf (NewFileName + Len - 1, "%d", SequenceNumber);
+ strcat (NewFileName, Part2Start);
+ return TRUE;
+ }
+ }
+}
+
+static
+BOOLEAN
+IsWhiteSpace (
+ WCHAR Char
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Char - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ switch (Char) {
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+static
+BOOLEAN
+IsToken (
+ SOURCE_FILE *File,
+ WCHAR *Token
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ File - GC_TODO: add argument description
+ Token - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ SkipWhiteSpace (File);
+ if (EndOfFile (File)) {
+ return FALSE;
+ }
+
+ if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) {
+ File->FileBufferPtr += wcslen (Token);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static
+STATUS
+CheckFirmwareVolumeHeader (
+ INT8 *FileName,
+ INT8 *Buffer,
+ UINT32 BufferSize
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER *Hdr;
+ EFI_GUID FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
+
+ Hdr = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;
+ if (Hdr->Signature != EFI_FVH_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)");
+ return STATUS_ERROR;
+ }
+
+ if (Hdr->Revision != EFI_FVH_REVISION) {
+ Error (NULL, 0, 0, FileName, "unsupported firmware volume header version");
+ return STATUS_ERROR;
+ }
+
+ if (Hdr->FvLength > BufferSize) {
+ Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size");
+ return STATUS_ERROR;
+ }
+
+ if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header");
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+DumpCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+#if 0
+ FILE *InFptr;
+ FILE_LIST *FileList;
+ EFI_CAPSULE_HEADER CapsuleHeader;
+ EFI_FIRMWARE_VOLUME_HEADER FVHeader;
+ EFI_CAPSULE_OEM_HEADER *OemHeader;
+ UINT8 *BPtr;
+ UINT32 FileSize;
+ UINT32 CapsuleHeaderDataSize;
+ UINT8 ByteCount;
+ UINT8 *CapsuleHeaderData;
+ BOOLEAN SplitImage;
+
+ InFptr = NULL;
+ CapsuleHeaderData = NULL;
+ FileList = mOptions.FileList;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto Done;
+ }
+
+ if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header");
+ goto Done;
+ }
+
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ if (CapsuleHeader.CapsuleImageSize > FileSize) {
+ SplitImage = TRUE;
+ } else {
+ SplitImage = FALSE;
+ }
+
+ printf (
+ "Capsule %s Size=0x%X CargoSize=0x%X\n",
+ FileList->FileName,
+ FileSize,
+ FileSize - CapsuleHeader.OffsetToCapsuleBody
+ );
+ printf (
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+ CapsuleHeader.CapsuleGuid.Data1,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data2,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data3,
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[0],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[1],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[2],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[3],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[4],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[5],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[6],
+ (UINT32) CapsuleHeader.CapsuleGuid.Data4[7]
+ );
+ if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ printf (" INVALID GUID");
+ }
+
+ printf ("\n");
+ printf (" Header size 0x%08X\n", CapsuleHeader.HeaderSize);
+ printf (" Flags 0x%08X\n", CapsuleHeader.Flags);
+ if (!SplitImage) {
+ printf (" Capsule image size 0x%08X\n", CapsuleHeader.CapsuleImageSize);
+ } else {
+ printf (" Capsule image size 0x%08X (split)\n", CapsuleHeader.CapsuleImageSize);
+ }
+
+ printf (" Sequence number %d\n", CapsuleHeader.SequenceNumber);
+ printf (
+ " InstanceId %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+ CapsuleHeader.InstanceId.Data1,
+ (UINT32) CapsuleHeader.InstanceId.Data2,
+ (UINT32) CapsuleHeader.InstanceId.Data3,
+ (UINT32) CapsuleHeader.InstanceId.Data4[0],
+ (UINT32) CapsuleHeader.InstanceId.Data4[1],
+ (UINT32) CapsuleHeader.InstanceId.Data4[2],
+ (UINT32) CapsuleHeader.InstanceId.Data4[3],
+ (UINT32) CapsuleHeader.InstanceId.Data4[4],
+ (UINT32) CapsuleHeader.InstanceId.Data4[5],
+ (UINT32) CapsuleHeader.InstanceId.Data4[6],
+ (UINT32) CapsuleHeader.InstanceId.Data4[7]
+ );
+ printf (" Offset to capsule 0x%X\n", CapsuleHeader.OffsetToCapsuleBody);
+ //
+ // Dump header data if there
+ //
+ CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize;
+ if (CapsuleHeaderDataSize != 0) {
+ CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize);
+ if (CapsuleHeaderData == NULL) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "failed to allocate memory to read in capsule header data",
+ "0x%X bytes",
+ CapsuleHeaderDataSize
+ );
+ goto Done;
+ }
+
+ fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET);
+ if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "failed to read capsule header data contents from file",
+ "0x%X bytes",
+ CapsuleHeaderDataSize
+ );
+ goto Done;
+ }
+ //
+ // ************************************************************************
+ //
+ // OEM HEADER
+ //
+ // ************************************************************************
+ //
+ if (CapsuleHeader.OffsetToOemDefinedHeader != 0) {
+ OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize);
+ printf (" OEM Header\n");
+ printf (
+ " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
+ OemHeader->OemGuid.Data1,
+ (UINT32) OemHeader->OemGuid.Data2,
+ (UINT32) OemHeader->OemGuid.Data3,
+ (UINT32) OemHeader->OemGuid.Data4[0],
+ (UINT32) OemHeader->OemGuid.Data4[1],
+ (UINT32) OemHeader->OemGuid.Data4[2],
+ (UINT32) OemHeader->OemGuid.Data4[3],
+ (UINT32) OemHeader->OemGuid.Data4[4],
+ (UINT32) OemHeader->OemGuid.Data4[5],
+ (UINT32) OemHeader->OemGuid.Data4[6],
+ (UINT32) OemHeader->OemGuid.Data4[7]
+ );
+ printf (" Header size: 0x%X\n", OemHeader->HeaderSize);
+ printf (" OEM data");
+ BPtr = (UINT8 *) (OemHeader + 1);
+ for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) {
+ if ((ByteCount & 0x7) == 0) {
+ printf ("\n ");
+ }
+
+ printf ("%02X ", (UINT32) *BPtr);
+ BPtr++;
+ }
+
+ printf ("\n");
+ }
+ //
+ // ************************************************************************
+ //
+ // Author, revision, short description, and long description information
+ //
+ // ************************************************************************
+ //
+ if (CapsuleHeader.OffsetToAuthorInformation != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Author information",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToRevisionInformation != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Revision information",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToShortDescription != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Short description",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (CapsuleHeader.OffsetToLongDescription != 0) {
+ if (DumpCapsuleHeaderStrings (
+ "Long description",
+ (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize)
+ ) != STATUS_SUCCESS) {
+ goto Done;
+ }
+ }
+ }
+ //
+ // If it's not a split image, or it is a split image and this is the first in the series, then
+ // dump the cargo volume.
+ //
+ if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) {
+ printf (" Cargo FV dump\n");
+ fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET);
+ if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header");
+ goto Done;
+ }
+
+ printf (" FV length 0x%X", FVHeader.FvLength);
+ if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) {
+ if (!SplitImage) {
+ printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody);
+ }
+ }
+
+ printf ("\n");
+ printf (" Signature 0x%X ", FVHeader.Signature);
+ if (FVHeader.Signature == EFI_FVH_SIGNATURE) {
+ printf ("_FVH\n");
+ } else {
+ printf ("INVALID\n");
+ }
+
+ printf (" FV header length 0x%X\n", (UINT32) FVHeader.HeaderLength);
+ printf (" Revision 0x%X\n", (UINT32) FVHeader.Revision);
+ printf ("\n");
+ }
+
+ FileList = FileList->Next;
+ }
+
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (CapsuleHeaderData != NULL) {
+ free (CapsuleHeaderData);
+ }
+#endif
+}
+
+static
+STATUS
+JoinCapsule (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Join split capsule images into a single image. This is the
+ support function for the -j command-line option.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - no problems encountered
+
+--*/
+{
+#if 0
+ UINT32 Size;
+ FILE *InFptr;
+ FILE *OutFptr;
+ INT8 *Buffer;
+ FILE_LIST *FileList;
+ STATUS Status;
+ EFI_CAPSULE_HEADER CapHdr;
+ EFI_CAPSULE_HEADER *CapHdrPtr;
+ UINT32 SizeLeft;
+ UINT32 SequenceNumber;
+ //
+ // Must have at least two files for join mode
+ //
+ if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) {
+ Error (NULL, 0, 0, "must specify at least two file names to join", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");
+ return STATUS_ERROR;
+ }
+
+ FileList = mOptions.FileList;
+ Buffer = NULL;
+ SequenceNumber = 0;
+ InFptr = NULL;
+ SizeLeft = 0;
+ while (FileList != NULL) {
+ if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");
+ goto FailDone;
+ }
+ //
+ // Allocate a buffer into which we can read the file.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ Size = ftell (InFptr);
+ rewind (InFptr);
+ Buffer = (char *) malloc (Size);
+ if (Buffer == NULL) {
+ Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");
+ goto FailDone;
+ }
+
+ CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer;
+ if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");
+ goto FailDone;
+ }
+ //
+ // Check the header for validity. Check size first.
+ //
+ if (Size < sizeof (EFI_CAPSULE_HEADER)) {
+ Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header");
+ goto FailDone;
+ }
+ //
+ // Check GUID
+ //
+ if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID");
+ goto FailDone;
+ }
+ //
+ // Check sequence number
+ //
+ if (CapHdrPtr->SequenceNumber != SequenceNumber) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ FileList->FileName,
+ "invalid sequence number %d (expected %d)",
+ CapHdrPtr->SequenceNumber,
+ SequenceNumber
+ );
+ goto FailDone;
+ }
+ //
+ // If the first file, read save the capsule header
+ //
+ if (SequenceNumber == 0) {
+ memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER));
+ //
+ // Erase the InstanceId GUID
+ //
+ memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID));
+ if (fwrite (Buffer, Size, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file");
+ goto FailDone;
+ }
+
+ if (CapHdr.CapsuleImageSize < Size) {
+ Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size");
+ goto FailDone;
+ }
+
+ SizeLeft = CapHdr.CapsuleImageSize - Size;
+ } else {
+ //
+ // Check the GUID against the first file's GUID
+ //
+ if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) {
+ Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID");
+ goto FailDone;
+ }
+ //
+ // Make sure we're not throwing out any header info
+ //
+ if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) {
+ //
+ // Could be the split information, so just emit a warning
+ //
+ Warning (
+ NULL,
+ 0,
+ 0,
+ FileList->FileName,
+ "image appears to have additional capsule header information -- ignoring"
+ );
+ } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) {
+ Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient");
+ goto FailDone;
+ }
+
+ if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");
+ goto FailDone;
+ }
+
+ if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) {
+ Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL);
+ goto FailDone;
+ }
+ //
+ // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody);
+ //
+ SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody);
+ }
+ //
+ // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft);
+ //
+ fclose (InFptr);
+ InFptr = NULL;
+ free (Buffer);
+ Buffer = NULL;
+ FileList = FileList->Next;
+ SequenceNumber++;
+ }
+
+ if (SizeLeft) {
+ Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft);
+ goto FailDone;
+ }
+
+ Status = STATUS_SUCCESS;
+ goto Done;
+FailDone:
+ Status = STATUS_ERROR;
+Done:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ }
+
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+
+#endif
+return STATUS_SUCCESS;
+}
+
+static
+STATUS
+DumpCapsuleHeaderStrings (
+ UINT8 *SectionName,
+ WCHAR *Buffer
+ )
+/*++
+
+Routine Description:
+ Given a pointer to string data from a capsule header, dump
+ the strings.
+
+Arguments:
+ SectionName - name of the capsule header section to which
+ the string data pertains
+ Buffer - pointer to string data from a capsule header
+
+Returns:
+ STATUS_SUCCESS - all went well
+
+--*/
+{
+ printf (" %s\n", SectionName);
+ while (*Buffer) {
+ printf (" Language: %S\n", Buffer);
+ while (*Buffer) {
+ Buffer++;
+ }
+
+ Buffer++;
+ while (*Buffer) {
+ if (wcslen (Buffer) > 60) {
+ printf (" %.60S\n", Buffer);
+ Buffer += 60;
+ } else {
+ printf (" %S\n", Buffer);
+ Buffer += wcslen (Buffer);
+ }
+ }
+
+ Buffer++;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+GetHexValue (
+ SOURCE_FILE *SourceFile,
+ UINT32 *Value,
+ UINT32 NumDigits
+ )
+/*++
+
+Routine Description:
+ Scan a hex value from the input stream.
+
+Arguments:
+ SourceFile - input file contents
+ Value - returned value
+ NumDigits - number of digits to read
+
+Returns:
+ STATUS_SUCCESS - if NumDigits were read from the file
+ STATUS_ERROR - otherwise
+
+
+--*/
+{
+ WCHAR *SaveFilePos;
+ UINT32 Digits;
+ WCHAR Nibble;
+
+ SaveFilePos = SourceFile->FileBufferPtr;
+ *Value = 0;
+ Digits = NumDigits;
+ while (Digits > 0) {
+ Nibble = SourceFile->FileBufferPtr[0];
+ if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_0);
+ } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10);
+ } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) {
+ *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10);
+ } else {
+ Error (
+ SourceFile->FileName,
+ SourceFile->LineNum,
+ 0,
+ NULL,
+ "expected %d valid hex nibbles at %.20S",
+ NumDigits,
+ SaveFilePos
+ );
+ return STATUS_ERROR;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Digits--;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *File
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ File - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) {
+ File->EndOfFile = TRUE;
+ }
+ //
+ // Reposition to the end of the file if we went beyond
+ //
+ if (File->EndOfFile) {
+ File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR);
+ }
+
+ return File->EndOfFile;
+}
+
+static
+void
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SourceFile - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ while (!EndOfFile (SourceFile)) {
+ switch (*SourceFile->FileBufferPtr) {
+ case UNICODE_NULL:
+ case UNICODE_CR:
+ case UNICODE_SPACE:
+ case UNICODE_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case UNICODE_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ break;
+
+ default:
+ return ;
+ }
+ }
+}
+//
+// Parse a number. Possible format:
+// 1234
+// 1234k
+// 1234K
+// 1M
+// 1m
+// 0x100
+//
+static
+BOOLEAN
+GetNumber (
+ INT8 *Str,
+ UINT32 *Value
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Str - GC_TODO: add argument description
+ Value - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ UINT32 LValue;
+
+ *Value = 0;
+ LValue = 0;
+ if (!isdigit (Str[0])) {
+ return FALSE;
+ }
+ //
+ // Look for hex number
+ //
+ if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) {
+ Str += 2;
+ if (Str[0] == 0) {
+ return FALSE;
+ }
+
+ while (Str[0]) {
+ if ((Str[0] >= '0') && (Str[0] <= '9')) {
+ LValue = (LValue << 4) | (Str[0] - '0');
+ } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) {
+ LValue = (LValue << 4) | (Str[0] - 'A' + 0x10);
+ } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) {
+ LValue = (LValue << 4) | (Str[0] - 'a' + 0x10);
+ } else {
+ break;
+ }
+
+ Str++;
+ }
+ } else {
+ LValue = atoi (Str);
+ while (isdigit (*Str)) {
+ Str++;
+ }
+ }
+ //
+ // If string left over, better be one character we recognize
+ //
+ if (Str[0]) {
+ if (Str[1]) {
+ return FALSE;
+ }
+
+ switch (Str[0]) {
+ case 'k':
+ case 'K':
+ LValue *= 1024;
+ break;
+
+ case 'm':
+ case 'M':
+ LValue *= 1024 * 1024;
+ break;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ *Value = LValue;
+ return TRUE;
+}
+//
+// Process the command-line arguments
+//
+static
+STATUS
+ProcessArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Processes command line arguments.
+
+Arguments:
+
+ Argc - Number of command line arguments
+ Argv[] - Array of files input on command line
+
+Returns:
+
+ STATUS_ERROR - Function exited with an error
+ STATUS_SUCCESS - Function executed successfully
+
+--*/
+{
+ FILE_LIST *NewFile;
+
+ FILE_LIST *LastFile;
+ SIZE_LIST *NewSize;
+
+ NewFile = NULL;
+ NewSize = NULL;
+
+ //
+ // Clear our globals
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+
+ //
+ // Skip program name
+ //
+ Argc--;
+ Argv++;
+
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more options
+ //
+ while ((Argc > 0) && (Argv[0][0] == '-')) {
+ if (stricmp (Argv[0], "-script") == 0) {
+ //
+ // Check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Save the file name
+ //
+ if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) {
+ Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size");
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.ScriptFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing script file name with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ //
+ // -o outfilename -- specify output file name (required)
+ //
+ } else if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // check for one more arg
+ //
+ if (Argc > 1) {
+ //
+ // Try to open the file
+ //
+ // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) {
+ // Error (NULL, 0, 0, Argv[1], "failed to open output file for writing");
+ // return STATUS_ERROR;
+ // }
+ //
+ strcpy (mOptions.OutputFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing output filename with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if (stricmp (Argv[0], "-j") == 0) {
+ mOptions.JoinMode = TRUE;
+ //
+ // -split <size> option (multiple allowed)
+ //
+ } else if (stricmp (Argv[0], "-split") == 0) {
+ if (Argc > 1) {
+ NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST));
+ if (NewSize == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ memset (NewSize, 0, sizeof (SIZE_LIST));
+ //
+ // Get the size from the next arg, and then add this size
+ // to our size list
+ //
+ if (!GetNumber (Argv[1], &NewSize->Size)) {
+ Error (NULL, 0, 0, Argv[1], "invalid split size argument");
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ if (mOptions.SizeList == NULL) {
+ mOptions.SizeList = NewSize;
+ mOptions.CurrentSize = NewSize;
+ } else {
+ mOptions.LastSize->Next = NewSize;
+ }
+
+ mOptions.LastSize = NewSize;
+ free (NewSize);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing size parameter with option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ //
+ // Default minimum header
+ //
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ mOptions.Dump = TRUE;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ mOptions.Verbose = TRUE;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ Argc--;
+ Argv++;
+ }
+ //
+ // Can't -j join files and -s split output capsule
+ //
+ if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) {
+ Error (NULL, 0, 0, "cannot specify both -j and -size", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+ //
+ // Must have specified an output file name if not -dump
+ //
+ if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) {
+ Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified");
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+ //
+ // Rest of arguments are input files. The first one is a firmware
+ // volume image, and the rest are FFS files that are to be inserted
+ // into the firmware volume.
+ //
+ LastFile = NULL;
+ while (Argc > 0) {
+ NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST));
+ if (NewFile == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ memset ((char *) NewFile, 0, sizeof (FILE_LIST));
+ strcpy (NewFile->FileName, Argv[0]);
+ if (mOptions.FileList == NULL) {
+ mOptions.FileList = NewFile;
+ } else {
+ if (LastFile == NULL) {
+ LastFile = NewFile;
+ } else {
+ LastFile->Next = NewFile;
+ }
+ }
+
+ LastFile = NewFile;
+ Argc--;
+ Argv++;
+ }
+
+ //
+ // Must have provided at least one file name
+ //
+ if (mOptions.FileList == NULL) {
+ Error (NULL, 0, 0, "must specify at least one file name", NULL);
+ Usage ();
+
+ if (NewFile != NULL) {
+ free (NewFile);
+ }
+ if (NewSize != NULL) {
+ free (NewSize);
+ }
+
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Str[] = {
+ PROGRAM_NAME " -- create a capsule header",
+ " Usage: "PROGRAM_NAME " {options} [CapsuleFV]",
+ //
+ // {FfsFileNames}",
+ //
+ " Options include:",
+ " -h or -? for this help information",
+ " -script fname to take capsule header info from unicode script",
+ " file fname",
+ " -o fname write output to file fname (required)",
+ " -split size split capsule image into multiple output files",
+ " -dump to dump a capsule header",
+ " -v for verbose output\n",
+ " -j to join split capsule images into a single image",
+ "",
+ " CapsuleFV is the name of an existing well-formed Tiano firmware",
+ " volume file.",
+ //
+ // FfsFileNames are the names of one or more Tiano FFS files to",
+ // " insert into the output capsule image.",
+ //
+ NULL
+ };
+ for (Index = 0; Str[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Str[Index]);
+ }
+}
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/Makefile b/Tools/Source/TianoTools/GenCapsuleHdr/Makefile
new file mode 100644
index 0000000..1979c3d
--- /dev/null
+++ b/Tools/Source/TianoTools/GenCapsuleHdr/Makefile
@@ -0,0 +1,75 @@
+#/*++
+#
+# Copyright (c) 2002 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+#
+# Module Name:
+#
+# Makefile
+#
+# Abstract:
+#
+# makefile for the GenCapsuleHdr utility.
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+
+TARGET_NAME = GenCapsuleHdr
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+SRC = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+ETO = $(TIANO_TOOLS_OUTPUT)
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+LIBS = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib" ole32.lib
+
+OBJECTS = $(ETO)\$(TARGET_NAME).obj \
+ $(ETO)\CreateGuid.obj
+
+#
+# Compile each source file
+#
+$(ETO)\$(TARGET_NAME).obj : $(SRC)\$(TARGET_NAME).c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(SRC)\$(TARGET_NAME).c /Fo$@
+
+$(ETO)\CreateGuid.obj : $(SRC)\CreateGuid.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(SRC)\CreateGuid.c /Fo$@
+
+#
+# Link the object files together
+#
+$(TARGET_EXE) : $(OBJECTS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
+clean:
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImage.h b/Tools/Source/TianoTools/GenFdImage/GenFdImage.h
new file mode 100644
index 0000000..68cfa8c
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/GenFdImage.h
@@ -0,0 +1,89 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenFdImage.h
+
+Abstract:
+
+ This file contains the relevant declarations required
+ to generate the Firmware Device
+
+--*/
+
+//
+// Coded to EFI 2.0 Coding Standard
+//
+#ifndef _EFI_GEN_FD_IMAGE_H
+#define _EFI_GEN_FD_IMAGE_H
+
+//
+// Included Header files
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <assert.h>
+#include "TianoCommon.h"
+#include "ParseInf.h"
+#include "GenFvImage.h"
+
+//
+// Defines
+//
+#define FILE_NAME_SIZE 256
+
+//
+// Type Definition
+//
+typedef struct {
+ UINT64 FdSize;
+ UINT64 FdBaseAddress;
+ UINT8 PadValue;
+ CHAR8 OutFileName[FILE_NAME_SIZE];
+} FDINFO;
+
+//
+// Exported Function Prototype
+//
+EFI_STATUS
+GenerateFdImage (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size,
+ IN UINT8 PadByte,
+ IN CHAR8 *OutFile,
+ IN CHAR8 **FileList
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ BaseAddress - GC_TODO: add argument description
+ Size - GC_TODO: add argument description
+ PadByte - GC_TODO: add argument description
+ OutFile - GC_TODO: add argument description
+ FileList - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c
new file mode 100644
index 0000000..c7d9b8b
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c
@@ -0,0 +1,864 @@
+/*++
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+ Module Name:
+ GenFdImageDll.C
+
+ Abstarct:
+ This file contains the relevant functions required to complete
+ the API to generate Firmware Device
+--*/
+
+// GC_TODO: fix comment to add: Abstract:
+//
+// This tells the compiler to export the DLL functions
+//
+#define GEN_FD_IMAGE_EXPORTS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <io.h>
+#include <assert.h>
+#include "TianoCommon.h"
+#include "GenFdImage.h"
+#include "GenFvImage.h"
+#include "ParseInf.h"
+
+//
+// Global declaration
+//
+UINTN ValidLineNum = 0;
+
+UINTN NumFvFiles = 0;
+static UINT64 LastAddress = 0;
+
+CHAR8 **TokenStr;
+CHAR8 **OrgStrTokPtr;
+
+FDINFO *FdInfo;
+FDINFO *OrgFdInfoPtr;
+
+FVINFO **FvInfo;
+FVINFO **OrgFvInfoPtr;
+
+//
+// Global function declarations
+//
+EFI_STATUS
+BuildFirmwareDeviceBinaryFromFwVolumes (
+ IN UINT64 FvBaseAddress,
+ IN CHAR8 *FvFileName,
+ IN CHAR8 *FdFileName
+ );
+
+INTN
+CompareItems (
+ IN const VOID *Arg1,
+ IN const VOID *Arg2
+ )
+/*++
+Description:
+
+ This function is used by qsort to sort the Fv list based on FvBaseAddress
+
+Input:
+ Arg1
+ Arg2
+
+Return:
+
+ None
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: Arg1 - add argument and description to function comment
+// GC_TODO: Arg2 - add argument and description to function comment
+{
+ if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {
+ return 1;
+ } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+VOID
+BuildTokenList (
+ IN CHAR8 *Token
+ )
+/*++
+Description:
+
+ This function builds the token list in an array which will be parsed later
+
+Input:
+ Token String,
+
+Return:
+
+ None
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: Token - add argument and description to function comment
+{
+
+ strcpy (*TokenStr, Token);
+ TokenStr++;
+}
+
+VOID
+TrimLine (
+ IN CHAR8 *Line
+ )
+/*++
+Description:
+
+ This function cleans up the line by removing all whitespace and
+ comments
+
+Input:
+
+ Line String,
+
+Return:
+ None
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: Line - add argument and description to function comment
+{
+ CHAR8 TmpLine[FILE_NAME_SIZE];
+ CHAR8 c;
+ CHAR8 *Ptr0;
+ UINTN i;
+ UINTN j;
+
+ //
+ // Change '#' to '//' for Comment style
+ //
+ // if((Ptr0=strchr(Line, '#')) != NULL) {
+ //
+ if ((Ptr0 = strstr (Line, "//")) != NULL) {
+ Line[Ptr0 - Line] = 0;
+ }
+
+ i = j = 0;
+
+ while ((c = Line[i]) != 0) {
+ if ((c != ' ') && (c != '\t') && (c != '\n')) {
+ TmpLine[j++] = c;
+ }
+
+ i++;
+ }
+
+ TmpLine[j] = 0;
+ strcpy (Line, TmpLine);
+}
+
+VOID
+ValidLineCount (
+ IN FILE *Fp
+ )
+/*++
+
+Description:
+
+ This function calculated number of valid lines in a input file.
+
+Input:
+
+ Fp Pointer to a file handle which has been opened.
+
+Return:
+
+ None
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: Fp - add argument and description to function comment
+{
+ CHAR8 Buff[FILE_NAME_SIZE];
+
+ while (fgets (Buff, sizeof (Buff), Fp)) {
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ ValidLineNum++;
+ }
+}
+
+VOID
+ParseInputFile (
+ IN FILE *Fp
+ )
+/*++
+
+Description:
+
+ This function parses the input file and tokenize the string
+
+Input:
+
+ Fp Pointer to a file handle which has been opened.
+
+Return:
+
+ None
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: Fp - add argument and description to function comment
+{
+ CHAR8 *Token;
+ CHAR8 Buff[FILE_NAME_SIZE];
+ CHAR8 OrgLine[FILE_NAME_SIZE];
+ CHAR8 Str[FILE_NAME_SIZE];
+ CHAR8 Delimit[] = "=";
+
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
+ strcpy (OrgLine, Buff);
+ TrimLine (Buff);
+
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ Token = strtok (Buff, Delimit);
+
+ while (Token != NULL) {
+ strcpy (Str, Token);
+ BuildTokenList (Str);
+ Token = strtok (NULL, Delimit);
+ }
+ }
+}
+
+EFI_STATUS
+InitializeComps (
+ VOID
+ )
+/*++
+
+Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Input:
+
+ None
+
+Return:
+
+ EFI_STATUS
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINTN Index;
+
+ FdInfo = malloc (sizeof (FDINFO));
+
+ if (FdInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrgFdInfoPtr = FdInfo;
+
+ FvInfo = malloc (sizeof (int) * NumFvFiles);
+
+ if (FvInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrgFvInfoPtr = FvInfo;
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ *FvInfo = malloc (sizeof (FVINFO));
+
+ if (*FvInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (*FvInfo, 0, sizeof (FVINFO));
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+InitializeInFileInfo (
+ VOID
+ )
+/*++
+
+Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Input:
+
+ NONE
+
+Return:
+
+ NONE
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+{
+ UINTN OptionFlag;
+ UINT64 StringValue;
+
+ OptionFlag = 0;
+ TokenStr = OrgStrTokPtr;
+
+ while (*TokenStr != NULL) {
+ if (stricmp (*TokenStr, "[options]") == 0) {
+ OptionFlag = 1;
+ }
+
+ if (OptionFlag) {
+ if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {
+ *TokenStr++;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ printf ("\nERROR: Cannot determine the FV base address.");
+ return ;
+ }
+ (*FvInfo)->FvBaseAddress = StringValue;
+ } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {
+ *TokenStr++;
+ strcpy ((*FvInfo)->FvFile, *TokenStr);
+ }
+ }
+
+ TokenStr++;
+ }
+}
+
+EFI_STATUS
+GetFvRelatedInfoFromInfFile (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to Firmware Volume.
+
+Input:
+
+ FileName FileName which needed to be read to parse data
+
+Return:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: FileName - add argument and description to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+ UINTN Index;
+
+ Fp = fopen (FileName, "r");
+
+ if (Fp == NULL) {
+ printf ("Error in opening %s file\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ ValidLineCount (Fp);
+
+ if (ValidLineNum == 0) {
+ printf ("\nFile doesn't contain any valid informations");
+ return EFI_ABORTED;
+ }
+
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));
+ memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));
+ OrgStrTokPtr = TokenStr;
+
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {
+ *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
+ memset (*TokenStr, 0, FILE_NAME_SIZE);
+ TokenStr++;
+ }
+
+ *TokenStr = NULL;
+ TokenStr = OrgStrTokPtr;
+ fseek (Fp, 0L, SEEK_SET);
+
+ ParseInputFile (Fp);
+ InitializeInFileInfo ();
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteFwBinary (
+ IN CHAR8 *FileName,
+ IN UINT64 StartAddress,
+ IN UINT64 Size,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to Firmware Volume.
+
+Input:
+
+ FileName FileName which needed to be read to parse data
+ StartAddress This will set the file position.
+ Size Size in bytes needed to be written
+ Buffer Buffer needed to e written
+
+Return:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: FileName - add argument and description to function comment
+// GC_TODO: StartAddress - add argument and description to function comment
+// GC_TODO: Size - add argument and description to function comment
+// GC_TODO: Buffer - add argument and description to function comment
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+ UINTN NumByte;
+
+ Fp = fopen (FileName, "a+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Error in opening file %s ", FileName);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ fseek (Fp, (UINTN) StartAddress, SEEK_SET);
+ NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);
+
+ //
+ // Check to ensure that buffer has been copied successfully
+ //
+ if (NumByte != Size) {
+ printf ("\nERROR: Error in copying the buffer into file");
+ return EFI_ABORTED;
+ }
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BuildFirmwareDeviceBinaryFromFwVolumes (
+ IN UINT64 FvBaseAddress,
+ IN CHAR8 *FvFileName,
+ IN CHAR8 *FdFileName
+ )
+/*++
+
+Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to Firmware Volume.
+
+Input:
+
+ FvBaseAddress Base Address. This info is retrieved from INF file
+ FvFileName InputFileName
+ FdFileName Output File Name
+
+Return:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: FvBaseAddress - add argument and description to function comment
+// GC_TODO: FvFileName - add argument and description to function comment
+// GC_TODO: FdFileName - add argument and description to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT64 PadByteSize;
+ UINTN Index;
+ UINT64 BaseAddress;
+ UINT8 *Buffer;
+ EFI_STATUS Status;
+ static UINT64 StartAddress = 0;
+
+ Fp = fopen (FvFileName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Error in opening file %s", FvFileName);
+ return EFI_ABORTED;
+ }
+
+ BaseAddress = FdInfo->FdBaseAddress;
+
+ //
+ // Check if Base Address of Firmware Volume falls below the Base Address
+ // Firmware Device, if yes, then abort this process.
+ //
+ if (FvBaseAddress < BaseAddress) {
+ printf ("\nERROR: Firmware Volume Base Address falls below Firmware Device Address.\n");
+ return EFI_ABORTED;
+ }
+ //
+ // Check if there are any hole between two Firmware Volumes. If any hole
+ // exists, fill the hole with PadByte data.
+ //
+ if (FvBaseAddress > LastAddress) {
+ PadByteSize = (FvBaseAddress - LastAddress);
+ Buffer = malloc ((UINTN) PadByteSize);
+
+ for (Index = 0; Index < PadByteSize; Index++) {
+ *Buffer = FdInfo->PadValue;
+ Buffer++;
+ }
+
+ Buffer -= PadByteSize;
+ Status = WriteFwBinary (FdFileName, StartAddress, (UINT64) PadByteSize, Buffer);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in writing the binary image to file");
+ return Status;
+ }
+
+ StartAddress += PadByteSize;
+ LastAddress += PadByteSize;
+ }
+ //
+ // Proceed with next Firmware Volume updates
+ //
+ FileSize = _filelength (fileno (Fp));
+
+ if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {
+ printf (
+ "\nERROR:Unable to update Firmware Device. File %s is larger than \
+ available space.",
+ FvFileName
+ );
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_ABORTED;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+
+ if (Buffer == NULL) {
+ printf ("Error in allocating buffer to read specific file\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+
+ Status = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);
+
+ if (Buffer) {
+ free ((VOID *) Buffer);
+ }
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in writing the binary image to file");
+ return Status;
+ }
+
+ StartAddress += NumByteRead;
+ LastAddress += FileSize;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+CleanUpMemory (
+ VOID
+ )
+/*++
+
+Description:
+
+ This function cleans up any allocated buffer
+
+Input:
+
+ NONE
+
+Return:
+
+ NONE
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+{
+ UINTN Index;
+
+ if (FdInfo) {
+ free (FdInfo);
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ if (FvInfo) {
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ if (*FvInfo) {
+ free (*FvInfo);
+ }
+
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+ free (FvInfo);
+ }
+}
+
+GEN_FD_IMAGE_API
+EFI_STATUS
+GenerateFdImage (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size,
+ IN UINT8 PadByte,
+ IN CHAR8 *OutFile,
+ IN CHAR8 **FileList
+ )
+/*++
+
+Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to Firmware Volume.
+
+Input:
+
+ BaseAddress Base Address for this Firmware Device
+ Size, Total Size of the Firmware Device
+ PadByte Pad byte data
+ OutFile Output File Name
+ FileList File List pointer to INF file names.
+
+Return:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: function comment is missing 'Routine Description:'
+// GC_TODO: function comment is missing 'Arguments:'
+// GC_TODO: function comment is missing 'Returns:'
+// GC_TODO: BaseAddress - add argument and description to function comment
+// GC_TODO: Size - add argument and description to function comment
+// GC_TODO: PadByte - add argument and description to function comment
+// GC_TODO: OutFile - add argument and description to function comment
+// GC_TODO: FileList - add argument and description to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN PadSize;
+ UINTN FileSize;
+ CHAR8 **InFile;
+ FILE *Fp;
+ UINT8 *Buffer;
+ UINTN NumByte;
+
+ //
+ // Ensure, if there are any previous Firmware Device exists,
+ // If yes, make it to 0 bytes
+ //
+ if ((Fp = fopen (OutFile, "w")) != NULL) {
+ fclose (Fp);
+ }
+
+ InFile = FileList;
+
+ while (*InFile != NULL) {
+ NumFvFiles++;
+ InFile++;
+ }
+
+ InitializeComps ();
+
+ //
+ // Restore the orginal pointers
+ //
+ FvInfo = OrgFvInfoPtr;
+ InFile = FileList;
+
+ while (*InFile != NULL) {
+ strcpy ((*FvInfo)->FvInfoFile, *InFile);
+ Status = GetFvRelatedInfoFromInfFile (*InFile);
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error occurred in processsing INF file");
+ CleanUpMemory ();
+ return Status;
+ }
+
+ InFile++;
+ FvInfo++;
+ }
+
+ FdInfo->FdSize = Size;
+ FdInfo->FdBaseAddress = BaseAddress;
+ FdInfo->PadValue = PadByte;
+ FvInfo = OrgFvInfoPtr;
+ strcpy (FdInfo->OutFileName, OutFile);
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ Status = GenerateFvImage ((*FvInfo)->FvInfoFile);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ //
+ // Sort the Firmware Volume informations. Firmware Volume with lower
+ // base addresses will be processed first and hiher base address one
+ // will be processed later.
+ //
+ qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);
+
+ LastAddress = (*FvInfo)->FvBaseAddress;
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ Status = BuildFirmwareDeviceBinaryFromFwVolumes (
+ (*FvInfo)->FvBaseAddress,
+ (*FvInfo)->FvFile,
+ FdInfo->OutFileName
+ );
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ FvInfo++;
+ }
+ //
+ // Check if any space left after copying data from all Firmware Volumes
+ // If yes, then fill those location with PadValue.
+ //
+ if ((FdInfo->FdBaseAddress + Size) > LastAddress) {
+
+ PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);
+ Buffer = malloc (PadSize);
+
+ if (Buffer == NULL) {
+ CleanUpMemory ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < PadSize; Index++) {
+ *Buffer = FdInfo->PadValue;
+ Buffer++;
+ }
+
+ Buffer -= PadSize;
+
+ Fp = fopen (OutFile, "a+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Opening file %s", OutFile);
+ CleanUpMemory ();
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (fileno (Fp));
+ fseek (Fp, FileSize, SEEK_SET);
+ NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ fclose (Fp);
+
+ if (NumByte != (sizeof (UINT8) * PadSize)) {
+ printf ("\nERROR: Copying data from buffer to File %s ", OutFile);
+ CleanUpMemory ();
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Clean up all the memory which has been allocated so far.
+ //
+ CleanUpMemory ();
+ return EFI_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c
new file mode 100644
index 0000000..9c56d06
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c
@@ -0,0 +1,330 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenFdImageExe.c
+
+Abstract:
+
+ This contains all code necessary to build the GenFdImage.exe utility.
+ This utility relies heavily on the GenFdImage Lib. Definitions for both
+ can be found in the GenFdImage Utility Specification, review draft.
+
+--*/
+
+//
+// Coded to EFI 2.0 Coding Standards
+//
+//
+// Include files
+//
+#include "GenFdImage.h"
+#include "GenFdImageExe.h"
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s, EFI 2.0 Firmware Device Image Generation Utility. ""Version %i.%i, %s.\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION,
+ UTILITY_DATE
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "Usage: %s -B BaseAddress -S Size -F FillByte"" [-I FvInfFileName] -O OutputFileName \n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf ("\tBaseAddress is the starting address of the FD Image\n\n");
+ printf ("\tSize is the size of the FD Image.\n\n");
+ printf ("\tFillByte is the desired value of free space in the Image\n\n");
+ printf ("\tFvInfFileName is the name of an FV Image description file.\n\n");
+ printf ("\tOutputFileName is the desired output file name.\n\n");
+}
+
+EFI_STATUS
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility uses GenFdImage.lib to build a Firmware Device Image
+ which will include several Firmware Volume Images.
+
+Arguments:
+
+ Base Address Base Address of the firmware volume..
+ Size Size of the Firmware Volume
+ FillByte The byte value which would be needed to pad
+ between various Firmware Volumes
+ FvInfFile Fv inf file
+ OutputFileName The name of output file which would be created
+
+Returns:
+
+ EFI_SUCCESS No error conditions detected.
+ EFI_INVALID_PARAMETER One or more of the input parameters is invalid.
+ EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable.
+ Most commonly this will be memory allocation or
+ file creation.
+ EFI_LOAD_ERROR GenFvImage.lib could not be loaded.
+ EFI_ABORTED Error executing the GenFvImage lib.
+
+--*/
+// GC_TODO: argc - add argument and description to function comment
+// GC_TODO: argv - add argument and description to function comment
+{
+ UINTN Index;
+ UINTN FvFilesCount;
+
+ UINT8 i;
+
+ UINT64 StartAddress;
+ UINT64 Size;
+ UINT64 FillByteVal;
+
+ CHAR8 **FvInfFileList;
+ CHAR8 **OrgFvInfFileList;
+ CHAR8 OutputFileName[_MAX_PATH];
+
+ EFI_STATUS Status;
+
+ INTN arg_counter;
+
+ //
+ // Echo for makefile debug
+ //
+ printf ("\n\n");
+ for (arg_counter = 0; arg_counter < argc; arg_counter++) {
+ printf ("%s ", argv[arg_counter]);
+ }
+
+ printf ("\n\n");
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc < MIN_ARGS) {
+ printf ("ERROR: missing 1 or more input arguments.\n\n");
+ PrintUsage ();
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Initialize variables
+ //
+ StartAddress = 0;
+ Size = 0;
+ FillByteVal = 0;
+ FvFilesCount = 0;
+
+ for (i = 1; i < argc; i++) {
+ if (stricmp (argv[i], "-I") == 0) {
+ FvFilesCount++;
+ }
+ }
+
+ FvInfFileList = malloc (sizeof (UINTN) * (FvFilesCount + 1));
+ if (FvInfFileList == NULL) {
+ printf ("ERROR: allocating memory for FvInfFileList in -main- function.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (FvInfFileList, 0, sizeof (UINTN) * (FvFilesCount + 1));
+
+ OrgFvInfFileList = FvInfFileList;
+
+ for (Index = 0; Index < FvFilesCount; Index++) {
+ *FvInfFileList = malloc (_MAX_PATH);
+ memset (*FvInfFileList, 0, _MAX_PATH);
+ FvInfFileList++;
+ }
+
+ strcpy (OutputFileName, "");
+
+ //
+ // Parse the command line arguments
+ //
+ FvInfFileList = OrgFvInfFileList;
+
+ for (i = 1; i < argc; i += 2) {
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[i][0] != '-' && argv[i][0] != '/') {
+ PrintUsage ();
+ printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[i][2] != 0) {
+ PrintUsage ();
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Determine argument to read
+ //
+ switch (argv[i][1]) {
+
+ case 'I':
+ case 'i':
+ if ((FvInfFileList != NULL) && (strlen (*FvInfFileList) == 0)) {
+ strcpy (*FvInfFileList, argv[i + 1]);
+ FvInfFileList++;
+ } else {
+ printf ("ERROR: FvInfFile Name is more than specifed.\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case 'O':
+ case 'o':
+ if (strlen (OutputFileName) == 0) {
+ strcpy (OutputFileName, argv[i + 1]);
+ } else {
+ PrintUsage ();
+ printf ("ERROR: OutputFileName may only be specified once.\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case 'B':
+ case 'b':
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &StartAddress);
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Bad FD Image start address specified");
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case 'S':
+ case 's':
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &Size);
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Bad FD Image size specified");
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ case 'F':
+ case 'f':
+ Status = AsciiStringToUint64 (argv[i + 1], FALSE, &FillByteVal);
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Not a recognized Fill Byte value");
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+
+ default:
+ PrintUsage ();
+ printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+ }
+ //
+ // Call the GenFdImage Lib
+ //
+ FvInfFileList = OrgFvInfFileList;
+
+ Status = GenerateFdImage (
+ StartAddress,
+ Size,
+ (UINT8) FillByteVal,
+ OutputFileName,
+ FvInfFileList
+ );
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ printf ("\nERROR: Invalid parameter passed to GenFdImage lib.\n");
+ break;
+
+ case EFI_ABORTED:
+ printf ("\nERROR: Error detected while creating the file image.\n");
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ printf ("\nERROR: GenFdImage Lib could not allocate required resources.\n");
+ break;
+
+ case EFI_VOLUME_CORRUPTED:
+ printf ("\nERROR: No base address was specified \n");
+ break;
+
+ case EFI_LOAD_ERROR:
+ printf ("\nERROR: An error occurred loading one of the required support Lib.\n");
+ break;
+
+ default:
+ printf ("\nERROR: GenFdImage lib returned unknown status %X.\n", Status);
+ break;
+ }
+
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h
new file mode 100644
index 0000000..e07cb23
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h
@@ -0,0 +1,91 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenFdImageExe.h
+
+Abstract:
+
+ Definitions for the Boot Strap File Image generation utility.
+
+--*/
+
+#ifndef _EFI_GEN_FD_IMAGE_EXE_H
+#define _EFI_GEN_FD_IMAGE_EXE_H
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "GenFdImage"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 0
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MIN_ARGS 10
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c
new file mode 100644
index 0000000..39698d9
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c
@@ -0,0 +1,848 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenFdImageLib.C
+
+Abstract:
+
+ This file contains the functions required to generate
+ the Firmware Device
+
+--*/
+
+//
+// Coded to EFI 2.0 Coding Standards
+//
+//
+// Include file in build
+//
+#include "GenFdImage.h"
+
+//
+// Global declarations
+//
+UINTN ValidLineNum = 0;
+UINTN NumFvFiles = 0;
+
+static UINT64 LastAddress = 0;
+
+CHAR8 **TokenStr;
+CHAR8 **OrgStrTokPtr;
+
+FDINFO *FdInfo;
+FDINFO *OrgFdInfoPtr;
+
+FVINFO **FvInfo;
+FVINFO **OrgFvInfoPtr;
+
+//
+// Internal Functions
+//
+INTN
+CompareItems (
+ IN const VOID *Arg1,
+ IN const VOID *Arg2
+ )
+/*++
+
+Routine Description:
+
+ This function is used by qsort to sort the Fv list based on FvBaseAddress
+
+Arguments:
+
+ Arg1
+ Arg2
+
+Returns:
+
+ None
+
+--*/
+// GC_TODO: Arg1 - add argument and description to function comment
+// GC_TODO: Arg2 - add argument and description to function comment
+{
+ if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {
+ return 1;
+ } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+VOID
+BuildTokenList (
+ IN CHAR8 *Token
+ )
+/*++
+
+Routine Description:
+
+ This function builds the token list in an array which will be parsed later
+
+Arguments:
+
+ Token String,
+
+Returns:
+
+ None
+
+--*/
+{
+ strcpy (*TokenStr, Token);
+ TokenStr++;
+}
+
+VOID
+TrimLine (
+ IN CHAR8 *Line
+ )
+/*++
+
+Routine Description:
+
+ This function cleans up the line by removing all whitespace and
+ comments.
+
+Arguments:
+
+ Line String,
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 TmpLine[FILE_NAME_SIZE];
+ CHAR8 c;
+ CHAR8 *Ptr0;
+
+ UINTN i;
+ UINTN j;
+
+ //
+ // Change '#' to '//' for Comment style
+ //
+ // if((Ptr0=strchr(Line, '#')) != NULL) {
+ //
+ if ((Ptr0 = strstr (Line, "//")) != NULL) {
+ Line[Ptr0 - Line] = 0;
+ }
+
+ i = 0;
+ j = 0;
+ while ((c = Line[i]) != 0) {
+ if ((c != ' ') && (c != '\t') && (c != '\n')) {
+ TmpLine[j++] = c;
+ }
+
+ i++;
+ }
+
+ TmpLine[j] = 0;
+ strcpy (Line, TmpLine);
+}
+
+VOID
+ValidLineCount (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function calculates number of valid lines in a input file.
+
+Arguments:
+
+ Fp Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 Buff[FILE_NAME_SIZE];
+
+ while (fgets (Buff, sizeof (Buff), Fp)) {
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ ValidLineNum++;
+ }
+}
+
+VOID
+ParseInputFile (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function parses the input file and tokenizes the string
+
+Arguments:
+
+ Fp Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Token;
+ CHAR8 Buff[FILE_NAME_SIZE];
+ CHAR8 OrgLine[FILE_NAME_SIZE];
+ CHAR8 Str[FILE_NAME_SIZE];
+ CHAR8 Delimit[] = "=";
+
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
+ strcpy (OrgLine, Buff);
+ TrimLine (Buff);
+
+ if (Buff[0] == 0) {
+ continue;
+ }
+
+ Token = strtok (Buff, Delimit);
+
+ while (Token != NULL) {
+ strcpy (Str, Token);
+ BuildTokenList (Str);
+ Token = strtok (NULL, Delimit);
+ }
+ }
+}
+
+EFI_STATUS
+InitializeComps (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable
+ used to store the information retrieved from the INF file.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ UINTN Index;
+
+ FdInfo = malloc (sizeof (FDINFO));
+
+ if (FdInfo == NULL) {
+ printf ("ERROR: allocating memory (struct FDINFO) in"" function InitializeComps.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrgFdInfoPtr = FdInfo;
+
+ FvInfo = malloc (sizeof (INTN) * NumFvFiles);
+
+ if (FvInfo == NULL) {
+ printf ("ERROR: allocating memory (INTN * NumFvFiles) in"" function InitializeComps.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ OrgFvInfoPtr = FvInfo;
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ *FvInfo = malloc (sizeof (FVINFO));
+
+ if (*FvInfo == NULL) {
+ printf ("ERROR: allocating memory (FVINFO) in"" function InitializeComps.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (*FvInfo, 0, sizeof (FVINFO));
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+InitializeInFileInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable
+ used to store the information retrieved from the INF file.
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN OptionFlag;
+
+ UINT64 StringValue;
+
+ OptionFlag = 0;
+ TokenStr = OrgStrTokPtr;
+
+ while (*TokenStr != NULL) {
+ if (stricmp (*TokenStr, "[options]") == 0) {
+ OptionFlag = 1;
+ }
+
+ if (OptionFlag) {
+ if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {
+ *TokenStr++;
+ if (AsciiStringToUint64 (
+ *TokenStr,
+ FALSE,
+ &StringValue
+ ) != EFI_SUCCESS) {
+ printf ("\nERROR: Cannot determine the FV base address.");
+ return ;
+ }
+ (*FvInfo)->FvBaseAddress = StringValue;
+ } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {
+ *TokenStr++;
+ strcpy ((*FvInfo)->FvFile, *TokenStr);
+ }
+ }
+
+ TokenStr++;
+ }
+}
+
+EFI_STATUS
+GetFvRelatedInfoFromInfFile (
+ IN CHAR8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parses it and create a list of tokens
+ which are parsed and used, to intialize the data related to the Firmware
+ Volume.
+
+Arguments:
+
+ FileName FileName which needed to be read to parse data
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+
+ UINTN Index;
+
+ Fp = fopen (FileName, "r");
+
+ if (Fp == NULL) {
+ printf ("Error in opening %s file\n", FileName);
+ return EFI_ABORTED;
+ }
+
+ ValidLineCount (Fp);
+
+ if (ValidLineNum == 0) {
+ printf ("\nFile doesn't contain any valid informations");
+ return EFI_ABORTED;
+ }
+
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));
+ memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));
+ OrgStrTokPtr = TokenStr;
+
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {
+ *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
+ memset (*TokenStr, 0, FILE_NAME_SIZE);
+ TokenStr++;
+ }
+
+ *TokenStr = NULL;
+ TokenStr = OrgStrTokPtr;
+ fseek (Fp, 0L, SEEK_SET);
+
+ ParseInputFile (Fp);
+ InitializeInFileInfo ();
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteFwBinary (
+ IN CHAR8 *FileName,
+ IN UINT64 StartAddress,
+ IN UINT64 Size,
+ IN UINT8 *Buffer
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parses it and creates a list of tokens
+ which are parsed and used to intialize the data related to the Firmware
+ Volume.
+
+Arguments:
+
+ FileName FileName which needed to be read to parse data
+ StartAddress This will set the file position.
+ Size Size in bytes needed to be written
+ Buffer Buffer needed to e written
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: EFI_INVALID_PARAMETER - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+
+ UINTN NumByte;
+
+ Fp = fopen (FileName, "a+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Error in opening file %s ", FileName);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ fseek (Fp, (UINTN) StartAddress, SEEK_SET);
+ NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);
+
+ //
+ // Check to ensure that buffer has been copied successfully
+ //
+ if (NumByte != Size) {
+ printf ("\nERROR: Error in copying the buffer into file");
+ return EFI_ABORTED;
+ }
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+BuildFirmwareDeviceBinaryFromFwVolumes (
+ IN UINT64 FvBaseAddress,
+ IN CHAR8 *FvFileName,
+ IN CHAR8 *FdFileName
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parses it and creates a list of tokens
+ which are parsed and used to intialize the data related to the Firmware
+ Volume.
+
+Arguments:
+
+ FvBaseAddress Base Address. This info is retrieved from INF file
+ FvFileName InputFileName
+ FdFileName Output File Name
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ FILE *Fp;
+
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT64 PadByteSize;
+ UINT64 BaseAddress;
+
+ UINTN Index;
+
+ UINT8 *Buffer;
+
+ EFI_STATUS Status;
+
+ static UINT64 StartAddress = 0;
+
+ Fp = fopen (FvFileName, "r+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Error in opening file %s", FvFileName);
+ return EFI_ABORTED;
+ }
+
+ BaseAddress = FdInfo->FdBaseAddress;
+
+ //
+ // Check if Base Address of Firmware Volume falls below the Base Address
+ // Firmware Device, if yes, then abort this process.
+ //
+ if (FvBaseAddress < BaseAddress) {
+ printf ("\nERROR: Firmware Volume Base Address falls below Firmware ""Device Address.\n");
+ return EFI_ABORTED;
+ }
+ //
+ // Check if there are any holes between two Firmware Volumes. If any holes
+ // exist, fill the hole with PadByted data.
+ //
+ if (FvBaseAddress > LastAddress) {
+ PadByteSize = (FvBaseAddress - LastAddress);
+ Buffer = malloc ((UINTN) PadByteSize);
+ if (Buffer == NULL) {
+ printf ("ERROR: allocating (Buffer) memory in"" function BuildFirmwareDeviceBinaryFromFwVolumes.\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < PadByteSize; Index++) {
+ *Buffer = FdInfo->PadValue;
+ Buffer++;
+ }
+
+ Buffer -= PadByteSize;
+ Status = WriteFwBinary (
+ FdFileName,
+ StartAddress,
+ (UINT64) PadByteSize,
+ Buffer
+ );
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in writing the binary image to file");
+ return Status;
+ }
+
+ StartAddress += PadByteSize;
+ LastAddress += PadByteSize;
+ }
+ //
+ // Proceed with next Firmware Volume updates
+ //
+ FileSize = _filelength (fileno (Fp));
+
+ if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {
+ printf (
+ "\nERROR:Unable to update Firmware Device. File %s is larger than \
+ available space.",
+ FvFileName
+ );
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ return EFI_ABORTED;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+
+ if (Buffer == NULL) {
+ printf ("Error in allocating buffer to read specific file\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+
+ Status = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);
+
+ if (Buffer) {
+ free ((VOID *) Buffer);
+ }
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error in writing the binary image to file");
+ return Status;
+ }
+
+ StartAddress += NumByteRead;
+ LastAddress += FileSize;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+CleanUpMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function cleans up any allocated buffer
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+
+ if (FdInfo) {
+ free (FdInfo);
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ if (FvInfo) {
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ if (*FvInfo) {
+ free (*FvInfo);
+ }
+
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+ free (FvInfo);
+ }
+}
+
+EFI_STATUS
+GenerateFdImage (
+ IN UINT64 BaseAddress,
+ IN UINT64 Size,
+ IN UINT8 PadByte,
+ IN CHAR8 *OutFile,
+ IN CHAR8 **FileList
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parses it and creates a list of tokens
+ which are parsed and used to intialize the data related to the Firmware
+ Volume.
+
+Arguments:
+
+ BaseAddress Base Address for this Firmware Device
+ Size, Total Size of the Firmware Device
+ PadByte Pad byte data
+ OutFile Output File Name
+ FileList File List pointer to INF file names.
+
+Returns:
+
+ EFI_STATUS
+
+--*/
+// GC_TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_ABORTED - add return value to function comment
+// GC_TODO: EFI_SUCCESS - add return value to function comment
+{
+ EFI_STATUS Status;
+
+ UINTN Index;
+ UINTN PadSize;
+ UINTN FileSize;
+ UINTN NumByte;
+
+ CHAR8 **InFile;
+
+ FILE *Fp;
+
+ UINT8 *Buffer;
+
+ //
+ // If any previous Firmware Device existed,
+ // make it to 0 bytes
+ //
+ if ((Fp = fopen (OutFile, "w")) != NULL) {
+ fclose (Fp);
+ }
+
+ InFile = FileList;
+
+ while (*InFile != NULL) {
+ NumFvFiles++;
+ InFile++;
+ }
+
+ InitializeComps ();
+
+ //
+ // Restore the orginal pointers
+ //
+ FvInfo = OrgFvInfoPtr;
+ InFile = FileList;
+
+ while (*InFile != NULL) {
+ strcpy ((*FvInfo)->FvInfoFile, *InFile);
+ Status = GetFvRelatedInfoFromInfFile (*InFile);
+
+ if (Status != EFI_SUCCESS) {
+ printf ("\nERROR: Error occurred in processsing INF file");
+ CleanUpMemory ();
+ return Status;
+ }
+
+ InFile++;
+ FvInfo++;
+ }
+
+ FdInfo->FdSize = Size;
+ FdInfo->FdBaseAddress = BaseAddress;
+ FdInfo->PadValue = PadByte;
+ FvInfo = OrgFvInfoPtr;
+ strcpy (FdInfo->OutFileName, OutFile);
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ Status = GenerateFvImage ((*FvInfo)->FvInfoFile);
+
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ FvInfo++;
+ }
+
+ FvInfo = OrgFvInfoPtr;
+
+ //
+ // Sort the Firmware Volume information. Firmware Volume with lower
+ // base addresses will be processed first and higher base address one
+ // will be processed later.
+ //
+ qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);
+
+ LastAddress = (*FvInfo)->FvBaseAddress;
+
+ for (Index = 0; Index < NumFvFiles; Index++) {
+ Status = BuildFirmwareDeviceBinaryFromFwVolumes (
+ (*FvInfo)->FvBaseAddress,
+ (*FvInfo)->FvFile,
+ FdInfo->OutFileName
+ );
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ FvInfo++;
+ }
+ //
+ // Check if any space left after copying data from all Firmware Volumes
+ // If yes, then fill those location with PadValue.
+ //
+ if ((FdInfo->FdBaseAddress + Size) > LastAddress) {
+
+ PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);
+ Buffer = malloc (PadSize);
+
+ if (Buffer == NULL) {
+ printf ("\nERROR: allocating PadSize memory in function GenerateFdImage.\n");
+ CleanUpMemory ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < PadSize; Index++) {
+ *Buffer = FdInfo->PadValue;
+ Buffer++;
+ }
+
+ Buffer -= PadSize;
+
+ Fp = fopen (OutFile, "a+b");
+
+ if (Fp == NULL) {
+ printf ("\nERROR:Opening file %s", OutFile);
+ CleanUpMemory ();
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (fileno (Fp));
+ fseek (Fp, FileSize, SEEK_SET);
+ NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ fclose (Fp);
+
+ if (NumByte != (sizeof (UINT8) * PadSize)) {
+ printf ("\nERROR: Copying data from buffer to File %s ", OutFile);
+ CleanUpMemory ();
+ return EFI_ABORTED;
+ }
+ }
+ //
+ // Clean up all the memory which has been allocated so far.
+ //
+ CleanUpMemory ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/GenFdImage/Makefile b/Tools/Source/TianoTools/GenFdImage/Makefile
new file mode 100644
index 0000000..94fafaf
--- /dev/null
+++ b/Tools/Source/TianoTools/GenFdImage/Makefile
@@ -0,0 +1,100 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Define some macros we use here. Should get rid of them someday and
+# get rid of the extra level of indirection.
+#
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)
+
+#
+# Common information
+#
+
+INC=$(INC) \
+ -I "$(TIANO_TOOLS_SOURCE)\GenFvImage"
+
+#
+# Target specific information
+#
+
+TARGET_NAME=GenFdImage
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+
+TARGET_LIB = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).lib
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.c"
+TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.h" \
+ "$(TARGET_SOURCE_DIR)\GenFdImage.h" \
+ "$(COMMON_SOURCE)\ParseInf.h" \
+ "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \
+ "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \
+ "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"
+
+TARGET_LIB_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageLib.c"
+TARGET_LIB_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImage.h" \
+ "$(TIANO_TOOLS_SOURCE)\GenFvImage\GenFvImage.h" \
+ "$(COMMON_SOURCE)\ParseInf.h" \
+ "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"
+TARGET_LIB_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \
+ "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \
+ "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"
+
+
+#
+# Build targets
+#
+
+all: $(TARGET_LIB) $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_LIB)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)
+
+#
+# Build LIB
+#
+
+$(TARGET_LIB): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj $(TARGET_LIB_LIBS)
+ $(LIB) $(LIB_FLAGS) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj /OUT:$(TARGET_LIB)
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj: $(TARGET_LIB_SOURCE) $(TARGET_LIB_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_LIB_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj
+
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* > NUL
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/GenTEImage/GenTEImage.c b/Tools/Source/TianoTools/GenTEImage/GenTEImage.c
new file mode 100644
index 0000000..8aef6d3
--- /dev/null
+++ b/Tools/Source/TianoTools/GenTEImage/GenTEImage.c
@@ -0,0 +1,919 @@
+/*++
+
+Copyright (c) 1999-2004 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+Module Name:
+
+ GenTEImage.c
+
+Abstract:
+
+ Utility program to shrink a PE32 image down by replacing
+ the DOS, PE, and optional headers with a minimal header.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Tiano.h"
+#include "TianoCommon.h"
+#include "EfiImage.h" // for PE32 structure definitions
+#include "EfiUtilityMsgs.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "GenTEImage"
+#define UTILITY_VERSION "v0.11"
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 256
+#define DEFAULT_OUTPUT_EXTENSION ".te"
+
+//
+// Use this to track our command-line options and globals
+//
+struct {
+ INT8 OutFileName[MAX_PATH];
+ INT8 InFileName[MAX_PATH];
+ INT8 Verbose;
+ INT8 Dump;
+} mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ INT8 *Name;
+} STRING_LOOKUP;
+
+static STRING_LOOKUP mMachineTypes[] = {
+ EFI_IMAGE_MACHINE_IA32,
+ "IA32",
+ EFI_IMAGE_MACHINE_IA64,
+ "IA64",
+ EFI_IMAGE_MACHINE_EBC,
+ "EBC",
+ 0,
+ NULL
+};
+
+static STRING_LOOKUP mSubsystemTypes[] = {
+ EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,
+ "EFI application",
+ EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,
+ "EFI boot service driver",
+ EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,
+ "EFI runtime driver",
+ 0,
+ NULL
+};
+//
+// Function prototypes
+//
+static
+void
+Usage (
+ VOID
+ );
+
+static
+STATUS
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ );
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ );
+
+static
+void
+DumpImage (
+ INT8 *FileName
+ );
+
+static
+INT8 *
+GetMachineTypeStr (
+ UINT16 MachineType
+ );
+
+static
+INT8 *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ );
+
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ INT8 *Ext;
+ UINT32 Status;
+
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv)) {
+ return STATUS_ERROR;
+ }
+ //
+ // If dumping an image, then do that and quit
+ //
+ if (mOptions.Dump) {
+ DumpImage (mOptions.InFileName);
+ goto Finish;
+ }
+ //
+ // Determine the output filename. Either what they specified on
+ // the command line, or the first input filename with a different extension.
+ //
+ if (!mOptions.OutFileName[0]) {
+ strcpy (mOptions.OutFileName, mOptions.InFileName);
+ //
+ // Find the last . on the line and replace the filename extension with
+ // the default
+ //
+ for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
+ (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
+ Ext--
+ )
+ ;
+ //
+ // If dot here, then insert extension here, otherwise append
+ //
+ if (*Ext != '.') {
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
+ }
+
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {
+ Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");
+ goto Finish;
+ }
+ //
+ // Process the file
+ //
+ ProcessFile (mOptions.InFileName, mOptions.OutFileName);
+Finish:
+ Status = GetUtilityStatus ();
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ INT8 *InFileName,
+ INT8 *OutFileName
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ InFileName - the file name pointer to the input file
+ OutFileName - the file name pointer to the output file
+
+Returns:
+
+ STATUS_SUCCESS - the process has been finished successfully
+ STATUS_ERROR - error occured during the processing
+
+--*/
+{
+ STATUS Status;
+ FILE *InFptr;
+ FILE *OutFptr;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ EFI_TE_IMAGE_HEADER TEImageHeader;
+ UINT32 PESigOffset;
+ EFI_IMAGE_FILE_HEADER FileHeader;
+ EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;
+ EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;
+ UINT32 BytesStripped;
+ UINT32 FileSize;
+ UINT8 *Buffer;
+ long SaveFilePosition;
+
+ InFptr = NULL;
+ OutFptr = NULL;
+ Buffer = NULL;
+ Status = STATUS_ERROR;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (InFileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, InFileName, "failed to open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {
+ goto Finish;
+ }
+ //
+ // Initialize our new header
+ //
+ memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
+
+ //
+ // Seek to the end to get the file size
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ fseek (InFptr, 0, SEEK_SET);
+
+ //
+ // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit
+ // offset (from the start of the file) to the PE signature, which always
+ // follows the MSDOS stub. The PE signature is immediately followed by the
+ // COFF file header.
+ //
+ //
+ if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);
+ goto Finish;
+ }
+
+ if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");
+ goto Finish;
+ }
+
+ if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {
+ Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");
+ goto Finish;
+ }
+ //
+ // We should now be at the COFF file header. Read it in and verify it's
+ // of an image type we support.
+ //
+ if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read file header from image");
+ goto Finish;
+ }
+
+ if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {
+ Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);
+ goto Finish;
+ }
+ //
+ // Calculate the total number of bytes we're going to strip off. The '4' is for the
+ // PE signature PE\0\0. Then sanity check the size.
+ //
+ BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;
+ if (BytesStripped >= FileSize) {
+ Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");
+ goto Finish;
+ }
+
+ if (BytesStripped &~0xFFFF) {
+ Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);
+ goto Finish;
+ }
+
+ TEImageHeader.StrippedSize = (UINT16) BytesStripped;
+
+ //
+ // Read in the optional header. Assume PE32, and if not, then re-read as PE32+
+ //
+ SaveFilePosition = ftell (InFptr);
+ if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");
+ goto Finish;
+ }
+
+ if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ //
+ // Fill in our new header with required data directory entries
+ //
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;
+ //
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
+ //
+ // We're going to pack the subsystem into 1 byte. Make sure it fits
+ //
+ if (OptionalHeader32.Subsystem &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image subsystem 0x%X cannot be packed into 1 byte",
+ (UINT32) OptionalHeader32.Subsystem
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader32.Subsystem;
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+ } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ //
+ // Rewind and re-read the optional header
+ //
+ fseek (InFptr, SaveFilePosition, SEEK_SET);
+ if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");
+ goto Finish;
+ }
+
+ TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;
+ //
+ // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);
+ //
+ // We're going to pack the subsystem into 1 byte. Make sure it fits
+ //
+ if (OptionalHeader64.Subsystem &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image subsystem 0x%X cannot be packed into 1 byte",
+ (UINT32) OptionalHeader64.Subsystem
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.Subsystem = (UINT8) OptionalHeader64.Subsystem;
+ TEImageHeader.BaseOfCode = OptionalHeader32.BaseOfCode;
+ TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ }
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ "unsupported magic number 0x%X found in optional header",
+ (UINT32) OptionalHeader32.Magic
+ );
+ goto Finish;
+ }
+ //
+ // Fill in the remainder of our new image header
+ //
+ TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
+ TEImageHeader.Machine = FileHeader.Machine;
+ //
+ // We're going to pack the number of sections into a single byte. Make sure it fits.
+ //
+ if (FileHeader.NumberOfSections &~0xFF) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ InFileName,
+ NULL,
+ "image's number of sections 0x%X cannot be packed into 1 byte",
+ (UINT32) FileHeader.NumberOfSections
+ );
+ goto Finish;
+ }
+
+ TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;
+
+ //
+ // Now open our output file
+ //
+ if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
+ Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");
+ goto Finish;
+ }
+ //
+ // Write the TE header
+ //
+ if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, "failed to write image header to output file", NULL);
+ goto Finish;
+ }
+ //
+ // Position into the input file, read the part we're not stripping, and
+ // write it out.
+ //
+ fseek (InFptr, BytesStripped, SEEK_SET);
+ Buffer = (UINT8 *) malloc (FileSize - BytesStripped);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 0, "application error", "failed to allocate memory");
+ goto Finish;
+ }
+
+ if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {
+ Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");
+ goto Finish;
+ }
+
+ if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");
+ goto Finish;
+ }
+
+ Status = STATUS_SUCCESS;
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // Close the output file. If there was an error, delete the output file so
+ // that a subsequent build will rebuild it.
+ //
+ if (OutFptr != NULL) {
+ fclose (OutFptr);
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutFileName);
+ }
+ }
+
+ //
+ // Free up our buffer
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ return Status;
+}
+
+static
+STATUS
+CheckPE32File (
+ INT8 *FileName,
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileName - GC_TODO: add argument description
+ Fptr - GC_TODO: add argument description
+ MachineType - GC_TODO: add argument description
+ SubSystem - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ /*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_FILE_HEADER FileHdr;
+ EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;
+ UINT32 PESig;
+ STATUS Status;
+
+ Status = STATUS_ERROR;
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");
+ goto Finish;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");
+ goto Finish;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");
+ goto Finish;
+ }
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PESig != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");
+ goto Finish;
+ }
+ //
+ // Read the file header
+ //
+ if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");
+ goto Finish;
+ }
+ //
+ // Read the optional header so we can get the subsystem
+ //
+ if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");
+ goto Finish;
+ }
+
+ *SubSystem = OptionalHdr.Subsystem;
+ if (mOptions.Verbose) {
+ fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem);
+ }
+ //
+ // Good to go
+ //
+ Status = STATUS_SUCCESS;
+Finish:
+ fseek (Fptr, 0, SEEK_SET);
+ return Status;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv - standard C main() argument list
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+// GC_TODO: ] - add argument and description to function comment
+{
+ //
+ // Clear out the options
+ //
+ memset ((char *) &mOptions, 0, sizeof (mOptions));
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+ //
+ // If no arguments, assume they want usage info
+ //
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Process until no more arguments
+ //
+ while ((Argc > 0) && ((Argv[0][0] == '-') || (Argv[0][0] == '/'))) {
+ //
+ // To simplify string comparisons, replace slashes with dashes
+ //
+ Argv[0][0] = '-';
+ if (stricmp (Argv[0], "-o") == 0) {
+ //
+ // Output filename specified with -o
+ // Make sure there's another parameter
+ //
+ if (Argc > 1) {
+ strcpy (mOptions.OutFileName, Argv[1]);
+ } else {
+ Error (NULL, 0, 0, Argv[0], "missing output file name with option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {
+ //
+ // Help option
+ //
+ Usage ();
+ return STATUS_ERROR;
+ } else if (stricmp (Argv[0], "-v") == 0) {
+ //
+ // -v for verbose
+ //
+ mOptions.Verbose = 1;
+ } else if (stricmp (Argv[0], "-dump") == 0) {
+ //
+ // -dump for dumping an image
+ //
+ mOptions.Dump = 1;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ Usage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+ }
+ //
+ // Better be one more arg for input file name
+ //
+ if (Argc == 0) {
+ Error (NULL, 0, 0, "input file name required", NULL);
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if (Argc != 1) {
+ Error (NULL, 0, 0, Argv[1], "extra arguments on command line");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mOptions.InFileName, Argv[0]);
+ return STATUS_SUCCESS;
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ int Index;
+ static const char *Msg[] = {
+ UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",
+ " Generate a TE image from an EFI PE32 image",
+ " Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",
+ " [-e|-b] [FileName(s)]",
+ " where:",
+ " -v - for verbose output",
+ " -dump - to dump the input file to a text file",
+ " -h -? - for this help information",
+ " -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,
+ " InFileName - name of the input PE32 file",
+ "",
+ NULL
+ };
+ for (Index = 0; Msg[Index] != NULL; Index++) {
+ fprintf (stdout, "%s\n", Msg[Index]);
+ }
+}
+
+static
+VOID
+DumpImage (
+ INT8 *FileName
+ )
+/*++
+
+Routine Description:
+
+ Dump a specified image information
+
+Arguments:
+
+ FileName - File name pointer to the image to dump
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ FILE *InFptr;
+ EFI_TE_IMAGE_HEADER TEImageHeader;
+ INT8 *NamePtr;
+
+ //
+ // Open the input file
+ //
+ InFptr = NULL;
+
+ if ((InFptr = fopen (FileName, "rb")) == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open input file for reading");
+ return ;
+ }
+
+ if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {
+ Error (NULL, 0, 0, FileName, "failed to read image header from input file");
+ goto Finish;
+ }
+
+ if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");
+ goto Finish;
+ }
+ //
+ // Dump the header
+ //
+ fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));
+ fprintf (stdout, " Signature: 0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);
+ NamePtr = GetMachineTypeStr (TEImageHeader.Machine);
+ fprintf (stdout, " Machine: 0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);
+ NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);
+ fprintf (stdout, " Subsystem: 0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);
+ fprintf (stdout, " Number of sections 0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);
+ fprintf (stdout, " Stripped size: 0x%04X\n", (UINT32) TEImageHeader.StrippedSize);
+ fprintf (stdout, " Entry point: 0x%08X\n", TEImageHeader.AddressOfEntryPoint);
+ fprintf (stdout, " Base of code: 0x%08X\n", TEImageHeader.BaseOfCode);
+ fprintf (stdout, " Data directories:\n");
+ fprintf (
+ stdout,
+ " %8X [%8X] RVA [size] of Base Relocation Directory\n",
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size
+ );
+ fprintf (
+ stdout,
+ " %8X [%8X] RVA [size] of Debug Directory\n",
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,
+ TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size
+ );
+
+Finish:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+}
+
+static
+INT8 *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
+ if (mMachineTypes[Index].Value == MachineType) {
+ return mMachineTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
+
+static
+INT8 *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
+ if (mSubsystemTypes[Index].Value == SubsystemType) {
+ return mSubsystemTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
diff --git a/Tools/Source/TianoTools/GenTEImage/Makefile b/Tools/Source/TianoTools/GenTEImage/Makefile
new file mode 100644
index 0000000..f731b6d
--- /dev/null
+++ b/Tools/Source/TianoTools/GenTEImage/Makefile
@@ -0,0 +1,68 @@
+#/*++
+#
+# Copyright (c) 2002 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name:
+#
+# makefile
+#
+# Abstract:
+#
+# makefile for building the GenTEImage utility.
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Define the toolchain which is used to set build options and toolchain paths
+#
+TOOLCHAIN = TOOLCHAIN_MSVC
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = GenTEImage
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib
+
+INC_DEPS = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h
+
+#
+# Build the EXE by compiling the source files, then linking the resultant
+# object files together.
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@
+
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c
new file mode 100644
index 0000000..1845c48
--- /dev/null
+++ b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c
@@ -0,0 +1,973 @@
+/*++
+
+Copyright (c) 1999 - 2005 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ PeiRebaseExe.c
+
+Abstract:
+
+ This contains all code necessary to build the PeiRebase.exe utility.
+ This utility relies heavily on the PeiRebase DLL. Definitions for both
+ can be found in the PEI Rebase Utility Specification, review draft.
+
+--*/
+
+#include "PeiRebaseExe.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "CommonLib.h"
+#include "ParseInf.h"
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)
+#include "FvLib.h"
+
+#include "EfiUtilityMsgs.h"
+
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader;
+
+EFI_STATUS
+ReadHeader (
+ IN FILE *InputFile,
+ OUT UINT32 *FvSize,
+ OUT BOOLEAN *ErasePolarity
+ );
+
+int
+main (
+ int argc,
+ char **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility relocates PEI XIP PE32s in a FV.
+
+Arguments:
+
+ argc - Number of command line arguments
+ argv[]:
+ BaseAddress The base address to use for rebasing the FV. The correct
+ format is a hex number preceded by 0x.
+ InputFileName The name of the input FV file.
+ OutputFileName The name of the output FV file.
+
+ Arguments come in pair in any order.
+ -I InputFileName
+ -O OutputFileName
+ -B BaseAddress
+
+Returns:
+
+ 0 No error conditions detected.
+ 1 One or more of the input parameters is invalid.
+ 2 A resource required by the utility was unavailable.
+ Most commonly this will be memory allocation or file creation.
+ 3 PeiRebase.dll could not be loaded.
+ 4 Error executing the PEI rebase.
+
+--*/
+{
+ UINT8 Index;
+ CHAR8 InputFileName[_MAX_PATH];
+ CHAR8 OutputFileName[_MAX_PATH];
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ BOOLEAN BaseAddressSet;
+ EFI_STATUS Status;
+ FILE *InputFile;
+ FILE *OutputFile;
+ UINT64 FvOffset;
+ UINT32 FileCount;
+ int BytesRead;
+ EFI_FIRMWARE_VOLUME_HEADER *FvImage;
+ UINT32 FvSize;
+ EFI_FFS_FILE_HEADER *CurrentFile;
+ BOOLEAN ErasePolarity;
+ EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress;
+
+ ErasePolarity = FALSE;
+ //
+ // Set utility name for error/warning reporting purposes.
+ //
+ SetUtilityName (UTILITY_NAME);
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Initialize variables
+ //
+ InputFileName[0] = 0;
+ OutputFileName[0] = 0;
+ BaseAddress = 0;
+ BaseAddressSet = FALSE;
+ FvOffset = 0;
+ FileCount = 0;
+ ErasePolarity = FALSE;
+ InputFile = NULL;
+ OutputFile = NULL;
+ FvImage = NULL;
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < MAX_ARGS; Index += 2) {
+ //
+ // Make sure argument pair begin with - or /
+ //
+ if (argv[Index][0] != '-' && argv[Index][0] != '/') {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ //
+ // Make sure argument specifier is only one letter
+ //
+ if (argv[Index][2] != 0) {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized option");
+ return STATUS_ERROR;
+ }
+ //
+ // Determine argument to read
+ //
+ switch (argv[Index][1]) {
+ case 'I':
+ case 'i':
+ if (strlen (InputFileName) == 0) {
+ strcpy (InputFileName, argv[Index + 1]);
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");
+ return STATUS_ERROR;
+ }
+ break;
+
+ case 'O':
+ case 'o':
+ if (strlen (OutputFileName) == 0) {
+ strcpy (OutputFileName, argv[Index + 1]);
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");
+ return STATUS_ERROR;
+ }
+ break;
+
+ case 'B':
+ case 'b':
+ if (!BaseAddressSet) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);
+ if (EFI_ERROR (Status)) {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");
+ return STATUS_ERROR;
+ }
+
+ BaseAddressSet = TRUE;
+ } else {
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");
+ return STATUS_ERROR;
+ }
+ break;
+
+ default:
+ PrintUsage ();
+ Error (NULL, 0, 0, argv[Index], "unrecognized argument");
+ return STATUS_ERROR;
+ break;
+ }
+ }
+ //
+ // Open the file containing the FV
+ //
+ InputFile = fopen (InputFileName, "rb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0, InputFileName, "could not open input file for reading");
+ return STATUS_ERROR;
+ }
+ //
+ // Determine size of FV
+ //
+ Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "could not parse the FV header", NULL);
+ goto Finish;
+ }
+ //
+ // Allocate a buffer for the FV image
+ //
+ FvImage = malloc (FvSize);
+ if (FvImage == NULL) {
+ Error (NULL, 0, 0, "application error", "memory allocation failed");
+ goto Finish;
+ }
+ //
+ // Read the entire FV to the buffer
+ //
+ BytesRead = fread (FvImage, 1, FvSize, InputFile);
+ fclose (InputFile);
+ InputFile = NULL;
+ if ((unsigned int) BytesRead != FvSize) {
+ Error (NULL, 0, 0, InputFileName, "failed to read from file");
+ goto Finish;
+ }
+ //
+ // Prepare to walk the FV image
+ //
+ InitializeFvLib (FvImage, FvSize);
+ //
+ // Get the first file
+ //
+ Status = GetNextFile (NULL, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);
+ goto Finish;
+ }
+ //
+ // Check if each file should be rebased
+ //
+ while (CurrentFile != NULL) {
+ //
+ // Rebase this file
+ //
+ CurrentFileBaseAddress = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);
+ Status = FfsRebase (CurrentFile, CurrentFileBaseAddress);
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);
+ break;
+
+ case EFI_ABORTED:
+ Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);
+ break;
+
+ case EFI_NOT_FOUND:
+ Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);
+ break;
+
+ default:
+ Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);
+ break;
+ }
+
+ goto Finish;
+ }
+ //
+ // Get the next file
+ //
+ Status = GetNextFile (CurrentFile, &CurrentFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);
+ goto Finish;
+ }
+ }
+ //
+ // Open the output file
+ //
+ OutputFile = fopen (OutputFileName, "wb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file");
+ goto Finish;
+ }
+
+ if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {
+ Error (NULL, 0, 0, "failed to write to output file", 0);
+ goto Finish;
+ }
+
+Finish:
+ if (InputFile != NULL) {
+ fclose (InputFile);
+ }
+ //
+ // If we created an output file, and there was an error, remove it so
+ // subsequent builds will rebuild it.
+ //
+ if (OutputFile != NULL) {
+ if (GetUtilityStatus () == STATUS_ERROR) {
+ remove (OutputFileName);
+ }
+
+ fclose (OutputFile);
+ }
+
+ if (FvImage != NULL) {
+ free (FvImage);
+ }
+
+ return GetUtilityStatus ();
+}
+
+EFI_STATUS
+ReadHeader (
+ IN FILE *InputFile,
+ OUT UINT32 *FvSize,
+ OUT BOOLEAN *ErasePolarity
+ )
+/*++
+
+Routine Description:
+
+ This function determines the size of the FV and the erase polarity. The
+ erase polarity is the FALSE value for file state.
+
+Arguments:
+
+ InputFile The file that contains the FV image.
+ FvSize The size of the FV.
+ ErasePolarity The FV erase polarity.
+
+Returns:
+
+ EFI_SUCCESS Function completed successfully.
+ EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
+ EFI_ABORTED The function encountered an error.
+
+--*/
+{
+ EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
+ EFI_FV_BLOCK_MAP_ENTRY BlockMap;
+ UINTN Signature[2];
+ UINTN BytesRead;
+ UINT32 Size;
+
+ BytesRead = 0;
+ Size = 0;
+ //
+ // Check input parameters
+ //
+ if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {
+ Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Read the header
+ //
+ fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
+ BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+ Signature[0] = VolumeHeader.Signature;
+ Signature[1] = 0;
+
+ //
+ // Get erase polarity
+ //
+ if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
+ *ErasePolarity = TRUE;
+ }
+
+ do {
+ fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
+ BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
+
+ if (BlockMap.NumBlocks != 0) {
+ Size += BlockMap.NumBlocks * BlockMap.BlockLength;
+ }
+
+ } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));
+
+ if (VolumeHeader.FvLength != Size) {
+ Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);
+ return EFI_ABORTED;
+ }
+
+ *FvSize = Size;
+
+ rewind (InputFile);
+
+ return EFI_SUCCESS;
+}
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION,
+ UTILITY_DATE
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf (" InputFileName is the name of the EFI FV file to rebase.\n");
+ printf (" OutputFileName is the desired output file name.\n");
+ printf (" BaseAddress is the FV base address to rebase agains.\n");
+ printf (" Argument pair may be in any order.\n\n");
+}
+
+EFI_STATUS
+FfsRebase (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ This function determines if a file is XIP and should be rebased. It will
+ rebase any PE32 sections found in the file using the base address.
+
+Arguments:
+
+ FfsFile A pointer to Ffs file image.
+ BaseAddress The base address to use for rebasing the file image.
+
+Returns:
+
+ EFI_SUCCESS The image was properly rebased.
+ EFI_INVALID_PARAMETER An input parameter is invalid.
+ EFI_ABORTED An error occurred while rebasing the input file image.
+ EFI_OUT_OF_RESOURCES Could not allocate a required resource.
+ EFI_NOT_FOUND No compressed sections could be found.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINTN MemoryImagePointer;
+ UINTN MemoryImagePointerAligned;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+ EFI_PHYSICAL_ADDRESS EntryPoint;
+ UINT32 Pe32ImageSize;
+ UINT32 NewPe32BaseAddress;
+ UINTN Index;
+ EFI_FILE_SECTION_POINTER CurrentPe32Section;
+ EFI_FFS_FILE_STATE SavedState;
+ EFI_IMAGE_NT_HEADERS *PeHdr;
+ UINT32 *PeHdrSizeOfImage;
+ UINT32 *PeHdrChecksum;
+ UINT32 FoundCount;
+ EFI_TE_IMAGE_HEADER *TEImageHeader;
+ UINT8 *TEBuffer;
+ EFI_IMAGE_DOS_HEADER *DosHeader;
+ UINT8 FileGuidString[80];
+ UINT32 TailSize;
+ EFI_FFS_FILE_TAIL TailValue;
+
+ //
+ // Verify input parameters
+ //
+ if (FfsFile == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Convert the GUID to a string so we can at least report which file
+ // if we find an error.
+ //
+ PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Do some cursory checks on the FFS file contents
+ //
+ Status = VerifyFfsFile (FfsFile);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Check if XIP file type. If not XIP, don't rebase.
+ //
+ if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
+ FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
+ FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
+ ) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Rebase each PE32 section
+ //
+ Status = EFI_SUCCESS;
+ FoundCount = 0;
+ for (Index = 1;; Index++) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ FoundCount++;
+
+ //
+ // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
+ //
+ NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
+
+ Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);
+ return Status;
+ }
+ //
+ // Allocate a buffer for the image to be loaded into.
+ //
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));
+ if (MemoryImagePointer == 0) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
+
+
+ ImageContext.ImageAddress = MemoryImagePointerAligned;
+
+ Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageAddress = ImageContext.ImageAddress;
+ ImageSize = ImageContext.ImageSize;
+ EntryPoint = ImageContext.EntryPoint;
+
+ if (ImageSize > Pe32ImageSize) {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "rebased image is larger than original PE32 image",
+ "0x%X > 0x%X, file %s",
+ ImageSize,
+ Pe32ImageSize,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ return EFI_ABORTED;
+ }
+ //
+ // Since we may have updated the Codeview RVA, we need to insure the PE
+ // header indicates the image is large enough to contain the Codeview data
+ // so it will be loaded properly later if the PEIM is reloaded into memory...
+ //
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "unknown machine type in PE32 image",
+ "machine type=0x%X, file=%s",
+ (UINT32) PeHdr->FileHeader.Machine,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ return EFI_ABORTED;
+ }
+
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
+ if (*PeHdrChecksum) {
+ *PeHdrChecksum = 0;
+ }
+ }
+
+ memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);
+
+ free ((VOID *) MemoryImagePointer);
+
+ //
+ // Now update file checksum
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ SavedState = FfsFile->State;
+ FfsFile->IntegrityCheck.Checksum.File = 0;
+ FfsFile->State = 0;
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) FfsFile,
+ GetLength (FfsFile->Size) - TailSize
+ );
+ } else {
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FfsFile->State = SavedState;
+ }
+ //
+ // Update tail if present
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ }
+ //
+ // Now process TE sections
+ //
+ for (Index = 1;; Index++) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ FoundCount++;
+
+ //
+ // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
+ // by GenTEImage
+ //
+ TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
+
+ NewPe32BaseAddress = ((UINT32) BaseAddress) +
+ (
+ (UINTN) CurrentPe32Section.Pe32Section +
+ sizeof (EFI_COMMON_SECTION_HEADER) +
+ sizeof (EFI_TE_IMAGE_HEADER) -
+ TEImageHeader->StrippedSize -
+ (UINTN) FfsFile
+ );
+
+ //
+ // Allocate a buffer to unshrink the image into.
+ //
+ Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER);
+ Pe32ImageSize += TEImageHeader->StrippedSize;
+ TEBuffer = (UINT8 *) malloc (Pe32ImageSize);
+ if (TEBuffer == NULL) {
+ Error (NULL, 0, 0, "failed to allocate memory", NULL);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Expand the image into our buffer and fill in critical fields in the DOS header
+ // Fill in fields required by the loader.
+ // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
+ // itself.
+ //
+ memset (TEBuffer, 0, Pe32ImageSize);
+ DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;
+ DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;
+ *(UINT32 *) (TEBuffer + 0x3C) = 0x40;
+ PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);
+ PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
+ PeHdr->FileHeader.Machine = TEImageHeader->Machine;
+ PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;
+
+ //
+ // 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
+ // the 0x40 bytes for our DOS header.
+ //
+ PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));
+ PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
+ PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
+ PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
+ PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
+ sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
+
+ //
+ // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
+ //
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
+ ) {
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
+ }
+
+ if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
+ (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
+ ) {
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+ PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+ if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
+ PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
+ }
+ }
+ //
+ // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
+ //
+ PeHdr->OptionalHeader.SectionAlignment = 0x10;
+
+ //
+ // Copy the rest of the image to its original offset
+ //
+ memcpy (
+ TEBuffer + TEImageHeader->StrippedSize,
+ (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER)
+ );
+
+ //
+ // Initialize context
+ //
+ memset (&ImageContext, 0, sizeof (ImageContext));
+ ImageContext.Handle = (VOID *) TEBuffer;
+ ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
+
+ Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
+
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ return Status;
+ }
+ //
+ // Allocate a buffer for the image to be loaded into.
+ //
+ MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));
+ if (MemoryImagePointer == 0) {
+ Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);
+ MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
+
+
+ ImageContext.ImageAddress = MemoryImagePointerAligned;
+ Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);
+ free (TEBuffer);
+ free ((VOID *) MemoryImagePointer);
+ return Status;
+ }
+
+ ImageContext.DestinationAddress = NewPe32BaseAddress;
+ Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ return Status;
+ }
+
+ ImageAddress = ImageContext.ImageAddress;
+ ImageSize = ImageContext.ImageSize;
+ EntryPoint = ImageContext.EntryPoint;
+
+ //
+ // Since we may have updated the Codeview RVA, we need to insure the PE
+ // header indicates the image is large enough to contain the Codeview data
+ // so it will be loaded properly later if the PEIM is reloaded into memory...
+ //
+ PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
+ if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);
+ } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
+ PeHdrSizeOfImage = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);
+ PeHdrChecksum = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "unknown machine type in TE image",
+ "machine type=0x%X, file=%s",
+ (UINT32) PeHdr->FileHeader.Machine,
+ FileGuidString
+ );
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ return EFI_ABORTED;
+ }
+
+ if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
+ *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
+ if (*PeHdrChecksum) {
+ *PeHdrChecksum = 0;
+ }
+ }
+
+ TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
+ memcpy (
+ (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),
+ (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),
+ GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
+ sizeof (EFI_TE_IMAGE_HEADER)
+ );
+ free ((VOID *) MemoryImagePointer);
+ free (TEBuffer);
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailSize = sizeof (EFI_FFS_FILE_TAIL);
+ } else {
+ TailSize = 0;
+ }
+ //
+ // Now update file checksum
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ SavedState = FfsFile->State;
+ FfsFile->IntegrityCheck.Checksum.File = 0;
+ FfsFile->State = 0;
+ if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ (UINT8 *) FfsFile,
+ GetLength (FfsFile->Size) - TailSize
+ );
+ } else {
+ FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FfsFile->State = SavedState;
+ }
+ //
+ // Update tail if present
+ //
+ if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
+ *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
+ }
+ }
+ //
+ // If we found no files, then emit an error if no compressed sections either
+ //
+ if (FoundCount == 0) {
+ Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
+
+Arguments:
+
+ FileHandle - The handle to the PE/COFF file
+
+ FileOffset - The offset, in bytes, into the file to read
+
+ ReadSize - The number of bytes to read from the file starting at FileOffset
+
+ Buffer - A pointer to the buffer to read the data into.
+
+Returns:
+
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
+
+--*/
+{
+ CHAR8 *Destination8;
+ CHAR8 *Source8;
+ UINT32 Length;
+
+ Destination8 = Buffer;
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
+ Length = *ReadSize;
+ while (Length--) {
+ *(Destination8++) = *(Source8++);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h
new file mode 100644
index 0000000..9070d1c
--- /dev/null
+++ b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h
@@ -0,0 +1,153 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ PeiRebaseExe.h
+
+Abstract:
+
+ Definitions for the PeiRebase exe utility.
+
+--*/
+
+#ifndef _EFI_PEIM_FIXUP_EXE_H
+#define _EFI_PEIM_FIXUP_EXE_H
+
+#include "Efi2WinNt.h"
+#include "EfiFirmwareFileSystem.h"
+#include "EfiFirmwareVolumeHeader.h"
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "PeiRebase"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 7
+
+//
+// The file copy buffer size
+//
+#define FILE_COPY_BUFFER_SIZE 512
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// Internal function declarations
+//
+EFI_STATUS
+FfsRebaseImageRead (
+ IN VOID *FileHandle,
+ IN UINTN FileOffset,
+ IN OUT UINT32 *ReadSize,
+ OUT VOID *Buffer
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FileHandle - GC_TODO: add argument description
+ FileOffset - GC_TODO: add argument description
+ ReadSize - GC_TODO: add argument description
+ Buffer - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+EFI_STATUS
+FfsRebase (
+ IN OUT EFI_FFS_FILE_HEADER *FfsFile,
+ IN EFI_PHYSICAL_ADDRESS BaseAddress
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FfsFile - GC_TODO: add argument description
+ BaseAddress - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Tools/Source/TianoTools/PeiRebase/makefile b/Tools/Source/TianoTools/PeiRebase/makefile
new file mode 100644
index 0000000..4b19309
--- /dev/null
+++ b/Tools/Source/TianoTools/PeiRebase/makefile
@@ -0,0 +1,71 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name:
+#
+# makefile
+#
+# Abstract:
+#
+# makefile for building the PeiRebase utility.
+#
+# Revision History
+#
+#--*/
+
+#
+# Make sure environmental variable EFI_SOURCE is set
+#
+!IFNDEF EFI_SOURCE
+!ERROR EFI_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = PeiRebase
+TARGET_SRC_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\PeiRebase.exe
+TARGET_EXE_LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\PeiRebase.obj
+
+#
+# Compile each source file
+#
+$(TIANO_TOOLS_OUTPUT)\PeiRebase.obj : $(TARGET_SRC_DIR)\PeiRebaseExe.c $(INC_DEPS) $(TARGET_EXE_LIBS)
+ $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\PeiRebaseExe.c /Fo$@
+
+#
+# Link the object files together
+#
+$(TARGET_EXE) : $(OBJECTS) $(TARGET_EXE_LIBS)
+ @echo LINKING
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) $(TARGET_EXE_LIBS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/Makefile b/Tools/Source/TianoTools/SecApResetVectorFixup/Makefile
new file mode 100644
index 0000000..53e6be5
--- /dev/null
+++ b/Tools/Source/TianoTools/SecApResetVectorFixup/Makefile
@@ -0,0 +1,58 @@
+#/*++
+#
+# Copyright (c) 2005 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = SecApResetVectorFixup
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+TARGET_EXE_SOURCE = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+LIBS = $(TIANO_TOOLS_OUTPUT)\Common.lib
+
+#
+# Build EXE
+#
+
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@
+
+$(TARGET_EXE): $(OBJECTS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)
+
+clean:
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c
new file mode 100644
index 0000000..5cb03f0
--- /dev/null
+++ b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c
@@ -0,0 +1,363 @@
+/*++
+
+Copyright (c) 2005 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ SecApResetVectorFixup.c
+
+Abstract:
+
+ This utility is part of build process for IA32 Fvrecovery.fv whose total size
+ is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset
+ vector at the zero vector of Fv header.
+
+ PEI FV after using the tool
+
+ -------------------------
+ |zzz |
+ | |
+ | |
+ | FFS |
+ | |
+ | |
+ | |
+ |---------------------- |
+ | PAD |
+ | |
+ |.......................| ---
+ | | |
+ |xxx | | 128K
+ |---------------------- | |
+ | VTF (SEC) | |
+ ------------------------- ---
+
+ 1. zzz --> Zero vector, which is beyond the 128K limited address space
+ 2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD
+ file area.
+ 3. After the build process ,the PAD guid is changed to a new GUID to avoid
+ the PAD definition confusing. If there is some problem, try to disable
+ UpdatePadFileGuid
+
+
+
+--*/
+
+#include "SecApResetVectorFixup.h"
+
+
+EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
+EFI_GUID NewFvPadFileNameGuid = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };
+
+//
+// jmp 0xf000:0xffd0 (0xFFFFFFD0)
+//
+UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s - Tiano IA32 SEC Ap Reset Vector Fixup Utility."" Version %i.%i\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);
+ printf (" Where:\n");
+ printf ("\tInputFvrecoveryFile - Name of the IA32 input Fvrecovery.fv file.\n");
+ printf ("\tOutputFvrecoveryFile - Name of the IA32 output Fvrecovery.fv file.\n");
+}
+
+
+VOID
+UpdatePadFileGuid (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
+ IN EFI_FFS_FILE_HEADER *FileHeader,
+ IN UINT32 FileLength,
+ IN OUT EFI_GUID *Guid
+ )
+/*++
+
+Routine Description:
+
+ Update the Pad File Guid to change it to other guid and update
+ the checksum
+
+Arguments:
+ FvHeader - EFI_FIRMWARE_VOLUME_HEADER
+ FileHeader - The FFS PAD file header.
+ FileLength - The FFS PAD file length.
+ Guid - The Guid to compare and if it is PAD Guid, update it to new Guid
+Returns:
+ VOID
+--*/
+
+{
+ if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {
+ //
+ // Set new Pad file guid
+ //
+ memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));
+
+
+
+ FileHeader->Type = EFI_FV_FILETYPE_FFS_PAD;
+ FileHeader->Attributes = 0;
+ //
+ // Fill in checksums and state, must be zero during checksum calculation.
+ //
+ FileHeader->IntegrityCheck.Checksum.Header = 0;
+ FileHeader->IntegrityCheck.Checksum.File = 0;
+ FileHeader->State = 0;
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);
+ } else {
+ FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
+ FileHeader->State = (UINT8)~(FileHeader->State);
+ }
+ }
+
+}
+
+
+STATUS
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *FpIn;
+ FILE *FpOut;
+ UINT32 FvrecoveryFileSize;
+ UINT8 *FileBuffer;
+ UINT8 *FileBufferRaw;
+ UINT64 FvLength;
+ UINT32 Offset;
+ UINT32 FileLength;
+ UINT32 FileOccupiedSize;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ EFI_GUID *TempGuid;
+ UINT8 *FixPoint;
+ UINT32 TempResult;
+ UINT32 Index;
+ UINT32 IpiVector;
+
+ TempGuid = NULL;
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Open the Input Fvrecovery.fv file
+ //
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the Input Fvrecovery.fv file size
+ //
+ fseek (FpIn, 0, SEEK_END);
+ FvrecoveryFileSize = ftell (FpIn);
+ //
+ // Read the contents of input file to memory buffer
+ //
+ FileBuffer = NULL;
+ FileBufferRaw = NULL;
+ FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);
+ if (NULL == FileBufferRaw) {
+ Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);
+ FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);
+ fseek (FpIn, 0, SEEK_SET);
+ TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);
+ if (TempResult != FvrecoveryFileSize) {
+ Error (NULL, 0, 0, "Read input file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the input Fvrecovery.fv file
+ //
+ fclose (FpIn);
+ //
+ // Find the pad FFS file
+ //
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;
+ FvLength = FvHeader->FvLength;
+ FileHeader = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;
+
+ while (Offset < FvLength) {
+ TempGuid = (EFI_GUID *)&(FileHeader->Name);
+ FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;
+ FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);
+ if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {
+ break;
+ }
+ FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);
+ Offset = (UINT32)FileHeader - (UINT32)FileBuffer;
+ }
+
+ if (Offset >= FvLength) {
+ Error (NULL, 0, 0, "No pad file found!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Find the position to place Ap reset vector, the offset
+ // between the position and the end of Fvrecovery.fv file
+ // should not exceed 128kB to prevent Ap reset vector from
+ // outside legacy E and F segment
+ //
+ FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));
+ TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);
+ FixPoint +=TempResult;
+ if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {
+ Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {
+ FixPoint += 0x1000;
+ }
+ FixPoint -= 0x1000;
+ if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {
+ Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Fix up Ap reset vector and calculate the IPI vector
+ //
+ for (Index = 0; Index < 5; Index++) {
+ FixPoint[Index] = ApResetVector[Index];
+ }
+ TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);
+ TempResult >>= 12;
+ IpiVector = TempResult & 0x0FF;
+
+
+ UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);
+
+ //
+ // Open the output Fvrecovery.fv file
+ //
+ if ((FpOut = fopen (argv[2], "w+b")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Write the output Fvrecovery.fv file
+ //
+ if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {
+ Error (NULL, 0, 0, "Write output file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ //
+ //
+ fseek (FpOut, -8, SEEK_END);
+ if ((fwrite (&IpiVector, 1, sizeof(UINT32), FpOut)) != sizeof(UINT32)) {
+ Error (NULL, 0, 0, "Write output file error!", NULL);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the output Fvrecovery.fv file
+ //
+ fclose (FpOut);
+ free ((VOID *)FileBufferRaw);
+ return STATUS_SUCCESS;
+}
+
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h
new file mode 100644
index 0000000..2bed5bc
--- /dev/null
+++ b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 2005 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ SecApResetVectorFixup.h
+
+Abstract:
+
+ Definitions for the SecApResetVectorFixup utility.
+
+--*/
+
+#ifndef _SEC_AP_RESET_VECTOR_FIXUP_H
+#define _SEC_AP_RESET_VECTOR_FIXUP_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "EfiCommon.h"
+#include "EfiImage.h"
+#include "EfiImageFormat.h"
+#include "EfiFirmwareFileSystem.h"
+#include "EfiFirmwareVolumeHeader.h"
+#include "EfiUtilityMsgs.c"
+#include "CommonLib.h"
+
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "SecApResetVectorFixup"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 3
+#define BUF_SIZE (8 * 1024)
+
+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \
+ (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
+
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+
+#endif
diff --git a/Tools/Source/TianoTools/SecFixup/Makefile b/Tools/Source/TianoTools/SecFixup/Makefile
new file mode 100644
index 0000000..6ae2ebd
--- /dev/null
+++ b/Tools/Source/TianoTools/SecFixup/Makefile
@@ -0,0 +1,57 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = SecFixup
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+TARGET_EXE_SOURCE = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+OBJECTS = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+#
+# Build EXE
+#
+
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@
+
+$(TARGET_EXE): $(OBJECTS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)
+
+clean:
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/SecFixup/SecFixup.c b/Tools/Source/TianoTools/SecFixup/SecFixup.c
new file mode 100644
index 0000000..a8e707f
--- /dev/null
+++ b/Tools/Source/TianoTools/SecFixup/SecFixup.c
@@ -0,0 +1,362 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ SecFixup.c
+
+Abstract:
+
+ This utility is part of build process for IA32 SEC FFS file.
+
+ It fixup the reset vector data. The reset vector data binary file
+ will be wrapped as a RAW section and be located immediately after
+ the PE/TE section.
+
+ The SEC EXE file can be either PE or TE file.
+
+--*/
+
+#include <stdio.h>
+
+#include "EfiCommon.h"
+#include "EfiImage.h"
+#include "EfiImageFormat.h"
+#include "EfiUtilityMsgs.c"
+
+#include "SecFixup.h"
+
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf (
+ "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",
+ UTILITY_NAME,
+ UTILITY_MAJOR_VERSION,
+ UTILITY_MINOR_VERSION
+ );
+}
+
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);
+ printf (" Where:\n");
+ printf ("\tSecExeFile - Name of the IA32 SEC EXE file.\n");
+ printf ("\tResetVectorDataFile - Name of the reset vector data binary file.\n");
+ printf ("\tOutputFileName - Name of the output file.\n\n");
+}
+
+STATUS
+main (
+ IN INTN argc,
+ IN CHAR8 **argv
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *FpIn;
+
+ FILE *FpOut;
+ UINT32 AddressOfEntryPoint;
+ INT32 DestRel;
+ STATUS Status;
+ UINT32 SecFileSize;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Display utility information
+ //
+ PrintUtilityInfo ();
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc != MAX_ARGS) {
+ Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+ //
+ // Open the SEC exe file
+ //
+ if ((FpIn = fopen (argv[1], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[1]);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the entry point of the EXE file
+ //
+ Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);
+ if (Status != STATUS_SUCCESS) {
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the SEC file size
+ //
+ fseek (FpIn, 0, SEEK_END);
+ SecFileSize = ftell (FpIn);
+
+ //
+ // Close the SEC file
+ //
+ fclose (FpIn);
+
+ //
+ // Open the reset vector data file
+ //
+ if ((FpIn = fopen (argv[2], "rb")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[2]);
+ return STATUS_ERROR;
+ }
+ //
+ // Open the output file
+ //
+ if ((FpOut = fopen (argv[3], "w+b")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", argv[3]);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+ //
+ // Copy the input file to the output file
+ //
+ if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {
+ fclose (FpIn);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the reset vector data file
+ //
+ fclose (FpIn);
+
+ //
+ // Fix the destination relative in the jmp instruction
+ // in the reset vector data structure
+ //
+ fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);
+ DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);
+ if (DestRel <= -65536) {
+ Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+
+ if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {
+ Error (NULL, 0, 0, "Failed to write to the output file", NULL);
+ fclose (FpOut);
+ return STATUS_ERROR;
+ }
+ //
+ // Close the output file
+ //
+ fclose (FpOut);
+
+ return STATUS_SUCCESS;
+}
+
+STATUS
+GetEntryPoint (
+ IN FILE *ExeFile,
+ OUT UINT32 *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ Get the address of the entry point of a PE/TE file.
+
+Arguments:
+
+ PeFile - File pointer to the specified PE/TE file.
+ EntryPoint - Buffer for the address of the entry point to be returned.
+
+Returns:
+ STATUS_SUCCESS - Function completed successfully.
+ STATUS_ERROR - Error occured.
+
+--*/
+// GC_TODO: ExeFile - add argument and description to function comment
+{
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_NT_HEADERS32 NtHeader;
+ EFI_TE_IMAGE_HEADER TeHeader;
+
+ //
+ // Check if it is a TE file
+ //
+ fseek (ExeFile, 0, SEEK_SET);
+ //
+ // Attempt to read the TE header
+ //
+ if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {
+ if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+ if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
+ return STATUS_ERROR;
+ }
+
+ *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;
+ return STATUS_SUCCESS;
+ }
+ }
+ //
+ // Check if it is a PE file
+ //
+ fseek (ExeFile, 0, SEEK_SET);
+ //
+ // Attempt to read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {
+ goto InvalidFile;
+ }
+ //
+ // Check the magic number
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ goto InvalidFile;
+ }
+ //
+ // Position into the file and read the NT PE header
+ //
+ fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);
+ if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {
+ goto InvalidFile;
+ }
+ //
+ // Check the PE signature in the header
+ //
+ if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ goto InvalidFile;
+ }
+ //
+ // Make sure the PE file is PE32 for IA32
+ //
+ if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||
+ NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
+ ) {
+ Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Get the entry point from the optional header
+ //
+ *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;
+ return STATUS_SUCCESS;
+
+InvalidFile:
+ Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);
+ return STATUS_ERROR;
+}
+
+STATUS
+CopyFile (
+ FILE *FpIn,
+ FILE *FpOut
+ )
+/*++
+
+Routine Description:
+
+ Copy file.
+
+Arguments:
+
+ FpIn - File pointer to the source file.
+ FpOut - File pointer to the destination file.
+
+Returns:
+ STATUS_SUCCESS - Function completed successfully.
+ STATUS_ERROR - Error occured.
+
+--*/
+{
+ INTN FileSize;
+
+ INTN Offset;
+
+ INTN Length;
+ UINT8 Buffer[BUF_SIZE];
+
+ fseek (FpIn, 0, SEEK_END);
+ FileSize = ftell (FpIn);
+
+ fseek (FpIn, 0, SEEK_SET);
+ fseek (FpOut, 0, SEEK_SET);
+
+ Offset = 0;
+ while (Offset < FileSize) {
+ Length = sizeof (Buffer);
+ if (FileSize - Offset < Length) {
+ Length = FileSize - Offset;
+ }
+
+ if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {
+ Error (NULL, 0, 0, "Copy file error", NULL);
+ return STATUS_ERROR;
+ }
+
+ Offset += Length;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/Tools/Source/TianoTools/SecFixup/SecFixup.h b/Tools/Source/TianoTools/SecFixup/SecFixup.h
new file mode 100644
index 0000000..5571dc3
--- /dev/null
+++ b/Tools/Source/TianoTools/SecFixup/SecFixup.h
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ SecFixup.h
+
+Abstract:
+
+ Definitions for the SecFixup utility.
+
+--*/
+
+#ifndef _SEC_FIXUP_H
+#define _SEC_FIXUP_H
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "SecFixup"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// The maximum number of arguments accepted from the command line.
+//
+#define MAX_ARGS 4
+
+#define DEST_REL_OFFSET 13
+#define BUF_SIZE (8 * 1024)
+
+//
+// The function that displays general utility information
+//
+VOID
+PrintUtilityInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that displays the utility usage message.
+//
+VOID
+PrintUsage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that gets the entry point of a PE/TE file.
+//
+STATUS
+GetEntryPoint (
+ IN FILE *ExeFile,
+ OUT UINT32 *EntryPoint
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ ExeFile - GC_TODO: add argument description
+ EntryPoint - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+//
+// The function that copies a file.
+//
+STATUS
+CopyFile (
+ FILE *FpIn,
+ FILE *FpOut
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ FpIn - GC_TODO: add argument description
+ FpOut - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/Tools/Source/TianoTools/SplitFile/Makefile b/Tools/Source/TianoTools/SplitFile/Makefile
new file mode 100644
index 0000000..3cd45f9
--- /dev/null
+++ b/Tools/Source/TianoTools/SplitFile/Makefile
@@ -0,0 +1,70 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Define some macros we use here. Should get rid of them someday and
+# get rid of the extra level of indirection.
+#
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)
+
+#
+# Common information
+#
+
+INC=$(INC)
+
+#
+# Target specific information
+#
+
+TARGET_NAME=SplitFile
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\SplitFile.c"
+TARGET_EXE_INCLUDE =
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/SplitFile/SplitFile.c b/Tools/Source/TianoTools/SplitFile/SplitFile.c
new file mode 100644
index 0000000..b1af1a8
--- /dev/null
+++ b/Tools/Source/TianoTools/SplitFile/SplitFile.c
@@ -0,0 +1,131 @@
+/*
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+*/
+
+// GC_TODO: fix comment to start with /*++
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+
+void
+helpmsg (
+ void
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ printf (
+ "SplitFile Filename Offset\n"" Filename = Input file to split\n"" Offset = offset at which to split file\n"
+ "\n\n""SplitFile will break a file in two pieces at the requested offset\n"
+ " outputting Filename1 and Filename2\n"
+ );
+}
+
+int
+main (
+ int argc,
+ char*argv[]
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ argc - GC_TODO: add argument description
+ ] - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ FILE *In;
+
+ FILE *Out1;
+
+ FILE *Out2;
+ char OutName1[512];
+ char OutName2[512];
+ unsigned long Index;
+ unsigned long splitpoint;
+ char CharC;
+
+ if (argc != 3) {
+ helpmsg ();
+ return -1;
+ }
+
+ In = fopen (argv[1], "rb");
+ if (In == NULL) {
+ printf ("Unable to open file \"%s\"\n", argv[1]);
+ return -1;
+ }
+
+ strncpy (OutName1, argv[1], 510);
+ strncpy (OutName2, argv[1], 510);
+ strcat (OutName1, "1");
+ strcat (OutName2, "2");
+
+ Out1 = fopen (OutName1, "wb");
+ if (Out1 == NULL) {
+ printf ("Unable to open file \"%s\"\n", OutName1);
+ return -1;
+ }
+
+ Out2 = fopen (OutName2, "wb");
+ if (Out2 == NULL) {
+ printf ("Unable to open file \"%s\"\n", OutName2);
+ return -1;
+ }
+
+ splitpoint = atoi (argv[2]);
+
+ for (Index = 0; Index < splitpoint; Index++) {
+ CharC = (char) fgetc (In);
+ if (feof (In)) {
+ break;
+ }
+
+ fputc (CharC, Out1);
+ }
+
+ for (;;) {
+ CharC = (char) fgetc (In);
+ if (feof (In)) {
+ break;
+ }
+
+ fputc (CharC, Out2);
+ }
+
+ fclose (In);
+ fclose (Out1);
+ fclose (Out2);
+
+ return 0;
+}
diff --git a/Tools/Source/TianoTools/Strip/Makefile b/Tools/Source/TianoTools/Strip/Makefile
new file mode 100644
index 0000000..f47a68f
--- /dev/null
+++ b/Tools/Source/TianoTools/Strip/Makefile
@@ -0,0 +1,70 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation. All rights reserved.
+#
+# This software and associated documentation (if any) is furnished under
+# a license and may only be used or copied in accordance with the terms
+# of the license. Except as permitted by such license, no part of this
+# software or documentation may be reproduced, stored in a retrieval
+# system, or transmitted in any form or by any means without the express
+# written consent of Intel Corporation.
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Define some macros we use here. Should get rid of them someday and
+# get rid of the extra level of indirection.
+#
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)
+
+#
+# Common information
+#
+
+INC=$(INC)
+
+#
+# Target specific information
+#
+
+TARGET_NAME=Strip
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\Strip.c"
+TARGET_EXE_INCLUDE =
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
diff --git a/Tools/Source/TianoTools/Strip/Strip.c b/Tools/Source/TianoTools/Strip/Strip.c
new file mode 100644
index 0000000..3fd6ad7
--- /dev/null
+++ b/Tools/Source/TianoTools/Strip/Strip.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ Strip.c
+
+Abstract:
+
+ Quick Exe2Bin equivalent.
+
+--*/
+
+#include <stdio.h>
+#include <memory.h>
+#include <string.h>
+#include <malloc.h>
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Converts executable files to binary files.
+
+Arguments:
+
+ argc - Number of command line arguments
+ argv[] - Array of pointers to the command line arguments
+
+Returns:
+
+ Zero - Function completed successfully.
+ Non-zero - Function exited with errors.
+
+--*/
+{
+ FILE *InFile;
+ FILE *OutFile;
+ int Index;
+ int FileSize;
+ char *Buffer;
+ char *Ptrx;
+
+ if (argc < 3) {
+ printf ("Need more args, such as file name to convert and output name\n");
+ return -1;
+ }
+
+ InFile = fopen (argv[1], "rb");
+ OutFile = fopen (argv[2], "wb");
+
+ if (!InFile) {
+ printf ("no file, exit\n");
+ return -1;
+ }
+
+ if (OutFile == NULL) {
+ printf ("Unable to open output file.\n");
+ return -1;
+ }
+
+ fseek (InFile, 0, SEEK_END);
+ FileSize = ftell (InFile);
+
+ if (FileSize < 0x200) {
+ printf ("%d is not a legal size, exit\n", FileSize);
+ return -1;
+ }
+
+ fseek (InFile, 0, SEEK_SET);
+
+ Buffer = malloc (FileSize);
+ if (Buffer == NULL) {
+ printf ("Error: Out of resources.\n");
+ return -1;
+ }
+
+ fread (Buffer, 1, FileSize, InFile);
+
+ Ptrx = Buffer + 0x200;
+
+ Index = FileSize - 0x200;
+
+ fwrite (Ptrx, Index, 1, OutFile);
+
+ fclose (InFile);
+ fclose (OutFile);
+ free (Buffer);
+
+ return 0;
+}
diff --git a/Tools/Source/TianoTools/ZeroDebugData/Makefile b/Tools/Source/TianoTools/ZeroDebugData/Makefile
new file mode 100644
index 0000000..c20fd85
--- /dev/null
+++ b/Tools/Source/TianoTools/ZeroDebugData/Makefile
@@ -0,0 +1,63 @@
+#/*++
+#
+# Copyright (c) 2001 Intel Corporation
+#
+# Module Name: makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE PlatformTools.env
+
+#
+# Define some macros we use here. Should get rid of them someday and
+# get rid of the extra level of indirection.
+#
+COMMON_SOURCE = $(EDK_TOOLS_COMMON)
+
+#
+# Common information
+#
+
+INC=$(INC)
+
+#
+# Target specific information
+#
+
+TARGET_NAME=ZeroDebugData
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)
+
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\ZeroDebugData.c"
+TARGET_EXE_INCLUDE =
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS)
+
+clean:
+ @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).*
diff --git a/Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c b/Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c
new file mode 100644
index 0000000..2f20039
--- /dev/null
+++ b/Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c
@@ -0,0 +1,390 @@
+/*++
+
+Copyright (c) 2001 - 2002 Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+ ZeroDebugData.c
+
+Abstract:
+ Zero the Debug Data Fields of Portable Executable (PE) format file.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+void
+PrintUsage (
+ void
+ )
+/*++
+Routine Description:
+ print usage of ZeroDebugData command
+
+Arguments:
+ None
+
+Returns:
+ None
+--*/
+// GC_TODO: void - add argument and description to function comment
+{
+ //
+ // print usage of command
+ //
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");
+}
+
+int
+ReadFromFile (
+ FILE *fp,
+ long offset,
+ void *buffer,
+ int size
+ )
+/*++
+Routine Description:
+ read data from a specified location of file
+
+Arguments:
+ fp - file pointer
+ offset - number of bytes from beginning of file
+ buffer - buffer used to store data
+ size - size of buffer
+
+Returns:
+ = 0 - Success
+ = -1 - Failed
+--*/
+{
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, offset, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ return -1;
+ }
+ //
+ // read data from the file
+ //
+ if (fread (buffer, size, 1, fp) != 1) {
+ printf ("Error: Cannot read data from the file.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+ZeroDebugData (
+ FILE *fp,
+ FILE *fpData
+ )
+/*++
+
+Routine Description:
+
+ Zero the debug data fields of the file
+
+Arguments:
+
+ fp - file pointer
+ fpData - pointer to output file that ZeroDebugData progress is written to
+
+Returns:
+
+ = 0 - Success
+ = -1 - Failed
+
+--*/
+{
+ unsigned char header[4];
+ unsigned long offset;
+ unsigned long NumberOfRvaAndSizes;
+ unsigned int nvalue;
+ unsigned long lvalue;
+ unsigned long Size;
+ unsigned long Pointer;
+ unsigned char *Buffer;
+ unsigned long Index;
+
+ //
+ // read the header of file
+ //
+ if (ReadFromFile (fp, 0, header, 2) != 0) {
+ printf ("Error: open image file\n");
+ return -1;
+ }
+ //
+ // "MZ" -- the header of image file (PE)
+ //
+ if (strncmp ((char *) header, "MZ", 2) != 0) {
+ printf ("Error: Invalid Image file.\n");
+ return -1;
+ }
+ //
+ // At location 0x3C, the stub has the file offset to the
+ // PE signature.
+ //
+ if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {
+ return -1;
+ }
+ //
+ // read the header of optional
+ //
+ if (ReadFromFile (fp, offset, header, 4) != 0) {
+ return -1;
+ }
+ //
+ // "PE\0\0" -- the signature of optional header
+ //
+ if (strncmp ((char *) header, "PE\0\0", 4) != 0) {
+ printf ("Error: Invalid PE format file.\n");
+ return -1;
+ }
+ //
+ // Add 16 to skip COFF file header, and get to optional header.
+ //
+ offset += 24;
+
+ //
+ // Check the magic field, 0x10B for PE32 and 0x20B for PE32+
+ //
+ if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {
+ return -1;
+ }
+ //
+ // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.
+ // Else it is 108.
+ //
+ switch (nvalue & 0xFFFF) {
+ case 0x10B:
+ offset += 92;
+ printf ("Info: Image is PE32. ");
+ break;
+
+ case 0x20B:
+ offset += 108;
+ printf ("Info: Image is PE32+. ");
+ break;
+
+ default:
+ printf ("Error: Magic value is unknown.\n");
+ return -1;
+ }
+ //
+ // get the value of NumberOfRvaAndSizes
+ //
+ if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {
+ printf ("Error: read NumberOfRvaAndSizes error.\n");
+ return -1;
+ }
+ //
+ // printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes);
+ //
+ //
+ // Finding Debug Table, offset of Debug Table
+ // is 4 + 6 * 8 = 52.
+ //
+ if (NumberOfRvaAndSizes >= 7) {
+ if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {
+ return -1;
+ }
+ //
+ // Read the SizeOfData(16) and PointerToRawData(24)
+ //
+ if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) {
+ printf ("error: Size = %d\n", Size);
+ return -1;
+ }
+
+ printf ("Debug data: size = %xh, ", Size);
+ fprintf (fpData, "Debug data: size = %xh, ", Size);
+
+ if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) {
+ printf ("error: LoadOffset = %xh\n", Pointer);
+ return -1;
+ }
+ //
+ // printf ("LoadOffset = %xh, ", Pointer);
+ //
+ fprintf (fpData, "LoadOffset = %xh, ", Pointer);
+
+ if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) {
+ printf ("error: FileOffset = %xh\n", Pointer);
+ return -1;
+ }
+
+ printf ("FileOffset = %xh, ", Pointer);
+ fprintf (fpData, "FileOffset = %xh, \n", Pointer);
+
+ if ((lvalue != 0) && (Pointer != 0)) {
+ //
+ // prepare buffer
+ //
+ Buffer = malloc (Size + 1);
+ if (Buffer == NULL) {
+ printf ("Error: Cannot allocate memory.\n");
+ return -1;
+ }
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // read data from PE file
+ //
+ if (fread (Buffer, Size, 1, fp) != 1) {
+ printf ("Error: Cannot read data from the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // write to data file
+ //
+ for (Index = 0; Index < Size;) {
+ fprintf (fpData, "%02x ", Buffer[Index]);
+
+ Index++;
+ if (Index % 8 == 0) {
+ fprintf (fpData, "\n");
+ }
+ }
+
+ fprintf (fpData, "\n");
+
+ //
+ // zero buffer and write back to PE file
+ //
+ if (fseek (fp, Pointer, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ memset (Buffer, 0, Size);
+ if (fwrite (Buffer, Size, 1, fp) != 1) {
+ perror ("Error: Cannot write zero to the file.\n");
+ free (Buffer);
+ return -1;
+ }
+ //
+ // set file pointer to the specified location of file
+ //
+ if (fseek (fp, lvalue + 4, SEEK_SET) != 0) {
+ printf ("Error: Cannot move the current location of the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ if (fwrite (Buffer, 4, 1, fp) != 1) {
+ perror ("Error: Cannot write zero to the file.\n");
+ free (Buffer);
+ return -1;
+ }
+
+ free (Buffer);
+ }
+ }
+
+ return 0;
+}
+
+int
+main (
+ int argc,
+ char *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Prints the zero debug data of the PE file to the DebugData file.
+ Executes the ZeroDebugData function.
+
+Arguments:
+
+ argc - Standard C argument, number of command line arguments.
+ argv[] - Standard C argument, array of pointers to the input files,
+ such as the PE and DebugData files.
+
+Returns:
+
+ zero - success
+ nonzero - failure
+
+--*/
+{
+ FILE *fp;
+ FILE *fpData;
+ char DataFile[1024] = "";
+
+ //
+ // check the number of parameters
+ //
+ if (argc < 2) {
+ printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");
+ return -1;
+ }
+ //
+ // open the DebugData file, if not exists, return
+ //
+ if (argc >= 3) {
+ strcpy (DataFile, argv[2]);
+ } else {
+ strcpy (DataFile, "DebugData.dat");
+ }
+
+ fpData = fopen (DataFile, "a+");
+ if (fpData == NULL) {
+ fpData = fopen (DataFile, "w");
+ if (fpData == NULL) {
+ printf ("Error: Cannot open the data file!\n");
+ return -1;
+ }
+ }
+ //
+ // open the PE file
+ //
+ fp = fopen (argv[1], "r+b");
+ if (fp == NULL) {
+ printf ("Error: Cannot open the PE file!\n");
+ return -1;
+ }
+ //
+ // Zero the Debug Data to the PE file
+ //
+ printf ("Zero Debug Data to file %s:\n", argv[1]);
+ fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]);
+ if ((int *) ZeroDebugData (fp, fpData) != 0) {
+ printf ("Error: Zero Debug Data PE file\n");
+ fclose (fp);
+ return -1;
+ }
+
+ printf (" success\n");
+
+ //
+ // close the PE file
+ //
+ fflush (fpData);
+ fflush (fp);
+ fclose (fpData);
+ fclose (fp);
+
+ return 0;
+}