summaryrefslogtreecommitdiff
path: root/BaseTools/Source/C/GenVtf/GenVtf.c
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/C/GenVtf/GenVtf.c')
-rw-r--r--BaseTools/Source/C/GenVtf/GenVtf.c2721
1 files changed, 2721 insertions, 0 deletions
diff --git a/BaseTools/Source/C/GenVtf/GenVtf.c b/BaseTools/Source/C/GenVtf/GenVtf.c
new file mode 100644
index 0000000000..e633b7ccf8
--- /dev/null
+++ b/BaseTools/Source/C/GenVtf/GenVtf.c
@@ -0,0 +1,2721 @@
+/**
+
+Copyright (c) 1999 - 2008, Intel Corporation. All rights reserved
+This software and associated documentation (if any) is furnished
+under a license and may only be used or copied in accordance
+with the terms of the license. Except as permitted by such
+license, no part of this software or documentation may be
+reproduced, stored in a retrieval system, or transmitted in any
+form or by any means without the express written consent of
+Intel Corporation.
+
+
+Module Name:
+
+ GenVtf.c
+
+Abstract:
+
+ This file contains functions required to generate a boot strap file (BSF)
+ also known as the Volume Top File (VTF)
+
+**/
+
+//
+//
+//
+#include <FvLib.h>
+#include <Common/UefiBaseTypes.h>
+#include "GenVtf.h"
+#include <Guid/PiFirmwareFileSystem.h>
+#include "CommonLib.h"
+#include "EfiUtilityMsgs.h"
+
+//
+// Global variables
+//
+UINTN SectionOptionFlag = 0;
+UINTN SectionCompFlag = 0;
+
+UINT64 DebugLevel;
+BOOLEAN DebugMode;
+
+BOOLEAN QuietMode = FALSE;
+
+BOOLEAN VTF_OUTPUT = FALSE;
+CHAR8 *OutFileName1;
+CHAR8 *OutFileName2;
+CHAR8 *SymFileName;
+
+CHAR8 **TokenStr;
+CHAR8 **OrgStrTokPtr;
+
+PARSED_VTF_INFO *FileListPtr;
+PARSED_VTF_INFO *FileListHeadPtr;
+
+VOID *Vtf1Buffer;
+VOID *Vtf1EndBuffer;
+VOID *Vtf2Buffer;
+VOID *Vtf2EndBuffer;
+
+UINTN ValidLineNum = 0;
+UINTN ValidFFDFileListNum = 0;
+
+//
+// Section Description and their number of occurences in *.INF file
+//
+UINTN NumFvFiles = 0;
+UINTN SectionOptionNum = 0;
+
+//
+// Global flag which will check for VTF Present, if yes then will be used
+// to decide about adding FFS header to pad data
+//
+BOOLEAN VTFPresent = FALSE;
+BOOLEAN SecondVTF = FALSE;
+
+//
+// Address related information
+//
+UINT64 Fv1BaseAddress = 0;
+UINT64 Fv2BaseAddress = 0;
+UINT64 Fv1EndAddress = 0;
+UINT64 Fv2EndAddress = 0;
+UINT32 Vtf1TotalSize = SIZE_TO_OFFSET_PAL_A_END;
+UINT64 Vtf1LastStartAddress = 0;
+UINT32 Vtf2TotalSize = 0;
+UINT64 Vtf2LastStartAddress = 0;
+
+UINT32 BufferToTop = 0;
+
+//
+// IA32 Reset Vector Bin name
+//
+CHAR8 IA32BinFile[FILE_NAME_SIZE];
+
+//
+// Function Implementations
+//
+EFI_STATUS
+ConvertVersionInfo (
+ IN CHAR8 *Str,
+ IN OUT UINT8 *MajorVer,
+ IN OUT UINT8 *MinorVer
+ )
+/*++
+Routine Description:
+
+ This function converts GUID string to GUID
+
+Arguments:
+
+ Str - String representing in form XX.XX
+ MajorVer - The major vertion
+ MinorVer - The minor vertion
+
+Returns:
+
+ EFI_SUCCESS - The fuction completed successfully.
+
+--*/
+{
+ CHAR8 StrPtr[40];
+ CHAR8 *Token;
+ UINTN Length;
+ UINT32 Major;
+ UINT32 Minor;
+
+ Major = 0;
+ Minor = 0;
+ memset (StrPtr, 0, 40);
+ Token = strtok (Str, ".");
+
+ while (Token != NULL) {
+ strcat (StrPtr, Token);
+ Token = strtok (NULL, ".");
+ }
+
+ Length = strlen (StrPtr);
+ sscanf (
+ StrPtr,
+ "%01x%02x",
+ &Major,
+ &Minor
+ );
+
+ *MajorVer = (UINT8) Major;
+ *MinorVer = (UINT8) Minor;
+ return EFI_SUCCESS;
+}
+
+VOID
+TrimLine (
+ IN CHAR8 *Line
+ )
+/*++
+Routine Description:
+
+ This function cleans up the line by removing all whitespace and
+ comments
+
+Arguments:
+
+ Line - The pointer of the string
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 TmpLine[FILE_NAME_SIZE];
+ CHAR8 Char;
+ CHAR8 *Ptr0;
+ UINTN Index;
+ UINTN Index2;
+
+ //
+ // Change '#' to '//' for Comment style
+ //
+ if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {
+ Line[Ptr0 - Line] = 0;
+ }
+
+ //
+ // Initialize counters
+ //
+ Index = 0;
+ Index2 = 0;
+
+ while ((Char = Line[Index]) != 0) {
+ if ((Char != ' ') && (Char != '\t') && (Char != '\n') && (Char != '\r')) {
+ TmpLine[Index2++] = Char;
+ }
+ Index++;
+ }
+
+ TmpLine[Index2] = 0;
+ strcpy (Line, TmpLine);
+}
+
+VOID
+ValidLineCount (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function calculated number of valid lines in a input file.
+
+Arguments:
+
+ Fp - Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 Buff[FILE_NAME_SIZE];
+ while (fgets(Buff, sizeof (Buff), Fp)) {
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+ ValidLineNum++;
+ }
+}
+
+EFI_STATUS
+ParseInputFile (
+ IN FILE *Fp
+ )
+/*++
+
+Routine Description:
+
+ This function parses the input file and tokenize the string
+
+Arguments:
+
+ Fp - Pointer to a file handle which has been opened.
+
+Returns:
+
+ None
+
+--*/
+{
+ CHAR8 *Token;
+ CHAR8 Buff[FILE_NAME_SIZE + 1];
+ CHAR8 Delimit[] = "=";
+
+ Buff [FILE_NAME_SIZE] = '\0';
+ Token = NULL;
+
+ while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) {
+ TrimLine (Buff);
+ if (Buff[0] == 0) {
+ continue;
+ }
+ Token = strtok (Buff, Delimit);
+ while (Token != NULL) {
+ strcpy (*TokenStr, Token);
+ TokenStr ++;
+ Token = strtok (NULL, Delimit);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+InitializeComps (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file. This also initializes
+ the VTF symbol file.
+
+Arguments:
+
+ None
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_OUT_OF_RESOURCES - Malloc failed.
+
+--*/
+{
+
+ FileListPtr = malloc (sizeof (PARSED_VTF_INFO));
+
+ if (FileListPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileListHeadPtr = FileListPtr;
+ memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
+ FileListPtr->NextVtfInfo = NULL;
+
+ remove (SymFileName);
+ return EFI_SUCCESS;
+}
+
+VOID
+ParseAndUpdateComponents (
+ IN PARSED_VTF_INFO *VtfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ VtfInfo - A pointer to the VTF Info Structure
+
+
+Returns:
+
+ None
+
+--*/
+{
+ UINT64 StringValue;
+
+ while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) {
+
+ if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) {
+ TokenStr++;
+ if (strnicmp (*TokenStr, "F", 1) == 0) {
+ VtfInfo->LocationType = FIRST_VTF;
+ } else if (strnicmp (*TokenStr, "S", 1) == 0) {
+ VtfInfo->LocationType = SECOND_VTF;
+ } else {
+ VtfInfo->LocationType = NONE;
+ Warning(UTILITY_NAME, 0, 0001, "Unknown location for component.", VtfInfo->CompName);
+ }
+ } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) {
+ TokenStr++;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ Error (NULL, 0, 5001, "Cannot get: \"0x%x\".", *TokenStr);
+ return ;
+ }
+
+ VtfInfo->CompType = (UINT8) StringValue;
+ } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) {
+ TokenStr++;
+ if (strnicmp (*TokenStr, "-", 1) == 0) {
+ VtfInfo->VersionPresent = FALSE;
+ VtfInfo->MajorVer = 0;
+ VtfInfo->MinorVer = 0;
+ } else {
+ VtfInfo->VersionPresent = TRUE;
+ ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer);
+ }
+ } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) {
+ TokenStr++;
+ strcpy (VtfInfo->CompBinName, *TokenStr);
+ } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) {
+ TokenStr++;
+ strcpy (VtfInfo->CompSymName, *TokenStr);
+ } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) {
+ TokenStr++;
+ if (strnicmp (*TokenStr, "-", 1) == 0) {
+ VtfInfo->PreferredSize = FALSE;
+ VtfInfo->CompSize = 0;
+ } else {
+ VtfInfo->PreferredSize = TRUE;
+ if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
+ Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr);
+ return ;
+ }
+
+ VtfInfo->CompSize = (UINTN) StringValue;
+ }
+
+ } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) {
+ TokenStr++;
+ if (strnicmp (*TokenStr, "1", 1) == 0) {
+ VtfInfo->CheckSumRequired = 1;
+ } else if (strnicmp (*TokenStr, "0", 1) == 0) {
+ VtfInfo->CheckSumRequired = 0;
+ } else {
+ Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
+ }
+ }
+
+ TokenStr++;
+ if (*TokenStr == NULL) {
+ break;
+ }
+ }
+}
+
+VOID
+InitializeInFileInfo (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function intializes the relevant global variable which is being
+ used to store the information retrieved from INF file.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+
+ SectionOptionFlag = 0;
+ SectionCompFlag = 0;
+ TokenStr = OrgStrTokPtr;
+
+ while (*TokenStr != NULL) {
+ if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) {
+ SectionOptionFlag = 1;
+ SectionCompFlag = 0;
+ }
+
+ if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 0) {
+ if (FileListPtr == NULL) {
+ FileListPtr = FileListHeadPtr;
+ }
+
+ SectionCompFlag = 1;
+ SectionOptionFlag = 0;
+ TokenStr++;
+ }
+
+ if (SectionOptionFlag) {
+ if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
+ TokenStr++;
+ strcpy (IA32BinFile, *TokenStr);
+ }
+ }
+
+ if (SectionCompFlag) {
+ if (stricmp (*TokenStr, "COMP_NAME") == 0) {
+ TokenStr++;
+ strcpy (FileListPtr->CompName, *TokenStr);
+ TokenStr++;
+ ParseAndUpdateComponents (FileListPtr);
+ }
+
+ if (*TokenStr != NULL) {
+ FileListPtr->NextVtfInfo = malloc (sizeof (PARSED_VTF_INFO));
+ if (FileListPtr->NextVtfInfo == NULL) {
+ Error (NULL, 0, 4003, "Resource", "Out of memory resources.", NULL);
+ break;
+ }
+ FileListPtr = FileListPtr->NextVtfInfo;
+ memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
+ FileListPtr->NextVtfInfo = NULL;
+ continue;
+ } else {
+ break;
+ }
+ }
+
+ TokenStr++;
+ }
+}
+
+EFI_STATUS
+GetVtfRelatedInfoFromInfFile (
+ IN FILE *FilePointer
+ )
+/*++
+
+Routine Description:
+
+ This function reads the input file, parse it and create a list of tokens
+ which is parsed and used, to intialize the data related to VTF
+
+Arguments:
+
+ FileName - FileName which needed to be read to parse data
+
+Returns:
+
+ EFI_ABORTED - Error in opening file
+ EFI_INVALID_PARAMETER - File doesn't contain any valid information
+ EFI_OUT_OF_RESOURCES - Malloc Failed
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FILE *Fp;
+ UINTN Index;
+ UINTN Index1;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ Fp = FilePointer;
+ if (Fp == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
+ return EFI_ABORTED;
+ }
+
+ ValidLineCount (Fp);
+
+ if (ValidLineNum == 0) {
+ Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
+
+ if (TokenStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
+ OrgStrTokPtr = TokenStr;
+
+ for (Index = 0; Index < (2 * ValidLineNum); Index++) {
+ *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
+
+ if (*TokenStr == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ParseFileError;
+ }
+
+ memset (*TokenStr, 0, FILE_NAME_SIZE);
+ TokenStr++;
+ }
+
+ TokenStr = OrgStrTokPtr;
+ fseek (Fp, 0L, SEEK_SET);
+
+ Status = InitializeComps ();
+
+ if (Status != EFI_SUCCESS) {
+ goto ParseFileError;
+ }
+
+ Status = ParseInputFile (Fp);
+ if (Status != EFI_SUCCESS) {
+ goto ParseFileError;
+ }
+
+ InitializeInFileInfo ();
+
+ParseFileError:
+
+ for (Index1 = 0; Index1 < Index; Index1 ++) {
+ free (OrgStrTokPtr[Index1]);
+ }
+
+ free (OrgStrTokPtr);
+
+ return Status;
+}
+
+VOID
+GetRelativeAddressInVtfBuffer (
+ IN UINT64 Address,
+ IN OUT UINTN *RelativeAddress,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ This function checks for the address alignmnet for specified data boundary. In
+ case the address is not aligned, it returns FALSE and the amount of data in
+ terms of byte needed to adjust to get the boundary alignmnet. If data is
+ aligned, TRUE will be returned.
+
+Arguments:
+
+ Address - The address of the flash map space
+ RelativeAddress - The relative address of the Buffer
+ LocType - The type of the VTF
+
+
+Returns:
+
+
+--*/
+{
+ UINT64 TempAddress;
+ UINT8 *LocalBuff;
+
+ if (LocType == FIRST_VTF) {
+ LocalBuff = (UINT8 *) Vtf1EndBuffer;
+ TempAddress = Fv1EndAddress - Address;
+ *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
+ } else {
+ LocalBuff = (UINT8 *) Vtf2EndBuffer;
+ TempAddress = Fv2EndAddress - Address;
+ *RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
+ }
+}
+
+EFI_STATUS
+GetComponentVersionInfo (
+ IN OUT PARSED_VTF_INFO *VtfInfo,
+ IN UINT8 *Buffer
+ )
+/*++
+Routine Description:
+
+ This function will extract the version information from File
+
+Arguments:
+
+ VtfInfo - A Pointer to the VTF Info Structure
+ Buffer - A Pointer to type UINT8
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The parameter is invalid
+
+--*/
+{
+ UINT16 VersionInfo;
+ EFI_STATUS Status;
+
+ switch (VtfInfo->CompType) {
+
+ case COMP_TYPE_FIT_PAL_A:
+ case COMP_TYPE_FIT_PAL_B:
+ memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));
+ VtfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);
+ VtfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+BOOLEAN
+CheckAddressAlignment (
+ IN UINT64 Address,
+ IN UINT64 AlignmentData,
+ IN OUT UINT64 *AlignAdjustByte
+ )
+/*++
+
+Routine Description:
+
+ This function checks for the address alignmnet for specified data boundary. In
+ case the address is not aligned, it returns FALSE and the amount of data in
+ terms of byte needed to adjust to get the boundary alignmnet. If data is
+ aligned, TRUE will be returned.
+
+Arguments:
+
+ Address - Pointer to buffer containing byte data of component.
+ AlignmentData - DataSize for which address needed to be aligned
+ AlignAdjustByte - Number of bytes needed to adjust alignment.
+
+Returns:
+
+ TRUE - Address is aligned to specific data size boundary
+ FALSE - Address in not aligned to specified data size boundary
+ - Add/Subtract AlignAdjustByte to aling the address.
+
+--*/
+{
+ //
+ // Check if the assigned address is on address boundary. If not, it will
+ // return the remaining byte required to adjust the address for specified
+ // address boundary
+ //
+ *AlignAdjustByte = (Address % AlignmentData);
+
+ if (*AlignAdjustByte == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+EFI_STATUS
+GetFitTableStartAddress (
+ IN OUT FIT_TABLE **FitTable
+ )
+/*++
+
+Routine Description:
+
+ Get the FIT table start address in VTF Buffer
+
+Arguments:
+
+ FitTable - Pointer to available fit table where new component can be added
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN RelativeAddress;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File. The relative address will be
+ // the address of fit table VTF buffer.
+ //
+ GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ //
+ // The FitTableAdd is the extracted Itanium based address pointing to FIT
+ // table. The relative address will return its actual location in VTF
+ // Buffer.
+ //
+ GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ *FitTable = (FIT_TABLE *) RelativeAddress;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetNextAvailableFitPtr (
+ IN FIT_TABLE **FitPtr
+ )
+/*++
+
+Routine Description:
+
+ Get the FIT table address and locate the free space in fit where we can add
+ new component. In this process, this function locates the fit table using
+ Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
+ and locate the available location in FIT table to be used by new components.
+ If there are any Fit table which areg not being used contains ComponentType
+ field as 0x7F. If needed we can change this and spec this out.
+
+Arguments:
+
+ FitPtr - Pointer to available fit table where new component can be added
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN Index;
+ UINTN NumFitComponents;
+ UINTN RelativeAddress;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File. The relative address will be
+ // the address of fit table VTF buffer.
+ //
+ GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ //
+ // The FitTableAdd is the extracted Itanium based address pointing to FIT
+ // table. The relative address will return its actual location in VTF
+ // Buffer.
+ //
+ GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ TmpFitPtr = (FIT_TABLE *) RelativeAddress;
+ NumFitComponents = TmpFitPtr->CompSize;
+
+ for (Index = 0; Index < NumFitComponents; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {
+ *FitPtr = TmpFitPtr;
+ break;
+ }
+
+ TmpFitPtr++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+int
+CompareItems (
+ IN const VOID *Arg1,
+ IN const VOID *Arg2
+ )
+/*++
+
+Routine Description:
+
+ This function is used by qsort to sort the FIT table based upon Component
+ Type in their incresing order.
+
+Arguments:
+
+ Arg1 - Pointer to Arg1
+ Arg2 - Pointer to Arg2
+
+Returns:
+
+ None
+
+--*/
+{
+ if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
+ return 1;
+ } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+VOID
+SortFitTable (
+ IN VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is used by qsort to sort the FIT table based upon Component
+ Type in their incresing order.
+
+Arguments:
+
+ VOID
+
+Returns:
+
+ None
+
+--*/
+{
+ FIT_TABLE *FitTable;
+ FIT_TABLE *TmpFitPtr;
+ UINTN NumFitComponents;
+ UINTN Index;
+
+ GetFitTableStartAddress (&FitTable);
+ TmpFitPtr = FitTable;
+ NumFitComponents = 0;
+ for (Index = 0; Index < FitTable->CompSize; Index++) {
+ if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {
+ NumFitComponents += 1;
+ }
+ TmpFitPtr++;
+ }
+ qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);
+}
+
+VOID
+UpdateFitEntryForFwVolume (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function updates the information about Firmware Volume in FIT TABLE.
+ This FIT table has to be immediately below the PAL_A Start and it contains
+ component type and address information. Other information can't be
+ created this time so we would need to fix it up..
+
+
+Arguments:
+
+ Size - Firmware Volume Size
+
+Returns:
+
+ VOID
+
+--*/
+{
+ FIT_TABLE *CompFitPtr;
+ UINTN RelativeAddress;
+
+ //
+ // FV Fit table will be located at PAL_A Startaddress - 16 byte location
+ //
+ Vtf1LastStartAddress -= 0x10;
+ Vtf1TotalSize += 0x10;
+
+ GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+
+ CompFitPtr = (FIT_TABLE *) RelativeAddress;
+ CompFitPtr->CompAddress = Fv1BaseAddress;
+
+ //
+ // Since we don't have any information about its location in Firmware Volume,
+ // initialize address to 0. This will be updated once Firmware Volume is
+ // being build and its current address will be fixed in FIT table. Currently
+ // we haven't implemented it so far and working on architectural clarafication
+ //
+ //
+ // Firmware Volume Size in 16 byte block
+ //
+ CompFitPtr->CompSize = ((UINT32) Size) / 16;
+
+ //
+ // Since Firmware Volume does not exist by the time we create this FIT info
+ // this should be fixedup from Firmware Volume creation tool. We haven't
+ // worked out a method so far.
+ //
+ CompFitPtr->CompVersion = MAKE_VERSION (0, 0);
+
+ //
+ // Since we don't have any info about this file, we are making sure that
+ // checksum is not needed.
+ //
+ CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);
+
+ //
+ // Since non VTF component will reside outside the VTF, we will not have its
+ // binary image while creating VTF, hence we will not perform checksum at
+ // this time. Once Firmware Volume is being created which will contain this
+ // VTF, it will fix the FIT table for all the non VTF component and hence
+ // checksum
+ //
+ CompFitPtr->CheckSum = 0;
+}
+
+EFI_STATUS
+UpdateFitEntryForNonVTFComp (
+ IN PARSED_VTF_INFO *VtfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function updates the information about non VTF component in FIT TABLE.
+ Since non VTF componets binaries are not part of VTF binary, we would still
+ be required to update its location information in Firmware Volume, inside
+ FIT table.
+
+Arguments:
+
+ VtfInfo - Pointer to VTF Info Structure
+
+Returns:
+
+ EFI_ABORTED - The function fails to update the component in FIT
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *CompFitPtr;
+
+ //
+ // Scan the FIT table for available space
+ //
+ GetNextAvailableFitPtr (&CompFitPtr);
+ if (CompFitPtr == NULL) {
+ Error (NULL, 0, 5003, "Invalid", "Can't update this component in FIT");
+ return EFI_ABORTED;
+ }
+
+ //
+ // Since we don't have any information about its location in Firmware Volume,
+ // initialize address to 0. This will be updated once Firmware Volume is
+ // being build and its current address will be fixed in FIT table
+ //
+ CompFitPtr->CompAddress = 0;
+ CompFitPtr->CompSize = VtfInfo->CompSize;
+ CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
+ CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
+
+ //
+ // Since non VTF component will reside outside the VTF, we will not have its
+ // binary image while creating VTF, hence we will not perform checksum at
+ // this time. Once Firmware Volume is being created which will contain this
+ // VTF, it will fix the FIT table for all the non VTF component and hence
+ // checksum
+ //
+ CompFitPtr->CheckSum = 0;
+
+ //
+ // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
+ // address of Firmware Volume in which this VTF will be attached.
+ //
+ if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {
+ CompFitPtr->CompAddress = Fv1BaseAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// !!!WARNING
+// This function is updating the SALE_ENTRY in Itanium address space as per SAL
+// spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
+// CORE moves in Firmware Volume, we would need to modify this function to be
+// used with a API which will detect PEICORE component while building Firmware
+// Volume and update its entry in FIT table as well as in Itanium address space
+// as per Intel?Itanium(TM) SAL address space
+//
+EFI_STATUS
+UpdateEntryPoint (
+ IN PARSED_VTF_INFO *VtfInfo,
+ IN UINT64 *CompStartAddress
+ )
+/*++
+
+Routine Description:
+
+ This function updated the architectural entry point in IPF, SALE_ENTRY.
+
+Arguments:
+
+ VtfInfo - Pointer to VTF Info Structure
+ CompStartAddress - Pointer to Component Start Address
+
+Returns:
+
+ EFI_INVALID_PARAMETER - The parameter is invalid
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINTN RelativeAddress;
+ UINT64 SalEntryAdd;
+ FILE *Fp;
+ UINTN Offset;
+
+ CHAR8 Buff[FILE_NAME_SIZE];
+ CHAR8 Buff1[10];
+ CHAR8 Buff2[10];
+ CHAR8 OffsetStr[30];
+ CHAR8 Buff3[10];
+ CHAR8 Buff4[10];
+ CHAR8 Buff5[10];
+ CHAR8 Token[50];
+
+ Fp = fopen (VtfInfo->CompSymName, "rb");
+
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
+ fscanf (
+ Fp,
+ "%s %s %s %s %s %s %s",
+ Buff1,
+ Buff2,
+ OffsetStr,
+ Buff3,
+ Buff4,
+ Buff5,
+ Token
+ );
+ if (strnicmp (Token, "SALE_ENTRY", 10) == 0) {
+ break;
+ }
+ }
+
+ Offset = strtoul (OffsetStr, NULL, 16);
+
+ *CompStartAddress += Offset;
+ SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
+
+ GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
+
+ memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
+
+ if (Fp != NULL) {
+ fclose (Fp);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CreateAndUpdateComponent (
+ IN PARSED_VTF_INFO *VtfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components and update them
+ in VTF Buffer as well as in FIT table. If the component is located in non
+ VTF area, only the FIT table address will be updated
+
+Arguments:
+
+ VtfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_SUCCESS - The function completed successful
+ EFI_ABORTED - Aborted due to one of the many reasons like:
+ (a) Component Size greater than the specified size.
+ (b) Error opening files.
+
+ EFI_INVALID_PARAMETER Value returned from call to UpdateEntryPoint()
+ EFI_OUT_OF_RESOURCES Memory allocation failure.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 CompStartAddress;
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT64 NumAdjustByte;
+ UINT8 *Buffer;
+ FILE *Fp;
+ FIT_TABLE *CompFitPtr;
+ BOOLEAN Aligncheck;
+
+ if (VtfInfo->LocationType == NONE) {
+ UpdateFitEntryForNonVTFComp (VtfInfo);
+ return EFI_SUCCESS;
+ }
+
+ Fp = fopen (VtfInfo->CompBinName, "rb");
+
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (fileno (Fp));
+ if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
+
+ //
+ // BUGBUG: Satish to correct
+ //
+ FileSize -= SIZE_OF_PAL_HEADER;
+ }
+
+ if (VtfInfo->PreferredSize) {
+ if (FileSize > VtfInfo->CompSize) {
+ Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
+ return EFI_ABORTED;
+ }
+
+ FileSize = VtfInfo->CompSize;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer, 0, (UINTN) FileSize);
+
+ if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
+
+ //
+ // Read first 64 bytes of PAL header and use it to find version info
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
+
+ //
+ // PAL header contains the version info. Currently, we will use the header
+ // to read version info and then discard.
+ //
+ if (!VtfInfo->VersionPresent) {
+ GetComponentVersionInfo (VtfInfo, Buffer);
+ }
+ }
+
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ //
+ // If it is non PAL_B component, pass the entire buffer to get the version
+ // info and implement any specific case inside GetComponentVersionInfo.
+ //
+ if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
+ if (!VtfInfo->VersionPresent) {
+ GetComponentVersionInfo (VtfInfo, Buffer);
+ }
+ }
+
+ if (VtfInfo->LocationType == SECOND_VTF) {
+
+ CompStartAddress = (Vtf2LastStartAddress - FileSize);
+ } else {
+ CompStartAddress = (Vtf1LastStartAddress - FileSize);
+ }
+
+ if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
+ Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
+ } else {
+ Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
+ }
+
+ if (!Aligncheck) {
+ CompStartAddress -= NumAdjustByte;
+ }
+
+ if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) {
+ Vtf2LastStartAddress = CompStartAddress;
+ Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
+ Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
+ } else if (VtfInfo->LocationType == FIRST_VTF) {
+ Vtf1LastStartAddress = CompStartAddress;
+ Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
+ Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
+ } else {
+ Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ GetNextAvailableFitPtr (&CompFitPtr);
+
+ CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
+ if ((FileSize % 16) != 0) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
+ return EFI_INVALID_PARAMETER;
+ }
+ //assert ((FileSize % 16) == 0);
+ CompFitPtr->CompSize = (UINT32) (FileSize / 16);
+ CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
+ CompFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
+ if (VtfInfo->CheckSumRequired) {
+ CompFitPtr->CheckSum = 0;
+ CompFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
+ }
+
+ //
+ // Free the buffer
+ //
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ //
+ // Update the SYM file for this component based on it's start address.
+ //
+ Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName);
+ if (EFI_ERROR (Status)) {
+
+ //
+ // At this time, SYM files are not required, so continue on error.
+ //
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!
+ // BUGBUG:
+ // This part of the code is a temporary line since PEICORE is going to be inside
+ // VTF till we work out how to determine the SALE_ENTRY through it. We will need
+ // to clarify so many related questions
+ // !!!!!!!!!!!!!!!!!!!!!!!
+
+ if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
+ Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CreateAndUpdatePAL_A (
+ IN PARSED_VTF_INFO *VtfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function reads the binary file for each components and update them
+ in VTF Buffer as well as FIT table
+
+Arguments:
+
+ VtfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Due to one of the following reasons:
+ (a)Error Opening File
+ (b)The PAL_A Size is more than specified size status
+ One of the values mentioned below returned from
+ call to UpdateSymFile
+ EFI_SUCCESS - The function completed successfully.
+ EFI_INVALID_PARAMETER - One of the input parameters was invalid.
+ EFI_ABORTED - An error occurred.UpdateSymFile
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT64 PalStartAddress;
+ UINT64 AbsAddress;
+ UINTN RelativeAddress;
+ UINT64 FileSize;
+ UINT64 NumByteRead;
+ UINT8 *Buffer;
+ FILE *Fp;
+ FIT_TABLE *PalFitPtr;
+
+ Fp = fopen (VtfInfo->CompBinName, "rb");
+
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (fileno (Fp));
+ if (FileSize < 64) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
+ return EFI_INVALID_PARAMETER;
+ }
+ FileSize -= SIZE_OF_PAL_HEADER;
+
+
+ if (VtfInfo->PreferredSize) {
+ if (FileSize > VtfInfo->CompSize) {
+ Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
+ return EFI_ABORTED;
+ }
+
+ FileSize = VtfInfo->CompSize;
+ }
+
+ Buffer = malloc ((UINTN) FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Buffer, 0, (UINTN) FileSize);
+
+ //
+ // Read, Get version Info and discard the PAL header.
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
+
+ //
+ // Extract the version info from header of PAL_A. Once done, discrad this buffer
+ //
+ if (!VtfInfo->VersionPresent) {
+ GetComponentVersionInfo (VtfInfo, Buffer);
+ }
+
+ //
+ // Read PAL_A file in a buffer
+ //
+ NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
+ fclose (Fp);
+
+ PalStartAddress = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);
+ Vtf1LastStartAddress = PalStartAddress;
+ Vtf1TotalSize += (UINT32) FileSize;
+ Status = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
+
+ AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
+ GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
+ PalFitPtr = (FIT_TABLE *) RelativeAddress;
+ PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;
+ //assert ((FileSize % 16) == 0);
+ if ((FileSize % 16) != 0) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PalFitPtr->CompSize = (UINT32) (FileSize / 16);
+ PalFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
+ PalFitPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
+ if (VtfInfo->CheckSumRequired) {
+ PalFitPtr->CheckSum = 0;
+ PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
+ }
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ //
+ // Update the SYM file for this component based on it's start address.
+ //
+ Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName);
+ if (EFI_ERROR (Status)) {
+
+ //
+ // At this time, SYM files are not required, so continue on error.
+ //
+ }
+
+ return Status;
+}
+
+EFI_STATUS
+CreateFitTableAndInitialize (
+ IN PARSED_VTF_INFO *VtfInfo
+ )
+/*++
+
+Routine Description:
+
+ This function creates and intializes FIT table which would be used to
+ add component info inside this
+
+Arguments:
+
+ VtfInfo - Pointer to Parsed Info
+
+Returns:
+
+ EFI_ABORTED - Aborted due to no size information
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT64 PalFitTableAdd;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddressOffset;
+ FIT_TABLE *PalFitPtr;
+ FIT_TABLE *FitStartPtr;
+ UINTN NumFitComp;
+ UINTN RelativeAddress;
+ UINTN Index;
+
+ if (!VtfInfo->PreferredSize) {
+ Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
+ return EFI_ABORTED;
+ }
+
+ if ((VtfInfo->CompSize % 16) != 0) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
+ }
+
+ PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
+ GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
+ PalFitPtr = (FIT_TABLE *) RelativeAddress;
+ PalFitTableAdd = (PalFitPtr->CompAddress - VtfInfo->CompSize);
+
+ FitTableAdd = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize;
+ FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+ GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
+ *(UINT64 *) RelativeAddress = FitTableAdd;
+
+ GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ //
+ // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
+ //
+ FitStartPtr = (FIT_TABLE *) RelativeAddress;
+
+ strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8); // "_FIT_ "
+ assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
+ FitStartPtr->CompSize = (VtfInfo->CompSize & 0x00FFFFFF) / 16;
+ FitStartPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
+
+ //
+ // BUGBUG: If a checksum is required, add code to checksum the FIT table. Also
+ // determine what to do for things like the FV component that aren't easily checksummed.
+ // The checksum will be done once we are done with all the componet update in the FIT
+ // table
+ //
+ FitStartPtr->CvAndType = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
+
+ NumFitComp = FitStartPtr->CompSize;
+
+ FitStartPtr++;
+
+ //
+ // Intialize remaining FIT table space to UNUSED fit component type
+ // so that when we need to create a FIT entry for a component, we can
+ // locate a free one and use it.
+ //
+ for (Index = 0; Index < (NumFitComp - 1); Index++) {
+ FitStartPtr->CvAndType = 0x7F; // Initialize all with UNUSED
+ FitStartPtr++;
+ }
+
+ Vtf1TotalSize += VtfInfo->CompSize;
+ Vtf1LastStartAddress -= VtfInfo->CompSize;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+WriteVtfBinary (
+ IN CHAR8 *FileName,
+ IN UINT32 VtfSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Write Firmware Volume from memory to a file.
+
+Arguments:
+
+ FileName - Output File Name which needed to be created/
+ VtfSize - FileSize
+ LocType - The type of the VTF
+
+Returns:
+
+ EFI_ABORTED - Returned due to one of the following resons:
+ (a) Error Opening File
+ (b) Failing to copy buffers
+ EFI_SUCCESS - The fuction completes successfully
+
+--*/
+{
+ FILE *Fp;
+ UINTN NumByte;
+ VOID *VtfBuffer;
+ UINTN RelativeAddress;
+
+ if (LocType == FIRST_VTF) {
+ GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+ VtfBuffer = (VOID *) RelativeAddress;
+ } else {
+ GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
+ VtfBuffer = (VOID *) RelativeAddress;
+ }
+
+ Fp = fopen (FileName, "wb");
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", FileName);
+ return EFI_ABORTED;
+ }
+
+ NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (NumByte != (sizeof (UINT8) * VtfSize)) {
+ Error (NULL, 0, 0002, "Error writing file", FileName);
+ return EFI_ABORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateVtfBuffer (
+ IN UINT64 StartAddress,
+ IN UINT8 *Buffer,
+ IN UINT64 DataSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ StartAddress - StartAddress in buffer. This number will automatically
+ point to right address in buffer where data needed
+ to be updated.
+ Buffer - Buffer pointer from data will be copied to memory mapped buffer.
+ DataSize - Size of the data needed to be copied.
+ LocType - The type of the VTF: First or Second
+
+Returns:
+
+ EFI_ABORTED - The input parameter is error
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ UINT8 *LocalBufferPtrToWrite;
+
+ if (LocType == FIRST_VTF) {
+ if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
+ return EFI_ABORTED;
+ }
+
+ LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;
+
+ LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
+
+ } else {
+
+ if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");
+ return EFI_ABORTED;
+ }
+ LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;
+ LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
+ }
+
+ memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+UpdateFfsHeader (
+ IN UINT32 TotalVtfSize,
+ IN LOC_TYPE LocType
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ TotalVtfSize - Size of the VTF
+ Fileoffset - The start of the file relative to the start of the FV.
+ LocType - The type of the VTF
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
+
+--*/
+{
+ EFI_FFS_FILE_HEADER *FileHeader;
+ UINTN RelativeAddress;
+ EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
+
+ //
+ // Find the VTF file header location
+ //
+ if (LocType == FIRST_VTF) {
+ GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
+ FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
+ } else {
+ GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
+ FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
+ }
+
+ if (FileHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // write header
+ //
+ memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
+ memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
+ FileHeader->Type = EFI_FV_FILETYPE_RAW;
+ FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
+
+ //
+ // Now FileSize includes the EFI_FFS_FILE_HEADER
+ //
+ FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);
+ FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);
+ FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);
+
+ //
+ // Fill in checksums and state, all three must be zero for the checksums.
+ //
+ FileHeader->IntegrityCheck.Checksum.Header = 0;
+ FileHeader->IntegrityCheck.Checksum.File = 0;
+ FileHeader->State = 0;
+ FileHeader->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
+ FileHeader->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) FileHeader, TotalVtfSize);
+ FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+ValidateAddressAndSize (
+ IN UINT64 BaseAddress,
+ IN UINT64 FwVolSize
+ )
+/*++
+
+Routine Description:
+
+ Update the Firmware Volume Buffer with requested buffer data
+
+Arguments:
+
+ BaseAddress - Base address for the Fw Volume.
+
+ FwVolSize - Total Size of the FwVolume to which VTF will be attached..
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_UNSUPPORTED - The input parameter is error
+
+--*/
+{
+ if ((BaseAddress >= 0) && (FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+UpdateIA32ResetVector (
+ IN CHAR8 *FileName,
+ IN UINT64 FirstFwVSize
+ )
+/*++
+
+Routine Description:
+
+ Update the 16 byte IA32 Reset vector to maintain the compatibility
+
+Arguments:
+
+ FileName - Binary file name which contains the IA32 Reset vector info..
+ FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - Invalid File Size
+ EFI_INVALID_PARAMETER - Bad File Name
+ EFI_OUT_OF_RESOURCES - Memory allocation failed.
+
+--*/
+{
+ UINT8 *Buffer;
+ UINT8 *LocalVtfBuffer;
+ UINTN FileSize;
+ UINTN NumByteRead;
+ FILE *Fp;
+
+ if (!strcmp (FileName, "")) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Fp = fopen (FileName, "rb");
+
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", FileName);
+ return EFI_ABORTED;
+ }
+
+ FileSize = _filelength (fileno (Fp));
+
+ if (FileSize > 16) {
+ return EFI_ABORTED;
+ }
+
+ Buffer = malloc (FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NumByteRead = fread (Buffer, sizeof (UINT8), FileSize, Fp);
+
+ LocalVtfBuffer = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;
+ memcpy (LocalVtfBuffer, Buffer, FileSize);
+
+ if (Buffer) {
+ free (Buffer);
+ }
+
+ if (Fp != NULL) {
+ fclose (Fp);
+ }
+ return EFI_SUCCESS;
+}
+
+VOID
+CleanUpMemory (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function cleans up any allocated buffer
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ NONE
+
+--*/
+{
+ PARSED_VTF_INFO *TempFileListPtr;
+
+ if (Vtf1Buffer) {
+ free (Vtf1Buffer);
+ }
+
+ if (Vtf2Buffer) {
+ free (Vtf2Buffer);
+ }
+
+ //
+ // Cleanup the buffer which was allocated to read the file names from FV.INF
+ //
+ FileListPtr = FileListHeadPtr;
+ while (FileListPtr != NULL) {
+ TempFileListPtr = FileListPtr->NextVtfInfo;
+ free (FileListPtr);
+ FileListPtr = TempFileListPtr;
+ }
+}
+
+EFI_STATUS
+ProcessAndCreateVtf (
+ IN UINT64 Size
+ )
+/*++
+
+Routine Description:
+
+ This function process the link list created during INF file parsing
+ and create component in VTF and updates its info in FIT table
+
+Arguments:
+
+ Size - Size of the Firmware Volume of which, this VTF belongs to.
+
+Returns:
+
+ EFI_UNSUPPORTED - Unknown FIT type
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ EFI_STATUS Status;
+ PARSED_VTF_INFO *ParsedInfoPtr;
+
+ Status = EFI_SUCCESS;
+
+ ParsedInfoPtr = FileListHeadPtr;
+
+ while (ParsedInfoPtr != NULL) {
+
+ switch (ParsedInfoPtr->CompType) {
+ //
+ // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
+ //
+ case COMP_TYPE_FIT_HEADER:
+ //COMP_TYPE_FIT_HEADER 0x00
+ Status = CreateFitTableAndInitialize (ParsedInfoPtr);
+ break;
+
+ //
+ // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
+ //
+ case COMP_TYPE_FIT_PAL_A:
+ //COMP_TYPE_FIT_PAL_A 0x0F
+ Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
+
+ //
+ // Based on VTF specification, once the PAL_A component has been written,
+ // update the Firmware Volume info as FIT table. This will be utilized
+ // to extract the Firmware Volume Start address where this VTF will be
+ // of part.
+ //
+ if (Status == EFI_SUCCESS) {
+ UpdateFitEntryForFwVolume (Size);
+ }
+ break;
+
+ case COMP_TYPE_FIT_FV_BOOT:
+ //COMP_TYPE_FIT_FV_BOOT 0x7E
+ //
+ // Since FIT entry for Firmware Volume has been created and it is
+ // located at (PAL_A start - 16 byte). So we will not process any
+ // Firmware Volume related entry from INF file
+ //
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ //
+ // Any other component type should be handled here. This will create the
+ // image in specified VTF and create appropriate entry about this
+ // component in FIT Entry.
+ //
+ Status = CreateAndUpdateComponent (ParsedInfoPtr);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);
+ return EFI_ABORTED;
+ } else {
+ break;}
+ }
+
+ ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;
+ }
+ return Status;
+}
+
+EFI_STATUS
+GenerateVtfImage (
+ IN UINT64 StartAddress1,
+ IN UINT64 Size1,
+ IN UINT64 StartAddress2,
+ IN UINT64 Size2,
+ IN FILE *fp
+ )
+/*++
+
+Routine Description:
+
+ This is the main function which will be called from application.
+
+Arguments:
+
+ StartAddress1 - The start address of the first VTF
+ Size1 - The size of the first VTF
+ StartAddress2 - The start address of the second VTF
+ Size2 - The size of the second VTF
+ fp - The pointer to BSF inf file
+
+Returns:
+
+ EFI_OUT_OF_RESOURCES - Can not allocate memory
+ The return value can be any of the values
+ returned by the calls to following functions:
+ GetVtfRelatedInfoFromInfFile
+ ProcessAndCreateVtf
+ UpdateIA32ResetVector
+ UpdateFfsHeader
+ WriteVtfBinary
+
+--*/
+{
+ EFI_STATUS Status;
+ FILE *VtfFP;
+
+ Status = EFI_UNSUPPORTED;
+ VtfFP = fp;
+
+ if (StartAddress2 == 0) {
+ SecondVTF = FALSE;
+ } else {
+ SecondVTF = TRUE;
+ }
+
+ Fv1BaseAddress = StartAddress1;
+ Fv1EndAddress = Fv1BaseAddress + Size1;
+ if (Fv1EndAddress != 0x100000000 || Size1 < 0x100000) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
+ if (Size1 < 0x100000) {
+ Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
+ } else if (SecondVTF != TRUE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
+ }
+ Usage();
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The image buffer for the First VTF
+ //
+ Vtf1Buffer = malloc ((UINTN) Size1);
+ if (Vtf1Buffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Vtf1Buffer, 0x00, (UINTN) Size1);
+ Vtf1EndBuffer = (UINT8 *) Vtf1Buffer + Size1;
+ Vtf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
+
+ if (SecondVTF) {
+ Fv2BaseAddress = StartAddress2;
+ Fv2EndAddress = Fv2BaseAddress + Size2;
+ if (Fv2EndAddress != StartAddress1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
+ if (SecondVTF == TRUE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
+ Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
+ }
+ Usage();
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The image buffer for the second VTF
+ //
+ Vtf2Buffer = malloc ((UINTN) Size2);
+ if (Vtf2Buffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ memset (Vtf2Buffer, 0x00, (UINTN) Size2);
+ Vtf2EndBuffer = (UINT8 *) Vtf2Buffer + Size2;
+ Vtf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
+ }
+
+ Status = GetVtfRelatedInfoFromInfFile (VtfFP);
+
+ if (Status != EFI_SUCCESS) {
+ Error (NULL, 0, 0003, "Error parsing file", "the input file.");
+ CleanUpMemory ();
+ return Status;
+ }
+
+ Status = ProcessAndCreateVtf (Size1);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ if (SectionOptionFlag) {
+ Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+ }
+
+ //
+ // Re arrange the FIT Table for Ascending order of their FIT Type..
+ //
+ SortFitTable ();
+
+ //
+ // All components have been updated in FIT table. Now perform the FIT table
+ // checksum. The following function will check if Checksum is required,
+ // if yes, then it will perform the checksum otherwise not.
+ //
+ CalculateFitTableChecksum ();
+
+ //
+ // Write the FFS header
+ //
+ Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
+ Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
+
+ Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+ //
+ // Update the VTF buffer into specified VTF binary file
+ //
+ Status = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);
+
+ if (SecondVTF) {
+ Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
+ Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
+ Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF);
+ if (Status != EFI_SUCCESS) {
+ CleanUpMemory ();
+ return Status;
+ }
+
+ //
+ // Update the VTF buffer into specified VTF binary file
+ //
+ Status = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);
+ }
+
+ CleanUpMemory ();
+
+ return Status;
+}
+
+EFI_STATUS
+PeimFixupInFitTable (
+ IN UINT64 StartAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is an entry point to fixup SAL-E entry point.
+
+Arguments:
+
+ StartAddress - StartAddress for PEIM.....
+
+Returns:
+
+ EFI_SUCCESS - The function completed successfully
+ EFI_ABORTED - Error Opening File
+ EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
+
+--*/
+{
+ EFI_STATUS Status;
+ FILE *Fp;
+ UINT64 *StartAddressPtr;
+ UINTN FirstFwVSize;
+ UINTN NumByte;
+
+ StartAddressPtr = malloc (sizeof (UINT64));
+ if (StartAddressPtr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *StartAddressPtr = StartAddress;
+
+ Fp = fopen (OutFileName1, "rb");
+
+ if (Fp == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", OutFileName1);
+ if (StartAddressPtr) {
+ free (StartAddressPtr);
+ }
+ return EFI_ABORTED;
+ }
+
+ FirstFwVSize = _filelength (fileno (Fp));
+ fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);
+ NumByte = fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);
+
+ if (Fp) {
+ fclose (Fp);
+ }
+
+ if (StartAddressPtr) {
+ free (StartAddressPtr);
+ }
+
+ Status = EFI_SUCCESS;
+ return Status;
+}
+
+EFI_STATUS
+UpdateSymFile (
+ IN UINT64 BaseAddress,
+ IN CHAR8 *DestFileName,
+ 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.
+ DestFileName - The destination file.
+ 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;
+ FILE *DestFile;
+ CHAR8 Buffer[_MAX_PATH];
+ CHAR8 Type[_MAX_PATH];
+ CHAR8 Address[_MAX_PATH];
+ CHAR8 Section[_MAX_PATH];
+ CHAR8 Token[_MAX_PATH];
+ CHAR8 BaseToken[_MAX_PATH];
+ UINT64 TokenAddress;
+ long StartLocation;
+
+ //
+ // Verify input parameters.
+ //
+ if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Open the source file
+ //
+ SourceFile = fopen (SourceFileName, "r");
+ if (SourceFile == NULL) {
+
+ //
+ // SYM files are not required.
+ //
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Use the file name minus extension as the base for tokens
+ //
+ strcpy (BaseToken, SourceFileName);
+ strtok (BaseToken, ". \t\n");
+ strcat (BaseToken, "__");
+
+ //
+ // Open the destination file
+ //
+ DestFile = fopen (DestFileName, "a+");
+ if (DestFile == NULL) {
+ fclose (SourceFile);
+ Error (NULL, 0, 0001, "Error opening file", DestFileName);
+ return EFI_ABORTED;
+ }
+
+ //
+ // If this is the beginning of the output file, write the symbol format info.
+ //
+ if (fseek (DestFile, 0, SEEK_END) != 0) {
+ fclose (SourceFile);
+ fclose (DestFile);
+ Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
+ return EFI_ABORTED;
+ }
+
+ StartLocation = ftell (DestFile);
+
+ if (StartLocation == 0) {
+ fprintf (DestFile, "TEXTSYM format | V1.0\n");
+ } else if (StartLocation == -1) {
+ fclose (SourceFile);
+ fclose (DestFile);
+ Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");
+ return EFI_ABORTED;
+ }
+
+ //
+ // 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);
+ fclose (DestFile);
+ Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
+ 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) {
+
+ //
+ // Get the token address
+ //
+ AsciiStringToUint64 (Address, TRUE, &TokenAddress);
+
+ //
+ // Add the base address, the size of the FFS file header and the size of the peim header.
+ //
+ TokenAddress += BaseAddress &~IPF_CACHE_BIT;
+
+#ifdef __GNUC__
+ fprintf (DestFile, "%s | %016lX | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);
+#else
+ fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);
+#endif
+ }
+ }
+
+ fclose (SourceFile);
+ fclose (DestFile);
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+CalculateFitTableChecksum (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function will perform byte checksum on the FIT table, if the the checksum required
+ field is set to CheckSum required. If the checksum is not required then checksum byte
+ will have value as 0;.
+
+Arguments:
+
+ NONE
+
+Returns:
+
+ Status - Value returned by call to CalculateChecksum8 ()
+ EFI_SUCCESS - The function completed successfully
+
+--*/
+{
+ FIT_TABLE *TmpFitPtr;
+ UINT64 FitTableAdd;
+ UINT64 FitTableAddOffset;
+ UINTN RelativeAddress;
+ UINTN Size;
+
+ //
+ // Read the Fit Table address from Itanium-based address map.
+ //
+ FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
+
+ //
+ // Translate this Itanium-based address in terms of local buffer address which
+ // contains the image for Boot Strapped File
+ //
+ GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
+ FitTableAdd = *(UINTN *) RelativeAddress;
+
+ GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
+
+ TmpFitPtr = (FIT_TABLE *) RelativeAddress;
+
+ Size = TmpFitPtr->CompSize * 16;
+
+ if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
+ TmpFitPtr->CheckSum = 0;
+ TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);
+ } else {
+ TmpFitPtr->CheckSum = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+VOID
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the standard utility information to SDTOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
+}
+
+VOID
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n");
+ //
+ // Details Option
+ //
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, " -f Input_file, --filename Input_file\n\
+ Input_file is name of the BS Image INF file\n");
+ fprintf (stdout, " -r BaseAddress, --baseaddr BaseAddress\n\
+ BaseAddress is the starting address of Firmware Volume\n\
+ where Boot Strapped Image will reside.\n");
+ fprintf (stdout, " -s FwVolumeSize, --size FwVolumeSize\n\
+ FwVolumeSize is the size of Firmware Volume.\n");
+ fprintf (stdout, " -o FileName, --output FileName\n\
+ File will be created to store the ouput content.\n");
+ fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
+ fprintf (stdout, " --version Show program's version number and exit.\n");
+ fprintf (stdout, " -h, --help Show this help message and exit.\n");
+ fprintf (stdout, " -q, --quiet Disable all messages except FATAL ERRORS.\n");
+ fprintf (stdout, " -d, --debug [#, 0-9] Enable debug messages at level #.\n");
+}
+
+int
+main (
+ IN int argc,
+ IN char **argv
+ )
+/*++
+
+Routine Description:
+
+ This utility uses GenVtf.dll to build a Boot Strap File Image which will be
+ part of firmware volume image.
+
+Arguments:
+
+ argc - The count of the parameters
+ argv - The parameters
+
+
+Returns:
+
+ 0 - No error conditions detected.
+ 1 - One or more of the input parameters is invalid.
+ 2 - A resource required by the utility was unavailable.
+ - Most commonly this will be memory allocation or file creation.
+ 3 - GenFvImage.dll could not be loaded.
+ 4 - Error executing the GenFvImage dll.
+ 5 - Now this tool does not support the IA32 platform
+
+--*/
+{
+ UINT8 Index;
+ UINT64 StartAddress1;
+ UINT64 StartAddress2;
+ UINT64 FwVolSize1;
+ UINT64 FwVolSize2;
+ BOOLEAN FirstRoundO;
+ BOOLEAN FirstRoundB;
+ BOOLEAN FirstRoundS;
+ EFI_STATUS Status;
+ FILE *VtfFP;
+ CHAR8 *VtfFileName;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Initialize variables
+ //
+ StartAddress1 = 0;
+ StartAddress2 = 0;
+ FwVolSize1 = 0;
+ FwVolSize2 = 0;
+ FirstRoundB = TRUE;
+ FirstRoundS = TRUE;
+ FirstRoundO = TRUE;
+ DebugMode = FALSE;
+ OutFileName1 = NULL;
+ OutFileName2 = NULL;
+ VtfFP = NULL;
+ DebugLevel = 0;
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc == 1) {
+ Usage();
+ return 0;
+ }
+
+ if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
+ Usage();
+ return 0;
+ }
+
+ if ((strcmp(argv[1], "--version") == 0)) {
+ Version();
+ return 0;
+ }
+
+ //
+ // Parse the command line arguments
+ //
+ for (Index = 1; Index < argc; Index += 2) {
+ if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {
+ if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
+ goto ERROR;
+ }
+ //
+ // Get the output file name
+ //
+ VTF_OUTPUT = TRUE;
+ if (FirstRoundO) {
+ //
+ // It's the first output file name
+ //
+ OutFileName1 = (CHAR8 *)argv[Index+1];
+ FirstRoundO = FALSE;
+ } else {
+ //
+ //It's the second output file name
+ //
+ OutFileName2 = (CHAR8 *)argv[Index+1];
+ }
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {
+ if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
+ goto ERROR;
+ }
+ //
+ // Get the input VTF file name
+ //
+ VtfFileName = argv[Index+1];
+ VtfFP = fopen(VtfFileName, "rb");
+ if (VtfFP == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", VtfFileName);
+ goto ERROR;
+ }
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {
+ if (FirstRoundB) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
+ FirstRoundB = FALSE;
+ } else {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
+ }
+ if (Status != EFI_SUCCESS) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);
+ goto ERROR;
+ }
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {
+ if (FirstRoundS) {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
+ FirstRoundS = FALSE;
+ } else {
+ Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
+ SecondVTF = TRUE;
+ }
+
+ if (Status != EFI_SUCCESS) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);
+ goto ERROR;
+ }
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
+ VerboseMode = TRUE;
+ Index--;
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
+ QuietMode = TRUE;
+ Index--;
+ continue;
+ }
+
+ if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
+ //
+ // debug level specified
+ //
+ Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);
+ goto ERROR;
+ }
+ if (DebugLevel > 9) {
+ Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);
+ goto ERROR;
+ }
+ if((DebugLevel <= 9) &&(DebugLevel >= 5)) {
+ DebugMode = TRUE;
+ } else {
+ DebugMode = FALSE;
+ }
+ continue;
+ }
+
+ Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);
+ goto ERROR;
+ }
+
+ if (VtfFP == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
+ goto ERROR;
+ }
+
+ if (FirstRoundB) {
+ Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");
+ goto ERROR;
+ }
+
+ if (FirstRoundS) {
+ Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");
+ goto ERROR;
+ }
+ //
+ // All Parameters has been parsed, now set the message print level
+ //
+ if (QuietMode) {
+ SetPrintLevel(40);
+ } else if (VerboseMode) {
+ SetPrintLevel(15);
+ } else if (DebugMode) {
+ SetPrintLevel(DebugLevel);
+ }
+
+ if (VerboseMode) {
+ VerboseMsg("%s tool start.\n", UTILITY_NAME);
+ }
+
+ if (VTF_OUTPUT == FALSE) {
+ if (SecondVTF == TRUE) {
+ OutFileName1 = VTF_OUTPUT_FILE1;
+ OutFileName2 = VTF_OUTPUT_FILE2;
+ } else {
+ OutFileName1 = VTF_OUTPUT_FILE1;
+ }
+ SymFileName = VTF_SYM_FILE;
+ } else {
+ INTN OutFileNameLen = strlen(OutFileName1);
+ INTN Index;
+
+ for (Index = OutFileNameLen; Index > 0; --Index) {
+ if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') {
+ break;
+ }
+ }
+ if (Index == 0) {
+ SymFileName = VTF_SYM_FILE;
+ } else {
+ INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE);
+ SymFileName = malloc(SymFileNameLen + 1);
+ memcpy(SymFileName, OutFileName1, Index + 1);
+ memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));
+ SymFileName[SymFileNameLen] = '\0';
+ }
+ if (DebugMode) {
+ DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);
+ }
+ }
+
+ //
+ // Call the GenVtfImage
+ //
+ if (DebugMode) {
+ DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);
+ }
+ Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);
+
+ if (EFI_ERROR (Status)) {
+ switch (Status) {
+
+ case EFI_INVALID_PARAMETER:
+ Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
+ break;
+
+ case EFI_ABORTED:
+ Error (NULL, 0, 3000, "Invaild", "Error detected while creating the file image.");
+ break;
+
+ case EFI_OUT_OF_RESOURCES:
+ Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
+ break;
+
+ case EFI_VOLUME_CORRUPTED:
+ Error (NULL, 0, 3000, "Invaild", "No base address was specified.");
+ break;
+
+ default:
+ Error (NULL, 0, 3000, "Invaild", "GenVtfImage function returned unknown status %x.",Status );
+ break;
+ }
+ }
+ERROR:
+ if (VtfFP != NULL) {
+ fclose (VtfFP);
+ }
+
+ if (DebugMode) {
+ DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);
+ }
+
+ if (VerboseMode) {
+ VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
+ }
+ return GetUtilityStatus();
+}