From 28305207ea586d0b5ceb530b0e2a436cad9fdd8f Mon Sep 17 00:00:00 2001 From: lhauch Date: Thu, 5 Oct 2006 23:16:50 +0000 Subject: More renames for Tool Packages git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1675 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Source/GenFvImage/Ebc/PeCoffLoaderEx.c | 57 + Tools/CodeTools/Source/GenFvImage/GenFvImageExe.c | 299 +++ Tools/CodeTools/Source/GenFvImage/GenFvImageExe.h | 98 + Tools/CodeTools/Source/GenFvImage/GenFvImageLib.c | 2727 ++++++++++++++++++++ Tools/CodeTools/Source/GenFvImage/GenFvImageLib.h | 142 + .../Source/GenFvImage/GenFvImageLibInternal.h | 172 ++ Tools/CodeTools/Source/GenFvImage/build.xml | 124 + 7 files changed, 3619 insertions(+) create mode 100644 Tools/CodeTools/Source/GenFvImage/Ebc/PeCoffLoaderEx.c create mode 100644 Tools/CodeTools/Source/GenFvImage/GenFvImageExe.c create mode 100644 Tools/CodeTools/Source/GenFvImage/GenFvImageExe.h create mode 100644 Tools/CodeTools/Source/GenFvImage/GenFvImageLib.c create mode 100644 Tools/CodeTools/Source/GenFvImage/GenFvImageLib.h create mode 100644 Tools/CodeTools/Source/GenFvImage/GenFvImageLibInternal.h create mode 100644 Tools/CodeTools/Source/GenFvImage/build.xml (limited to 'Tools/CodeTools/Source/GenFvImage') diff --git a/Tools/CodeTools/Source/GenFvImage/Ebc/PeCoffLoaderEx.c b/Tools/CodeTools/Source/GenFvImage/Ebc/PeCoffLoaderEx.c new file mode 100644 index 0000000000..e8cf8b6457 --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/Ebc/PeCoffLoaderEx.c @@ -0,0 +1,57 @@ +/*++ + +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: + + PeCoffLoaderEx.c + +Abstract: + + EBC Specific relocation fixups + +Revision History + +--*/ + + + + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + return RETURN_UNSUPPORTED; +} diff --git a/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.c b/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.c new file mode 100644 index 0000000000..d0117b8ae9 --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.c @@ -0,0 +1,299 @@ +/*++ + +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: + + GenFvImageExe.c + +Abstract: + + This contains all code necessary to build the GenFvImage.exe utility. + This utility relies heavily on the GenFvImage Lib. Definitions for both + can be found in the Tiano Firmware Volume Generation Utility + Specification, review draft. + +--*/ + +// +// File included in build +// +#include "GenFvImageExe.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "%s - Tiano Firmware Volume Generation Utility."" Version %i.%i\n\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION + ); +} + +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("Usage: %s -I FvInfFileName\n", UTILITY_NAME); + printf (" Where:\n"); + printf ("\tFvInfFileName is the name of the image description file.\n\n"); +} + +int +main ( + IN INTN argc, + IN CHAR8 **argv + ) +/*++ + +Routine Description: + + This utility uses GenFvImage.Lib to build a firmware volume image. + +Arguments: + + FvInfFileName The name of an FV image description file. + + Arguments come in pair in any order. + -I FvInfFileName + +Returns: + + EFI_SUCCESS No error conditions detected. + EFI_INVALID_PARAMETER One or more of the input parameters is invalid. + EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable. + Most commonly this will be memory allocation + or file creation. + EFI_LOAD_ERROR GenFvImage.lib could not be loaded. + EFI_ABORTED Error executing the GenFvImage lib. + +--*/ +{ + EFI_STATUS Status; + CHAR8 InfFileName[_MAX_PATH]; + CHAR8 *InfFileImage; + UINTN InfFileSize; + UINT8 *FvImage; + UINTN FvImageSize; + UINT8 Index; + CHAR8 FvFileNameBuffer[_MAX_PATH]; + CHAR8 *FvFileName; + FILE *FvFile; + FILE *SymFile; + CHAR8 SymFileNameBuffer[_MAX_PATH]; + CHAR8 *SymFileName; + UINT8 *SymImage; + UINTN SymImageSize; + CHAR8 *CurrentSymString; + + FvFileName = FvFileNameBuffer; + SymFileName = SymFileNameBuffer; + + SetUtilityName (UTILITY_NAME); + // + // Display utility information + // + PrintUtilityInfo (); + + // + // Verify the correct number of arguments + // + if (argc != MAX_ARGS) { + Error (NULL, 0, 0, "invalid number of input parameters specified", NULL); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Initialize variables + // + strcpy (InfFileName, ""); + + // + // Parse the command line arguments + // + for (Index = 1; Index < MAX_ARGS; Index += 2) { + // + // Make sure argument pair begin with - or / + // + if (argv[Index][0] != '-' && argv[Index][0] != '/') { + Error (NULL, 0, 0, argv[Index], "argument pair must begin with \"-\" or \"/\""); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Make sure argument specifier is only one letter + // + if (argv[Index][2] != 0) { + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Determine argument to read + // + switch (argv[Index][1]) { + + case 'I': + case 'i': + if (strlen (InfFileName) == 0) { + strcpy (InfFileName, argv[Index + 1]); + } else { + Error (NULL, 0, 0, argv[Index + 1], "FvInfFileName may only be specified once"); + PrintUsage (); + return GetUtilityStatus (); + } + break; + + default: + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + break; + } + } + // + // Read the INF file image + // + Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + // + // Call the GenFvImage lib + // + Status = GenerateFvImage ( + InfFileImage, + InfFileSize, + &FvImage, + &FvImageSize, + &FvFileName, + &SymImage, + &SymImageSize, + &SymFileName + ); + + if (EFI_ERROR (Status)) { + switch (Status) { + + case EFI_INVALID_PARAMETER: + Error (NULL, 0, 0, "invalid parameter passed to GenFvImage Lib", NULL); + return GetUtilityStatus (); + break; + + case EFI_ABORTED: + Error (NULL, 0, 0, "error detected while creating the file image", NULL); + return GetUtilityStatus (); + break; + + case EFI_OUT_OF_RESOURCES: + Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL); + return GetUtilityStatus (); + break; + + case EFI_VOLUME_CORRUPTED: + Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL); + return GetUtilityStatus (); + break; + + case EFI_LOAD_ERROR: + Error (NULL, 0, 0, "could not load FV image generation library", NULL); + return GetUtilityStatus (); + break; + + default: + Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status); + return GetUtilityStatus (); + break; + } + } + // + // Write file + // + FvFile = fopen (FvFileName, "wb"); + if (FvFile == NULL) { + Error (NULL, 0, 0, FvFileName, "could not open output file"); + free (FvImage); + free (SymImage); + return GetUtilityStatus (); + } + + if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) { + Error (NULL, 0, 0, FvFileName, "failed to write to output file"); + free (FvImage); + free (SymImage); + fclose (FvFile); + return GetUtilityStatus (); + } + + fclose (FvFile); + free (FvImage); + + // + // Write symbol file + // + if (strcmp (SymFileName, "")) { + SymFile = fopen (SymFileName, "wt"); + if (SymFile == NULL) { + Error (NULL, 0, 0, SymFileName, "could not open output symbol file"); + free (SymImage); + return GetUtilityStatus (); + } + + fprintf (SymFile, "TEXTSYM format | V1.0\n"); + + CurrentSymString = SymImage; + while (((UINTN) CurrentSymString - (UINTN) SymImage) < SymImageSize) { + fprintf (SymFile, "%s", CurrentSymString); + CurrentSymString = (CHAR8 *) (((UINTN) CurrentSymString) + strlen (CurrentSymString) + 1); + } + + fclose (SymFile); + } + + free (SymImage); + + return GetUtilityStatus (); +} diff --git a/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.h b/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.h new file mode 100644 index 0000000000..9b97935656 --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/GenFvImageExe.h @@ -0,0 +1,98 @@ +/*++ + +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: + + GenFvImageExe.h + +Abstract: + + Definitions for the PeimFixup exe utility. + +--*/ + +// +// Coded to Tiano Coding Standards +// +#ifndef _EFI_GEN_FV_IMAGE_EXE_H +#define _EFI_GEN_FV_IMAGE_EXE_H + +#include +#include +#include +#include "GenFvImageLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "GenFvImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define UTILITY_DATE __DATE__ + +// +// The maximum number of arguments accepted from the command line. +// +#define MAX_ARGS 3 + +// +// The function that displays general utility information +// +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +// +// The function that displays the utility usage message. +// +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.c b/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.c new file mode 100644 index 0000000000..888656ad5c --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.c @@ -0,0 +1,2727 @@ +/*++ +i + +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: + + GenFvImageLib.c + +Abstract: + + This file contains functions required to generate a Firmware Volume. + +--*/ + +// +// Include files +// +#ifdef __GNUC__ +#include +#include +#endif +#include +#ifndef __GNUC__ +#include +#endif +#include + +#include +#include +#include +#include +#include + +#include "GenFvImageLib.h" +#include "GenFvImageLibInternal.h" +#include "CommonLib.h" +#include "Crc32.h" +#include "EfiUtilityMsgs.h" +#include "FvLib.h" +#include "EfiCompress.h" +#include "WinNtInclude.h" + + +// +// Local function prototypes +// +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ); + +// +// Local function implementations. +// +EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; +EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f }; + +// +// This data array will be located at the base of the Firmware Volume Header (FVH) +// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes +// will be used to keep the FVH checksum consistent. +// This code will be run in response to a starutp IPI for HT-enabled systems. +// +#define SIZEOF_STARTUP_DATA_ARRAY 0x10 + +UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EA D0 FF 00 F0 ; far jmp F000:FFD0 + // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEA, + 0xD0, + 0xFF, + 0x0, + 0xF0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EB CE ; jmp short ($-0x30) + // ; (from offset 0x0 to offset 0xFFD0) + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEB, + 0xCE, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function parses a FV.INF file and copies info into a FV_INFO structure. + +Arguments: + + InfFile Memory file image. + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS INF file information successfully retrieved. + EFI_ABORTED INF file has an invalid format. + EFI_NOT_FOUND A required string was not found in the INF file. +--*/ +{ + CHAR8 Value[_MAX_PATH]; + UINT64 Value64; + UINTN Index; + EFI_STATUS Status; + + // + // Initialize FV info + // + memset (FvInfo, 0, sizeof (FV_INFO)); + + // + // Read the FV base address + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Get the base address + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value"); + return EFI_ABORTED; + } + + FvInfo->BaseAddress = Value64; + } else { + Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value"); + return EFI_ABORTED; + } + // + // Read the FV Guid + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &FvInfo->FvGuid); + if (EFI_ERROR (Status)) { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + } else { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + // + // Read the FV file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->FvName, Value); + } else { + Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified"); + return EFI_ABORTED; + } + // + // Read the Sym file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->SymName, Value); + } else { + // + // Symbols not required, so init to NULL. + // + strcpy (FvInfo->SymName, ""); + } + // + // Read the read disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the write disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the lock capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the lock status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the sticky write attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified"); + return Status; + } + // + // Read the memory mapped attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified"); + return Status; + } + // + // Read the erase polarity attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, ONE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY; + } else if (strcmp (Value, ZERO_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified"); + return Status; + } + // + // Read the alignment capabilities attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified"); + return Status; + } + // + // Read the dword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified"); + return Status; + } + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified"); + return Status; + } + // + // Read the qword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified"); + return Status; + } + // + // Read the 32 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified"); + return Status; + } + // + // Read the 64 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified"); + return Status; + } + // + // Read the 128 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified"); + return Status; + } + // + // Read the 256 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified"); + return Status; + } + // + // Read the 512 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified"); + return Status; + } + // + // Read the 1K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified"); + return Status; + } + // + // Read the 2K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified"); + return Status; + } + // + // Read the 4K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified"); + return Status; + } + // + // Read the 8K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified"); + return Status; + } + // + // Read the 16K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified"); + return Status; + } + // + // Read the 32K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified"); + return Status; + } + // + // Read the 64K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified"); + return Status; + } + + if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) && + ( + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K) + ) + ) { + Error ( + NULL, + 0, + 0, + "illegal combination of alignment attributes", + "if %s is not %s, no individual alignments can be %s", + EFI_FVB_ALIGNMENT_CAP_STRING, + TRUE_STRING, + TRUE_STRING + ); + return EFI_ABORTED; + } + // + // Read block maps + // + for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { + // + // Read the number of blocks + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; + } else { + // + // If there is no number of blocks, but there is a size, then we have a mismatched pair + // and should return an error. + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + if (!EFI_ERROR (Status)) { + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } else { + // + // We are done + // + break; + } + } + // + // Read the size of blocks + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64; + } else { + // + // There is a number of blocks, but there is no size, so we have a mismatched pair + // and should return an error. + // + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + } + // + // Read files + // + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { + // + // Read the number of blocks + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (FvInfo->FvFiles[Index], Value); + } else { + break; + } + } + + if (FindSection (InfFile, COMPONENT_SECTION_STRING)) { + Index = 0; + // + // Read component FV_VARIABLE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING); + } + + Index++; + // + // Read component FV_EVENT_LOG + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING); + } + + Index++; + // + // Read component FV_FTW_WORKING + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING); + } + + Index++; + // + // Read component FV_FTW_SPARE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING); + } + } + // + // Compute size for easy access later + // + FvInfo->Size = 0; + for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) { + FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength; + } + + return EFI_SUCCESS; +} + +VOID +UpdateFfsFileState ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + This function changes the FFS file attributes based on the erase polarity + of the FV. + +Arguments: + + FfsFile File header. + FvHeader FV header. + +Returns: + + None + +--*/ +{ + if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + FfsFile->State = (UINT8)~(FfsFile->State); + } +} + +EFI_STATUS +ReadFfsAlignment ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT UINT32 *Alignment + ) +/*++ + +Routine Description: + + This function determines the alignment of the FFS input file from the file + attributes. + +Arguments: + + FfsFile FFS file to parse + Alignment The minimum required alignment of the FFS file, in bytes + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + // + // Verify input parameters. + // + if (FfsFile == NULL || Alignment == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch ((FfsFile->Attributes >> 3) & 0x07) { + + case 0: + // + // 1 byte alignment + // + *Alignment = (1 << 0); + break; + + case 1: + // + // 16 byte alignment + // + *Alignment = (1 << 4); + break; + + case 2: + // + // 128 byte alignment + // + *Alignment = (1 << 7); + break; + + case 3: + // + // 512 byte alignment + // + *Alignment = (1 << 9); + break; + + case 4: + // + // 1K byte alignment + // + *Alignment = (1 << 10); + break; + + case 5: + // + // 4K byte alignment + // + *Alignment = (1 << 12); + break; + + case 6: + // + // 32K byte alignment + // + *Alignment = (1 << 15); + break; + + case 7: + // + // 64K byte alignment + // + *Alignment = (1 << 16); + break; + + default: + Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddPadFile ( + IN OUT MEMORY_FILE *FvImage, + IN UINT32 DataAlignment + ) +/*++ + +Routine Description: + + This function adds a pad file to the FV image if it required to align the + data of the next file. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + DataAlignment The data alignment of the next FFS file. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete + the pad file add. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + EFI_GUID PadFileGuid; + UINTN PadFileSize; + + // + // Verify input parameters. + // + if (FvImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Basic assumption is we start from an 8 byte aligned address + // and our file header is a multiple of 8 bytes + // + assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0); + assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0); + + // + // Check if a pad file is necessary + // + if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) { + return EFI_SUCCESS; + } + // + // Write pad file header + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // Verify that we have enough space for the file header + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + +#ifdef __GNUC__ + { + uuid_t tmp_id; + uuid_generate (tmp_id); + memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID)); + } +#else + UuidCreate (&PadFileGuid); +#endif + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // Calculate the pad file size + // + // + // This is the earliest possible valid offset (current plus pad file header + // plus the next file header) + // + PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2); + + // + // Add whatever it takes to get to the next aligned address + // + while ((PadFileSize % DataAlignment) != 0) { + PadFileSize++; + } + // + // Subtract the next file header size + // + PadFileSize -= sizeof (EFI_FFS_FILE_HEADER); + + // + // Subtract the starting offset to get size + // + PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage; + + // + // Write pad file size (calculated size minus next file header size) + // + PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF); + PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF); + PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF); + + // + // Fill in checksums and state, they must be 0 for checksumming. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize); + } else { + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // Verify that we have enough space (including the padding + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer += PadFileSize; + + return EFI_SUCCESS; +} + +BOOLEAN +IsVtfFile ( + IN EFI_FFS_FILE_HEADER *FileBuffer + ) +/*++ + +Routine Description: + + This function checks the header to validate if it is a VTF file + +Arguments: + + FileBuffer Buffer in which content of a file has been read. + +Returns: + + TRUE If this is a VTF file + FALSE If this is not a VTF file + +--*/ +{ + EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; + if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) { + return TRUE; + } else { + return FALSE; + } +} + +EFI_STATUS +FfsRebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +AddSymFile ( + IN UINT64 BaseAddress, + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT MEMORY_FILE *SymImage, + IN CHAR8 *SourceFileName + ) +/*++ + +Routine Description: + + This function adds the SYM tokens in the source file to the destination file. + The SYM tokens are updated to reflect the base address. + +Arguments: + + BaseAddress The base address for the new SYM tokens. + FfsFile Pointer to the beginning of the FFS file in question. + SymImage The memory file to update with symbol information. + SourceFileName The source file. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + FILE *SourceFile; + + CHAR8 Buffer[_MAX_PATH]; + CHAR8 Type[_MAX_PATH]; + CHAR8 Address[_MAX_PATH]; + CHAR8 Section[_MAX_PATH]; + CHAR8 Token[_MAX_PATH]; + CHAR8 SymFileName[_MAX_PATH]; + CHAR8 CodeModuleName[_MAX_PATH]; + CHAR8 *Ptr; + + UINT64 TokenAddress; + + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + + // + // Verify input parameters. + // + if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) { + Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL); + return EFI_INVALID_PARAMETER; + } + // + // Check if we want to add this file + // + // + // Get the file name + // + strcpy (Buffer, SourceFileName); + + // + // Copy the file name for the path of the sym file and truncate the name portion. + // + strcpy (SymFileName, Buffer); + Ptr = strrchr (SymFileName, '\\'); + assert (Ptr); + Ptr[0] = 0; + + // + // Find the file extension and make it lower case + // + Ptr = strrchr (SymFileName, '.'); + if (Ptr != NULL) { + strlwr (Ptr); + } + // + // Check if it is PEI file + // + if (strstr (Buffer, ".pei") != NULL) { + // + // Find the human readable portion + // + if (!strtok (Buffer, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strcpy (Buffer, strtok (NULL, ".")) + ) { + Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL); + return EFI_ABORTED; + } + // + // Save code module name + // + strcpy (CodeModuleName, Buffer); + + // + // Add the symbol file name and extension to the file path. + // + strcat (Buffer, ".sym"); + strcat (SymFileName, "\\"); + strcat (SymFileName, Buffer); + } else { + // + // Only handle PEIM files. + // + return EFI_SUCCESS; + } + // + // Find PE32 section + // + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section); + + // + // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address + // + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (Status == EFI_SUCCESS) { + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + } else if (Status == EFI_NOT_FOUND) { + // + // For PIC, hardcode. + // + BaseOfCode = 0x60; + Status = EFI_SUCCESS; + } else { + Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL); + return Status; + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL); + return Status; + } + + // + // Open the source file + // + SourceFile = fopen (SymFileName, "r"); + if (SourceFile == NULL) { + // + // SYM files are not required. + // + return EFI_SUCCESS; + } + // + // Read the first line + // + if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) { + Buffer[0] = 0; + } + // + // Make sure it matches the expected sym format + // + if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) { + fclose (SourceFile); + Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL); + return EFI_ABORTED; + } + // + // Read in the file + // + while (feof (SourceFile) == 0) { + // + // Read a line + // + if (fscanf ( + SourceFile, + "%s | %s | %s | %s\n", + Type, + Address, + Section, + Token + ) == 4) { + // + // If the token starts with "??" ignore it + // + if (Token[0] == '?' && Token[1] == '?') { + continue; + } + // + // Get the token address + // + AsciiStringToUint64 (Address, TRUE, &TokenAddress); + + // + // Add the base address + // + TokenAddress += BaseAddress; + + // + // If PE32 or TE section then find the start of code. For PIC it is hardcoded. + // + if (Pe32Section.Pe32Section) { + // + // Add the offset of the PE32 section + // + TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile; + + // + // Add the size of the PE32 section header + // + TokenAddress += sizeof (EFI_PE32_SECTION); + } else { + // + // For PIC hardcoded. + // + TokenAddress += 0x28; + } + + // + // Add the beginning of the code + // + TokenAddress += BaseOfCode; + + sprintf ( + Buffer, + "%s | %016I64X | %s | _%s%s\n", + Type, + TokenAddress, + Section, + CodeModuleName, + Token + ); + memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1); + SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1); + } + } + + fclose (SourceFile); + return EFI_SUCCESS; +} + +EFI_STATUS +AddFile ( + IN OUT MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN UINTN Index, + IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, + IN OUT MEMORY_FILE *SymImage + ) +/*++ + +Routine Description: + + This function adds a file to the FV image. The file will pad to the + appropriate alignment if required. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + FvInfo Pointer to information about the FV. + Index The file in the FvInfo file list to add. + VtfFileImage A pointer to the VTF file within the FvImage. If this is equal + to the end of the FvImage then no VTF previously found. + SymImage The memory image of the Sym file to update if symbols are present. + The current offset must be valid. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. + +--*/ +{ + FILE *NewFile; + UINTN FileSize; + UINT8 *FileBuffer; + UINTN NumBytesRead; + UINT32 CurrentFileAlignment; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress; + UINT8 VtfHeaderChecksum; + UINT8 VtfFileChecksum; + UINT8 FileState; + EFI_FFS_FILE_TAIL TailValue; + UINT32 TailSize; + // + // Verify input parameters. + // + if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Read the file to add + // + NewFile = fopen (FvInfo->FvFiles[Index], "rb"); + + if (NewFile == NULL) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading"); + return EFI_ABORTED; + } + // + // Get the file size + // +#ifdef __GNUC__ + { + struct stat stat_buf; + fstat(fileno(NewFile), &stat_buf); + FileSize = stat_buf.st_size; + } +#else + FileSize = _filelength (fileno (NewFile)); +#endif + + // + // Read the file into a buffer + // + FileBuffer = malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return EFI_OUT_OF_RESOURCES; + } + + NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile); + + // + // Done with the file, from this point on we will just use the buffer read. + // + fclose (NewFile); + + // + // Verify read successful + // + if (NumBytesRead != sizeof (UINT8) * FileSize) { + free (FileBuffer); + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents"); + return EFI_ABORTED; + } + // + // Verify space exists to add the file + // + if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file"); + return EFI_OUT_OF_RESOURCES; + } + // + // Update the file state based on polarity of the FV. + // + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) FileBuffer, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // If we have a VTF file, add it at the top. + // + if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) { + if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) { + // + // No previous VTF, add this one. + // + *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize); + // + // Sanity check. The file MUST align appropriately + // + if ((((UINTN) *VtfFileImage) & 0x07) != 0) { + Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL); + } + // + // copy VTF File Header + // + memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER)); + + // + // Copy VTF body + // + memcpy ( + (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER), + FileBuffer + sizeof (EFI_FFS_FILE_HEADER), + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + + // + // re-calculate the VTF File Header + // + FileState = (*VtfFileImage)->State; + (*VtfFileImage)->State = 0; + *(UINT32 *) ((*VtfFileImage)->Size) = FileSize; + (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0; + (*VtfFileImage)->IntegrityCheck.Checksum.File = 0; + + VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER)); + (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum; + // + // Determine if it has a tail + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize); + (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum; + } else { + (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + // + // If it has a file tail, update it + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } + (*VtfFileImage)->State = FileState; + free (FileBuffer); + return EFI_SUCCESS; + } else { + // + // Already found a VTF file. + // + Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL); + free (FileBuffer); + return EFI_ABORTED; + } + } + // + // Check if alignment is required + // + Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add pad file if necessary + // + Status = AddPadFile (FvImage, CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not align the file data properly.\n"); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add file + // + if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) { + // + // Copy the file + // + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + + // + // If the file is XIP, rebase + // + CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage); + // + // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress); + // if (EFI_ERROR(Status)) { + // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]); + // return EFI_ABORTED; + // } + // + // Update Symbol file + // + Status = AddSymFile ( + CurrentFileBaseAddress, + (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer, + SymImage, + FvInfo->FvFiles[Index] + ); + assert (!EFI_ERROR (Status)); + + // + // Update the current pointer in the FV image + // + FvImage->CurrentFilePointer += FileSize; + } else { + printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + // + // Make next file start at QWord Boundry + // + while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) { + FvImage->CurrentFilePointer++; + } + // + // Free allocated memory. + // + free (FileBuffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +AddVariableBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + VARIABLE_STORE_HEADER *VarStoreHeader; + // + // Variable block should exclude FvHeader. Since the length of + // FvHeader depends on the block map, which is variable length, + // we could only decide the actual variable block length here. + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + FvImage = FvImage + FvHeader->HeaderLength; + + VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage; + + VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE; + VarStoreHeader->Size = Size - FvHeader->HeaderLength; + VarStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VarStoreHeader->State = VARIABLE_STORE_HEALTHY; + VarStoreHeader->Reserved = 0; + VarStoreHeader->Reserved1 = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +AddEventLogBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWWorkingBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader; + UINT32 Crc32; + + Crc32 = 0; + FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage; + memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID)); + FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); + CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32); + FTWHeader->Crc = Crc32; + if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) { + FTWHeader->WorkingBlockValid = 0; + FTWHeader->WorkingBlockInvalid = 1; + } else { + FTWHeader->WorkingBlockValid = 1; + FTWHeader->WorkingBlockInvalid = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWSpareBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +GenNonFFSFv ( + IN UINT8 *FvImage, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function generate the non FFS FV image, such as the working block + and spare block. How each component of the FV is built is component + specific. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + FvInfo Pointer to information about the FV. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. + +--*/ +{ + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 TotalSize; + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + TotalSize = 0; + + for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) { + if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) { + AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) { + AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) { + AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) { + AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else { + printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName); + return EFI_ABORTED; + } + + FvImage = FvImage + FvInfo->FvComponents[Index].Size; + TotalSize = TotalSize + FvInfo->FvComponents[Index].Size; + } + // + // Index and TotalSize is zero mean there's no component, so this is an empty fv + // + if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) { + printf ("Error. Component size does not sum up to FV size.\n"); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PadFvImage ( + IN MEMORY_FILE *FvImage, + IN EFI_FFS_FILE_HEADER *VtfFileImage + ) +/*++ + +Routine Description: + + This function places a pad file between the last file in the FV and the VTF + file if the VTF file exists. + +Arguments: + + FvImage Memory file for the FV memory image + VtfFileImage The address of the VTF file. If this is the end of the FV + image, no VTF exists and no pad file is needed. + +Returns: + + EFI_SUCCESS Completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINTN FileSize; + + // + // If there is no VTF or the VTF naturally follows the previous file without a + // pad file, then there's nothing to do + // + if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) { + return EFI_SUCCESS; + } + // + // Pad file starts at beginning of free space + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // write header + // + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer; + PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF); + PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8); + PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16); + + // + // Fill in checksums and state, must be zero during checksum calculation. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize); + } else { + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer = FvImage->Eof; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateResetVector ( + IN MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN EFI_FFS_FILE_HEADER *VtfFile + ) +/*++ + +Routine Description: + + This parses the FV looking for the PEI core and then plugs the address into + the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to + complete an IA32 Bootstrap FV. + +Arguments: + + FvImage Memory file for the FV memory image + FvInfo Information read from INF file. + VtfFile Pointer to the VTF file in the FV image. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_FFS_FILE_HEADER *PeiCoreFile; + EFI_FFS_FILE_HEADER *SecCoreFile; + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress; + EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress; + EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr; + UINT32 *Ia32ResetAddressPtr; + UINT8 *BytePointer; + UINT8 *BytePointer2; + UINT16 *WordPointer; + UINT16 CheckSum; + UINTN Index; + EFI_FFS_FILE_STATE SavedState; + EFI_FFS_FILE_TAIL TailValue; + UINT32 TailSize; + UINT64 FitAddress; + FIT_TABLE *FitTablePtr; + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage); + + // + // Verify VTF file + // + Status = VerifyFfsFile (VtfFile); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + // + // Find the PEI Core + // + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (EFI_ERROR (Status) || PeiCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL); + return EFI_ABORTED; + } + + // + // PEI Core found, now find PE32 or TE section + // + Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + PeiCorePhysicalAddress = FvInfo->BaseAddress; + PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + PeiCorePhysicalAddress += EntryPoint; + + if (MachineType == EFI_IMAGE_MACHINE_IA64) { + // + // Update PEI_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + PeiCorePhysicalAddress |= 0x8000000000000000ULL; + + // + // Check if address is aligned on a 16 byte boundary + // + if (PeiCorePhysicalAddress & 0xF) { + printf ( + "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + PeiCorePhysicalAddress + ); + return EFI_ABORTED; + } + // + // First Get the FIT table address + // + FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF; + + FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress)); + + Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress); + + if (!EFI_ERROR (Status)) { + UpdateFitCheckSum (FitTablePtr); + } + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL); + return EFI_ABORTED; + } + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + SecCorePhysicalAddress = FvInfo->BaseAddress; + SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + SecCorePhysicalAddress += EntryPoint; + + // + // Update SEC_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + SecCorePhysicalAddress |= 0x8000000000000000ULL; + + // + // Update the address + // + SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET); + *SecCoreEntryAddressPtr = SecCorePhysicalAddress; + + // + // Check if address is aligned on a 16 byte boundary + // + if (SecCorePhysicalAddress & 0xF) { + printf ( + "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + SecCorePhysicalAddress + ); + return EFI_ABORTED; + } + } else if (MachineType == EFI_IMAGE_MACHINE_IA32) { + // + // Get the location to update + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); + + // + // Write lower 32 bits of physical address + // + *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; + + // + // Update the BFV base address + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); + *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); + + CheckSum = 0x0000; + + // + // Update the Startup AP in the FVH header block ZeroVector region. + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray; + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { + *BytePointer++ = *BytePointer2++; + } + // + // Calculate the checksum + // + WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage); + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { + CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); + WordPointer++; + } + // + // Update the checksum field + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2); + WordPointer = (UINT16 *) BytePointer; + *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); + } else { + Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType); + return EFI_ABORTED; + } + // + // Determine if it has an FFS file tail. + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Now update file checksum + // + SavedState = VtfFile->State; + VtfFile->IntegrityCheck.Checksum.File = 0; + VtfFile->State = 0; + if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) VtfFile, + GetLength (VtfFile->Size) - TailSize + ); + } else { + VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + VtfFile->State = SavedState; + + // + // Update tail if present + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ) +/*++ + +Routine Description: + + Retrieves the PE32 entry point offset and machine type from PE image or TeImage. + See EfiImage.h for machine types. The entry point offset is from the beginning + of the PE32 buffer passed in. + +Arguments: + + Pe32 Beginning of the PE32. + EntryPoint Offset from the beginning of the PE32 to the image entry point. + BaseOfCode Base address of code. + MachineType Magic number for the machine type. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_UNSUPPORTED The operation is unsupported. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *NtHeader; + EFI_TE_IMAGE_HEADER *TeHeader; + + // + // Verify input parameters + // + if (Pe32 == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // First check whether it is one TE Image. + // + TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32; + if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + // + // By TeImage Header to get output + // + *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; + *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; + *MachineType = TeHeader->Machine; + } else { + + // + // Then check whether + // First is the DOS header + // + DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32; + + // + // Verify DOS header is expected + // + if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic); + return EFI_UNSUPPORTED; + } + // + // Immediately following is the NT header. + // + NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew); + + // + // Verify NT header is expected + // + if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { + printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature); + return EFI_UNSUPPORTED; + } + // + // Get output + // + *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; + *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode; + *MachineType = NtHeader->FileHeader.Machine; + } + + // + // Verify machine type is supported + // + if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) { + printf ("ERROR: Unrecognized machine type in the PE32 file.\n"); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} +// +// Exposed function implementations (prototypes are defined in GenFvImageLib.h) +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + EFI_STATUS Status; + MEMORY_FILE InfMemoryFile; + MEMORY_FILE FvImageMemoryFile; + MEMORY_FILE SymImageMemoryFile; + FV_INFO FvInfo; + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FFS_FILE_HEADER *VtfFileImage; + + // + // Check for invalid parameter + // + if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the FV inf file for header information + // + Status = ParseFvInf (&InfMemoryFile, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not parse the input INF file.\n"); + return EFI_ABORTED; + } + // + // Update the file name return values + // + strcpy (*FvFileName, FvInfo.FvName); + strcpy (*SymFileName, FvInfo.SymName); + + // + // Calculate the FV size + // + *FvImageSize = FvInfo.Size; + + // + // Allocate the FV + // + *FvImage = malloc (*FvImageSize); + if (*FvImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate space for symbol file storage + // + *SymImage = malloc (SYMBOL_FILE_SIZE); + if (*SymImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize the FV to the erase polarity + // + if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) { + memset (*FvImage, -1, *FvImageSize); + } else { + memset (*FvImage, 0, *FvImageSize); + } + // + // Initialize FV header + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage; + + // + // Initialize the zero vector to all zeros. + // + memset (FvHeader->ZeroVector, 0, 16); + + // + // Copy the FFS GUID + // + memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID)); + + FvHeader->FvLength = *FvImageSize; + FvHeader->Signature = EFI_FVH_SIGNATURE; + FvHeader->Attributes = FvInfo.FvAttributes; + FvHeader->Revision = EFI_FVH_REVISION; + FvHeader->Reserved[0] = 0; + FvHeader->Reserved[1] = 0; + FvHeader->Reserved[2] = 0; + + // + // Copy firmware block map + // + for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) { + FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks; + FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength; + } + // + // Add block map terminator + // + FvHeader->FvBlockMap[Index].NumBlocks = 0; + FvHeader->FvBlockMap[Index].BlockLength = 0; + + // + // Complete the header + // + FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + // + // If there is no FFS file, find and generate each components of the FV + // + if (FvInfo.FvFiles[0][0] == 0) { + Status = GenNonFFSFv (*FvImage, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not generate NonFFS FV.\n"); + free (*FvImage); + return EFI_ABORTED; + } + + return EFI_SUCCESS; + } + // + // Initialize our "file" view of the buffer + // + FvImageMemoryFile.FileImage = *FvImage; + FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength; + FvImageMemoryFile.Eof = *FvImage +*FvImageSize; + + // + // Initialize our "file" view of the symbol file. + // + SymImageMemoryFile.FileImage = *SymImage; + SymImageMemoryFile.CurrentFilePointer = *SymImage; + SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE; + + // + // Initialize the FV library. + // + InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size); + + // + // Files start on 8 byte alignments, so move to the next 8 byte aligned + // address. For now, just assert if it isn't. Currently FV header is + // always a multiple of 8 bytes. + // BUGBUG: Handle this better + // + assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0); + + // + // Initialize the VTF file address. + // + VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; + + // + // Add files to FV + // + for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) { + // + // Add the file + // + Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile); + + // + // Exit if error detected while adding the file + // + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]); + free (*FvImage); + return EFI_ABORTED; + } + } + // + // If there is a VTF file, some special actions need to occur. + // + if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) { + // + // Pad from the end of the last file to the beginning of the VTF file. + // + Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n"); + free (*FvImage); + return EFI_ABORTED; + } + // + // Update reset vector (SALE_ENTRY for IPF) + // Now for IA32 and IA64 platform, the fv which has bsf file must have the + // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the + // reset vector. If the PEI Core is found, the VTF file will probably get + // corrupted by updating the entry point. + // + if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) { + Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage); + if (EFI_ERROR(Status)) { + printf ("ERROR: Could not update the reset vector.\n"); + free (*FvImage); + return EFI_ABORTED; + } + } + } + // + // Determine final Sym file size + // + *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +{ + FIT_TABLE *TmpFitPtr; + UINTN Index; + UINTN NumFitComponents; + + TmpFitPtr = FitTablePtr; + NumFitComponents = TmpFitPtr->CompSize; + + for (Index = 0; Index < NumFitComponents; Index++) { + if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) { + TmpFitPtr->CompAddress = PeiCorePhysicalAddress; + return EFI_SUCCESS; + } + + TmpFitPtr++; + } + + return EFI_NOT_FOUND; +} + +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +{ + if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) { + FitTablePtr->CheckSum = 0; + FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16); + } +} diff --git a/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.h b/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.h new file mode 100644 index 0000000000..47a5a3b1b2 --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/GenFvImageLib.h @@ -0,0 +1,142 @@ +/*++ + +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: + + GenFvImageLib.h + +Abstract: + + This file contains describes the public interfaces to the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_H +#define _EFI_GEN_FV_IMAGE_LIB_H + +// +// Include files +// +#include +#include + +#include "ParseInf.h" + +// +// Following definition is used for FIT in IPF +// +#define COMP_TYPE_FIT_PEICORE 0x10 +#define COMP_TYPE_FIT_UNUSED 0x7F + +#define FIT_TYPE_MASK 0x7F +#define CHECKSUM_BIT_MASK 0x80 + +#pragma pack(1) + +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; + +#pragma pack() +// +// Exported function prototypes +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +; + +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +; + +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +; + +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +#endif diff --git a/Tools/CodeTools/Source/GenFvImage/GenFvImageLibInternal.h b/Tools/CodeTools/Source/GenFvImage/GenFvImageLibInternal.h new file mode 100644 index 0000000000..cff3b1aea4 --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/GenFvImageLibInternal.h @@ -0,0 +1,172 @@ +/*++ + +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: + + GenFvImageLibInternal.h + +Abstract: + + This file contains describes the private declarations for the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H +#define _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H + +// +// Include files +// +#include + +#include + +#include "CommonLib.h" +#include "GenFvImageLib.h" + +// +// Private data declarations +// +// +// The maximum number of block map entries supported by the library +// +#define MAX_NUMBER_OF_FV_BLOCKS 100 + +// +// The maximum number of files in the FV supported by the library +// +#define MAX_NUMBER_OF_FILES_IN_FV 1000 +#define MAX_NUMBER_OF_COMPONENTS_IN_FV 10 + +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" +#define COMPONENT_SECTION_STRING "[components]" + +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_SYM_FILE_NAME_STRING "EFI_SYM_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_FV_GUID_STRING "EFI_FV_GUID" + +#define EFI_FVB_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP" +#define EFI_FVB_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP" +#define EFI_FVB_READ_STATUS_STRING "EFI_READ_STATUS" + +#define EFI_FVB_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP" +#define EFI_FVB_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP" +#define EFI_FVB_WRITE_STATUS_STRING "EFI_WRITE_STATUS" + +#define EFI_FVB_LOCK_CAP_STRING "EFI_LOCK_CAP" +#define EFI_FVB_LOCK_STATUS_STRING "EFI_LOCK_STATUS" + +#define EFI_FVB_STICKY_WRITE_STRING "EFI_STICKY_WRITE" +#define EFI_FVB_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED" +#define EFI_FVB_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY" + +#define EFI_FVB_ALIGNMENT_CAP_STRING "EFI_ALIGNMENT_CAP" +#define EFI_FVB_ALIGNMENT_2_STRING "EFI_ALIGNMENT_2" +#define EFI_FVB_ALIGNMENT_4_STRING "EFI_ALIGNMENT_4" +#define EFI_FVB_ALIGNMENT_8_STRING "EFI_ALIGNMENT_8" +#define EFI_FVB_ALIGNMENT_16_STRING "EFI_ALIGNMENT_16" +#define EFI_FVB_ALIGNMENT_32_STRING "EFI_ALIGNMENT_32" +#define EFI_FVB_ALIGNMENT_64_STRING "EFI_ALIGNMENT_64" +#define EFI_FVB_ALIGNMENT_128_STRING "EFI_ALIGNMENT_128" +#define EFI_FVB_ALIGNMENT_256_STRING "EFI_ALIGNMENT_256" +#define EFI_FVB_ALIGNMENT_512_STRING "EFI_ALIGNMENT_512" +#define EFI_FVB_ALIGNMENT_1K_STRING "EFI_ALIGNMENT_1K" +#define EFI_FVB_ALIGNMENT_2K_STRING "EFI_ALIGNMENT_2K" +#define EFI_FVB_ALIGNMENT_4K_STRING "EFI_ALIGNMENT_4K" +#define EFI_FVB_ALIGNMENT_8K_STRING "EFI_ALIGNMENT_8K" +#define EFI_FVB_ALIGNMENT_16K_STRING "EFI_ALIGNMENT_16K" +#define EFI_FVB_ALIGNMENT_32K_STRING "EFI_ALIGNMENT_32K" +#define EFI_FVB_ALIGNMENT_64K_STRING "EFI_ALIGNMENT_64K" + +// +// Component sections +// +#define EFI_NV_VARIABLE_STRING "EFI_NV_VARIABLE" +#define EFI_NV_EVENT_LOG_STRING "EFI_NV_EVENT_LOG" +#define EFI_NV_FTW_WORKING_STRING "EFI_NV_FTW_WORKING" +#define EFI_NV_FTW_SPARE_STRING "EFI_NV_FTW_SPARE" + +#define EFI_FILE_NAME_STRING "EFI_FILE_NAME" + +#define ONE_STRING "1" +#define ZERO_STRING "0" +#define TRUE_STRING "TRUE" +#define FALSE_STRING "FALSE" +#define NULL_STRING "NULL" + +// +// Defines to calculate the offset for PEI CORE entry points +// +#define IA32_PEI_CORE_ENTRY_OFFSET 0x20 + +// +// Defines to calculate the FIT table +// +#define IPF_FIT_ADDRESS_OFFSET 0x20 + +// +// Defines to calculate the offset for SALE_ENTRY +// +#define IPF_SALE_ENTRY_ADDRESS_OFFSET 0x18 + +// +// Symbol file definitions, current max size if 512K +// +#define SYMBOL_FILE_SIZE 0x80000 + +#define FV_IMAGES_TOP_ADDRESS 0x100000000ULL + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[_MAX_PATH]; +} COMPONENT_INFO; + +// +// FV information holder +// +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_GUID FvGuid; + UINTN Size; + CHAR8 FvName[_MAX_PATH]; + CHAR8 SymName[_MAX_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + EFI_FVB_ATTRIBUTES FvAttributes; + CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH]; + COMPONENT_INFO FvComponents[MAX_NUMBER_OF_COMPONENTS_IN_FV]; +} FV_INFO; + +// +// Private function prototypes +// +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN FV_INFO *FvInfo + ) +; + +#endif diff --git a/Tools/CodeTools/Source/GenFvImage/build.xml b/Tools/CodeTools/Source/GenFvImage/build.xml new file mode 100644 index 0000000000..ae930b053b --- /dev/null +++ b/Tools/CodeTools/Source/GenFvImage/build.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3