summaryrefslogtreecommitdiff
path: root/Source/GenFfsFile
diff options
context:
space:
mode:
Diffstat (limited to 'Source/GenFfsFile')
-rw-r--r--Source/GenFfsFile/GenFfsFile.c2646
-rw-r--r--Source/GenFfsFile/GenFfsFile.h36
-rw-r--r--Source/GenFfsFile/SimpleFileParsing.c969
-rw-r--r--Source/GenFfsFile/build.xml70
4 files changed, 3721 insertions, 0 deletions
diff --git a/Source/GenFfsFile/GenFfsFile.c b/Source/GenFfsFile/GenFfsFile.c
new file mode 100644
index 0000000..1eea09f
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.c
@@ -0,0 +1,2646 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFfsFile.c
+
+Abstract:
+
+ This file contains functions required to generate a Firmware File System
+ file.
+
+--*/
+
+#include <stdio.h>
+#include <ctype.h> // for isalpha()
+//
+// include file for _spawnv
+//
+#ifndef __GNUC__
+#include <process.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+#include <Common/FirmwareFileSystem.h>
+#include <Common/FirmwareVolumeHeader.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+#include "ParseInf.h"
+#include "EfiCompress.h"
+#include "EfiCustomizedCompress.h"
+#include "Crc32.h"
+#include "GenFfsFile.h"
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#define UTILITY_NAME "GenFfsFile"
+#define TOOLVERSION "0.32"
+#define MAX_ARRAY_SIZE 100
+
+static
+INT32
+GetNextLine (
+ OUT CHAR8 *Destination,
+ IN FILE *Package,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+void
+CheckSlash (
+ IN OUT CHAR8 *String,
+ IN FILE *In,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+INT32
+FindSectionInPackage (
+ IN CHAR8 *BuildDirectory,
+ IN FILE *OverridePackage,
+ IN OUT UINT32 *LineNumber
+ );
+
+static
+STATUS
+ProcessCommandLineArgs (
+ int Argc,
+ char *Argv[]
+ );
+
+static
+void
+PrintUsage (
+ void
+ );
+
+//
+// Keep globals in this structure
+//
+static struct {
+ UINT8 BuildDirectory[_MAX_PATH];
+ UINT8 PrimaryPackagePath[_MAX_PATH];
+ UINT8 OverridePackagePath[_MAX_PATH];
+ BOOLEAN Verbose;
+} mGlobals;
+
+static EFI_GUID mZeroGuid = { 0 };
+
+static
+void
+StripQuotes (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes quotes and/or whitespace from around a string
+
+Arguments:
+
+ String - String to remove quotes from
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ UINTN Index2;
+ UINTN StrLen;
+
+ Index2 = strspn (String, "\" \t\n");
+ StrLen = strlen (String);
+
+ for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) {
+ String[Index - Index2] = String[Index];
+ }
+
+ String[Index - Index2] = 0;
+}
+
+static
+void
+PrintUsage (
+ void
+ )
+/*++
+
+Routine Description:
+
+ Print Error / Help message.
+
+Arguments:
+
+ void
+
+Returns:
+
+ None
+
+--*/
+{
+ printf ("Usage:\n");
+ printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
+ printf (" -b \"build directory\":\n ");
+ printf (" specifies the full path to the component build directory.\n");
+ printf (" -p1 \"P1_path\":\n");
+ printf (" specifies fully qualified file name to the primary package file.\n");
+ printf (" This file will normally exist in the same directory as the makefile\n");
+ printf (" for the component. Required.\n");
+ printf (" -p2 \"P2_path\":\n");
+ printf (" specifies fully qualified file name to the override package file.\n");
+ printf (" This file will normally exist in the build tip. Optional.\n");
+}
+
+static
+INT32
+TestComment (
+ IN CHAR8 *String,
+ IN FILE *In
+ )
+/*++
+
+Routine Description:
+
+ Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment
+
+Arguments:
+
+ String - String to test
+
+ In - Open file to move pointer within
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Not a comment
+ 1 - Comment bypassed
+
+--*/
+{
+ CHAR8 CharBuffer;
+
+ CharBuffer = 0;
+ if ((String[0] == '/') && (String[1] == '/')) {
+ while (CharBuffer != '\n') {
+ fscanf (In, "%c", &CharBuffer);
+ if (feof (In)) {
+ return -1;
+ }
+ }
+ } else {
+ return 0;
+ }
+
+ return 1;
+}
+
+static
+void
+BreakString (
+ IN CONST CHAR8 *Source,
+ OUT CHAR8 *Destination,
+ IN INTN Direction
+ )
+/*++
+
+Routine Description:
+
+ Takes an input string and returns either the part before the =, or the part after the =, depending on direction
+
+Arguments:
+
+ Source - String to break
+
+ Destination - Buffer to place new string in
+
+ Direction - 0 to return all of source string before =
+ 1 to return all of source string after =
+
+Returns:
+
+ None
+
+--*/
+{
+ UINTN Index;
+ UINTN Index2;
+
+ Index = 0;
+ Index2 = 0;
+
+ if (strchr (Source, '=') == NULL) {
+ strcpy (Destination, Source);
+
+ return ;
+ }
+
+ if (Direction == 0) {
+ //
+ // return part of string before =
+ //
+ while (Source[Index] != '=') {
+ Destination[Index] = Source[Index++];
+ }
+
+ Destination[Index] = 0;
+ } else {
+ //
+ // return part of string after =
+ //
+ strcpy (Destination, strchr (Source, '=') + 1);
+ }
+}
+
+static
+INT32
+GetNextLine (
+ OUT CHAR8 *Destination,
+ IN FILE *Package,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Gets the next non-commented line from the file
+
+Arguments:
+
+ Destination - Where to put string
+
+ Package - Package to get string from
+
+ LineNumber - The actual line number.
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Success
+
+--*/
+{
+ CHAR8 String[_MAX_PATH];
+ fscanf (Package, "%s", &String);
+ if (feof (Package)) {
+ return -1;
+ }
+
+ while (TestComment (String, Package) == 1) {
+ fscanf (Package, "%s", &String);
+ if (feof (Package)) {
+ return -1;
+ }
+ }
+
+ strcpy (Destination, String);
+ return 0;
+}
+
+static
+VOID
+CheckSlash (
+ IN OUT CHAR8 *String,
+ IN FILE *In,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Checks to see if string is line continuation character, if so goes to next valid line
+
+Arguments:
+
+ String - String to test
+
+ In - Open file to move pointer within
+
+ LineNumber - The line number.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 ByteBuffer;
+ ByteBuffer = 0;
+
+ switch (String[0]) {
+
+ case '\\':
+ while (String[0] == '\\') {
+ while (ByteBuffer != '\n') {
+ fscanf (In, "%c", &ByteBuffer);
+ }
+ (*LineNumber)++;
+ if (GetNextLine (String, In, LineNumber) == -1) {
+ return ;
+ }
+ }
+ break;
+
+ case '\n':
+ (*LineNumber)++;
+ while (String[0] == '\n') {
+ if (GetNextLine (String, In, LineNumber) == -1) {
+ return ;
+ }
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+}
+
+static
+INT32
+FindSectionInPackage (
+ IN CHAR8 *BuildDirectory,
+ IN FILE *OverridePackage,
+ IN OUT UINT32 *LineNumber
+ )
+/*++
+
+Routine Description:
+
+ Finds the matching section within the package
+
+Arguments:
+
+ BuildDirectory - name of section to find
+
+ OverridePackage - Package file to search within
+
+ LineNumber - The line number.
+
+Returns:
+
+ -1 - End of file reached
+ 0 - Success
+
+--*/
+{
+ CHAR8 String[_MAX_PATH];
+ CHAR8 NewString[_MAX_PATH];
+ String[0] = 0;
+
+ while (strcmp (BuildDirectory, String) != 0) {
+ if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) {
+ return -1;
+ }
+
+ if (NewString[0] == '[') {
+ if (NewString[strlen (NewString) - 1] != ']') {
+ //
+ // have to construct string.
+ //
+ strcpy (String, NewString + 1);
+
+ while (1) {
+ fscanf (OverridePackage, "%s", &NewString);
+ if (feof (OverridePackage)) {
+ return -1;
+ }
+
+ if (NewString[0] != ']') {
+ if (strlen (String) != 0) {
+ strcat (String, " ");
+ }
+
+ strcat (String, NewString);
+ if (String[strlen (String) - 1] == ']') {
+ String[strlen (String) - 1] = 0;
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+ } else {
+ NewString[strlen (NewString) - 1] = 0;
+ strcpy (String, NewString + 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static
+EFI_STATUS
+GenSimpleGuidSection (
+ IN OUT UINT8 *FileBuffer,
+ IN OUT UINT32 *BufferSize,
+ IN UINT32 DataSize,
+ IN EFI_GUID SignGuid,
+ IN UINT16 GuidedSectionAttributes
+ )
+/*++
+
+Routine Description:
+
+ add GUIDed section header for the data buffer.
+ data stays in same location (overwrites source data).
+
+Arguments:
+
+ FileBuffer - Buffer containing data to sign
+
+ BufferSize - On input, the size of FileBuffer. On output, the size of
+ actual section data (including added section header).
+
+ DataSize - Length of data to Sign
+
+ SignGuid - Guid to be add.
+
+ GuidedSectionAttributes - The section attribute.
+
+Returns:
+
+ EFI_SUCCESS - Successful
+ EFI_OUT_OF_RESOURCES - Not enough resource.
+
+--*/
+{
+ UINT32 TotalSize;
+
+ EFI_GUID_DEFINED_SECTION GuidSectionHeader;
+ UINT8 *SwapBuffer;
+
+ SwapBuffer = NULL;
+
+ if (DataSize == 0) {
+ *BufferSize = 0;
+
+ return EFI_SUCCESS;
+ }
+
+ TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION);
+ GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED;
+ GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
+ GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
+ GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
+ memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID));
+ GuidSectionHeader.Attributes = GuidedSectionAttributes;
+ GuidSectionHeader.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION);
+
+ SwapBuffer = (UINT8 *) malloc (DataSize);
+ if (SwapBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memcpy (SwapBuffer, FileBuffer, DataSize);
+ memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION));
+ memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize);
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((TotalSize & 0x03) != 0) {
+ FileBuffer[TotalSize] = 0;
+ TotalSize++;
+ }
+
+ *BufferSize = TotalSize;
+
+ if (SwapBuffer != NULL) {
+ free (SwapBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+EFI_STATUS
+CompressSection (
+ UINT8 *FileBuffer,
+ UINT32 *BufferSize,
+ UINT32 DataSize,
+ CHAR8 *Type
+ )
+/*++
+
+Routine Description:
+
+ Compress the data and add section header for the compressed data.
+ Compressed data (with section header) stays in same location as the source
+ (overwrites source data).
+
+Arguments:
+
+ FileBuffer - Buffer containing data to Compress
+
+ BufferSize - On input, the size of FileBuffer. On output, the size of
+ actual compressed data (including added section header).
+ When buffer is too small, this value indicates the size needed.
+
+ DataSize - The size of data to compress
+
+ Type - The compression type (not used currently).
+ Assume EFI_HEAVY_COMPRESSION.
+
+Returns:
+
+ EFI_BUFFER_TOO_SMALL - Buffer size is too small.
+ EFI_UNSUPPORTED - Compress type can not be supported.
+ EFI_SUCCESS - Successful
+ EFI_OUT_OF_RESOURCES - Not enough resource.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT8 *CompData;
+ UINT32 CompSize;
+ UINT32 TotalSize;
+ EFI_COMPRESSION_SECTION CompressionSet;
+ UINT8 CompressionType;
+ COMPRESS_FUNCTION CompressFunction;
+
+ Status = EFI_SUCCESS;
+ CompData = NULL;
+ CompSize = 0;
+ TotalSize = 0;
+ CompressFunction = NULL;
+
+ //
+ // Get the compress type
+ //
+ if (strcmpi (Type, "Dummy") == 0) {
+ //
+ // Added "Dummy" to keep backward compatibility.
+ //
+ CompressionType = EFI_STANDARD_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) Compress;
+
+ } else if (strcmpi (Type, "LZH") == 0) {
+ //
+ // EFI stardard compression (LZH)
+ //
+ CompressionType = EFI_STANDARD_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) Compress;
+
+ } else {
+ //
+ // Customized compression
+ //
+ Status = SetCustomizedCompressionType (Type);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CompressionType = EFI_CUSTOMIZED_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
+ }
+ //
+ // Compress the raw data
+ //
+ Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ CompData = malloc (CompSize);
+ if (!CompData) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return Status;
+ }
+
+ TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION);
+
+ //
+ // Buffer too small?
+ //
+ if (TotalSize > *BufferSize) {
+ *BufferSize = TotalSize;
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Add the section header for the compressed data
+ //
+ CompressionSet.CommonHeader.Type = EFI_SECTION_COMPRESSION;
+ CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff);
+ CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8);
+ CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16);
+ CompressionSet.CompressionType = CompressionType;
+ CompressionSet.UncompressedLength = DataSize;
+
+ //
+ // Copy header and data to the buffer
+ //
+ memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION));
+ memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize);
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((TotalSize & 0x03) != 0) {
+ FileBuffer[TotalSize] = 0;
+ TotalSize++;
+ }
+
+ *BufferSize = TotalSize;
+
+ if (CompData != NULL) {
+ free (CompData);
+ }
+
+ return EFI_SUCCESS;
+}
+
+static
+void
+StripParens (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes Parenthesis from around a string
+
+Arguments:
+
+ String - String to remove parens from
+
+Returns:
+
+ None
+
+--*/
+{
+ INT32 Index;
+
+ if (String[0] != '(') {
+ return ;
+ }
+
+ for (Index = 1; String[Index] != ')'; Index++) {
+ String[Index - 1] = String[Index];
+ if (String[Index] == 0) {
+ return ;
+ }
+ }
+
+ String[Index - 1] = 0;
+
+ return ;
+}
+
+static
+void
+StripEqualMark (
+ IN OUT CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Removes Equal Mark from around a string
+
+Arguments:
+
+ String - String to remove equal mark from
+
+Returns:
+
+ None
+
+--*/
+{
+ INT32 Index;
+
+ if (String[0] != '=' && String[strlen (String) - 1] != '=') {
+ return ;
+ }
+
+ if (String[0] == '=') {
+
+ for (Index = 1; String[Index] != 0; Index++) {
+ String[Index - 1] = String[Index];
+ }
+
+ String[Index - 1] = 0;
+ }
+
+ if (String[strlen (String) - 1] == '=') {
+ String[strlen (String) - 1] = 0;
+ }
+
+ return ;
+}
+
+static
+INT32
+ProcessEnvironmentVariable (
+ IN CHAR8 *Buffer,
+ OUT CHAR8 *NewBuffer
+ )
+/*++
+
+Routine Description:
+
+ Converts environment variables to values
+
+Arguments:
+
+ Buffer - Buffer containing Environment Variable String
+
+ NewBuffer - Buffer containing value of environment variable
+
+
+Returns:
+
+ Number of characters from Buffer used
+
+--*/
+{
+ INT32 Index;
+ INT32 Index2;
+ CHAR8 VariableBuffer[_MAX_PATH];
+
+ Index = 2;
+ Index2 = 0;
+
+ while (Buffer[Index] != ')') {
+ VariableBuffer[Index - 2] = Buffer[Index++];
+ }
+
+ VariableBuffer[Index - 2] = 0;
+ Index++;
+
+ if (getenv (VariableBuffer) != NULL) {
+ strcpy (NewBuffer, getenv (VariableBuffer));
+ } else {
+ printf ("Environment variable %s not found!\n", VariableBuffer);
+ }
+
+ return Index;
+}
+
+static
+void
+SplitAttributesField (
+ IN CHAR8 *Buffer,
+ IN CHAR8 *AttributesArray[],
+ IN OUT UINT32 *NumberOfAttributes
+ )
+/*
+ NumberOfAttributes: on input, it specifies the current number of attributes
+ stored in AttributeArray.
+ on output, it is updated to the latest number of attributes
+ stored in AttributesArray.
+*/
+{
+ UINT32 Index;
+ UINT32 Index2;
+ UINT32 z;
+ CHAR8 *CharBuffer;
+
+ CharBuffer = NULL;
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ ZeroMem (CharBuffer, _MAX_PATH);
+
+ for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) {
+
+ if (Buffer[Index] != '|') {
+ CharBuffer[z] = Buffer[Index];
+ z++;
+ } else {
+
+ CharBuffer[z] = 0;
+ AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
+ Index2++;
+
+ //
+ // allocate new char buffer for the next attributes string
+ //
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ ZeroMem (CharBuffer, _MAX_PATH);
+ z = 0;
+ }
+ }
+
+ CharBuffer[z] = 0;
+ //
+ // record the last attributes string in the Buffer
+ //
+ AttributesArray[*NumberOfAttributes + Index2] = CharBuffer;
+ Index2++;
+
+ *NumberOfAttributes += Index2;
+
+ return ;
+}
+
+static
+INT32
+GetToolArguments (
+ CHAR8 *ToolArgumentsArray[],
+ FILE *Package,
+ CHAR8 **PtrInputFileName,
+ CHAR8 **PtrOutputFileName,
+ EFI_GUID *Guid,
+ UINT16 *GuidedSectionAttributes
+ )
+{
+ CHAR8 Buffer[_MAX_PATH];
+ BOOLEAN ArgumentsFlag;
+ BOOLEAN InputFlag;
+ BOOLEAN OutputFlag;
+ BOOLEAN GuidFlag;
+ BOOLEAN AttributesFlag;
+ UINT32 argc;
+ UINT32 Index2;
+ UINT32 z;
+ CHAR8 *CharBuffer;
+ INT32 Index;
+ INT32 ReturnValue;
+ EFI_STATUS Status;
+
+ CHAR8 *AttributesArray[MAX_ARRAY_SIZE];
+ UINT32 NumberOfAttributes;
+ CHAR8 *InputFileName;
+ CHAR8 *OutputFileName;
+ UINT32 LineNumber;
+ Buffer[_MAX_PATH];
+
+ ArgumentsFlag = FALSE;
+ InputFlag = FALSE;
+ OutputFlag = FALSE;
+ GuidFlag = FALSE;
+ AttributesFlag = FALSE;
+ //
+ // Start at 1, since ToolArgumentsArray[0]
+ // is the program name.
+ //
+ argc = 1;
+ Index2 = 0;
+
+ z = 0;
+ ReturnValue = 0;
+ NumberOfAttributes = 0;
+ InputFileName = NULL;
+ OutputFileName = NULL;
+
+ ZeroMem (Buffer, _MAX_PATH);
+ ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
+ LineNumber = 0;
+ while (Buffer[0] != ')') {
+
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ StripEqualMark (Buffer);
+ } else {
+ Error (NULL, 0, 0, "failed to get next line from package file", NULL);
+ return -1;
+ }
+
+ if (Buffer[0] == ')') {
+ break;
+ } else if (strcmpi (Buffer, "ARGS") == 0) {
+
+ ArgumentsFlag = TRUE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "INPUT") == 0) {
+
+ InputFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "OUTPUT") == 0) {
+
+ OutputFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ continue;
+
+ } else if (strcmpi (Buffer, "GUID") == 0) {
+
+ GuidFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ AttributesFlag = FALSE;
+ //
+ // fetch the GUID for the section
+ //
+ continue;
+
+ } else if (strcmpi (Buffer, "ATTRIBUTES") == 0) {
+
+ AttributesFlag = TRUE;
+ ArgumentsFlag = FALSE;
+ //
+ // fetch the GUIDed Section's Attributes
+ //
+ continue;
+
+ } else if (strcmpi (Buffer, "") == 0) {
+ continue;
+ }
+ //
+ // get all command arguments into ToolArgumentsArray
+ //
+ if (ArgumentsFlag) {
+
+ StripEqualMark (Buffer);
+
+ CharBuffer = (CHAR8 *) malloc (_MAX_PATH);
+ if (CharBuffer == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (CharBuffer, sizeof (_MAX_PATH));
+
+ ToolArgumentsArray[argc] = CharBuffer;
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (ToolArgumentsArray[argc], &Buffer[Index]);
+ }
+ } else {
+ strcpy (ToolArgumentsArray[argc], Buffer);
+ }
+
+ argc += 1;
+ ToolArgumentsArray[argc] = NULL;
+ continue;
+ }
+
+ if (InputFlag) {
+
+ StripEqualMark (Buffer);
+
+ InputFileName = (CHAR8 *) malloc (_MAX_PATH);
+ if (InputFileName == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (InputFileName, sizeof (_MAX_PATH));
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (InputFileName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (InputFileName, Buffer);
+ }
+
+ InputFlag = FALSE;
+ continue;
+ }
+
+ if (OutputFlag) {
+
+ StripEqualMark (Buffer);
+
+ OutputFileName = (CHAR8 *) malloc (_MAX_PATH);
+ if (OutputFileName == NULL) {
+ goto ErrorExit;
+ }
+
+ ZeroMem (OutputFileName, sizeof (_MAX_PATH));
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (OutputFileName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (OutputFileName, Buffer);
+ }
+
+ OutputFlag = FALSE;
+ continue;
+ }
+
+ if (GuidFlag) {
+
+ StripEqualMark (Buffer);
+
+ Status = StringToGuid (Buffer, Guid);
+ if (EFI_ERROR (Status)) {
+ ReturnValue = -1;
+ goto ErrorExit;
+ }
+
+ GuidFlag = FALSE;
+ }
+
+ if (AttributesFlag) {
+
+ StripEqualMark (Buffer);
+
+ //
+ // there might be no space between each attribute in the statement,
+ // split them aside and return each attribute string
+ // in the AttributesArray
+ //
+ SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes);
+ }
+ }
+ //
+ // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
+ // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
+ //
+ for (z = 0; z < NumberOfAttributes; z++) {
+ if (strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) {
+ *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED;
+ } else if (strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) {
+ *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
+ }
+ }
+
+ErrorExit:
+
+ for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) {
+ if (AttributesArray[Index2] == NULL) {
+ break;
+ }
+
+ free (AttributesArray[Index2]);
+ }
+
+ *PtrInputFileName = InputFileName;
+ *PtrOutputFileName = OutputFileName;
+
+ return ReturnValue;
+}
+
+static
+INT32
+ProcessScript (
+ IN OUT UINT8 *FileBuffer,
+ IN FILE *Package,
+ IN CHAR8 *BuildDirectory,
+ IN BOOLEAN ForceUncompress
+ )
+/*++
+
+Routine Description:
+
+ Signs the section, data stays in same location
+
+Arguments:
+
+ FileBuffer - Data Buffer
+
+ Package - Points to curly brace in Image Script
+
+ BuildDirectory - Name of the source directory parameter
+
+ ForceUncompress - Whether to force uncompress.
+
+Returns:
+
+ Number of bytes added to file buffer
+ -1 on error
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT32 Size;
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 FileName[_MAX_PATH];
+ CHAR8 NewBuffer[_MAX_PATH];
+ INT32 Index3;
+ INT32 Index2;
+ UINT32 ReturnValue;
+ UINT8 ByteBuffer;
+ FILE *InFile;
+ UINT32 SourceDataSize;
+ CHAR8 *ToolArgumentsArray[MAX_ARRAY_SIZE];
+ CHAR8 *OutputFileName;
+ CHAR8 *InputFileName;
+ CHAR8 ToolName[_MAX_PATH];
+ FILE *OutputFile;
+ FILE *InputFile;
+ UINT8 Temp;
+ int returnint;
+ INT32 Index;
+ UINT32 LineNumber;
+ BOOLEAN IsError;
+ EFI_GUID SignGuid;
+ UINT16 GuidedSectionAttributes;
+ UINT8 *TargetFileBuffer;
+
+ OutputFileName = NULL;
+ InputFileName = NULL;
+ OutputFile = NULL;
+ InputFile = NULL;
+ IsError = FALSE;
+ GuidedSectionAttributes = 0;
+ TargetFileBuffer = NULL;
+
+ Size = 0;
+ LineNumber = 0;
+ Buffer[0] = 0;
+ for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) {
+ ToolArgumentsArray[Index3] = NULL;
+ }
+
+ while (Buffer[0] != '}') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ } else {
+ printf ("ERROR in IMAGE SCRIPT!\n");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ if (strcmpi (Buffer, "Compress") == 0) {
+ //
+ // Handle compress
+ //
+ //
+ // read compression type
+ //
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+
+ StripParens (Buffer);
+ if (Buffer[0] == '$') {
+ ProcessEnvironmentVariable (&Buffer[0], Type);
+ } else {
+ strcpy (Type, Buffer);
+ }
+ //
+ // build buffer
+ //
+ while (Buffer[0] != '{') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress);
+ if (ReturnValue == -1) {
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // Call compress routine on buffer.
+ // Occasionally, compressed data + section header would
+ // be largere than the source and EFI_BUFFER_TOO_SMALL is
+ // returned from CompressSection()
+ //
+ SourceDataSize = ReturnValue;
+
+ if (!ForceUncompress) {
+
+ Status = CompressSection (
+ &FileBuffer[Size],
+ &ReturnValue,
+ SourceDataSize,
+ Type
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = CompressSection (
+ &FileBuffer[Size],
+ &ReturnValue,
+ SourceDataSize,
+ Type
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ IsError = TRUE;
+ goto Done;
+ }
+ }
+
+ Size += ReturnValue;
+
+ } else if (strcmpi (Buffer, "Tool") == 0) {
+
+ ZeroMem (ToolName, _MAX_PATH);
+ ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE);
+ ZeroMem (&SignGuid, sizeof (EFI_GUID));
+
+ //
+ // handle signing Tool
+ //
+ while (Buffer[0] != '(') {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ if (strcmpi (Buffer, "(") == 0) {
+ if (GetNextLine (Buffer, Package, &LineNumber) != -1) {
+ CheckSlash (Buffer, Package, &LineNumber);
+ }
+ }
+
+ StripParens (Buffer);
+
+ if (Buffer[0] == '$') {
+ Index = ProcessEnvironmentVariable (&Buffer[0], ToolName);
+ //
+ // if there is string after the environment variable, cat it.
+ //
+ if ((UINT32) Index < strlen (Buffer)) {
+ strcat (ToolName, &Buffer[Index]);
+ }
+ } else {
+ strcpy (ToolName, Buffer);
+ }
+
+ ToolArgumentsArray[0] = ToolName;
+
+ //
+ // read ARGS
+ //
+ if (GetToolArguments (
+ ToolArgumentsArray,
+ Package,
+ &InputFileName,
+ &OutputFileName,
+ &SignGuid,
+ &GuidedSectionAttributes
+ ) == -1) {
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // if the tool need input file,
+ // dump the file buffer to the specified input file.
+ //
+ if (InputFileName != NULL) {
+ InputFile = fopen (InputFileName, "wb");
+ if (InputFile == NULL) {
+ Error (NULL, 0, 0, InputFileName, "failed to open output file for writing");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ fwrite (FileBuffer, sizeof (UINT8), Size, InputFile);
+ fclose (InputFile);
+ InputFile = NULL;
+ free (InputFileName);
+ InputFileName = NULL;
+ }
+ //
+ // dispatch signing tool
+ //
+#ifdef __GNUC__
+ {
+ char CommandLine[1000];
+ sprintf(CommandLine, "%s %s", ToolName, ToolArgumentsArray);
+ returnint = system(CommandLine);
+ }
+#else
+ returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray);
+#endif
+ if (returnint != 0) {
+ Error (NULL, 0, 0, ToolName, "external tool failed");
+ IsError = TRUE;
+ goto Done;
+ }
+ //
+ // if the tool has output file,
+ // dump the output file to the file buffer
+ //
+ if (OutputFileName != NULL) {
+
+ OutputFile = fopen (OutputFileName, "rb");
+ if (OutputFile == NULL) {
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ TargetFileBuffer = &FileBuffer[Size];
+ SourceDataSize = Size;
+
+ fread (&Temp, sizeof (UINT8), 1, OutputFile);
+ while (!feof (OutputFile)) {
+ FileBuffer[Size++] = Temp;
+ fread (&Temp, sizeof (UINT8), 1, OutputFile);
+ }
+
+ while ((Size & 0x03) != 0) {
+ FileBuffer[Size] = 0;
+ Size++;
+ }
+
+ SourceDataSize = Size - SourceDataSize;
+
+ fclose (OutputFile);
+ OutputFile = NULL;
+ free (OutputFileName);
+ OutputFileName = NULL;
+
+ if (CompareGuid (&SignGuid, &mZeroGuid) != 0) {
+ ReturnValue = SourceDataSize;
+ Status = GenSimpleGuidSection (
+ TargetFileBuffer,
+ &ReturnValue,
+ SourceDataSize,
+ SignGuid,
+ GuidedSectionAttributes
+ );
+ if (EFI_ERROR (Status)) {
+ IsError = TRUE;
+ goto Done;
+ }
+
+ Size = ReturnValue;
+ }
+ }
+
+ } else if (Buffer[0] != '}') {
+ //
+ // if we are here, we should see either a file name,
+ // or a }.
+ //
+ Index3 = 0;
+ FileName[0] = 0;
+ //
+ // Prepend the build directory to the file name if the
+ // file name does not already contain a full path.
+ //
+ if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) {
+ sprintf (FileName, "%s\\", BuildDirectory);
+ }
+
+ while (Buffer[Index3] != '\n') {
+ if (Buffer[Index3] == '$') {
+ Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer);
+ strcat (FileName, NewBuffer);
+ }
+
+ if (Buffer[Index3] == 0) {
+ break;
+ } else {
+ Index2 = strlen (FileName);
+ FileName[Index2++] = Buffer[Index3++];
+ FileName[Index2] = 0;
+ }
+ }
+
+ InFile = fopen (FileName, "rb");
+ if (InFile == NULL) {
+ Error (NULL, 0, 0, FileName, "failed to open file for reading");
+ IsError = TRUE;
+ goto Done;
+ }
+
+ fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
+ while (!feof (InFile)) {
+ FileBuffer[Size++] = ByteBuffer;
+ fread (&ByteBuffer, sizeof (UINT8), 1, InFile);
+ }
+
+ fclose (InFile);
+ InFile = NULL;
+
+ //
+ // Make sure section ends on a DWORD boundary
+ //
+ while ((Size & 0x03) != 0) {
+ FileBuffer[Size] = 0;
+ Size++;
+ }
+
+ }
+ }
+
+Done:
+ for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) {
+ if (ToolArgumentsArray[Index3] == NULL) {
+ break;
+ }
+
+ free (ToolArgumentsArray[Index3]);
+ }
+
+ if (IsError) {
+ return -1;
+ }
+
+ return Size;
+
+}
+
+static
+UINT8
+StringToType (
+ IN CHAR8 *String
+ )
+/*++
+
+Routine Description:
+
+ Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
+ unrecognized file type was specified.
+
+Arguments:
+
+ String - File type string
+
+Returns:
+
+ File Type Value
+
+--*/
+{
+ if (strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) {
+ return EFI_FV_FILETYPE_RAW;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) {
+ return EFI_FV_FILETYPE_FREEFORM;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
+ return EFI_FV_FILETYPE_SECURITY_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
+ return EFI_FV_FILETYPE_PEI_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
+ return EFI_FV_FILETYPE_DXE_CORE;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) {
+ return EFI_FV_FILETYPE_PEIM;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) {
+ return EFI_FV_FILETYPE_DRIVER;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
+ return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) {
+ return EFI_FV_FILETYPE_APPLICATION;
+ }
+
+ if (strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
+ return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE;
+ }
+
+ return EFI_FV_FILETYPE_ALL;
+}
+
+static
+UINT32
+AdjustFileSize (
+ IN UINT8 *FileBuffer,
+ IN UINT32 FileSize
+ )
+/*++
+
+Routine Description:
+ Adjusts file size to insure sectioned file is exactly the right length such
+ that it ends on exactly the last byte of the last section. ProcessScript()
+ may have padded beyond the end of the last section out to a 4 byte boundary.
+ This padding is stripped.
+
+Arguments:
+ FileBuffer - Data Buffer - contains a section stream
+ FileSize - Size of FileBuffer as returned from ProcessScript()
+
+Returns:
+ Corrected size of file.
+
+--*/
+{
+ UINT32 TotalLength;
+ UINT32 CurrentLength;
+ UINT32 SectionLength;
+ UINT32 SectionStreamLength;
+ EFI_COMMON_SECTION_HEADER *SectionHeader;
+ EFI_COMMON_SECTION_HEADER *NextSectionHeader;
+
+ TotalLength = 0;
+ CurrentLength = 0;
+ SectionStreamLength = FileSize;
+
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileBuffer;
+
+ while (TotalLength < SectionStreamLength) {
+ SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff;
+ TotalLength += SectionLength;
+
+ if (TotalLength == SectionStreamLength) {
+ return TotalLength;
+ }
+ //
+ // Move to the next byte following the section...
+ //
+ SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength);
+ CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer;
+
+ //
+ // Figure out where the next section begins
+ //
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3);
+ NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3);
+ TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader;
+ SectionHeader = NextSectionHeader;
+ }
+
+ return CurrentLength;
+}
+
+static
+INT32
+MainEntry (
+ INT32 argc,
+ CHAR8 *argv[],
+ BOOLEAN ForceUncompress
+ )
+/*++
+
+Routine Description:
+
+ MainEntry function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to command line parameter strings.
+ ForceUncompress - If TRUE, force to do not compress the sections even if compression
+ is specified in the script. Otherwise, FALSE.
+
+Returns:
+ STATUS_SUCCESS - Function exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ FILE *PrimaryPackage;
+ FILE *OverridePackage;
+ FILE *Out;
+ CHAR8 BaseName[_MAX_PATH];
+ EFI_GUID FfsGuid;
+ CHAR8 GuidString[_MAX_PATH];
+ EFI_FFS_FILE_HEADER FileHeader;
+ CHAR8 FileType[_MAX_PATH];
+ EFI_FFS_FILE_ATTRIBUTES FfsAttrib;
+ EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined;
+ UINT64 FfsAlignment;
+ UINT32 FfsAlignment32;
+ CHAR8 InputString[_MAX_PATH];
+ BOOLEAN ImageScriptInOveride;
+ UINT32 FileSize;
+ UINT8 *FileBuffer;
+ EFI_STATUS Status;
+ UINT32 LineNumber;
+ EFI_FFS_FILE_TAIL TailValue;
+
+ BaseName[0] = 0;
+ FileType[0] = 0;
+ FfsAttrib = 0;
+ FfsAttribDefined = 0;
+ FfsAlignment = 0;
+ FfsAlignment32 = 0;
+ PrimaryPackage = NULL;
+ Out = NULL;
+ OverridePackage = NULL;
+ FileBuffer = NULL;
+
+ strcpy (GuidString, "00000000-0000-0000-0000-000000000000");
+ Status = StringToGuid (GuidString, &FfsGuid);
+ if (Status != 0) {
+ Error (NULL, 0, 0, GuidString, "error parsing GUID string");
+ return STATUS_ERROR;
+ }
+
+ GuidString[0] = 0;
+ ImageScriptInOveride = FALSE;
+ //
+ // Initialize the simple file parsing routines. Then open
+ // the primary package file for parsing.
+ //
+ SFPInit ();
+ if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) {
+ Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
+ goto Done;
+ }
+ //
+ // First token in the file must be "PACKAGE.INF"
+ //
+ if (!SFPIsToken ("PACKAGE.INF")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL);
+ goto Done;
+ }
+ //
+ // Find the [.] section
+ //
+ if (!SFPSkipToToken ("[.]")) {
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL);
+ goto Done;
+ }
+ //
+ // Start parsing the data. The algorithm is essentially the same for each keyword:
+ // 1. Identify the keyword
+ // 2. Verify that the keyword/value pair has not already been defined
+ // 3. Set some flag indicating that the keyword/value pair has been defined
+ // 4. Skip over the "="
+ // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
+ //
+ while (1) {
+ if (SFPIsToken ("BASE_NAME")) {
+ //
+ // Found BASE_NAME, format:
+ // BASE_NAME = MyBaseName
+ //
+ if (BaseName[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNextToken (BaseName, sizeof (BaseName))) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("IMAGE_SCRIPT")) {
+ //
+ // Found IMAGE_SCRIPT. Break out and process below.
+ //
+ break;
+ } else if (SFPIsToken ("FFS_FILEGUID")) {
+ //
+ // found FILEGUID, format:
+ // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
+ //
+ if (GuidString[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL);
+ goto Done;
+ }
+
+ Status = StringToGuid (GuidString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_FILETYPE")) {
+ //
+ // ***********************************************************************
+ //
+ // Found FFS_FILETYPE, format:
+ // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
+ //
+ if (FileType[0] != 0) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL);
+ goto Done;
+ }
+
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNextToken (FileType, sizeof (FileType))) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
+ // Spec says the bit is for future expansion, and must be false.
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "FFS_ATTRIB_HEADER_EXTENSION previously defined",
+ NULL
+ );
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
+ NULL
+ );
+ goto Done;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_RECOVERY;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_CHECKSUM;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
+ //
+ // ***********************************************************************
+ //
+ // Found FFS_ALIGNMENT, formats:
+ // FFS_ALIGNMENT = 0-7
+ // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ SFPGetLineNumber (),
+ 0,
+ "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
+ NULL
+ );
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (!SFPGetNumber (&FfsAlignment32)) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL);
+ goto Done;
+ }
+
+ if (FfsAlignment32 > 7) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL);
+ goto Done;
+ }
+
+ FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3);
+ } else {
+ SFPGetNextToken (InputString, sizeof (InputString));
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token");
+ goto Done;
+ }
+ }
+ //
+ // Close the primary package file
+ //
+ SFPCloseFile ();
+ //
+ // TODO: replace code below with basically a copy of the code above. Don't
+ // forget to reset the FfsAttribDefined variable first. Also, you'll need
+ // to somehow keep track of whether or not the basename is defined multiple
+ // times in the override package. Ditto on the file GUID.
+ //
+ if (mGlobals.OverridePackagePath[0] != 0) {
+ OverridePackage = fopen (mGlobals.OverridePackagePath, "r");
+ //
+ // NOTE: For package override to work correctly, the code below must be modified to
+ // SET or CLEAR bits properly. For example, if the primary package set
+ // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
+ // we'd need to clear the bit below. Since this is not happening, I'm guessing that
+ // the override functionality is not being used, so should be made obsolete. If I'm
+ // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
+ // used, and we'll address it then. 4/10/2003
+ //
+ Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL);
+ goto Done;
+ } else {
+ OverridePackage = NULL;
+ }
+
+#ifdef OVERRIDE_SUPPORTED
+ if (OverridePackage != NULL) {
+ //
+ // Parse override package file
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ if (strcmpi (InputString, "PACKAGE.INF") != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
+ goto Done;
+ }
+ //
+ // Match [dir] to Build Directory
+ //
+ if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file");
+ goto Done;
+ }
+
+ InputString[0] = 0;
+ while ((InputString[0] != '[') && (!feof (OverridePackage))) {
+ if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) {
+ if (InputString[0] != '[') {
+here:
+ if (strcmpi (InputString, "BASE_NAME") == 0) {
+ //
+ // found BASE_NAME, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ strcpy (BaseName, InputString);
+ } else {
+ BreakString (InputString, InputString, 1);
+ strcpy (BaseName, InputString);
+ }
+ } else if (strcmpi (InputString, "IMAGE_SCRIPT") == 0) {
+ //
+ // found IMAGE_SCRIPT, come back later to process it
+ //
+ ImageScriptInOveride = TRUE;
+ fscanf (OverridePackage, "%s", &InputString);
+ } else if (strcmpi (InputString, "FFS_FILEGUID") == 0) {
+ //
+ // found FILEGUID, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ Status = StringToGuid (InputString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
+ goto Done;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ Status = StringToGuid (InputString, &FfsGuid);
+ if (Status != 0) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format");
+ goto Done;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_FILETYPE") == 0) {
+ //
+ // found FILETYPE, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ strcpy (FileType, InputString);
+ } else {
+ BreakString (InputString, InputString, 1);
+ strcpy (FileType, InputString);
+ }
+
+ } else if (strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) {
+ //
+ // found FFS_ATTRIB_RECOVERY, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_RECOVERY;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) {
+ //
+ // found FFS_ATTRIB_CHECKSUM, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ }
+ } else {
+ BreakString (InputString, InputString, 1);
+ if (strcmpi (InputString, "TRUE") == 0) {
+ FfsAttrib |= FFS_ATTRIB_CHECKSUM;
+ }
+ }
+ } else if (strcmpi (InputString, "FFS_ALIGNMENT") == 0) {
+ //
+ // found FFS_ALIGNMENT, next is = and string.
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strlen (InputString) == 1) {
+ //
+ // string is just =
+ //
+ fscanf (OverridePackage, "%s", &InputString);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ } else {
+ BreakString (InputString, InputString, 1);
+ }
+
+ AsciiStringToUint64 (InputString, FALSE, &FfsAlignment);
+ if (FfsAlignment > 7) {
+ Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value");
+ goto Done;
+ }
+
+ FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3);
+ } else if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, String, 1);
+ fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR);
+ BreakString (InputString, InputString, 0);
+ goto here;
+ }
+ }
+ }
+ }
+ }
+#endif // #ifdef OVERRIDE_SUPPORTED
+ //
+ // Require that they specified a file GUID at least, since that's how we're
+ // naming the file.
+ //
+ if (GuidString[0] == 0) {
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Build Header and process image script
+ //
+ FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8));
+ if (FileBuffer == NULL) {
+ Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL);
+ goto Done;
+ }
+
+ FileSize = 0;
+ if (ImageScriptInOveride) {
+#ifdef OVERRIDE_SUPORTED
+ rewind (OverridePackage);
+ LineNumber = 0;
+ FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber);
+ while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
+ GetNextLine (InputString, OverridePackage, &LineNumber);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, InputString, 0);
+ }
+ }
+
+ while (InputString[0] != '{') {
+ GetNextLine (InputString, OverridePackage, &LineNumber);
+ CheckSlash (InputString, OverridePackage, &LineNumber);
+ }
+ //
+ // Found start of image script, process it
+ //
+ FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress);
+ if (FileSize == -1) {
+ return -1;
+ }
+
+ if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
+ FileSize = AdjustFileSize (FileBuffer, FileSize);
+ }
+
+ if (BaseName[0] == '\"') {
+ StripQuotes (BaseName);
+ }
+
+ if (BaseName[0] != 0) {
+ sprintf (InputString, "%s-%s", GuidString, BaseName);
+ } else {
+ strcpy (InputString, GuidString);
+ }
+
+ switch (StringToType (FileType)) {
+
+ case EFI_FV_FILETYPE_SECURITY_CORE:
+ strcat (InputString, ".SEC");
+ break;
+
+ case EFI_FV_FILETYPE_PEIM:
+ case EFI_FV_FILETYPE_PEI_CORE:
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
+ strcat (InputString, ".PEI");
+ break;
+
+ case EFI_FV_FILETYPE_DRIVER:
+ case EFI_FV_FILETYPE_DXE_CORE:
+ strcat (InputString, ".DXE");
+ break;
+
+ case EFI_FV_FILETYPE_APPLICATION:
+ strcat (InputString, ".APP");
+ break;
+
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
+ strcat (InputString, ".FVI");
+ break;
+
+ case EFI_FV_FILETYPE_ALL:
+ Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
+ goto Done;
+
+ default:
+ strcat (InputString, ".FFS");
+ break;
+ }
+
+ if (ForceUncompress) {
+ strcat (InputString, ".ORG");
+ }
+
+ Out = fopen (InputString, "wb");
+ if (Out == NULL) {
+ Error (NULL, 0, 0, InputString, "could not open output file for writing");
+ goto Done;
+ }
+ //
+ // create ffs header
+ //
+ memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
+ FileHeader.Type = StringToType (FileType);
+ FileHeader.Attributes = FfsAttrib;
+ //
+ // Now FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileSize += sizeof (EFI_FFS_FILE_HEADER);
+ FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
+ FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
+ FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
+ //
+ // Fill in checksums and state, these must be zero for checksumming
+ //
+ // FileHeader.IntegrityCheck.Checksum.Header = 0;
+ // FileHeader.IntegrityCheck.Checksum.File = 0;
+ // FileHeader.State = 0;
+ //
+ FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
+ (UINT8 *) &FileHeader,
+ sizeof (EFI_FFS_FILE_HEADER)
+ );
+ if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize);
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+
+ FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ //
+ // write header
+ //
+ if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file header to output file", NULL);
+ goto Done;
+ }
+ //
+ // write data
+ //
+ if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write all bytes to output file", NULL);
+ goto Done;
+ }
+
+ fclose (Out);
+ Out = NULL;
+#endif // #ifdef OVERRIDE_SUPPORTED
+ } else {
+ //
+ // Open primary package file and process the IMAGE_SCRIPT section
+ //
+ PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r");
+ if (PrimaryPackage == NULL) {
+ Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file");
+ goto Done;
+ }
+
+ LineNumber = 1;
+ FindSectionInPackage (".", PrimaryPackage, &LineNumber);
+ while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) {
+ GetNextLine (InputString, PrimaryPackage, &LineNumber);
+ CheckSlash (InputString, PrimaryPackage, &LineNumber);
+ if (strchr (InputString, '=') != NULL) {
+ BreakString (InputString, InputString, 0);
+ }
+ }
+
+ while (InputString[0] != '{') {
+ GetNextLine (InputString, PrimaryPackage, &LineNumber);
+ CheckSlash (InputString, PrimaryPackage, &LineNumber);
+ }
+ //
+ // Found start of image script, process it
+ //
+ FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress);
+ if (FileSize == -1) {
+ goto Done;
+ }
+
+ if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) {
+ FileSize = AdjustFileSize (FileBuffer, FileSize);
+ }
+
+ if (BaseName[0] == '\"') {
+ StripQuotes (BaseName);
+ }
+
+ if (BaseName[0] != 0) {
+ sprintf (InputString, "%s-%s", GuidString, BaseName);
+ } else {
+ strcpy (InputString, GuidString);
+ }
+
+ switch (StringToType (FileType)) {
+
+ case EFI_FV_FILETYPE_SECURITY_CORE:
+ strcat (InputString, ".SEC");
+ break;
+
+ case EFI_FV_FILETYPE_PEIM:
+ case EFI_FV_FILETYPE_PEI_CORE:
+ case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
+ strcat (InputString, ".PEI");
+ break;
+
+ case EFI_FV_FILETYPE_DRIVER:
+ case EFI_FV_FILETYPE_DXE_CORE:
+ strcat (InputString, ".DXE");
+ break;
+
+ case EFI_FV_FILETYPE_APPLICATION:
+ strcat (InputString, ".APP");
+ break;
+
+ case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
+ strcat (InputString, ".FVI");
+ break;
+
+ case EFI_FV_FILETYPE_ALL:
+ Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL);
+ goto Done;
+
+ default:
+ strcat (InputString, ".FFS");
+ break;
+ }
+
+ if (ForceUncompress) {
+ strcat (InputString, ".ORG");
+ }
+
+ Out = fopen (InputString, "wb");
+ if (Out == NULL) {
+ Error (NULL, 0, 0, InputString, "failed to open output file for writing");
+ goto Done;
+ }
+ //
+ // Initialize the FFS file header
+ //
+ memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID));
+ FileHeader.Type = StringToType (FileType);
+ FileHeader.Attributes = FfsAttrib;
+ //
+ // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
+ //
+ FileSize += sizeof (EFI_FFS_FILE_HEADER);
+ //
+ // If using a tail, then it adds two bytes
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ //
+ // Tail is not allowed for pad and 0-length files
+ //
+ if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) {
+ Error (
+ mGlobals.PrimaryPackagePath,
+ 1,
+ 0,
+ "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
+ NULL
+ );
+ goto Done;
+ }
+
+ FileSize += sizeof (EFI_FFS_FILE_TAIL);
+ }
+
+ FileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
+ FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
+ FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
+ //
+ // Fill in checksums and state, they must be 0 for checksumming.
+ //
+ // FileHeader.IntegrityCheck.Checksum.Header = 0;
+ // FileHeader.IntegrityCheck.Checksum.File = 0;
+ // FileHeader.State = 0;
+ //
+ FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
+ (UINT8 *) &FileHeader,
+ sizeof (EFI_FFS_FILE_HEADER)
+ );
+ if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
+ //
+ // Cheating here. Since the header checksums, just calculate the checksum of the body.
+ // Checksum does not include the tail
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ FileBuffer,
+ FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL)
+ );
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
+ FileBuffer,
+ FileSize - sizeof (EFI_FFS_FILE_HEADER)
+ );
+ }
+ } else {
+ FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
+ }
+ //
+ // Set the state now. Spec says the checksum assumes the state is 0
+ //
+ FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+ //
+ // If there is a tail, then set it
+ //
+ if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) {
+ TailValue = FileHeader.IntegrityCheck.TailReference;
+ TailValue = (UINT16) (~TailValue);
+ memcpy (
+ (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL),
+ &TailValue,
+ sizeof (TailValue)
+ );
+ }
+ //
+ // Write the FFS file header
+ //
+ if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file header contents", NULL);
+ goto Done;
+ }
+ //
+ // Write data
+ //
+ if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) {
+ Error (NULL, 0, 0, "failed to write file contents", NULL);
+ goto Done;
+ }
+ }
+
+Done:
+ SFPCloseFile ();
+ if (Out != NULL) {
+ fclose (Out);
+ }
+
+ if (PrimaryPackage != NULL) {
+ fclose (PrimaryPackage);
+ }
+
+ if (FileBuffer != NULL) {
+ free (FileBuffer);
+ }
+
+ if (OverridePackage != NULL) {
+ fclose (OverridePackage);
+ }
+
+ return GetUtilityStatus ();
+}
+
+int
+main (
+ INT32 argc,
+ CHAR8 *argv[]
+ )
+/*++
+
+Routine Description:
+
+ Main function.
+
+Arguments:
+
+ argc - Number of command line parameters.
+ argv - Array of pointers to parameter strings.
+
+Returns:
+ STATUS_SUCCESS - Utility exits successfully.
+ STATUS_ERROR - Some error occurred during execution.
+
+--*/
+{
+ STATUS Status;
+ //
+ // Set the name of our utility for error reporting purposes.
+ //
+ SetUtilityName (UTILITY_NAME);
+ Status = ProcessCommandLineArgs (argc, argv);
+ if (Status != STATUS_SUCCESS) {
+ return Status;
+ }
+
+ Status = MainEntry (argc, argv, TRUE);
+ if (Status == STATUS_SUCCESS) {
+ MainEntry (argc, argv, FALSE);
+ }
+ //
+ // If any errors were reported via the standard error reporting
+ // routines, then the status has been saved. Get the value and
+ // return it to the caller.
+ //
+ return GetUtilityStatus ();
+}
+
+static
+STATUS
+ProcessCommandLineArgs (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+ Process the command line arguments.
+
+Arguments:
+ Argc - as passed in to main()
+ Argv - as passed in to main()
+
+Returns:
+ STATUS_SUCCESS - arguments all ok
+ STATUS_ERROR - problem with args, so caller should exit
+
+--*/
+{
+ //
+ // If no args, then print usage instructions and return an error
+ //
+ if (Argc == 1) {
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+
+ memset (&mGlobals, 0, sizeof (mGlobals));
+ Argc--;
+ Argv++;
+ while (Argc > 0) {
+ if (strcmpi (Argv[0], "-b") == 0) {
+ //
+ // OPTION: -b BuildDirectory
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, "-b option requires the build directory name", NULL);
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.BuildDirectory[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.BuildDirectory, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-p1") == 0) {
+ //
+ // OPTION: -p1 PrimaryPackageFile
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "option requires the primary package file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.PrimaryPackagePath[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.PrimaryPackagePath, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-p2") == 0) {
+ //
+ // OPTION: -p2 OverridePackageFile
+ // Make sure there is another argument, then save it to our globals.
+ //
+ if (Argc < 2) {
+ Error (NULL, 0, 0, Argv[0], "option requires the override package file name");
+ return STATUS_ERROR;
+ }
+
+ if (mGlobals.OverridePackagePath[0]) {
+ Error (NULL, 0, 0, Argv[0], "option can only be specified once");
+ return STATUS_ERROR;
+ }
+
+ strcpy (mGlobals.OverridePackagePath, Argv[1]);
+ Argc--;
+ Argv++;
+ } else if (strcmpi (Argv[0], "-v") == 0) {
+ //
+ // OPTION: -v verbose
+ //
+ mGlobals.Verbose = TRUE;
+ } else if (strcmpi (Argv[0], "-h") == 0) {
+ //
+ // OPTION: -h help
+ //
+ PrintUsage ();
+ return STATUS_ERROR;
+ } else if (strcmpi (Argv[0], "-?") == 0) {
+ //
+ // OPTION: -? help
+ //
+ PrintUsage ();
+ return STATUS_ERROR;
+ } else {
+ Error (NULL, 0, 0, Argv[0], "unrecognized option");
+ PrintUsage ();
+ return STATUS_ERROR;
+ }
+
+ Argv++;
+ Argc--;
+ }
+ //
+ // Must have at least specified the package file name
+ //
+ if (mGlobals.PrimaryPackagePath[0] == 0) {
+ Error (NULL, 0, 0, "must specify primary package file", NULL);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/Source/GenFfsFile/GenFfsFile.h b/Source/GenFfsFile/GenFfsFile.h
new file mode 100644
index 0000000..f5bc718
--- /dev/null
+++ b/Source/GenFfsFile/GenFfsFile.h
@@ -0,0 +1,36 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ GenFfsFile.h
+
+Abstract:
+
+ Header file for GenFfsFile.
+
+--*/
+
+//
+// Module Coded to Tiano Coding Conventions
+//
+#ifndef _EFI_GEN_FFSFILE_H
+#define _EFI_GEN_FFSFILE_H
+
+//
+// External Files Referenced
+//
+#include <Common/UefiBaseTypes.h>
+#include <Common/FirmwareVolumeImageFormat.h>
+
+#include "MyAlloc.h"
+
+#endif
diff --git a/Source/GenFfsFile/SimpleFileParsing.c b/Source/GenFfsFile/SimpleFileParsing.c
new file mode 100644
index 0000000..5fa5a22
--- /dev/null
+++ b/Source/GenFfsFile/SimpleFileParsing.c
@@ -0,0 +1,969 @@
+/*++
+
+Copyright (c) 2004, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ SimpleFileParsing.c
+
+Abstract:
+
+ Generic but simple file parsing routines.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <Common/UefiBaseTypes.h>
+
+#include "EfiUtilityMsgs.h"
+#include "SimpleFileParsing.h"
+
+#define MAX_PATH 255
+#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop.
+#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars
+#define MAX_LINE_LEN 400
+
+#define T_CHAR_SPACE ' '
+#define T_CHAR_NULL 0
+#define T_CHAR_CR '\r'
+#define T_CHAR_TAB '\t'
+#define T_CHAR_LF '\n'
+#define T_CHAR_SLASH '/'
+#define T_CHAR_BACKSLASH '\\'
+#define T_CHAR_DOUBLE_QUOTE '"'
+#define T_CHAR_LC_X 'x'
+#define T_CHAR_0 '0'
+
+//
+// We keep a linked list of these for the source files we process
+//
+typedef struct _SOURCE_FILE {
+ FILE *Fptr;
+ T_CHAR *FileBuffer;
+ T_CHAR *FileBufferPtr;
+ UINT32 FileSize;
+ INT8 FileName[MAX_PATH];
+ UINT32 LineNum;
+ BOOLEAN EndOfFile;
+ BOOLEAN SkipToHash;
+ struct _SOURCE_FILE *Previous;
+ struct _SOURCE_FILE *Next;
+ T_CHAR ControlCharacter;
+} SOURCE_FILE;
+
+//
+// Here's all our module globals.
+//
+static struct {
+ SOURCE_FILE SourceFile;
+ BOOLEAN Verbose;
+} mGlobals;
+
+static
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ );
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ );
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ );
+
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ );
+
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+//
+// static
+// T_CHAR *
+// GetQuotedString (
+// SOURCE_FILE *SourceFile,
+// BOOLEAN Optional
+// );
+//
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ );
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ );
+
+static
+STATUS
+ParseFile (
+ SOURCE_FILE *SourceFile
+ );
+
+static
+FILE *
+FindFile (
+ IN INT8 *FileName,
+ OUT INT8 *FoundFileName,
+ IN UINT32 FoundFileNameLen
+ );
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ );
+
+STATUS
+SFPInit (
+ VOID
+ )
+{
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));
+ return STATUS_SUCCESS;
+}
+
+UINT32
+SFPGetLineNumber (
+ VOID
+ )
+{
+ return mGlobals.SourceFile.LineNum;
+}
+
+/*++
+
+Routine Description:
+ Return the line number of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ The line number, or 0 if no file is being processed
+
+--*/
+T_CHAR *
+SFPGetFileName (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Return the name of the file we're parsing. Used
+ for error reporting purposes.
+
+Arguments:
+ None.
+
+Returns:
+ A pointer to the file name. Null if no file is being
+ processed.
+
+--*/
+{
+ if (mGlobals.SourceFile.FileName[0]) {
+ return mGlobals.SourceFile.FileName;
+ }
+
+ return NULL;
+}
+
+STATUS
+SFPOpenFile (
+ IN INT8 *FileName
+ )
+/*++
+
+Routine Description:
+ Open a file for parsing.
+
+Arguments:
+ FileName - name of the file to parse
+
+Returns:
+
+
+--*/
+{
+ STATUS Status;
+ t_strcpy (mGlobals.SourceFile.FileName, FileName);
+ Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL);
+ return Status;
+}
+
+BOOLEAN
+SFPIsToken (
+ T_CHAR *Str
+ )
+/*++
+
+Routine Description:
+ Check to see if the specified token is found at
+ the current position in the input file.
+
+Arguments:
+ Str - the token to look for
+
+Returns:
+ TRUE - the token is next
+ FALSE - the token is not next
+
+Notes:
+ We do a simple string comparison on this function. It is
+ the responsibility of the caller to ensure that the token
+ is not a subset of some other token.
+
+ The file pointer is advanced past the token in the input file.
+
+--*/
+{
+ UINT32 Len;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+
+ if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ return FALSE;
+
+}
+
+BOOLEAN
+SFPGetNextToken (
+ T_CHAR *Str,
+ UINT32 Len
+ )
+{
+ UINT32 Index;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ Index = 0;
+ while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) {
+ if (IsWhiteSpace (&mGlobals.SourceFile)) {
+ if (Index > 0) {
+ Str[Index] = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+ } else {
+ Str[Index] = mGlobals.SourceFile.FileBufferPtr[0];
+ mGlobals.SourceFile.FileBufferPtr++;
+ Index++;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+SFPSkipToToken (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ T_CHAR *SavePos;
+ Len = t_strlen (Str);
+ SavePos = mGlobals.SourceFile.FileBufferPtr;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ while (!EndOfFile (&mGlobals.SourceFile)) {
+ if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) {
+ mGlobals.SourceFile.FileBufferPtr += Len;
+ return TRUE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr++;
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ }
+
+ mGlobals.SourceFile.FileBufferPtr = SavePos;
+ return FALSE;
+}
+
+BOOLEAN
+SFPGetNumber (
+ UINT32 *Value
+ )
+/*++
+
+Routine Description:
+ Check the token at the current file position for a numeric value.
+ May be either decimal or hex.
+
+Arguments:
+ Value - pointer where to store the value
+
+Returns:
+ FALSE - current token is not a number
+ TRUE - current token is a number
+
+--*/
+{
+ //
+ // UINT32 Len;
+ //
+ SkipWhiteSpace (&mGlobals.SourceFile);
+ if (EndOfFile (&mGlobals.SourceFile)) {
+ return FALSE;
+ }
+
+ if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ //
+ // Check for hex value
+ //
+ if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) {
+ if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) {
+ return FALSE;
+ }
+
+ mGlobals.SourceFile.FileBufferPtr += 2;
+ sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value);
+ while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ } else {
+ *Value = atoi (mGlobals.SourceFile.FileBufferPtr);
+ while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) {
+ mGlobals.SourceFile.FileBufferPtr++;
+ }
+
+ return TRUE;
+ }
+ } else {
+ return FALSE;
+ }
+}
+
+STATUS
+SFPCloseFile (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Close the file being parsed.
+
+Arguments:
+ None.
+
+Returns:
+ STATUS_SUCCESS - the file was closed
+ STATUS_ERROR - no file is currently open
+
+--*/
+{
+ if (mGlobals.SourceFile.FileBuffer != NULL) {
+ free (mGlobals.SourceFile.FileBuffer);
+ memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile));
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_ERROR;
+}
+
+static
+STATUS
+ProcessIncludeFile (
+ SOURCE_FILE *SourceFile,
+ SOURCE_FILE *ParentSourceFile
+ )
+/*++
+
+Routine Description:
+
+ Given a source file, open the file and parse it
+
+Arguments:
+
+ SourceFile - name of file to parse
+ ParentSourceFile - for error reporting purposes, the file that #included SourceFile.
+
+Returns:
+
+ Standard status.
+
+--*/
+{
+ static UINT32 NestDepth = 0;
+ INT8 FoundFileName[MAX_PATH];
+ STATUS Status;
+
+ Status = STATUS_SUCCESS;
+ NestDepth++;
+ //
+ // Print the file being processed. Indent so you can tell the include nesting
+ // depth.
+ //
+ if (mGlobals.Verbose) {
+ fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName);
+ }
+
+ //
+ // Make sure we didn't exceed our maximum nesting depth
+ //
+ if (NestDepth > MAX_NEST_DEPTH) {
+ Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth);
+ Status = STATUS_ERROR;
+ goto Finish;
+ }
+ //
+ // Try to open the file locally, and if that fails try along our include paths.
+ //
+ strcpy (FoundFileName, SourceFile->FileName);
+ if ((SourceFile->Fptr = fopen (FoundFileName, "r")) == NULL) {
+ //
+ // Try to find it among the paths if it has a parent (that is, it is included
+ // by someone else).
+ //
+ Error (NULL, 0, 0, SourceFile->FileName, "file not found");
+ return STATUS_ERROR;
+ }
+ //
+ // Process the file found
+ //
+ ProcessFile (SourceFile);
+Finish:
+ //
+ // Close open files and return status
+ //
+ if (SourceFile->Fptr != NULL) {
+ fclose (SourceFile->Fptr);
+ SourceFile->Fptr = NULL;
+ }
+
+ return Status;
+}
+
+static
+STATUS
+ProcessFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // Get the file size, and then read the entire thing into memory.
+ // Allocate space for a terminator character.
+ //
+ fseek (SourceFile->Fptr, 0, SEEK_END);
+ SourceFile->FileSize = ftell (SourceFile->Fptr);
+ fseek (SourceFile->Fptr, 0, SEEK_SET);
+ SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR));
+ if (SourceFile->FileBuffer == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr);
+ SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL;
+ //
+ // Pre-process the file to replace comments with spaces
+ //
+ PreprocessFile (SourceFile);
+ SourceFile->LineNum = 1;
+ return STATUS_SUCCESS;
+}
+
+static
+void
+PreprocessFile (
+ SOURCE_FILE *SourceFile
+ )
+/*++
+
+Routine Description:
+ Preprocess a file to replace all carriage returns with NULLs so
+ we can print lines from the file to the screen.
+
+Arguments:
+ SourceFile - structure that we use to keep track of an input file.
+
+Returns:
+ Nothing.
+
+--*/
+{
+ BOOLEAN InComment;
+
+ RewindFile (SourceFile);
+ InComment = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ //
+ // If a line-feed, then no longer in a comment
+ //
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ InComment = 0;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ //
+ // Replace all carriage returns with a NULL so we can print stuff
+ //
+ SourceFile->FileBufferPtr[0] = 0;
+ SourceFile->FileBufferPtr++;
+ } else if (InComment) {
+ SourceFile->FileBufferPtr[0] = T_CHAR_SPACE;
+ SourceFile->FileBufferPtr++;
+ } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) {
+ SourceFile->FileBufferPtr += 2;
+ InComment = TRUE;
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ }
+ //
+ // Could check for end-of-file and still in a comment, but
+ // should not be necessary. So just restore the file pointers.
+ //
+ RewindFile (SourceFile);
+}
+
+#if 0
+static
+T_CHAR *
+GetQuotedString (
+ SOURCE_FILE *SourceFile,
+ BOOLEAN Optional
+ )
+{
+ T_CHAR *String;
+ T_CHAR *Start;
+ T_CHAR *Ptr;
+ UINT32 Len;
+ BOOLEAN PreviousBackslash;
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ if (!Optional) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr);
+ }
+
+ return NULL;
+ }
+
+ Len = 0;
+ SourceFile->FileBufferPtr++;
+ Start = Ptr = SourceFile->FileBufferPtr;
+ PreviousBackslash = FALSE;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (!PreviousBackslash)) {
+ break;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start);
+ PreviousBackslash = FALSE;
+ } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) {
+ PreviousBackslash = TRUE;
+ } else {
+ PreviousBackslash = FALSE;
+ }
+
+ SourceFile->FileBufferPtr++;
+ Len++;
+ }
+
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start);
+ } else {
+ SourceFile->FileBufferPtr++;
+ }
+ //
+ // Now allocate memory for the string and save it off
+ //
+ String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR));
+ if (String == NULL) {
+ Error (NULL, 0, 0, "memory allocation failed", NULL);
+ return NULL;
+ }
+ //
+ // Copy the string from the file buffer to the local copy.
+ // We do no reformatting of it whatsoever at this point.
+ //
+ Ptr = String;
+ while (Len > 0) {
+ *Ptr = *Start;
+ Start++;
+ Ptr++;
+ Len--;
+ }
+
+ *Ptr = 0;
+ return String;
+}
+#endif
+static
+BOOLEAN
+EndOfFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ //
+ // The file buffer pointer will typically get updated before the End-of-file flag in the
+ // source file structure, so check it first.
+ //
+ if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) {
+ SourceFile->EndOfFile = TRUE;
+ return TRUE;
+ }
+
+ if (SourceFile->EndOfFile) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#if 0
+static
+void
+ProcessTokenInclude (
+ SOURCE_FILE *SourceFile
+ )
+{
+ INT8 IncludeFileName[MAX_PATH];
+ INT8 *To;
+ UINT32 Len;
+ BOOLEAN ReportedError;
+ SOURCE_FILE IncludedSourceFile;
+
+ ReportedError = FALSE;
+ if (SkipWhiteSpace (SourceFile) == 0) {
+ Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL);
+ }
+ //
+ // Should be quoted file name
+ //
+ if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ SourceFile->FileBufferPtr++;
+ //
+ // Copy the filename as ascii to our local string
+ //
+ To = IncludeFileName;
+ Len = 0;
+ while (!EndOfFile (SourceFile)) {
+ if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL);
+ goto FailDone;
+ }
+
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) {
+ SourceFile->FileBufferPtr++;
+ break;
+ }
+ //
+ // If too long, then report the error once and process until the closing quote
+ //
+ Len++;
+ if (!ReportedError && (Len >= sizeof (IncludeFileName))) {
+ Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL);
+ ReportedError = TRUE;
+ }
+
+ if (!ReportedError) {
+ //
+ // *To = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]);
+ //
+ *To = (T_CHAR) SourceFile->FileBufferPtr[0];
+ To++;
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+
+ if (!ReportedError) {
+ *To = 0;
+ memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE));
+ strcpy (IncludedSourceFile.FileName, IncludeFileName);
+ //
+ // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER;
+ //
+ ProcessIncludeFile (&IncludedSourceFile, SourceFile);
+ //
+ // printf ("including file '%s'\n", IncludeFileName);
+ //
+ }
+
+ return ;
+FailDone:
+ //
+ // Error recovery -- skip to next #
+ //
+ SourceFile->SkipToHash = TRUE;
+}
+#endif
+static
+BOOLEAN
+IsWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ case T_CHAR_LF:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+UINT32
+SkipWhiteSpace (
+ SOURCE_FILE *SourceFile
+ )
+{
+ UINT32 Count;
+
+ Count = 0;
+ while (!EndOfFile (SourceFile)) {
+ Count++;
+ switch (*SourceFile->FileBufferPtr) {
+ case T_CHAR_NULL:
+ case T_CHAR_CR:
+ case T_CHAR_SPACE:
+ case T_CHAR_TAB:
+ SourceFile->FileBufferPtr++;
+ break;
+
+ case T_CHAR_LF:
+ SourceFile->FileBufferPtr++;
+ SourceFile->LineNum++;
+ if (mGlobals.Verbose) {
+ printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr);
+ }
+ break;
+
+ default:
+ return Count - 1;
+ }
+ }
+ //
+ // Some tokens require trailing whitespace. If we're at the end of the
+ // file, then we count that as well.
+ //
+ if ((Count == 0) && (EndOfFile (SourceFile))) {
+ Count++;
+ }
+
+ return Count;
+}
+
+static
+UINT32
+t_strcmp (
+ T_CHAR *Buffer,
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+
+ Len = 0;
+ while (*Str == *Buffer) {
+ Buffer++;
+ Str++;
+ Len++;
+ }
+
+ if (*Str) {
+ return 0;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strlen (
+ T_CHAR *Str
+ )
+{
+ UINT32 Len;
+ Len = 0;
+ while (*Str) {
+ Len++;
+ Str++;
+ }
+
+ return Len;
+}
+
+static
+UINT32
+t_strncmp (
+ T_CHAR *Str1,
+ T_CHAR *Str2,
+ UINT32 Len
+ )
+{
+ while (Len > 0) {
+ if (*Str1 != *Str2) {
+ return Len;
+ }
+
+ Len--;
+ Str1++;
+ Str2++;
+ }
+
+ return 0;
+}
+
+static
+T_CHAR *
+t_strcpy (
+ T_CHAR *Dest,
+ T_CHAR *Src
+ )
+{
+ T_CHAR *SaveDest;
+ SaveDest = Dest;
+ while (*Src) {
+ *Dest = *Src;
+ Dest++;
+ Src++;
+ }
+
+ *Dest = 0;
+ return SaveDest;
+}
+
+#if 0
+static
+BOOLEAN
+IsValidIdentifierChar (
+ INT8 Char,
+ BOOLEAN FirstChar
+ )
+{
+ //
+ // If it's the first character of an identifier, then
+ // it must be one of [A-Za-z_].
+ //
+ if (FirstChar) {
+ if (isalpha (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ } else {
+ //
+ // If it's not the first character, then it can
+ // be one of [A-Za-z_0-9]
+ //
+ if (isalnum (Char) || (Char == '_')) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+#endif
+static
+void
+RewindFile (
+ SOURCE_FILE *SourceFile
+ )
+{
+ SourceFile->LineNum = 1;
+ SourceFile->FileBufferPtr = SourceFile->FileBuffer;
+ SourceFile->EndOfFile = 0;
+}
+
+#if 0
+static
+BOOLEAN
+SkipTo (
+ SOURCE_FILE *SourceFile,
+ T_CHAR TChar,
+ BOOLEAN StopAfterNewline
+ )
+{
+ while (!EndOfFile (SourceFile)) {
+ //
+ // Check for the character of interest
+ //
+ if (SourceFile->FileBufferPtr[0] == TChar) {
+ return TRUE;
+ } else {
+ if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) {
+ SourceFile->LineNum++;
+ if (StopAfterNewline) {
+ SourceFile->FileBufferPtr++;
+ if (SourceFile->FileBufferPtr[0] == 0) {
+ SourceFile->FileBufferPtr++;
+ }
+
+ return FALSE;
+ }
+ }
+
+ SourceFile->FileBufferPtr++;
+ }
+ }
+
+ return FALSE;
+}
+#endif
diff --git a/Source/GenFfsFile/build.xml b/Source/GenFfsFile/build.xml
new file mode 100644
index 0000000..71f8bc9
--- /dev/null
+++ b/Source/GenFfsFile/build.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" ?>
+<!--
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+-->
+<project default="GenTool" basedir=".">
+<!--
+ EDK GenFfsFile Tool
+ Copyright (c) 2006, Intel Corporation
+-->
+ <property name="ToolName" value="GenFfsFile"/>
+ <property name="FileSet" value="GenFfsFile.c"/>
+
+ <taskdef resource="net/sf/antcontrib/antlib.xml"/>
+
+ <property name="LINK_OUTPUT_TYPE" value="static"/>
+ <property name="BUILD_DIR" value="${PACKAGE_DIR}/${ToolName}/tmp"/>
+
+ <target name="GenTool" depends="init, Tool">
+ <echo message="The EDK Tool: ${ToolName} build has completed!"/>
+ </target>
+
+ <target name="init">
+ <echo message="Building the EDK Tool: ${ToolName}"/>
+ <mkdir dir="${BUILD_DIR}"/>
+ </target>
+
+ <target name="Tool" depends="init">
+ <cc name="${ToolChain}" objdir="${BUILD_DIR}"
+ outfile="${BIN_DIR}/${ToolName}"
+ outtype="executable"
+ debug="true"
+ optimize="speed">
+ <compilerarg value="${ExtraArgus}" if="ExtraArgus" />
+
+ <fileset dir="${basedir}/${ToolName}"
+ includes="${FileSet}"
+ defaultexcludes="TRUE"
+ excludes="*.xml *.inf"/>
+
+ <includepath path="${PACKAGE_DIR}/Include"/>
+ <includepath path="${PACKAGE_DIR}/Include/${HostArch}"/>
+ <includepath path="${PACKAGE_DIR}/Common"/>
+ <libset dir="${LIB_DIR}" libs="CommonTools CustomizedCompress"/>
+ </cc>
+ </target>
+
+ <target name="clean">
+ <echo message="Removing Intermediate Files Only"/>
+ <delete>
+ <fileset dir="${BUILD_DIR}" includes="*.obj"/>
+ </delete>
+ </target>
+
+ <target name="cleanall">
+ <echo message="Removing Object Files and the Executable: ${ToolName}${ext_exe}"/>
+ <delete failonerror="false" quiet="true" includeEmptyDirs="true">
+ <fileset dir="${BUILD_DIR}"/>
+ <fileset file="${BIN_DIR}/${ToolName}${ext_exe}"/>
+ <fileset file="${BIN_DIR}/${ToolName}.pdb"/>
+ </delete>
+ </target>
+
+</project>