Adding Additional Tools that are needed for Platform Image creation.
authorlhauch <lhauch@de2fecce-e211-0410-80a6-f3fac2684e05>
Fri, 19 May 2006 02:38:56 +0000 (02:38 +0000)
committerlhauch <lhauch@de2fecce-e211-0410-80a6-f3fac2684e05>
Fri, 19 May 2006 02:38:56 +0000 (02:38 +0000)
git-svn-id: https://edk2.tianocore.org/svn/edk2/trunk@198 de2fecce-e211-0410-80a6-f3fac2684e05

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

diff --git a/edk2/Tools/Source/TianoTools/CreateMtFile/CreateMtFile.c b/edk2/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/edk2/Tools/Source/TianoTools/CreateMtFile/Makefile b/edk2/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/edk2/Tools/Source/TianoTools/EfiCompress/EfiCompressMain.c b/edk2/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/edk2/Tools/Source/TianoTools/EfiCompress/makefile b/edk2/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/edk2/Tools/Source/TianoTools/EfiRom/EfiRom.c b/edk2/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/edk2/Tools/Source/TianoTools/EfiRom/Makefile b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/FlashDefFile.c b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/FlashDefFile.h b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/FlashMap.c b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/Makefile b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/Microcode.c b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/Microcode.h b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/Symbols.c b/edk2/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/edk2/Tools/Source/TianoTools/FlashMap/Symbols.h b/edk2/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/edk2/Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c b/edk2/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/edk2/Tools/Source/TianoTools/GenAcpiTable/Makefile b/edk2/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/edk2/Tools/Source/TianoTools/GenCapsuleHdr/CreateGuid.c b/edk2/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/edk2/Tools/Source/TianoTools/GenCapsuleHdr/GenCapsuleHdr.c b/edk2/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