diff options
author | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 07:00:39 +0000 |
---|---|---|
committer | qwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524> | 2007-06-28 07:00:39 +0000 |
commit | 3eb9473ea9a949badfe06ae61d2d3fcfa53651c7 (patch) | |
tree | e9d8c368dbb1e58794b2c00acefe4bbad270f8c4 /EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile | |
parent | 30d4a0c7ec19938196b1308006b990e0945150da (diff) | |
download | edk2-platforms-3eb9473ea9a949badfe06ae61d2d3fcfa53651c7.tar.xz |
Add in the 1st version of ECP.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2832 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile')
3 files changed, 2804 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c new file mode 100644 index 0000000000..188ca77945 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c @@ -0,0 +1,2681 @@ +/*++
+
+Copyright (c) 2004 - 2007, 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 "TianoCommon.h"
+#include "EfiFirmwareFileSystem.h"
+#include "EfiFirmwareVolumeHeader.h"
+#include "EfiImageFormat.h"
+#include "ParseInf.h"
+#include "Compress.h"
+#include "EfiCustomizedCompress.h"
+#include "crc32.h"
+#include "GenFfsFile.h"
+#include <stdio.h>
+#include <ctype.h> // for isalpha()
+//
+// include file for _spawnv
+//
+#include <process.h>
+#include <stdlib.h>
+#include <string.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) TianoCompress;
+
+ } else if (_strcmpi (Type, "LZH") == 0) {
+ //
+ // EFI stardard compression (LZH)
+ //
+ CompressionType = EFI_STANDARD_COMPRESSION;
+ CompressFunction = (COMPRESS_FUNCTION) TianoCompress;
+
+ } 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
+ //
+ returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray);
+ 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;
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ EFI_FFS_FILE_TAIL TailValue;
+#endif
+ 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;
+ }
+ }
+#if (PI_SPECIFICATION_VERSION < 0x00010000)
+ 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
+ else if (SFPIsToken ("FFS_ATTRIB_FIXED")) {
+ //
+ // ***********************************************************************
+ //
+ // Found: FFS_ATTRIB_FIXED = TRUE | FALSE
+ //
+ if (FfsAttribDefined & FFS_ATTRIB_FIXED) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_FIXED previously defined", NULL);
+ goto Done;
+ }
+
+ FfsAttribDefined |= FFS_ATTRIB_FIXED;
+ if (!SFPIsToken ("=")) {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL);
+ goto Done;
+ }
+
+ if (SFPIsToken ("TRUE")) {
+ FfsAttrib |= FFS_ATTRIB_FIXED;
+ } else if (SFPIsToken ("FALSE")) {
+ //
+ // Default is FALSE
+ //
+ } else {
+ Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL);
+ goto Done;
+ }
+ }
+#endif
+ 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_SUPPORTED
+ 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) {
+ Error (NULL, 0, 0, "failed to process script", NULL);
+ 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_RAW:
+ strcat (InputString, ".RAW");
+ 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) {
+ Error (NULL, 0, 0, "failed to process script", NULL);
+ 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_RAW:
+ strcat (InputString, ".RAW");
+ 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 (PI_SPECIFICATION_VERSION < 0x00010000)
+
+ //
+ // 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)
+ );
+ }
+#endif
+ //
+ // 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/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h new file mode 100644 index 0000000000..d3bcdbb90c --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h @@ -0,0 +1,35 @@ +/*++
+
+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 "TianoCommon.h"
+#include "EfiImageFormat.h"
+#include "MyAlloc.h"
+
+#endif
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile new file mode 100644 index 0000000000..85f9cfde9a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile @@ -0,0 +1,88 @@ +#/*++
+#
+# Copyright (c) 2004 - 2007, 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:
+#
+# makefile
+#
+# Abstract:
+#
+# This file is used to build the EFI GenFfsFile utility.
+#
+#--*/
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE $(BUILD_DIR)\PlatformTools.env
+
+#
+# Common information
+#
+
+INC=$(INC)
+
+LIBS = $(LIBS) $(EDK_TOOLS_OUTPUT)\CustomizedCompress.lib
+
+#
+# Target specific information
+#
+
+TARGET_NAME = GenFfsFile
+TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe
+TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFfsFile.c"
+TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \
+ "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h" \
+ "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" \
+ "$(EDK_TOOLS_COMMON)\ParseInf.h" \
+ "$(EDK_TOOLS_COMMON)\MyAlloc.h"
+
+TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib"
+C_FLAGS = $(C_FLAGS) -W4
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+#
+# Build EXE
+#
+
+$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj
+
+#
+# Add Binary Build description for this tool.
+#
+
+!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe))
+$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe
+ copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y
+ if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \
+ copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y
+!ELSE
+$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(LIBS) $(TARGET_EXE_LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj \
+ $(TARGET_LIB) $(TARGET_EXE_LIBS)
+ if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools
+ if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y
+ if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \
+ copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y
+!ENDIF
+
+clean:
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
|