From 30fdf1140b8d1ce93f3821d986fa165552023440 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Fri, 17 Jul 2009 09:10:31 +0000 Subject: Check In tool source code based on Build tool project revision r1655. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524 --- BaseTools/Source/C/GenVtf/GNUmakefile | 10 + BaseTools/Source/C/GenVtf/GenVtf.c | 2721 +++++++++++++++++++++++++++++++++ BaseTools/Source/C/GenVtf/GenVtf.h | 330 ++++ BaseTools/Source/C/GenVtf/Makefile | 10 + 4 files changed, 3071 insertions(+) create mode 100644 BaseTools/Source/C/GenVtf/GNUmakefile create mode 100644 BaseTools/Source/C/GenVtf/GenVtf.c create mode 100644 BaseTools/Source/C/GenVtf/GenVtf.h create mode 100644 BaseTools/Source/C/GenVtf/Makefile (limited to 'BaseTools/Source/C/GenVtf') diff --git a/BaseTools/Source/C/GenVtf/GNUmakefile b/BaseTools/Source/C/GenVtf/GNUmakefile new file mode 100644 index 0000000000..2449bb8ed5 --- /dev/null +++ b/BaseTools/Source/C/GenVtf/GNUmakefile @@ -0,0 +1,10 @@ +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = GenVtf + +LIBS = -lCommon + +OBJECTS = GenVtf.o + +include $(MAKEROOT)/Makefiles/app.makefile 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 +#include +#include "GenVtf.h" +#include +#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(); +} diff --git a/BaseTools/Source/C/GenVtf/GenVtf.h b/BaseTools/Source/C/GenVtf/GenVtf.h new file mode 100644 index 0000000000..25ce1141ba --- /dev/null +++ b/BaseTools/Source/C/GenVtf/GenVtf.h @@ -0,0 +1,330 @@ +/** @file + +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.h + +Abstract: + + This file contains the relevant declarations required + to generate Boot Strap File + +**/ + +// +// Module Coded to EFI 2.0 Coding Conventions +// +#ifndef __GEN_VTF_H__ +#define __GEN_VTF_H__ + +// +// External Files Referenced +// +#include +#include +#include +#include "assert.h" +#include +#include "ParseInf.h" + +// +// Internal Constants +// +#define CV_N_TYPE(a,b) (UINT8)(((UINT8)a << 7) + (UINT8)b) // Keeps the CV and Type in same byte field +#define MAKE_VERSION(a,b) (UINT16)(((UINT16)a << 8) + (UINT16)b) + +#define FILE_NAME_SIZE 256 +#define COMPONENT_NAME_SIZE 128 +#define VTF_INPUT_FILE "VTF.INF" +#define VTF_OUTPUT_FILE1 "VTF1.RAW" +#define VTF_OUTPUT_FILE2 "VTF2.RAW" +#define VTF_SYM_FILE "Vtf.SYM" +#define FIT_SIGNATURE "_FIT_ " + +// +//Fit Type Definition +// +#define COMP_TYPE_FIT_HEADER 0x00 +#define COMP_TYPE_FIT_PAL_B 0x01 + +// +// This is generic PAL_A +// +#define COMP_TYPE_FIT_PAL_A 0x0F +#define COMP_TYPE_FIT_PEICORE 0x10 +#define COMP_TYPE_FIT_AUTOSCAN 0x30 +#define COMP_TYPE_FIT_FV_BOOT 0x7E + +// +//This is processor Specific PAL_A +// +#define COMP_TYPE_FIT_PAL_A_SPECIFIC 0x0E +#define COMP_TYPE_FIT_UNUSED 0x7F + +#define FIT_TYPE_MASK 0x7F +#define CHECKSUM_BIT_MASK 0x80 + +// +// IPF processor address is cached bit +// +#define IPF_CACHE_BIT 0x8000000000000000ULL + +// +// Size definition to calculate the location from top of address for +// each component +// +#define SIZE_IA32_RESET_VECT 0x10 // 16 Bytes +#define SIZE_SALE_ENTRY_POINT 0x08 // 8 Byte +#define SIZE_FIT_TABLE_ADD 0x08 // 8 Byte +#define SIZE_FIT_TABLE_PAL_A 0x10 +#define SIZE_RESERVED 0x10 + + +#define SIZE_TO_OFFSET_PAL_A_END (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \ + SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A + \ + SIZE_RESERVED) +#define SIZE_TO_PAL_A_FIT (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + \ + SIZE_FIT_TABLE_ADD + SIZE_FIT_TABLE_PAL_A) + +#define SIZE_OF_PAL_HEADER 0x40 //PAL has 64 byte header + +// +// Utility Name +// +#define UTILITY_NAME "GenVtf" + +// +// 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 ONE_VTF_ARGS 10 +#define TWO_VTF_ARGS 12 +#define THREE_VTF_ARGS 16 + +static BOOLEAN VerboseMode = FALSE; + +// +// Internal Data Structure +// +typedef enum _LOC_TYPE +{ + NONE, // In case there is - INF file + FIRST_VTF, // First VTF + SECOND_VTF, // Outside VTF +} LOC_TYPE; + +typedef struct _PARSED_VTF_INFO { + CHAR8 CompName[COMPONENT_NAME_SIZE]; + LOC_TYPE LocationType; + UINT8 CompType; + UINT8 MajorVer; + UINT8 MinorVer; + UINT8 CheckSumRequired; + BOOLEAN VersionPresent; // If it is TRUE, then, Version is in INF file + BOOLEAN PreferredSize; + BOOLEAN PreferredAddress; + CHAR8 CompBinName[FILE_NAME_SIZE]; + CHAR8 CompSymName[FILE_NAME_SIZE]; + UINTN CompSize; + UINT64 CompPreferredAddress; + UINT32 Align; + + // + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // Fixed - warning C4133: '=' : incompatible types - from 'struct _ParsedVtfInfo *' to 'struct _PARSED_VTF_INFO *' + // + struct _PARSED_VTF_INFO *NextVtfInfo; +} PARSED_VTF_INFO; + +#pragma pack (1) +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; +#pragma pack () + +// +// Function Prototype Declarations +// + +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 + +Returns: + + EFI_ABORTED - The input parameter is error + EFI_SUCCESS - The function completed successfully + +--*/ +; + +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. + +--*/ +; + +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 + +--*/ +; + +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 + +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 +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 + +--*/ +; + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; +#endif diff --git a/BaseTools/Source/C/GenVtf/Makefile b/BaseTools/Source/C/GenVtf/Makefile new file mode 100644 index 0000000000..0d6a8d134b --- /dev/null +++ b/BaseTools/Source/C/GenVtf/Makefile @@ -0,0 +1,10 @@ +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenVtf + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenVtf.obj + +!INCLUDE ..\Makefiles\ms.app + -- cgit v1.2.3