]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Adding Additional Tools that are needed for Platform Image creation.
authorlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 19 May 2006 02:38:56 +0000 (02:38 +0000)
committerlhauch <lhauch@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 19 May 2006 02:38:56 +0000 (02:38 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@198 6f19259b-4bc3-4df7-8a09-765794883524

42 files changed:
Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c [new file with mode: 0644]
Tools/Source/TianoTools/CreateMtFile/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c [new file with mode: 0644]
Tools/Source/TianoTools/EfiCompress/makefile [new file with mode: 0644]
Tools/Source/TianoTools/EfiRom/EfiRom.c [new file with mode: 0644]
Tools/Source/TianoTools/EfiRom/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/FlashDefFile.c [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/FlashDefFile.h [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/FlashMap.c [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/Microcode.c [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/Microcode.h [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/Symbols.c [new file with mode: 0644]
Tools/Source/TianoTools/FlashMap/Symbols.h [new file with mode: 0644]
Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c [new file with mode: 0644]
Tools/Source/TianoTools/GenAcpiTable/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c [new file with mode: 0644]
Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c [new file with mode: 0644]
Tools/Source/TianoTools/GenCapsuleHdr/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/GenFdImage.h [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c [new file with mode: 0644]
Tools/Source/TianoTools/GenFdImage/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/GenTEImage/GenTEImage.c [new file with mode: 0644]
Tools/Source/TianoTools/GenTEImage/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c [new file with mode: 0644]
Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h [new file with mode: 0644]
Tools/Source/TianoTools/PeiRebase/makefile [new file with mode: 0644]
Tools/Source/TianoTools/SecApResetVectorFixup/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c [new file with mode: 0644]
Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h [new file with mode: 0644]
Tools/Source/TianoTools/SecFixup/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/SecFixup/SecFixup.c [new file with mode: 0644]
Tools/Source/TianoTools/SecFixup/SecFixup.h [new file with mode: 0644]
Tools/Source/TianoTools/SplitFile/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/SplitFile/SplitFile.c [new file with mode: 0644]
Tools/Source/TianoTools/Strip/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/Strip/Strip.c [new file with mode: 0644]
Tools/Source/TianoTools/ZeroDebugData/Makefile [new file with mode: 0644]
Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c [new file with mode: 0644]

diff --git a/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c b/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c
new file mode 100644 (file)
index 0000000..e769b88
--- /dev/null
@@ -0,0 +1,246 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  CreateMtFile.c\r
+\r
+Abstract:\r
+\r
+  Simple utility to create a pad file containing fixed data.\r
+  \r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include "TianoCommon.h"\r
+\r
+#define PROGRAM_NAME  "CreateMtFile"\r
+\r
+typedef struct {\r
+  INT8    *OutFileName;\r
+  INT8    ByteValue;\r
+  UINT32  FileSize;\r
+} OPTIONS;\r
+\r
+static\r
+EFI_STATUS\r
+ProcessArgs (\r
+  IN INT32          Argc,\r
+  IN INT8           *Argv[],\r
+  IN OUT OPTIONS    *Options\r
+  );\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+int\r
+main (\r
+  IN INT32  Argc,\r
+  IN INT8   *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Main entry point for this utility.\r
+\r
+Arguments:\r
+\r
+  Standard C entry point args Argc and Argv\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS if good to go\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+// GC_TODO:    EFI_DEVICE_ERROR - add return value to function comment\r
+{\r
+  FILE    *OutFptr;\r
+  OPTIONS Options;\r
+\r
+  //\r
+  // Process the command-line arguments.\r
+  //\r
+  if (ProcessArgs (Argc, Argv, &Options) != EFI_SUCCESS) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Open the output file\r
+  //\r
+  if ((OutFptr = fopen (Options.OutFileName, "wb")) == NULL) {\r
+    fprintf (\r
+      stdout,\r
+      PROGRAM_NAME " ERROR: Could not open output file '%s' for writing\n",\r
+      Options.OutFileName\r
+      );\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+  //\r
+  // Write the pad bytes. Do it the slow way (one at a time) for now.\r
+  //\r
+  while (Options.FileSize > 0) {\r
+    if (fwrite (&Options.ByteValue, 1, 1, OutFptr) != 1) {\r
+      fclose (OutFptr);\r
+      fprintf (stdout, PROGRAM_NAME " ERROR: Failed to write to output file\n");\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    Options.FileSize--;\r
+  }\r
+  //\r
+  // Close the file\r
+  //\r
+  fclose (OutFptr);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+static\r
+EFI_STATUS\r
+ProcessArgs (\r
+  IN INT32          Argc,\r
+  IN INT8           *Argv[],\r
+  IN OUT OPTIONS    *Options\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Process the command line arguments.\r
+\r
+Arguments:\r
+\r
+  Argc    - argument count as passed in to the entry point function\r
+  Argv    - array of arguments as passed in to the entry point function\r
+  Options - stucture of where to put the values of the parsed arguments\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS if everything looks good\r
+  EFI_INVALID_PARAMETER otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  UINT32  Multiplier;\r
+\r
+  //\r
+  // Clear the options\r
+  //\r
+  memset ((char *) Options, 0, sizeof (OPTIONS));\r
+\r
+  //\r
+  // Skip program name\r
+  //\r
+  Argv++;\r
+  Argc--;\r
+  if (Argc < 2) {\r
+    Usage ();\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // If first arg is dash-option, then print usage.\r
+  //\r
+  if (Argv[0][0] == '-') {\r
+    Usage ();\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // First arg is file name\r
+  //\r
+  Options->OutFileName = Argv[0];\r
+  Argc--;\r
+  Argv++;\r
+\r
+  //\r
+  // Second arg is file size. Allow 0x1000, 0x100K, 1024, 1K\r
+  //\r
+  Multiplier = 1;\r
+  if ((Argv[0][strlen (Argv[0]) - 1] == 'k') || (Argv[0][strlen (Argv[0]) - 1] == 'K')) {\r
+    Multiplier = 1024;\r
+  }\r
+  //\r
+  // Look for 0x prefix on file size\r
+  //\r
+  if ((Argv[0][0] == '0') && ((Argv[0][1] == 'x') || (Argv[0][1] == 'X'))) {\r
+    if (sscanf (Argv[0], "%x", &Options->FileSize) != 1) {\r
+      fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);\r
+      Usage ();\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    //\r
+    // Otherwise must be a decimal number\r
+    //\r
+  } else {\r
+    if (sscanf (Argv[0], "%d", &Options->FileSize) != 1) {\r
+      fprintf (stdout, PROGRAM_NAME " ERROR: Invalid file size '%s'\n", Argv[0]);\r
+      Usage ();\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  }\r
+\r
+  Options->FileSize *= Multiplier;\r
+  //\r
+  // Assume byte value of 0xff\r
+  //\r
+  Options->ByteValue = (INT8) (UINT8) 0xFF;\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// Print utility usage info\r
+//\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  UINT32            Index;\r
+  static const INT8 *Text[] = {\r
+    " ",\r
+    "Usage:  "PROGRAM_NAME " OutFileName FileSize",\r
+    "  where:",\r
+    "    OutFileName is the name of the output file to generate",\r
+    "    FileSize is the size of the file to create",\r
+    "  Examples:",\r
+    "    "PROGRAM_NAME " OutFile.bin 32K",\r
+    "    "PROGRAM_NAME " OutFile.bin 0x1000",\r
+    " ",\r
+    NULL\r
+  };\r
+\r
+  for (Index = 0; Text[Index] != NULL; Index++) {\r
+    fprintf (stdout, "%s\n", Text[Index]);\r
+  }\r
+}\r
diff --git a/Tools/Source/TianoTools/CreateMtFile/Makefile b/Tools/Source/TianoTools/CreateMtFile/Makefile
new file mode 100644 (file)
index 0000000..d6574fc
--- /dev/null
@@ -0,0 +1,67 @@
+#/*++\r
+#  \r
+#  Copyright (c)  1999 - 2001 Intel Corporation. All rights reserved\r
+#  This software and associated documentation (if any) is furnished\r
+#  under a license and may only be used or copied in accordance\r
+#  with the terms of the license. Except as permitted by such\r
+#  license, no part of this software or documentation may be\r
+#  reproduced, stored in a retrieval system, or transmitted in any\r
+#  form or by any means without the express written consent of\r
+#  Intel Corporation.\r
+#  \r
+#  \r
+#  Module Name:\r
+#  \r
+#    Makefile\r
+#  \r
+#  Abstract:\r
+#  \r
+#    makefile for building the CreateMtFile utility.\r
+#  \r
+#  Revision History\r
+#  \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = CreateMtFile\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj\r
+            \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\CreateMtFile.obj : $(TARGET_SRC_DIR)\CreateMtFile.c\r
+  $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\CreateMtFile.c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c b/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c
new file mode 100644 (file)
index 0000000..db3e184
--- /dev/null
@@ -0,0 +1,163 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  EfiCompressMain.c\r
+\r
+Abstract:\r
+\r
+  The main function for the compression utility.\r
+  \r
+--*/\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <stdarg.h>\r
+#include <stdio.h>\r
+#include "TianoCommon.h"\r
+#include "EfiCompress.h"\r
+\r
+int\r
+main (\r
+  INT32 argc,\r
+  CHAR8 *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Compresses the input files\r
+\r
+Arguments:\r
+\r
+  argc   - number of arguments passed into the command line.\r
+  argv[] - files to compress and files to output compressed data to.\r
+\r
+Returns:\r
+\r
+  int: 0 for successful execution of the function.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS  Status;\r
+  FILE        *infile;\r
+  FILE        *outfile;\r
+  UINT32      SrcSize;\r
+  UINT32      DstSize;\r
+  UINT8       *SrcBuffer;\r
+  UINT8       *DstBuffer;\r
+  UINT8       Buffer[8];\r
+\r
+  //\r
+  //  Added for makefile debug - KCE\r
+  //\r
+  INT32       arg_counter;\r
+  printf ("\n\n");\r
+  for (arg_counter = 0; arg_counter < argc; arg_counter++) {\r
+    printf ("%s ", argv[arg_counter]);\r
+  }\r
+\r
+  printf ("\n\n");\r
+\r
+  SrcBuffer             = DstBuffer = NULL;\r
+\r
+  infile                = outfile = NULL;\r
+\r
+  if (argc != 3) {\r
+    printf ("Usage: EFICOMPRESS <infile> <outfile>\n");\r
+    goto Done;\r
+  }\r
+\r
+  if ((outfile = fopen (argv[2], "wb")) == NULL) {\r
+    printf ("Can't open output file\n");\r
+    goto Done;\r
+  }\r
+\r
+  if ((infile = fopen (argv[1], "rb")) == NULL) {\r
+    printf ("Can't open input file\n");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Get the size of source file\r
+  //\r
+  SrcSize = 0;\r
+  while (fread (Buffer, 1, 1, infile)) {\r
+    SrcSize++;\r
+\r
+  }\r
+  //\r
+  // Read in the source data\r
+  //\r
+  if ((SrcBuffer = malloc (SrcSize)) == NULL) {\r
+    printf ("Can't allocate memory\n");\r
+    goto Done;\r
+  }\r
+\r
+  rewind (infile);\r
+  if (fread (SrcBuffer, 1, SrcSize, infile) != SrcSize) {\r
+    printf ("Can't read from source\n");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Get destination data size and do the compression\r
+  //\r
+  DstSize = 0;\r
+  Status  = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+  if (Status == EFI_BUFFER_TOO_SMALL) {\r
+    if ((DstBuffer = malloc (DstSize)) == NULL) {\r
+      printf ("Can't allocate memory\n");\r
+      goto Done;\r
+    }\r
+\r
+    Status = Compress (SrcBuffer, SrcSize, DstBuffer, &DstSize);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    printf ("Compress Error\n");\r
+    goto Done;\r
+  }\r
+\r
+  printf ("\nOrig Size = %ld\n", SrcSize);\r
+  printf ("Comp Size = %ld\n", DstSize);\r
+\r
+  if (DstBuffer == NULL) {\r
+    printf ("No destination to write to.\n");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Write out the result\r
+  //\r
+  if (fwrite (DstBuffer, 1, DstSize, outfile) != DstSize) {\r
+    printf ("Can't write to destination file\n");\r
+  }\r
+\r
+Done:\r
+  if (SrcBuffer) {\r
+    free (SrcBuffer);\r
+  }\r
+\r
+  if (DstBuffer) {\r
+    free (DstBuffer);\r
+  }\r
+\r
+  if (infile) {\r
+    fclose (infile);\r
+  }\r
+\r
+  if (outfile) {\r
+    fclose (outfile);\r
+  }\r
+\r
+  return 0;\r
+}\r
diff --git a/Tools/Source/TianoTools/EfiCompress/makefile b/Tools/Source/TianoTools/EfiCompress/makefile
new file mode 100644 (file)
index 0000000..b20a219
--- /dev/null
@@ -0,0 +1,77 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE      = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# BUGBUG: Override standard flags, cannot be built without warnings.\r
+#\r
+\r
+C_FLAGS=/nologo /W4 /GX /Zi /Od /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /c \r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=EfiCompress\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\EfiCompressMain.c"\r
+TARGET_EXE_INCLUDE = "$(COMMON_SOURCE)\EfiCompress.h"\r
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib"\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_LIB)  $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* > NUL\r
diff --git a/Tools/Source/TianoTools/EfiRom/EfiRom.c b/Tools/Source/TianoTools/EfiRom/EfiRom.c
new file mode 100644 (file)
index 0000000..fc168ed
--- /dev/null
@@ -0,0 +1,1543 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  EfiRom.c\r
+  \r
+Abstract:\r
+\r
+  Utility program to create an EFI option ROM image from binary and \r
+  EFI PE32 files.\r
+\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+//\r
+// Includes for EFI 1.1 build\r
+//\r
+// #include "Tiano.h"        // required defines for Compress.h\r
+// #include "EfiImage.h"   // for PE32 structure definitions\r
+// #include "Compress.h"   // for compression function\r
+// Includes for Tiano build\r
+//\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiCompress.h"\r
+\r
+//\r
+// END include differences\r
+//\r
+#include "Pci22.h"  // for option ROM header structures\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_VERSION "v2.5"\r
+\r
+//\r
+// Define some status return values\r
+//\r
+#define STATUS_SUCCESS  0\r
+#define STATUS_WARNING  1\r
+#define STATUS_ERROR    2\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH                  200\r
+\r
+#define DEFAULT_OUTPUT_EXTENSION  ".rom"\r
+\r
+//\r
+// Max size for an option ROM image\r
+//\r
+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16)  // 16MB\r
+//\r
+// Values for the indicator field in the PCI data structure\r
+//\r
+#define INDICATOR_LAST  0x80  // last file in series of files\r
+//\r
+// Masks for the FILE_LIST.FileFlags field\r
+//\r
+#define FILE_FLAG_BINARY    0x01\r
+#define FILE_FLAG_EFI       0x02\r
+#define FILE_FLAG_COMPRESS  0x04\r
+\r
+//\r
+// Use this linked list structure to keep track of all the filenames\r
+// specified on the command line.\r
+//\r
+typedef struct _FILE_LIST {\r
+  struct _FILE_LIST *Next;\r
+  INT8              *FileName;\r
+  UINT32            FileFlags;\r
+  UINT32            ClassCode;\r
+  UINT16            CodeRevision;\r
+} FILE_LIST;\r
+\r
+//\r
+// Use this to track our command-line options\r
+//\r
+typedef struct {\r
+  INT8      OutFileName[MAX_PATH];\r
+  INT8      NoLast;\r
+  INT8      Verbose;\r
+  INT8      DumpOption;\r
+  UINT8     DevIdValid;\r
+  UINT8     VendIdValid;\r
+  UINT16    VendId;\r
+  UINT16    DevId;\r
+  FILE_LIST *FileList;\r
+} OPTIONS;\r
+\r
+//\r
+// Make a global structure to keep track of command-line options\r
+//\r
+static OPTIONS  mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+  UINT16  Value;\r
+  char    *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP  mMachineTypes[] = {\r
+  EFI_IMAGE_MACHINE_IA32,\r
+  "IA32",\r
+  EFI_IMAGE_MACHINE_IA64,\r
+  "IA64",\r
+  EFI_IMAGE_MACHINE_EBC,\r
+  "EBC",\r
+  0,\r
+  NULL\r
+};\r
+\r
+static STRING_LOOKUP  mSubsystemTypes[] = {\r
+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+  "EFI application",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+  "EFI boot service driver",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+  "EFI runtime driver",\r
+  0,\r
+  NULL\r
+};\r
+//\r
+//  Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+  int       Argc,\r
+  char      *Argv[],\r
+  OPTIONS   *Options\r
+  );\r
+\r
+static\r
+int\r
+CheckPE32File (\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  );\r
+\r
+static\r
+int\r
+ProcessEfiFile (\r
+  FILE      *OutFptr,\r
+  FILE_LIST *InFile,\r
+  UINT16    VendId,\r
+  UINT16    DevId,\r
+  UINT32    *Size\r
+  );\r
+\r
+static\r
+int\r
+ProcessBinFile (\r
+  FILE      *OutFptr,\r
+  FILE_LIST *InFile,\r
+  UINT32    *Size\r
+  );\r
+\r
+static\r
+void\r
+DumpImage (\r
+  FILE_LIST *InFile\r
+  );\r
+\r
+char                  *\r
+GetMachineTypeStr (\r
+  UINT16    MachineType\r
+  );\r
+\r
+static\r
+char                  *\r
+GetSubsystemTypeStr (\r
+  UINT16  SubsystemType\r
+  );\r
+\r
+main (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given an EFI image filename, create a ROM-able image by creating an option \r
+  ROM header and PCI data structure, filling them in, and then writing the\r
+  option ROM header + PCI data structure + EFI image out to the output file.\r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+\r
+  Argv            - standard C main() argument list\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  INT8      *Ext;\r
+  FILE      *FptrOut;\r
+  UINT32    Status;\r
+  FILE_LIST *FList;\r
+  UINT32    TotalSize;\r
+  UINT32    Size;\r
+\r
+  Status  = STATUS_SUCCESS;\r
+  FptrOut = NULL;\r
+\r
+  //\r
+  // Parse the command line arguments\r
+  //\r
+  if (ParseCommandLine (Argc, Argv, &mOptions)) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If dumping an image, then do that and quit\r
+  //\r
+  if (mOptions.DumpOption) {\r
+    DumpImage (mOptions.FileList);\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Determine the output filename. Either what they specified on\r
+  // the command line, or the first input filename with a different extension.\r
+  //\r
+  if (!mOptions.OutFileName[0]) {\r
+    strcpy (mOptions.OutFileName, mOptions.FileList->FileName);\r
+    //\r
+    // Find the last . on the line and replace the filename extension with\r
+    // the default\r
+    //\r
+    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
+         Ext--\r
+        )\r
+      ;\r
+    //\r
+    // If dot here, then insert extension here, otherwise append\r
+    //\r
+    if (*Ext != '.') {\r
+      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+    }\r
+\r
+    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+  }\r
+  //\r
+  // Make sure we don't have the same filename for input and output files\r
+  //\r
+  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
+    if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {\r
+      Status = STATUS_ERROR;\r
+      fprintf (\r
+        stdout,\r
+        "ERROR: Input and output file names must be different - %s = %s\n",\r
+        FList->FileName,\r
+        mOptions.OutFileName\r
+        );\r
+      goto BailOut;\r
+    }\r
+  }\r
+  //\r
+  // Now open our output file\r
+  //\r
+  if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {\r
+    fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Process all our files\r
+  //\r
+  TotalSize = 0;\r
+  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
+    Size = 0;\r
+    if (FList->FileFlags & FILE_FLAG_EFI) {\r
+      if (mOptions.Verbose) {\r
+        fprintf (stdout, "Processing EFI file    %s\n", FList->FileName);\r
+      }\r
+\r
+      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);\r
+    } else if (FList->FileFlags & FILE_FLAG_BINARY) {\r
+      if (mOptions.Verbose) {\r
+        fprintf (stdout, "Processing binary file %s\n", FList->FileName);\r
+      }\r
+\r
+      Status = ProcessBinFile (FptrOut, FList, &Size);\r
+    } else {\r
+      fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);\r
+      Status = STATUS_ERROR;\r
+    }\r
+\r
+    if (mOptions.Verbose) {\r
+      fprintf (stdout, "  Output size = 0x%X\n", Size);\r
+    }\r
+\r
+    if (Status != STATUS_SUCCESS) {\r
+      break;\r
+    }\r
+\r
+    TotalSize += Size;\r
+  }\r
+  //\r
+  // Check total size\r
+  //\r
+  if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+    fprintf (\r
+      stdout,\r
+      "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",\r
+      MAX_OPTION_ROM_SIZE\r
+      );\r
+    Status = STATUS_ERROR;\r
+  }\r
+\r
+BailOut:\r
+  if (FptrOut != NULL) {\r
+    fclose (FptrOut);\r
+  }\r
+  //\r
+  // Clean up our file list\r
+  //\r
+  while (mOptions.FileList != NULL) {\r
+    FList = mOptions.FileList->Next;\r
+    free (mOptions.FileList);\r
+    mOptions.FileList = FList;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+int\r
+ProcessBinFile (\r
+  FILE      *OutFptr,\r
+  FILE_LIST *InFile,\r
+  UINT32    *Size\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Process a binary input file.\r
+\r
+Arguments:\r
+\r
+  OutFptr     - file pointer to output binary ROM image file we're creating\r
+  InFile      - structure contains information on the binary file to process\r
+  Size        - pointer to where to return the size added to the output file\r
+\r
+Returns:\r
+\r
+  0 - successful\r
+\r
+--*/\r
+{\r
+  FILE                      *InFptr;\r
+  UINT32                    TotalSize;\r
+  UINT32                    FileSize;\r
+  UINT8                     *Buffer;\r
+  UINT32                    Status;\r
+  PCI_EXPANSION_ROM_HEADER  *RomHdr;\r
+  PCI_DATA_STRUCTURE        *PciDs;\r
+  UINT32                    Index;\r
+  UINT8                     ByteCheckSum;\r
+\r
+  Status = STATUS_SUCCESS;\r
+\r
+  //\r
+  // Try to open the input file\r
+  //\r
+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+    fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Seek to the end of the input file and get the file size. Then allocate\r
+  // a buffer to read it in to.\r
+  //\r
+  fseek (InFptr, 0, SEEK_END);\r
+  FileSize = ftell (InFptr);\r
+  if (mOptions.Verbose) {\r
+    fprintf (stdout, "  File size   = 0x%X\n", FileSize);\r
+  }\r
+\r
+  fseek (InFptr, 0, SEEK_SET);\r
+  Buffer = (INT8 *) malloc (FileSize);\r
+  if (Buffer == NULL) {\r
+    fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Total size must be an even multiple of 512 bytes, and can't exceed\r
+  // the option ROM image size.\r
+  //\r
+  TotalSize = FileSize;\r
+  if (TotalSize & 0x1FF) {\r
+    TotalSize = (TotalSize + 0x200) &~0x1ff;\r
+  }\r
+\r
+  if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+    fprintf (\r
+      stdout,\r
+      "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
+      InFile->FileName,\r
+      MAX_OPTION_ROM_SIZE\r
+      );\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Return the size to the caller so they can keep track of the running total.\r
+  //\r
+  *Size = TotalSize;\r
+\r
+  //\r
+  // Crude check to make sure it's a legitimate ROM image\r
+  //\r
+  RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;\r
+  if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
+    fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Make sure the pointer to the PCI data structure is within the size of the image.\r
+  // Then check it for valid signature.\r
+  //\r
+  if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {\r
+    fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);\r
+  if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
+    fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // If this is the last image, then set the LAST bit unless requested not\r
+  // to via the command-line -l argument. Otherwise, make sure you clear it.\r
+  //\r
+  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
+    PciDs->Indicator = INDICATOR_LAST;\r
+  } else {\r
+    PciDs->Indicator = 0;\r
+  }\r
+\r
+  ByteCheckSum = 0;\r
+  for (Index = 0; Index < FileSize - 1; Index++) {\r
+    ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
+  }\r
+\r
+  Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
+  fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);\r
+\r
+  //\r
+  // Now copy the input file contents out to the output file\r
+  //\r
+  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  TotalSize -= FileSize;\r
+  //\r
+  // Pad the rest of the image to make it a multiple of 512 bytes\r
+  //\r
+  while (TotalSize > 0) {\r
+    putc (~0, OutFptr);\r
+    TotalSize--;\r
+  }\r
+\r
+BailOut:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+  //\r
+  // Print the file name if errors occurred\r
+  //\r
+  if (Status != STATUS_SUCCESS) {\r
+    fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+int\r
+ProcessEfiFile (\r
+  FILE      *OutFptr,\r
+  FILE_LIST *InFile,\r
+  UINT16    VendId,\r
+  UINT16    DevId,\r
+  UINT32    *Size\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Process a PE32 EFI file.\r
+\r
+Arguments:\r
+\r
+  OutFptr     - file pointer to output binary ROM image file we're creating\r
+  InFile      - structure contains information on the PE32 file to process\r
+  VendId      - vendor ID as required in the option ROM header\r
+  DevId       - device ID as required in the option ROM header\r
+  Size        - pointer to where to return the size added to the output file\r
+\r
+Returns:\r
+\r
+  0 - successful\r
+\r
+--*/\r
+{\r
+  UINT32                        Status;\r
+  FILE                          *InFptr;\r
+  EFI_PCI_EXPANSION_ROM_HEADER  RomHdr;\r
+  PCI_DATA_STRUCTURE            PciDs;\r
+  UINT32                        FileSize;\r
+  UINT32                        CompressedFileSize;\r
+  UINT8                         *Buffer;\r
+  UINT8                         *CompressedBuffer;\r
+  UINT8                         *TempBufferPtr;\r
+  UINT32                        TotalSize;\r
+  UINT32                        HeaderSize;\r
+  UINT16                        MachineType;\r
+  UINT16                        SubSystem;\r
+  UINT32                        HeaderPadBytes;\r
+\r
+  //\r
+  // Try to open the input file\r
+  //\r
+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+    fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Initialize our buffer pointers to null.\r
+  //\r
+  Buffer            = NULL;\r
+  CompressedBuffer  = NULL;\r
+\r
+  //\r
+  // Double-check the file to make sure it's what we expect it to be\r
+  //\r
+  Status = CheckPE32File (InFptr, &MachineType, &SubSystem);\r
+  if (Status != STATUS_SUCCESS) {\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Seek to the end of the input file and get the file size\r
+  //\r
+  fseek (InFptr, 0, SEEK_END);\r
+  FileSize = ftell (InFptr);\r
+\r
+  //\r
+  // Get the size of the headers we're going to put in front of the image. The\r
+  // EFI header must be aligned on a 4-byte boundary, so pad accordingly.\r
+  //\r
+  if (sizeof (RomHdr) & 0x03) {\r
+    HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);\r
+  } else {\r
+    HeaderPadBytes = 0;\r
+  }\r
+\r
+  HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
+  if (mOptions.Verbose) {\r
+    fprintf (stdout, "  File size   = 0x%X\n", FileSize);\r
+  }\r
+  //\r
+  // Allocate memory for the entire file (in case we have to compress), then\r
+  // seek back to the beginning of the file and read it into our buffer.\r
+  //\r
+  Buffer = (INT8 *) malloc (FileSize);\r
+  if (Buffer == NULL) {\r
+    fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  fseek (InFptr, 0, SEEK_SET);\r
+  if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read all bytes from input file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Now determine the size of the final output file. It's either the header size\r
+  // plus the file's size, or the header size plus the compressed file size.\r
+  //\r
+  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {\r
+    //\r
+    // Allocate a buffer into which we can compress the image, compress it,\r
+    // and use that size as the new size.\r
+    //\r
+    CompressedBuffer = (INT8 *) malloc (FileSize);\r
+    if (CompressedBuffer == NULL) {\r
+      fprintf (stdout, "ERROR: Memory allocation failed\n");\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+\r
+    CompressedFileSize  = FileSize;\r
+    Status              = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);\r
+    if (Status != STATUS_SUCCESS) {\r
+      fprintf (stdout, "ERROR: Compression failed\n");\r
+      goto BailOut;\r
+    }\r
+    //\r
+    // Now compute the size, then swap buffer pointers.\r
+    //\r
+    if (mOptions.Verbose) {\r
+      fprintf (stdout, "  Comp size   = 0x%X\n", CompressedFileSize);\r
+    }\r
+\r
+    TotalSize         = CompressedFileSize + HeaderSize;\r
+    FileSize          = CompressedFileSize;\r
+    TempBufferPtr     = Buffer;\r
+    Buffer            = CompressedBuffer;\r
+    CompressedBuffer  = TempBufferPtr;\r
+  } else {\r
+    TotalSize = FileSize + HeaderSize;\r
+  }\r
+  //\r
+  // Total size must be an even multiple of 512 bytes\r
+  //\r
+  if (TotalSize & 0x1FF) {\r
+    TotalSize = (TotalSize + 0x200) &~0x1ff;\r
+  }\r
+  //\r
+  // Check size\r
+  //\r
+  if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+    fprintf (\r
+      stdout,\r
+      "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
+      InFile->FileName,\r
+      MAX_OPTION_ROM_SIZE\r
+      );\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Return the size to the caller so they can keep track of the running total.\r
+  //\r
+  *Size = TotalSize;\r
+\r
+  //\r
+  // Now fill in the ROM header. These values come from chapter 18 of the\r
+  // EFI 1.02 specification.\r
+  //\r
+  memset (&RomHdr, 0, sizeof (RomHdr));\r
+  RomHdr.Signature            = PCI_EXPANSION_ROM_HEADER_SIGNATURE;\r
+  RomHdr.InitializationSize   = (UINT16) (TotalSize / 512);\r
+  RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;\r
+  RomHdr.EfiSubsystem         = SubSystem;\r
+  RomHdr.EfiMachineType       = MachineType;\r
+  RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;\r
+  RomHdr.PcirOffset           = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);\r
+  //\r
+  // Set image as compressed or not\r
+  //\r
+  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {\r
+    RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;\r
+  }\r
+  //\r
+  // Fill in the PCI data structure\r
+  //\r
+  memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE));\r
+\r
+  PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE;\r
+  PciDs.VendorId  = VendId;\r
+  PciDs.DeviceId  = DevId;\r
+  PciDs.Length    = (UINT16) sizeof (PCI_DATA_STRUCTURE);\r
+  PciDs.Revision  = 0;\r
+  //\r
+  // Class code and code revision from the command line (optional)\r
+  //\r
+  PciDs.ClassCode[0]  = (UINT8) InFile->ClassCode;\r
+  PciDs.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);\r
+  PciDs.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);\r
+  PciDs.ImageLength   = RomHdr.InitializationSize;\r
+  PciDs.CodeRevision  = InFile->CodeRevision;\r
+  PciDs.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;\r
+\r
+  //\r
+  // If this is the last image, then set the LAST bit unless requested not\r
+  // to via the command-line -l argument.\r
+  //\r
+  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
+    PciDs.Indicator = INDICATOR_LAST;\r
+  }\r
+  //\r
+  // Write the ROM header to the output file\r
+  //\r
+  if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  //\r
+  // Write pad bytes to align the PciDs\r
+  //\r
+  while (HeaderPadBytes > 0) {\r
+    if (putc (0, OutFptr) == EOF) {\r
+      fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+\r
+    HeaderPadBytes--;\r
+  }\r
+  //\r
+  // Write the PCI data structure header to the output file\r
+  //\r
+  if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+  //\r
+  // Keep track of how many bytes left to write\r
+  //\r
+  TotalSize -= HeaderSize;\r
+\r
+  //\r
+  // Now dump the input file's contents to the output file\r
+  //\r
+  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");\r
+    Status = STATUS_ERROR;\r
+    goto BailOut;\r
+  }\r
+\r
+  TotalSize -= FileSize;\r
+  //\r
+  // Pad the rest of the image to make it a multiple of 512 bytes\r
+  //\r
+  while (TotalSize > 0) {\r
+    if (putc (~0, OutFptr) == EOF) {\r
+      fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+\r
+    TotalSize--;\r
+  }\r
+\r
+BailOut:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  //\r
+  // Free up our buffers\r
+  //\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+\r
+  if (CompressedBuffer != NULL) {\r
+    free (CompressedBuffer);\r
+  }\r
+  //\r
+  // Print the file name if errors occurred\r
+  //\r
+  if (Status != STATUS_SUCCESS) {\r
+    fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+int\r
+CheckPE32File (\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Fptr        - GC_TODO: add argument description\r
+  MachineType - GC_TODO: add argument description\r
+  SubSystem   - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  /*++\r
+\r
+Routine Description:\r
+  \r
+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+  PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+  Fptr          File pointer to the already-opened PE32 file\r
+  MachineType   Location to stuff the machine type of the PE32 file. This is needed\r
+                because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+  EFI_IMAGE_DOS_HEADER      DosHeader;\r
+  EFI_IMAGE_FILE_HEADER     FileHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+  UINT32                    PESig;\r
+\r
+  //\r
+  // Position to the start of the file\r
+  //\r
+  fseek (Fptr, 0, SEEK_SET);\r
+\r
+  //\r
+  // Read the DOS header\r
+  //\r
+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Check the magic number (0x5A4D)\r
+  //\r
+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Position into the file and check the PE signature\r
+  //\r
+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Check the PE signature in the header "PE\0\0"\r
+  //\r
+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Read the file header and stuff their MachineType\r
+  //\r
+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  memcpy ((char *) MachineType, &FileHdr.Machine, 2);\r
+\r
+  //\r
+  // Read the optional header so we can get the subsystem\r
+  //\r
+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+    fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  *SubSystem = OptionalHdr.Subsystem;\r
+  if (mOptions.Verbose) {\r
+    fprintf (stdout, "  Got subsystem = 0x%X from image\n", (int) *SubSystem);\r
+  }\r
+  //\r
+  // Good to go\r
+  //\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+  int         Argc,\r
+  char        *Argv[],\r
+  OPTIONS     *Options\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+  parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+  Argv[]          - standard C main() argument list\r
+  Options         - pointer to a structure to store the options in\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS    success\r
+  non-zero          otherwise\r
+\r
+--*/\r
+//\r
+{\r
+  FILE_LIST *FileList;\r
+\r
+  FILE_LIST *PrevFileList;\r
+  UINT32    FileFlags;\r
+  UINT32    ClassCode;\r
+  UINT32    CodeRevision;\r
+\r
+  FileFlags = 0;\r
+\r
+  //\r
+  // Clear out the options\r
+  //\r
+  memset ((char *) Options, 0, sizeof (OPTIONS));\r
+\r
+  //\r
+  // To avoid compile warnings\r
+  //\r
+  FileList                = PrevFileList = NULL;\r
+\r
+  ClassCode               = 0;\r
+  CodeRevision            = 0;\r
+  //\r
+  // Skip over the program name\r
+  //\r
+  Argc--;\r
+  Argv++;\r
+\r
+  //\r
+  // If no arguments, assume they want usage info\r
+  //\r
+  if (Argc == 0) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Process until no more arguments\r
+  //\r
+  while (Argc > 0) {\r
+    if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) {\r
+      //\r
+      // To simplify string comparisons, replace slashes with dashes\r
+      //\r
+      Argv[0][0] = '-';\r
+\r
+      //\r
+      // Vendor ID specified with -v\r
+      //\r
+      if (stricmp (Argv[0], "-v") == 0) {\r
+        //\r
+        // Make sure there's another parameter\r
+        //\r
+        if (Argc > 1) {\r
+          Options->VendId       = (UINT16) strtol (Argv[1], NULL, 16);\r
+          Options->VendIdValid  = 1;\r
+        } else {\r
+          fprintf (\r
+            stdout,\r
+            "ERROR: Missing Vendor ID with %s\n\n",\r
+            Argv[0]\r
+            );\r
+          Usage ();\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        Argv++;\r
+        Argc--;\r
+      } else if (stricmp (Argv[0], "-d") == 0) {\r
+        //\r
+        // Device ID specified with -d\r
+        // Make sure there's another parameter\r
+        //\r
+        if (Argc > 1) {\r
+          Options->DevId      = (UINT16) strtol (Argv[1], NULL, 16);\r
+          Options->DevIdValid = 1;\r
+        } else {\r
+          fprintf (\r
+            stdout,\r
+            "ERROR: Missing Device ID with %s\n\n",\r
+            Argv[0]\r
+            );\r
+          Usage ();\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        Argv++;\r
+        Argc--;\r
+      } else if (stricmp (Argv[0], "-o") == 0) {\r
+        //\r
+        // Output filename specified with -o\r
+        // Make sure there's another parameter\r
+        //\r
+        if (Argc > 1) {\r
+          strcpy (Options->OutFileName, Argv[1]);\r
+        } else {\r
+          fprintf (\r
+            stdout,\r
+            "ERROR: Missing output file name with %s\n\n",\r
+            Argv[0]\r
+            );\r
+          Usage ();\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        Argv++;\r
+        Argc--;\r
+      } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+        //\r
+        // Help option\r
+        //\r
+        Usage ();\r
+        return STATUS_ERROR;\r
+      } else if (stricmp (Argv[0], "-b") == 0) {\r
+        //\r
+        // Specify binary files with -b\r
+        //\r
+        FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;\r
+      } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {\r
+        //\r
+        // Specify EFI files with -e. Specify EFI-compressed with -ec.\r
+        //\r
+        FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI;\r
+        if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {\r
+          FileFlags |= FILE_FLAG_COMPRESS;\r
+        }\r
+        //\r
+        // Specify not to set the LAST bit in the last file with -l\r
+        //\r
+      } else if (stricmp (Argv[0], "-l") == 0) {\r
+        Options->NoLast = 1;\r
+      } else if (stricmp (Argv[0], "-p") == 0) {\r
+        //\r
+        // -v for verbose would have been nicer, but it's already used. Let's use\r
+        // -p for prolix (wordy) output\r
+        //\r
+        Options->Verbose = 1;\r
+      } else if (stricmp (Argv[0], "-dump") == 0) {\r
+        //\r
+        // -dump for dumping a ROM image. In this case, say that the device id\r
+        // and vendor id are valid so we don't have to specify bogus ones on the\r
+        // command line.\r
+        //\r
+        Options->DumpOption   = 1;\r
+\r
+        Options->VendIdValid  = 1;\r
+        Options->DevIdValid   = 1;\r
+        FileFlags             = FILE_FLAG_BINARY;\r
+      } else if (stricmp (Argv[0], "-cc") == 0) {\r
+        //\r
+        // Class code value for the next file in the list.\r
+        // Make sure there's another parameter\r
+        //\r
+        if (Argc > 1) {\r
+          //\r
+          // No error checking on the return value. Could check for LONG_MAX,\r
+          // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)\r
+          // at least.\r
+          //\r
+          ClassCode = (UINT32) strtol (Argv[1], NULL, 16);\r
+          if (ClassCode & 0xFF000000) {\r
+            fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]);\r
+            return STATUS_ERROR;\r
+          }\r
+        } else {\r
+          fprintf (\r
+            stdout,\r
+            "ERROR: Missing class code value with %s\n\n",\r
+            Argv[0]\r
+            );\r
+          Usage ();\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        Argv++;\r
+        Argc--;\r
+      } else if (stricmp (Argv[0], "-rev") == 0) {\r
+        //\r
+        // Code revision in the PCI data structure. The value is for the next\r
+        // file in the list.\r
+        // Make sure there's another parameter\r
+        //\r
+        if (Argc > 1) {\r
+          //\r
+          // No error checking on the return value. Could check for LONG_MAX,\r
+          // LONG_MIN, or 0 value if desired. Check range (2 bytes)\r
+          // at least.\r
+          //\r
+          CodeRevision = (UINT32) strtol (Argv[1], NULL, 16);\r
+          if (CodeRevision & 0xFFFF0000) {\r
+            fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]);\r
+            return STATUS_ERROR;\r
+          }\r
+        } else {\r
+          fprintf (\r
+            stdout,\r
+            "ERROR: Missing code revision value with %s\n\n",\r
+            Argv[0]\r
+            );\r
+          Usage ();\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        Argv++;\r
+        Argc--;\r
+      } else {\r
+        fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]);\r
+        Usage ();\r
+        return STATUS_ERROR;\r
+      }\r
+    } else {\r
+      //\r
+      // Not a slash-option argument. Must be a file name. Make sure they've specified\r
+      // -e or -b already.\r
+      //\r
+      if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {\r
+        fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]);\r
+        return STATUS_ERROR;\r
+      }\r
+      //\r
+      // Create a new file structure\r
+      //\r
+      FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
+      if (FileList == NULL) {\r
+        fprintf (stdout, "ERROR: Memory allocation failure\n");\r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      memset ((char *) FileList, 0, sizeof (FILE_LIST));\r
+      FileList->FileName  = Argv[0];\r
+      FileList->FileFlags = FileFlags;\r
+      if (Options->FileList == NULL) {\r
+        Options->FileList = FileList;\r
+      } else {\r
+        if (PrevFileList == NULL) {\r
+          PrevFileList = FileList;\r
+        } else {          \r
+          PrevFileList->Next = FileList;\r
+        }\r
+      }\r
+\r
+      PrevFileList = FileList;\r
+      //\r
+      // Set the class code and code revision for this file, then reset the values.\r
+      //\r
+      FileList->ClassCode     = ClassCode;\r
+      FileList->CodeRevision  = (UINT16) CodeRevision;\r
+      ClassCode               = 0;\r
+      CodeRevision            = 0;\r
+    }\r
+    //\r
+    // Next argument\r
+    //\r
+    Argv++;\r
+    Argc--;\r
+  }\r
+  //\r
+  // Make sure they specified a device ID and vendor ID\r
+  //\r
+  if (!Options->VendIdValid) {\r
+    fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n");\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (!Options->DevIdValid) {\r
+    fprintf (stdout, "ERROR: Missing Device ID on command line\n\n");\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Must have specified some files\r
+  //\r
+  if (Options->FileList == NULL) {\r
+    fprintf (stdout, "ERROR: Missing input file name\n");\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  Nothing.\r
+\r
+--*/\r
+{\r
+  int               Index;\r
+  static const char *Msg[] = {\r
+    "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility",\r
+    "  Copyright (C), 1999-2002 Intel Coproration\n",\r
+    "  Create an option ROM image from a list of input files",\r
+    "  Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",\r
+    "                [-e|-b] [FileName(s)]",\r
+    "    where:",\r
+    "      VendorId       - required hex PCI Vendor ID for the device",\r
+    "      DeviceId       - required hex PCI Device ID for the device",\r
+    "      OutFileName    - optional output file name. Default is the first input",\r
+    "                       file name with a "DEFAULT_OUTPUT_EXTENSION " file extension",\r
+    "      FileNames      - input PE32 or binary file name(s)",\r
+    "      BinFileName    - input binary file name(s)",\r
+    "      -p             - for verbose output",\r
+    "      -l             - to not automatically set the LAST bit on the last file",\r
+    "      -b             - following FileNames are binary files",\r
+    "      -e             - following FileNames are EFI PE32 image files",\r
+    "      -ec            - following FileNames are EFI PE32 image files, and should",\r
+    "                       be compressed by this utility",\r
+    "      -cc ClassCode  - to use hex ClassCode in the PCI data structure header for",\r
+    "                       the following FileName",\r
+    "      -rev Revision  - to use hex Revision in the PCI data structure header for",\r
+    "                       the following FileName",\r
+    "      -dump          - to dump the headers of an existing option ROM image",\r
+    "",\r
+    "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",\r
+    "",\r
+    NULL\r
+  };\r
+\r
+  for (Index = 0; Msg[Index] != NULL; Index++) {\r
+    fprintf (stdout, "%s\n", Msg[Index]);\r
+  }\r
+}\r
+\r
+static\r
+void\r
+DumpImage (\r
+  FILE_LIST *InFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  InFile  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  PCI_EXPANSION_ROM_HEADER      PciRomHdr;\r
+  FILE                          *InFptr;\r
+  UINT32                        ImageStart;\r
+  UINT32                        ImageCount;\r
+  EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;\r
+  PCI_DATA_STRUCTURE            PciDs;\r
+\r
+  //\r
+  // Open the input file\r
+  //\r
+  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+    fprintf (\r
+      stdout,\r
+      "ERROR: Could not open input file %s\n",\r
+      InFile->FileName\r
+      );\r
+    return ;\r
+  }\r
+  //\r
+  // Go through the image and dump the header stuff for each\r
+  //\r
+  ImageCount = 0;\r
+  for (;;) {\r
+    //\r
+    // Save our postition in the file, since offsets in the headers\r
+    // are relative to the particular image.\r
+    //\r
+    ImageStart = ftell (InFptr);\r
+    ImageCount++;\r
+\r
+    //\r
+    // Read the option ROM header. Have to assume a raw binary image for now.\r
+    //\r
+    if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {\r
+      fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n");\r
+      goto BailOut;\r
+    }\r
+\r
+    //\r
+    // Dump the contents of the header\r
+    //\r
+    fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart);\r
+    fprintf (stdout, "  ROM header contents\n");\r
+    fprintf (stdout, "    Signature              0x%04X\n", (UINT32) PciRomHdr.Signature);\r
+    fprintf (stdout, "    PCIR offset            0x%04X\n", (UINT32) PciRomHdr.PcirOffset);\r
+    //\r
+    // Find PCI data structure\r
+    //\r
+    if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {\r
+      fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n");\r
+      goto BailOut;\r
+    }\r
+    //\r
+    // Read and dump the PCI data structure\r
+    //\r
+    if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) {\r
+      fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n");\r
+      goto BailOut;\r
+    }\r
+\r
+    fprintf (stdout, "  PCI Data Structure\n");\r
+    fprintf (\r
+      stdout,\r
+      "    Signature              %c%c%c%c\n",\r
+      (char) PciDs.Signature,\r
+      (char) (PciDs.Signature >> 8),\r
+      (char) (PciDs.Signature >> 16),\r
+      (char) (PciDs.Signature >> 24)\r
+      );\r
+    fprintf (stdout, "    Vendor ID              0x%04X\n", PciDs.VendorId);\r
+    fprintf (stdout, "    Device ID              0x%04X\n", PciDs.DeviceId);\r
+    fprintf (\r
+      stdout,\r
+      "    Class Code             0x%06X\n",\r
+      (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))\r
+      );\r
+    fprintf (stdout, "    Image size             0x%X\n", PciDs.ImageLength * 512);\r
+    fprintf (stdout, "    Code revision:         0x%04X\n", PciDs.CodeRevision);\r
+    fprintf (stdout, "    Indicator              0x%02X", (UINT32) PciDs.Indicator);\r
+    //\r
+    // Print the indicator, used to flag the last image\r
+    //\r
+    if (PciDs.Indicator == INDICATOR_LAST) {\r
+      fprintf (stdout, "   (last image)\n");\r
+    } else {\r
+      fprintf (stdout, "\n");\r
+    }\r
+    //\r
+    // Print the code type. If EFI code, then we can provide more info.\r
+    //\r
+    fprintf (stdout, "    Code type              0x%02X", (UINT32) PciDs.CodeType);\r
+    if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+      fprintf (stdout, "   (EFI image)\n");\r
+      //\r
+      // Re-read the header as an EFI ROM header, then dump more info\r
+      //\r
+      fprintf (stdout, "  EFI ROM header contents\n");\r
+      if (fseek (InFptr, ImageStart, SEEK_SET)) {\r
+        fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");\r
+        goto BailOut;\r
+      }\r
+\r
+      if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {\r
+        fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");\r
+        goto BailOut;\r
+      }\r
+      //\r
+      // Now dump more info\r
+      //\r
+      fprintf (stdout, "    EFI Signature          0x%04X\n", EfiRomHdr.EfiSignature);\r
+      fprintf (\r
+        stdout,\r
+        "    Compression Type       0x%04X ",\r
+        (UINT32) EfiRomHdr.CompressionType\r
+        );\r
+      if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {\r
+        fprintf (stdout, "(compressed)\n");\r
+      } else {\r
+        fprintf (stdout, "(not compressed)\n");\r
+      }\r
+\r
+      fprintf (\r
+        stdout,\r
+        "    Machine type           0x%04X (%s)\n",\r
+        EfiRomHdr.EfiMachineType,\r
+        GetMachineTypeStr (EfiRomHdr.EfiMachineType)\r
+        );\r
+      fprintf (\r
+        stdout,\r
+        "    Subsystem              0x%04X (%s)\n",\r
+        EfiRomHdr.EfiSubsystem,\r
+        GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)\r
+        );\r
+      fprintf (\r
+        stdout,\r
+        "    EFI image offset       0x%04X (@0x%X)\n",\r
+        (UINT32) EfiRomHdr.EfiImageHeaderOffset,\r
+        (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)\r
+        );\r
+\r
+    } else {\r
+      //\r
+      // Not an EFI image\r
+      //\r
+      fprintf (stdout, "\n");\r
+    }\r
+    //\r
+    // If code type is EFI image, then dump it as well?\r
+    //\r
+    // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
+    // }\r
+    //\r
+    // If last image, then we're done\r
+    //\r
+    if (PciDs.Indicator == INDICATOR_LAST) {\r
+      goto BailOut;\r
+    }\r
+    //\r
+    // Seek to the start of the next image\r
+    //\r
+    if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) {\r
+      fprintf (stdout, "ERROR: Failed to seek to next image\n");\r
+      goto BailOut;\r
+    }\r
+  }\r
+\r
+BailOut:\r
+  fclose (InFptr);\r
+}\r
+\r
+char *\r
+GetMachineTypeStr (\r
+  UINT16    MachineType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  MachineType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  int Index;\r
+\r
+  for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {\r
+    if (mMachineTypes[Index].Value == MachineType) {\r
+      return mMachineTypes[Index].Name;\r
+    }\r
+  }\r
+\r
+  return "unknown";\r
+}\r
+\r
+static\r
+char *\r
+GetSubsystemTypeStr (\r
+  UINT16  SubsystemType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SubsystemType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  int Index;\r
+\r
+  for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {\r
+    if (mSubsystemTypes[Index].Value == SubsystemType) {\r
+      return mSubsystemTypes[Index].Name;\r
+    }\r
+  }\r
+\r
+  return "unknown";\r
+}\r
diff --git a/Tools/Source/TianoTools/EfiRom/Makefile b/Tools/Source/TianoTools/EfiRom/Makefile
new file mode 100644 (file)
index 0000000..5ba3607
--- /dev/null
@@ -0,0 +1,70 @@
+#/*++\r
+#  \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#  \r
+#  Module Name:\r
+#  \r
+#    makefile\r
+#    \r
+#  Abstract:\r
+#  \r
+#    makefile for building the EfiRom utility.\r
+#  \r
+#  Revision History\r
+#  \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = EfiRom\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\EfiRom.exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\EfiRom.obj \\r
+            $(TIANO_TOOLS_OUTPUT)\EfiCompress.obj\r
+            \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiRom.obj : $(TARGET_SRC_DIR)\EfiRom.c\r
+  $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\EfiRom.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\EfiCompress.obj : $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c\r
+  $(CC) $(C_FLAGS) $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c /Fo$@\r
+  \r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/FlashMap/FlashDefFile.c b/Tools/Source/TianoTools/FlashMap/FlashDefFile.c
new file mode 100644 (file)
index 0000000..fa31863
--- /dev/null
@@ -0,0 +1,2787 @@
+/*++\r
+\r
+Copyright (c)  2004-2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  FlashDefFile.c\r
+\r
+Abstract:\r
+\r
+  Utility for flash management in the Intel Platform Innovation Framework\r
+  for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "FlashDefFile.h"\r
+#include "SimpleFileParsing.h"\r
+#include "Symbols.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+\r
+//\r
+// #include "TrackMallocFree.h"\r
+//\r
+#define WCHAR_T           char\r
+#define MAX_STRING_LEN    256\r
+#define MAX_NAME_LEN      128\r
+#define BUFFER_SIZE       1024\r
+#define MAX_ATTR_LEN      128\r
+#define MAX_AREATYPE_LEN  128\r
+#define COLUMN2_START     60\r
+#define COLUMN3_START     70\r
+//\r
+// Information for each subregions defined in the fdf file will be saved in these\r
+//\r
+typedef struct _FLASH_SUBREGION_DESCRIPTION {\r
+  struct _FLASH_SUBREGION_DESCRIPTION *Next;\r
+  int                                 CreateHob;                  // to add to the auto-created HOB array\r
+  WCHAR_T                             Name[MAX_NAME_LEN];         // each subregion within a region must have a unique name\r
+  unsigned int                        Size;                       // size, in bytes, of this subregion\r
+  unsigned int                        SizeLeft;                   // used when creating the image\r
+  WCHAR_T                             Attributes[MAX_ATTR_LEN];   // subregion attributes used in the output HOB\r
+  WCHAR_T                             AreaType[MAX_AREATYPE_LEN]; // subregion area type used in the output HOB\r
+  EFI_GUID                            NameGuid;                   // used in the output HOB\r
+  WCHAR_T                             NameGuidString[MAX_NAME_LEN];\r
+  EFI_GUID                            AreaTypeGuid;               // used in the output HOB\r
+  WCHAR_T                             AreaTypeGuidString[MAX_NAME_LEN];\r
+  EFI_GUID                            FileSystemGuid;             // used in the output HOB\r
+  WCHAR_T                             FileSystemGuidString[MAX_NAME_LEN];\r
+} FLASH_SUBREGION_DESCRIPTION;\r
+\r
+//\r
+// Information for each block in a flash device will be saved in one of these.\r
+// We'll also use it for region definitions.\r
+//\r
+typedef struct _FLASH_BLOCK_DESCRIPTION {\r
+  struct _FLASH_BLOCK_DESCRIPTION *Next;                      // next block in the linked list\r
+  WCHAR_T                         Name[MAX_NAME_LEN];         // each block must have a unique name\r
+  unsigned int                    Size;                       // size, in bytes, of this block\r
+  unsigned int                    SizeLeft;                   // for use when creating image\r
+  unsigned int                    Flags;                      // user-defined flags for the block\r
+  unsigned int                    Alignment;                  // power of 2 alignment\r
+  WCHAR_T                         Attributes[MAX_ATTR_LEN];   // only used for Region definitions\r
+  WCHAR_T                         AreaType[MAX_AREATYPE_LEN]; // only used for Region definitions\r
+  FLASH_SUBREGION_DESCRIPTION     *Subregions;\r
+  FLASH_SUBREGION_DESCRIPTION     *LastSubregion;\r
+} FLASH_BLOCK_DESCRIPTION;\r
+\r
+//\r
+// Information for each flash device will be saved in one of these\r
+//\r
+typedef struct _FLASH_DEVICE_DESCRIPTION {\r
+  struct _FLASH_DEVICE_DESCRIPTION  *Next;              // next flash device in our linked list\r
+  int                               ErasePolarity;      // erase polarity of the flash device\r
+  unsigned int                      BaseAddress;        // base address of the flash device\r
+  unsigned int                      Size;               // total size, in bytes, of the flash device\r
+  WCHAR_T                           Name[MAX_NAME_LEN]; // name of the flash device\r
+  FLASH_BLOCK_DESCRIPTION           *PBlocks;           // linked list of physical block descriptors\r
+  FLASH_BLOCK_DESCRIPTION           *LastPBlock;        // last block in the linked list\r
+  FLASH_BLOCK_DESCRIPTION           *Regions;           // linked list of flash region descriptors\r
+  FLASH_BLOCK_DESCRIPTION           *LastRegion;        // last region in the linked list\r
+} FLASH_DEVICE_DESCRIPTION;\r
+\r
+//\r
+// For image definitions, they can specify a file name or raw data bytes. Keep a linked list.\r
+//\r
+typedef struct _IMAGE_DEFINITION_ENTRY {\r
+  struct _IMAGE_DEFINITION_ENTRY  *Next;\r
+  WCHAR_T                         RegionName[MAX_NAME_LEN];\r
+  WCHAR_T                         SubregionName[MAX_NAME_LEN];\r
+  WCHAR_T                         Name[MAX_NAME_LEN]; // file or data name\r
+  int                             IsRawData;          // non-zero if raw data bytes\r
+  unsigned int                    RawDataSize;\r
+  char                            *RawData;\r
+  int                             Optional;           // optional file (don't include if it doesn't exist)\r
+} IMAGE_DEFINITION_ENTRY;\r
+\r
+//\r
+// When we parse an image definition, save all the data for each in one of these\r
+//\r
+typedef struct _IMAGE_DEFINITION {\r
+  struct _IMAGE_DEFINITION  *Next;\r
+  WCHAR_T                   Name[MAX_NAME_LEN];\r
+  IMAGE_DEFINITION_ENTRY    *Entries;\r
+  IMAGE_DEFINITION_ENTRY    *LastEntry;\r
+} IMAGE_DEFINITION;\r
+\r
+typedef struct {\r
+  char  *BufferStart;\r
+  char  *BufferEnd;\r
+  char  *BufferPos;\r
+} BUFFER_DATA;\r
+\r
+static const char               *CIncludeHeader = "/*++\n\n"\r
+"  DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n""#ifndef _FLASH_MAP_H_\n"\r
+"#define _FLASH_MAP_H_\n\n";\r
+//\r
+//  "#include \"EfiFlashMap.h\"\n\n";\r
+//\r
+static const char               *CIncludeFooter = "#endif // #ifndef _FLASH_MAP_H_\n\n";\r
+\r
+static const char               *CFlashMapDataFileHeader = "/*++\n\n"\r
+"  DO NOT EDIT -- file auto-generated by FlashMap utility\n\n""--*/\n""\n";\r
+\r
+static FLASH_DEVICE_DESCRIPTION *mFlashDevices      = NULL;\r
+static IMAGE_DEFINITION         *mImageDefinitions  = NULL;\r
+\r
+//\r
+// Local function prototypes\r
+//\r
+static\r
+BUFFER_DATA                     *\r
+CreateBufferData (\r
+  VOID\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+AddBufferDataByte (\r
+  BUFFER_DATA *Buffer,\r
+  char        Data\r
+  );\r
+\r
+static\r
+void\r
+FreeBufferData (\r
+  BUFFER_DATA *Buffer,\r
+  BOOLEAN     FreeData\r
+  );\r
+\r
+static\r
+char                            *\r
+GetBufferData (\r
+  BUFFER_DATA *Buffer,\r
+  int         *BufferSize\r
+  );\r
+\r
+static\r
+FLASH_SUBREGION_DESCRIPTION     *\r
+ParseSubregionDefinition (\r
+  unsigned int  SizeLeft\r
+  );\r
+\r
+void\r
+FDFConstructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Initialization routine for the services that operate on a flash\r
+  definition file.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  NA\r
+\r
+--*/\r
+{\r
+  mFlashDevices     = NULL;\r
+  mImageDefinitions = NULL;\r
+}\r
+\r
+void\r
+FDFDestructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Finalization/cleanup routine for the services that operate on a flash\r
+  definition file.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  NA\r
+\r
+--*/\r
+{\r
+  FLASH_BLOCK_DESCRIPTION     *FBNext;\r
+  FLASH_DEVICE_DESCRIPTION    *FDNext;\r
+  IMAGE_DEFINITION            *IDNext;\r
+  IMAGE_DEFINITION_ENTRY      *IDENext;\r
+  FLASH_SUBREGION_DESCRIPTION *SubNext;\r
+  //\r
+  // Go through all our flash devices and free the memory\r
+  //\r
+  while (mFlashDevices != NULL) {\r
+    //\r
+    // Free the physical block definitions\r
+    //\r
+    while (mFlashDevices->PBlocks != NULL) {\r
+      FBNext = mFlashDevices->PBlocks->Next;\r
+      _free (mFlashDevices->PBlocks);\r
+      mFlashDevices->PBlocks = FBNext;\r
+    }\r
+    //\r
+    // Free the region definitions\r
+    //\r
+    while (mFlashDevices->Regions != NULL) {\r
+      FBNext = mFlashDevices->Regions->Next;\r
+      //\r
+      // First free the subregion definitions\r
+      //\r
+      while (mFlashDevices->Regions->Subregions != NULL) {\r
+        SubNext = mFlashDevices->Regions->Subregions->Next;\r
+        _free (mFlashDevices->Regions->Subregions);\r
+        mFlashDevices->Regions->Subregions = SubNext;\r
+      }\r
+\r
+      _free (mFlashDevices->Regions);\r
+      mFlashDevices->Regions = FBNext;\r
+    }\r
+\r
+    FDNext = mFlashDevices->Next;\r
+    _free (mFlashDevices);\r
+    mFlashDevices = FDNext;\r
+  }\r
+  //\r
+  // Free up the image definitions, and the data\r
+  //\r
+  while (mImageDefinitions != NULL) {\r
+    //\r
+    // Free the entries\r
+    //\r
+    while (mImageDefinitions->Entries != NULL) {\r
+      IDENext = mImageDefinitions->Entries->Next;\r
+      if (mImageDefinitions->Entries->RawData != NULL) {\r
+        _free (mImageDefinitions->Entries->RawData);\r
+      }\r
+\r
+      _free (mImageDefinitions->Entries);\r
+      mImageDefinitions->Entries = IDENext;\r
+    }\r
+\r
+    IDNext = mImageDefinitions->Next;\r
+    _free (mImageDefinitions);\r
+    mImageDefinitions = IDNext;\r
+  }\r
+}\r
+\r
+STATUS\r
+FDFParseFile (\r
+  char    *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse the specified flash definition file, saving the definitions in\r
+  file-static variables for use by other functions.\r
+  \r
+Arguments:\r
+  FileName    - name of the input flash definition text file.\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - file parsed with no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered while parsing\r
+  STATUS_ERROR      - errors were encountered while parsing\r
+  \r
+--*/\r
+{\r
+  FILE                        *Fptr;\r
+  STATUS                      Status;\r
+  unsigned int                Num;\r
+  FLASH_DEVICE_DESCRIPTION    *FDDesc;\r
+  FLASH_BLOCK_DESCRIPTION     *FBlockDesc;\r
+  FLASH_BLOCK_DESCRIPTION     *TempBlockDesc;\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  FLASH_SUBREGION_DESCRIPTION *TempSubregion;\r
+  unsigned int                BlockSizeLeft;\r
+  unsigned int                RegionSizeLeft;\r
+  unsigned int                SubregionSizeLeft;\r
+  int                         ErrorCount;\r
+  int                         WarningCount;\r
+  IMAGE_DEFINITION            *ImageDef;\r
+  IMAGE_DEFINITION_ENTRY      *ImageDefEntry;\r
+  IMAGE_DEFINITION_ENTRY      *TempImageDefEntry;\r
+  BUFFER_DATA                 *BufferData;\r
+  char                        Str[100];\r
+  BOOLEAN                     PreviousComma;\r
+\r
+  if ((Fptr = fopen (FileName, "r")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open input flash definition file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  fclose (Fptr);\r
+  Status        = STATUS_SUCCESS;\r
+  ErrorCount    = 0;\r
+  WarningCount  = 0;\r
+  //\r
+  // Initialize the simple-file-parsing routines\r
+  //\r
+  SFPInit ();\r
+  //\r
+  // Open the file\r
+  //\r
+  if ((Status = SFPOpenFile (FileName)) != STATUS_SUCCESS) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Parse the file. Should start with a series of these:\r
+  // FlashDevice {\r
+  //   Name = "FLASH_1234", Size = 0x2004, BaseAddress = 0xFFF0000, ErasePolarity = 1,\r
+  //   Block { Name = "BLOCK1",  Size = 0x1000, Flags = 0x0001 }\r
+  //   Block { Name = "BLOCK2",  Size = 0x1004, Flags = 0x0002 }\r
+  //   Region  { Name = "REGION_NAME", Size = 0x2004, Align= 4 }\r
+  // }\r
+  //\r
+  while (SFPIsKeyword ("FlashDevice")) {\r
+    //\r
+    // Allocate memory for new flash device description block\r
+    //\r
+    FDDesc = (FLASH_DEVICE_DESCRIPTION *) _malloc (sizeof (FLASH_DEVICE_DESCRIPTION));\r
+    if (FDDesc == NULL) {\r
+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    memset (FDDesc, 0, sizeof (FLASH_DEVICE_DESCRIPTION));\r
+    //\r
+    // Open brace -- warning if not there\r
+    //\r
+    if (!SFPIsToken ("{")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Parse:  Name = "DeviceName",\r
+    //\r
+    if (!SFPIsKeyword ("Name")) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPGetQuotedString (FDDesc->Name, sizeof (FDDesc->Name))) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of flash device", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken (",")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following flash device name", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Parse: Size = 0x20000,\r
+    //\r
+    if (!SFPIsKeyword ("Size")) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPGetNumber (&FDDesc->Size)) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+    //\r
+    // Check for 0 size\r
+    //\r
+    if (FDDesc->Size == 0) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, FDDesc->Name, "Size field cannot be 0", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    SFPIsToken (",");\r
+    //\r
+    // Parse: BaseAddress = 0xFFF0000,\r
+    //\r
+    if (!SFPIsKeyword ("BaseAddress")) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'BaseAddress'", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPGetNumber (&FDDesc->BaseAddress)) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for BaseAddress", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken (",")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following BaseAddress value", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Parse: ErasePolarity = 1,\r
+    //\r
+    if (!SFPIsKeyword ("ErasePolarity")) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'ErasePolarity'", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPGetNumber (&Num) || ((Num != 0) && (Num != 1))) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric erase polarity value 1 or 0", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    FDDesc->ErasePolarity = Num;\r
+    if (!SFPIsToken (",")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following erase polarity value", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Parse array of:\r
+    //   Block {  Name = "BLOCK1", Size = 0x1000, Flags = 0x0001 }\r
+    //\r
+    // Keep track of size to make sure the sum of the physical blocks and region sizes do not\r
+    // exceed the size of the flash device.\r
+    //\r
+    BlockSizeLeft   = FDDesc->Size;\r
+    RegionSizeLeft  = FDDesc->Size;\r
+    while (SFPIsKeyword ("Block")) {\r
+      //\r
+      // Allocate memory for a new physical block descriptor\r
+      //\r
+      FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));\r
+      if (FBlockDesc == NULL) {\r
+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));\r
+      //\r
+      // Open brace -- warning if not there\r
+      //\r
+      if (!SFPIsToken ("{")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Parse:  Name = "BlockName",\r
+      //\r
+      if (!SFPIsKeyword ("Name")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of physical block", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+      //\r
+      // Make sure there are no other physical block names with this same name\r
+      //\r
+      for (TempBlockDesc = FDDesc->PBlocks; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {\r
+        if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {\r
+          Error (\r
+            SFPGetFileName (),\r
+            SFPGetLineNumber (),\r
+            0,\r
+            TempBlockDesc->Name,\r
+            "physical block with this name already defined"\r
+            );\r
+          ErrorCount++;\r
+        }\r
+      }\r
+\r
+      if (!SFPIsToken (",")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following physical block name", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Parse: Size = 0x2000,\r
+      //\r
+      if (!SFPIsKeyword ("Size")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetNumber (&FBlockDesc->Size)) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+      //\r
+      // Make sure the sum of physical blocks so far does not exceed flash device size\r
+      //\r
+      if (BlockSizeLeft < FBlockDesc->Size) {\r
+        Error (\r
+          SFPGetFileName (),\r
+          SFPGetLineNumber (),\r
+          0,\r
+          "sum of physical block sizes exceeds flash device size",\r
+          NULL\r
+          );\r
+        ErrorCount++;\r
+      }\r
+\r
+      BlockSizeLeft -= FBlockDesc->Size;\r
+      SFPIsToken (",");\r
+      //\r
+      // Optional parse: Flags = 0xFFF0000,\r
+      //\r
+      if (SFPIsKeyword ("Flags")) {\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetNumber (&FBlockDesc->Flags)) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+      }\r
+\r
+      if (!SFPIsToken ("}")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected PhysicalBlock closing brace '}'", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Add the physical block descriptor to the end of the linked list\r
+      //\r
+      if (FDDesc->LastPBlock != NULL) {\r
+        FDDesc->LastPBlock->Next = FBlockDesc;\r
+      } else {\r
+        FDDesc->PBlocks = FBlockDesc;\r
+      }\r
+\r
+      FDDesc->LastPBlock = FBlockDesc;\r
+    }\r
+    //\r
+    // Make sure sum of sizes of physical blocks added up to size of flash device\r
+    //\r
+    if (BlockSizeLeft != 0) {\r
+      Error (\r
+        SFPGetFileName (),\r
+        SFPGetLineNumber (),\r
+        0,\r
+        NULL,\r
+        "sum of sizes of physical blocks (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",\r
+        FDDesc->Size - BlockSizeLeft,\r
+        FDDesc->Size,\r
+        BlockSizeLeft\r
+        );\r
+      ErrorCount++;\r
+    }\r
+    //\r
+    // Parse array of:\r
+    //   Region { Name = "REGION_1", Size = 0x2000, Flags = 0x1234, Alignment = 4, Attributes = "str", AreaType = "str" }\r
+    //\r
+    while (SFPIsKeyword ("Region")) {\r
+      //\r
+      // Allocate memory for a new physical block descriptor\r
+      //\r
+      FBlockDesc = (FLASH_BLOCK_DESCRIPTION *) _malloc (sizeof (FLASH_BLOCK_DESCRIPTION));\r
+      if (FBlockDesc == NULL) {\r
+        Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      memset (FBlockDesc, 0, sizeof (FLASH_BLOCK_DESCRIPTION));\r
+      //\r
+      // Open brace -- warning if not there\r
+      //\r
+      if (!SFPIsToken ("{")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Parse:  Name = "BlockName",\r
+      //\r
+      if (!SFPIsKeyword ("Name")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetQuotedString (FBlockDesc->Name, sizeof (FBlockDesc->Name))) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+      //\r
+      // Make sure there are no other region names with this same name\r
+      //\r
+      for (TempBlockDesc = FDDesc->Regions; TempBlockDesc != NULL; TempBlockDesc = TempBlockDesc->Next) {\r
+        if (strcmp (TempBlockDesc->Name, FBlockDesc->Name) == 0) {\r
+          Error (\r
+            SFPGetFileName (),\r
+            SFPGetLineNumber (),\r
+            0,\r
+            TempBlockDesc->Name,\r
+            "Region with this name already defined"\r
+            );\r
+          ErrorCount++;\r
+        }\r
+      }\r
+\r
+      if (!SFPIsToken (",")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Parse: Size = 0x2000,\r
+      //\r
+      if (!SFPIsKeyword ("Size")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetNumber (&FBlockDesc->Size)) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken (",")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+      }\r
+      //\r
+      // Make sure the sum of regions so far does not exceed flash device size\r
+      //\r
+      if (RegionSizeLeft < FBlockDesc->Size) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Region sizes exceeds flash device size", NULL);\r
+        ErrorCount++;\r
+      }\r
+\r
+      RegionSizeLeft -= FBlockDesc->Size;\r
+      //\r
+      // Optional parse: Flags = 0xFFF0000,\r
+      //\r
+      if (SFPIsKeyword ("Flags")) {\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetNumber (&FBlockDesc->Flags)) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric value for Flags", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+        //\r
+        // comma\r
+        //\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+        }\r
+      }\r
+      //\r
+      // Optional parse: Alignment = 4\r
+      //\r
+      if (SFPIsKeyword ("Alignment")) {\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetNumber (&FBlockDesc->Alignment)) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Alignment value", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+        //\r
+        // comma\r
+        //\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+        }\r
+      }\r
+      //\r
+      // Parse:  Attributes = "String",\r
+      //\r
+      if (!SFPIsKeyword ("Attributes")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetQuotedString (FBlockDesc->Attributes, sizeof (FBlockDesc->Attributes))) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken (",")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+      }\r
+      //\r
+      // Parse:  AreaType = "String",\r
+      //\r
+      if (!SFPIsKeyword ("AreaType")) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      if (!SFPIsToken ("=")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+        WarningCount++;\r
+      }\r
+\r
+      if (!SFPGetQuotedString (FBlockDesc->AreaType, sizeof (FBlockDesc->AreaType))) {\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+\r
+      PreviousComma = SFPIsToken (",");\r
+      //\r
+      // Parse optional Subregion definitions\r
+      //\r
+      SubregionSizeLeft = FBlockDesc->Size;\r
+      while (SFPIsToken ("Subregion")) {\r
+        if (!PreviousComma) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'Subregion'", NULL);\r
+          WarningCount++;\r
+          PreviousComma = TRUE;\r
+        }\r
+\r
+        Subregion = ParseSubregionDefinition (SubregionSizeLeft);\r
+        if (Subregion == NULL) {\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        SubregionSizeLeft -= Subregion->Size;\r
+        //\r
+        // Add it to the end of our list\r
+        //\r
+        if (FBlockDesc->Subregions == NULL) {\r
+          FBlockDesc->Subregions = Subregion;\r
+        } else {\r
+          FBlockDesc->LastSubregion->Next = Subregion;\r
+        }\r
+\r
+        FBlockDesc->LastSubregion = Subregion;\r
+        //\r
+        // Make sure all subregion names are unique. We do this each time\r
+        // through so that we catch the error immediately after it happens, in\r
+        // which case the reported line number is at least close to where the\r
+        // problem lies. We don't exit on the error because we can continue parsing\r
+        // the script to perhaps catch other errors or warnings.\r
+        //\r
+        for (Subregion = FBlockDesc->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+          for (TempSubregion = Subregion->Next; TempSubregion != NULL; TempSubregion = TempSubregion->Next) {\r
+            if (strcmp (Subregion->Name, TempSubregion->Name) == 0) {\r
+              Error (SFPGetFileName (), SFPGetLineNumber (), 0, Subregion->Name, "duplicate Subregion name");\r
+              ErrorCount++;\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      if (!SFPIsToken ("}")) {\r
+        Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Region closing brace '}'", NULL);\r
+        WarningCount++;\r
+      }\r
+      //\r
+      // Add the region descriptor to the end of the linked list\r
+      //\r
+      if (FDDesc->LastRegion != NULL) {\r
+        FDDesc->LastRegion->Next = FBlockDesc;\r
+      } else {\r
+        FDDesc->Regions = FBlockDesc;\r
+      }\r
+\r
+      FDDesc->LastRegion = FBlockDesc;\r
+    }\r
+    //\r
+    // Make sure sum of sizes of regions adds up to size of flash device\r
+    //\r
+    if (RegionSizeLeft != 0) {\r
+      Error (\r
+        SFPGetFileName (),\r
+        SFPGetLineNumber (),\r
+        0,\r
+        NULL,\r
+        "sum of sizes of Regions (0x%08X) != flash device size (0x%08X) : delta = 0x%08X",\r
+        FDDesc->Size - RegionSizeLeft,\r
+        FDDesc->Size,\r
+        RegionSizeLeft\r
+        );\r
+      ErrorCount++;\r
+    }\r
+    //\r
+    // Look for closing brace\r
+    //\r
+    if (!SFPIsToken ("}")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected FlashDevice closing brace '}'", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Add this flash description to the list\r
+    //\r
+    FDDesc->Next  = mFlashDevices;\r
+    mFlashDevices = FDDesc;\r
+  }\r
+\r
+  while (SFPIsKeyword ("FlashDeviceImage")) {\r
+    //\r
+    // Allocate memory for a new FD image definition\r
+    //\r
+    ImageDef = (IMAGE_DEFINITION *) _malloc (sizeof (IMAGE_DEFINITION));\r
+    if (ImageDef == NULL) {\r
+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    memset (ImageDef, 0, sizeof (IMAGE_DEFINITION));\r
+    //\r
+    // Open brace -- warning if not there\r
+    //\r
+    if (!SFPIsToken ("{")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Parse:  Name = "ImageName",\r
+    //\r
+    if (!SFPIsKeyword ("Name")) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPGetQuotedString (ImageDef->Name, sizeof (ImageDef->Name))) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of image", NULL);\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    if (!SFPIsToken (",")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following image name", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    while (1) {\r
+      //\r
+      // Parse: File { Name = "FV\FvOem.fv", Region = "REGION_OEM", Optional = TRUE }\r
+      //\r
+      if (SFPIsKeyword ("File")) {\r
+        ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));\r
+        if (ImageDefEntry == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));\r
+        //\r
+        // Open brace -- warning if not there\r
+        //\r
+        if (!SFPIsToken ("{")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse: Name = "FileName.txt"\r
+        //\r
+        if (!SFPIsKeyword ("Name")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of file", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following file name", NULL);\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse: Region = "REGION_NAME"\r
+        //\r
+        if (!SFPIsKeyword ("Region")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse optional: Subregion = "SUBREGION_NAME"\r
+        //\r
+        if (SFPIsKeyword ("Subregion")) {\r
+          if (!SFPIsToken ("=")) {\r
+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+            WarningCount++;\r
+          }\r
+\r
+          if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {\r
+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);\r
+            ErrorCount++;\r
+            goto Done;\r
+          }\r
+\r
+          if (!SFPIsToken (",")) {\r
+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);\r
+            WarningCount++;\r
+          }\r
+          //\r
+          // For a given region, you can only place data using the region name, or the subregion names.\r
+          // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that\r
+          // here by checking that any previous entries with the same Region name had a Subregion specified\r
+          // as well.\r
+          //\r
+          for (TempImageDefEntry = ImageDef->Entries;\r
+               TempImageDefEntry != NULL;\r
+               TempImageDefEntry = TempImageDefEntry->Next\r
+              ) {\r
+            if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {\r
+              if (TempImageDefEntry->SubregionName[0] == 0) {\r
+                Error (\r
+                  SFPGetFileName (),\r
+                  SFPGetLineNumber (),\r
+                  0,\r
+                  TempImageDefEntry->RegionName,\r
+                  "data already placed on a region-basis in the region, can't place data using subregions"\r
+                  );\r
+                ErrorCount++;\r
+              }\r
+            }\r
+          }\r
+        }\r
+        //\r
+        // Optional parse: Optional = TRUE | FALSE\r
+        //\r
+        if (SFPIsKeyword ("Optional")) {\r
+          if (!SFPIsToken ("=")) {\r
+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+            WarningCount++;\r
+          }\r
+\r
+          if (!SFPIsKeyword ("TRUE")) {\r
+            ImageDefEntry->Optional = 1;\r
+          } else if (SFPIsKeyword ("FALSE")) {\r
+            //\r
+            // Already set to 0\r
+            //\r
+          } else {\r
+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);\r
+            ErrorCount++;\r
+            goto Done;\r
+          }\r
+\r
+          SFPIsToken (",");\r
+        }\r
+        //\r
+        // Closing brace\r
+        //\r
+        if (!SFPIsToken ("}")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace to File entry", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+        //\r
+        // Add the entry to the end of the list\r
+        //\r
+        if (ImageDef->LastEntry != NULL) {\r
+          ImageDef->LastEntry->Next = ImageDefEntry;\r
+        } else {\r
+          ImageDef->Entries = ImageDefEntry;\r
+        }\r
+\r
+        ImageDef->LastEntry = ImageDefEntry;\r
+      } else if (SFPIsKeyword ("RawData")) {\r
+        //\r
+        // Parse: RawData { Name = "PadBytes", Region = "REGION_1", Data = { 0x78, 0x56, 0x34, 0x12 }}\r
+        //\r
+        ImageDefEntry = (IMAGE_DEFINITION_ENTRY *) _malloc (sizeof (IMAGE_DEFINITION_ENTRY));\r
+        if (ImageDefEntry == NULL) {\r
+          Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        memset (ImageDefEntry, 0, sizeof (IMAGE_DEFINITION_ENTRY));\r
+        ImageDefEntry->IsRawData = 1;\r
+        //\r
+        // Open brace -- warning if not there\r
+        //\r
+        if (!SFPIsToken ("{")) {\r
+          Warning (\r
+            SFPGetFileName (),\r
+            SFPGetLineNumber (),\r
+            0,\r
+            "expected '{' opening brace for RawData definition",\r
+            NULL\r
+            );\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse: Name = "PadBytes"\r
+        //\r
+        if (!SFPIsKeyword ("Name")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetQuotedString (ImageDefEntry->Name, sizeof (ImageDefEntry->Name))) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted name of raw data", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following raw data name", NULL);\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse: Region = "REGION_NAME"\r
+        //\r
+        if (!SFPIsKeyword ("Region")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Region'", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPGetQuotedString (ImageDefEntry->RegionName, sizeof (ImageDefEntry->RegionName))) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Region name", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken (",")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+          WarningCount++;\r
+        }\r
+        //\r
+        // Parse optional: Subregion = "SUBREGION_NAME"\r
+        //\r
+        if (SFPIsKeyword ("Subregion")) {\r
+          if (!SFPIsToken ("=")) {\r
+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+            WarningCount++;\r
+          }\r
+\r
+          if (!SFPGetQuotedString (ImageDefEntry->SubregionName, sizeof (ImageDefEntry->SubregionName))) {\r
+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Subegion name", NULL);\r
+            ErrorCount++;\r
+            goto Done;\r
+          }\r
+\r
+          if (!SFPIsToken (",")) {\r
+            Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Subregion name", NULL);\r
+            WarningCount++;\r
+          }\r
+          //\r
+          // For a given region, you can only place data using the region name, or the subregion names.\r
+          // In other words, you can't say File1->Region1 and File2->Region1.Subregion1. Enforce that\r
+          // here by checking that any previous entries with the same Region name had a Subregion specified\r
+          // as well.\r
+          //\r
+          for (TempImageDefEntry = ImageDef->Entries;\r
+               TempImageDefEntry != NULL;\r
+               TempImageDefEntry = TempImageDefEntry->Next\r
+              ) {\r
+            if (strcmp (TempImageDefEntry->Name, ImageDefEntry->Name) == 0) {\r
+              if (TempImageDefEntry->SubregionName[0] == 0) {\r
+                Error (\r
+                  SFPGetFileName (),\r
+                  SFPGetLineNumber (),\r
+                  0,\r
+                  TempImageDefEntry->RegionName,\r
+                  "data already placed on a region-basis in the region, can't place data using subregions"\r
+                  );\r
+                ErrorCount++;\r
+              }\r
+            }\r
+          }\r
+        }\r
+        //\r
+        // Parse: Data = { 0x78, 0x56, 0x34, 0x12 }\r
+        //\r
+        if (!SFPIsKeyword ("Data")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Data'", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+\r
+        if (!SFPIsToken ("=")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if (!SFPIsToken ("{")) {\r
+          Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '{' preceeding data list", NULL);\r
+          WarningCount++;\r
+        }\r
+\r
+        if ((BufferData = CreateBufferData ()) == NULL) {\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+        //\r
+        // Read bytes from input file until closing brace\r
+        //\r
+        while (!SFPIsToken ("}")) {\r
+          if (!SFPGetNumber (&Num)) {\r
+            SFPGetNextToken (Str, sizeof (Str));\r
+            Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected data value", Str);\r
+            ErrorCount++;\r
+            FreeBufferData (BufferData, TRUE);\r
+            goto Done;\r
+          } else {\r
+            //\r
+            // Only allow bytes\r
+            //\r
+            if (Num > 0xFF) {\r
+              Error (SFPGetFileName (), SFPGetLineNumber (), 0, "only values 0-255 (0x00-0xFF) allowed", NULL);\r
+              ErrorCount++;\r
+              FreeBufferData (BufferData, TRUE);\r
+              goto Done;\r
+            }\r
+\r
+            AddBufferDataByte (BufferData, (char) Num);\r
+            SFPIsToken (",");\r
+          }\r
+        }\r
+        //\r
+        // Now get the data and save it in our image entry\r
+        //\r
+        ImageDefEntry->RawData = GetBufferData (BufferData, &ImageDefEntry->RawDataSize);\r
+        FreeBufferData (BufferData, 0);\r
+        //\r
+        // Closing brace for RawData {}\r
+        //\r
+        if (!SFPIsToken ("}")) {\r
+          Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '}' closing brace for RawData", NULL);\r
+          ErrorCount++;\r
+          goto Done;\r
+        }\r
+        //\r
+        // Add the entry to the end of the list\r
+        //\r
+        if (ImageDef->LastEntry != NULL) {\r
+          ImageDef->LastEntry->Next = ImageDefEntry;\r
+        } else {\r
+          ImageDef->Entries = ImageDefEntry;\r
+        }\r
+\r
+        ImageDef->LastEntry = ImageDefEntry;\r
+      } else if (SFPIsToken ("}")) {\r
+        //\r
+        // Closing brace for FDImage {}\r
+        //\r
+        break;\r
+      } else {\r
+        SFPGetNextToken (Str, sizeof (Str));\r
+        Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "unrecognized token", Str);\r
+        ErrorCount++;\r
+        goto Done;\r
+      }\r
+    }\r
+    //\r
+    // Add this image definition to our global list\r
+    //\r
+    ImageDef->Next    = mImageDefinitions;\r
+    mImageDefinitions = ImageDef;\r
+  }\r
+  //\r
+  // Check for end-of-file\r
+  //\r
+  if (!SFPIsEOF ()) {\r
+    SFPGetNextToken (Str, sizeof (Str));\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, Str, "expected end-of-file", Str);\r
+    ErrorCount++;\r
+  }\r
+\r
+Done:\r
+  SFPCloseFile ();\r
+  if (ErrorCount != 0) {\r
+    return STATUS_ERROR;\r
+  } else if (WarningCount != 0) {\r
+    return STATUS_WARNING;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+FLASH_SUBREGION_DESCRIPTION *\r
+ParseSubregionDefinition (\r
+  unsigned int  SizeLeft\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  Parse Subregion definitions from the input flash definition file. Format:\r
+\r
+    Subregion {\r
+      CreateHob       = TRUE,\r
+      Name            = "FOO",\r
+      Size            = 0xA000,\r
+      Attributes      = "EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV",\r
+      AreaType        = "EFI_FLASH_AREA_EFI_VARIABLES",\r
+      NameGuid        = 12345678-1234-5678-AAAA-BBBBCCCCDDDD (or "EFI_SOME_GUID"),\r
+      AreaTypeGuid    = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)\r
+      FileSystemGuid  = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID") (optional)\r
+    }\r
+\r
+    NOTE: The caller has already parsed the "Subregion" token, so start with the opening brace.\r
+\r
+Arguments:\r
+   \r
+   SizeLeft   - in the flash definition file, a Region can be broken up into\r
+                one or more subregions. As we parse the subregion definitions,\r
+                the caller keeps track of how much space is left in the region\r
+                that we're parsing subregions for. SizeLeft is that size, and\r
+                so the size of the subregion we're now parsing better not\r
+                exceed the size left.\r
+  Returns:\r
+\r
+    NULL    - unrecoverable errors detected while parsing the subregion definition\r
+\r
+    pointer to a subregion definition created from the parsed subregion\r
+\r
+--*/\r
+{\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  int                         ErrorCount;\r
+  int                         WarningCount;\r
+  unsigned int                Number;\r
+  BOOLEAN                     PreviousComma;\r
+  //\r
+  // Allocate memory for the new subregion descriptor\r
+  //\r
+  ErrorCount    = 0;\r
+  WarningCount  = 0;\r
+  Subregion     = (FLASH_SUBREGION_DESCRIPTION *) _malloc (sizeof (FLASH_SUBREGION_DESCRIPTION));\r
+  if (Subregion == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  memset (Subregion, 0, sizeof (FLASH_SUBREGION_DESCRIPTION));\r
+  //\r
+  // Open brace -- warning if not there\r
+  //\r
+  if (!SFPIsToken ("{")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected {", NULL);\r
+    WarningCount++;\r
+  }\r
+  //\r
+  // Parse:  CreateHob = TRUE | FALSE,\r
+  //\r
+  if (!SFPIsKeyword ("CreateHob")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'CreateHob'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+  if (SFPIsToken ("TRUE")) {\r
+    Subregion->CreateHob = 1;\r
+  } else if (SFPIsToken ("FALSE")) {\r
+    //\r
+    // Subregion->CreateHob = 0; -- not required since we did a memset earlier\r
+    //\r
+  } else {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken (",")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following CreateHob value", NULL);\r
+    WarningCount++;\r
+  }\r
+  //\r
+  // Parse:  Name = "Name",\r
+  //\r
+  if (!SFPIsKeyword ("Name")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Name'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+  if (!SFPGetQuotedString (Subregion->Name, sizeof (Subregion->Name))) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion name", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken (",")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected comma following Region name", NULL);\r
+    WarningCount++;\r
+  }\r
+  //\r
+  // Parse: Size = 0x2000,\r
+  //\r
+  if (!SFPIsKeyword ("Size")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Size'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+  if (!SFPGetNumber (&Subregion->Size)) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected numeric Size value", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Check that the size does not exceed the size left passed in\r
+  //\r
+  if (Subregion->Size > SizeLeft) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "sum of Subregion sizes exceeds Region size", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken (",")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following Size value", NULL);\r
+  }\r
+  //\r
+  // Parse:  Attributes = Number | "String",\r
+  //\r
+  if (!SFPIsKeyword ("Attributes")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'Attributes'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+  if (SFPGetNumber (&Number)) {\r
+    sprintf (Subregion->Attributes, "0x%X", Number);\r
+  } else if (!SFPGetQuotedString (Subregion->Attributes, sizeof (Subregion->Attributes))) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted Attributes string", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken (",")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ','", NULL);\r
+  }\r
+  //\r
+  // Parse:  AreaType = Number | "String",\r
+  // AreaType is a UINT8, so error if it exceeds the size\r
+  //\r
+  if (!SFPIsKeyword ("AreaType")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'AreaType'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+  if (SFPGetNumber (&Number)) {\r
+    if (Number > 0xFF) {\r
+      Error (SFPGetFileName (), SFPGetLineNumber (), 0, "AreaType value exceeds 255", NULL);\r
+      ErrorCount++;\r
+    }\r
+\r
+    sprintf (Subregion->AreaType, "0x%X", Number & 0x00FF);\r
+  } else if (!SFPGetQuotedString (Subregion->AreaType, sizeof (Subregion->AreaType))) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected quoted AreaType string", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken (",")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' following AreaType value", NULL);\r
+  }\r
+  //\r
+  // Parse the three GUIDs (last two are optional)\r
+  //\r
+  //    NameGuid        = 12345678-1234-5678-AAAA-BBBBCCCCDDDD, (or "EFI_SOME_GUID")\r
+  //    AreaTypeGuid    = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")\r
+  //    FileSysteGuid   = 11111111-2222-3333-4444-1, (or "EFI_SOME_GUID")\r
+  //\r
+  if (!SFPIsKeyword ("NameGuid")) {\r
+    Error (SFPGetFileName (), SFPGetLineNumber (), 0, "expected 'NameGuid'", NULL);\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+\r
+  if (!SFPIsToken ("=")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+    WarningCount++;\r
+  }\r
+  //\r
+  // Allow a GUID or a quoted string identifier, which we'll just copy as a string\r
+  //\r
+  if (SFPGetQuotedString (Subregion->NameGuidString, sizeof (Subregion->NameGuidString))) {\r
+    //\r
+    // Nothing else to do\r
+    //\r
+  } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->NameGuid)) {\r
+    Error (\r
+      SFPGetFileName (),\r
+      SFPGetLineNumber (),\r
+      0,\r
+      "expected NameGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+      NULL\r
+      );\r
+    ErrorCount++;\r
+    goto Done;\r
+  }\r
+  //\r
+  // Comma following NameGuid is optional if they don't specify AreaTypeGuid or FileSystemGuid\r
+  //\r
+  PreviousComma = SFPIsToken (",");\r
+  if (SFPIsKeyword ("AreaTypeGuid")) {\r
+    //\r
+    // Check for preceeding comma now\r
+    //\r
+    if (!PreviousComma) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'AreaTypeGuid'", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (SFPGetQuotedString (Subregion->AreaTypeGuidString, sizeof (Subregion->AreaTypeGuidString))) {\r
+      //\r
+      // Nothing else to do\r
+      //\r
+    } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->AreaTypeGuid)) {\r
+      Error (\r
+        SFPGetFileName (),\r
+        SFPGetLineNumber (),\r
+        0,\r
+        "expected AreaTypeGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+        NULL\r
+        );\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    PreviousComma = SFPIsToken (",");\r
+  }\r
+\r
+  if (SFPIsKeyword ("FileSystemGuid")) {\r
+    //\r
+    // Check for preceeding comma now\r
+    //\r
+    if (!PreviousComma) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected ',' before 'FileSystemGuid'", NULL);\r
+      WarningCount++;\r
+    }\r
+\r
+    if (!SFPIsToken ("=")) {\r
+      Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected '='", NULL);\r
+      WarningCount++;\r
+    }\r
+    //\r
+    // Allow a GUID or a quoted string identifier, which we'll just copy as a string\r
+    //\r
+    if (SFPGetQuotedString (Subregion->FileSystemGuidString, sizeof (Subregion->FileSystemGuidString))) {\r
+      //\r
+      // Nothing else to do\r
+      //\r
+    } else if (!SFPGetGuid (PARSE_GUID_STYLE_5_FIELDS, &Subregion->FileSystemGuid)) {\r
+      Error (\r
+        SFPGetFileName (),\r
+        SFPGetLineNumber (),\r
+        0,\r
+        "expected FileSystemGuid quoted string or GUID of form 12345678-1234-1234-1234-123456789ABC",\r
+        NULL\r
+        );\r
+      ErrorCount++;\r
+      goto Done;\r
+    }\r
+\r
+    SFPIsToken (",");\r
+  }\r
+  //\r
+  // Look for subregion closing brace\r
+  //\r
+  if (!SFPIsToken ("}")) {\r
+    Warning (SFPGetFileName (), SFPGetLineNumber (), 0, "expected Subregion closing brace '}'", NULL);\r
+    WarningCount++;\r
+  }\r
+\r
+Done:\r
+  //\r
+  // If any errors were encountered, then delete the subregion definition\r
+  //\r
+  if (ErrorCount != 0) {\r
+    _free (Subregion);\r
+    Subregion = NULL;\r
+  }\r
+\r
+  return Subregion;\r
+}\r
+\r
+STATUS\r
+FDFCreateCIncludeFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create a header file with #define definitions per an already-parsed\r
+  flash definition file.\r
+\r
+Arguments:\r
+  FlashDeviceName - name of flash device (from the flash definition file)\r
+                    to use\r
+  FileName        - name of output file to create\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  FILE                        *OutFptr;\r
+  FLASH_BLOCK_DESCRIPTION     *FBlock;\r
+  FLASH_DEVICE_DESCRIPTION    *FDev;\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  unsigned int                Offset;\r
+  unsigned int                SubregionOffset;\r
+  int                         CreateHobs;\r
+  //\r
+  // Find the definition we're supposed to use\r
+  //\r
+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FDev == NULL) {\r
+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Write a header\r
+  //\r
+  fprintf (OutFptr, CIncludeHeader);\r
+  //\r
+  // Write flash block base and size defines\r
+  //\r
+  fprintf (OutFptr, "#define FLASH_BASE                                          0x%08X\n", FDev->BaseAddress);\r
+  fprintf (OutFptr, "#define FLASH_SIZE                                          0x%08X\n\n", FDev->Size);\r
+  //\r
+  // Write flash regions base, size and offset defines\r
+  //\r
+  Offset      = 0;\r
+  CreateHobs  = 0;\r
+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+    fprintf (\r
+      OutFptr,\r
+      "#define FLASH_REGION_%s_BASE              %*c0x%08X\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      Offset + FDev->BaseAddress\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "#define FLASH_REGION_%s_SIZE              %*c0x%08X\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      FBlock->Size\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "#define FLASH_REGION_%s_OFFSET            %*c0x%08X\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      Offset\r
+      );\r
+    //\r
+    // Create defines for any subregions\r
+    //\r
+    SubregionOffset = 0;\r
+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+      fprintf (\r
+        OutFptr,\r
+        "#define FLASH_REGION_%s_SUBREGION_%s_BASE     %*c0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        FDev->BaseAddress + Offset + SubregionOffset\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "#define FLASH_REGION_%s_SUBREGION_%s_SIZE     %*c0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Subregion->Size\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "#define FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*c0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 43 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Offset + SubregionOffset\r
+        );\r
+      SubregionOffset += Subregion->Size;\r
+      if (Subregion->CreateHob != 0) {\r
+        CreateHobs = 1;\r
+      }\r
+    }\r
+\r
+    Offset += FBlock->Size;\r
+  }\r
+  //\r
+  // Now create a #define for the flash map data definition\r
+  //\r
+  fprintf (OutFptr, "\n\n#define EFI_FLASH_AREA_DATA_DEFINITION \\\n");\r
+  //\r
+  // Emit entry for each region\r
+  //\r
+  Offset = 0;\r
+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+    fprintf (OutFptr, "  /* %s region */\\\n", FBlock->Name);\r
+    fprintf (OutFptr, "  {\\\n");\r
+    fprintf (OutFptr, "    FLASH_REGION_%s_BASE,\\\n", FBlock->Name);\r
+    fprintf (OutFptr, "    FLASH_REGION_%s_SIZE,\\\n", FBlock->Name);\r
+    fprintf (OutFptr, "    %s,\\\n", FBlock->Attributes);\r
+    fprintf (OutFptr, "    %s,\\\n  },\\\n", FBlock->AreaType);\r
+  }\r
+\r
+  fprintf (OutFptr, "\n\n");\r
+  //\r
+  // Now walk the list again to create the EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\r
+  //\r
+  if (CreateHobs != 0) {\r
+    fprintf (OutFptr, "//\n// EFI_HOB_FLASH_MAP_ENTRY_TYPE definition\n//\n");\r
+    fprintf (OutFptr, "#define EFI_HOB_FLASH_MAP_ENTRY_TYPE_DATA_DEFINITION");\r
+    for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+      //\r
+      // See if the block has subregions, and that the CreateHobs flag is set\r
+      // for any of them.\r
+      //\r
+      CreateHobs = 0;\r
+      for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+        if (Subregion->CreateHob != 0) {\r
+          CreateHobs = 1;\r
+          break;\r
+        }\r
+      }\r
+      //\r
+      // If any of the subregions had the CreateHobs flag set, then create the entries in the\r
+      // output file\r
+      //\r
+      if (CreateHobs != 0) {\r
+        for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+          if (Subregion->CreateHob != 0) {\r
+            fprintf (OutFptr, " \\\n");\r
+            fprintf (OutFptr, "  /* %s.%s Subregion */\\\n", FBlock->Name, Subregion->Name);\r
+            fprintf (OutFptr, "  {\\\n");\r
+            fprintf (OutFptr, "    EFI_HOB_TYPE_GUID_EXTENSION,\\\n");\r
+            fprintf (OutFptr, "    sizeof (EFI_HOB_FLASH_MAP_ENTRY_TYPE ),\\\n");\r
+            fprintf (OutFptr, "    0,\\\n");\r
+            //\r
+            // The NameGuid may have been specified in the input flash definition file as a GUID, or\r
+            // as a quoted string. Do the right one.\r
+            //\r
+            if (Subregion->NameGuidString[0] != 0) {\r
+              fprintf (OutFptr, "    %s, \\\n", Subregion->NameGuidString);\r
+            } else {\r
+              fprintf (\r
+                OutFptr,\r
+                "    { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+                Subregion->NameGuid.Data1,\r
+                (unsigned int) Subregion->NameGuid.Data2,\r
+                (unsigned int) Subregion->NameGuid.Data3,\r
+                (unsigned int) Subregion->NameGuid.Data4[0],\r
+                (unsigned int) Subregion->NameGuid.Data4[1],\r
+                (unsigned int) Subregion->NameGuid.Data4[2],\r
+                (unsigned int) Subregion->NameGuid.Data4[3],\r
+                (unsigned int) Subregion->NameGuid.Data4[4],\r
+                (unsigned int) Subregion->NameGuid.Data4[5],\r
+                (unsigned int) Subregion->NameGuid.Data4[6],\r
+                (unsigned int) Subregion->NameGuid.Data4[7]\r
+                );\r
+            }\r
+\r
+            fprintf (OutFptr, "    0, 0, 0,\\\n");\r
+            fprintf (OutFptr, "    %s,\\\n", Subregion->AreaType);\r
+            //\r
+            // The AreaTypeGuid may have been specified in the input flash definition file as a GUID, or\r
+            // as a quoted string. Do the right one.\r
+            //\r
+            if (Subregion->AreaTypeGuidString[0] != 0) {\r
+              fprintf (OutFptr, "    %s, \\\n", Subregion->AreaTypeGuidString);\r
+            } else {\r
+              fprintf (\r
+                OutFptr,\r
+                "    { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+                Subregion->AreaTypeGuid.Data1,\r
+                (unsigned int) Subregion->AreaTypeGuid.Data2,\r
+                (unsigned int) Subregion->AreaTypeGuid.Data3,\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[0],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[1],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[2],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[3],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[4],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[5],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[6],\r
+                (unsigned int) Subregion->AreaTypeGuid.Data4[7]\r
+                );\r
+            }\r
+\r
+            fprintf (OutFptr, "    1,\\\n");\r
+            fprintf (OutFptr, "    {\\\n");\r
+            fprintf (OutFptr, "      %s,\\\n", Subregion->Attributes);\r
+            fprintf (OutFptr, "      0,\\\n");\r
+            fprintf (OutFptr, "      FLASH_REGION_%s_SUBREGION_%s_BASE,\\\n", FBlock->Name, Subregion->Name);\r
+            fprintf (OutFptr, "      FLASH_REGION_%s_SUBREGION_%s_SIZE,\\\n", FBlock->Name, Subregion->Name);\r
+            //\r
+            // The FileSystemGuid may have been specified in the input flash definition file as a GUID, or\r
+            // as a quoted string. Do the right one.\r
+            //\r
+            if (Subregion->FileSystemGuidString[0] != 0) {\r
+              fprintf (OutFptr, "      %s, \\\n", Subregion->FileSystemGuidString);\r
+            } else {\r
+              fprintf (\r
+                OutFptr,\r
+                "      { 0x%08X, 0x%04X, 0x%04X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X },\\\n",\r
+                Subregion->FileSystemGuid.Data1,\r
+                (unsigned int) Subregion->FileSystemGuid.Data2,\r
+                (unsigned int) Subregion->FileSystemGuid.Data3,\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[0],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[1],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[2],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[3],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[4],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[5],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[6],\r
+                (unsigned int) Subregion->FileSystemGuid.Data4[7]\r
+                );\r
+            }\r
+\r
+            fprintf (OutFptr, "    },\\\n");\r
+            fprintf (OutFptr, "  },");\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    fprintf (OutFptr, "\n\n");\r
+  }\r
+\r
+  //\r
+  // Write the file's closing #endif\r
+  //\r
+  fprintf (OutFptr, CIncludeFooter);\r
+  fclose (OutFptr);\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateAsmIncludeFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create an assembly header file with equate definitions per an already-parsed\r
+  flash definition file.\r
+\r
+Arguments:\r
+  FlashDeviceName - name of flash device (from the flash definition file)\r
+                    to use\r
+  FileName        - name of output file to create\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  FILE                        *OutFptr;\r
+  FLASH_BLOCK_DESCRIPTION     *FBlock;\r
+  FLASH_DEVICE_DESCRIPTION    *FDev;\r
+  unsigned int                Offset;\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  unsigned int                SubregionOffset;\r
+  //\r
+  // Find the definition we're supposed to use\r
+  //\r
+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FDev == NULL) {\r
+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Write a header\r
+  //\r
+  fprintf (OutFptr, "\n\n");\r
+  //\r
+  // Write flash block size and offset defines\r
+  //\r
+  fprintf (\r
+    OutFptr,\r
+    "FLASH_BASE                               %*cequ 0%08Xh\n",\r
+    COLUMN2_START - 40,\r
+    ' ',\r
+    FDev->BaseAddress\r
+    );\r
+  fprintf (OutFptr, "FLASH_SIZE                               %*cequ 0%08Xh\n", COLUMN2_START - 40, ' ', FDev->Size);\r
+  //\r
+  // Write flash region size and offset defines\r
+  //\r
+  fprintf (OutFptr, "\n");\r
+  Offset = 0;\r
+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_BASE   %*cequ 0%08Xh\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 20 - strlen (FBlock->Name),\r
+      ' ',\r
+      FDev->BaseAddress + Offset\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_SIZE   %*cequ 0%08Xh\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 20 - strlen (FBlock->Name),\r
+      ' ',\r
+      FBlock->Size\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_OFFSET %*cequ 0%08Xh\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 20 - strlen (FBlock->Name),\r
+      ' ',\r
+      Offset\r
+      );\r
+    //\r
+    // Create defines for any subregions\r
+    //\r
+    SubregionOffset = 0;\r
+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_BASE     %*cequ 0%08Xh\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        FDev->BaseAddress + Offset + SubregionOffset\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_SIZE     %*cequ 0%08Xh\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Subregion->Size\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*cequ 0%08Xh\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 39 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Offset + SubregionOffset\r
+        );\r
+      SubregionOffset += Subregion->Size;\r
+    }\r
+\r
+    Offset += FBlock->Size;\r
+  }\r
+\r
+  //\r
+  // Write closing \n\r
+  //\r
+  fprintf (OutFptr, "\n\n");\r
+  fclose (OutFptr);\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateSymbols (\r
+  char      *FlashDeviceName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Using the given flash device name, add symbols to the global symbol table. This\r
+  allows other functions to use the symbol definitions for other purposes.\r
+\r
+Arguments:\r
+  FlashDeviceName - name of flash device (from the flash definition file)\r
+                    to use\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  FLASH_BLOCK_DESCRIPTION     *FBlock;\r
+  FLASH_DEVICE_DESCRIPTION    *FDev;\r
+  unsigned int                Offset;\r
+  char                        SymName[120];\r
+  char                        SymValue[120];\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  unsigned int                SubregionOffset;\r
+  //\r
+  // Find the definition we're supposed to use\r
+  //\r
+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FDev == NULL) {\r
+    Error (NULL, 0, 0, NULL, FlashDeviceName, "flash device not found in flash definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  sprintf (SymValue, "0x%08X", FDev->BaseAddress);\r
+  SymbolAdd ("FLASH_BASE", SymValue, 0);\r
+  sprintf (SymValue, "0x%08X", FDev->Size);\r
+  SymbolAdd ("FLASH_SIZE", SymValue, 0);\r
+  //\r
+  // Add flash block size and offset defines\r
+  //\r
+  // Offset = 0;\r
+  // for (FBlock = FDev->PBlocks; FBlock != NULL; FBlock = FBlock->Next) {\r
+  //  sprintf (SymName, "FLASH_BLOCK_%s_BASE", FBlock->Name);\r
+  //  sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);\r
+  //  SymbolAdd (SymName, SymValue, 0);\r
+  //  sprintf (SymName, "FLASH_BLOCK_%s_SIZE", FBlock->Name);\r
+  //  sprintf (SymValue, "0x%08X", FBlock->Size);\r
+  //  SymbolAdd (SymName, SymValue, 0);\r
+  //  sprintf (SymName, "FLASH_BLOCK_%s_OFFSET", FBlock->Name);\r
+  //  sprintf (SymValue, "0x%08X", Offset);\r
+  //  SymbolAdd (SymName, SymValue, 0);\r
+  //  Offset += FBlock->Size;\r
+  // }\r
+  //\r
+  // Add flash region block base, size, and offset defines\r
+  //\r
+  Offset = 0;\r
+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+    sprintf (SymName, "FLASH_REGION_%s_BASE", FBlock->Name);\r
+    sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset);\r
+    SymbolAdd (SymName, SymValue, 0);\r
+    sprintf (SymName, "FLASH_REGION_%s_SIZE", FBlock->Name);\r
+    sprintf (SymValue, "0x%08X", FBlock->Size);\r
+    SymbolAdd (SymName, SymValue, 0);\r
+    sprintf (SymName, "FLASH_REGION_%s_OFFSET", FBlock->Name);\r
+    sprintf (SymValue, "0x%08X", Offset);\r
+    SymbolAdd (SymName, SymValue, 0);\r
+    //\r
+    // Add subregion symbols\r
+    //\r
+    if (FBlock->Subregions != NULL) {\r
+      SubregionOffset = 0;\r
+      for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_BASE", FBlock->Name, Subregion->Name);\r
+        sprintf (SymValue, "0x%08X", FDev->BaseAddress + Offset + SubregionOffset);\r
+        SymbolAdd (SymName, SymValue, 0);\r
+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_SIZE", FBlock->Name, Subregion->Name);\r
+        sprintf (SymValue, "0x%08X", Subregion->Size);\r
+        SymbolAdd (SymName, SymValue, 0);\r
+        sprintf (SymName, "FLASH_REGION_%s_SUBREGION_%s_OFFSET", FBlock->Name, Subregion->Name);\r
+        sprintf (SymValue, "0x%08X", Offset + SubregionOffset);\r
+        SymbolAdd (SymName, SymValue, 0);\r
+        SubregionOffset += Subregion->Size;\r
+      }\r
+    }\r
+\r
+    Offset += FBlock->Size;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+FDFCreateImage (\r
+  char      *FlashDeviceName,\r
+  char      *ImageName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create a flash image using the given device and image names.\r
+\r
+Arguments:\r
+  FlashDeviceName - name of flash device (from the flash definition file)\r
+                    to use\r
+  ImageName       - name of image (from the flash definition file) to create\r
+  FileName        - name of output file to create\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  STATUS                      Status;\r
+  FILE                        *OutFptr;\r
+  FLASH_BLOCK_DESCRIPTION     *RegionDef;\r
+  FLASH_DEVICE_DESCRIPTION    *FDev;\r
+  IMAGE_DEFINITION            *ImageDef;\r
+  unsigned int                Offset;\r
+  char                        *Buffer;\r
+  FILE                        *InFptr;\r
+  long                        FileSize;\r
+  IMAGE_DEFINITION_ENTRY      *IDefEntry;\r
+  FLASH_SUBREGION_DESCRIPTION *SubregionDef;\r
+  //\r
+  // Find the flash definition we're supposed to use\r
+  //\r
+  InFptr  = NULL;\r
+  Status  = STATUS_ERROR;\r
+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FDev == NULL) {\r
+    Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Find the image name we're supposed to create\r
+  //\r
+  for (ImageDef = mImageDefinitions; ImageDef != NULL; ImageDef = ImageDef->Next) {\r
+    if (strcmp (ImageDef->Name, ImageName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (ImageDef == NULL) {\r
+    Error (NULL, 0, 0, ImageName, "image definition not found in image definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Open the output file\r
+  //\r
+  if ((OutFptr = fopen (FileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Allocate a buffer to copy the input data to\r
+  //\r
+  Buffer = (char *) _malloc (FDev->Size);\r
+  if (Buffer == NULL) {\r
+    Error (NULL, 0, 0, (INT8 *) "failed to allocate memory", NULL);\r
+    goto Done;\r
+  }\r
+  //\r
+  // Set contents of buffer to the erased value\r
+  //\r
+  if (FDev->ErasePolarity) {\r
+    memset (Buffer, 0xFF, FDev->Size);\r
+  } else {\r
+    memset (Buffer, 0, FDev->Size);\r
+  }\r
+  //\r
+  // Set all region and subregion size-left fields to the size of the region/subregion\r
+  //\r
+  for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {\r
+    RegionDef->SizeLeft = RegionDef->Size;\r
+    for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {\r
+      SubregionDef->SizeLeft = SubregionDef->Size;\r
+    }\r
+  }\r
+  //\r
+  // Now go through the image list, read files into the buffer.\r
+  //\r
+  for (IDefEntry = ImageDef->Entries; IDefEntry != NULL; IDefEntry = IDefEntry->Next) {\r
+    //\r
+    // If it's a file name, open the file, get the size, find the corresponding\r
+    // flash region it's in, and copy the data.\r
+    //\r
+    if (IDefEntry->IsRawData == 0) {\r
+      if ((InFptr = fopen (IDefEntry->Name, "rb")) == NULL) {\r
+        Error (NULL, 0, 0, IDefEntry->Name, "failed to open input file for reading");\r
+        goto Done;\r
+      }\r
+\r
+      fseek (InFptr, 0, SEEK_END);\r
+      FileSize = ftell (InFptr);\r
+      fseek (InFptr, 0, SEEK_SET);\r
+    } else {\r
+      FileSize = IDefEntry->RawDataSize;\r
+    }\r
+    //\r
+    // Find the region/subregion it's in, see if we have space left\r
+    //\r
+    Offset = 0;\r
+    for (RegionDef = FDev->Regions; RegionDef != NULL; RegionDef = RegionDef->Next) {\r
+      if (strcmp (RegionDef->Name, IDefEntry->RegionName) == 0) {\r
+        break;\r
+      }\r
+\r
+      Offset += RegionDef->Size;\r
+    }\r
+\r
+    if (RegionDef == NULL) {\r
+      Error (NULL, 0, 0, IDefEntry->RegionName, "Region name not found in FlashDevice %s definition", FDev->Name);\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Check for subregion\r
+    //\r
+    if (IDefEntry->SubregionName[0] != 0) {\r
+      for (SubregionDef = RegionDef->Subregions; SubregionDef != NULL; SubregionDef = SubregionDef->Next) {\r
+        if (strcmp (SubregionDef->Name, IDefEntry->SubregionName) == 0) {\r
+          break;\r
+        }\r
+\r
+        Offset += SubregionDef->Size;\r
+      }\r
+\r
+      if (SubregionDef == NULL) {\r
+        Error (\r
+          NULL,\r
+          0,\r
+          0,\r
+          IDefEntry->SubregionName,\r
+          "Subregion name not found in FlashDevice %s.%s Region definition",\r
+          FDev->Name,\r
+          RegionDef->Name\r
+          );\r
+        goto Done;\r
+      }\r
+      //\r
+      // Enough space in the subregion?\r
+      //\r
+      if (SubregionDef->SizeLeft < (unsigned int) FileSize) {\r
+        Error (\r
+          NULL,\r
+          0,\r
+          0,\r
+          IDefEntry->Name,\r
+          "insufficient space in Subregion (at least 0x%X additional bytes required)",\r
+          FileSize - SubregionDef->SizeLeft\r
+          );\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Read the file into the buffer if it's a file. Otherwise copy the raw data\r
+      //\r
+      if (IDefEntry->IsRawData == 0) {\r
+        if (fread (Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft), FileSize, 1, InFptr) != 1) {\r
+          Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");\r
+          goto Done;\r
+        }\r
+\r
+        fclose (InFptr);\r
+        InFptr = NULL;\r
+      } else {\r
+        memcpy (\r
+          Buffer + Offset + (SubregionDef->Size - SubregionDef->SizeLeft),\r
+          IDefEntry->RawData,\r
+          IDefEntry->RawDataSize\r
+          );\r
+      }\r
+\r
+      SubregionDef->SizeLeft -= FileSize;\r
+      //\r
+      // Align based on the Region alignment requirements.\r
+      //\r
+      if (RegionDef->Alignment != 0) {\r
+        while (((unsigned int) (SubregionDef->Size - SubregionDef->SizeLeft) &~RegionDef->Alignment) != 0) {\r
+          if (SubregionDef->SizeLeft == 0) {\r
+            break;\r
+          }\r
+\r
+          SubregionDef->SizeLeft--;\r
+        }\r
+      }\r
+    } else {\r
+      //\r
+      // Placing data in a region. Check for enough space in the region left.\r
+      //\r
+      if (RegionDef->SizeLeft < (unsigned int) FileSize) {\r
+        Error (\r
+          NULL,\r
+          0,\r
+          0,\r
+          IDefEntry->Name,\r
+          "insufficient space in Region (at least 0x%X additional bytes required)",\r
+          FileSize - RegionDef->SizeLeft\r
+          );\r
+        goto Done;\r
+      }\r
+\r
+      //\r
+      // Read the file into the buffer if it's a file. Otherwise copy the raw data\r
+      //\r
+      if (IDefEntry->IsRawData == 0) {\r
+        if (fread (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), FileSize, 1, InFptr) != 1) {\r
+          Error (NULL, 0, 0, IDefEntry->Name, "failed to read file contents");\r
+          goto Done;\r
+        }\r
+\r
+        fclose (InFptr);\r
+        InFptr = NULL;\r
+      } else {\r
+        memcpy (Buffer + Offset + (RegionDef->Size - RegionDef->SizeLeft), IDefEntry->RawData, IDefEntry->RawDataSize);\r
+      }\r
+\r
+      RegionDef->SizeLeft -= FileSize;\r
+      //\r
+      // Align\r
+      //\r
+      if (RegionDef->Alignment != 0) {\r
+        while (((unsigned int) (RegionDef->Size - RegionDef->SizeLeft) &~RegionDef->Alignment) != 0) {\r
+          if (RegionDef->SizeLeft == 0) {\r
+            break;\r
+          }\r
+\r
+          RegionDef->SizeLeft--;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  if (fwrite (Buffer, FDev->Size, 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, "failed to write buffer contents to output file", NULL);\r
+    goto Done;\r
+  }\r
+\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  if (Buffer != NULL) {\r
+    _free (Buffer);\r
+  }\r
+\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+    if (Status == STATUS_ERROR) {\r
+      remove (FileName);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+STATUS\r
+FDFCreateDscFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Create a DSC-style output file with equates for flash management.\r
+\r
+Arguments:\r
+  FlashDeviceName - name of flash device (from the flash definition file)\r
+                    to use\r
+  FileName        - name of output file to create\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  FILE                        *OutFptr;\r
+  FLASH_BLOCK_DESCRIPTION     *FBlock;\r
+  FLASH_DEVICE_DESCRIPTION    *FDev;\r
+  unsigned int                Offset;\r
+  FLASH_SUBREGION_DESCRIPTION *Subregion;\r
+  unsigned int                SubregionOffset;\r
+  //\r
+  // Find the definition we're supposed to use\r
+  //\r
+  for (FDev = mFlashDevices; FDev != NULL; FDev = FDev->Next) {\r
+    if (strcmp (FDev->Name, FlashDeviceName) == 0) {\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (FDev == NULL) {\r
+    Error (NULL, 0, 0, FlashDeviceName, "flash device not found in flash definitions");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if ((OutFptr = fopen (FileName, "w")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Write the flash base address and size\r
+  //\r
+  fprintf (OutFptr, "\n");\r
+  fprintf (OutFptr, "FLASH_BASE                                      = 0x%08X\n", FDev->BaseAddress);\r
+  fprintf (OutFptr, "FLASH_SIZE                                      = 0x%08X\n\n", FDev->Size);\r
+  //\r
+  // Write flash block size and offset defines\r
+  //\r
+  Offset = 0;\r
+  for (FBlock = FDev->Regions; FBlock != NULL; FBlock = FBlock->Next) {\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_BASE          %*c= 0x%08X\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      Offset + FDev->BaseAddress\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_SIZE          %*c= 0x%08X\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      FBlock->Size\r
+      );\r
+    fprintf (\r
+      OutFptr,\r
+      "FLASH_REGION_%s_SIZE_BLOCKS   %*c= 0x%x\n",\r
+      FBlock->Name,\r
+      COLUMN2_START - 40 - strlen (FBlock->Name),\r
+      ' ',\r
+      (FBlock->Size)/(FDev->PBlocks->Size)\r
+      );      \r
+    //\r
+    // Create defines for any subregions\r
+    //\r
+    SubregionOffset = 0;\r
+    for (Subregion = FBlock->Subregions; Subregion != NULL; Subregion = Subregion->Next) {\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_BASE     %*c= 0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        FDev->BaseAddress + Offset + SubregionOffset\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_SIZE     %*c= 0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Subregion->Size\r
+        );\r
+      fprintf (\r
+        OutFptr,\r
+        "FLASH_REGION_%s_SUBREGION_%s_OFFSET   %*c= 0x%08X\n",\r
+        FBlock->Name,\r
+        Subregion->Name,\r
+        COLUMN3_START - 48 - strlen (FBlock->Name) - strlen (Subregion->Name),\r
+        ' ',\r
+        Offset + SubregionOffset\r
+        );\r
+\r
+      SubregionOffset += Subregion->Size;\r
+    }\r
+\r
+    Offset += FBlock->Size;\r
+  }\r
+  //\r
+  // Close file\r
+  //\r
+  fprintf (OutFptr, "\n");\r
+  fclose (OutFptr);\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+  The following buffer management routines are used to encapsulate functionality\r
+  for managing a growable data buffer.\r
+\r
+Arguments:\r
+  BUFFER_DATA     - structure that is used to maintain a data buffer\r
+\r
+Returns:\r
+  NA\r
+\r
+--*/\r
+static\r
+BUFFER_DATA *\r
+CreateBufferData (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Create a growable data buffer with default buffer length.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  NULL          - error occured during data buffer creation\r
+  Not NULL      - the pointer to the newly created data buffer\r
+\r
+--*/\r
+{\r
+  BUFFER_DATA *BD;\r
+  BD = (BUFFER_DATA *) _malloc (sizeof (BUFFER_DATA));\r
+  if (BD == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+    return NULL;\r
+  }\r
+\r
+  memset (BD, 0, sizeof (BUFFER_DATA));\r
+  BD->BufferStart = (char *) _malloc (BUFFER_SIZE);\r
+  if (BD->BufferStart == NULL) {\r
+    _free (BD);\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+    return NULL;\r
+  }\r
+\r
+  BD->BufferEnd = BD->BufferStart + BUFFER_SIZE;\r
+  BD->BufferPos = BD->BufferStart;\r
+  return BD;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+AddBufferDataByte (\r
+  BUFFER_DATA *Buffer,\r
+  char        Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Add a single byte to a growable data buffer, growing the buffer if required.\r
+\r
+Arguments:\r
+\r
+  Buffer  - pointer to the growable data buffer to add a single byte to\r
+  Data    - value of the single byte data to be added\r
+\r
+Returns:\r
+\r
+  TRUE    - the single byte data was successfully added\r
+  FALSE   - error occurred, the single byte data was not added\r
+\r
+--*/\r
+{\r
+  int   Size;\r
+  char  *NewBuffer;\r
+  //\r
+  // See if we have to grow the buffer\r
+  //\r
+  if (Buffer->BufferPos >= Buffer->BufferEnd) {\r
+    Size      = (int) Buffer->BufferEnd - (int) Buffer->BufferStart;\r
+    NewBuffer = (char *) _malloc (Size + BUFFER_SIZE);\r
+    if (NewBuffer == NULL) {\r
+      Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);\r
+      return FALSE;\r
+    }\r
+\r
+    memcpy (NewBuffer, Buffer->BufferStart, Size);\r
+    _free (Buffer->BufferStart);\r
+    Buffer->BufferStart = NewBuffer;\r
+    Buffer->BufferPos   = Buffer->BufferStart + Size;\r
+    Buffer->BufferEnd   = Buffer->BufferStart + Size + BUFFER_SIZE;\r
+  }\r
+\r
+  *Buffer->BufferPos = Data;\r
+  Buffer->BufferPos++;\r
+  return TRUE;\r
+}\r
+\r
+static\r
+void\r
+FreeBufferData (\r
+  BUFFER_DATA *Buffer,\r
+  BOOLEAN     FreeData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Free memory used to manage a growable data buffer.\r
+\r
+Arguments:\r
+\r
+  Buffer    - pointer to the growable data buffer to be destructed\r
+  FreeData  - TRUE, free memory containing the buffered data\r
+              FALSE, do not free the buffered data memory\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (Buffer != NULL) {\r
+    if (FreeData && (Buffer->BufferStart != NULL)) {\r
+      _free (Buffer->BufferStart);\r
+    }\r
+\r
+    _free (Buffer);\r
+  }\r
+}\r
+\r
+static\r
+char *\r
+GetBufferData (\r
+  BUFFER_DATA *Buffer,\r
+  int         *BufferSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Return a pointer and size of the data in a growable data buffer.\r
+\r
+Arguments:\r
+\r
+  Buffer      - pointer to the growable data buffer\r
+  BufferSize  - size of the data in the growable data buffer\r
+\r
+Returns:\r
+\r
+  pointer of the data in the growable data buffer\r
+\r
+--*/\r
+{\r
+  *BufferSize = (int) Buffer->BufferPos - (int) Buffer->BufferStart;\r
+  return Buffer->BufferStart;\r
+}\r
+\r
+STATUS\r
+FDDiscover (\r
+  char          *FDFileName,\r
+  unsigned int  BaseAddr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Walk a binary image and see if you find anything that looks like a\r
+  firmware volume.\r
+\r
+Arguments:\r
+  FDFileName        - name of input FD image to parse\r
+  BaseAddr          - base address of input FD image\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_WARNING    - warnings, but no errors, were encountered\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+NOTE:\r
+  This routine is used for debug purposes only.\r
+\r
+--*/\r
+{\r
+  FILE                        *InFptr;\r
+  long                        FileSize;\r
+  long                        Offset;\r
+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;\r
+  EFI_GUID\r
+    FileSystemGuid = { 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF };\r
+\r
+  if ((InFptr = fopen (FDFileName, "rb")) == NULL) {\r
+    Error (NULL, 0, 0, FDFileName, "failed to open file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  fseek (InFptr, 0, SEEK_END);\r
+  FileSize = ftell (InFptr);\r
+  fseek (InFptr, 0, SEEK_SET);\r
+  Offset = 0;\r
+  while (Offset < FileSize) {\r
+    fseek (InFptr, Offset, SEEK_SET);\r
+    //\r
+    // Read the contents of the file, see if it's an FV header\r
+    //\r
+    if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) == 1) {\r
+      //\r
+      // Check version and GUID\r
+      //\r
+      if ((FVHeader.Revision == EFI_FVH_REVISION) && (FVHeader.Signature == EFI_FVH_SIGNATURE)) {\r
+        fprintf (stdout, "FV header at 0x%08X FVSize=0x%08X ", Offset + BaseAddr, (UINT32) FVHeader.FvLength);\r
+        if (memcmp (&FVHeader.FileSystemGuid, &FileSystemGuid, sizeof (EFI_GUID)) == 0) {\r
+          fprintf (stdout, "standard FFS file system\n");\r
+        } else {\r
+          fprintf (stdout, "non-standard FFS file system\n");\r
+        }\r
+      }\r
+    }\r
+\r
+    Offset += 16 * 1024;\r
+  }\r
+\r
+  fclose (InFptr);\r
+  return STATUS_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/FlashMap/FlashDefFile.h b/Tools/Source/TianoTools/FlashMap/FlashDefFile.h
new file mode 100644 (file)
index 0000000..1ffbfb1
--- /dev/null
@@ -0,0 +1,281 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  FlashDefFile.h\r
+\r
+Abstract:\r
+\r
+  Header file for flash management utility in the Intel Platform \r
+  Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#ifndef _FLASH_DEF_FILE_H_\r
+#define _FLASH_DEF_FILE_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+void\r
+FDFConstructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+FDFDestructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFParseFile (\r
+  char    *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileName  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateCIncludeFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+  FileName        - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateCFlashMapDataFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+  FileName        - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateAsmIncludeFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+  FileName        - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFParseFile (\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileName  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateImage (\r
+  char      *FlashDeviceName,\r
+  char      *ImageName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+  ImageName       - GC_TODO: add argument description\r
+  FileName        - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateDscFile (\r
+  char      *FlashDeviceName,\r
+  char      *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+  FileName        - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDFCreateSymbols (\r
+  char      *FlashDeviceName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FlashDeviceName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+FDDiscover (\r
+  char          *FDFileName,\r
+  unsigned int  BaseAddr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FDFileName  - GC_TODO: add argument description\r
+  BaseAddr    - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // #ifndef _FLASH_DEF_FILE_H_\r
diff --git a/Tools/Source/TianoTools/FlashMap/FlashMap.c b/Tools/Source/TianoTools/FlashMap/FlashMap.c
new file mode 100644 (file)
index 0000000..86e26b6
--- /dev/null
@@ -0,0 +1,745 @@
+/*++\r
+\r
+Copyright (c)  2004-2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  FlashMap.c\r
+\r
+Abstract:\r
+\r
+  Utility for flash management in the Intel Platform Innovation Framework\r
+  for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"\r
+\r
+#ifndef INT8\r
+#define INT8  char\r
+#endif\r
+\r
+#include "EfiUtilityMsgs.h"\r
+#include "Microcode.h"\r
+#include "FlashDefFile.h"\r
+#include "Symbols.h"\r
+\r
+#define UTILITY_NAME  "FlashMap"\r
+\r
+typedef struct _STRING_LIST {\r
+  struct _STRING_LIST *Next;\r
+  char                *Str;\r
+} STRING_LIST;\r
+\r
+//\r
+// Keep our globals in one of these structures\r
+//\r
+static struct {\r
+  char          *CIncludeFileName;\r
+  char          *FlashDevice;\r
+  char          *FlashDeviceImage;\r
+  char          *MCIFileName;\r
+  char          *MCOFileName;\r
+  char          *ImageOutFileName;\r
+  char          *DscFileName;\r
+  char          *AsmIncludeFileName;\r
+  char          *FlashDefinitionFileName;\r
+  char          *StringReplaceInFileName;\r
+  char          *StringReplaceOutFileName;\r
+  char          *DiscoverFDImageName;\r
+  char          MicrocodePadByteValue;\r
+  unsigned int  MicrocodeAlignment;\r
+  STRING_LIST   *MCIFileNames;\r
+  STRING_LIST   *LastMCIFileNames;\r
+  unsigned int  BaseAddress;\r
+} mGlobals;\r
+\r
+#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF\r
+#define DEFAULT_MC_ALIGNMENT      16\r
+\r
+static\r
+STATUS\r
+ProcessCommandLine (\r
+  int     argc,\r
+  char    *argv[]\r
+  );\r
+\r
+static\r
+STATUS\r
+MergeMicrocodeFiles (\r
+  char            *OutFileName,\r
+  STRING_LIST     *FileNames,\r
+  unsigned int    Alignment,\r
+  char            PadByteValue\r
+  );\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+int\r
+main (\r
+  int   argc,\r
+  char  *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse the command line arguments and then call worker functions to do the work\r
+  \r
+Arguments:\r
+  argc      - number of elements in argv\r
+  argv      - array of command-line arguments\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no problems encountered while processing\r
+  STATUS_WARNING    - warnings, but no errors, were encountered while processing\r
+  STATUS_ERROR      - errors were encountered while processing\r
+  \r
+--*/\r
+{\r
+  STATUS  Status;\r
+\r
+  SetUtilityName (UTILITY_NAME);\r
+  Status = ProcessCommandLine (argc, argv);\r
+  if (Status != STATUS_SUCCESS) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Check for discovery of an FD (command line option)\r
+  //\r
+  if (mGlobals.DiscoverFDImageName != NULL) {\r
+    Status = FDDiscover (mGlobals.DiscoverFDImageName, mGlobals.BaseAddress);\r
+    goto Done;\r
+  }\r
+  //\r
+  // If they're doing microcode file parsing, then do that\r
+  //\r
+  if (mGlobals.MCIFileName != NULL) {\r
+    MicrocodeConstructor ();\r
+    MicrocodeParseFile (mGlobals.MCIFileName, mGlobals.MCOFileName);\r
+    MicrocodeDestructor ();\r
+  }\r
+  //\r
+  // If they're doing microcode file merging, then do that now\r
+  //\r
+  if (mGlobals.MCIFileNames != NULL) {\r
+    MergeMicrocodeFiles (\r
+      mGlobals.MCOFileName,\r
+      mGlobals.MCIFileNames,\r
+      mGlobals.MicrocodeAlignment,\r
+      mGlobals.MicrocodePadByteValue\r
+      );\r
+  }\r
+  //\r
+  // If using a flash definition file, then process that and return\r
+  //\r
+  if (mGlobals.FlashDefinitionFileName != NULL) {\r
+    FDFConstructor ();\r
+    SymbolsConstructor ();\r
+    Status = FDFParseFile (mGlobals.FlashDefinitionFileName);\r
+    if (GetUtilityStatus () != STATUS_ERROR) {\r
+      //\r
+      // If they want us to do a string-replace on a file, then add the symbol definitions to\r
+      // the symbol table, and then do the string replace.\r
+      //\r
+      if (mGlobals.StringReplaceInFileName != NULL) {\r
+        Status  = FDFCreateSymbols (mGlobals.FlashDevice);\r
+        Status  = SymbolsFileStringsReplace (mGlobals.StringReplaceInFileName, mGlobals.StringReplaceOutFileName);\r
+      }\r
+      //\r
+      // If they want us to create a .h defines file or .c flashmap data file, then do so now\r
+      //\r
+      if (mGlobals.CIncludeFileName != NULL) {\r
+        Status = FDFCreateCIncludeFile (mGlobals.FlashDevice, mGlobals.CIncludeFileName);\r
+      }\r
+      if (mGlobals.AsmIncludeFileName != NULL) {\r
+        Status = FDFCreateAsmIncludeFile (mGlobals.FlashDevice, mGlobals.AsmIncludeFileName);\r
+      }\r
+      //\r
+      // If they want us to create an image, do that now\r
+      //\r
+      if (mGlobals.ImageOutFileName != NULL) {\r
+        Status = FDFCreateImage (mGlobals.FlashDevice, mGlobals.FlashDeviceImage, mGlobals.ImageOutFileName);\r
+      }\r
+      //\r
+      // If they want to create an output DSC file, do that now\r
+      //\r
+      if (mGlobals.DscFileName != NULL) {\r
+        Status = FDFCreateDscFile (mGlobals.FlashDevice, mGlobals.DscFileName);\r
+      }\r
+    }\r
+    SymbolsDestructor ();\r
+    FDFDestructor ();\r
+  }\r
+Done:\r
+  //\r
+  // Free up memory\r
+  //\r
+  while (mGlobals.MCIFileNames != NULL) {\r
+    mGlobals.LastMCIFileNames = mGlobals.MCIFileNames->Next;\r
+    _free (mGlobals.MCIFileNames);\r
+    mGlobals.MCIFileNames = mGlobals.LastMCIFileNames;\r
+  }\r
+  return GetUtilityStatus ();\r
+}\r
+\r
+static\r
+STATUS\r
+MergeMicrocodeFiles (\r
+  char            *OutFileName,\r
+  STRING_LIST     *FileNames,\r
+  unsigned int    Alignment,\r
+  char            PadByteValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Merge binary microcode files into a single file, taking into consideration\r
+  the alignment and pad value.\r
+\r
+Arguments:\r
+\r
+  OutFileName     - name of the output file to create\r
+  FileNames       - linked list of input microcode files to merge\r
+  Alignment       - alignment for each microcode file in the output image\r
+  PadByteValue    - value to use when padding to meet alignment requirements\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS  - merge completed successfully or with acceptable warnings\r
+  STATUS_ERROR    - merge failed, output file not created\r
+\r
+--*/\r
+{\r
+  long    FileSize;\r
+  long    TotalFileSize;\r
+  FILE    *InFptr;\r
+  FILE    *OutFptr;\r
+  char    *Buffer;\r
+  STATUS  Status;\r
+\r
+  //\r
+  // Open the output file\r
+  //\r
+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Walk the list of files\r
+  //\r
+  Status        = STATUS_ERROR;\r
+  Buffer        = NULL;\r
+  InFptr        = NULL;\r
+  TotalFileSize = 0;\r
+  while (FileNames != NULL) {\r
+    //\r
+    // Open the file, determine the size, then read it in and write\r
+    // it back out.\r
+    //\r
+    if ((InFptr = fopen (FileNames->Str, "rb")) == NULL) {\r
+      Error (NULL, 0, 0, FileNames->Str, "failed to open input file for reading");\r
+      goto Done;\r
+    }\r
+    fseek (InFptr, 0, SEEK_END);\r
+    FileSize = ftell (InFptr);\r
+    fseek (InFptr, 0, SEEK_SET);\r
+    if (FileSize != 0) {\r
+      Buffer = (char *) _malloc (FileSize);\r
+      if (Buffer == NULL) {\r
+        Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+        goto Done;\r
+      }\r
+      if (fread (Buffer, FileSize, 1, InFptr) != 1) {\r
+        Error (NULL, 0, 0, FileNames->Str, "failed to read file contents");\r
+        goto Done;\r
+      }\r
+      //\r
+      // Align\r
+      //\r
+      if (Alignment != 0) {\r
+        while ((TotalFileSize % Alignment) != 0) {\r
+          if (fwrite (&PadByteValue, 1, 1, OutFptr) != 1) {\r
+            Error (NULL, 0, 0, OutFileName, "failed to write pad bytes to output file");\r
+            goto Done;\r
+          }\r
+          TotalFileSize++;\r
+        }\r
+      }\r
+      TotalFileSize += FileSize;\r
+      if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, OutFileName, "failed to write to output file");\r
+        goto Done;\r
+      }\r
+      _free (Buffer);\r
+      Buffer = NULL;\r
+    } else {\r
+      Warning (NULL, 0, 0, FileNames->Str, "0-size file encountered");\r
+    }\r
+    fclose (InFptr);\r
+    InFptr    = NULL;\r
+    FileNames = FileNames->Next;\r
+  }\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  fclose (OutFptr);\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+  if (Buffer != NULL) {\r
+    _free (Buffer);\r
+  }\r
+  if (Status == STATUS_ERROR) {\r
+    remove (OutFileName);\r
+  }\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessCommandLine (\r
+  int   argc,\r
+  char  *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Process the command line arguments\r
+  \r
+Arguments:\r
+  argc   - Standard C entry point arguments\r
+  argv[] - Standard C entry point arguments\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no problems encountered while processing\r
+  STATUS_WARNING    - warnings, but no errors, were encountered while processing\r
+  STATUS_ERROR      - errors were encountered while processing\r
+  \r
+--*/\r
+{\r
+  int           ThingsToDo;\r
+  unsigned int  Temp;\r
+  STRING_LIST   *Str;\r
+  //\r
+  // Skip program name arg, process others\r
+  //\r
+  argc--;\r
+  argv++;\r
+  if (argc == 0) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Clear out our globals, then start walking the arguments\r
+  //\r
+  memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
+  mGlobals.MicrocodePadByteValue  = DEFAULT_MC_PAD_BYTE_VALUE;\r
+  mGlobals.MicrocodeAlignment     = DEFAULT_MC_ALIGNMENT;\r
+  ThingsToDo                      = 0;\r
+  while (argc > 0) {\r
+    if (strcmp (argv[0], "-?") == 0) {\r
+      Usage ();\r
+      return STATUS_ERROR;\r
+    } else if (strcmp (argv[0], "-hfile") == 0) {\r
+      //\r
+      // -hfile FileName\r
+      //\r
+      // Used to specify an output C #include file to create that contains\r
+      // #define statements for all the flashmap region offsets and sizes.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an output file name");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.CIncludeFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-flashdevice") == 0) {\r
+      //\r
+      // -flashdevice FLASH_DEVICE_NAME\r
+      //\r
+      // Used to select which flash device definition to operate on.\r
+      // Check for additional argument\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires a flash device name to use");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.FlashDevice = argv[0];\r
+    } else if (strcmp (argv[0], "-mco") == 0) {\r
+      //\r
+      // -mco OutFileName\r
+      //\r
+      // Used to specify a microcode output binary file to create.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an output microcode file name to create");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.MCOFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-asmincfile") == 0) {\r
+      //\r
+      // -asmincfile FileName\r
+      //\r
+      // Used to specify the name of the output assembly include file that contains\r
+      // equates for the flash region addresses and sizes.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an output ASM include file name to create");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.AsmIncludeFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-mci") == 0) {\r
+      //\r
+      // -mci FileName\r
+      //\r
+      // Used to specify an input microcode text file to parse.\r
+      // Check for additional argument\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, (INT8 *) argv[0], (INT8 *) "option requires an input microcode text file name to parse");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.MCIFileName = argv[0];\r
+    } else if (strcmp (argv[0], "-flashdeviceimage") == 0) {\r
+      //\r
+      // -flashdeviceimage FlashDeviceImage\r
+      //\r
+      // Used to specify which flash device image definition from the input flash definition file\r
+      // to create.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires the name of a flash definition image to use");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.FlashDeviceImage = argv[0];\r
+    } else if (strcmp (argv[0], "-imageout") == 0) {\r
+      //\r
+      // -imageout FileName\r
+      //\r
+      // Used to specify the name of the output FD image file to create.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an output image filename to create");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.ImageOutFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-dsc") == 0) {\r
+      //\r
+      // -dsc FileName\r
+      //\r
+      // Used to specify the name of the output DSC file to create.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an output DSC filename to create");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.DscFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-fdf") == 0) {\r
+      //\r
+      // -fdf FileName\r
+      //\r
+      // Used to specify the name of the input flash definition file.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an input flash definition file name");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.FlashDefinitionFileName = argv[0];\r
+    } else if (strcmp (argv[0], "-discover") == 0) {\r
+      //\r
+      // -discover FDFileName\r
+      //\r
+      // Debug functionality used to scan an existing FD image, trying to find\r
+      // firmware volumes at 64K boundaries.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an input FD image file name");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.DiscoverFDImageName = argv[0];\r
+      ThingsToDo++;\r
+    } else if (strcmp (argv[0], "-baseaddr") == 0) {\r
+      //\r
+      // -baseaddr Addr\r
+      //\r
+      // Used to specify a base address when doing a discover of an FD image.\r
+      // Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires a base address");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      if (tolower (argv[0][1]) == 'x') {\r
+        sscanf (argv[0] + 2, "%x", &mGlobals.BaseAddress);\r
+      } else {\r
+        sscanf (argv[0], "%d", &mGlobals.BaseAddress);\r
+      }\r
+    } else if (strcmp (argv[0], "-padvalue") == 0) {\r
+      //\r
+      // -padvalue Value\r
+      //\r
+      // Used to specify the value to pad with when aligning data while\r
+      // creating an FD image. Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires a byte value");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      if (tolower (argv[0][1]) == 'x') {\r
+        sscanf (argv[0] + 2, "%x", &Temp);\r
+        mGlobals.MicrocodePadByteValue = (char) Temp;\r
+      } else {\r
+        sscanf (argv[0], "%d", &Temp);\r
+        mGlobals.MicrocodePadByteValue = (char) Temp;\r
+      }\r
+    } else if (strcmp (argv[0], "-align") == 0) {\r
+      //\r
+      // -align Alignment\r
+      //\r
+      // Used to specify how each data file is aligned in the region\r
+      // when creating an FD image. Check for additional argument.\r
+      //\r
+      if (argc < 2) {\r
+        Error (NULL, 0, 0, argv[0], "option requires an alignment");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      if (tolower (argv[0][1]) == 'x') {\r
+        sscanf (argv[0] + 2, "%x", &mGlobals.MicrocodeAlignment);\r
+      } else {\r
+        sscanf (argv[0], "%d", &mGlobals.MicrocodeAlignment);\r
+      }\r
+    } else if (strcmp (argv[0], "-mcmerge") == 0) {\r
+      //\r
+      // -mcmerge FileName(s)\r
+      //\r
+      // Used to concatenate multiple microde binary files. Can specify\r
+      // multiple file names with the one -mcmerge flag. Check for additional argument.\r
+      //\r
+      if ((argc < 2) || (argv[1][0] == '-')) {\r
+        Error (NULL, 0, 0, argv[0], "option requires one or more input file names");\r
+        return STATUS_ERROR;\r
+      }\r
+      //\r
+      // Take input files until another option or end of list\r
+      //\r
+      ThingsToDo++;\r
+      while ((argc > 1) && (argv[1][0] != '-')) {\r
+        Str = (STRING_LIST *) _malloc (sizeof (STRING_LIST));\r
+        if (Str == NULL) {\r
+          Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+          return STATUS_ERROR;\r
+        }\r
+        memset (Str, 0, sizeof (STRING_LIST));\r
+        Str->Str = argv[1];\r
+        if (mGlobals.MCIFileNames == NULL) {\r
+          mGlobals.MCIFileNames = Str;\r
+        } else {\r
+          mGlobals.LastMCIFileNames->Next = Str;\r
+        }\r
+        mGlobals.LastMCIFileNames = Str;\r
+        argc--;\r
+        argv++;\r
+      }\r
+    } else if (strcmp (argv[0], "-strsub") == 0) {\r
+      //\r
+      // -strsub SrcFile DestFile\r
+      //\r
+      // Used to perform string substitutions on a file, writing the result to a new\r
+      // file. Check for two additional arguments.\r
+      //\r
+      if (argc < 3) {\r
+        Error (NULL, 0, 0, argv[0], "option requires input and output file names for string substitution");\r
+        return STATUS_ERROR;\r
+      }\r
+      argc--;\r
+      argv++;\r
+      mGlobals.StringReplaceInFileName = argv[0];\r
+      argc--;\r
+      argv++;\r
+      mGlobals.StringReplaceOutFileName = argv[0];\r
+      ThingsToDo++;\r
+    } else {\r
+      Error (NULL, 0, 0, argv[0], "invalid option");\r
+      return STATUS_ERROR;\r
+    }\r
+    argc--;\r
+    argv++;\r
+  }\r
+  //\r
+  // If no outputs requested, then report an error\r
+  //\r
+  if (ThingsToDo == 0) {\r
+    Error (NULL, 0, 0, "nothing to do", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If they want an asm file, #include file, or C file to be created, then they have to specify a\r
+  // flash device name and flash definition file name.\r
+  //\r
+  if ((mGlobals.CIncludeFileName != NULL) &&\r
+      ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {\r
+    Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -hfile", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  if ((mGlobals.AsmIncludeFileName != NULL) &&\r
+      ((mGlobals.FlashDevice == NULL) || (mGlobals.FlashDefinitionFileName == NULL))) {\r
+    Error (NULL, 0, 0, "must specify -flashdevice and -fdf with -asmincfile", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If they want a dsc file to be created, then they have to specify a\r
+  // flash device name and a flash definition file name\r
+  //\r
+  if (mGlobals.DscFileName != NULL) {\r
+    if (mGlobals.FlashDevice == NULL) {\r
+      Error (NULL, 0, 0, "must specify -flashdevice with -dsc", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+    if (mGlobals.FlashDefinitionFileName == NULL) {\r
+      Error (NULL, 0, 0, "must specify -fdf with -dsc", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+  }\r
+  //\r
+  // If they specified an output microcode file name, then they have to specify an input\r
+  // file name, and vice versa.\r
+  //\r
+  if ((mGlobals.MCIFileName != NULL) && (mGlobals.MCOFileName == NULL)) {\r
+    Error (NULL, 0, 0, "must specify output microcode file name", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  if ((mGlobals.MCOFileName != NULL) && (mGlobals.MCIFileName == NULL) && (mGlobals.MCIFileNames == NULL)) {\r
+    Error (NULL, 0, 0, "must specify input microcode file name", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If doing merge, then have to specify output file name\r
+  //\r
+  if ((mGlobals.MCIFileNames != NULL) && (mGlobals.MCOFileName == NULL)) {\r
+    Error (NULL, 0, 0, "must specify output microcode file name", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If they want an output image to be created, then they have to specify\r
+  // the flash device and the flash device image to use.\r
+  //\r
+  if (mGlobals.ImageOutFileName != NULL) {\r
+    if (mGlobals.FlashDevice == NULL) {\r
+      Error (NULL, 0, 0, "must specify -flashdevice with -imageout", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+    if (mGlobals.FlashDeviceImage == NULL) {\r
+      Error (NULL, 0, 0, "must specify -flashdeviceimage with -imageout", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+    if (mGlobals.FlashDefinitionFileName == NULL) {\r
+      Error (NULL, 0, 0, "must specify -c or -fdf with -imageout", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+  }\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Print utility command line help\r
+  \r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  NA\r
+\r
+--*/\r
+{\r
+  int   i;\r
+  char  *Msg[] = {\r
+    "Usage: FlashTool -fdf FlashDefFile -flashdevice FlashDevice",\r
+    "                 -flashdeviceimage FlashDeviceImage -mci MCIFile -mco MCOFile",\r
+    "                 -discover FDImage -dsc DscFile -asmincfile AsmIncFile",\r
+    "                 -imageOut ImageOutFile -hfile HFile -strsub InStrFile OutStrFile",\r
+    "                 -baseaddr BaseAddr -align Alignment -padvalue PadValue",\r
+    "                 -mcmerge MCIFile(s)",\r
+    "  where",\r
+    "    FlashDefFile     - input Flash Definition File",\r
+    "    FlashDevice      - flash device to use (from flash definition file)",\r
+    "    FlashDeviceImage - flash device image to use (from flash definition file)",\r
+    "    MCIFile          - input microcode file to parse",\r
+    "    MCOFile          - output binary microcode image to create from MCIFile",\r
+    "    HFile            - output #include file to create",\r
+    "    FDImage          - name of input FDImage file to scan",\r
+    "    ImageOutFile     - output image file to create",\r
+    "    DscFile          - output DSC file to create",\r
+    "    AsmIncFile       - output ASM include file to create",\r
+    "    InStrFile        - input file to replace symbol names, writing result to OutStrFile",\r
+    "    BaseAddr         - base address of FDImage (used with -discover)",\r
+    "    Alignment        - alignment to use when merging microcode binaries",\r
+    "    PadValue         - byte value to use as pad value when aligning microcode binaries",\r
+    "    MCIFile(s)       - one or more microcode binary files to merge/concatenate",\r
+    "",\r
+    NULL\r
+  };\r
+  for (i = 0; Msg[i] != NULL; i++) {\r
+    fprintf (stdout, "%s\n", Msg[i]);\r
+  }\r
+}\r
diff --git a/Tools/Source/TianoTools/FlashMap/Makefile b/Tools/Source/TianoTools/FlashMap/Makefile
new file mode 100644 (file)
index 0000000..6b6d011
--- /dev/null
@@ -0,0 +1,81 @@
+#/*++\r
+#  \r
+#  Copyright (c) 2004 Intel Corporation. All rights reserved\r
+#  This software and associated documentation (if any) is furnished\r
+#  under a license and may only be used or copied in accordance\r
+#  with the terms of the license. Except as permitted by such\r
+#  license, no part of this software or documentation may be\r
+#  reproduced, stored in a retrieval system, or transmitted in any\r
+#  form or by any means without the express written consent of\r
+#  Intel Corporation.\r
+#  \r
+#  \r
+#  Module Name:\r
+#  \r
+#    Makefile\r
+#  \r
+#  Abstract:\r
+#  \r
+#    makefile for building the FlashMap utility\r
+#    \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+INCLUDE_PATHS = -I $(TIANO_TOOLS_SOURCE)\Common\r
+\r
+#\r
+# Target specific information\r
+#\r
+TARGET_NAME         = FlashMap\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\FlashMap.exe\r
+LIBS                = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib"\r
+\r
+#\r
+# Build targets\r
+#\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\FlashMap.obj  \\r
+            $(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj \\r
+            $(TIANO_TOOLS_OUTPUT)\Symbols.obj \\r
+            $(TIANO_TOOLS_OUTPUT)\Microcode.obj \r
+            \r
+#            $(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj \r
\r
+#C_FLAGS  = $(C_FLAGS) /D TRACK_MALLOC_FREE\r
+C_FLAGS   = $(C_FLAGS) /D _malloc=malloc /D _free=free\r
+           \r
+#\r
+# Compile each source file\r
+#\r
+$(TIANO_TOOLS_OUTPUT)\FlashMap.obj : $(TARGET_SRC_DIR)\FlashMap.c $(TARGET_SRC_DIR)\Symbols.h $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\FlashMap.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\Symbols.obj : $(TARGET_SRC_DIR)\Symbols.c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(INCLUDE_PATHS) $(TARGET_SRC_DIR)\Symbols.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\Microcode.obj : $(TARGET_SRC_DIR)\Microcode.c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\Microcode.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\FlashDefFile.obj : $(TARGET_SRC_DIR)\FlashDefFile.c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\FlashDefFile.c /Fo$@\r
+\r
+$(TIANO_TOOLS_OUTPUT)\TrackMallocFree.obj : $(TARGET_SRC_DIR)\TrackMallocFree.c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\TrackMallocFree.c /Fo$@\r
+\r
+#\r
+# Link the object files together to create the final executable\r
+#\r
+$(TARGET_EXE) : $(OBJECTS) $(LIBS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
diff --git a/Tools/Source/TianoTools/FlashMap/Microcode.c b/Tools/Source/TianoTools/FlashMap/Microcode.c
new file mode 100644 (file)
index 0000000..51ae20e
--- /dev/null
@@ -0,0 +1,306 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  Microcode.c\r
+\r
+Abstract:\r
+\r
+  Utility for working with microcode patch files in the Intel \r
+  Platform Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h> // for memset()\r
+#include <ctype.h>\r
+#include <stdlib.h> // for malloc()\r
+#define INT8    char\r
+#define UINT32  unsigned int\r
+\r
+#include "EfiUtilityMsgs.h"\r
+#include "Microcode.h"\r
+\r
+#define MAX_LINE_LEN  256\r
+\r
+//\r
+// Structure definition for a microcode header\r
+//\r
+typedef struct {\r
+  unsigned int  HeaderVersion;\r
+  unsigned int  PatchId;\r
+  unsigned int  Date;\r
+  unsigned int  CpuId;\r
+  unsigned int  Checksum;\r
+  unsigned int  LoaderVersion;\r
+  unsigned int  PlatformId;\r
+  unsigned int  DataSize;   // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
+  unsigned int  TotalSize;  // number of bytes\r
+  unsigned int  Reserved[3];\r
+} MICROCODE_IMAGE_HEADER;\r
+\r
+static\r
+STATUS\r
+MicrocodeReadData (\r
+  FILE          *InFptr,\r
+  unsigned int  *Data\r
+  );\r
+\r
+void\r
+MicrocodeConstructor (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Constructor of module Microcode\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+}\r
+\r
+void\r
+MicrocodeDestructor (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Destructor of module Microcode\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+}\r
+\r
+static\r
+STATUS\r
+MicrocodeReadData (\r
+  FILE          *InFptr,\r
+  unsigned int  *Data\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
+\r
+Arguments:\r
+  InFptr    - file pointer to input text file\r
+  Data      - pointer to where to return the data parsed\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings, Data contains valid information\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  char  Line[MAX_LINE_LEN];\r
+  char  *cptr;\r
+\r
+  Line[MAX_LINE_LEN - 1]  = 0;\r
+  *Data                   = 0;\r
+  if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If it was a binary file, then it may have overwritten our null terminator\r
+  //\r
+  if (Line[MAX_LINE_LEN - 1] != 0) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Look for\r
+  // dd 000000001h ; comment\r
+  // dd XXXXXXXX\r
+  // DD  XXXXXXXXX\r
+  //  DD XXXXXXXXX\r
+  //\r
+  for (cptr = Line; *cptr && isspace(*cptr); cptr++) {\r
+  }\r
+  if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {\r
+    //\r
+    // Skip blanks and look for a hex digit\r
+    //\r
+    cptr += 3;\r
+    for (; *cptr && isspace(*cptr); cptr++) {\r
+    }\r
+    if (isxdigit (*cptr)) {\r
+      if (sscanf (cptr, "%X", Data) != 1) {\r
+        return STATUS_ERROR;\r
+      }\r
+    }\r
+    return STATUS_SUCCESS;\r
+  }\r
+  return STATUS_ERROR;\r
+}\r
+\r
+STATUS\r
+MicrocodeParseFile (\r
+  char  *InFileName,\r
+  char  *OutFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse a microcode text file, and write the binary results to an output file.\r
+\r
+Arguments:\r
+  InFileName  - input text file to parse\r
+  OutFileName - output file to write raw binary data from parsed input file\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+{\r
+  FILE                    *InFptr;\r
+  FILE                    *OutFptr;\r
+  STATUS                  Status;\r
+  MICROCODE_IMAGE_HEADER  *Header;\r
+  unsigned int            Size;\r
+  unsigned int            Size2;\r
+  unsigned int            Data;\r
+  unsigned int            Checksum;\r
+  char                    *Buffer;\r
+  char                    *Ptr;\r
+  unsigned int            TotalSize;\r
+\r
+  Status  = STATUS_ERROR;\r
+  InFptr  = NULL;\r
+  OutFptr = NULL;\r
+  Buffer  = NULL;\r
+  //\r
+  // Open the input text file\r
+  //\r
+  if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
+    Error (NULL, 0, 0, InFileName, "failed to open input microcode file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Make two passes on the input file. The first pass is to determine how\r
+  // much data is in the file so we can allocate a working buffer. Then\r
+  // we'll allocate a buffer and re-read the file into the buffer for processing.\r
+  //\r
+  Size = 0;\r
+  do {\r
+    Status = MicrocodeReadData (InFptr, &Data);\r
+    if (Status == STATUS_SUCCESS) {\r
+      Size += sizeof (Data);\r
+    }\r
+  } while (Status == STATUS_SUCCESS);\r
+  //\r
+  // Error if no data.\r
+  //\r
+  if (Size == 0) {\r
+    Error (NULL, 0, 0, InFileName, "no parse-able data found in file");\r
+    goto Done;\r
+  }\r
+  if (Size < sizeof (MICROCODE_IMAGE_HEADER)) {\r
+    Error (NULL, 0, 0, InFileName, "amount of parse-able data is insufficient to contain a microcode header");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Allocate a buffer for the data\r
+  //\r
+  Buffer = (char *) _malloc (Size);\r
+  if (Buffer == NULL) {\r
+    Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+    goto Done;\r
+  }\r
+  //\r
+  // Re-read the file, storing the data into our buffer\r
+  //\r
+  fseek (InFptr, 0, SEEK_SET);\r
+  Ptr = Buffer;\r
+  do {\r
+    Status = MicrocodeReadData (InFptr, &Data);\r
+    if (Status == STATUS_SUCCESS) {\r
+      *(unsigned int *) Ptr = Data;\r
+      Ptr += sizeof (Data);\r
+    }\r
+  } while (Status == STATUS_SUCCESS);\r
+  //\r
+  // Can't do much checking on the header because, per the spec, the\r
+  // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
+  // and the TotalSize field is invalid (actually missing). Thus we can't\r
+  // even verify the Reserved fields are 0.\r
+  //\r
+  Header = (MICROCODE_IMAGE_HEADER *) Buffer;\r
+  if (Header->DataSize == 0) {\r
+    TotalSize = 2048;\r
+  } else {\r
+    TotalSize = Header->TotalSize;\r
+  }\r
+  if (TotalSize != Size) {\r
+    Error (NULL, 0, 0, InFileName, "file contents do not contain expected TotalSize 0x%04X", TotalSize);\r
+    goto Done;\r
+  }\r
+  //\r
+  // Checksum the contents\r
+  //\r
+  Ptr       = Buffer;\r
+  Checksum  = 0;\r
+  Size2     = 0;\r
+  while (Size2 < Size) {\r
+    Checksum += *(unsigned int *) Ptr;\r
+    Ptr += 4;\r
+    Size2 += 4;\r
+  }\r
+  if (Checksum != 0) {\r
+    Error (NULL, 0, 0, InFileName, "checksum failed on file contents");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Open the output file and write the buffer contents\r
+  //\r
+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to open output microcode file for writing");\r
+    goto Done;\r
+  }\r
+  if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to write microcode data to output file");\r
+    goto Done;\r
+  }\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+    if (Status == STATUS_ERROR) {\r
+      remove (OutFileName);\r
+    }\r
+  }\r
+  return Status;\r
+}\r
diff --git a/Tools/Source/TianoTools/FlashMap/Microcode.h b/Tools/Source/TianoTools/FlashMap/Microcode.h
new file mode 100644 (file)
index 0000000..5f5a13e
--- /dev/null
@@ -0,0 +1,87 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  Microcode.h\r
+\r
+Abstract:\r
+\r
+  Header file for flash management utility in the Intel Platform \r
+  Innovation Framework for EFI build environment.\r
+\r
+--*/\r
+\r
+#ifndef _MICROCODE_H_\r
+#define _MICROCODE_H_\r
+\r
+void\r
+MicrocodeConstructor (\r
+  void\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Constructor of module Microcode\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+void\r
+MicrocodeDestructor (\r
+  void\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Destructor of module Microcode\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+STATUS\r
+MicrocodeParseFile (\r
+  char  *InFileName,\r
+  char  *OutFileName\r
+  );\r
+/*++\r
+\r
+Routine Description:\r
+  Parse a microcode text file, and write the binary results to an output file.\r
+\r
+Arguments:\r
+  InFileName  - input text file to parse\r
+  OutFileName - output file to write raw binary data from parsed input file\r
+\r
+Returns:\r
+  STATUS_SUCCESS    - no errors or warnings\r
+  STATUS_ERROR      - errors were encountered\r
+\r
+--*/\r
+\r
+\r
+#endif // #ifndef _MICROCODE_H_\r
diff --git a/Tools/Source/TianoTools/FlashMap/Symbols.c b/Tools/Source/TianoTools/FlashMap/Symbols.c
new file mode 100644 (file)
index 0000000..471128a
--- /dev/null
@@ -0,0 +1,647 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  Symbol.c\r
+\r
+Abstract:\r
+\r
+  Class-like implementation for a symbol table.\r
+\r
+--*/\r
+\r
+// GC_TODO: fix comment to set correct module name: Symbols.c\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+//\r
+// for isspace()\r
+//\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiUtilityMsgs.h"\r
+#include "Symbols.h"\r
+\r
+#define MAX_LINE_LEN  512\r
+\r
+//\r
+// Linked list to keep track of all symbols\r
+//\r
+typedef struct _SYMBOL {\r
+  struct _SYMBOL  *Next;\r
+  int             Type;\r
+  char            *Name;\r
+  char            *Value;\r
+} SYMBOL;\r
+\r
+static\r
+SYMBOL        *\r
+FreeSymbols (\r
+  SYMBOL *Syms\r
+  );\r
+\r
+static\r
+int\r
+ExpandMacros (\r
+  char  *SourceLine,\r
+  char  *DestLine,\r
+  int   LineLen\r
+  );\r
+\r
+static SYMBOL *mSymbolTable = NULL;\r
+\r
+void\r
+SymbolsConstructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  SymbolsDestructor ();\r
+}\r
+\r
+void\r
+SymbolsDestructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  mSymbolTable = FreeSymbols (mSymbolTable);\r
+}\r
+\r
+char *\r
+GetSymbolValue (\r
+  char *SymbolName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Look up a symbol in our symbol table.\r
+\r
+Arguments:\r
+\r
+  SymbolName\r
+\r
+Returns:\r
+\r
+  Pointer to the value of the symbol if found\r
+  NULL if the symbol is not found\r
+\r
+--*/\r
+// GC_TODO:    SymbolName - add argument and description to function comment\r
+{\r
+  SYMBOL  *Symbol;\r
+  //\r
+  // Walk the symbol table\r
+  //\r
+  Symbol = mSymbolTable;\r
+  while (Symbol) {\r
+    if (stricmp (SymbolName, Symbol->Name) == 0) {\r
+      return Symbol->Value;\r
+    }\r
+\r
+    Symbol = Symbol->Next;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+int\r
+SymbolAdd (\r
+  char    *Name,\r
+  char    *Value,\r
+  int     Mode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Add a symbol name/value to the symbol table\r
+\r
+Arguments:\r
+\r
+  Name  - name of symbol to add\r
+  Value - value of symbol to add\r
+  Mode  - currrently unused\r
+\r
+Returns:\r
+\r
+  Length of symbol added.\r
+\r
+Notes:\r
+  If Value == NULL, then this routine will assume that the Name field\r
+  looks something like "MySymName = MySymValue", and will try to parse\r
+  it that way and add the symbol name/pair from the string.\r
+\r
+--*/\r
+{\r
+  SYMBOL  *Symbol;\r
+\r
+  SYMBOL  *NewSymbol;\r
+  int     Len;\r
+  char    *Start;\r
+  char    *Cptr;\r
+  char    CSave;\r
+  char    *SaveCptr;\r
+\r
+  Len       = 0;\r
+  SaveCptr  = NULL;\r
+  CSave     = 0;\r
+  //\r
+  // If value pointer is null, then they passed us a line something like:\r
+  //    varname = value, or simply var =\r
+  //\r
+  if (Value == NULL) {\r
+    Start = Name;\r
+    while (*Name && isspace (*Name)) {\r
+      Name++;\r
+    }\r
+\r
+    if (Name == NULL) {\r
+      return -1;\r
+    }\r
+    //\r
+    // Find the end of the name. Either space or a '='.\r
+    //\r
+    for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++)\r
+      ;\r
+    if (Value == NULL) {\r
+      return -1;\r
+    }\r
+    //\r
+    // Look for the '='\r
+    //\r
+    Cptr = Value;\r
+    while (*Value && (*Value != '=')) {\r
+      Value++;\r
+    }\r
+\r
+    if (Value == NULL) {\r
+      return -1;\r
+    }\r
+    //\r
+    // Now truncate the name\r
+    //\r
+    *Cptr = 0;\r
+    //\r
+    // Skip over the = and then any spaces\r
+    //\r
+    Value++;\r
+    while (*Value && isspace (*Value)) {\r
+      Value++;\r
+\r
+    }\r
+    //\r
+    // Find end of string, checking for quoted string\r
+    //\r
+    if (*Value == '\"') {\r
+      Value++;\r
+      for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++)\r
+        ;\r
+    } else {\r
+      for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++)\r
+        ;\r
+    }\r
+    //\r
+    // Null terminate the value string\r
+    //\r
+    CSave     = *Cptr;\r
+    SaveCptr  = Cptr;\r
+    *Cptr     = 0;\r
+    Len       = (int) (Cptr - Start);\r
+  }\r
+  //\r
+  // We now have a symbol name and a value. Look for an existing variable\r
+  // and overwrite it.\r
+  //\r
+  Symbol = mSymbolTable;\r
+  while (Symbol) {\r
+    //\r
+    // Check for symbol name match\r
+    //\r
+    if (stricmp (Name, Symbol->Name) == 0) {\r
+      _free (Symbol->Value);\r
+      Symbol->Value = (char *) _malloc (strlen (Value) + 1);\r
+      if (Symbol->Value == NULL) {\r
+        Error (NULL, 0, 0, NULL, "failed to allocate memory");\r
+        return -1;\r
+      }\r
+\r
+      strcpy (Symbol->Value, Value);\r
+      //\r
+      // If value == "NULL", then make it a 0-length string\r
+      //\r
+      if (stricmp (Symbol->Value, "NULL") == 0) {\r
+        Symbol->Value[0] = 0;\r
+      }\r
+\r
+      return Len;\r
+    }\r
+\r
+    Symbol = Symbol->Next;\r
+  }\r
+  //\r
+  // Does not exist, create a new one\r
+  //\r
+  NewSymbol = (SYMBOL *) _malloc (sizeof (SYMBOL));\r
+  if (NewSymbol == NULL) {\r
+    Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+    return -1;\r
+  }\r
+\r
+  memset ((char *) NewSymbol, 0, sizeof (SYMBOL));\r
+  NewSymbol->Name = (char *) _malloc (strlen (Name) + 1);\r
+  if (NewSymbol->Name == NULL) {\r
+    Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+    _free (NewSymbol);\r
+    return -1;\r
+  }\r
+\r
+  NewSymbol->Value = (char *) _malloc (strlen (Value) + 1);\r
+  if (NewSymbol->Value == NULL) {\r
+    Error (NULL, 0, 0, NULL, "memory allocation failure");\r
+    _free (NewSymbol->Name);\r
+    _free (NewSymbol);\r
+    return -1;\r
+  }\r
+\r
+  strcpy (NewSymbol->Name, Name);\r
+  strcpy (NewSymbol->Value, Value);\r
+  //\r
+  // Remove trailing spaces\r
+  //\r
+  Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1;\r
+  while (Cptr > NewSymbol->Value) {\r
+    if (isspace (*Cptr)) {\r
+      *Cptr = 0;\r
+      Cptr--;\r
+    } else {\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Add it to the head of the list.\r
+  //\r
+  NewSymbol->Next = mSymbolTable;\r
+  mSymbolTable    = NewSymbol;\r
+  //\r
+  // If value == "NULL", then make it a 0-length string\r
+  //\r
+  if (stricmp (NewSymbol->Value, "NULL") == 0) {\r
+    NewSymbol->Value[0] = 0;\r
+  }\r
+  //\r
+  // Restore the terminator we inserted if they passed in var=value\r
+  //\r
+  if (SaveCptr != NULL) {\r
+    *SaveCptr = CSave;\r
+  }\r
+  _free (NewSymbol->Value);\r
+  _free (NewSymbol->Name);\r
+  _free (NewSymbol);\r
+  return Len;\r
+}\r
+\r
+static\r
+STATUS\r
+RemoveSymbol (\r
+  char *Name,\r
+  char SymbolType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Remove a symbol name/value from the symbol table\r
+\r
+Arguments:\r
+\r
+  Name  - name of symbol to remove\r
+  SymbolType - type of symbol to remove\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS - matching symbol found and removed\r
+  STATUS_ERROR   - matching symbol not found in symbol table\r
+\r
+--*/\r
+{\r
+  SYMBOL  *Symbol;\r
+\r
+  SYMBOL  *PrevSymbol;\r
+\r
+  PrevSymbol  = NULL;\r
+  Symbol      = mSymbolTable;\r
+  //\r
+  // Walk the linked list of symbols in the symbol table looking\r
+  // for a match of both symbol name and type.\r
+  //\r
+  while (Symbol) {\r
+    if ((stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) {\r
+      //\r
+      // If the symbol has a value associated with it, free the memory\r
+      // allocated for the value.\r
+      // Then free the memory allocated for the symbols string name.\r
+      //\r
+      if (Symbol->Value) {\r
+        _free (Symbol->Value);\r
+      }\r
+\r
+      _free (Symbol->Name);\r
+      //\r
+      // Link the previous symbol to the next symbol to effectively\r
+      // remove this symbol from the linked list.\r
+      //\r
+      if (PrevSymbol) {\r
+        PrevSymbol->Next = Symbol->Next;\r
+      } else {\r
+        mSymbolTable = Symbol->Next;\r
+      }\r
+\r
+      _free (Symbol);\r
+      return STATUS_SUCCESS;\r
+    }\r
+\r
+    PrevSymbol  = Symbol;\r
+    Symbol      = Symbol->Next;\r
+  }\r
+\r
+  return STATUS_WARNING;\r
+}\r
+\r
+static\r
+SYMBOL *\r
+FreeSymbols (\r
+  SYMBOL *Syms\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Syms  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  SYMBOL  *Next;\r
+  while (Syms) {\r
+    if (Syms->Name != NULL) {\r
+      _free (Syms->Name);\r
+    }\r
+\r
+    if (Syms->Value != NULL) {\r
+      _free (Syms->Value);\r
+    }\r
+\r
+    Next = Syms->Next;\r
+    _free (Syms);\r
+    Syms = Next;\r
+  }\r
+\r
+  return Syms;\r
+}\r
+\r
+static\r
+int\r
+ExpandMacros (\r
+  char  *SourceLine,\r
+  char  *DestLine,\r
+  int   LineLen\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given a line of text, replace all variables of format $(NAME) with values\r
+  from our symbol table.\r
+\r
+Arguments:\r
+\r
+  SourceLine    - input line of text to do symbol replacements on\r
+  DestLine      - on output, SourceLine with symbols replaced\r
+  LineLen       - length of DestLine, so we don't exceed its allocated length\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS - no problems encountered\r
+  STATUS_WARNING - missing closing parenthesis on a symbol reference in SourceLine\r
+  STATUS_ERROR   - memory allocation failure\r
+\r
+--*/\r
+{\r
+  static int  NestDepth = 0;\r
+  char        *FromPtr;\r
+  char        *ToPtr;\r
+  char        *SaveStart;\r
+  char        *Cptr;\r
+  char        *value;\r
+  int         Expanded;\r
+  int         ExpandedCount;\r
+  INT8        *LocalDestLine;\r
+  STATUS      Status;\r
+  int         LocalLineLen;\r
+\r
+  NestDepth++;\r
+  Status        = STATUS_SUCCESS;\r
+  LocalDestLine = (char *) _malloc (LineLen);\r
+  if (LocalDestLine == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  FromPtr = SourceLine;\r
+  ToPtr   = LocalDestLine;\r
+  //\r
+  // Walk the entire line, replacing $(MACRO_NAME).\r
+  //\r
+  LocalLineLen  = LineLen;\r
+  ExpandedCount = 0;\r
+  while (*FromPtr && (LocalLineLen > 0)) {\r
+    if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) {\r
+      //\r
+      // Save the start in case it's undefined, in which case we copy it as-is.\r
+      //\r
+      SaveStart = FromPtr;\r
+      Expanded  = 0;\r
+      //\r
+      // Macro expansion time. Find the end (no spaces allowed)\r
+      //\r
+      FromPtr += 2;\r
+      for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++)\r
+        ;\r
+      if (*Cptr) {\r
+        //\r
+        // Truncate the string at the closing parenthesis for ease-of-use.\r
+        // Then copy the string directly to the destination line in case we don't find\r
+        // a definition for it.\r
+        //\r
+        *Cptr = 0;\r
+        strcpy (ToPtr, SaveStart);\r
+        if ((value = GetSymbolValue (FromPtr)) != NULL) {\r
+          strcpy (ToPtr, value);\r
+          LocalLineLen -= strlen (value);\r
+          ToPtr += strlen (value);\r
+          Expanded = 1;\r
+          ExpandedCount++;\r
+        }\r
+\r
+        if (!Expanded) {\r
+          //\r
+          // Restore closing parenthesis, and advance to next character\r
+          //\r
+          *Cptr   = ')';\r
+          FromPtr = SaveStart + 1;\r
+          ToPtr++;\r
+        } else {\r
+          FromPtr = Cptr + 1;\r
+        }\r
+      } else {\r
+        Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on macro");\r
+        strcpy (ToPtr, FromPtr);\r
+        Status = STATUS_WARNING;\r
+        goto Done;\r
+      }\r
+    } else {\r
+      *ToPtr = *FromPtr;\r
+      FromPtr++;\r
+      ToPtr++;\r
+      LocalLineLen--;\r
+    }\r
+  }\r
+\r
+  if (*FromPtr == 0) {\r
+    *ToPtr = 0;\r
+  }\r
+\r
+  //\r
+  // If we expanded at least one string successfully, then make a recursive call to try again.\r
+  //\r
+  if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (NestDepth < 10)) {\r
+    Status = ExpandMacros (LocalDestLine, DestLine, LineLen);\r
+    _free (LocalDestLine);\r
+    NestDepth = 0;\r
+    return Status;\r
+  }\r
+\r
+Done:\r
+  if (Status != STATUS_ERROR) {\r
+    strcpy (DestLine, LocalDestLine);\r
+  }\r
+\r
+  NestDepth = 0;\r
+  _free (LocalDestLine);\r
+  return Status;\r
+}\r
+\r
+STATUS\r
+SymbolsFileStringsReplace (\r
+  char    *InFileName,\r
+  char    *OutFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given input and output file names, read in the input file, replace variable\r
+  references of format $(NAME) with appropriate values from our symbol table,\r
+  and write the result out to the output file.\r
+\r
+Arguments:\r
+\r
+  InFileName  - name of input text file to replace variable references\r
+  OutFileName - name of output text file to write results to\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS - no problems encountered\r
+  STATUS_ERROR   - failed to open input or output file\r
+\r
+--*/\r
+{\r
+  STATUS  Status;\r
+  FILE    *InFptr;\r
+  FILE    *OutFptr;\r
+  char    Line[MAX_LINE_LEN];\r
+  char    OutLine[MAX_LINE_LEN];\r
+\r
+  Status = STATUS_ERROR;\r
+  //\r
+  // Open input and output files\r
+  //\r
+  InFptr  = NULL;\r
+  OutFptr = NULL;\r
+  if ((InFptr = fopen (InFileName, "r")) == NULL) {\r
+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+    goto Done;\r
+  }\r
+\r
+  if ((OutFptr = fopen (OutFileName, "w")) == NULL) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+    goto Done;\r
+  }\r
+  //\r
+  // Read lines from input file until done\r
+  //\r
+  while (fgets (Line, sizeof (Line), InFptr) != NULL) {\r
+    ExpandMacros (Line, OutLine, sizeof (OutLine));\r
+    fprintf (OutFptr, OutLine);\r
+  }\r
+\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+  }\r
+\r
+  return Status;\r
+}\r
diff --git a/Tools/Source/TianoTools/FlashMap/Symbols.h b/Tools/Source/TianoTools/FlashMap/Symbols.h
new file mode 100644 (file)
index 0000000..1d93910
--- /dev/null
@@ -0,0 +1,125 @@
+/*++\r
+\r
+Copyright (c)  2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  Symbols.h\r
+\r
+Abstract:\r
+\r
+  Defines and prototypes for a class-like symbol table service.\r
+\r
+--*/\r
+\r
+#ifndef _SYMBOLS_H_\r
+#define _SYMBOLS_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C"\r
+{\r
+#endif\r
+\r
+int\r
+SymbolAdd (\r
+  char    *Name,\r
+  char    *Value,\r
+  int     Mode\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Name  - GC_TODO: add argument description\r
+  Value - GC_TODO: add argument description\r
+  Mode  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+STATUS\r
+SymbolsFileStringsReplace (\r
+  char    *InFileName,\r
+  char    *OutFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  InFileName  - GC_TODO: add argument description\r
+  OutFileName - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+SymbolsConstructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+void\r
+SymbolsDestructor (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif // #ifndef _SYMBOLS_H_\r
diff --git a/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c b/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c
new file mode 100644 (file)
index 0000000..6c1ec5f
--- /dev/null
@@ -0,0 +1,542 @@
+/*++\r
+\r
+Copyright (c)  2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  GenAcpiTable.c\r
+  \r
+Abstract:\r
+\r
+  A utility that extracts the .DATA section from a PE/COFF image.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiUtilityMsgs.h"\r
+\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_NAME    "GenAcpiTable"\r
+#define UTILITY_VERSION "v0.11"\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH                  256\r
+#define DEFAULT_OUTPUT_EXTENSION  ".acpi"\r
+\r
+//\r
+// Use this to track our command-line options and globals\r
+//\r
+struct {\r
+  INT8  OutFileName[MAX_PATH];\r
+  INT8  InFileName[MAX_PATH];\r
+} mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+  UINT16  Value;\r
+  INT8    *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP  mMachineTypes[] = {\r
+  EFI_IMAGE_MACHINE_IA32,\r
+  "IA32",\r
+  EFI_IMAGE_MACHINE_IA64,\r
+  "IA64",\r
+  EFI_IMAGE_MACHINE_EBC,\r
+  "EBC",\r
+  0,\r
+  NULL\r
+};\r
+\r
+static STRING_LOOKUP  mSubsystemTypes[] = {\r
+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+  "EFI application",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+  "EFI boot service driver",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+  "EFI runtime driver",\r
+  0,\r
+  NULL\r
+};\r
+//\r
+//  Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+static\r
+STATUS\r
+ParseCommandLine (\r
+  int       Argc,\r
+  char      *Argv[]\r
+  );\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+  INT8      *FileName,\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  INT8      *InFileName,\r
+  INT8      *OutFileName\r
+  );\r
+\r
+static\r
+void\r
+DumpImage (\r
+  INT8      *FileName\r
+  );\r
+\r
+main (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+\r
+  Argv            - standard C main() argument list\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  UINT32  Status;\r
+\r
+  SetUtilityName (UTILITY_NAME);\r
+  //\r
+  // Parse the command line arguments\r
+  //\r
+  if (ParseCommandLine (Argc, Argv)) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Make sure we don't have the same filename for input and output files\r
+  //\r
+  if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
+    Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Process the file\r
+  //\r
+  ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
+Finish:\r
+  Status = GetUtilityStatus ();\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  INT8      *InFileName,\r
+  INT8      *OutFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Process a PE32 EFI file.\r
+\r
+Arguments:\r
+\r
+  InFileName - Name of the PE32 EFI file to process.\r
+  OutFileName - Name of the output file for the processed data.\r
+\r
+Returns:\r
+\r
+  0 - successful\r
+\r
+--*/\r
+{\r
+  STATUS                      Status;\r
+  UINTN                       Index;\r
+  FILE                        *InFptr;\r
+  FILE                        *OutFptr;\r
+  UINT16                      MachineType;\r
+  UINT16                      SubSystem;\r
+  UINT32                      PESigOffset;\r
+  EFI_IMAGE_FILE_HEADER       FileHeader;\r
+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
+  EFI_IMAGE_SECTION_HEADER    SectionHeader;\r
+  UINT8                       *Buffer;\r
+  long                        SaveFilePosition;\r
+\r
+  InFptr  = NULL;\r
+  OutFptr = NULL;\r
+  Buffer  = NULL;\r
+  Status  = STATUS_ERROR;\r
+  //\r
+  // Try to open the input file\r
+  //\r
+  if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Double-check the file to make sure it's what we expect it to be\r
+  //\r
+  if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
+  // offset (from the start of the file) to the PE signature, which always\r
+  // follows the MSDOS stub. The PE signature is immediately followed by the\r
+  // COFF file header.\r
+  //\r
+  //\r
+  if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
+    goto Finish;\r
+  }\r
+\r
+  if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // We should now be at the COFF file header. Read it in and verify it's\r
+  // of an image type we support.\r
+  //\r
+  if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
+    goto Finish;\r
+  }\r
+\r
+  if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {\r
+    Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
+  //\r
+  SaveFilePosition = ftell (InFptr);\r
+  if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {\r
+      Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
+      goto Finish;\r
+    }\r
+\r
+    if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+      goto Finish;\r
+    }\r
+  }\r
+  //\r
+  // Search for the ".data" section\r
+  //\r
+  for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {\r
+    if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+      goto Finish;\r
+    }\r
+\r
+    if (strcmp (SectionHeader.Name, ".data") == 0) {\r
+      if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {\r
+        Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
+        goto Finish;\r
+      }\r
+\r
+      Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);\r
+      if (Buffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Finish;\r
+      }\r
+      if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {\r
+        Error (NULL, 0, 0, InFileName, "failed to .data section");\r
+        goto Finish;\r
+      }\r
+      //\r
+      // Now open our output file\r
+      //\r
+      if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+        Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+        goto Finish;\r
+      }\r
+\r
+      if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, OutFileName, "failed to write .data section");\r
+        goto Finish;\r
+      }\r
+\r
+      Status = STATUS_SUCCESS;\r
+      goto Finish;\r
+    }\r
+  }\r
+\r
+  Status = STATUS_ERROR;\r
+\r
+Finish:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+  //\r
+  // Close the output file. If there was an error, delete the output file so\r
+  // that a subsequent build will rebuild it.\r
+  //\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+    if (GetUtilityStatus () == STATUS_ERROR) {\r
+      remove (OutFileName);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free up our buffer\r
+  //\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+  INT8      *FileName,\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileName    - GC_TODO: add argument description\r
+  Fptr        - GC_TODO: add argument description\r
+  MachineType - GC_TODO: add argument description\r
+  SubSystem   - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  /*++\r
+\r
+Routine Description:\r
+  \r
+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+  PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+  Fptr          File pointer to the already-opened PE32 file\r
+  MachineType   Location to stuff the machine type of the PE32 file. This is needed\r
+                because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+  EFI_IMAGE_DOS_HEADER      DosHeader;\r
+  EFI_IMAGE_FILE_HEADER     FileHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+  UINT32                    PESig;\r
+  STATUS                    Status;\r
+\r
+  Status = STATUS_ERROR;\r
+  //\r
+  // Position to the start of the file\r
+  //\r
+  fseek (Fptr, 0, SEEK_SET);\r
+  //\r
+  // Read the DOS header\r
+  //\r
+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Check the magic number (0x5A4D)\r
+  //\r
+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Position into the file and check the PE signature\r
+  //\r
+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Check the PE signature in the header "PE\0\0"\r
+  //\r
+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read the file header\r
+  //\r
+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read the optional header so we can get the subsystem\r
+  //\r
+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
+    goto Finish;\r
+  }\r
+\r
+  *SubSystem = OptionalHdr.Subsystem;\r
+  //\r
+  // Good to go\r
+  //\r
+  Status = STATUS_SUCCESS;\r
+Finish:\r
+  fseek (Fptr, 0, SEEK_SET);\r
+  return Status;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+  int         Argc,\r
+  char        *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+  parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+  Argv            - standard C main() argument list\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS    success\r
+  non-zero          otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  //\r
+  // Clear out the options\r
+  //\r
+  memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+  //\r
+  // Skip over the program name\r
+  //\r
+  Argc--;\r
+  Argv++;\r
+\r
+  if (Argc != 2) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  strcpy (mOptions.InFileName, Argv[0]);\r
+  //\r
+  // Next argument\r
+  //\r
+  Argv++;\r
+  Argc--;\r
+\r
+  strcpy (mOptions.OutFileName, Argv[0]);\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  Nothing.\r
+\r
+--*/\r
+{\r
+  int               Index;\r
+  static const char *Msg[] = {\r
+    UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",\r
+    "  Generate an ACPI Table image from an EFI PE32 image",\r
+    "  Usage: "UTILITY_NAME " InFileName OutFileName",\r
+    "    where:",\r
+    "      InFileName     - name of the input PE32 file",\r
+    "      OutFileName    - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
+    "",\r
+    NULL\r
+  };\r
+  for (Index = 0; Msg[Index] != NULL; Index++) {\r
+    fprintf (stdout, "%s\n", Msg[Index]);\r
+  }\r
+}\r
diff --git a/Tools/Source/TianoTools/GenAcpiTable/Makefile b/Tools/Source/TianoTools/GenAcpiTable/Makefile
new file mode 100644 (file)
index 0000000..c4df9bc
--- /dev/null
@@ -0,0 +1,68 @@
+#/*++\r
+#  \r
+#  Copyright (c) 2002 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#  \r
+#  Module Name:\r
+#  \r
+#    makefile\r
+#    \r
+#  Abstract:\r
+#  \r
+#    makefile for building the GenAcpiTable utility.\r
+#  \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = GenAcpiTable\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj \r
+\r
+LIBS      = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+INC_DEPS  = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h\r
+          \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c b/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c
new file mode 100644 (file)
index 0000000..05234e8
--- /dev/null
@@ -0,0 +1,50 @@
+/*++\r
+\r
+Copyright (c)  2003 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  CreateGuid.c  \r
+\r
+Abstract:\r
+\r
+  Library routine to create a GUID\r
+\r
+--*/\r
+\r
+#include <windows.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+void\r
+CreateGuid (\r
+  GUID *Guid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Guid  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  CoCreateGuid (Guid);\r
+}\r
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c b/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c
new file mode 100644 (file)
index 0000000..87195e7
--- /dev/null
@@ -0,0 +1,2667 @@
+/*++\r
+\r
+Copyright (c)  2002 - 2005, Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  GenCapsuleHdr.c  \r
+\r
+Abstract:\r
+\r
+  Generate a capsule header for a file, and optionally prepend the\r
+  header to a file or list of files.\r
+\r
+--*/\r
+\r
+#define _UNICODE\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <ctype.h>\r
+\r
+#include "Tiano.h"                  // need a guid definition\r
+#include "EfiUtilityMsgs.h"\r
+#include "EfiCapsule.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+#include "EfiFirmwareFileSystem.h"  // for FV header GUID\r
+#define MAX_PATH                  256\r
+#define PROGRAM_NAME              "GenCapsuleHdr"\r
+\r
+#define UNICODE_BACKSLASH         L'\\'\r
+#define UNICODE_FILE_START        0xFEFF\r
+#define UNICODE_CR                0x000D\r
+#define UNICODE_LF                0x000A\r
+#define UNICODE_NULL              0x0000\r
+#define UNICODE_SPACE             L' '\r
+#define UNICODE_SLASH             L'/'\r
+#define UNICODE_DOUBLE_QUOTE      L'"'\r
+#define UNICODE_A                 L'A'\r
+#define UNICODE_F                 L'F'\r
+#define UNICODE_Z                 L'Z'\r
+#define UNICODE_a                 L'a'\r
+#define UNICODE_f                 L'f'\r
+#define UNICODE_z                 L'z'\r
+#define UNICODE_0                 L'0'\r
+#define UNICODE_9                 L'9'\r
+#define UNICODE_TAB               L'\t'\r
+\r
+#define OEM_HEADER_STRING         L"OemHeader"\r
+#define AUTHOR_INFO_STRING        L"AuthorInfo"\r
+#define REVISION_INFO_STRING      L"RevisionInfo"\r
+#define SHORT_DESCRIPTION_STRING  L"ShortDescription"\r
+#define LONG_DESCRIPTION_STRING   L"LongDescription"\r
+#define EQUAL_STRING              L"="\r
+#define OPEN_BRACE_STRING         L"{"\r
+#define CLOSE_BRACE_STRING        L"}"\r
+#define GUID_STRING               L"GUID"\r
+#define DATA_STRING               L"DATA"\r
+\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+#define UEFI_CAPSULE_HEADER_NO_FALAGS      0\r
+#define UEFI_CAPSULE_HEADER_RESET_FALAGS   CAPSULE_FLAGS_PERSIST_ACROSS_RESET\r
+#define UEFI_CAPSULE_HEADER_ALL_FALAGS     (CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE)\r
+#endif\r
+\r
+typedef wchar_t WCHAR;\r
+\r
+typedef struct _FILE_LIST {\r
+  struct _FILE_LIST *Next;\r
+  INT8              FileName[MAX_PATH];\r
+} FILE_LIST;\r
+\r
+typedef struct _SIZE_LIST {\r
+  struct _SIZE_LIST *Next;\r
+  UINT32            Size;\r
+} SIZE_LIST;\r
+\r
+typedef struct {\r
+  INT8    FileName[MAX_PATH];\r
+  WCHAR   *FileBuffer;\r
+  WCHAR   *FileBufferPtr;\r
+  UINT32  FileSize;\r
+  FILE    *FilePtr;\r
+  BOOLEAN EndOfFile;\r
+  UINT32  LineNum;\r
+} SOURCE_FILE;\r
+\r
+//\r
+// Here's all our globals.\r
+//\r
+static struct {\r
+  BOOLEAN   Dump;\r
+  BOOLEAN   Verbose;\r
+  BOOLEAN   JoinMode;\r
+  INT8      ScriptFileName[MAX_PATH];\r
+  INT8      OutputFileName[MAX_PATH];\r
+  FILE_LIST *FileList;\r
+  FILE      *OutFptr;\r
+  SIZE_LIST *SizeList;\r
+  SIZE_LIST *LastSize;\r
+  SIZE_LIST *CurrentSize;\r
+} mOptions;\r
+\r
+static EFI_GUID mEfiCapsuleHeaderGuid = EFI_CAPSULE_GUID;\r
+\r
+void\r
+CreateGuid (\r
+  EFI_GUID *Guid\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessArgs (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  );\r
+\r
+static\r
+void\r
+SkipWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  );\r
+\r
+static\r
+STATUS\r
+GetHexValue (\r
+  SOURCE_FILE  *SourceFile,\r
+  UINT32       *Value,\r
+  UINT32       NumDigits\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+GetSplitFileName (\r
+  INT8    *BaseFileName,\r
+  INT8    *NewFileName,\r
+  UINT32  SequenceNumber\r
+  );\r
+\r
+static\r
+STATUS\r
+SplitCapsule (\r
+  INT8 *CapsuleFileName\r
+  );\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+static\r
+void\r
+DumpCapsule (\r
+  VOID\r
+  );\r
+\r
+static\r
+STATUS\r
+JoinCapsule (\r
+  VOID\r
+  );\r
+\r
+static\r
+STATUS\r
+DumpCapsuleHeaderStrings (\r
+  UINT8   *SectionName,\r
+  WCHAR   *Buffer\r
+  );\r
+\r
+static\r
+STATUS\r
+CheckFirmwareVolumeHeader (\r
+  INT8    *FileName,\r
+  INT8    *Buffer,\r
+  UINT32  BufferSize\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+IsToken (\r
+  SOURCE_FILE *File,\r
+  WCHAR       *Token\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+GetNumber (\r
+  INT8    *Str,\r
+  UINT32  *Value\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessScriptFile (\r
+  INT8                *ScriptFileName,\r
+  FILE                *OutFptr,\r
+  EFI_CAPSULE_HEADER  *CapsuleHeader\r
+  );\r
+\r
+static\r
+STATUS\r
+ParseCapsuleInfo (\r
+  SOURCE_FILE       *SourceFile,\r
+  FILE              *OutFptr,\r
+  WCHAR             *SectionName\r
+  );\r
+\r
+static\r
+STATUS\r
+CreateCapsule (\r
+  VOID\r
+  );\r
+\r
+static\r
+STATUS\r
+ParseOemInfo (\r
+  SOURCE_FILE       *SourceFile,\r
+  FILE              *OutFptr\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+  WCHAR Char\r
+  );\r
+\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+  SOURCE_FILE *File\r
+  );\r
+\r
+int\r
+main (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Call the routine to process the command-line arguments, then\r
+  dispatch to the appropriate function.\r
+  \r
+Arguments:\r
+  Standard C main() argc and argv.\r
+\r
+Returns:\r
+  0      if successful\r
+  nonzero otherwise\r
+  \r
+--*/\r
+// GC_TODO:    Argc - add argument and description to function comment\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  STATUS    Status;\r
+  FILE_LIST *NextFile;\r
+  //\r
+  // Specify our program name to the error printing routines.\r
+  //\r
+  SetUtilityName (PROGRAM_NAME);\r
+  //\r
+  // Process the command-line arguments\r
+  //\r
+  Status = ProcessArgs (Argc, Argv);\r
+  if (Status == STATUS_SUCCESS) {\r
+    if (mOptions.Dump) {\r
+      DumpCapsule ();\r
+    } else if (mOptions.JoinMode) {\r
+      JoinCapsule ();\r
+    } else {\r
+      CreateCapsule ();\r
+    }\r
+  }\r
+  //\r
+  // Cleanup\r
+  //\r
+  while (mOptions.FileList != NULL) {\r
+    NextFile = mOptions.FileList->Next;\r
+    free (mOptions.FileList);\r
+    mOptions.FileList = NextFile;\r
+  }\r
+\r
+  while (mOptions.SizeList != NULL) {\r
+    mOptions.CurrentSize = mOptions.SizeList->Next;\r
+    free (mOptions.SizeList);\r
+    mOptions.SizeList = mOptions.CurrentSize;\r
+  }\r
+\r
+  return GetUtilityStatus ();\r
+}\r
+\r
+static\r
+STATUS\r
+CreateCapsule (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  FILE                        *InFptr;\r
+  FILE_LIST                   *FileList;\r
+  INT8                        *Buffer;\r
+  UINT32                      Size;\r
+  EFI_CAPSULE_HEADER          CapsuleHeader;\r
+  UINT8                       Zero;\r
+  UINT8                       FirstFile;\r
+  UINT32                      CapsuleHeaderSize;\r
+  long                        InsertedBlockMapEntryOffset;\r
+  EFI_FV_BLOCK_MAP_ENTRY      InsertedBlockMapEntry;\r
+  UINT64                      FirmwareVolumeSize;\r
+  long                        FileSize;\r
+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;\r
+\r
+  Buffer                      = NULL;\r
+  InFptr                      = NULL;\r
+  FirmwareVolumeSize          = 0;\r
+  CapsuleHeaderSize           = 0;\r
+  InsertedBlockMapEntryOffset = 0;\r
+  memset (&InsertedBlockMapEntry, 0, sizeof (EFI_FV_BLOCK_MAP_ENTRY));\r
+  memset (&FVHeader, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+\r
+  if ((mOptions.OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  memset ((char *) &CapsuleHeader, 0, sizeof (CapsuleHeader));\r
+  memcpy ((void *) &CapsuleHeader.CapsuleGuid, (void *) &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID));\r
+  CapsuleHeader.HeaderSize        = sizeof (EFI_CAPSULE_HEADER);\r
+  CapsuleHeader.CapsuleImageSize  = sizeof (EFI_CAPSULE_HEADER);\r
+  if (mOptions.ScriptFileName[0] != 0) {\r
+    if (ProcessScriptFile (mOptions.ScriptFileName, mOptions.OutFptr, &CapsuleHeader) != STATUS_SUCCESS) {\r
+      goto Done;\r
+    }\r
+  } else {\r
+    //\r
+    // Insert a default capsule header\r
+#if (EFI_SPECIFICATION_VERSION >= 0x00020000)\r
+    CapsuleHeader.HeaderSize = sizeof (EFI_CAPSULE_HEADER);\r
+    CapsuleHeader.Flags   = UEFI_CAPSULE_HEADER_ALL_FALAGS;\r
+#endif\r
+    CapsuleHeader.OffsetToCapsuleBody = sizeof (EFI_CAPSULE_HEADER);\r
+\r
+   if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {\r
+     Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+     goto Done;\r
+   }\r
+ }\r
+\r
+  CapsuleHeaderSize = CapsuleHeader.OffsetToCapsuleBody;\r
+  //\r
+  // Now copy the contents of any other files specified on the command\r
+  // line to the output file. Files must be FFS files, which are aligned\r
+  // on 8-byte boundaries. Don't align the first file, since it's the start\r
+  // of the image once the capsule header has been removed.\r
+  //\r
+  FileList  = mOptions.FileList;\r
+  FirstFile = 1;\r
+  Zero      = 0;\r
+  while (FileList != NULL) {\r
+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+      goto Done;\r
+    }\r
+    //\r
+    // Allocate a buffer into which we can read the file.\r
+    //\r
+    fseek (InFptr, 0, SEEK_END);\r
+    Size = ftell (InFptr);\r
+    rewind (InFptr);\r
+    Buffer = (char *) malloc (Size);\r
+    if (Buffer == NULL) {\r
+      Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");\r
+      goto Done;\r
+    }\r
+\r
+    if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");\r
+      goto Done;\r
+    }\r
+\r
+    if (Size > 0) {\r
+      //\r
+      // Align the write of the first bytes from the file if not the first file\r
+      //\r
+      if (FirstFile) {\r
+        //\r
+        // First file must be a firmware volume. Double-check, and then insert\r
+        // an additional block map entry so we can add more files from the command line\r
+        //\r
+        if (CheckFirmwareVolumeHeader (FileList->FileName, Buffer, Size) != STATUS_SUCCESS) {\r
+          goto Done;\r
+        }\r
+        //\r
+        // Save a copy of the firmware volume header for later\r
+        //\r
+        memcpy (&FVHeader, Buffer, sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
+        FirmwareVolumeSize = FVHeader.FvLength;\r
+        if (FileList->Next != NULL) {\r
+          //\r
+          // Copy the firmware volume header\r
+          //\r
+          InsertedBlockMapEntryOffset = CapsuleHeaderSize + FVHeader.HeaderLength;\r
+          if (fwrite (Buffer, FVHeader.HeaderLength, 1, mOptions.OutFptr) != 1) {\r
+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+            goto Done;\r
+          }\r
+\r
+          if (fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr) != 1) {\r
+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+            goto Done;\r
+          }\r
+\r
+          if (fwrite (\r
+                Buffer + FVHeader.HeaderLength,\r
+                Size - FVHeader.HeaderLength,\r
+                1,\r
+                mOptions.OutFptr\r
+                ) != 1) {\r
+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+            goto Done;\r
+          }\r
+        } else {\r
+          //\r
+          // Copy the file contents as-is\r
+          //\r
+          if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {\r
+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+            goto Done;\r
+          }\r
+        }\r
+      } else {\r
+        while ((ftell (mOptions.OutFptr) - CapsuleHeaderSize) & 0x07) {\r
+          if (fwrite ((void *) &Zero, 1, 1, mOptions.OutFptr) != 1) {\r
+            Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+            goto Done;\r
+          }\r
+        }\r
+\r
+        if (fwrite ((void *) Buffer, Size, 1, mOptions.OutFptr) != 1) {\r
+          Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+          goto Done;\r
+        }\r
+      }\r
+\r
+      FirstFile = 0;\r
+    }\r
+\r
+    free (Buffer);\r
+    Buffer = NULL;\r
+    fclose (InFptr);\r
+    InFptr    = NULL;\r
+    FileList  = FileList->Next;\r
+  }\r
+\r
+Done:\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+  //\r
+  // If we inserted an additional block map entry, then fix it up. Fix up the\r
+  // FV header as well to reflect our new size.\r
+  //\r
+  if (InsertedBlockMapEntryOffset != 0) {\r
+    FileSize                        = ftell (mOptions.OutFptr);\r
+    InsertedBlockMapEntry.NumBlocks = 1;\r
+    InsertedBlockMapEntry.BlockLength = (UINT32) ((UINT64) FileSize - (UINT64) CapsuleHeaderSize - FirmwareVolumeSize - sizeof (EFI_FV_BLOCK_MAP_ENTRY));\r
+    fseek (mOptions.OutFptr, InsertedBlockMapEntryOffset, SEEK_SET);\r
+    fwrite (&InsertedBlockMapEntry, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);\r
+    //\r
+    // Fix up the firmware volume header and write it out\r
+    //\r
+    fseek (mOptions.OutFptr, CapsuleHeaderSize, SEEK_SET);\r
+    FVHeader.FvLength = FileSize - CapsuleHeaderSize;\r
+    FVHeader.HeaderLength += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+    fwrite (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, mOptions.OutFptr);\r
+    //\r
+    // Reposition to the end of the file\r
+    //\r
+  }\r
+  //\r
+  // Close files and free the global string lists we allocated memory for\r
+  //\r
+  if (mOptions.OutFptr != NULL) {\r
+    //\r
+    // We should now know the full capsule image size. Update the header and write it again.\r
+    //\r
+    fseek (mOptions.OutFptr, 0, SEEK_END);\r
+    Size  = ftell (mOptions.OutFptr);\r
+    CapsuleHeader.CapsuleImageSize = Size;\r
+    fseek (mOptions.OutFptr, 0, SEEK_SET);\r
+    if (fwrite ((void *) &CapsuleHeader, sizeof (CapsuleHeader), 1, mOptions.OutFptr) != 1) {\r
+      Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+    }\r
+\r
+    fseek (mOptions.OutFptr, 0, SEEK_END);\r
+    fclose (mOptions.OutFptr);\r
+    mOptions.OutFptr = NULL;\r
+  }\r
+  //\r
+  // If they are doing split capsule output, then split it up now.\r
+  //\r
+  if ((mOptions.Dump == 0) && (GetUtilityStatus () == STATUS_SUCCESS) && (mOptions.SizeList != NULL)) {\r
+    SplitCapsule (mOptions.OutputFileName);\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessScriptFile (\r
+  INT8                *ScriptFileName,\r
+  FILE                *OutFptr,\r
+  EFI_CAPSULE_HEADER  *CapsuleHeader\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Parse a capsule header script file.\r
+\r
+Arguments:\r
+  ScriptFileName    - name of script file to parse\r
+  OutFptr           - output to dump binary data\r
+  CapsuleHeader     - capsule header to update with size info\r
+                      of parsed fields in the script file\r
+\r
+Returns:\r
+  STATUS_SUCCESS - if all went well\r
+\r
+--*/\r
+{\r
+#if 0\r
+  STATUS      Status;\r
+  SOURCE_FILE SourceFile;\r
+  WCHAR       *WScriptFileName;\r
+  BOOLEAN     InComment;\r
+\r
+  if (fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, "failed to write capsule header to output file", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  memset (&SourceFile, 0, sizeof (SOURCE_FILE));\r
+  strcpy (SourceFile.FileName, ScriptFileName);\r
+\r
+  Status = STATUS_ERROR;\r
+  //\r
+  // Open the input unicode script file and read it into a buffer\r
+  //\r
+  WScriptFileName = (WCHAR *) malloc ((strlen (ScriptFileName) + 1) * sizeof (WCHAR));\r
+  if (WScriptFileName == NULL) {\r
+    Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  swprintf (WScriptFileName, L"%S", ScriptFileName);\r
+  if ((SourceFile.FilePtr = _wfopen (WScriptFileName, L"r")) == NULL) {\r
+    free (WScriptFileName);\r
+    Error (NULL, 0, 0, ScriptFileName, "failed to open script file for reading");\r
+    goto Done;\r
+  }\r
+\r
+  free (WScriptFileName);\r
+  fseek (SourceFile.FilePtr, 0, SEEK_END);\r
+  SourceFile.FileSize = ftell (SourceFile.FilePtr);\r
+  rewind (SourceFile.FilePtr);\r
+  SourceFile.FileBuffer = (WCHAR *) malloc (SourceFile.FileSize + sizeof (WCHAR));\r
+  if (SourceFile.FileBuffer == NULL) {\r
+    Error (__FILE__, __LINE__, 0, ScriptFileName, "failed to allocate memory to read in file contents");\r
+    goto Done;\r
+  }\r
+\r
+  if (fread (SourceFile.FileBuffer, SourceFile.FileSize, 1, SourceFile.FilePtr) != 1) {\r
+    Error (NULL, 0, 0, ScriptFileName, "failed to read file contents");\r
+    goto Done;\r
+  }\r
+\r
+  SourceFile.FileBufferPtr  = SourceFile.FileBuffer;\r
+  SourceFile.LineNum        = 1;\r
+  if (SourceFile.FileBuffer[0] != UNICODE_FILE_START) {\r
+    Error (ScriptFileName, 1, 0, "file does not appear to be a unicode file", NULL);\r
+    goto Done;\r
+  }\r
+\r
+  SourceFile.FileBufferPtr++;\r
+  SourceFile.FileBuffer[SourceFile.FileSize / sizeof (WCHAR)] = 0;\r
+  //\r
+  // Walk the source file buffer and replace all carriage returns with 0 so\r
+  // we can print from the file contents on parse errors.\r
+  //\r
+  InComment = 0;\r
+  while (!EndOfFile (&SourceFile)) {\r
+    if (SourceFile.FileBufferPtr[0] == UNICODE_CR) {\r
+      SourceFile.FileBufferPtr[0] = 0;\r
+      InComment                   = 0;\r
+    } else if (SourceFile.FileBufferPtr[0] == UNICODE_LF) {\r
+      InComment = 0;\r
+    } else if (InComment) {\r
+      SourceFile.FileBufferPtr[0] = UNICODE_SPACE;\r
+    } else if ((SourceFile.FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile.FileBufferPtr[1] == UNICODE_SLASH)) {\r
+      InComment                   = 1;\r
+      SourceFile.FileBufferPtr[0] = UNICODE_SPACE;\r
+    }\r
+\r
+    SourceFile.FileBufferPtr++;\r
+  }\r
+  //\r
+  // Reposition to the start of the file, but skip over the unicode file start\r
+  //\r
+  SourceFile.FileBufferPtr = SourceFile.FileBuffer;\r
+  SourceFile.FileBufferPtr++;\r
+  SourceFile.EndOfFile                    = 0;\r
+  CapsuleHeader->OffsetToOemDefinedHeader = ftell (OutFptr);\r
+  //\r
+  // Parse the OEM bytes\r
+  //\r
+  if (ParseOemInfo (&SourceFile, OutFptr) != STATUS_SUCCESS) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Parse the author information\r
+  //\r
+  CapsuleHeader->OffsetToAuthorInformation = ftell (OutFptr);\r
+  if (ParseCapsuleInfo (&SourceFile, OutFptr, AUTHOR_INFO_STRING) != STATUS_SUCCESS) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Parse the revision information\r
+  //\r
+  CapsuleHeader->OffsetToRevisionInformation = ftell (OutFptr);\r
+  if (ParseCapsuleInfo (&SourceFile, OutFptr, REVISION_INFO_STRING) != STATUS_SUCCESS) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Parse the short description\r
+  //\r
+  CapsuleHeader->OffsetToShortDescription = ftell (OutFptr);\r
+  if (ParseCapsuleInfo (&SourceFile, OutFptr, SHORT_DESCRIPTION_STRING) != STATUS_SUCCESS) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Parse the long description\r
+  //\r
+  CapsuleHeader->OffsetToLongDescription = ftell (OutFptr);\r
+  if (ParseCapsuleInfo (&SourceFile, OutFptr, LONG_DESCRIPTION_STRING) != STATUS_SUCCESS) {\r
+    goto Done;\r
+  }\r
+  //\r
+  // Better be end of contents\r
+  //\r
+  SkipWhiteSpace (&SourceFile);\r
+  if (!EndOfFile (&SourceFile)) {\r
+    Error (ScriptFileName, SourceFile.LineNum, 0, NULL, "expected end-of-file, not %.20S", SourceFile.FileBufferPtr);\r
+    goto Done;\r
+  }\r
+\r
+  CapsuleHeader->OffsetToCapsuleBody = ftell (OutFptr);\r
+  rewind (OutFptr);\r
+  fwrite (CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, OutFptr);\r
+  fseek (OutFptr, 0, SEEK_END);\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  if (SourceFile.FilePtr != NULL) {\r
+    fclose (SourceFile.FilePtr);\r
+  }\r
+\r
+  if (SourceFile.FileBuffer != NULL) {\r
+    free (SourceFile.FileBuffer);\r
+  }\r
+\r
+  return Status;\r
+\r
+#endif\r
+  return STATUS_SUCCESS;\r
+}\r
+//\r
+// Parse the OEM data of format:\r
+//      OemInfo {\r
+//            GUID = 12345676-1234-1234-123456789ABC\r
+//            DATA = 0x01, 0x02, 0x03...\r
+//      }\r
+//\r
+static\r
+STATUS\r
+ParseOemInfo (\r
+  SOURCE_FILE       *SourceFile,\r
+  FILE              *OutFptr\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SourceFile  - GC_TODO: add argument description\r
+  OutFptr     - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  long                    OemHeaderOffset;\r
+  UINT32                  Data;\r
+  EFI_CAPSULE_OEM_HEADER  OemHeader;\r
+  STATUS                  Status;\r
+  UINT32                  DigitCount;\r
+  WCHAR                   *SaveFilePos;\r
+  UINT8                   ByteData;\r
+\r
+  Status = STATUS_ERROR;\r
+  memset (&OemHeader, 0, sizeof (EFI_CAPSULE_OEM_HEADER));\r
+  OemHeaderOffset       = ftell (OutFptr);\r
+  OemHeader.HeaderSize  = sizeof (EFI_CAPSULE_OEM_HEADER);\r
+  if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, OEM_HEADER_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      OEM_HEADER_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      EQUAL_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      OPEN_BRACE_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+  //\r
+  // Look for:  GUID = xxxxxxx-xxxx-xxxx-xxxxxxxxxxxxx\r
+  //\r
+  if (!IsToken (SourceFile, GUID_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      GUID_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      EQUAL_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+  //\r
+  // Parse the xxxxxxxx-xxxx-xxxx-xxxx portion of the GUID\r
+  //\r
+  SkipWhiteSpace (SourceFile);\r
+  if (GetHexValue (SourceFile, &Data, 8) != STATUS_SUCCESS) {\r
+    Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+    goto Done;\r
+  }\r
+\r
+  OemHeader.OemGuid.Data1 = Data;\r
+  if (!IsToken (SourceFile, L"-")) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected dash in GUID, not %S",\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+  //\r
+  // Get 3 word values\r
+  //\r
+  for (DigitCount = 0; DigitCount < 3; DigitCount++) {\r
+    if (GetHexValue (SourceFile, &Data, 4) != STATUS_SUCCESS) {\r
+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+      goto Done;\r
+    }\r
+\r
+    switch (DigitCount) {\r
+    case 0:\r
+      OemHeader.OemGuid.Data2 = (UINT16) Data;\r
+      break;\r
+\r
+    case 1:\r
+      OemHeader.OemGuid.Data3 = (UINT16) Data;\r
+      break;\r
+\r
+    case 2:\r
+      OemHeader.OemGuid.Data4[1]  = (UINT8) Data;\r
+      OemHeader.OemGuid.Data4[0]  = (UINT8) (Data >> 8);\r
+      break;\r
+    }\r
+\r
+    if (!IsToken (SourceFile, L"-")) {\r
+      Error (\r
+        SourceFile->FileName,\r
+        SourceFile->LineNum,\r
+        0,\r
+        NULL,\r
+        "expected dash in GUID, not %S",\r
+        SourceFile->FileBufferPtr\r
+        );\r
+      goto Done;\r
+    }\r
+  }\r
+  //\r
+  // Pick up the last 6 bytes of the GUID\r
+  //\r
+  SaveFilePos = SourceFile->FileBufferPtr;\r
+  for (DigitCount = 0; DigitCount < 6; DigitCount++) {\r
+    if (GetHexValue (SourceFile, &Data, 2) != STATUS_SUCCESS) {\r
+      Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid GUID", NULL);\r
+      goto Done;\r
+    }\r
+\r
+    OemHeader.OemGuid.Data4[DigitCount + 2] = (UINT8) Data;\r
+  }\r
+  //\r
+  // Now read raw OEM data bytes. May or may not be present.\r
+  //    DATA = 0x01, 0x02, 0x02...\r
+  //\r
+  if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+    Status = STATUS_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, DATA_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      DATA_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      EQUAL_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  while (!EndOfFile (SourceFile)) {\r
+    if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+      Status = STATUS_SUCCESS;\r
+      goto Done;\r
+    }\r
+\r
+    if (IsToken (SourceFile, L"0x")) {\r
+      if (swscanf (SourceFile->FileBufferPtr, L"%x", &Data) != 1) {\r
+        Error (\r
+          SourceFile->FileName,\r
+          SourceFile->LineNum,\r
+          0,\r
+          NULL,\r
+          "expected hex byte value, not %.20S",\r
+          SourceFile->FileBufferPtr\r
+          );\r
+        goto Done;\r
+      }\r
+\r
+      if (Data &~0xFF) {\r
+        Error (\r
+          SourceFile->FileName,\r
+          SourceFile->LineNum,\r
+          0,\r
+          NULL,\r
+          "expected byte hex byte value at %.20S",\r
+          SourceFile->FileBufferPtr\r
+          );\r
+        goto Done;\r
+      }\r
+      //\r
+      // Skip over the hex digits, then write the data\r
+      //\r
+      while (iswxdigit (SourceFile->FileBufferPtr[0])) {\r
+        SourceFile->FileBufferPtr++;\r
+      }\r
+\r
+      ByteData = (UINT8) Data;\r
+      if (fwrite (&ByteData, 1, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, "failed to write OEM data to output file", NULL);\r
+        goto Done;\r
+      }\r
+\r
+      OemHeader.HeaderSize++;\r
+      //\r
+      // Optional comma\r
+      //\r
+      IsToken (SourceFile, L",");\r
+    } else {\r
+      Error (\r
+        SourceFile->FileName,\r
+        SourceFile->LineNum,\r
+        0,\r
+        NULL,\r
+        "expected hex OEM data, not %.20S",\r
+        SourceFile->FileBufferPtr\r
+        );\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  if (EndOfFile (SourceFile)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S close to OEM header data",\r
+      CLOSE_BRACE_STRING\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  //\r
+  // re-write the oem header if no errors\r
+  //\r
+  if (Status == STATUS_SUCCESS) {\r
+    fseek (OutFptr, OemHeaderOffset, SEEK_SET);\r
+    if (fwrite (&OemHeader, sizeof (EFI_CAPSULE_OEM_HEADER), 1, OutFptr) != 1) {\r
+      Error (NULL, 0, 0, "failed to write OEM header to output file", NULL);\r
+      goto Done;\r
+    }\r
+\r
+    fseek (OutFptr, 0, SEEK_END);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ParseCapsuleInfo (\r
+  SOURCE_FILE       *SourceFile,\r
+  FILE              *OutFptr,\r
+  WCHAR             *SectionName\r
+  )\r
+// GC_TODO: function comment should start with '/*++'\r
+//\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    SourceFile - add argument and description to function comment\r
+// GC_TODO:    OutFptr - add argument and description to function comment\r
+// GC_TODO:    SectionName - add argument and description to function comment\r
+// Parse:  eng "string " "parts"\r
+//          spa "string " "parts"\r
+// Write out: "eng string parts\0spa string parts\0\0\r
+//\r
+{\r
+  STATUS  Status;\r
+  int     StringCount;\r
+  WCHAR   Zero;\r
+  WCHAR   Spacebar;\r
+\r
+  Status    = STATUS_ERROR;\r
+  Zero      = 0;\r
+  Spacebar  = UNICODE_SPACE;\r
+\r
+  if (!IsToken (SourceFile, SectionName)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      SectionName,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, EQUAL_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      EQUAL_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  if (!IsToken (SourceFile, OPEN_BRACE_STRING)) {\r
+    Error (\r
+      SourceFile->FileName,\r
+      SourceFile->LineNum,\r
+      0,\r
+      NULL,\r
+      "expected %S, not %.20S",\r
+      OPEN_BRACE_STRING,\r
+      SourceFile->FileBufferPtr\r
+      );\r
+    goto Done;\r
+  }\r
+\r
+  while (!EndOfFile (SourceFile)) {\r
+    if (IsToken (SourceFile, CLOSE_BRACE_STRING)) {\r
+      break;\r
+    }\r
+    //\r
+    // Look for language identifier (3 lowercase chars)\r
+    //\r
+    if ((SourceFile->FileBufferPtr[0] >= UNICODE_a) &&\r
+        (SourceFile->FileBufferPtr[0] <= UNICODE_z) &&\r
+        (SourceFile->FileBufferPtr[1] >= UNICODE_a) &&\r
+        (SourceFile->FileBufferPtr[1] <= UNICODE_z) &&\r
+        (SourceFile->FileBufferPtr[2] >= UNICODE_a) &&\r
+        (SourceFile->FileBufferPtr[2] <= UNICODE_z) &&\r
+        IsWhiteSpace (SourceFile->FileBufferPtr[3])\r
+          ) {\r
+      //\r
+      // Write the 3 chars followed by a spacebar, and then look for opening quote\r
+      //\r
+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+      SourceFile->FileBufferPtr++;\r
+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+      SourceFile->FileBufferPtr++;\r
+      fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+      SourceFile->FileBufferPtr++;\r
+      fwrite (&Spacebar, sizeof (WCHAR), 1, OutFptr);\r
+      StringCount = 0;\r
+      while (IsToken (SourceFile, L"\"")) {\r
+        StringCount++;\r
+        while (!EndOfFile (SourceFile)) {\r
+          if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) {\r
+            SourceFile->FileBufferPtr++;\r
+            break;\r
+          } else if ((SourceFile->FileBufferPtr[0] == UNICODE_LF) || (SourceFile->FileBufferPtr[0] == 0)) {\r
+            Error (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", NULL);\r
+            goto Done;\r
+          } else {\r
+            fwrite (SourceFile->FileBufferPtr, sizeof (WCHAR), 1, OutFptr);\r
+            SourceFile->FileBufferPtr++;\r
+          }\r
+        }\r
+      }\r
+\r
+      if (StringCount == 0) {\r
+        Error (\r
+          SourceFile->FileName,\r
+          SourceFile->LineNum,\r
+          0,\r
+          NULL,\r
+          "expected quoted string, not %.20S",\r
+          SourceFile->FileBufferPtr\r
+          );\r
+        goto Done;\r
+      }\r
+      //\r
+      // This string's null terminator\r
+      //\r
+      fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);\r
+    } else {\r
+      Error (\r
+        SourceFile->FileName,\r
+        SourceFile->LineNum,\r
+        0,\r
+        NULL,\r
+        "expected valid language identifer, not %.20S",\r
+        SourceFile->FileBufferPtr\r
+        );\r
+      goto Done;\r
+    }\r
+  }\r
+  //\r
+  // Double null terminator\r
+  //\r
+  fwrite (&Zero, sizeof (WCHAR), 1, OutFptr);\r
+  Status = STATUS_SUCCESS;\r
+Done:\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+SplitCapsule (\r
+  INT8    *CapsuleFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  We've created an entire capsule image. Now split it up into the \r
+  size pieces they requested.\r
+\r
+Arguments:\r
+  CapsuleFileName  - name of an existing capsule file on disk\r
+\r
+Returns:\r
+  STATUS_SUCCESS - if no problems\r
+\r
+Notes:\r
+  This implementation reads in the entire capsule image from\r
+  disk, then overwrites the original file with the first\r
+  in the series.\r
+\r
+--*/\r
+{\r
+#if 0\r
+  EFI_CAPSULE_HEADER  *CapHdr;\r
+\r
+  EFI_CAPSULE_HEADER  Hdr;\r
+  FILE                *CapFptr;\r
+  FILE                *OutFptr;\r
+  UINT32              SizeLeft;\r
+  UINT32              CurrentSize;\r
+  UINT32              DataSize;\r
+  UINT32              SequenceNumber;\r
+  INT8                *Buffer;\r
+  INT8                FileName[MAX_PATH];\r
+  STATUS              Status;\r
+  UINT32              FileSize;\r
+  //\r
+  // Figure out the total size, then rewind the input file and\r
+  // read the entire thing in\r
+  //\r
+  if ((CapFptr = fopen (CapsuleFileName, "rb")) == NULL) {\r
+    Error (NULL, 0, 0, CapsuleFileName, "failed to open capsule image for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  OutFptr = NULL;\r
+  Status  = STATUS_SUCCESS;\r
+  fseek (CapFptr, 0, SEEK_END);\r
+  SizeLeft = ftell (CapFptr);\r
+  fseek (CapFptr, 0, SEEK_SET);\r
+  CapHdr = (EFI_CAPSULE_HEADER *) malloc (SizeLeft);\r
+  if (CapHdr == NULL) {\r
+    Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+    goto FailDone;\r
+  }\r
+\r
+  if (fread (CapHdr, SizeLeft, 1, CapFptr) != 1) {\r
+    Error (NULL, 0, 0, "failed to read capsule contents", "split failed");\r
+    goto FailDone;\r
+  }\r
+\r
+  fclose (CapFptr);\r
+  CapFptr = NULL;\r
+  //\r
+  // Get a GUID to fill in the InstanceId GUID in the header\r
+  //\r
+  CreateGuid (&CapHdr->InstanceId);\r
+  SequenceNumber = 0;\r
+  //\r
+  // If the split size is larger than the original capsule image, then\r
+  // we're done.\r
+  //\r
+  if (mOptions.SizeList->Size >= SizeLeft) {\r
+    mOptions.SizeList->Size = SizeLeft;\r
+    goto Done;\r
+  }\r
+  //\r
+  // First size has to be big enough for the original header\r
+  //\r
+  if (mOptions.SizeList->Size < CapHdr->OffsetToCapsuleBody) {\r
+    Error (NULL, 0, 0, "first split size is insufficient for the original capsule header", NULL);\r
+    goto FailDone;\r
+  }\r
+  //\r
+  // Initialize the header we'll use on all but the first part\r
+  //\r
+  memset (&Hdr, 0, sizeof (Hdr));\r
+  Hdr.CapsuleGuid         = CapHdr->CapsuleGuid;\r
+  Hdr.HeaderSize          = sizeof (Hdr);\r
+  Hdr.Flags               = CapHdr->Flags;\r
+  Hdr.InstanceId          = CapHdr->InstanceId;\r
+  Hdr.CapsuleImageSize    = CapHdr->CapsuleImageSize;\r
+  Hdr.OffsetToCapsuleBody = Hdr.HeaderSize;\r
+  Hdr.SequenceNumber      = 1;\r
+  //\r
+  // printf ("Created %s - 0x%X bytes\n", CapsuleFileName, mOptions.SizeList->Size);\r
+  //\r
+  Buffer = (UINT8 *) CapHdr;\r
+  //\r
+  // Walk the list of sizes and write out a capsule header, and\r
+  // then the raw capsule data.\r
+  //\r
+  //  SizeLeft -= mOptions.SizeList->Size;\r
+  //\r
+  mOptions.CurrentSize = mOptions.SizeList;\r
+  while (SizeLeft) {\r
+    CurrentSize = mOptions.CurrentSize->Size;\r
+    GetSplitFileName (mOptions.OutputFileName, FileName, SequenceNumber);\r
+    if ((OutFptr = fopen (FileName, "wb")) == NULL) {\r
+      Error (NULL, 0, 0, FileName, "failed to open split file for writing");\r
+      goto FailDone;\r
+    }\r
+\r
+    if (Buffer == (UINT8 *) CapHdr) {\r
+      //\r
+      // First part -- write out original header and data\r
+      //\r
+      if (fwrite (Buffer, CurrentSize, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, FileName, "failed to write to split image file");\r
+        goto FailDone;\r
+      }\r
+\r
+      SizeLeft -= CurrentSize;\r
+      Buffer += CurrentSize;\r
+      DataSize  = CurrentSize;\r
+      FileSize  = CurrentSize;\r
+    } else {\r
+      //\r
+      // Not the first part. Write the default header, and then the raw bytes from the\r
+      // original image.\r
+      //\r
+      if (CurrentSize <= sizeof (Hdr)) {\r
+        Error (NULL, 0, 0, "split size too small for capsule header + data", "0x%X", CurrentSize);\r
+        goto FailDone;\r
+      }\r
+\r
+      DataSize = CurrentSize - sizeof (Hdr);\r
+      if (DataSize > SizeLeft) {\r
+        DataSize = SizeLeft;\r
+      }\r
+\r
+      if (fwrite (&Hdr, sizeof (Hdr), 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, FileName, "failed to write capsule header to output file");\r
+        fclose (OutFptr);\r
+        goto FailDone;\r
+      }\r
+\r
+      if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, FileName, "failed to write capsule data to output file");\r
+        fclose (OutFptr);\r
+        goto FailDone;\r
+      }\r
+\r
+      Hdr.SequenceNumber++;\r
+      Buffer += DataSize;\r
+      SizeLeft -= DataSize;\r
+      FileSize = DataSize + sizeof (Hdr);\r
+    }\r
+    //\r
+    // Next size in list if there is one\r
+    //\r
+    if (mOptions.CurrentSize->Next != NULL) {\r
+      mOptions.CurrentSize = mOptions.CurrentSize->Next;\r
+    }\r
+\r
+    SequenceNumber++;\r
+    fclose (OutFptr);\r
+    OutFptr = NULL;\r
+    printf ("Created %s - 0x%X bytes (0x%X bytes of data)\n", FileName, FileSize, DataSize);\r
+  }\r
+\r
+  goto Done;\r
+FailDone:\r
+  Status = STATUS_ERROR;\r
+Done:\r
+  if (CapHdr != NULL) {\r
+    free (CapHdr);\r
+  }\r
+\r
+  if (CapFptr != NULL) {\r
+    fclose (CapFptr);\r
+  }\r
+\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+  }\r
+\r
+  return Status;\r
+\r
+#endif\r
+   return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+GetSplitFileName (\r
+  INT8    *BaseFileName,\r
+  INT8    *NewFileName,\r
+  UINT32  SequenceNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  BaseFileName    - GC_TODO: add argument description\r
+  NewFileName     - GC_TODO: add argument description\r
+  SequenceNumber  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  /*++\r
+\r
+Routine Description:\r
+  Given an initial split capsule file name and a sequence number,\r
+  create an appropriate file name for this split of a capsule image.\r
+\r
+Arguments:\r
+  BaseFileName   - name of of the first split file in the series\r
+  NewFileName    - output name of the split file\r
+  SequenceNumber - 0-based sequence number of split images\r
+\r
+Returns:\r
+  TRUE   - name created successfully\r
+  FALSE  - otherwise\r
+\r
+--*/\r
+  INT8    *Ptr;\r
+  INT8    *Part2Start;\r
+  UINT32  Digits;\r
+  UINT32  Len;\r
+  UINT32  BaseOffset;\r
+  //\r
+  // Work back from the end of the file name and see if there is a number somewhere\r
+  //\r
+  for (Ptr = BaseFileName + strlen (BaseFileName) - 1; (Ptr > BaseFileName) && !isdigit (*Ptr); Ptr--)\r
+    ;\r
+  if ((Ptr == BaseFileName) && (!isdigit (*Ptr))) {\r
+    //\r
+    // Found no number, so just add it to the end\r
+    //\r
+    sprintf (NewFileName, "%s%d", BaseFileName, SequenceNumber);\r
+    return TRUE;\r
+  } else {\r
+    //\r
+    // Found a number. Look back to find the first digit.\r
+    //\r
+    Part2Start = Ptr + 1;\r
+    for (Digits = 1; isdigit (*Ptr) && (Ptr > BaseFileName); Ptr--, Digits++)\r
+      ;\r
+    if (!isdigit (*Ptr)) {\r
+      Ptr++;\r
+      Digits--;\r
+    }\r
+\r
+    BaseOffset      = atoi (Ptr);\r
+    SequenceNumber  = SequenceNumber + BaseOffset;\r
+    if (Digits > 1) {\r
+      //\r
+      // Copy the first part of the original file name to the new filename\r
+      // This is the path for filenames with format path\name001.cap\r
+      //\r
+      Len = (UINT32) Ptr - (UINT32) BaseFileName;\r
+      strncpy (NewFileName, BaseFileName, Len);\r
+      sprintf (NewFileName + Len, "%0*d", Digits, SequenceNumber);\r
+      strcat (NewFileName, Part2Start);\r
+      return TRUE;\r
+    } else {\r
+      //\r
+      // Only one digit found. This is the path for filenames with\r
+      // format path\name1.cap\r
+      //\r
+      Len = (UINT32) Ptr - (UINT32) BaseFileName + 1;\r
+      strncpy (NewFileName, BaseFileName, Len);\r
+      sprintf (NewFileName + Len - 1, "%d", SequenceNumber);\r
+      strcat (NewFileName, Part2Start);\r
+      return TRUE;\r
+    }\r
+  }\r
+}\r
+\r
+static\r
+BOOLEAN\r
+IsWhiteSpace (\r
+  WCHAR  Char\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Char  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  switch (Char) {\r
+  case UNICODE_SPACE:\r
+  case UNICODE_TAB:\r
+  case UNICODE_NULL:\r
+  case UNICODE_CR:\r
+  case UNICODE_LF:\r
+    return TRUE;\r
+\r
+  default:\r
+    return FALSE;\r
+  }\r
+}\r
+\r
+static\r
+BOOLEAN\r
+IsToken (\r
+  SOURCE_FILE *File,\r
+  WCHAR       *Token\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  File  - GC_TODO: add argument description\r
+  Token - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  SkipWhiteSpace (File);\r
+  if (EndOfFile (File)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (wcsncmp (Token, File->FileBufferPtr, wcslen (Token)) == 0) {\r
+    File->FileBufferPtr += wcslen (Token);\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckFirmwareVolumeHeader (\r
+  INT8    *FileName,\r
+  INT8    *Buffer,\r
+  UINT32  BufferSize\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileName    - GC_TODO: add argument description\r
+  Buffer      - GC_TODO: add argument description\r
+  BufferSize  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER  *Hdr;\r
+  EFI_GUID                    FVHeaderGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;\r
+\r
+  Hdr           = (EFI_FIRMWARE_VOLUME_HEADER *) Buffer;\r
+  if (Hdr->Signature != EFI_FVH_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "file does not appear to be a firmware volume (bad signature)");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (Hdr->Revision != EFI_FVH_REVISION) {\r
+    Error (NULL, 0, 0, FileName, "unsupported firmware volume header version");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (Hdr->FvLength > BufferSize) {\r
+    Error (NULL, 0, 0, FileName, "malformed firmware volume -- FvLength > file size");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (memcmp (&Hdr->FileSystemGuid, &FVHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+    Error (NULL, 0, 0, FileName, "invalid FFS GUID in firmware volume header");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+DumpCapsule (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+#if 0\r
+  FILE                        *InFptr;\r
+  FILE_LIST                   *FileList;\r
+  EFI_CAPSULE_HEADER          CapsuleHeader;\r
+  EFI_FIRMWARE_VOLUME_HEADER  FVHeader;\r
+  EFI_CAPSULE_OEM_HEADER      *OemHeader;\r
+  UINT8                       *BPtr;\r
+  UINT32                      FileSize;\r
+  UINT32                      CapsuleHeaderDataSize;\r
+  UINT8                       ByteCount;\r
+  UINT8                       *CapsuleHeaderData;\r
+  BOOLEAN                     SplitImage;\r
+\r
+  InFptr            = NULL;\r
+  CapsuleHeaderData = NULL;\r
+  FileList          = mOptions.FileList;\r
+  while (FileList != NULL) {\r
+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+      goto Done;\r
+    }\r
+\r
+    if (fread (&CapsuleHeader, sizeof (EFI_CAPSULE_HEADER), 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to read capsule header");\r
+      goto Done;\r
+    }\r
+\r
+    fseek (InFptr, 0, SEEK_END);\r
+    FileSize = ftell (InFptr);\r
+    if (CapsuleHeader.CapsuleImageSize > FileSize) {\r
+      SplitImage = TRUE;\r
+    } else {\r
+      SplitImage = FALSE;\r
+    }\r
+\r
+    printf (\r
+      "Capsule %s Size=0x%X CargoSize=0x%X\n",\r
+      FileList->FileName,\r
+      FileSize,\r
+      FileSize - CapsuleHeader.OffsetToCapsuleBody\r
+      );\r
+    printf (\r
+      "  GUID                  %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",\r
+      CapsuleHeader.CapsuleGuid.Data1,\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data2,\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data3,\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[0],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[1],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[2],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[3],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[4],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[5],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[6],\r
+      (UINT32) CapsuleHeader.CapsuleGuid.Data4[7]\r
+      );\r
+    if (memcmp (&CapsuleHeader.CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+      printf ("  INVALID GUID");\r
+    }\r
+\r
+    printf ("\n");\r
+    printf ("  Header size           0x%08X\n", CapsuleHeader.HeaderSize);\r
+    printf ("  Flags                 0x%08X\n", CapsuleHeader.Flags);\r
+    if (!SplitImage) {\r
+      printf ("  Capsule image size    0x%08X\n", CapsuleHeader.CapsuleImageSize);\r
+    } else {\r
+      printf ("  Capsule image size    0x%08X (split)\n", CapsuleHeader.CapsuleImageSize);\r
+    }\r
+\r
+    printf ("  Sequence number       %d\n", CapsuleHeader.SequenceNumber);\r
+    printf (\r
+      "  InstanceId            %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+      CapsuleHeader.InstanceId.Data1,\r
+      (UINT32) CapsuleHeader.InstanceId.Data2,\r
+      (UINT32) CapsuleHeader.InstanceId.Data3,\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[0],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[1],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[2],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[3],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[4],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[5],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[6],\r
+      (UINT32) CapsuleHeader.InstanceId.Data4[7]\r
+      );\r
+    printf ("  Offset to capsule     0x%X\n", CapsuleHeader.OffsetToCapsuleBody);\r
+    //\r
+    // Dump header data if there\r
+    //\r
+    CapsuleHeaderDataSize = CapsuleHeader.OffsetToCapsuleBody - CapsuleHeader.HeaderSize;\r
+    if (CapsuleHeaderDataSize != 0) {\r
+      CapsuleHeaderData = (UINT8 *) malloc (CapsuleHeaderDataSize);\r
+      if (CapsuleHeaderData == NULL) {\r
+        Error (\r
+          NULL,\r
+          0,\r
+          0,\r
+          "failed to allocate memory to read in capsule header data",\r
+          "0x%X bytes",\r
+          CapsuleHeaderDataSize\r
+          );\r
+        goto Done;\r
+      }\r
+\r
+      fseek (InFptr, CapsuleHeader.HeaderSize, SEEK_SET);\r
+      if (fread (CapsuleHeaderData, CapsuleHeaderDataSize, 1, InFptr) != 1) {\r
+        Error (\r
+          NULL,\r
+          0,\r
+          0,\r
+          "failed to read capsule header data contents from file",\r
+          "0x%X bytes",\r
+          CapsuleHeaderDataSize\r
+          );\r
+        goto Done;\r
+      }\r
+      //\r
+      // ************************************************************************\r
+      //\r
+      // OEM HEADER\r
+      //\r
+      // ************************************************************************\r
+      //\r
+      if (CapsuleHeader.OffsetToOemDefinedHeader != 0) {\r
+        OemHeader = (EFI_CAPSULE_OEM_HEADER *) (CapsuleHeaderData + CapsuleHeader.OffsetToOemDefinedHeader - CapsuleHeader.HeaderSize);\r
+        printf ("  OEM Header\n");\r
+        printf (\r
+          "    GUID                %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",\r
+          OemHeader->OemGuid.Data1,\r
+          (UINT32) OemHeader->OemGuid.Data2,\r
+          (UINT32) OemHeader->OemGuid.Data3,\r
+          (UINT32) OemHeader->OemGuid.Data4[0],\r
+          (UINT32) OemHeader->OemGuid.Data4[1],\r
+          (UINT32) OemHeader->OemGuid.Data4[2],\r
+          (UINT32) OemHeader->OemGuid.Data4[3],\r
+          (UINT32) OemHeader->OemGuid.Data4[4],\r
+          (UINT32) OemHeader->OemGuid.Data4[5],\r
+          (UINT32) OemHeader->OemGuid.Data4[6],\r
+          (UINT32) OemHeader->OemGuid.Data4[7]\r
+          );\r
+        printf ("    Header size:        0x%X\n", OemHeader->HeaderSize);\r
+        printf ("    OEM data");\r
+        BPtr = (UINT8 *) (OemHeader + 1);\r
+        for (ByteCount = 0; ByteCount < OemHeader->HeaderSize - sizeof (EFI_CAPSULE_OEM_HEADER); ByteCount++) {\r
+          if ((ByteCount & 0x7) == 0) {\r
+            printf ("\n      ");\r
+          }\r
+\r
+          printf ("%02X ", (UINT32) *BPtr);\r
+          BPtr++;\r
+        }\r
+\r
+        printf ("\n");\r
+      }\r
+      //\r
+      // ************************************************************************\r
+      //\r
+      // Author, revision, short description, and long description information\r
+      //\r
+      // ************************************************************************\r
+      //\r
+      if (CapsuleHeader.OffsetToAuthorInformation != 0) {\r
+        if (DumpCapsuleHeaderStrings (\r
+              "Author information",\r
+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToAuthorInformation - CapsuleHeader.HeaderSize)\r
+              ) != STATUS_SUCCESS) {\r
+          goto Done;\r
+        }\r
+      }\r
+\r
+      if (CapsuleHeader.OffsetToRevisionInformation != 0) {\r
+        if (DumpCapsuleHeaderStrings (\r
+              "Revision information",\r
+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToRevisionInformation - CapsuleHeader.HeaderSize)\r
+              ) != STATUS_SUCCESS) {\r
+          goto Done;\r
+        }\r
+      }\r
+\r
+      if (CapsuleHeader.OffsetToShortDescription != 0) {\r
+        if (DumpCapsuleHeaderStrings (\r
+              "Short description",\r
+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToShortDescription - CapsuleHeader.HeaderSize)\r
+              ) != STATUS_SUCCESS) {\r
+          goto Done;\r
+        }\r
+      }\r
+\r
+      if (CapsuleHeader.OffsetToLongDescription != 0) {\r
+        if (DumpCapsuleHeaderStrings (\r
+              "Long description",\r
+              (WCHAR *) (CapsuleHeaderData + CapsuleHeader.OffsetToLongDescription - CapsuleHeader.HeaderSize)\r
+              ) != STATUS_SUCCESS) {\r
+          goto Done;\r
+        }\r
+      }\r
+    }\r
+    //\r
+    // If it's not a split image, or it is a split image and this is the first in the series, then\r
+    // dump the cargo volume.\r
+    //\r
+    if ((!SplitImage) || (CapsuleHeader.SequenceNumber == 0)) {\r
+      printf ("  Cargo FV dump\n");\r
+      fseek (InFptr, CapsuleHeader.OffsetToCapsuleBody, SEEK_SET);\r
+      if (fread (&FVHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER), 1, InFptr) != 1) {\r
+        Error (NULL, 0, 0, FileList->FileName, "failed to read cargo FV header");\r
+        goto Done;\r
+      }\r
+\r
+      printf ("    FV length           0x%X", FVHeader.FvLength);\r
+      if (FileSize - CapsuleHeader.OffsetToCapsuleBody != FVHeader.FvLength) {\r
+        if (!SplitImage) {\r
+          printf (" ERROR: expected 0x%X to jive with file size on disk", FileSize - CapsuleHeader.OffsetToCapsuleBody);\r
+        }\r
+      }\r
+\r
+      printf ("\n");\r
+      printf ("    Signature           0x%X ", FVHeader.Signature);\r
+      if (FVHeader.Signature == EFI_FVH_SIGNATURE) {\r
+        printf ("_FVH\n");\r
+      } else {\r
+        printf ("INVALID\n");\r
+      }\r
+\r
+      printf ("    FV header length    0x%X\n", (UINT32) FVHeader.HeaderLength);\r
+      printf ("    Revision            0x%X\n", (UINT32) FVHeader.Revision);\r
+      printf ("\n");\r
+    }\r
+\r
+    FileList = FileList->Next;\r
+  }\r
+\r
+Done:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  if (CapsuleHeaderData != NULL) {\r
+    free (CapsuleHeaderData);\r
+  }\r
+#endif\r
+}\r
+\r
+static\r
+STATUS\r
+JoinCapsule (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Join split capsule images into a single image. This is the\r
+  support function for the -j command-line option.\r
+\r
+Arguments:\r
+  None.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - no problems encountered\r
+\r
+--*/\r
+{\r
+#if 0\r
+  UINT32              Size;\r
+  FILE                *InFptr;\r
+  FILE                *OutFptr;\r
+  INT8                *Buffer;\r
+  FILE_LIST           *FileList;\r
+  STATUS              Status;\r
+  EFI_CAPSULE_HEADER  CapHdr;\r
+  EFI_CAPSULE_HEADER  *CapHdrPtr;\r
+  UINT32              SizeLeft;\r
+  UINT32              SequenceNumber;\r
+  //\r
+  // Must have at least two files for join mode\r
+  //\r
+  if ((mOptions.FileList == NULL) || (mOptions.FileList->Next == NULL)) {\r
+    Error (NULL, 0, 0, "must specify at least two file names to join", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Open the output file\r
+  //\r
+  if ((OutFptr = fopen (mOptions.OutputFileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, mOptions.OutputFileName, "failed to open output file for writing");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  FileList        = mOptions.FileList;\r
+  Buffer          = NULL;\r
+  SequenceNumber  = 0;\r
+  InFptr          = NULL;\r
+  SizeLeft        = 0;\r
+  while (FileList != NULL) {\r
+    if ((InFptr = fopen (FileList->FileName, "rb")) == NULL) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to open file for reading");\r
+      goto FailDone;\r
+    }\r
+    //\r
+    // Allocate a buffer into which we can read the file.\r
+    //\r
+    fseek (InFptr, 0, SEEK_END);\r
+    Size = ftell (InFptr);\r
+    rewind (InFptr);\r
+    Buffer = (char *) malloc (Size);\r
+    if (Buffer == NULL) {\r
+      Error (__FILE__, __LINE__, 0, FileList->FileName, "failed to allocate buffer to read file into");\r
+      goto FailDone;\r
+    }\r
+\r
+    CapHdrPtr = (EFI_CAPSULE_HEADER *) Buffer;\r
+    if (fread ((void *) Buffer, Size, 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, FileList->FileName, "failed to read file contents");\r
+      goto FailDone;\r
+    }\r
+    //\r
+    // Check the header for validity. Check size first.\r
+    //\r
+    if (Size < sizeof (EFI_CAPSULE_HEADER)) {\r
+      Error (NULL, 0, 0, FileList->FileName, "file size is insufficient for a capsule header");\r
+      goto FailDone;\r
+    }\r
+    //\r
+    // Check GUID\r
+    //\r
+    if (memcmp (&CapHdrPtr->CapsuleGuid, &mEfiCapsuleHeaderGuid, sizeof (EFI_GUID)) != 0) {\r
+      Error (NULL, 0, 0, FileList->FileName, "invalid capsule GUID");\r
+      goto FailDone;\r
+    }\r
+    //\r
+    // Check sequence number\r
+    //\r
+    if (CapHdrPtr->SequenceNumber != SequenceNumber) {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        FileList->FileName,\r
+        "invalid sequence number %d (expected %d)",\r
+        CapHdrPtr->SequenceNumber,\r
+        SequenceNumber\r
+        );\r
+      goto FailDone;\r
+    }\r
+    //\r
+    // If the first file, read save the capsule header\r
+    //\r
+    if (SequenceNumber == 0) {\r
+      memcpy (&CapHdr, CapHdrPtr, sizeof (EFI_CAPSULE_HEADER));\r
+      //\r
+      // Erase the InstanceId GUID\r
+      //\r
+      memset (&CapHdrPtr->InstanceId, 0, sizeof (EFI_GUID));\r
+      if (fwrite (Buffer, Size, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, FileList->FileName, "failed to write contents to output file");\r
+        goto FailDone;\r
+      }\r
+\r
+      if (CapHdr.CapsuleImageSize < Size) {\r
+        Error (NULL, 0, 0, FileList->FileName, "capsule image size in capsule header < image size");\r
+        goto FailDone;\r
+      }\r
+\r
+      SizeLeft = CapHdr.CapsuleImageSize - Size;\r
+    } else {\r
+      //\r
+      // Check the GUID against the first file's GUID\r
+      //\r
+      if (memcmp (&CapHdr.CapsuleGuid, &CapHdrPtr->CapsuleGuid, sizeof (EFI_GUID)) != 0) {\r
+        Error (NULL, 0, 0, FileList->FileName, "GUID does not match first file's GUID");\r
+        goto FailDone;\r
+      }\r
+      //\r
+      // Make sure we're not throwing out any header info\r
+      //\r
+      if (CapHdrPtr->OffsetToCapsuleBody > sizeof (EFI_CAPSULE_HEADER)) {\r
+        //\r
+        // Could be the split information, so just emit a warning\r
+        //\r
+        Warning (\r
+          NULL,\r
+          0,\r
+          0,\r
+          FileList->FileName,\r
+          "image appears to have additional capsule header information -- ignoring"\r
+          );\r
+      } else if (CapHdrPtr->OffsetToCapsuleBody < sizeof (EFI_CAPSULE_HEADER)) {\r
+        Error (NULL, 0, 0, FileList->FileName, "offset to capsule body in capsule header is insufficient");\r
+        goto FailDone;\r
+      }\r
+\r
+      if (fwrite (Buffer + CapHdrPtr->OffsetToCapsuleBody, Size - CapHdrPtr->OffsetToCapsuleBody, 1, OutFptr) != 1) {\r
+        Error (NULL, 0, 0, mOptions.OutputFileName, "failed to write to file");\r
+        goto FailDone;\r
+      }\r
+\r
+      if (SizeLeft < (Size - CapHdrPtr->OffsetToCapsuleBody)) {\r
+        Error (NULL, 0, 0, "sum of image sizes exceeds size specified in initial capsule header", NULL);\r
+        goto FailDone;\r
+      }\r
+      //\r
+      // printf ("FILE: %s OffsetToCapsuleBody=0x%X\n", FileList->FileName, CapHdrPtr->OffsetToCapsuleBody);\r
+      //\r
+      SizeLeft = SizeLeft - (Size - CapHdrPtr->OffsetToCapsuleBody);\r
+    }\r
+    //\r
+    // printf ("FILE: %s sizeleft=0x%X\n", FileList->FileName, SizeLeft);\r
+    //\r
+    fclose (InFptr);\r
+    InFptr = NULL;\r
+    free (Buffer);\r
+    Buffer    = NULL;\r
+    FileList  = FileList->Next;\r
+    SequenceNumber++;\r
+  }\r
+\r
+  if (SizeLeft) {\r
+    Error (NULL, 0, 0, "sum of capsule images is insufficient", "0x%X bytes missing", SizeLeft);\r
+    goto FailDone;\r
+  }\r
+\r
+  Status = STATUS_SUCCESS;\r
+  goto Done;\r
+FailDone:\r
+  Status = STATUS_ERROR;\r
+Done:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+  }\r
+\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+\r
+  return Status;\r
+\r
+#endif\r
+return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+DumpCapsuleHeaderStrings (\r
+  UINT8   *SectionName,\r
+  WCHAR   *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Given a pointer to string data from a capsule header, dump\r
+  the strings.\r
+\r
+Arguments:\r
+  SectionName  - name of the capsule header section to which\r
+                 the string data pertains\r
+  Buffer       - pointer to string data from a capsule header\r
+\r
+Returns:\r
+  STATUS_SUCCESS - all went well\r
+\r
+--*/\r
+{\r
+  printf ("  %s\n", SectionName);\r
+  while (*Buffer) {\r
+    printf ("    Language: %S\n", Buffer);\r
+    while (*Buffer) {\r
+      Buffer++;\r
+    }\r
+\r
+    Buffer++;\r
+    while (*Buffer) {\r
+      if (wcslen (Buffer) > 60) {\r
+        printf ("      %.60S\n", Buffer);\r
+        Buffer += 60;\r
+      } else {\r
+        printf ("      %S\n", Buffer);\r
+        Buffer += wcslen (Buffer);\r
+      }\r
+    }\r
+\r
+    Buffer++;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+STATUS\r
+GetHexValue (\r
+  SOURCE_FILE  *SourceFile,\r
+  UINT32       *Value,\r
+  UINT32       NumDigits\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  Scan a hex value from the input stream.\r
+  \r
+Arguments:\r
+  SourceFile   - input file contents\r
+  Value        - returned value\r
+  NumDigits    - number of digits to read\r
+\r
+Returns:\r
+  STATUS_SUCCESS - if NumDigits were read from the file\r
+  STATUS_ERROR   - otherwise\r
+\r
+  \r
+--*/\r
+{\r
+  WCHAR   *SaveFilePos;\r
+  UINT32  Digits;\r
+  WCHAR   Nibble;\r
+\r
+  SaveFilePos = SourceFile->FileBufferPtr;\r
+  *Value      = 0;\r
+  Digits      = NumDigits;\r
+  while (Digits > 0) {\r
+    Nibble = SourceFile->FileBufferPtr[0];\r
+    if ((Nibble >= UNICODE_0) && (Nibble <= UNICODE_9)) {\r
+      *Value = (*Value << 4) | (Nibble - UNICODE_0);\r
+    } else if ((Nibble >= UNICODE_A) && (Nibble <= UNICODE_F)) {\r
+      *Value = (*Value << 4) | (Nibble - UNICODE_A + 0x10);\r
+    } else if ((Nibble >= UNICODE_a) && (Nibble <= UNICODE_f)) {\r
+      *Value = (*Value << 4) | (Nibble - UNICODE_a + 0x10);\r
+    } else {\r
+      Error (\r
+        SourceFile->FileName,\r
+        SourceFile->LineNum,\r
+        0,\r
+        NULL,\r
+        "expected %d valid hex nibbles at %.20S",\r
+        NumDigits,\r
+        SaveFilePos\r
+        );\r
+      return STATUS_ERROR;\r
+    }\r
+\r
+    SourceFile->FileBufferPtr++;\r
+    Digits--;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+BOOLEAN\r
+EndOfFile (\r
+  SOURCE_FILE *File\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  File  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  if ((UINT32) File->FileBufferPtr - (UINT32) File->FileBuffer >= File->FileSize) {\r
+    File->EndOfFile = TRUE;\r
+  }\r
+  //\r
+  // Reposition to the end of the file if we went beyond\r
+  //\r
+  if (File->EndOfFile) {\r
+    File->FileBufferPtr = File->FileBuffer + File->FileSize / sizeof (WCHAR);\r
+  }\r
+\r
+  return File->EndOfFile;\r
+}\r
+\r
+static\r
+void\r
+SkipWhiteSpace (\r
+  SOURCE_FILE *SourceFile\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SourceFile  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  while (!EndOfFile (SourceFile)) {\r
+    switch (*SourceFile->FileBufferPtr) {\r
+    case UNICODE_NULL:\r
+    case UNICODE_CR:\r
+    case UNICODE_SPACE:\r
+    case UNICODE_TAB:\r
+      SourceFile->FileBufferPtr++;\r
+      break;\r
+\r
+    case UNICODE_LF:\r
+      SourceFile->FileBufferPtr++;\r
+      SourceFile->LineNum++;\r
+      break;\r
+\r
+    default:\r
+      return ;\r
+    }\r
+  }\r
+}\r
+//\r
+// Parse a number. Possible format:\r
+//   1234\r
+//   1234k\r
+//   1234K\r
+//   1M\r
+//   1m\r
+//   0x100\r
+//\r
+static\r
+BOOLEAN\r
+GetNumber (\r
+  INT8    *Str,\r
+  UINT32  *Value\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Str   - GC_TODO: add argument description\r
+  Value - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  UINT32  LValue;\r
+\r
+  *Value  = 0;\r
+  LValue  = 0;\r
+  if (!isdigit (Str[0])) {\r
+    return FALSE;\r
+  }\r
+  //\r
+  // Look for hex number\r
+  //\r
+  if ((Str[0] == '0') && (tolower (Str[1]) == 'x')) {\r
+    Str += 2;\r
+    if (Str[0] == 0) {\r
+      return FALSE;\r
+    }\r
+\r
+    while (Str[0]) {\r
+      if ((Str[0] >= '0') && (Str[0] <= '9')) {\r
+        LValue = (LValue << 4) | (Str[0] - '0');\r
+      } else if ((Str[0] >= 'A') && (Str[0] <= 'F')) {\r
+        LValue = (LValue << 4) | (Str[0] - 'A' + 0x10);\r
+      } else if ((Str[0] >= 'a') && (Str[0] <= 'f')) {\r
+        LValue = (LValue << 4) | (Str[0] - 'a' + 0x10);\r
+      } else {\r
+        break;\r
+      }\r
+\r
+      Str++;\r
+    }\r
+  } else {\r
+    LValue = atoi (Str);\r
+    while (isdigit (*Str)) {\r
+      Str++;\r
+    }\r
+  }\r
+  //\r
+  // If string left over, better be one character we recognize\r
+  //\r
+  if (Str[0]) {\r
+    if (Str[1]) {\r
+      return FALSE;\r
+    }\r
+\r
+    switch (Str[0]) {\r
+    case 'k':\r
+    case 'K':\r
+      LValue *= 1024;\r
+      break;\r
+\r
+    case 'm':\r
+    case 'M':\r
+      LValue *= 1024 * 1024;\r
+      break;\r
+\r
+    default:\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  *Value = LValue;\r
+  return TRUE;\r
+}\r
+//\r
+// Process the command-line arguments\r
+//\r
+static\r
+STATUS\r
+ProcessArgs (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Processes command line arguments.\r
+\r
+Arguments:\r
+\r
+  Argc   - Number of command line arguments\r
+  Argv[] - Array of files input on command line  \r
+\r
+Returns:\r
+\r
+  STATUS_ERROR    - Function exited with an error\r
+  STATUS_SUCCESS  - Function executed successfully\r
+\r
+--*/\r
+{\r
+  FILE_LIST *NewFile;\r
+\r
+  FILE_LIST *LastFile;\r
+  SIZE_LIST *NewSize;\r
+  \r
+  NewFile = NULL;\r
+  NewSize = NULL;\r
+  \r
+  //\r
+  // Clear our globals\r
+  //\r
+  memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+\r
+  //\r
+  // Skip program name\r
+  //\r
+  Argc--;\r
+  Argv++;\r
+\r
+  if (Argc == 0) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Process until no more options\r
+  //\r
+  while ((Argc > 0) && (Argv[0][0] == '-')) {\r
+    if (stricmp (Argv[0], "-script") == 0) {\r
+      //\r
+      // Check for one more arg\r
+      //\r
+      if (Argc > 1) {\r
+        //\r
+        // Save the file name\r
+        //\r
+        if (strlen (Argv[1]) >= sizeof (mOptions.ScriptFileName)) {\r
+          Error (NULL, 0, 0, NULL, "input script file name length exceeds internal buffer size");\r
+          \r
+          if (NewFile != NULL) {\r
+            free (NewFile);\r
+          }\r
+          if (NewSize != NULL) {\r
+            free (NewSize);\r
+          }\r
+          \r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        strcpy (mOptions.ScriptFileName, Argv[1]);\r
+      } else {\r
+        Error (NULL, 0, 0, Argv[0], "missing script file name with option");\r
+        Usage ();\r
+        \r
+        if (NewFile != NULL) {\r
+          free (NewFile);\r
+        }\r
+        if (NewSize != NULL) {\r
+          free (NewSize);\r
+        }       \r
+\r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      Argc--;\r
+      Argv++;\r
+      //\r
+      // -o outfilename -- specify output file name (required)\r
+      //\r
+    } else if (stricmp (Argv[0], "-o") == 0) {\r
+      //\r
+      // check for one more arg\r
+      //\r
+      if (Argc > 1) {\r
+        //\r
+        // Try to open the file\r
+        //\r
+        // if ((mOptions.OutFptr = fopen (Argv[1], "wb")) == NULL) {\r
+        //  Error (NULL, 0, 0, Argv[1], "failed to open output file for writing");\r
+        //  return STATUS_ERROR;\r
+        // }\r
+        //\r
+        strcpy (mOptions.OutputFileName, Argv[1]);\r
+      } else {\r
+        Error (NULL, 0, 0, Argv[0], "missing output filename with option");\r
+        Usage ();\r
+        \r
+        if (NewFile != NULL) {\r
+          free (NewFile);\r
+        }\r
+        if (NewSize != NULL) {\r
+          free (NewSize);\r
+        }\r
+                \r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      Argc--;\r
+      Argv++;\r
+    } else if (stricmp (Argv[0], "-j") == 0) {\r
+      mOptions.JoinMode = TRUE;\r
+      //\r
+      // -split <size> option (multiple allowed)\r
+      //\r
+    } else if (stricmp (Argv[0], "-split") == 0) {\r
+      if (Argc > 1) {\r
+        NewSize = (SIZE_LIST *) malloc (sizeof (SIZE_LIST));\r
+        if (NewSize == NULL) {\r
+          Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+\r
+          if (NewFile != NULL) {\r
+            free (NewFile);\r
+          }\r
+          if (NewSize != NULL) {\r
+            free (NewSize);\r
+          }\r
+          \r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        memset (NewSize, 0, sizeof (SIZE_LIST));\r
+        //\r
+        // Get the size from the next arg, and then add this size\r
+        // to our size list\r
+        //\r
+        if (!GetNumber (Argv[1], &NewSize->Size)) {\r
+          Error (NULL, 0, 0, Argv[1], "invalid split size argument");\r
+\r
+          if (NewFile != NULL) {\r
+            free (NewFile);\r
+          }\r
+          if (NewSize != NULL) {\r
+            free (NewSize);\r
+          }       \r
+          \r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        if (mOptions.SizeList == NULL) {\r
+          mOptions.SizeList     = NewSize;\r
+          mOptions.CurrentSize  = NewSize;\r
+        } else {\r
+          mOptions.LastSize->Next = NewSize;\r
+        }\r
+\r
+        mOptions.LastSize = NewSize;\r
+        free (NewSize);\r
+      } else {\r
+        Error (NULL, 0, 0, Argv[0], "missing size parameter with option");\r
+        Usage ();\r
+\r
+        if (NewFile != NULL) {\r
+          free (NewFile);\r
+        }\r
+        if (NewSize != NULL) {\r
+          free (NewSize);\r
+        }\r
+        \r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      Argc--;\r
+      Argv++;      \r
+    } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+      Usage ();\r
+      \r
+      if (NewFile != NULL) {\r
+        free (NewFile);\r
+      }\r
+      if (NewSize != NULL) {\r
+        free (NewSize);\r
+      }\r
+      \r
+      return STATUS_ERROR;\r
+      //\r
+      // Default minimum header\r
+      //\r
+    } else if (stricmp (Argv[0], "-dump") == 0) {\r
+      mOptions.Dump = TRUE;\r
+    } else if (stricmp (Argv[0], "-v") == 0) {\r
+      mOptions.Verbose = TRUE;\r
+    } else {\r
+      Error (NULL, 0, 0, Argv[0], "unrecognized option");\r
+      Usage ();\r
+      \r
+      if (NewFile != NULL) {\r
+        free (NewFile);\r
+      }\r
+      if (NewSize != NULL) {\r
+        free (NewSize);\r
+      }\r
+      \r
+      return STATUS_ERROR;\r
+    }\r
+\r
+    Argc--;\r
+    Argv++;\r
+  }\r
+  //\r
+  // Can't -j join files and -s split output capsule\r
+  //\r
+  if ((mOptions.SizeList != NULL) && (mOptions.JoinMode)) {\r
+    Error (NULL, 0, 0, "cannot specify both -j and -size", NULL);\r
+    \r
+    if (NewFile != NULL) {\r
+      free (NewFile);\r
+    }\r
+    if (NewSize != NULL) {\r
+      free (NewSize);\r
+    }\r
+    \r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Must have specified an output file name if not -dump\r
+  //\r
+  if ((mOptions.Dump == 0) && (mOptions.OutputFileName[0] == 0)) {\r
+    Error (NULL, 0, 0, NULL, "-o OutputFileName must be specified");\r
+    Usage ();\r
+    \r
+    if (NewFile != NULL) {\r
+      free (NewFile);\r
+    }\r
+    if (NewSize != NULL) {\r
+      free (NewSize);\r
+    }\r
+    \r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Rest of arguments are input files. The first one is a firmware\r
+  // volume image, and the rest are FFS files that are to be inserted\r
+  // into the firmware volume.\r
+  //\r
+  LastFile = NULL;\r
+  while (Argc > 0) {\r
+    NewFile = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
+    if (NewFile == NULL) {\r
+      Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+\r
+      if (NewFile != NULL) {\r
+        free (NewFile);\r
+      }\r
+      if (NewSize != NULL) {\r
+        free (NewSize);\r
+      }\r
+    \r
+      return STATUS_ERROR;\r
+    }\r
+\r
+    memset ((char *) NewFile, 0, sizeof (FILE_LIST));\r
+    strcpy (NewFile->FileName, Argv[0]);\r
+    if (mOptions.FileList == NULL) {\r
+      mOptions.FileList = NewFile;\r
+    } else {\r
+      if (LastFile == NULL) {\r
+        LastFile = NewFile;\r
+      } else {\r
+        LastFile->Next = NewFile;\r
+      }      \r
+    }\r
+\r
+    LastFile = NewFile;\r
+    Argc--;\r
+    Argv++;\r
+  }\r
+\r
+  //\r
+  // Must have provided at least one file name\r
+  //\r
+  if (mOptions.FileList == NULL) {\r
+    Error (NULL, 0, 0, "must specify at least one file name", NULL);\r
+    Usage ();\r
+    \r
+    if (NewFile != NULL) {\r
+      free (NewFile);\r
+    }\r
+    if (NewSize != NULL) {\r
+      free (NewSize);\r
+    }\r
+    \r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Print usage information for this utility.\r
+  \r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  Nothing.\r
+  \r
+--*/\r
+{\r
+  int               Index;\r
+  static const char *Str[] = {\r
+    PROGRAM_NAME " -- create a capsule header",\r
+    "  Usage: "PROGRAM_NAME " {options} [CapsuleFV]",\r
+    //\r
+    // {FfsFileNames}",\r
+    //\r
+    "    Options include:",\r
+    "      -h or -?         for this help information",\r
+    "      -script fname    to take capsule header info from unicode script",\r
+    "                       file fname",\r
+    "      -o fname         write output to file fname (required)",\r
+    "      -split size      split capsule image into multiple output files",\r
+    "      -dump            to dump a capsule header",\r
+    "      -v               for verbose output\n",\r
+    "      -j               to join split capsule images into a single image",\r
+    "",\r
+    "    CapsuleFV is the name of an existing well-formed Tiano firmware",\r
+    "    volume file.",\r
+    //\r
+    // FfsFileNames are the names of one or more Tiano FFS files to",\r
+    // "    insert into the output capsule image.",\r
+    //\r
+    NULL\r
+  };\r
+  for (Index = 0; Str[Index] != NULL; Index++) {\r
+    fprintf (stdout, "%s\n", Str[Index]);\r
+  }\r
+}\r
diff --git a/Tools/Source/TianoTools/GenCapsuleHdr/Makefile b/Tools/Source/TianoTools/GenCapsuleHdr/Makefile
new file mode 100644 (file)
index 0000000..1979c3d
--- /dev/null
@@ -0,0 +1,75 @@
+#/*++\r
+#  \r
+#  Copyright (c)  2002 Intel Corporation. All rights reserved\r
+#  This software and associated documentation (if any) is furnished\r
+#  under a license and may only be used or copied in accordance\r
+#  with the terms of the license. Except as permitted by such\r
+#  license, no part of this software or documentation may be\r
+#  reproduced, stored in a retrieval system, or transmitted in any\r
+#  form or by any means without the express written consent of\r
+#  Intel Corporation.\r
+#  \r
+#  \r
+#  Module Name:\r
+#  \r
+#    Makefile\r
+#  \r
+#  Abstract:\r
+#  \r
+#    makefile for the GenCapsuleHdr utility.\r
+#    \r
+#--*/  \r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+\r
+TARGET_NAME         = GenCapsuleHdr\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+SRC                 = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+ETO                 = $(TIANO_TOOLS_OUTPUT)\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+LIBS    = $(LIBS) "$(TIANO_TOOLS_OUTPUT)\Common.lib" ole32.lib\r
+\r
+OBJECTS = $(ETO)\$(TARGET_NAME).obj \\r
+          $(ETO)\CreateGuid.obj\r
+\r
+#\r
+# Compile each source file\r
+#\r
+$(ETO)\$(TARGET_NAME).obj : $(SRC)\$(TARGET_NAME).c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(SRC)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(ETO)\CreateGuid.obj : $(SRC)\CreateGuid.c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(SRC)\CreateGuid.c /Fo$@\r
+\r
+#\r
+# Link the object files together\r
+#\r
+$(TARGET_EXE) : $(OBJECTS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImage.h b/Tools/Source/TianoTools/GenFdImage/GenFdImage.h
new file mode 100644 (file)
index 0000000..68cfa8c
--- /dev/null
@@ -0,0 +1,89 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  GenFdImage.h\r
+\r
+Abstract:\r
+\r
+  This file contains the relevant declarations required\r
+  to generate the Firmware Device\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standard\r
+//\r
+#ifndef _EFI_GEN_FD_IMAGE_H\r
+#define _EFI_GEN_FD_IMAGE_H\r
+\r
+//\r
+// Included Header files\r
+//\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <io.h>\r
+#include <assert.h>\r
+#include "TianoCommon.h"\r
+#include "ParseInf.h"\r
+#include "GenFvImage.h"\r
+\r
+//\r
+// Defines\r
+//\r
+#define FILE_NAME_SIZE  256\r
+\r
+//\r
+// Type Definition\r
+//\r
+typedef struct {\r
+  UINT64  FdSize;\r
+  UINT64  FdBaseAddress;\r
+  UINT8   PadValue;\r
+  CHAR8   OutFileName[FILE_NAME_SIZE];\r
+} FDINFO;\r
+\r
+//\r
+// Exported Function Prototype\r
+//\r
+EFI_STATUS\r
+GenerateFdImage (\r
+  IN UINT64  BaseAddress,\r
+  IN UINT64  Size,\r
+  IN UINT8   PadByte,\r
+  IN CHAR8   *OutFile,\r
+  IN CHAR8   **FileList\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  BaseAddress - GC_TODO: add argument description\r
+  Size        - GC_TODO: add argument description\r
+  PadByte     - GC_TODO: add argument description\r
+  OutFile     - GC_TODO: add argument description\r
+  FileList    - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageDll.c
new file mode 100644 (file)
index 0000000..c7d9b8b
--- /dev/null
@@ -0,0 +1,864 @@
+/*++\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+  Module Name:  \r
+          GenFdImageDll.C\r
+\r
+  Abstarct:\r
+          This file contains the relevant functions required to complete\r
+          the API to generate Firmware Device\r
+--*/\r
+\r
+// GC_TODO: fix comment to add:  Abstract:\r
+//\r
+// This tells the compiler to export the DLL functions\r
+//\r
+#define GEN_FD_IMAGE_EXPORTS\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <io.h>\r
+#include <assert.h>\r
+#include "TianoCommon.h"\r
+#include "GenFdImage.h"\r
+#include "GenFvImage.h"\r
+#include "ParseInf.h"\r
+\r
+//\r
+// Global declaration\r
+//\r
+UINTN         ValidLineNum  = 0;\r
+\r
+UINTN         NumFvFiles    = 0;\r
+static UINT64 LastAddress   = 0;\r
+\r
+CHAR8         **TokenStr;\r
+CHAR8         **OrgStrTokPtr;\r
+\r
+FDINFO        *FdInfo;\r
+FDINFO        *OrgFdInfoPtr;\r
+\r
+FVINFO        **FvInfo;\r
+FVINFO        **OrgFvInfoPtr;\r
+\r
+//\r
+// Global function declarations\r
+//\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+  IN UINT64   FvBaseAddress,\r
+  IN CHAR8    *FvFileName,\r
+  IN CHAR8    *FdFileName\r
+  );\r
+\r
+INTN\r
+CompareItems (\r
+  IN  const VOID *Arg1,\r
+  IN  const VOID *Arg2\r
+  )\r
+/*++\r
+Description:\r
+\r
+    This function is used by qsort to sort the Fv list based on FvBaseAddress\r
+\r
+Input:\r
+    Arg1\r
+    Arg2\r
+\r
+Return:\r
+\r
+    None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    Arg1 - add argument and description to function comment\r
+// GC_TODO:    Arg2 - add argument and description to function comment\r
+{\r
+  if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+    return 1;\r
+  } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+    return -1;\r
+  } else {\r
+    return 0;\r
+  }\r
+}\r
+\r
+VOID\r
+BuildTokenList (\r
+  IN  CHAR8 *Token\r
+  )\r
+/*++\r
+Description:\r
+\r
+    This function builds the token list in an array which will be parsed later\r
+\r
+Input:\r
+    Token    String,\r
+\r
+Return:\r
+\r
+    None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    Token - add argument and description to function comment\r
+{\r
+\r
+  strcpy (*TokenStr, Token);\r
+  TokenStr++;\r
+}\r
+\r
+VOID\r
+TrimLine (\r
+  IN  CHAR8 *Line\r
+  )\r
+/*++\r
+Description:\r
+\r
+  This function cleans up the line by removing all whitespace and \r
+  comments\r
+\r
+Input:\r
+\r
+  Line    String,\r
+\r
+Return:\r
+    None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    Line - add argument and description to function comment\r
+{\r
+  CHAR8 TmpLine[FILE_NAME_SIZE];\r
+  CHAR8 c;\r
+  CHAR8 *Ptr0;\r
+  UINTN i;\r
+  UINTN j;\r
+\r
+  //\r
+  // Change '#' to '//' for Comment style\r
+  //\r
+  //  if((Ptr0=strchr(Line, '#')) != NULL) {\r
+  //\r
+  if ((Ptr0 = strstr (Line, "//")) != NULL) {\r
+    Line[Ptr0 - Line] = 0;\r
+  }\r
+\r
+  i = j = 0;\r
+\r
+  while ((c = Line[i]) != 0) {\r
+    if ((c != ' ') && (c != '\t') && (c != '\n')) {\r
+      TmpLine[j++] = c;\r
+    }\r
+\r
+    i++;\r
+  }\r
+\r
+  TmpLine[j] = 0;\r
+  strcpy (Line, TmpLine);\r
+}\r
+\r
+VOID\r
+ValidLineCount (\r
+  IN  FILE *Fp\r
+  )\r
+/*++\r
+\r
+Description:\r
+\r
+  This function calculated number of valid lines in a input file.\r
+  \r
+Input:\r
+\r
+  Fp     Pointer to a file handle which has been opened.\r
+\r
+Return:\r
+\r
+  None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    Fp - add argument and description to function comment\r
+{\r
+  CHAR8 Buff[FILE_NAME_SIZE];\r
+\r
+  while (fgets (Buff, sizeof (Buff), Fp)) {\r
+    TrimLine (Buff);\r
+    if (Buff[0] == 0) {\r
+      continue;\r
+    }\r
+\r
+    ValidLineNum++;\r
+  }\r
+}\r
+\r
+VOID\r
+ParseInputFile (\r
+  IN  FILE *Fp\r
+  )\r
+/*++\r
+  \r
+Description:\r
+\r
+  This function parses the input file and tokenize the string\r
+  \r
+Input:\r
+\r
+  Fp     Pointer to a file handle which has been opened.\r
+  \r
+Return:\r
+\r
+  None\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    Fp - add argument and description to function comment\r
+{\r
+  CHAR8 *Token;\r
+  CHAR8 Buff[FILE_NAME_SIZE];\r
+  CHAR8 OrgLine[FILE_NAME_SIZE];\r
+  CHAR8 Str[FILE_NAME_SIZE];\r
+  CHAR8 Delimit[] = "=";\r
+\r
+  while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
+    strcpy (OrgLine, Buff);\r
+    TrimLine (Buff);\r
+\r
+    if (Buff[0] == 0) {\r
+      continue;\r
+    }\r
+\r
+    Token = strtok (Buff, Delimit);\r
+\r
+    while (Token != NULL) {\r
+      strcpy (Str, Token);\r
+      BuildTokenList (Str);\r
+      Token = strtok (NULL, Delimit);\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeComps (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Description:\r
+\r
+  This function intializes the relevant global variable which is being\r
+  used to store the information retrieved from INF file.\r
+  \r
+Input:\r
+\r
+  None\r
+\r
+Return:\r
+\r
+  EFI_STATUS\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  UINTN Index;\r
+\r
+  FdInfo = malloc (sizeof (FDINFO));\r
+\r
+  if (FdInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrgFdInfoPtr  = FdInfo;\r
+\r
+  FvInfo        = malloc (sizeof (int) * NumFvFiles);\r
+\r
+  if (FvInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrgFvInfoPtr = FvInfo;\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    *FvInfo = malloc (sizeof (FVINFO));\r
+\r
+    if (*FvInfo == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    memset (*FvInfo, 0, sizeof (FVINFO));\r
+    FvInfo++;\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitializeInFileInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Description:\r
+\r
+  This function intializes the relevant global variable which is being\r
+  used to store the information retrieved from INF file.\r
+\r
+Input:\r
+\r
+  NONE\r
+\r
+Return:\r
+\r
+  NONE\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+{\r
+  UINTN   OptionFlag;\r
+  UINT64  StringValue;\r
+\r
+  OptionFlag  = 0;\r
+  TokenStr    = OrgStrTokPtr;\r
+\r
+  while (*TokenStr != NULL) {\r
+    if (stricmp (*TokenStr, "[options]") == 0) {\r
+      OptionFlag = 1;\r
+    }\r
+\r
+    if (OptionFlag) {\r
+      if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {\r
+        *TokenStr++;\r
+        if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {\r
+          printf ("\nERROR: Cannot determine the FV base address.");\r
+          return ;\r
+        }\r
+        (*FvInfo)->FvBaseAddress = StringValue;\r
+      } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {\r
+        *TokenStr++;\r
+        strcpy ((*FvInfo)->FvFile, *TokenStr);\r
+      }\r
+    }\r
+\r
+    TokenStr++;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+GetFvRelatedInfoFromInfFile (\r
+  IN  CHAR8 *FileName\r
+  )\r
+/*++\r
+  \r
+Description:\r
+\r
+  This function reads the input file, parse it and create a list of tokens\r
+  which is parsed and used, to intialize the data related to Firmware Volume.\r
+  \r
+Input:\r
+\r
+  FileName  FileName which needed to be read to parse data\r
+\r
+Return:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    FileName - add argument and description to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE  *Fp;\r
+  UINTN Index;\r
+\r
+  Fp = fopen (FileName, "r");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("Error in opening %s file\n", FileName);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  ValidLineCount (Fp);\r
+\r
+  if (ValidLineNum == 0) {\r
+    printf ("\nFile doesn't contain any valid informations");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));\r
+  memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));\r
+  OrgStrTokPtr = TokenStr;\r
+\r
+  for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
+    *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
+    memset (*TokenStr, 0, FILE_NAME_SIZE);\r
+    TokenStr++;\r
+  }\r
+\r
+  *TokenStr = NULL;\r
+  TokenStr  = OrgStrTokPtr;\r
+  fseek (Fp, 0L, SEEK_SET);\r
+\r
+  ParseInputFile (Fp);\r
+  InitializeInFileInfo ();\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+WriteFwBinary (\r
+  IN  CHAR8   *FileName,\r
+  IN  UINT64  StartAddress,\r
+  IN  UINT64  Size,\r
+  IN  UINT8   *Buffer\r
+  )\r
+/*++\r
+  \r
+Description:\r
+\r
+  This function reads the input file, parse it and create a list of tokens\r
+  which is parsed and used, to intialize the data related to Firmware Volume.\r
+  \r
+Input:\r
+\r
+  FileName        FileName which needed to be read to parse data\r
+  StartAddress    This will set the file position.\r
+  Size            Size in bytes needed to be written\r
+  Buffer          Buffer needed to e written\r
+\r
+Return:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    FileName - add argument and description to function comment\r
+// GC_TODO:    StartAddress - add argument and description to function comment\r
+// GC_TODO:    Size - add argument and description to function comment\r
+// GC_TODO:    Buffer - add argument and description to function comment\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE  *Fp;\r
+  UINTN NumByte;\r
+\r
+  Fp = fopen (FileName, "a+b");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("\nERROR:Error in opening file %s ", FileName);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  fseek (Fp, (UINTN) StartAddress, SEEK_SET);\r
+  NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);\r
+\r
+  //\r
+  // Check to ensure that buffer has been copied successfully\r
+  //\r
+  if (NumByte != Size) {\r
+    printf ("\nERROR: Error in copying the buffer into file");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+  IN UINT64   FvBaseAddress,\r
+  IN CHAR8    *FvFileName,\r
+  IN CHAR8    *FdFileName\r
+  )\r
+/*++\r
+  \r
+Description:\r
+\r
+  This function reads the input file, parse it and create a list of tokens\r
+  which is parsed and used, to intialize the data related to Firmware Volume.\r
+  \r
+Input:\r
+\r
+  FvBaseAddress   Base Address. This info is retrieved from INF file\r
+  FvFileName      InputFileName\r
+  FdFileName      Output File Name\r
+\r
+Return:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    FvBaseAddress - add argument and description to function comment\r
+// GC_TODO:    FvFileName - add argument and description to function comment\r
+// GC_TODO:    FdFileName - add argument and description to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE          *Fp;\r
+  UINT64        FileSize;\r
+  UINT64        NumByteRead;\r
+  UINT64        PadByteSize;\r
+  UINTN         Index;\r
+  UINT64        BaseAddress;\r
+  UINT8         *Buffer;\r
+  EFI_STATUS    Status;\r
+  static UINT64 StartAddress  = 0;\r
+\r
+  Fp                          = fopen (FvFileName, "r+b");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("\nERROR:Error in opening file %s", FvFileName);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  BaseAddress = FdInfo->FdBaseAddress;\r
+\r
+  //\r
+  // Check if Base Address of Firmware Volume falls below the Base Address\r
+  // Firmware Device, if yes, then abort this process.\r
+  //\r
+  if (FvBaseAddress < BaseAddress) {\r
+    printf ("\nERROR: Firmware Volume Base Address falls below Firmware Device Address.\n");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Check if there are any hole between two Firmware Volumes. If any hole\r
+  // exists, fill the hole with PadByte data.\r
+  //\r
+  if (FvBaseAddress > LastAddress) {\r
+    PadByteSize = (FvBaseAddress - LastAddress);\r
+    Buffer      = malloc ((UINTN) PadByteSize);\r
+\r
+    for (Index = 0; Index < PadByteSize; Index++) {\r
+      *Buffer = FdInfo->PadValue;\r
+      Buffer++;\r
+    }\r
+\r
+    Buffer -= PadByteSize;\r
+    Status = WriteFwBinary (FdFileName, StartAddress, (UINT64) PadByteSize, Buffer);\r
+\r
+    if (Buffer) {\r
+      free (Buffer);\r
+    }\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      printf ("\nERROR: Error in writing the binary image to file");\r
+      return Status;\r
+    }\r
+\r
+    StartAddress += PadByteSize;\r
+    LastAddress += PadByteSize;\r
+  }\r
+  //\r
+  // Proceed with next Firmware Volume updates\r
+  //\r
+  FileSize = _filelength (fileno (Fp));\r
+\r
+  if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {\r
+    printf (\r
+      "\nERROR:Unable to update Firmware Device. File %s is larger than \\r
+                                  available space.",\r
+      FvFileName\r
+      );\r
+    if (Fp) {\r
+      fclose (Fp);\r
+    }\r
+\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Buffer = malloc ((UINTN) FileSize);\r
+\r
+  if (Buffer == NULL) {\r
+    printf ("Error in allocating buffer to read specific file\n");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
+\r
+  Status      = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);\r
+\r
+  if (Buffer) {\r
+    free ((VOID *) Buffer);\r
+  }\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  if (Status != EFI_SUCCESS) {\r
+    printf ("\nERROR: Error in writing the binary image to file");\r
+    return Status;\r
+  }\r
+\r
+  StartAddress += NumByteRead;\r
+  LastAddress += FileSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CleanUpMemory (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Description:\r
+\r
+  This function cleans up any allocated buffer\r
+  \r
+Input:\r
+\r
+  NONE\r
+\r
+Return:\r
+  \r
+  NONE\r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+{\r
+  UINTN Index;\r
+\r
+  if (FdInfo) {\r
+    free (FdInfo);\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  if (FvInfo) {\r
+    for (Index = 0; Index < NumFvFiles; Index++) {\r
+      if (*FvInfo) {\r
+        free (*FvInfo);\r
+      }\r
+\r
+      FvInfo++;\r
+    }\r
+\r
+    FvInfo = OrgFvInfoPtr;\r
+    free (FvInfo);\r
+  }\r
+}\r
+\r
+GEN_FD_IMAGE_API\r
+EFI_STATUS\r
+GenerateFdImage (\r
+  IN  UINT64  BaseAddress,\r
+  IN  UINT64  Size,\r
+  IN  UINT8   PadByte,\r
+  IN  CHAR8   *OutFile,\r
+  IN  CHAR8   **FileList\r
+  )\r
+/*++\r
+  \r
+Description:\r
+\r
+  This function reads the input file, parse it and create a list of tokens\r
+  which is parsed and used, to intialize the data related to Firmware Volume.\r
+  \r
+Input:\r
+\r
+  BaseAddress   Base Address for this Firmware Device\r
+  Size,         Total Size of the Firmware Device\r
+  PadByte       Pad byte data\r
+  OutFile       Output File Name\r
+  FileList      File List pointer to INF file names.\r
+\r
+Return:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO: function comment is missing 'Routine Description:'\r
+// GC_TODO: function comment is missing 'Arguments:'\r
+// GC_TODO: function comment is missing 'Returns:'\r
+// GC_TODO:    BaseAddress - add argument and description to function comment\r
+// GC_TODO:    Size - add argument and description to function comment\r
+// GC_TODO:    PadByte - add argument and description to function comment\r
+// GC_TODO:    OutFile - add argument and description to function comment\r
+// GC_TODO:    FileList - add argument and description to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS  Status;\r
+  UINTN       Index;\r
+  UINTN       PadSize;\r
+  UINTN       FileSize;\r
+  CHAR8       **InFile;\r
+  FILE        *Fp;\r
+  UINT8       *Buffer;\r
+  UINTN       NumByte;\r
+\r
+  //\r
+  // Ensure, if there are any previous Firmware Device exists,\r
+  // If yes, make it to 0 bytes\r
+  //\r
+  if ((Fp = fopen (OutFile, "w")) != NULL) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  InFile = FileList;\r
+\r
+  while (*InFile != NULL) {\r
+    NumFvFiles++;\r
+    InFile++;\r
+  }\r
+\r
+  InitializeComps ();\r
+\r
+  //\r
+  // Restore the orginal pointers\r
+  //\r
+  FvInfo  = OrgFvInfoPtr;\r
+  InFile  = FileList;\r
+\r
+  while (*InFile != NULL) {\r
+    strcpy ((*FvInfo)->FvInfoFile, *InFile);\r
+    Status = GetFvRelatedInfoFromInfFile (*InFile);\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      printf ("\nERROR: Error occurred in processsing INF file");\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    InFile++;\r
+    FvInfo++;\r
+  }\r
+\r
+  FdInfo->FdSize        = Size;\r
+  FdInfo->FdBaseAddress = BaseAddress;\r
+  FdInfo->PadValue      = PadByte;\r
+  FvInfo                = OrgFvInfoPtr;\r
+  strcpy (FdInfo->OutFileName, OutFile);\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    Status = GenerateFvImage ((*FvInfo)->FvInfoFile);\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    FvInfo++;\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  //\r
+  // Sort the Firmware Volume informations. Firmware Volume with lower\r
+  // base addresses will be processed first and hiher base address one\r
+  // will be processed later.\r
+  //\r
+  qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);\r
+\r
+  LastAddress = (*FvInfo)->FvBaseAddress;\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    Status = BuildFirmwareDeviceBinaryFromFwVolumes (\r
+              (*FvInfo)->FvBaseAddress,\r
+              (*FvInfo)->FvFile,\r
+              FdInfo->OutFileName\r
+              );\r
+    if (Status != EFI_SUCCESS) {\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    FvInfo++;\r
+  }\r
+  //\r
+  // Check if any space left after copying data from all Firmware Volumes\r
+  // If yes, then fill those location with PadValue.\r
+  //\r
+  if ((FdInfo->FdBaseAddress + Size) > LastAddress) {\r
+\r
+    PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);\r
+    Buffer  = malloc (PadSize);\r
+\r
+    if (Buffer == NULL) {\r
+      CleanUpMemory ();\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    for (Index = 0; Index < PadSize; Index++) {\r
+      *Buffer = FdInfo->PadValue;\r
+      Buffer++;\r
+    }\r
+\r
+    Buffer -= PadSize;\r
+\r
+    Fp = fopen (OutFile, "a+b");\r
+\r
+    if (Fp == NULL) {\r
+      printf ("\nERROR:Opening file %s", OutFile);\r
+      CleanUpMemory ();\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    FileSize = _filelength (fileno (Fp));\r
+    fseek (Fp, FileSize, SEEK_SET);\r
+    NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);\r
+\r
+    if (Buffer) {\r
+      free (Buffer);\r
+    }\r
+\r
+    fclose (Fp);\r
+\r
+    if (NumByte != (sizeof (UINT8) * PadSize)) {\r
+      printf ("\nERROR: Copying data from buffer to File %s ", OutFile);\r
+      CleanUpMemory ();\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  //\r
+  // Clean up all the memory which has been allocated so far.\r
+  //\r
+  CleanUpMemory ();\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.c
new file mode 100644 (file)
index 0000000..9c56d06
--- /dev/null
@@ -0,0 +1,330 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  GenFdImageExe.c\r
+\r
+Abstract:\r
+\r
+  This contains all code necessary to build the GenFdImage.exe utility.\r
+  This utility relies heavily on the GenFdImage Lib.  Definitions for both     \r
+  can be found in the GenFdImage Utility Specification, review draft.\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standards\r
+//\r
+//\r
+// Include files\r
+//\r
+#include "GenFdImage.h"\r
+#include "GenFdImageExe.h"\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "%s, EFI 2.0 Firmware Device Image Generation Utility. ""Version %i.%i, %s.\n\n",\r
+    UTILITY_NAME,\r
+    UTILITY_MAJOR_VERSION,\r
+    UTILITY_MINOR_VERSION,\r
+    UTILITY_DATE\r
+    );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "Usage: %s -B BaseAddress -S Size -F FillByte"" [-I FvInfFileName] -O OutputFileName \n",\r
+    UTILITY_NAME\r
+    );\r
+  printf ("  Where:\n");\r
+  printf ("\tBaseAddress is the starting address of the FD Image\n\n");\r
+  printf ("\tSize is the size of the FD Image.\n\n");\r
+  printf ("\tFillByte is the desired value of free space in the Image\n\n");\r
+  printf ("\tFvInfFileName is the name of an FV Image description file.\n\n");\r
+  printf ("\tOutputFileName is the desired output file name.\n\n");\r
+}\r
+\r
+EFI_STATUS\r
+main (\r
+  IN INTN   argc,\r
+  IN CHAR8  **argv\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This utility uses GenFdImage.lib to build a Firmware Device Image\r
+  which will include several Firmware Volume Images.\r
+\r
+Arguments:\r
+\r
+  Base Address      Base Address of the firmware volume..\r
+  Size              Size of the Firmware Volume\r
+  FillByte          The byte value which would be needed to pad\r
+                    between various Firmware Volumes\r
+  FvInfFile         Fv inf file\r
+  OutputFileName    The name of output file which would be created\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS            No error conditions detected.\r
+  EFI_INVALID_PARAMETER  One or more of the input parameters is invalid.\r
+  EFI_OUT_OF_RESOURCES   A resource required by the utility was unavailable.  \r
+                         Most commonly this will be memory allocation or \r
+                         file creation.\r
+  EFI_LOAD_ERROR         GenFvImage.lib could not be loaded.\r
+  EFI_ABORTED            Error executing the GenFvImage lib.\r
+\r
+--*/\r
+// GC_TODO:    argc - add argument and description to function comment\r
+// GC_TODO:    argv - add argument and description to function comment\r
+{\r
+  UINTN       Index;\r
+  UINTN       FvFilesCount;\r
+\r
+  UINT8       i;\r
+\r
+  UINT64      StartAddress;\r
+  UINT64      Size;\r
+  UINT64      FillByteVal;\r
+\r
+  CHAR8       **FvInfFileList;\r
+  CHAR8       **OrgFvInfFileList;\r
+  CHAR8       OutputFileName[_MAX_PATH];\r
+\r
+  EFI_STATUS  Status;\r
+\r
+  INTN        arg_counter;\r
+\r
+  //\r
+  //  Echo for makefile debug\r
+  //\r
+  printf ("\n\n");\r
+  for (arg_counter = 0; arg_counter < argc; arg_counter++) {\r
+    printf ("%s ", argv[arg_counter]);\r
+  }\r
+\r
+  printf ("\n\n");\r
+\r
+  //\r
+  // Display utility information\r
+  //\r
+  PrintUtilityInfo ();\r
+\r
+  //\r
+  // Verify the correct number of arguments\r
+  //\r
+  if (argc < MIN_ARGS) {\r
+    printf ("ERROR: missing 1 or more input arguments.\n\n");\r
+    PrintUsage ();\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Initialize variables\r
+  //\r
+  StartAddress  = 0;\r
+  Size          = 0;\r
+  FillByteVal   = 0;\r
+  FvFilesCount  = 0;\r
+\r
+  for (i = 1; i < argc; i++) {\r
+    if (stricmp (argv[i], "-I") == 0) {\r
+      FvFilesCount++;\r
+    }\r
+  }\r
+\r
+  FvInfFileList = malloc (sizeof (UINTN) * (FvFilesCount + 1));\r
+  if (FvInfFileList == NULL) {\r
+    printf ("ERROR: allocating memory for FvInfFileList in -main- function.\n");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  memset (FvInfFileList, 0, sizeof (UINTN) * (FvFilesCount + 1));\r
+\r
+  OrgFvInfFileList = FvInfFileList;\r
+\r
+  for (Index = 0; Index < FvFilesCount; Index++) {\r
+    *FvInfFileList = malloc (_MAX_PATH);\r
+    memset (*FvInfFileList, 0, _MAX_PATH);\r
+    FvInfFileList++;\r
+  }\r
+\r
+  strcpy (OutputFileName, "");\r
+\r
+  //\r
+  // Parse the command line arguments\r
+  //\r
+  FvInfFileList = OrgFvInfFileList;\r
+\r
+  for (i = 1; i < argc; i += 2) {\r
+    //\r
+    // Make sure argument pair begin with - or /\r
+    //\r
+    if (argv[i][0] != '-' && argv[i][0] != '/') {\r
+      PrintUsage ();\r
+      printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    //\r
+    // Make sure argument specifier is only one letter\r
+    //\r
+    if (argv[i][2] != 0) {\r
+      PrintUsage ();\r
+      printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    //\r
+    // Determine argument to read\r
+    //\r
+    switch (argv[i][1]) {\r
+\r
+    case 'I':\r
+    case 'i':\r
+      if ((FvInfFileList != NULL) && (strlen (*FvInfFileList) == 0)) {\r
+        strcpy (*FvInfFileList, argv[i + 1]);\r
+        FvInfFileList++;\r
+      } else {\r
+        printf ("ERROR: FvInfFile Name is more than specifed.\n");\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case 'O':\r
+    case 'o':\r
+      if (strlen (OutputFileName) == 0) {\r
+        strcpy (OutputFileName, argv[i + 1]);\r
+      } else {\r
+        PrintUsage ();\r
+        printf ("ERROR: OutputFileName may only be specified once.\n");\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case 'B':\r
+    case 'b':\r
+      Status = AsciiStringToUint64 (argv[i + 1], FALSE, &StartAddress);\r
+      if (Status != EFI_SUCCESS) {\r
+        printf ("\nERROR: Bad FD Image start address specified");\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case 'S':\r
+    case 's':\r
+      Status = AsciiStringToUint64 (argv[i + 1], FALSE, &Size);\r
+      if (Status != EFI_SUCCESS) {\r
+        printf ("\nERROR: Bad FD Image size specified");\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case 'F':\r
+    case 'f':\r
+      Status = AsciiStringToUint64 (argv[i + 1], FALSE, &FillByteVal);\r
+      if (Status != EFI_SUCCESS) {\r
+        printf ("\nERROR: Not a recognized Fill Byte value");\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      PrintUsage ();\r
+      printf ("ERROR: Unrecognized argument \"%s\".\n", argv[i]);\r
+      return EFI_INVALID_PARAMETER;\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Call the GenFdImage Lib\r
+  //\r
+  FvInfFileList = OrgFvInfFileList;\r
+\r
+  Status = GenerateFdImage (\r
+            StartAddress,\r
+            Size,\r
+            (UINT8) FillByteVal,\r
+            OutputFileName,\r
+            FvInfFileList\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    switch (Status) {\r
+\r
+    case EFI_INVALID_PARAMETER:\r
+      printf ("\nERROR: Invalid parameter passed to GenFdImage lib.\n");\r
+      break;\r
+\r
+    case EFI_ABORTED:\r
+      printf ("\nERROR: Error detected while creating the file image.\n");\r
+      break;\r
+\r
+    case EFI_OUT_OF_RESOURCES:\r
+      printf ("\nERROR: GenFdImage Lib could not allocate required resources.\n");\r
+      break;\r
+\r
+    case EFI_VOLUME_CORRUPTED:\r
+      printf ("\nERROR: No base address was specified \n");\r
+      break;\r
+\r
+    case EFI_LOAD_ERROR:\r
+      printf ("\nERROR: An error occurred loading one of the required support Lib.\n");\r
+      break;\r
+\r
+    default:\r
+      printf ("\nERROR: GenFdImage lib returned unknown status %X.\n", Status);\r
+      break;\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h b/Tools/Source/TianoTools/GenFdImage/GenFdImageExe.h
new file mode 100644 (file)
index 0000000..e07cb23
--- /dev/null
@@ -0,0 +1,91 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  GenFdImageExe.h\r
+\r
+Abstract:\r
+\r
+  Definitions for the Boot Strap File Image generation utility.\r
+\r
+--*/\r
+\r
+#ifndef _EFI_GEN_FD_IMAGE_EXE_H\r
+#define _EFI_GEN_FD_IMAGE_EXE_H\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME  "GenFdImage"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 0\r
+#define UTILITY_DATE          __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MIN_ARGS  10\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c b/Tools/Source/TianoTools/GenFdImage/GenFdImageLib.c
new file mode 100644 (file)
index 0000000..39698d9
--- /dev/null
@@ -0,0 +1,848 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  GenFdImageLib.C\r
+\r
+Abstract:\r
+\r
+  This file contains the functions required to generate \r
+  the Firmware Device\r
+\r
+--*/\r
+\r
+//\r
+// Coded to EFI 2.0 Coding Standards\r
+//\r
+//\r
+// Include file in build\r
+//\r
+#include "GenFdImage.h"\r
+\r
+//\r
+// Global declarations\r
+//\r
+UINTN         ValidLineNum  = 0;\r
+UINTN         NumFvFiles    = 0;\r
+\r
+static UINT64 LastAddress   = 0;\r
+\r
+CHAR8         **TokenStr;\r
+CHAR8         **OrgStrTokPtr;\r
+\r
+FDINFO        *FdInfo;\r
+FDINFO        *OrgFdInfoPtr;\r
+\r
+FVINFO        **FvInfo;\r
+FVINFO        **OrgFvInfoPtr;\r
+\r
+//\r
+// Internal Functions\r
+//\r
+INTN\r
+CompareItems (\r
+  IN const VOID  *Arg1,\r
+  IN const VOID  *Arg2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This function is used by qsort to sort the Fv list based on FvBaseAddress  \r
+\r
+Arguments:\r
+\r
+    Arg1\r
+    Arg2\r
+\r
+Returns:\r
+\r
+    None\r
+\r
+--*/\r
+// GC_TODO:    Arg1 - add argument and description to function comment\r
+// GC_TODO:    Arg2 - add argument and description to function comment\r
+{\r
+  if ((*(FVINFO **) Arg1)->FvBaseAddress > (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+    return 1;\r
+  } else if ((*(FVINFO **) Arg1)->FvBaseAddress < (*(FVINFO **) Arg2)->FvBaseAddress) {\r
+    return -1;\r
+  } else {\r
+    return 0;\r
+  }\r
+}\r
+\r
+VOID\r
+BuildTokenList (\r
+  IN CHAR8  *Token\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+    This function builds the token list in an array which will be parsed later\r
+\r
+Arguments:\r
+\r
+    Token    String,\r
+\r
+Returns:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+  strcpy (*TokenStr, Token);\r
+  TokenStr++;\r
+}\r
+\r
+VOID\r
+TrimLine (\r
+  IN CHAR8  *Line\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function cleans up the line by removing all whitespace and \r
+  comments.\r
+\r
+Arguments:\r
+\r
+  Line    String,\r
+\r
+Returns:\r
+\r
+    None\r
+\r
+--*/\r
+{\r
+  CHAR8 TmpLine[FILE_NAME_SIZE];\r
+  CHAR8 c;\r
+  CHAR8 *Ptr0;\r
+\r
+  UINTN i;\r
+  UINTN j;\r
+\r
+  //\r
+  // Change '#' to '//' for Comment style\r
+  //\r
+  //  if((Ptr0=strchr(Line, '#')) != NULL) {\r
+  //\r
+  if ((Ptr0 = strstr (Line, "//")) != NULL) {\r
+    Line[Ptr0 - Line] = 0;\r
+  }\r
+\r
+  i = 0;\r
+  j = 0;\r
+  while ((c = Line[i]) != 0) {\r
+    if ((c != ' ') && (c != '\t') && (c != '\n')) {\r
+      TmpLine[j++] = c;\r
+    }\r
+\r
+    i++;\r
+  }\r
+\r
+  TmpLine[j] = 0;\r
+  strcpy (Line, TmpLine);\r
+}\r
+\r
+VOID\r
+ValidLineCount (\r
+  IN FILE  *Fp\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function calculates number of valid lines in a input file.\r
+  \r
+Arguments:\r
+\r
+  Fp     Pointer to a file handle which has been opened.\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  CHAR8 Buff[FILE_NAME_SIZE];\r
+\r
+  while (fgets (Buff, sizeof (Buff), Fp)) {\r
+    TrimLine (Buff);\r
+    if (Buff[0] == 0) {\r
+      continue;\r
+    }\r
+\r
+    ValidLineNum++;\r
+  }\r
+}\r
+\r
+VOID\r
+ParseInputFile (\r
+  IN FILE  *Fp\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  This function parses the input file and tokenizes the string\r
+  \r
+Arguments:\r
+\r
+  Fp     Pointer to a file handle which has been opened.\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  CHAR8 *Token;\r
+  CHAR8 Buff[FILE_NAME_SIZE];\r
+  CHAR8 OrgLine[FILE_NAME_SIZE];\r
+  CHAR8 Str[FILE_NAME_SIZE];\r
+  CHAR8 Delimit[] = "=";\r
+\r
+  while (fgets (Buff, sizeof (Buff), Fp) != NULL) {\r
+    strcpy (OrgLine, Buff);\r
+    TrimLine (Buff);\r
+\r
+    if (Buff[0] == 0) {\r
+      continue;\r
+    }\r
+\r
+    Token = strtok (Buff, Delimit);\r
+\r
+    while (Token != NULL) {\r
+      strcpy (Str, Token);\r
+      BuildTokenList (Str);\r
+      Token = strtok (NULL, Delimit);\r
+    }\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+InitializeComps (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function intializes the relevant global variable \r
+  used to store the information retrieved from the INF file.\r
+  \r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+\r
+--*/\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  UINTN Index;\r
+\r
+  FdInfo = malloc (sizeof (FDINFO));\r
+\r
+  if (FdInfo == NULL) {\r
+    printf ("ERROR: allocating memory (struct FDINFO) in"" function InitializeComps.\n");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrgFdInfoPtr  = FdInfo;\r
+\r
+  FvInfo        = malloc (sizeof (INTN) * NumFvFiles);\r
+\r
+  if (FvInfo == NULL) {\r
+    printf ("ERROR: allocating memory (INTN * NumFvFiles) in"" function InitializeComps.\n");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  OrgFvInfoPtr = FvInfo;\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    *FvInfo = malloc (sizeof (FVINFO));\r
+\r
+    if (*FvInfo == NULL) {\r
+      printf ("ERROR: allocating memory (FVINFO) in"" function InitializeComps.\n");\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    memset (*FvInfo, 0, sizeof (FVINFO));\r
+    FvInfo++;\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+InitializeInFileInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function intializes the relevant global variable \r
+  used to store the information retrieved from the INF file.\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN   OptionFlag;\r
+\r
+  UINT64  StringValue;\r
+\r
+  OptionFlag  = 0;\r
+  TokenStr    = OrgStrTokPtr;\r
+\r
+  while (*TokenStr != NULL) {\r
+    if (stricmp (*TokenStr, "[options]") == 0) {\r
+      OptionFlag = 1;\r
+    }\r
+\r
+    if (OptionFlag) {\r
+      if (stricmp (*TokenStr, "EFI_FV_BASE_ADDRESS") == 0) {\r
+        *TokenStr++;\r
+        if (AsciiStringToUint64 (\r
+              *TokenStr,\r
+              FALSE,\r
+              &StringValue\r
+              ) != EFI_SUCCESS) {\r
+          printf ("\nERROR: Cannot determine the FV base address.");\r
+          return ;\r
+        }\r
+        (*FvInfo)->FvBaseAddress = StringValue;\r
+      } else if (stricmp (*TokenStr, "EFI_FV_FILE_NAME") == 0) {\r
+        *TokenStr++;\r
+        strcpy ((*FvInfo)->FvFile, *TokenStr);\r
+      }\r
+    }\r
+\r
+    TokenStr++;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+GetFvRelatedInfoFromInfFile (\r
+  IN CHAR8  *FileName\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  This function reads the input file, parses it and create a list of tokens\r
+  which are parsed and used, to intialize the data related to the Firmware \r
+  Volume.\r
+  \r
+Arguments:\r
+\r
+  FileName  FileName which needed to be read to parse data\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE  *Fp;\r
+\r
+  UINTN Index;\r
+\r
+  Fp = fopen (FileName, "r");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("Error in opening %s file\n", FileName);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  ValidLineCount (Fp);\r
+\r
+  if (ValidLineNum == 0) {\r
+    printf ("\nFile doesn't contain any valid informations");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum));\r
+  memset (TokenStr, 0, sizeof (UINTN) * (2 * ValidLineNum));\r
+  OrgStrTokPtr = TokenStr;\r
+\r
+  for (Index = 0; Index < (2 * ValidLineNum); Index++) {\r
+    *TokenStr = (CHAR8 *) malloc (sizeof (CHAR8) * FILE_NAME_SIZE);\r
+    memset (*TokenStr, 0, FILE_NAME_SIZE);\r
+    TokenStr++;\r
+  }\r
+\r
+  *TokenStr = NULL;\r
+  TokenStr  = OrgStrTokPtr;\r
+  fseek (Fp, 0L, SEEK_SET);\r
+\r
+  ParseInputFile (Fp);\r
+  InitializeInFileInfo ();\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+WriteFwBinary (\r
+  IN CHAR8   *FileName,\r
+  IN UINT64  StartAddress,\r
+  IN UINT64  Size,\r
+  IN UINT8   *Buffer\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  This function reads the input file, parses it and creates a list of tokens\r
+  which are parsed and used to intialize the data related to the Firmware \r
+  Volume.\r
+  \r
+Arguments:\r
+\r
+  FileName        FileName which needed to be read to parse data\r
+  StartAddress    This will set the file position.\r
+  Size            Size in bytes needed to be written\r
+  Buffer          Buffer needed to e written\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO:    EFI_INVALID_PARAMETER - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE  *Fp;\r
+\r
+  UINTN NumByte;\r
+\r
+  Fp = fopen (FileName, "a+b");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("\nERROR:Error in opening file %s ", FileName);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  fseek (Fp, (UINTN) StartAddress, SEEK_SET);\r
+  NumByte = fwrite ((VOID *) Buffer, sizeof (UINT8), (UINTN) Size, Fp);\r
+\r
+  //\r
+  // Check to ensure that buffer has been copied successfully\r
+  //\r
+  if (NumByte != Size) {\r
+    printf ("\nERROR: Error in copying the buffer into file");\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BuildFirmwareDeviceBinaryFromFwVolumes (\r
+  IN UINT64  FvBaseAddress,\r
+  IN CHAR8   *FvFileName,\r
+  IN CHAR8   *FdFileName\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  This function reads the input file, parses it and creates a list of tokens\r
+  which are parsed and used to intialize the data related to the Firmware \r
+  Volume.\r
+  \r
+Arguments:\r
+\r
+  FvBaseAddress   Base Address. This info is retrieved from INF file\r
+  FvFileName      InputFileName\r
+  FdFileName      Output File Name\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  FILE          *Fp;\r
+\r
+  UINT64        FileSize;\r
+  UINT64        NumByteRead;\r
+  UINT64        PadByteSize;\r
+  UINT64        BaseAddress;\r
+\r
+  UINTN         Index;\r
+\r
+  UINT8         *Buffer;\r
+\r
+  EFI_STATUS    Status;\r
+\r
+  static UINT64 StartAddress  = 0;\r
+\r
+  Fp                          = fopen (FvFileName, "r+b");\r
+\r
+  if (Fp == NULL) {\r
+    printf ("\nERROR:Error in opening file %s", FvFileName);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  BaseAddress = FdInfo->FdBaseAddress;\r
+\r
+  //\r
+  // Check if Base Address of Firmware Volume falls below the Base Address\r
+  // Firmware Device, if yes, then abort this process.\r
+  //\r
+  if (FvBaseAddress < BaseAddress) {\r
+    printf ("\nERROR: Firmware Volume Base Address falls below Firmware ""Device Address.\n");\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Check if there are any holes between two Firmware Volumes. If any holes\r
+  // exist, fill the hole with PadByted data.\r
+  //\r
+  if (FvBaseAddress > LastAddress) {\r
+    PadByteSize = (FvBaseAddress - LastAddress);\r
+    Buffer      = malloc ((UINTN) PadByteSize);\r
+    if (Buffer == NULL) {\r
+      printf ("ERROR: allocating (Buffer) memory in"" function BuildFirmwareDeviceBinaryFromFwVolumes.\n");\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    for (Index = 0; Index < PadByteSize; Index++) {\r
+      *Buffer = FdInfo->PadValue;\r
+      Buffer++;\r
+    }\r
+\r
+    Buffer -= PadByteSize;\r
+    Status = WriteFwBinary (\r
+              FdFileName,\r
+              StartAddress,\r
+              (UINT64) PadByteSize,\r
+              Buffer\r
+              );\r
+\r
+    if (Buffer) {\r
+      free (Buffer);\r
+    }\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      printf ("\nERROR: Error in writing the binary image to file");\r
+      return Status;\r
+    }\r
+\r
+    StartAddress += PadByteSize;\r
+    LastAddress += PadByteSize;\r
+  }\r
+  //\r
+  // Proceed with next Firmware Volume updates\r
+  //\r
+  FileSize = _filelength (fileno (Fp));\r
+\r
+  if ((FvBaseAddress + FileSize) > (FdInfo->FdBaseAddress + FdInfo->FdSize)) {\r
+    printf (\r
+      "\nERROR:Unable to update Firmware Device. File %s is larger than \\r
+                                  available space.",\r
+      FvFileName\r
+      );\r
+    if (Fp) {\r
+      fclose (Fp);\r
+    }\r
+\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  Buffer = malloc ((UINTN) FileSize);\r
+\r
+  if (Buffer == NULL) {\r
+    printf ("Error in allocating buffer to read specific file\n");\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  NumByteRead = fread ((VOID *) Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);\r
+\r
+  Status      = WriteFwBinary (FdFileName, StartAddress, FileSize, Buffer);\r
+\r
+  if (Buffer) {\r
+    free ((VOID *) Buffer);\r
+  }\r
+\r
+  if (Fp) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  if (Status != EFI_SUCCESS) {\r
+    printf ("\nERROR: Error in writing the binary image to file");\r
+    return Status;\r
+  }\r
+\r
+  StartAddress += NumByteRead;\r
+  LastAddress += FileSize;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+CleanUpMemory (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function cleans up any allocated buffer\r
+  \r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+  \r
+  None\r
+\r
+--*/\r
+{\r
+  UINTN Index;\r
+\r
+  if (FdInfo) {\r
+    free (FdInfo);\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  if (FvInfo) {\r
+    for (Index = 0; Index < NumFvFiles; Index++) {\r
+      if (*FvInfo) {\r
+        free (*FvInfo);\r
+      }\r
+\r
+      FvInfo++;\r
+    }\r
+\r
+    FvInfo = OrgFvInfoPtr;\r
+    free (FvInfo);\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+GenerateFdImage (\r
+  IN UINT64  BaseAddress,\r
+  IN UINT64  Size,\r
+  IN UINT8   PadByte,\r
+  IN CHAR8   *OutFile,\r
+  IN CHAR8   **FileList\r
+  )\r
+/*++\r
+  \r
+Routine Description:\r
+\r
+  This function reads the input file, parses it and creates a list of tokens\r
+  which are parsed and used to intialize the data related to the Firmware \r
+  Volume.\r
+  \r
+Arguments:\r
+\r
+  BaseAddress   Base Address for this Firmware Device\r
+  Size,         Total Size of the Firmware Device\r
+  PadByte       Pad byte data\r
+  OutFile       Output File Name\r
+  FileList      File List pointer to INF file names.\r
+\r
+Returns:\r
+\r
+  EFI_STATUS\r
+    \r
+--*/\r
+// GC_TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_ABORTED - add return value to function comment\r
+// GC_TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  UINTN       Index;\r
+  UINTN       PadSize;\r
+  UINTN       FileSize;\r
+  UINTN       NumByte;\r
+\r
+  CHAR8       **InFile;\r
+\r
+  FILE        *Fp;\r
+\r
+  UINT8       *Buffer;\r
+\r
+  //\r
+  // If any previous Firmware Device existed,\r
+  // make it to 0 bytes\r
+  //\r
+  if ((Fp = fopen (OutFile, "w")) != NULL) {\r
+    fclose (Fp);\r
+  }\r
+\r
+  InFile = FileList;\r
+\r
+  while (*InFile != NULL) {\r
+    NumFvFiles++;\r
+    InFile++;\r
+  }\r
+\r
+  InitializeComps ();\r
+\r
+  //\r
+  // Restore the orginal pointers\r
+  //\r
+  FvInfo  = OrgFvInfoPtr;\r
+  InFile  = FileList;\r
+\r
+  while (*InFile != NULL) {\r
+    strcpy ((*FvInfo)->FvInfoFile, *InFile);\r
+    Status = GetFvRelatedInfoFromInfFile (*InFile);\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      printf ("\nERROR: Error occurred in processsing INF file");\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    InFile++;\r
+    FvInfo++;\r
+  }\r
+\r
+  FdInfo->FdSize        = Size;\r
+  FdInfo->FdBaseAddress = BaseAddress;\r
+  FdInfo->PadValue      = PadByte;\r
+  FvInfo                = OrgFvInfoPtr;\r
+  strcpy (FdInfo->OutFileName, OutFile);\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    Status = GenerateFvImage ((*FvInfo)->FvInfoFile);\r
+\r
+    if (Status != EFI_SUCCESS) {\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    FvInfo++;\r
+  }\r
+\r
+  FvInfo = OrgFvInfoPtr;\r
+\r
+  //\r
+  // Sort the Firmware Volume information. Firmware Volume with lower\r
+  // base addresses will be processed first and higher base address one\r
+  // will be processed later.\r
+  //\r
+  qsort ((VOID *) FvInfo, NumFvFiles, sizeof (FVINFO *), CompareItems);\r
+\r
+  LastAddress = (*FvInfo)->FvBaseAddress;\r
+\r
+  for (Index = 0; Index < NumFvFiles; Index++) {\r
+    Status = BuildFirmwareDeviceBinaryFromFwVolumes (\r
+              (*FvInfo)->FvBaseAddress,\r
+              (*FvInfo)->FvFile,\r
+              FdInfo->OutFileName\r
+              );\r
+    if (Status != EFI_SUCCESS) {\r
+      CleanUpMemory ();\r
+      return Status;\r
+    }\r
+\r
+    FvInfo++;\r
+  }\r
+  //\r
+  // Check if any space left after copying data from all Firmware Volumes\r
+  // If yes, then fill those location with PadValue.\r
+  //\r
+  if ((FdInfo->FdBaseAddress + Size) > LastAddress) {\r
+\r
+    PadSize = (UINTN) ((FdInfo->FdBaseAddress + FdInfo->FdSize) - LastAddress);\r
+    Buffer  = malloc (PadSize);\r
+\r
+    if (Buffer == NULL) {\r
+      printf ("\nERROR: allocating PadSize memory in function GenerateFdImage.\n");\r
+      CleanUpMemory ();\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    for (Index = 0; Index < PadSize; Index++) {\r
+      *Buffer = FdInfo->PadValue;\r
+      Buffer++;\r
+    }\r
+\r
+    Buffer -= PadSize;\r
+\r
+    Fp = fopen (OutFile, "a+b");\r
+\r
+    if (Fp == NULL) {\r
+      printf ("\nERROR:Opening file %s", OutFile);\r
+      CleanUpMemory ();\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    FileSize = _filelength (fileno (Fp));\r
+    fseek (Fp, FileSize, SEEK_SET);\r
+    NumByte = fwrite (Buffer, sizeof (UINT8), PadSize, Fp);\r
+\r
+    if (Buffer) {\r
+      free (Buffer);\r
+    }\r
+\r
+    fclose (Fp);\r
+\r
+    if (NumByte != (sizeof (UINT8) * PadSize)) {\r
+      printf ("\nERROR: Copying data from buffer to File %s ", OutFile);\r
+      CleanUpMemory ();\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+  //\r
+  // Clean up all the memory which has been allocated so far.\r
+  //\r
+  CleanUpMemory ();\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/GenFdImage/Makefile b/Tools/Source/TianoTools/GenFdImage/Makefile
new file mode 100644 (file)
index 0000000..94fafaf
--- /dev/null
@@ -0,0 +1,100 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE      = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC) \\r
+    -I "$(TIANO_TOOLS_SOURCE)\GenFvImage"\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=GenFdImage\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_LIB = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).lib\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.c"\r
+TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImageExe.h" \\r
+                     "$(TARGET_SOURCE_DIR)\GenFdImage.h" \\r
+                     "$(COMMON_SOURCE)\ParseInf.h" \\r
+                     "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"\r
+TARGET_EXE_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \\r
+                  "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \\r
+                  "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"\r
+\r
+TARGET_LIB_SOURCE = "$(TARGET_SOURCE_DIR)\GenFdImageLib.c"\r
+TARGET_LIB_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFdImage.h" \\r
+                     "$(TIANO_TOOLS_SOURCE)\GenFvImage\GenFvImage.h" \\r
+                     "$(COMMON_SOURCE)\ParseInf.h" \\r
+                     "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h"\r
+TARGET_LIB_LIBS = "$(TIANO_TOOLS_OUTPUT)\Common.lib" \\r
+                  "$(TIANO_TOOLS_OUTPUT)\GenFvImage.lib" \\r
+                  "$(TIANO_TOOLS_OUTPUT)\PeimFixup.lib"\r
+\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_LIB) $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_LIB)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB)  $(TARGET_EXE_LIBS)\r
+\r
+#\r
+# Build LIB\r
+#\r
+\r
+$(TARGET_LIB): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj $(TARGET_LIB_LIBS)\r
+  $(LIB) $(LIB_FLAGS) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj /OUT:$(TARGET_LIB)\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj:  $(TARGET_LIB_SOURCE) $(TARGET_LIB_INCLUDE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_LIB_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj\r
+\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* > NUL\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del /q $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/GenTEImage/GenTEImage.c b/Tools/Source/TianoTools/GenTEImage/GenTEImage.c
new file mode 100644 (file)
index 0000000..8aef6d3
--- /dev/null
@@ -0,0 +1,919 @@
+/*++\r
+\r
+Copyright (c) 1999-2004 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+Module Name:\r
+\r
+  GenTEImage.c\r
+  \r
+Abstract:\r
+\r
+  Utility program to shrink a PE32 image down by replacing\r
+  the DOS, PE, and optional headers with a minimal header.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+#include "Tiano.h"\r
+#include "TianoCommon.h"\r
+#include "EfiImage.h" // for PE32 structure definitions\r
+#include "EfiUtilityMsgs.h"\r
+\r
+//\r
+// Version of this utility\r
+//\r
+#define UTILITY_NAME    "GenTEImage"\r
+#define UTILITY_VERSION "v0.11"\r
+\r
+//\r
+// Define the max length of a filename\r
+//\r
+#define MAX_PATH                  256\r
+#define DEFAULT_OUTPUT_EXTENSION  ".te"\r
+\r
+//\r
+// Use this to track our command-line options and globals\r
+//\r
+struct {\r
+  INT8  OutFileName[MAX_PATH];\r
+  INT8  InFileName[MAX_PATH];\r
+  INT8  Verbose;\r
+  INT8  Dump;\r
+} mOptions;\r
+\r
+//\r
+// Use these to convert from machine type value to a named type\r
+//\r
+typedef struct {\r
+  UINT16  Value;\r
+  INT8    *Name;\r
+} STRING_LOOKUP;\r
+\r
+static STRING_LOOKUP  mMachineTypes[] = {\r
+  EFI_IMAGE_MACHINE_IA32,\r
+  "IA32",\r
+  EFI_IMAGE_MACHINE_IA64,\r
+  "IA64",\r
+  EFI_IMAGE_MACHINE_EBC,\r
+  "EBC",\r
+  0,\r
+  NULL\r
+};\r
+\r
+static STRING_LOOKUP  mSubsystemTypes[] = {\r
+  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
+  "EFI application",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
+  "EFI boot service driver",\r
+  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
+  "EFI runtime driver",\r
+  0,\r
+  NULL\r
+};\r
+//\r
+//  Function prototypes\r
+//\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  );\r
+\r
+static\r
+STATUS\r
+ParseCommandLine (\r
+  int       Argc,\r
+  char      *Argv[]\r
+  );\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+  INT8      *FileName,\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  );\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  INT8      *InFileName,\r
+  INT8      *OutFileName\r
+  );\r
+\r
+static\r
+void\r
+DumpImage (\r
+  INT8      *FileName\r
+  );\r
+\r
+static\r
+INT8                  *\r
+GetMachineTypeStr (\r
+  UINT16    MachineType\r
+  );\r
+\r
+static\r
+INT8                  *\r
+GetSubsystemTypeStr (\r
+  UINT16  SubsystemType\r
+  );\r
+\r
+main (\r
+  int   Argc,\r
+  char  *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+\r
+  Argv            - standard C main() argument list\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  INT8    *Ext;\r
+  UINT32  Status;\r
+\r
+  SetUtilityName (UTILITY_NAME);\r
+  //\r
+  // Parse the command line arguments\r
+  //\r
+  if (ParseCommandLine (Argc, Argv)) {\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // If dumping an image, then do that and quit\r
+  //\r
+  if (mOptions.Dump) {\r
+    DumpImage (mOptions.InFileName);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Determine the output filename. Either what they specified on\r
+  // the command line, or the first input filename with a different extension.\r
+  //\r
+  if (!mOptions.OutFileName[0]) {\r
+    strcpy (mOptions.OutFileName, mOptions.InFileName);\r
+    //\r
+    // Find the last . on the line and replace the filename extension with\r
+    // the default\r
+    //\r
+    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
+         Ext--\r
+        )\r
+      ;\r
+    //\r
+    // If dot here, then insert extension here, otherwise append\r
+    //\r
+    if (*Ext != '.') {\r
+      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+    }\r
+\r
+    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+  }\r
+  //\r
+  // Make sure we don't have the same filename for input and output files\r
+  //\r
+  if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
+    Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Process the file\r
+  //\r
+  ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
+Finish:\r
+  Status = GetUtilityStatus ();\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+ProcessFile (\r
+  INT8      *InFileName,\r
+  INT8      *OutFileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Process a PE32 EFI file.\r
+\r
+Arguments:\r
+  \r
+  InFileName      - the file name pointer to the input file\r
+  OutFileName     - the file name pointer to the output file\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS  - the process has been finished successfully\r
+  STATUS_ERROR    - error occured during the processing\r
+\r
+--*/\r
+{\r
+  STATUS                      Status;\r
+  FILE                        *InFptr;\r
+  FILE                        *OutFptr;\r
+  UINT16                      MachineType;\r
+  UINT16                      SubSystem;\r
+  EFI_TE_IMAGE_HEADER         TEImageHeader;\r
+  UINT32                      PESigOffset;\r
+  EFI_IMAGE_FILE_HEADER       FileHeader;\r
+  EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
+  EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;\r
+  UINT32                      BytesStripped;\r
+  UINT32                      FileSize;\r
+  UINT8                       *Buffer;\r
+  long                        SaveFilePosition;\r
+\r
+  InFptr  = NULL;\r
+  OutFptr = NULL;\r
+  Buffer  = NULL;\r
+  Status  = STATUS_ERROR;\r
+\r
+  //\r
+  // Try to open the input file\r
+  //\r
+  if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
+    Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Double-check the file to make sure it's what we expect it to be\r
+  //\r
+  if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Initialize our new header\r
+  //\r
+  memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
+\r
+  //\r
+  // Seek to the end to get the file size\r
+  //\r
+  fseek (InFptr, 0, SEEK_END);\r
+  FileSize = ftell (InFptr);\r
+  fseek (InFptr, 0, SEEK_SET);\r
+\r
+  //\r
+  // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
+  // offset (from the start of the file) to the PE signature, which always\r
+  // follows the MSDOS stub. The PE signature is immediately followed by the\r
+  // COFF file header.\r
+  //\r
+  //\r
+  if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
+    goto Finish;\r
+  }\r
+\r
+  if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
+    Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // We should now be at the COFF file header. Read it in and verify it's\r
+  // of an image type we support.\r
+  //\r
+  if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
+    goto Finish;\r
+  }\r
+\r
+  if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64)) {\r
+    Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Calculate the total number of bytes we're going to strip off. The '4' is for the\r
+  // PE signature PE\0\0. Then sanity check the size.\r
+  //\r
+  BytesStripped = PESigOffset + 4 + sizeof (EFI_IMAGE_FILE_HEADER) + FileHeader.SizeOfOptionalHeader;\r
+  if (BytesStripped >= FileSize) {\r
+    Error (NULL, 0, 0, InFileName, "attempt to strip more bytes than the total file size");\r
+    goto Finish;\r
+  }\r
+\r
+  if (BytesStripped &~0xFFFF) {\r
+    Error (NULL, 0, 0, InFileName, "attempt to strip more than 64K bytes", NULL);\r
+    goto Finish;\r
+  }\r
+\r
+  TEImageHeader.StrippedSize = (UINT16) BytesStripped;\r
+\r
+  //\r
+  // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
+  //\r
+  SaveFilePosition = ftell (InFptr);\r
+  if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    //\r
+    // Fill in our new header with required data directory entries\r
+    //\r
+    TEImageHeader.AddressOfEntryPoint = OptionalHeader32.AddressOfEntryPoint;\r
+    //\r
+    // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);\r
+    //\r
+    // We're going to pack the subsystem into 1 byte. Make sure it fits\r
+    //\r
+    if (OptionalHeader32.Subsystem &~0xFF) {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        InFileName,\r
+        NULL,\r
+        "image subsystem 0x%X cannot be packed into 1 byte",\r
+        (UINT32) OptionalHeader32.Subsystem\r
+        );\r
+      goto Finish;\r
+    }\r
+\r
+    TEImageHeader.Subsystem   = (UINT8) OptionalHeader32.Subsystem;\r
+    TEImageHeader.BaseOfCode  = OptionalHeader32.BaseOfCode;\r
+    TEImageHeader.ImageBase = (UINT64) (OptionalHeader32.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+    if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+    }\r
+\r
+    if (OptionalHeader32.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader32.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+    }\r
+  } else if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    //\r
+    // Rewind and re-read the optional header\r
+    //\r
+    fseek (InFptr, SaveFilePosition, SEEK_SET);\r
+    if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
+      Error (NULL, 0, 0, InFileName, "failed to re-read optional header from input file");\r
+      goto Finish;\r
+    }\r
+\r
+    TEImageHeader.AddressOfEntryPoint = OptionalHeader64.AddressOfEntryPoint;\r
+    //\r
+    // - BytesStripped + sizeof (EFI_TE_IMAGE_HEADER);\r
+    //\r
+    // We're going to pack the subsystem into 1 byte. Make sure it fits\r
+    //\r
+    if (OptionalHeader64.Subsystem &~0xFF) {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        InFileName,\r
+        NULL,\r
+        "image subsystem 0x%X cannot be packed into 1 byte",\r
+        (UINT32) OptionalHeader64.Subsystem\r
+        );\r
+      goto Finish;\r
+    }\r
+\r
+    TEImageHeader.Subsystem   = (UINT8) OptionalHeader64.Subsystem;\r
+    TEImageHeader.BaseOfCode  = OptionalHeader32.BaseOfCode;\r
+    TEImageHeader.ImageBase = (UINT64) (OptionalHeader64.ImageBase + TEImageHeader.StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+    if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+    }\r
+\r
+    if (OptionalHeader64.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+      TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = OptionalHeader64.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+    }\r
+  } else {\r
+    Error (\r
+      NULL,\r
+      0,\r
+      0,\r
+      InFileName,\r
+      "unsupported magic number 0x%X found in optional header",\r
+      (UINT32) OptionalHeader32.Magic\r
+      );\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Fill in the remainder of our new image header\r
+  //\r
+  TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
+  TEImageHeader.Machine   = FileHeader.Machine;\r
+  //\r
+  // We're going to pack the number of sections into a single byte. Make sure it fits.\r
+  //\r
+  if (FileHeader.NumberOfSections &~0xFF) {\r
+    Error (\r
+      NULL,\r
+      0,\r
+      0,\r
+      InFileName,\r
+      NULL,\r
+      "image's number of sections 0x%X cannot be packed into 1 byte",\r
+      (UINT32) FileHeader.NumberOfSections\r
+      );\r
+    goto Finish;\r
+  }\r
+\r
+  TEImageHeader.NumberOfSections = (UINT8) FileHeader.NumberOfSections;\r
+\r
+  //\r
+  // Now open our output file\r
+  //\r
+  if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Write the TE header\r
+  //\r
+  if (fwrite (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, "failed to write image header to output file", NULL);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Position into the input file, read the part we're not stripping, and\r
+  // write it out.\r
+  //\r
+  fseek (InFptr, BytesStripped, SEEK_SET);\r
+  Buffer = (UINT8 *) malloc (FileSize - BytesStripped);\r
+  if (Buffer == NULL) {\r
+    Error (NULL, 0, 0, "application error", "failed to allocate memory");\r
+    goto Finish;\r
+  }\r
+\r
+  if (fread (Buffer, FileSize - BytesStripped, 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, InFileName, "failed to read remaining contents of input file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (fwrite (Buffer, FileSize - BytesStripped, 1, OutFptr) != 1) {\r
+    Error (NULL, 0, 0, OutFileName, "failed to write all bytes to output file");\r
+    goto Finish;\r
+  }\r
+\r
+  Status = STATUS_SUCCESS;\r
+\r
+Finish:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+  //\r
+  // Close the output file. If there was an error, delete the output file so\r
+  // that a subsequent build will rebuild it.\r
+  //\r
+  if (OutFptr != NULL) {\r
+    fclose (OutFptr);\r
+    if (GetUtilityStatus () == STATUS_ERROR) {\r
+      remove (OutFileName);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Free up our buffer\r
+  //\r
+  if (Buffer != NULL) {\r
+    free (Buffer);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+CheckPE32File (\r
+  INT8      *FileName,\r
+  FILE      *Fptr,\r
+  UINT16    *MachineType,\r
+  UINT16    *SubSystem\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileName    - GC_TODO: add argument description\r
+  Fptr        - GC_TODO: add argument description\r
+  MachineType - GC_TODO: add argument description\r
+  SubSystem   - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  /*++\r
+\r
+Routine Description:\r
+  \r
+  Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
+  PE32 image file, and then return the machine type in the supplied pointer.\r
+\r
+Arguments:\r
+\r
+  Fptr          File pointer to the already-opened PE32 file\r
+  MachineType   Location to stuff the machine type of the PE32 file. This is needed\r
+                because the image may be Itanium-based, IA32, or EBC.\r
+\r
+Returns:\r
+\r
+  0             success\r
+  non-zero      otherwise\r
+\r
+--*/\r
+  EFI_IMAGE_DOS_HEADER      DosHeader;\r
+  EFI_IMAGE_FILE_HEADER     FileHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
+  UINT32                    PESig;\r
+  STATUS                    Status;\r
+\r
+  Status = STATUS_ERROR;\r
+  //\r
+  // Position to the start of the file\r
+  //\r
+  fseek (Fptr, 0, SEEK_SET);\r
+  //\r
+  // Read the DOS header\r
+  //\r
+  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Check the magic number (0x5A4D)\r
+  //\r
+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Position into the file and check the PE signature\r
+  //\r
+  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
+  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Check the PE signature in the header "PE\0\0"\r
+  //\r
+  if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read the file header\r
+  //\r
+  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read the optional header so we can get the subsystem\r
+  //\r
+  if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
+    goto Finish;\r
+  }\r
+\r
+  *SubSystem = OptionalHdr.Subsystem;\r
+  if (mOptions.Verbose) {\r
+    fprintf (stdout, "  Got subsystem = 0x%X from image\n", (int) *SubSystem);\r
+  }\r
+  //\r
+  // Good to go\r
+  //\r
+  Status = STATUS_SUCCESS;\r
+Finish:\r
+  fseek (Fptr, 0, SEEK_SET);\r
+  return Status;\r
+}\r
+\r
+static\r
+int\r
+ParseCommandLine (\r
+  int         Argc,\r
+  char        *Argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Given the Argc/Argv program arguments, and a pointer to an options structure,\r
+  parse the command-line options and check their validity.\r
+\r
+\r
+Arguments:\r
+\r
+  Argc            - standard C main() argument count\r
+  Argv            - standard C main() argument list\r
+\r
+Returns:\r
+\r
+  STATUS_SUCCESS    success\r
+  non-zero          otherwise\r
+\r
+--*/\r
+// GC_TODO:    ] - add argument and description to function comment\r
+{\r
+  //\r
+  // Clear out the options\r
+  //\r
+  memset ((char *) &mOptions, 0, sizeof (mOptions));\r
+  //\r
+  // Skip over the program name\r
+  //\r
+  Argc--;\r
+  Argv++;\r
+  //\r
+  // If no arguments, assume they want usage info\r
+  //\r
+  if (Argc == 0) {\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Process until no more arguments\r
+  //\r
+  while ((Argc > 0) && ((Argv[0][0] == '-') || (Argv[0][0] == '/'))) {\r
+    //\r
+    // To simplify string comparisons, replace slashes with dashes\r
+    //\r
+    Argv[0][0] = '-';\r
+    if (stricmp (Argv[0], "-o") == 0) {\r
+      //\r
+      // Output filename specified with -o\r
+      // Make sure there's another parameter\r
+      //\r
+      if (Argc > 1) {\r
+        strcpy (mOptions.OutFileName, Argv[1]);\r
+      } else {\r
+        Error (NULL, 0, 0, Argv[0], "missing output file name with option");\r
+        Usage ();\r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      Argv++;\r
+      Argc--;\r
+    } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) {\r
+      //\r
+      // Help option\r
+      //\r
+      Usage ();\r
+      return STATUS_ERROR;\r
+    } else if (stricmp (Argv[0], "-v") == 0) {\r
+      //\r
+      // -v for verbose\r
+      //\r
+      mOptions.Verbose = 1;\r
+    } else if (stricmp (Argv[0], "-dump") == 0) {\r
+      //\r
+      // -dump for dumping an image\r
+      //\r
+      mOptions.Dump = 1;\r
+    } else {\r
+      Error (NULL, 0, 0, Argv[0], "unrecognized option");\r
+      Usage ();\r
+      return STATUS_ERROR;\r
+    }\r
+    //\r
+    // Next argument\r
+    //\r
+    Argv++;\r
+    Argc--;\r
+  }\r
+  //\r
+  // Better be one more arg for input file name\r
+  //\r
+  if (Argc == 0) {\r
+    Error (NULL, 0, 0, "input file name required", NULL);\r
+    Usage ();\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (Argc != 1) {\r
+    Error (NULL, 0, 0, Argv[1], "extra arguments on command line");\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  strcpy (mOptions.InFileName, Argv[0]);\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+  None.\r
+\r
+Returns:\r
+\r
+  Nothing.\r
+\r
+--*/\r
+{\r
+  int               Index;\r
+  static const char *Msg[] = {\r
+    UTILITY_NAME " version "UTILITY_VERSION " - TE image utility",\r
+    "  Generate a TE image from an EFI PE32 image",\r
+    "  Usage: "UTILITY_NAME " {-v} {-dump} {-h|-?} {-o OutFileName} InFileName",\r
+    "                [-e|-b] [FileName(s)]",\r
+    "    where:",\r
+    "      -v             - for verbose output",\r
+    "      -dump          - to dump the input file to a text file",\r
+    "      -h -?          - for this help information",\r
+    "      -o OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
+    "      InFileName     - name of the input PE32 file",\r
+    "",\r
+    NULL\r
+  };\r
+  for (Index = 0; Msg[Index] != NULL; Index++) {\r
+    fprintf (stdout, "%s\n", Msg[Index]);\r
+  }\r
+}\r
+\r
+static\r
+VOID\r
+DumpImage (\r
+  INT8    *FileName\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+  \r
+  Dump a specified image information\r
+\r
+Arguments:\r
+  \r
+  FileName - File name pointer to the image to dump\r
+\r
+Returns:\r
+\r
+  Nothing.\r
+\r
+--*/\r
+{\r
+  FILE                *InFptr;\r
+  EFI_TE_IMAGE_HEADER TEImageHeader;\r
+  INT8                *NamePtr;\r
+\r
+  //\r
+  // Open the input file\r
+  //\r
+  InFptr  = NULL;\r
+\r
+  if ((InFptr = fopen (FileName, "rb")) == NULL) {\r
+    Error (NULL, 0, 0, FileName, "failed to open input file for reading");\r
+    return ;\r
+  }\r
+\r
+  if (fread (&TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER), 1, InFptr) != 1) {\r
+    Error (NULL, 0, 0, FileName, "failed to read image header from input file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    Error (NULL, 0, 0, FileName, "Image does not appear to be a TE image (bad signature)");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Dump the header\r
+  //\r
+  fprintf (stdout, "Header (%d bytes):\n", sizeof (EFI_TE_IMAGE_HEADER));\r
+  fprintf (stdout, "  Signature:          0x%04X (TE)\n", (UINT32) TEImageHeader.Signature);\r
+  NamePtr = GetMachineTypeStr (TEImageHeader.Machine);\r
+  fprintf (stdout, "  Machine:            0x%04X (%s)\n", (UINT32) TEImageHeader.Machine, NamePtr);\r
+  NamePtr = GetSubsystemTypeStr (TEImageHeader.Subsystem);\r
+  fprintf (stdout, "  Subsystem:          0x%02X (%s)\n", (UINT32) TEImageHeader.Subsystem, NamePtr);\r
+  fprintf (stdout, "  Number of sections  0x%02X\n", (UINT32) TEImageHeader.NumberOfSections);\r
+  fprintf (stdout, "  Stripped size:      0x%04X\n", (UINT32) TEImageHeader.StrippedSize);\r
+  fprintf (stdout, "  Entry point:        0x%08X\n", TEImageHeader.AddressOfEntryPoint);\r
+  fprintf (stdout, "  Base of code:       0x%08X\n", TEImageHeader.BaseOfCode);\r
+  fprintf (stdout, "  Data directories:\n");\r
+  fprintf (\r
+    stdout,\r
+    "    %8X [%8X] RVA [size] of Base Relocation Directory\n",\r
+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,\r
+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size\r
+    );\r
+  fprintf (\r
+    stdout,\r
+    "    %8X [%8X] RVA [size] of Debug Directory\n",\r
+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress,\r
+    TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size\r
+    );\r
+\r
+Finish:\r
+  if (InFptr != NULL) {\r
+    fclose (InFptr);\r
+  }\r
+}\r
+\r
+static\r
+INT8 *\r
+GetMachineTypeStr (\r
+  UINT16    MachineType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  MachineType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  int Index;\r
+\r
+  for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {\r
+    if (mMachineTypes[Index].Value == MachineType) {\r
+      return mMachineTypes[Index].Name;\r
+    }\r
+  }\r
+\r
+  return "unknown";\r
+}\r
+\r
+static\r
+INT8 *\r
+GetSubsystemTypeStr (\r
+  UINT16  SubsystemType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SubsystemType - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  int Index;\r
+\r
+  for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {\r
+    if (mSubsystemTypes[Index].Value == SubsystemType) {\r
+      return mSubsystemTypes[Index].Name;\r
+    }\r
+  }\r
+\r
+  return "unknown";\r
+}\r
diff --git a/Tools/Source/TianoTools/GenTEImage/Makefile b/Tools/Source/TianoTools/GenTEImage/Makefile
new file mode 100644 (file)
index 0000000..f731b6d
--- /dev/null
@@ -0,0 +1,68 @@
+#/*++\r
+#  \r
+#  Copyright (c) 2002 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#  \r
+#  Module Name:\r
+#  \r
+#    makefile\r
+#    \r
+#  Abstract:\r
+#  \r
+#    makefile for building the GenTEImage utility.\r
+#  \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Define the toolchain which is used to set build options and toolchain paths\r
+#\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = GenTEImage\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj \r
+\r
+LIBS      = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+INC_DEPS  = $(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h\r
+          \r
+#\r
+# Build the EXE by compiling the source files, then linking the resultant\r
+# object files together.\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj : $(TARGET_SRC_DIR)\$(TARGET_NAME).c $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\$(TARGET_NAME).c /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS) $(TARGET_EXE_LIBS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.c
new file mode 100644 (file)
index 0000000..1845c48
--- /dev/null
@@ -0,0 +1,973 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  PeiRebaseExe.c\r
+\r
+Abstract:\r
+\r
+  This contains all code necessary to build the PeiRebase.exe utility.\r
+  This utility relies heavily on the PeiRebase DLL.  Definitions for both\r
+  can be found in the PEI Rebase Utility Specification, review draft.\r
+\r
+--*/\r
+\r
+#include "PeiRebaseExe.h"\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include "CommonLib.h"\r
+#include "ParseInf.h"\r
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)\r
+#include "FvLib.h"\r
+\r
+#include "EfiUtilityMsgs.h"\r
+\r
+extern EFI_PEI_PE_COFF_LOADER_PROTOCOL  mPeCoffLoader;\r
+\r
+EFI_STATUS\r
+ReadHeader (\r
+  IN FILE       *InputFile,\r
+  OUT UINT32    *FvSize,\r
+  OUT BOOLEAN   *ErasePolarity\r
+  );\r
+\r
+int\r
+main (\r
+  int  argc,\r
+  char **argv\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This utility relocates PEI XIP PE32s in a FV.\r
+\r
+Arguments:\r
+\r
+  argc          - Number of command line arguments\r
+  argv[]:\r
+  BaseAddress     The base address to use for rebasing the FV.  The correct \r
+                  format is a hex number preceded by 0x.\r
+  InputFileName   The name of the input FV file.\r
+  OutputFileName  The name of the output FV file.\r
+\r
+  Arguments come in pair in any order.\r
+    -I InputFileName \r
+    -O OutputFileName\r
+    -B BaseAddress \r
+\r
+Returns:\r
+\r
+  0   No error conditions detected.\r
+  1   One or more of the input parameters is invalid.\r
+  2   A resource required by the utility was unavailable.  \r
+      Most commonly this will be memory allocation or file creation.\r
+  3   PeiRebase.dll could not be loaded.\r
+  4   Error executing the PEI rebase.\r
+\r
+--*/\r
+{\r
+  UINT8                       Index;\r
+  CHAR8                       InputFileName[_MAX_PATH];\r
+  CHAR8                       OutputFileName[_MAX_PATH];\r
+  EFI_PHYSICAL_ADDRESS        BaseAddress;\r
+  BOOLEAN                     BaseAddressSet;\r
+  EFI_STATUS                  Status;\r
+  FILE                        *InputFile;\r
+  FILE                        *OutputFile;\r
+  UINT64                      FvOffset;\r
+  UINT32                      FileCount;\r
+  int                         BytesRead;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvImage;\r
+  UINT32                      FvSize;\r
+  EFI_FFS_FILE_HEADER         *CurrentFile;\r
+  BOOLEAN                     ErasePolarity;\r
+  EFI_PHYSICAL_ADDRESS        CurrentFileBaseAddress;\r
+\r
+  ErasePolarity = FALSE;\r
+  //\r
+  // Set utility name for error/warning reporting purposes.\r
+  //\r
+  SetUtilityName (UTILITY_NAME);\r
+  //\r
+  // Verify the correct number of arguments\r
+  //\r
+  if (argc != MAX_ARGS) {\r
+    PrintUsage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Initialize variables\r
+  //\r
+  InputFileName[0]  = 0;\r
+  OutputFileName[0] = 0;\r
+  BaseAddress       = 0;\r
+  BaseAddressSet    = FALSE;\r
+  FvOffset          = 0;\r
+  FileCount         = 0;\r
+  ErasePolarity     = FALSE;\r
+  InputFile         = NULL;\r
+  OutputFile        = NULL;\r
+  FvImage           = NULL;\r
+  //\r
+  // Parse the command line arguments\r
+  //\r
+  for (Index = 1; Index < MAX_ARGS; Index += 2) {\r
+    //\r
+    // Make sure argument pair begin with - or /\r
+    //\r
+    if (argv[Index][0] != '-' && argv[Index][0] != '/') {\r
+      PrintUsage ();\r
+      Error (NULL, 0, 0, argv[Index], "unrecognized option");\r
+      return STATUS_ERROR;\r
+    }\r
+    //\r
+    // Make sure argument specifier is only one letter\r
+    //\r
+    if (argv[Index][2] != 0) {\r
+      PrintUsage ();\r
+      Error (NULL, 0, 0, argv[Index], "unrecognized option");\r
+      return STATUS_ERROR;\r
+    }    \r
+    //\r
+    // Determine argument to read\r
+    //\r
+    switch (argv[Index][1]) {\r
+    case 'I':\r
+    case 'i':\r
+      if (strlen (InputFileName) == 0) {\r
+        strcpy (InputFileName, argv[Index + 1]);\r
+      } else {\r
+        PrintUsage ();\r
+        Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");\r
+        return STATUS_ERROR;\r
+      }\r
+      break;\r
+\r
+    case 'O':\r
+    case 'o':\r
+      if (strlen (OutputFileName) == 0) {\r
+        strcpy (OutputFileName, argv[Index + 1]);\r
+      } else {\r
+        PrintUsage ();\r
+        Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");\r
+        return STATUS_ERROR;\r
+      }\r
+      break;\r
+\r
+    case 'B':\r
+    case 'b':\r
+      if (!BaseAddressSet) {\r
+        Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BaseAddress);\r
+        if (EFI_ERROR (Status)) {\r
+          PrintUsage ();\r
+          Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for the base address");\r
+          return STATUS_ERROR;\r
+        }\r
+\r
+        BaseAddressSet = TRUE;\r
+      } else {\r
+        PrintUsage ();\r
+        Error (NULL, 0, 0, argv[Index + 1], "-b BaseAddress may only be specified once");\r
+        return STATUS_ERROR;\r
+      }\r
+      break;\r
+\r
+    default:\r
+      PrintUsage ();\r
+      Error (NULL, 0, 0, argv[Index], "unrecognized argument");\r
+      return STATUS_ERROR;\r
+      break;\r
+    }\r
+  }\r
+  //\r
+  // Open the file containing the FV\r
+  //\r
+  InputFile = fopen (InputFileName, "rb");\r
+  if (InputFile == NULL) {\r
+    Error (NULL, 0, 0, InputFileName, "could not open input file for reading");\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Determine size of FV\r
+  //\r
+  Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "could not parse the FV header", NULL);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Allocate a buffer for the FV image\r
+  //\r
+  FvImage = malloc (FvSize);\r
+  if (FvImage == NULL) {\r
+    Error (NULL, 0, 0, "application error", "memory allocation failed");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Read the entire FV to the buffer\r
+  //\r
+  BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
+  fclose (InputFile);\r
+  InputFile = NULL;\r
+  if ((unsigned int) BytesRead != FvSize) {\r
+    Error (NULL, 0, 0, InputFileName, "failed to read from file");\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Prepare to walk the FV image\r
+  //\r
+  InitializeFvLib (FvImage, FvSize);\r
+  //\r
+  // Get the first file\r
+  //\r
+  Status = GetNextFile (NULL, &CurrentFile);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);\r
+    goto Finish;\r
+  }\r
+  //\r
+  // Check if each file should be rebased\r
+  //\r
+  while (CurrentFile != NULL) {\r
+    //\r
+    // Rebase this file\r
+    //\r
+    CurrentFileBaseAddress  = BaseAddress + ((UINTN) CurrentFile - (UINTN) FvImage);\r
+    Status                  = FfsRebase (CurrentFile, CurrentFileBaseAddress);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      switch (Status) {\r
+\r
+      case EFI_INVALID_PARAMETER:\r
+        Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);\r
+        break;\r
+\r
+      case EFI_ABORTED:\r
+        Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);\r
+        break;\r
+\r
+      case EFI_OUT_OF_RESOURCES:\r
+        Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);\r
+        break;\r
+\r
+      case EFI_NOT_FOUND:\r
+        Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);\r
+        break;\r
+\r
+      default:\r
+        Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);\r
+        break;\r
+      }\r
+\r
+      goto Finish;\r
+    }\r
+    //\r
+    // Get the next file\r
+    //\r
+    Status = GetNextFile (CurrentFile, &CurrentFile);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);\r
+      goto Finish;\r
+    }\r
+  }\r
+  //\r
+  // Open the output file\r
+  //\r
+  OutputFile = fopen (OutputFileName, "wb");\r
+  if (OutputFile == NULL) {\r
+    Error (NULL, 0, 0, OutputFileName, "failed to open output file");\r
+    goto Finish;\r
+  }\r
+\r
+  if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {\r
+    Error (NULL, 0, 0, "failed to write to output file", 0);\r
+    goto Finish;\r
+  }\r
+\r
+Finish:\r
+  if (InputFile != NULL) {\r
+    fclose (InputFile);\r
+  }\r
+  //\r
+  // If we created an output file, and there was an error, remove it so\r
+  // subsequent builds will rebuild it.\r
+  //\r
+  if (OutputFile != NULL) {\r
+    if (GetUtilityStatus () == STATUS_ERROR) {\r
+      remove (OutputFileName);\r
+    }\r
+\r
+    fclose (OutputFile);\r
+  }\r
+\r
+  if (FvImage != NULL) {\r
+    free (FvImage);\r
+  }\r
+\r
+  return GetUtilityStatus ();\r
+}\r
+\r
+EFI_STATUS\r
+ReadHeader (\r
+  IN FILE       *InputFile,\r
+  OUT UINT32    *FvSize,\r
+  OUT BOOLEAN   *ErasePolarity\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function determines the size of the FV and the erase polarity.  The \r
+  erase polarity is the FALSE value for file state.\r
+\r
+Arguments:\r
+\r
+  InputFile       The file that contains the FV image.\r
+  FvSize          The size of the FV.\r
+  ErasePolarity   The FV erase polarity.\r
+    \r
+Returns:\r
\r
+  EFI_SUCCESS             Function completed successfully.\r
+  EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.\r
+  EFI_ABORTED             The function encountered an error.\r
+\r
+--*/\r
+{\r
+  EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;\r
+  EFI_FV_BLOCK_MAP_ENTRY      BlockMap;\r
+  UINTN                       Signature[2];\r
+  UINTN                       BytesRead;\r
+  UINT32                      Size;\r
+\r
+  BytesRead = 0;\r
+  Size      = 0;\r
+  //\r
+  // Check input parameters\r
+  //\r
+  if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {\r
+    Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Read the header\r
+  //\r
+  fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+  BytesRead     = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+  Signature[0]  = VolumeHeader.Signature;\r
+  Signature[1]  = 0;\r
+\r
+  //\r
+  // Get erase polarity\r
+  //\r
+  if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {\r
+    *ErasePolarity = TRUE;\r
+  }\r
+\r
+  do {\r
+    fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
+    BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
+\r
+    if (BlockMap.NumBlocks != 0) {\r
+      Size += BlockMap.NumBlocks * BlockMap.BlockLength;\r
+    }\r
+\r
+  } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));\r
+\r
+  if (VolumeHeader.FvLength != Size) {\r
+    Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);\r
+    return EFI_ABORTED;\r
+  }\r
+\r
+  *FvSize = Size;\r
+\r
+  rewind (InputFile);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "%s, PEI Rebase Utility. Version %i.%i, %s.\n\n",\r
+    UTILITY_NAME,\r
+    UTILITY_MAJOR_VERSION,\r
+    UTILITY_MINOR_VERSION,\r
+    UTILITY_DATE\r
+    );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",\r
+    UTILITY_NAME\r
+    );\r
+  printf ("  Where:\n");\r
+  printf ("    InputFileName is the name of the EFI FV file to rebase.\n");\r
+  printf ("    OutputFileName is the desired output file name.\n");\r
+  printf ("    BaseAddress is the FV base address to rebase agains.\n");\r
+  printf ("  Argument pair may be in any order.\n\n");\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebase (\r
+  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,\r
+  IN EFI_PHYSICAL_ADDRESS       BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This function determines if a file is XIP and should be rebased.  It will \r
+  rebase any PE32 sections found in the file using the base address.\r
+  \r
+Arguments:\r
+\r
+  FfsFile           A pointer to Ffs file image.\r
+  BaseAddress       The base address to use for rebasing the file image.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS             The image was properly rebased.\r
+  EFI_INVALID_PARAMETER   An input parameter is invalid.\r
+  EFI_ABORTED             An error occurred while rebasing the input file image.\r
+  EFI_OUT_OF_RESOURCES    Could not allocate a required resource.\r
+  EFI_NOT_FOUND           No compressed sections could be found.\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                            Status;\r
+  EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;\r
+  UINTN                                 MemoryImagePointer;\r
+  UINTN                                 MemoryImagePointerAligned;\r
+  EFI_PHYSICAL_ADDRESS                  ImageAddress;\r
+  UINT64                                ImageSize;\r
+  EFI_PHYSICAL_ADDRESS                  EntryPoint;\r
+  UINT32                                Pe32ImageSize;\r
+  UINT32                                NewPe32BaseAddress;\r
+  UINTN                                 Index;\r
+  EFI_FILE_SECTION_POINTER              CurrentPe32Section;\r
+  EFI_FFS_FILE_STATE                    SavedState;\r
+  EFI_IMAGE_NT_HEADERS                  *PeHdr;\r
+  UINT32                                *PeHdrSizeOfImage;\r
+  UINT32                                *PeHdrChecksum;\r
+  UINT32                                FoundCount;\r
+  EFI_TE_IMAGE_HEADER                   *TEImageHeader;\r
+  UINT8                                 *TEBuffer;\r
+  EFI_IMAGE_DOS_HEADER                  *DosHeader;\r
+  UINT8                                 FileGuidString[80];\r
+  UINT32                                TailSize;\r
+  EFI_FFS_FILE_TAIL                     TailValue;\r
+\r
+  //\r
+  // Verify input parameters\r
+  //\r
+  if (FfsFile == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Convert the GUID to a string so we can at least report which file\r
+  // if we find an error.\r
+  //\r
+  PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);\r
+  if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+    TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+  } else {\r
+    TailSize = 0;\r
+  }\r
+  //\r
+  // Do some cursory checks on the FFS file contents\r
+  //\r
+  Status = VerifyFfsFile (FfsFile);\r
+  if (EFI_ERROR (Status)) {\r
+    Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  //\r
+  // Check if XIP file type. If not XIP, don't rebase.\r
+  //\r
+  if (FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_PEIM &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&\r
+      FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\r
+      ) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Rebase each PE32 section\r
+  //\r
+  Status      = EFI_SUCCESS;\r
+  FoundCount  = 0;\r
+  for (Index = 1;; Index++) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    FoundCount++;\r
+\r
+    //\r
+    // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section\r
+    //\r
+    NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER) - (UINTN) FfsFile);\r
+\r
+    //\r
+    // Initialize context\r
+    //\r
+    memset (&ImageContext, 0, sizeof (ImageContext));\r
+    ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));\r
+    ImageContext.ImageRead  = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+    Status                  = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);\r
+      return Status;\r
+    }\r
+    //\r
+    // Allocate a buffer for the image to be loaded into.\r
+    //\r
+    Pe32ImageSize       = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);\r
+    MemoryImagePointer  = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
+    if (MemoryImagePointer == 0) {\r
+      Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+    \r
+\r
+    ImageContext.ImageAddress = MemoryImagePointerAligned;\r
+\r
+    Status                    = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+    Status                          = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    ImageAddress  = ImageContext.ImageAddress;\r
+    ImageSize     = ImageContext.ImageSize;\r
+    EntryPoint    = ImageContext.EntryPoint;\r
+\r
+    if (ImageSize > Pe32ImageSize) {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        "rebased image is larger than original PE32 image",\r
+        "0x%X > 0x%X, file %s",\r
+        ImageSize,\r
+        Pe32ImageSize,\r
+        FileGuidString\r
+        );\r
+      free ((VOID *) MemoryImagePointer);\r
+      return EFI_ABORTED;\r
+    }\r
+    //\r
+    // Since we may have updated the Codeview RVA, we need to insure the PE\r
+    // header indicates the image is large enough to contain the Codeview data\r
+    // so it will be loaded properly later if the PEIM is reloaded into memory...\r
+    //\r
+    PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+    if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
+      PeHdrSizeOfImage  = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+      PeHdrChecksum     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
+      PeHdrSizeOfImage  = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+      PeHdrChecksum     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {\r
+      PeHdrSizeOfImage  = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+      PeHdrChecksum     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+    } else {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        "unknown machine type in PE32 image",\r
+        "machine type=0x%X, file=%s",\r
+        (UINT32) PeHdr->FileHeader.Machine,\r
+        FileGuidString\r
+        );\r
+      free ((VOID *) MemoryImagePointer);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    if (*PeHdrSizeOfImage != ImageContext.ImageSize) {\r
+      *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;\r
+      if (*PeHdrChecksum) {\r
+        *PeHdrChecksum = 0;\r
+      }\r
+    }\r
+\r
+    memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);\r
+\r
+    free ((VOID *) MemoryImagePointer);\r
+\r
+    //\r
+    // Now update file checksum\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+      TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+    } else {\r
+      TailSize = 0;\r
+    }\r
+\r
+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+      SavedState  = FfsFile->State;\r
+      FfsFile->IntegrityCheck.Checksum.File = 0;\r
+      FfsFile->State                        = 0;\r
+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                                  (UINT8 *) FfsFile,\r
+                                                  GetLength (FfsFile->Size) - TailSize\r
+                                                  );\r
+      } else {\r
+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+      }\r
+\r
+      FfsFile->State = SavedState;\r
+    }\r
+    //\r
+    // Update tail if present\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+      TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));\r
+      *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+    }\r
+  }\r
+  //\r
+  // Now process TE sections\r
+  //\r
+  for (Index = 1;; Index++) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    FoundCount++;\r
+\r
+    //\r
+    // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off\r
+    // by GenTEImage\r
+    //\r
+    TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));\r
+\r
+    NewPe32BaseAddress = ((UINT32) BaseAddress) +\r
+      (\r
+        (UINTN) CurrentPe32Section.Pe32Section +\r
+        sizeof (EFI_COMMON_SECTION_HEADER) +\r
+        sizeof (EFI_TE_IMAGE_HEADER) -\r
+        TEImageHeader->StrippedSize -\r
+        (UINTN) FfsFile\r
+      );\r
+\r
+    //\r
+    // Allocate a buffer to unshrink the image into.\r
+    //\r
+    Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+    sizeof (EFI_TE_IMAGE_HEADER);\r
+    Pe32ImageSize += TEImageHeader->StrippedSize;\r
+    TEBuffer = (UINT8 *) malloc (Pe32ImageSize);\r
+    if (TEBuffer == NULL) {\r
+      Error (NULL, 0, 0, "failed to allocate memory", NULL);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    //\r
+    // Expand the image into our buffer and fill in critical fields in the DOS header\r
+    // Fill in fields required by the loader.\r
+    // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value\r
+    // itself.\r
+    //\r
+    memset (TEBuffer, 0, Pe32ImageSize);\r
+    DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;\r
+    DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
+    *(UINT32 *) (TEBuffer + 0x3C) = 0x40;\r
+    PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);\r
+    PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;\r
+    PeHdr->FileHeader.Machine = TEImageHeader->Machine;\r
+    PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;\r
+\r
+    //\r
+    // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and\r
+    // the 0x40 bytes for our DOS header.\r
+    //\r
+    PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));\r
+    PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));\r
+    PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+    PeHdr->OptionalHeader.Subsystem   = TEImageHeader->Subsystem;\r
+    PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;\r
+    PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *\r
+    sizeof (EFI_IMAGE_SECTION_HEADER) - 12;\r
+\r
+    //\r
+    // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image\r
+    //\r
+    if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||\r
+        (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)\r
+        ) {\r
+      PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;\r
+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
+    }\r
+\r
+    if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||\r
+        (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)\r
+        ) {\r
+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
+      PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
+      if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {\r
+        PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;\r
+      }\r
+    }\r
+    //\r
+    // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility\r
+    //\r
+    PeHdr->OptionalHeader.SectionAlignment = 0x10;\r
+\r
+    //\r
+    // Copy the rest of the image to its original offset\r
+    //\r
+    memcpy (\r
+      TEBuffer + TEImageHeader->StrippedSize,\r
+      (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),\r
+      GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+      sizeof (EFI_TE_IMAGE_HEADER)\r
+      );\r
+\r
+    //\r
+    // Initialize context\r
+    //\r
+    memset (&ImageContext, 0, sizeof (ImageContext));\r
+    ImageContext.Handle     = (VOID *) TEBuffer;\r
+    ImageContext.ImageRead  = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;\r
+\r
+    Status                  = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);\r
+      free (TEBuffer);\r
+      return Status;\r
+    }\r
+    //\r
+    // Allocate a buffer for the image to be loaded into.\r
+    //\r
+    MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x1000));\r
+    if (MemoryImagePointer == 0) {\r
+      Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);\r
+      free (TEBuffer);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x1000);\r
+    MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);\r
+    \r
+\r
+    ImageContext.ImageAddress = MemoryImagePointerAligned;\r
+    Status                    = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);\r
+      free (TEBuffer);\r
+      free ((VOID *) MemoryImagePointer);\r
+      return Status;\r
+    }\r
+\r
+    ImageContext.DestinationAddress = NewPe32BaseAddress;\r
+    Status                          = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);\r
+      free ((VOID *) MemoryImagePointer);\r
+      free (TEBuffer);\r
+      return Status;\r
+    }\r
+\r
+    ImageAddress  = ImageContext.ImageAddress;\r
+    ImageSize     = ImageContext.ImageSize;\r
+    EntryPoint    = ImageContext.EntryPoint;\r
+\r
+    //\r
+    // Since we may have updated the Codeview RVA, we need to insure the PE\r
+    // header indicates the image is large enough to contain the Codeview data\r
+    // so it will be loaded properly later if the PEIM is reloaded into memory...\r
+    //\r
+    PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);\r
+    if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {\r
+      PeHdrSizeOfImage  = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+      PeHdrChecksum     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER32 *) &PeHdr->OptionalHeader).CheckSum);\r
+    } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {\r
+      PeHdrSizeOfImage  = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).SizeOfImage);\r
+      PeHdrChecksum     = (UINT32 *) (&(*(EFI_IMAGE_OPTIONAL_HEADER64 *) &PeHdr->OptionalHeader).CheckSum);\r
+    } else {\r
+      Error (\r
+        NULL,\r
+        0,\r
+        0,\r
+        "unknown machine type in TE image",\r
+        "machine type=0x%X, file=%s",\r
+        (UINT32) PeHdr->FileHeader.Machine,\r
+        FileGuidString\r
+        );\r
+      free ((VOID *) MemoryImagePointer);\r
+      free (TEBuffer);\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    if (*PeHdrSizeOfImage != ImageContext.ImageSize) {\r
+      *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;\r
+      if (*PeHdrChecksum) {\r
+        *PeHdrChecksum = 0;\r
+      }\r
+    }\r
+\r
+    TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));\r
+    memcpy (\r
+      (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),\r
+      (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),\r
+      GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -\r
+      sizeof (EFI_TE_IMAGE_HEADER)\r
+      );\r
+    free ((VOID *) MemoryImagePointer);\r
+    free (TEBuffer);\r
+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+      TailSize = sizeof (EFI_FFS_FILE_TAIL);\r
+    } else {\r
+      TailSize = 0;\r
+    }\r
+    //\r
+    // Now update file checksum\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+      SavedState  = FfsFile->State;\r
+      FfsFile->IntegrityCheck.Checksum.File = 0;\r
+      FfsFile->State                        = 0;\r
+      if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+        FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
+                                                  (UINT8 *) FfsFile,\r
+                                                  GetLength (FfsFile->Size) - TailSize\r
+                                                  );\r
+      } else {\r
+        FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+      }\r
+\r
+      FfsFile->State = SavedState;\r
+    }\r
+    //\r
+    // Update tail if present\r
+    //\r
+    if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
+      TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));\r
+      *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;\r
+    }\r
+  }\r
+  //\r
+  // If we found no files, then emit an error if no compressed sections either\r
+  //\r
+  if (FoundCount == 0) {\r
+    Status = GetSectionByType (FfsFile, EFI_SECTION_COMPRESSION, Index, &CurrentPe32Section);\r
+    if (EFI_ERROR (Status)) {\r
+      Error (NULL, 0, 0, "no PE32, TE, nor compressed section found in FV file", FileGuidString);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINT32  *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+Arguments:\r
+\r
+  FileHandle - The handle to the PE/COFF file\r
+\r
+  FileOffset - The offset, in bytes, into the file to read\r
+\r
+  ReadSize   - The number of bytes to read from the file starting at FileOffset\r
+\r
+  Buffer     - A pointer to the buffer to read the data into.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+--*/\r
+{\r
+  CHAR8   *Destination8;\r
+  CHAR8   *Source8;\r
+  UINT32  Length;\r
+\r
+  Destination8  = Buffer;\r
+  Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+  Length        = *ReadSize;\r
+  while (Length--) {\r
+    *(Destination8++) = *(Source8++);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h b/Tools/Source/TianoTools/PeiRebase/PeiRebaseExe.h
new file mode 100644 (file)
index 0000000..9070d1c
--- /dev/null
@@ -0,0 +1,153 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  PeiRebaseExe.h\r
+\r
+Abstract:\r
+\r
+  Definitions for the PeiRebase exe utility.\r
+\r
+--*/\r
+\r
+#ifndef _EFI_PEIM_FIXUP_EXE_H\r
+#define _EFI_PEIM_FIXUP_EXE_H\r
+\r
+#include "Efi2WinNt.h"\r
+#include "EfiFirmwareFileSystem.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME  "PeiRebase"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE          __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS  7\r
+\r
+//\r
+// The file copy buffer size\r
+//\r
+#define FILE_COPY_BUFFER_SIZE 512\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// Internal function declarations\r
+//\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+  IN     VOID    *FileHandle,\r
+  IN     UINTN   FileOffset,\r
+  IN OUT UINT32  *ReadSize,\r
+  OUT    VOID    *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FileHandle  - GC_TODO: add argument description\r
+  FileOffset  - GC_TODO: add argument description\r
+  ReadSize    - GC_TODO: add argument description\r
+  Buffer      - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+EFI_STATUS\r
+FfsRebase (\r
+  IN OUT EFI_FFS_FILE_HEADER    *FfsFile,\r
+  IN EFI_PHYSICAL_ADDRESS       BaseAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FfsFile     - GC_TODO: add argument description\r
+  BaseAddress - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/Tools/Source/TianoTools/PeiRebase/makefile b/Tools/Source/TianoTools/PeiRebase/makefile
new file mode 100644 (file)
index 0000000..4b19309
--- /dev/null
@@ -0,0 +1,71 @@
+#/*++\r
+#  \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#  \r
+#  Module Name:\r
+#  \r
+#    makefile\r
+#    \r
+#  Abstract:\r
+#  \r
+#    makefile for building the PeiRebase utility.\r
+#  \r
+#  Revision History\r
+#  \r
+#--*/\r
+\r
+#\r
+# Make sure environmental variable EFI_SOURCE is set\r
+#\r
+!IFNDEF EFI_SOURCE\r
+!ERROR EFI_SOURCE environmental variable not set \r
+!ENDIF\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = PeiRebase\r
+TARGET_SRC_DIR      = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\PeiRebase.exe\r
+TARGET_EXE_LIBS     = $(TIANO_TOOLS_OUTPUT)\Common.lib\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\PeiRebase.obj  \r
+\r
+#\r
+# Compile each source file\r
+#\r
+$(TIANO_TOOLS_OUTPUT)\PeiRebase.obj : $(TARGET_SRC_DIR)\PeiRebaseExe.c $(INC_DEPS) $(TARGET_EXE_LIBS)\r
+  $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\PeiRebaseExe.c /Fo$@\r
+\r
+#\r
+# Link the object files together\r
+#\r
+$(TARGET_EXE) : $(OBJECTS) $(TARGET_EXE_LIBS)\r
+  @echo LINKING\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)  $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/Makefile b/Tools/Source/TianoTools/SecApResetVectorFixup/Makefile
new file mode 100644 (file)
index 0000000..53e6be5
--- /dev/null
@@ -0,0 +1,58 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2005 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = SecApResetVectorFixup\r
+TARGET_SOURCE_DIR   = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+TARGET_EXE_SOURCE   = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+LIBS      = $(TIANO_TOOLS_OUTPUT)\Common.lib  \r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)\r
+\r
+clean:\r
+  @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.c
new file mode 100644 (file)
index 0000000..5cb03f0
--- /dev/null
@@ -0,0 +1,363 @@
+/*++\r
+\r
+Copyright (c)  2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+    SecApResetVectorFixup.c\r
+\r
+Abstract:\r
+\r
+    This utility is part of build process for IA32 Fvrecovery.fv whose total size\r
+    is larger than 128kB so that we cannot use GenFvImage utility to put Ap reset \r
+    vector at the zero vector of Fv header.\r
+    \r
+      PEI FV after using the tool\r
+    \r
+    -------------------------\r
+    |zzz                    |\r
+    |                       |\r
+    |                       |\r
+    |      FFS              |\r
+    |                       |\r
+    |                       |\r
+    |                       |\r
+    |---------------------- |\r
+    |       PAD             |\r
+    |                       |\r
+    |.......................|  --- \r
+    |                       |   |\r
+    |xxx                    |   | 128K    \r
+    |---------------------- |   | \r
+    |       VTF (SEC)       |   |\r
+    -------------------------  ---\r
+    \r
+    1. zzz --> Zero vector, which is beyond the 128K limited address space\r
+    2. xxx --> AP reset vector at 4K alignment below 128K and it is in the PAD\r
+       file area.\r
+    3. After the build process ,the PAD guid is changed to a new GUID to avoid \r
+       the PAD definition confusing. If there is some problem, try to disable\r
+       UpdatePadFileGuid\r
+    \r
+     \r
+    \r
+--*/\r
+\r
+#include "SecApResetVectorFixup.h"\r
+\r
+\r
+EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };\r
+EFI_GUID  NewFvPadFileNameGuid     = { 0x145372bc, 0x66b9, 0x476d, 0x81, 0xbc, 0x21, 0x27, 0xc3, 0x76, 0xbb, 0x66 };\r
+\r
+//\r
+// jmp 0xf000:0xffd0 (0xFFFFFFD0)\r
+//\r
+UINT8 ApResetVector[5] = {0xEA, 0xD0, 0xFF, 0x00, 0xF0};\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "%s - Tiano IA32 SEC Ap Reset Vector Fixup Utility."" Version %i.%i\n\n",\r
+    UTILITY_NAME,\r
+    UTILITY_MAJOR_VERSION,\r
+    UTILITY_MINOR_VERSION\r
+    );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf ("Usage: %s InputFvrecoveryFile OutputFvrecoveryFile\n", UTILITY_NAME);\r
+  printf ("  Where:\n");\r
+  printf ("\tInputFvrecoveryFile   - Name of the IA32 input Fvrecovery.fv file.\n");\r
+  printf ("\tOutputFvrecoveryFile  - Name of the IA32 output Fvrecovery.fv file.\n");\r
+}\r
+\r
+\r
+VOID \r
+UpdatePadFileGuid (\r
+  IN     EFI_FIRMWARE_VOLUME_HEADER  *FvHeader,\r
+  IN     EFI_FFS_FILE_HEADER         *FileHeader,\r
+  IN     UINT32                      FileLength,\r
+  IN OUT EFI_GUID                    *Guid\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Update the Pad File Guid to change it to other guid and update\r
+  the checksum\r
+\r
+Arguments:\r
+  FvHeader   - EFI_FIRMWARE_VOLUME_HEADER \r
+  FileHeader - The FFS PAD file header.\r
+  FileLength - The FFS PAD file length.\r
+  Guid       - The Guid to compare and if it is PAD Guid, update it to new Guid\r
+Returns:\r
+  VOID\r
+--*/\r
+\r
+{\r
+  if ((CompareGuid (Guid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
+    //\r
+    // Set new Pad file guid\r
+    // \r
+    memcpy (Guid, &NewFvPadFileNameGuid, sizeof (EFI_GUID));\r
+\r
+\r
+\r
+    FileHeader->Type       = EFI_FV_FILETYPE_FFS_PAD;\r
+    FileHeader->Attributes = 0;\r
+    //\r
+    // Fill in checksums and state, must be zero during checksum calculation.\r
+    //\r
+    FileHeader->IntegrityCheck.Checksum.Header = 0;\r
+    FileHeader->IntegrityCheck.Checksum.File   = 0;\r
+    FileHeader->State                          = 0;\r
+    FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));\r
+    if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
+      FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, FileLength);\r
+    } else {\r
+      FileHeader->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
+    }\r
+\r
+    FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;\r
+\r
+    if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {\r
+      FileHeader->State = (UINT8)~(FileHeader->State);\r
+    }    \r
+  }\r
+  \r
+}\r
+\r
+\r
+STATUS\r
+main (\r
+  IN INTN   argc,\r
+  IN CHAR8  **argv\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Main function.\r
+\r
+Arguments:\r
+\r
+  argc - Number of command line parameters.\r
+  argv - Array of pointers to parameter strings.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - Utility exits successfully.\r
+  STATUS_ERROR   - Some error occurred during execution.\r
+\r
+--*/\r
+{\r
+  FILE                        *FpIn;\r
+  FILE                        *FpOut;\r
+  UINT32                      FvrecoveryFileSize;\r
+  UINT8                       *FileBuffer;\r
+  UINT8                       *FileBufferRaw;\r
+  UINT64                      FvLength;\r
+  UINT32                      Offset;\r
+  UINT32                      FileLength;\r
+  UINT32                      FileOccupiedSize;\r
+  EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;\r
+  EFI_FFS_FILE_HEADER         *FileHeader;\r
+  EFI_GUID                    *TempGuid;\r
+  UINT8                       *FixPoint;\r
+  UINT32                      TempResult;\r
+  UINT32                      Index;\r
+  UINT32                      IpiVector;\r
+\r
+  TempGuid = NULL;\r
+  SetUtilityName (UTILITY_NAME);\r
+\r
+  //\r
+  // Display utility information\r
+  //\r
+  PrintUtilityInfo ();\r
+\r
+  //\r
+  // Verify the correct number of arguments\r
+  //\r
+  if (argc != MAX_ARGS) {\r
+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);\r
+    PrintUsage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Open the Input Fvrecovery.fv file\r
+  //\r
+  if ((FpIn = fopen (argv[1], "rb")) == NULL) {\r
+    Error (NULL, 0, 0, "Unable to open file", argv[1]);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Get the Input Fvrecovery.fv file size\r
+  //\r
+  fseek (FpIn, 0, SEEK_END);\r
+  FvrecoveryFileSize = ftell (FpIn);\r
+  //\r
+  // Read the contents of input file to memory buffer\r
+  //\r
+  FileBuffer    = NULL;\r
+  FileBufferRaw = NULL;\r
+  FileBufferRaw = (UINT8 *) malloc (FvrecoveryFileSize + 0x10000);\r
+  if (NULL == FileBufferRaw) {\r
+    Error (NULL, 0, 0, "No sufficient memory to allocate!", NULL);\r
+    fclose (FpIn);\r
+    return STATUS_ERROR;\r
+  }\r
+  TempResult = 0x10000 - ((UINT32)FileBufferRaw & 0x0FFFF);\r
+  FileBuffer = (UINT8 *)((UINT32)FileBufferRaw + TempResult);\r
+  fseek (FpIn, 0, SEEK_SET);\r
+  TempResult = fread (FileBuffer, 1, FvrecoveryFileSize, FpIn);\r
+  if (TempResult != FvrecoveryFileSize) {\r
+    Error (NULL, 0, 0, "Read input file error!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    fclose (FpIn);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Close the input Fvrecovery.fv file\r
+  //\r
+  fclose (FpIn);\r
+  //\r
+  // Find the pad FFS file\r
+  //\r
+  FvHeader         = (EFI_FIRMWARE_VOLUME_HEADER *)FileBuffer;\r
+  FvLength         = FvHeader->FvLength;\r
+  FileHeader       = (EFI_FFS_FILE_HEADER *)(FileBuffer + FvHeader->HeaderLength);\r
+  FileLength       = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
+  FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
+  Offset           = (UINT32)FileHeader - (UINT32)FileBuffer;\r
+  \r
+  while (Offset < FvLength) {\r
+    TempGuid = (EFI_GUID *)&(FileHeader->Name);\r
+    FileLength = (*(UINT32 *)(FileHeader->Size)) & 0x00FFFFFF;\r
+    FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8);\r
+    if ((CompareGuid (TempGuid, (EFI_GUID *)&DefaultFvPadFileNameGuid)) == 0) {\r
+      break;\r
+    }\r
+    FileHeader = (EFI_FFS_FILE_HEADER *)((UINT32)FileHeader + FileOccupiedSize);\r
+    Offset = (UINT32)FileHeader - (UINT32)FileBuffer;\r
+  }\r
+\r
+  if (Offset >= FvLength) {\r
+    Error (NULL, 0, 0, "No pad file found!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Find the position to place Ap reset vector, the offset\r
+  // between the position and the end of Fvrecovery.fv file\r
+  // should not exceed 128kB to prevent Ap reset vector from\r
+  // outside legacy E and F segment\r
+  //\r
+  FixPoint = (UINT8 *)(FileHeader + sizeof(EFI_FFS_FILE_HEADER));\r
+  TempResult = 0x1000 - ((UINT32)FixPoint & 0x0FFF);\r
+  FixPoint +=TempResult;\r
+  if (((UINT32)FixPoint - (UINT32)FileHeader + 5) > FileOccupiedSize) {\r
+    Error (NULL, 0, 0, "No appropriate space in pad file to add Ap reset vector!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR;  \r
+  }\r
+  while (((UINT32)FixPoint - (UINT32)FileHeader + 5) <= FileOccupiedSize) {\r
+    FixPoint += 0x1000;\r
+  }\r
+  FixPoint -= 0x1000;\r
+  if ((UINT32)FvHeader + FvLength - (UINT32)FixPoint > 0x20000) {\r
+    Error (NULL, 0, 0, "The position to place Ap reset vector is not in E and F segment!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR; \r
+  }    \r
+  //\r
+  // Fix up Ap reset vector and calculate the IPI vector\r
+  //\r
+  for (Index = 0; Index < 5; Index++) {\r
+    FixPoint[Index] = ApResetVector[Index];\r
+  } \r
+  TempResult = 0x0FFFFFFFF - ((UINT32)FvHeader + (UINT32)FvLength - 1 - (UINT32)FixPoint);\r
+  TempResult >>= 12;\r
+  IpiVector = TempResult & 0x0FF;\r
+  \r
+  \r
+  UpdatePadFileGuid (FvHeader, FileHeader, FileLength, TempGuid);\r
+\r
+  //\r
+  // Open the output Fvrecovery.fv file\r
+  //\r
+  if ((FpOut = fopen (argv[2], "w+b")) == NULL) {\r
+    Error (NULL, 0, 0, "Unable to open file", argv[2]);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Write the output Fvrecovery.fv file\r
+  //\r
+  if ((fwrite (FileBuffer, 1, FvrecoveryFileSize, FpOut)) != FvrecoveryFileSize) {\r
+    Error (NULL, 0, 0, "Write output file error!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR;   \r
+  }\r
+  //\r
+  //\r
+  //\r
+  fseek (FpOut, -8, SEEK_END);\r
+  if ((fwrite (&IpiVector, 1, sizeof(UINT32), FpOut)) != sizeof(UINT32)) {\r
+    Error (NULL, 0, 0, "Write output file error!", NULL);\r
+    free ((VOID *)FileBufferRaw);\r
+    return STATUS_ERROR;\r
+  }  \r
+  //\r
+  // Close the output Fvrecovery.fv file\r
+  //\r
+  fclose (FpOut);\r
+  free ((VOID *)FileBufferRaw);\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
diff --git a/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h b/Tools/Source/TianoTools/SecApResetVectorFixup/SecApResetVectorFixup.h
new file mode 100644 (file)
index 0000000..2bed5bc
--- /dev/null
@@ -0,0 +1,102 @@
+/*++\r
+\r
+Copyright (c)  2005 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  SecApResetVectorFixup.h\r
+\r
+Abstract:\r
+\r
+  Definitions for the SecApResetVectorFixup utility.\r
+\r
+--*/\r
+\r
+#ifndef _SEC_AP_RESET_VECTOR_FIXUP_H\r
+#define _SEC_AP_RESET_VECTOR_FIXUP_H\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "EfiCommon.h"\r
+#include "EfiImage.h"\r
+#include "EfiImageFormat.h"\r
+#include "EfiFirmwareFileSystem.h"\r
+#include "EfiFirmwareVolumeHeader.h"\r
+#include "EfiUtilityMsgs.c"\r
+#include "CommonLib.h"\r
+\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME  "SecApResetVectorFixup"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE          __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS        3\r
+#define BUF_SIZE        (8 * 1024)\r
+\r
+#define GETOCCUPIEDSIZE(ActualSize, Alignment) \\r
+  (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))\r
+\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+;\r
+\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+;\r
+\r
+\r
+#endif\r
diff --git a/Tools/Source/TianoTools/SecFixup/Makefile b/Tools/Source/TianoTools/SecFixup/Makefile
new file mode 100644 (file)
index 0000000..6ae2ebd
--- /dev/null
@@ -0,0 +1,57 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME         = SecFixup\r
+TARGET_SOURCE_DIR   = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+TARGET_EXE          = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+TARGET_EXE_SOURCE   = $(TARGET_SOURCE_DIR)\$(TARGET_NAME).c\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+OBJECTS   = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj  \r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(OBJECTS) : $(TARGET_EXE_SOURCE) $(INC_DEPS)\r
+  $(CC) $(C_FLAGS) $(TARGET_EXE_SOURCE) /Fo$@\r
+\r
+$(TARGET_EXE): $(OBJECTS)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(OBJECTS) $(LIBS) /out:$(TARGET_EXE)\r
+\r
+clean:\r
+  @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/SecFixup/SecFixup.c b/Tools/Source/TianoTools/SecFixup/SecFixup.c
new file mode 100644 (file)
index 0000000..a8e707f
--- /dev/null
@@ -0,0 +1,362 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+    SecFixup.c\r
+\r
+Abstract:\r
+\r
+    This utility is part of build process for IA32 SEC FFS file.\r
+    \r
+    It fixup the reset vector data. The reset vector data binary file\r
+    will be wrapped as a RAW section and be located immediately after\r
+    the PE/TE section.\r
+\r
+    The SEC EXE file can be either PE or TE file.\r
+    \r
+--*/\r
+\r
+#include <stdio.h>\r
+\r
+#include "EfiCommon.h"\r
+#include "EfiImage.h"\r
+#include "EfiImageFormat.h"\r
+#include "EfiUtilityMsgs.c"\r
+\r
+#include "SecFixup.h"\r
+\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the standard utility information to SDTOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "%s - Tiano IA32 SEC Fixup Utility."" Version %i.%i\n\n",\r
+    UTILITY_NAME,\r
+    UTILITY_MAJOR_VERSION,\r
+    UTILITY_MINOR_VERSION\r
+    );\r
+}\r
+\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Displays the utility usage syntax to STDOUT\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  printf ("Usage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);\r
+  printf ("  Where:\n");\r
+  printf ("\tSecExeFile           - Name of the IA32 SEC EXE file.\n");\r
+  printf ("\tResetVectorDataFile  - Name of the reset vector data binary file.\n");\r
+  printf ("\tOutputFileName       - Name of the output file.\n\n");\r
+}\r
+\r
+STATUS\r
+main (\r
+  IN INTN   argc,\r
+  IN CHAR8  **argv\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Main function.\r
+\r
+Arguments:\r
+\r
+  argc - Number of command line parameters.\r
+  argv - Array of pointers to parameter strings.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - Utility exits successfully.\r
+  STATUS_ERROR   - Some error occurred during execution.\r
+\r
+--*/\r
+{\r
+  FILE    *FpIn;\r
+\r
+  FILE    *FpOut;\r
+  UINT32  AddressOfEntryPoint;\r
+  INT32   DestRel;\r
+  STATUS  Status;\r
+  UINT32  SecFileSize;\r
+\r
+  SetUtilityName (UTILITY_NAME);\r
+\r
+  //\r
+  // Display utility information\r
+  //\r
+  PrintUtilityInfo ();\r
+\r
+  //\r
+  // Verify the correct number of arguments\r
+  //\r
+  if (argc != MAX_ARGS) {\r
+    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);\r
+    PrintUsage ();\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Open the SEC exe file\r
+  //\r
+  if ((FpIn = fopen (argv[1], "rb")) == NULL) {\r
+    Error (NULL, 0, 0, "Unable to open file", argv[1]);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Get the entry point of the EXE file\r
+  //\r
+  Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);\r
+  if (Status != STATUS_SUCCESS) {\r
+    fclose (FpIn);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Get the SEC file size\r
+  //\r
+  fseek (FpIn, 0, SEEK_END);\r
+  SecFileSize = ftell (FpIn);\r
+\r
+  //\r
+  // Close the SEC file\r
+  //\r
+  fclose (FpIn);\r
+\r
+  //\r
+  // Open the reset vector data file\r
+  //\r
+  if ((FpIn = fopen (argv[2], "rb")) == NULL) {\r
+    Error (NULL, 0, 0, "Unable to open file", argv[2]);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Open the output file\r
+  //\r
+  if ((FpOut = fopen (argv[3], "w+b")) == NULL) {\r
+    Error (NULL, 0, 0, "Unable to open file", argv[3]);\r
+    fclose (FpIn);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Copy the input file to the output file\r
+  //\r
+  if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {\r
+    fclose (FpIn);\r
+    fclose (FpOut);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Close the reset vector data file\r
+  //\r
+  fclose (FpIn);\r
+\r
+  //\r
+  // Fix the destination relative in the jmp instruction\r
+  // in the reset vector data structure\r
+  //\r
+  fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);\r
+  DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);\r
+  if (DestRel <= -65536) {\r
+    Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);\r
+    fclose (FpOut);\r
+    return STATUS_ERROR;\r
+  }\r
+\r
+  if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {\r
+    Error (NULL, 0, 0, "Failed to write to the output file", NULL);\r
+    fclose (FpOut);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Close the output file\r
+  //\r
+  fclose (FpOut);\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
+\r
+STATUS\r
+GetEntryPoint (\r
+  IN  FILE   *ExeFile,\r
+  OUT UINT32 *EntryPoint\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get the address of the entry point of a PE/TE file.\r
+\r
+Arguments:\r
+\r
+  PeFile     - File pointer to the specified PE/TE file.\r
+  EntryPoint - Buffer for the address of the entry point to be returned.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - Function completed successfully.\r
+  STATUS_ERROR   - Error occured.\r
+\r
+--*/\r
+// GC_TODO:    ExeFile - add argument and description to function comment\r
+{\r
+  EFI_IMAGE_DOS_HEADER    DosHeader;\r
+  EFI_IMAGE_NT_HEADERS32  NtHeader;\r
+  EFI_TE_IMAGE_HEADER     TeHeader;\r
+\r
+  //\r
+  // Check if it is a TE file\r
+  //\r
+  fseek (ExeFile, 0, SEEK_SET);\r
+  //\r
+  // Attempt to read the TE header\r
+  //\r
+  if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {\r
+    if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+      if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {\r
+        Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);\r
+        return STATUS_ERROR;\r
+      }\r
+\r
+      *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;\r
+      return STATUS_SUCCESS;\r
+    }\r
+  }\r
+  //\r
+  // Check if it is a PE file\r
+  //\r
+  fseek (ExeFile, 0, SEEK_SET);\r
+  //\r
+  // Attempt to read the DOS header\r
+  //\r
+  if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {\r
+    goto InvalidFile;\r
+  }\r
+  //\r
+  // Check the magic number\r
+  //\r
+  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
+    goto InvalidFile;\r
+  }\r
+  //\r
+  // Position into the file and read the NT PE header\r
+  //\r
+  fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);\r
+  if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {\r
+    goto InvalidFile;\r
+  }\r
+  //\r
+  // Check the PE signature in the header\r
+  //\r
+  if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
+    goto InvalidFile;\r
+  }\r
+  //\r
+  // Make sure the PE file is PE32 for IA32\r
+  //\r
+  if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||\r
+      NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
+      ) {\r
+    Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);\r
+    return STATUS_ERROR;\r
+  }\r
+  //\r
+  // Get the entry point from the optional header\r
+  //\r
+  *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;\r
+  return STATUS_SUCCESS;\r
+\r
+InvalidFile:\r
+  Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);\r
+  return STATUS_ERROR;\r
+}\r
+\r
+STATUS\r
+CopyFile (\r
+  FILE    *FpIn,\r
+  FILE    *FpOut\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Copy file.\r
+\r
+Arguments:\r
+\r
+  FpIn  - File pointer to the source file.\r
+  FpOut - File pointer to the destination file.\r
+\r
+Returns:\r
+  STATUS_SUCCESS - Function completed successfully.\r
+  STATUS_ERROR   - Error occured.\r
+\r
+--*/\r
+{\r
+  INTN  FileSize;\r
+\r
+  INTN  Offset;\r
+\r
+  INTN  Length;\r
+  UINT8 Buffer[BUF_SIZE];\r
+\r
+  fseek (FpIn, 0, SEEK_END);\r
+  FileSize = ftell (FpIn);\r
+\r
+  fseek (FpIn, 0, SEEK_SET);\r
+  fseek (FpOut, 0, SEEK_SET);\r
+\r
+  Offset = 0;\r
+  while (Offset < FileSize) {\r
+    Length = sizeof (Buffer);\r
+    if (FileSize - Offset < Length) {\r
+      Length = FileSize - Offset;\r
+    }\r
+\r
+    if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {\r
+      Error (NULL, 0, 0, "Copy file error", NULL);\r
+      return STATUS_ERROR;\r
+    }\r
+\r
+    Offset += Length;\r
+  }\r
+\r
+  return STATUS_SUCCESS;\r
+}\r
diff --git a/Tools/Source/TianoTools/SecFixup/SecFixup.h b/Tools/Source/TianoTools/SecFixup/SecFixup.h
new file mode 100644 (file)
index 0000000..5571dc3
--- /dev/null
@@ -0,0 +1,146 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  \r
+  SecFixup.h\r
+\r
+Abstract:\r
+\r
+  Definitions for the SecFixup utility.\r
+\r
+--*/\r
+\r
+#ifndef _SEC_FIXUP_H\r
+#define _SEC_FIXUP_H\r
+\r
+//\r
+// Utility Name\r
+//\r
+#define UTILITY_NAME  "SecFixup"\r
+\r
+//\r
+// Utility version information\r
+//\r
+#define UTILITY_MAJOR_VERSION 0\r
+#define UTILITY_MINOR_VERSION 1\r
+#define UTILITY_DATE          __DATE__\r
+\r
+//\r
+// The maximum number of arguments accepted from the command line.\r
+//\r
+#define MAX_ARGS        4\r
+\r
+#define DEST_REL_OFFSET 13\r
+#define BUF_SIZE        (8 * 1024)\r
+\r
+//\r
+// The function that displays general utility information\r
+//\r
+VOID\r
+PrintUtilityInfo (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that displays the utility usage message.\r
+//\r
+VOID\r
+PrintUsage (\r
+  VOID\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  None\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that gets the entry point of a PE/TE file.\r
+//\r
+STATUS\r
+GetEntryPoint (\r
+  IN  FILE   *ExeFile,\r
+  OUT UINT32 *EntryPoint\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  ExeFile     - GC_TODO: add argument description\r
+  EntryPoint  - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+//\r
+// The function that copies a file.\r
+//\r
+STATUS\r
+CopyFile (\r
+  FILE    *FpIn,\r
+  FILE    *FpOut\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  FpIn  - GC_TODO: add argument description\r
+  FpOut - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+;\r
+\r
+#endif\r
diff --git a/Tools/Source/TianoTools/SplitFile/Makefile b/Tools/Source/TianoTools/SplitFile/Makefile
new file mode 100644 (file)
index 0000000..3cd45f9
--- /dev/null
@@ -0,0 +1,70 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE      = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=SplitFile\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\SplitFile.c"\r
+TARGET_EXE_INCLUDE = \r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB)  $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/SplitFile/SplitFile.c b/Tools/Source/TianoTools/SplitFile/SplitFile.c
new file mode 100644 (file)
index 0000000..b1af1a8
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+*/\r
+\r
+// GC_TODO: fix comment to start with /*++\r
+#include "stdio.h"\r
+#include "string.h"\r
+#include "stdlib.h"\r
+\r
+void\r
+helpmsg (\r
+  void\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  printf (\r
+    "SplitFile Filename Offset\n""   Filename = Input file to split\n""   Offset = offset at which to split file\n"\r
+    "\n\n""SplitFile will break a file in two pieces at the requested offset\n"\r
+    "  outputting Filename1 and Filename2\n"\r
+    );\r
+}\r
+\r
+int\r
+main (\r
+  int argc,\r
+  char*argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  GC_TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  argc  - GC_TODO: add argument description\r
+  ]     - GC_TODO: add argument description\r
+\r
+Returns:\r
+\r
+  GC_TODO: add return values\r
+\r
+--*/\r
+{\r
+  FILE          *In;\r
+\r
+  FILE          *Out1;\r
+\r
+  FILE          *Out2;\r
+  char          OutName1[512];\r
+  char          OutName2[512];\r
+  unsigned long Index;\r
+  unsigned long splitpoint;\r
+  char          CharC;\r
+\r
+  if (argc != 3) {\r
+    helpmsg ();\r
+    return -1;\r
+  }\r
+\r
+  In = fopen (argv[1], "rb");\r
+  if (In == NULL) {\r
+    printf ("Unable to open file \"%s\"\n", argv[1]);\r
+    return -1;\r
+  }\r
+\r
+  strncpy (OutName1, argv[1], 510);\r
+  strncpy (OutName2, argv[1], 510);\r
+  strcat (OutName1, "1");\r
+  strcat (OutName2, "2");\r
+\r
+  Out1 = fopen (OutName1, "wb");\r
+  if (Out1 == NULL) {\r
+    printf ("Unable to open file \"%s\"\n", OutName1);\r
+    return -1;\r
+  }\r
+\r
+  Out2 = fopen (OutName2, "wb");\r
+  if (Out2 == NULL) {\r
+    printf ("Unable to open file \"%s\"\n", OutName2);\r
+    return -1;\r
+  }\r
+\r
+  splitpoint = atoi (argv[2]);\r
+\r
+  for (Index = 0; Index < splitpoint; Index++) {\r
+    CharC = (char) fgetc (In);\r
+    if (feof (In)) {\r
+      break;\r
+    }\r
+\r
+    fputc (CharC, Out1);\r
+  }\r
+\r
+  for (;;) {\r
+    CharC = (char) fgetc (In);\r
+    if (feof (In)) {\r
+      break;\r
+    }\r
+\r
+    fputc (CharC, Out2);\r
+  }\r
+\r
+  fclose (In);\r
+  fclose (Out1);\r
+  fclose (Out2);\r
+\r
+  return 0;\r
+}\r
diff --git a/Tools/Source/TianoTools/Strip/Makefile b/Tools/Source/TianoTools/Strip/Makefile
new file mode 100644 (file)
index 0000000..f47a68f
--- /dev/null
@@ -0,0 +1,70 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation.  All rights reserved.\r
+#\r
+#  This software and associated documentation (if any) is furnished under \r
+#  a license and may only be used or copied in accordance with the terms \r
+#  of the license.  Except as permitted by such license, no part of this \r
+#  software or documentation may be reproduced, stored in a retrieval \r
+#  system, or transmitted in any form or by any means without the express \r
+#  written consent of Intel Corporation.\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE      = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=Strip\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\Strip.c"\r
+TARGET_EXE_INCLUDE = \r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB)  $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL\r
diff --git a/Tools/Source/TianoTools/Strip/Strip.c b/Tools/Source/TianoTools/Strip/Strip.c
new file mode 100644 (file)
index 0000000..3fd6ad7
--- /dev/null
@@ -0,0 +1,105 @@
+/*++\r
+\r
+Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+\r
+  Strip.c\r
+\r
+Abstract:\r
+\r
+  Quick Exe2Bin equivalent.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <memory.h>\r
+#include <string.h>\r
+#include <malloc.h>\r
+\r
+int\r
+main (\r
+  int  argc,\r
+  char *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Converts executable files to binary files.\r
+\r
+Arguments:\r
+\r
+  argc   - Number of command line arguments\r
+  argv[] - Array of pointers to the command line arguments\r
+\r
+Returns:\r
+\r
+  Zero     - Function completed successfully.\r
+  Non-zero - Function exited with errors. \r
+\r
+--*/\r
+{\r
+  FILE  *InFile;\r
+  FILE  *OutFile;\r
+  int   Index;\r
+  int   FileSize;\r
+  char  *Buffer;\r
+  char  *Ptrx;\r
+\r
+  if (argc < 3) {\r
+    printf ("Need more args, such as file name to convert and output name\n");\r
+    return -1;\r
+  }\r
+\r
+  InFile  = fopen (argv[1], "rb");\r
+  OutFile = fopen (argv[2], "wb");\r
+\r
+  if (!InFile) {\r
+    printf ("no file, exit\n");\r
+    return -1;\r
+  }\r
+\r
+  if (OutFile == NULL) {\r
+    printf ("Unable to open output file.\n");\r
+    return -1;\r
+  }\r
+\r
+  fseek (InFile, 0, SEEK_END);\r
+  FileSize = ftell (InFile);\r
+\r
+  if (FileSize < 0x200) {\r
+    printf ("%d is not a legal size, exit\n", FileSize);\r
+    return -1;\r
+  }\r
+\r
+  fseek (InFile, 0, SEEK_SET);\r
+\r
+  Buffer = malloc (FileSize);\r
+  if (Buffer == NULL) {\r
+    printf ("Error: Out of resources.\n");\r
+    return -1;\r
+  }\r
+\r
+  fread (Buffer, 1, FileSize, InFile);\r
+\r
+  Ptrx  = Buffer + 0x200;\r
+\r
+  Index = FileSize - 0x200;\r
+\r
+  fwrite (Ptrx, Index, 1, OutFile);\r
+\r
+  fclose (InFile);\r
+  fclose (OutFile);\r
+  free (Buffer);\r
+\r
+  return 0;\r
+}\r
diff --git a/Tools/Source/TianoTools/ZeroDebugData/Makefile b/Tools/Source/TianoTools/ZeroDebugData/Makefile
new file mode 100644 (file)
index 0000000..c20fd85
--- /dev/null
@@ -0,0 +1,63 @@
+#/*++\r
+#   \r
+#  Copyright (c) 2001 Intel Corporation\r
+#   \r
+#  Module Name:  makefile\r
+#   \r
+#  Abstract:\r
+#   \r
+#    This file is used to build the EFI utility.\r
+#   \r
+#--*/\r
+\r
+#\r
+# Do this if you want to compile from this directory\r
+#\r
+!IFNDEF TOOLCHAIN\r
+TOOLCHAIN = TOOLCHAIN_MSVC\r
+!ENDIF\r
+\r
+!INCLUDE PlatformTools.env\r
+\r
+#\r
+# Define some macros we use here. Should get rid of them someday and \r
+# get rid of the extra level of indirection.\r
+#\r
+COMMON_SOURCE      = $(EDK_TOOLS_COMMON)\r
+\r
+#\r
+# Common information\r
+#\r
+\r
+INC=$(INC)\r
+\r
+#\r
+# Target specific information\r
+#\r
+\r
+TARGET_NAME=ZeroDebugData\r
+TARGET_SOURCE_DIR = $(TIANO_TOOLS_SOURCE)\$(TARGET_NAME)\r
+\r
+TARGET_EXE = $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).exe\r
+\r
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\ZeroDebugData.c"\r
+TARGET_EXE_INCLUDE =\r
+\r
+#\r
+# Build targets\r
+#\r
+\r
+all: $(TARGET_EXE)\r
+\r
+#\r
+# Build EXE\r
+#\r
+\r
+$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE)\r
+  $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj\r
+\r
+$(TARGET_EXE): $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL)\r
+  $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB)  $(TARGET_EXE_LIBS)\r
+\r
+clean:\r
+  @if exist $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(TIANO_TOOLS_OUTPUT)\$(TARGET_NAME).*\r
diff --git a/Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c b/Tools/Source/TianoTools/ZeroDebugData/ZeroDebugData.c
new file mode 100644 (file)
index 0000000..2f20039
--- /dev/null
@@ -0,0 +1,390 @@
+/*++\r
+\r
+Copyright (c)  2001 - 2002 Intel Corporation. All rights reserved\r
+This software and associated documentation (if any) is furnished\r
+under a license and may only be used or copied in accordance\r
+with the terms of the license. Except as permitted by such\r
+license, no part of this software or documentation may be\r
+reproduced, stored in a retrieval system, or transmitted in any\r
+form or by any means without the express written consent of\r
+Intel Corporation.\r
+\r
+\r
+Module Name:\r
+  ZeroDebugData.c\r
+\r
+Abstract:\r
+  Zero the Debug Data Fields of Portable Executable (PE) format file.\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <malloc.h>\r
+\r
+void\r
+PrintUsage (\r
+  void\r
+  )\r
+/*++\r
+Routine Description:\r
+  print usage of ZeroDebugData command\r
+\r
+Arguments:\r
+  None\r
+\r
+Returns:\r
+  None\r
+--*/\r
+// GC_TODO:    void - add argument and description to function comment\r
+{\r
+  //\r
+  // print usage of command\r
+  //\r
+  printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");\r
+}\r
+\r
+int\r
+ReadFromFile (\r
+  FILE      *fp,\r
+  long      offset,\r
+  void      *buffer,\r
+  int       size\r
+  )\r
+/*++\r
+Routine Description:\r
+  read data from a specified location of file\r
+\r
+Arguments:\r
+  fp              - file pointer\r
+  offset          - number of bytes from beginning of file\r
+  buffer          - buffer used to store data\r
+  size            - size of buffer\r
+\r
+Returns:\r
+  =  0            - Success\r
+  = -1            - Failed\r
+--*/\r
+{\r
+  //\r
+  // set file pointer to the specified location of file\r
+  //\r
+  if (fseek (fp, offset, SEEK_SET) != 0) {\r
+    printf ("Error: Cannot move the current location of the file.\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // read data from the file\r
+  //\r
+  if (fread (buffer, size, 1, fp) != 1) {\r
+    printf ("Error: Cannot read data from the file.\n");\r
+    return -1;\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+ZeroDebugData (\r
+  FILE      *fp,\r
+  FILE      *fpData\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Zero the debug data fields of the file\r
+\r
+Arguments:\r
+\r
+  fp              - file pointer\r
+  fpData          - pointer to output file that ZeroDebugData progress is written to\r
+\r
+Returns:\r
+\r
+  =  0            - Success\r
+  = -1            - Failed\r
+\r
+--*/\r
+{\r
+  unsigned char header[4];\r
+  unsigned long offset;\r
+  unsigned long NumberOfRvaAndSizes;\r
+  unsigned int  nvalue;\r
+  unsigned long lvalue;\r
+  unsigned long Size;\r
+  unsigned long Pointer;\r
+  unsigned char *Buffer;\r
+  unsigned long Index;\r
+\r
+  //\r
+  // read the header of file\r
+  //\r
+  if (ReadFromFile (fp, 0, header, 2) != 0) {\r
+    printf ("Error: open image file\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // "MZ" -- the header of image file (PE)\r
+  //\r
+  if (strncmp ((char *) header, "MZ", 2) != 0) {\r
+    printf ("Error: Invalid Image file.\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // At location 0x3C, the stub has the file offset to the\r
+  // PE signature.\r
+  //\r
+  if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) {\r
+    return -1;\r
+  }\r
+  //\r
+  // read the header of optional\r
+  //\r
+  if (ReadFromFile (fp, offset, header, 4) != 0) {\r
+    return -1;\r
+  }\r
+  //\r
+  // "PE\0\0" -- the signature of optional header\r
+  //\r
+  if (strncmp ((char *) header, "PE\0\0", 4) != 0) {\r
+    printf ("Error: Invalid PE format file.\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // Add 16 to skip COFF file header, and get to optional header.\r
+  //\r
+  offset += 24;\r
+\r
+  //\r
+  // Check the magic field, 0x10B for PE32 and 0x20B for PE32+\r
+  //\r
+  if (ReadFromFile (fp, offset, &nvalue, 2) != 0) {\r
+    return -1;\r
+  }\r
+  //\r
+  // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92.\r
+  // Else it is 108.\r
+  //\r
+  switch (nvalue & 0xFFFF) {\r
+  case 0x10B:\r
+    offset += 92;\r
+    printf ("Info: Image is PE32. ");\r
+    break;\r
+\r
+  case 0x20B:\r
+    offset += 108;\r
+    printf ("Info: Image is PE32+. ");\r
+    break;\r
+\r
+  default:\r
+    printf ("Error: Magic value is unknown.\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // get the value of NumberOfRvaAndSizes\r
+  //\r
+  if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) {\r
+    printf ("Error: read NumberOfRvaAndSizes error.\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // printf ("Info: NumberOfRvaAndSizes = %d\n", NumberOfRvaAndSizes);\r
+  //\r
+  //\r
+  // Finding Debug Table, offset of Debug Table\r
+  // is 4 + 6 * 8 = 52.\r
+  //\r
+  if (NumberOfRvaAndSizes >= 7) {\r
+    if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) {\r
+      return -1;\r
+    }\r
+    //\r
+    // Read the SizeOfData(16) and PointerToRawData(24)\r
+    //\r
+    if (ReadFromFile (fp, lvalue + 16, &Size, 4) != 0) {\r
+      printf ("error: Size = %d\n", Size);\r
+      return -1;\r
+    }\r
+\r
+    printf ("Debug data: size = %xh, ", Size);\r
+    fprintf (fpData, "Debug data: size = %xh, ", Size);\r
+\r
+    if (ReadFromFile (fp, lvalue + 20, &Pointer, 4) != 0) {\r
+      printf ("error: LoadOffset = %xh\n", Pointer);\r
+      return -1;\r
+    }\r
+    //\r
+    // printf ("LoadOffset = %xh, ", Pointer);\r
+    //\r
+    fprintf (fpData, "LoadOffset = %xh, ", Pointer);\r
+\r
+    if (ReadFromFile (fp, lvalue + 24, &Pointer, 4) != 0) {\r
+      printf ("error: FileOffset = %xh\n", Pointer);\r
+      return -1;\r
+    }\r
+\r
+    printf ("FileOffset = %xh, ", Pointer);\r
+    fprintf (fpData, "FileOffset = %xh, \n", Pointer);\r
+\r
+    if ((lvalue != 0) && (Pointer != 0)) {\r
+      //\r
+      // prepare buffer\r
+      //\r
+      Buffer = malloc (Size + 1);\r
+      if (Buffer == NULL) {\r
+        printf ("Error: Cannot allocate memory.\n");\r
+        return -1;\r
+      }\r
+      //\r
+      // set file pointer to the specified location of file\r
+      //\r
+      if (fseek (fp, Pointer, SEEK_SET) != 0) {\r
+        printf ("Error: Cannot move the current location of the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+      //\r
+      // read data from PE file\r
+      //\r
+      if (fread (Buffer, Size, 1, fp) != 1) {\r
+        printf ("Error: Cannot read data from the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+      //\r
+      // write to data file\r
+      //\r
+      for (Index = 0; Index < Size;) {\r
+        fprintf (fpData, "%02x ", Buffer[Index]);\r
+\r
+        Index++;\r
+        if (Index % 8 == 0) {\r
+          fprintf (fpData, "\n");\r
+        }\r
+      }\r
+\r
+      fprintf (fpData, "\n");\r
+\r
+      //\r
+      // zero buffer and write back to PE file\r
+      //\r
+      if (fseek (fp, Pointer, SEEK_SET) != 0) {\r
+        printf ("Error: Cannot move the current location of the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+\r
+      memset (Buffer, 0, Size);\r
+      if (fwrite (Buffer, Size, 1, fp) != 1) {\r
+        perror ("Error: Cannot write zero to the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+      //\r
+      // set file pointer to the specified location of file\r
+      //\r
+      if (fseek (fp, lvalue + 4, SEEK_SET) != 0) {\r
+        printf ("Error: Cannot move the current location of the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+\r
+      if (fwrite (Buffer, 4, 1, fp) != 1) {\r
+        perror ("Error: Cannot write zero to the file.\n");\r
+        free (Buffer);\r
+        return -1;\r
+      }\r
+\r
+      free (Buffer);\r
+    }\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+int\r
+main (\r
+  int       argc,\r
+  char      *argv[]\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Prints the zero debug data of the PE file to the DebugData file.\r
+  Executes the ZeroDebugData function.\r
+\r
+Arguments:\r
+\r
+  argc   - Standard C argument, number of command line arguments.\r
+  argv[] - Standard C argument, array of pointers to the input files,\r
+           such as the PE and DebugData files.\r
+\r
+Returns:\r
+\r
+  zero    - success\r
+  nonzero - failure\r
+\r
+--*/\r
+{\r
+  FILE  *fp;\r
+  FILE  *fpData;\r
+  char  DataFile[1024] = "";\r
+\r
+  //\r
+  // check the number of parameters\r
+  //\r
+  if (argc < 2) {\r
+    printf ("\nUsage: ZeroDebugData <PE-File> [DebugData-File]\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // open the DebugData file, if not exists, return\r
+  //\r
+  if (argc >= 3) {\r
+    strcpy (DataFile, argv[2]);\r
+  } else {\r
+    strcpy (DataFile, "DebugData.dat");\r
+  }\r
+\r
+  fpData = fopen (DataFile, "a+");\r
+  if (fpData == NULL) {\r
+    fpData = fopen (DataFile, "w");\r
+    if (fpData == NULL) {\r
+      printf ("Error: Cannot open the data file!\n");\r
+      return -1;\r
+    }\r
+  }\r
+  //\r
+  // open the PE file\r
+  //\r
+  fp = fopen (argv[1], "r+b");\r
+  if (fp == NULL) {\r
+    printf ("Error: Cannot open the PE file!\n");\r
+    return -1;\r
+  }\r
+  //\r
+  // Zero the Debug Data to the PE file\r
+  //\r
+  printf ("Zero Debug Data to file %s:\n", argv[1]);\r
+  fprintf (fpData, "\nZero Debug Data to file %s:\n", argv[1]);\r
+  if ((int *) ZeroDebugData (fp, fpData) != 0) {\r
+    printf ("Error: Zero Debug Data PE file\n");\r
+    fclose (fp);\r
+    return -1;\r
+  }\r
+\r
+  printf (" success\n");\r
+\r
+  //\r
+  // close the PE file\r
+  //\r
+  fflush (fpData);\r
+  fflush (fp);\r
+  fclose (fpData);\r
+  fclose (fp);\r
+\r
+  return 0;\r
+}\r