mirror of https://github.com/acidanthera/audk.git
3520 lines
86 KiB
C
3520 lines
86 KiB
C
/*++
|
|
|
|
Copyright (c) 1999 - 2006, 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:
|
|
|
|
GenBsfImage.c
|
|
|
|
Abstract:
|
|
|
|
This file contains functions required to generate a boot strap file (BSF)
|
|
also known as the Volume Top File (VTF)
|
|
|
|
--*/
|
|
|
|
//
|
|
// Module Coded to EFI 2.0 Coding Conventions
|
|
//
|
|
#include <FvLib.h>
|
|
#include <Common/UefiBaseTypes.h>
|
|
#include "GenBsfImage.h"
|
|
#include <Guid/FirmwareFileSystem.h>
|
|
#include "CommonLib.h"
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
EFI_GUID Bsf1NameGuid = EFI_IPF_VTF1_GUID
|
|
EFI_GUID Bsf2NameGuid = EFI_IPF_VTF2_GUID
|
|
|
|
CHAR8 **TokenStr;
|
|
CHAR8 **OrgStrTokPtr;
|
|
|
|
PARSED_BSF_INFO *FileListPtr;
|
|
PARSED_BSF_INFO *FileListHeadPtr;
|
|
|
|
VOID *Bsf1Buffer;
|
|
VOID *Bsf1EndBuffer;
|
|
VOID *Bsf2Buffer;
|
|
VOID *Bsf2EndBuffer;
|
|
|
|
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 BSF Present, if yes then will be used
|
|
// to decide about adding FFS header to pad data
|
|
//
|
|
BOOLEAN BSFPresent = FALSE;
|
|
|
|
//
|
|
// Address related information
|
|
//
|
|
UINT64 Fv1BaseAddress = 0;
|
|
UINT64 Fv2BaseAddress = 0;
|
|
UINT64 Fv1EndAddress = 0;
|
|
UINT64 Fv2EndAddress = 0;
|
|
UINT32 Bsf1TotalSize = SIZE_TO_OFFSET_PAL_A_END;
|
|
UINT64 Bsf1LastStartAddress = 0;
|
|
UINT32 Bsf2TotalSize = 0;
|
|
UINT64 Bsf2LastStartAddress = 0;
|
|
|
|
UINT32 BufferToTop = 0;
|
|
|
|
//
|
|
// IA32 Reset Vector Bin name
|
|
//
|
|
CHAR8 IA32BinFile[FILE_NAME_SIZE];
|
|
|
|
//
|
|
// Function Implementations
|
|
//
|
|
VOID
|
|
BuildTokenList (
|
|
IN CHAR8 *Token
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This function builds the token list in an array which will be parsed later
|
|
|
|
Arguments:
|
|
|
|
Token - The pointer of string
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
strcpy (*TokenStr, Token);
|
|
TokenStr++;
|
|
}
|
|
|
|
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;
|
|
UINTN Major;
|
|
UINTN 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')) {
|
|
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++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
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];
|
|
CHAR8 OrgLine[FILE_NAME_SIZE];
|
|
CHAR8 Str[FILE_NAME_SIZE];
|
|
CHAR8 Delimit[] = "=";
|
|
|
|
while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
|
|
strcpy (OrgLine, Buff);
|
|
TrimLine (Buff);
|
|
if (Buff[0] == 0) {
|
|
continue;
|
|
}
|
|
|
|
Token = strtok (Buff, Delimit);
|
|
|
|
while (Token != NULL) {
|
|
strcpy (Str, Token);
|
|
BuildTokenList (Str);
|
|
Token = strtok (NULL, Delimit);
|
|
}
|
|
}
|
|
}
|
|
|
|
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 BSF symbol file.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - The function completed successfully
|
|
EFI_OUT_OF_RESOURCES - Malloc failed.
|
|
|
|
--*/
|
|
{
|
|
|
|
FileListPtr = malloc (sizeof (PARSED_BSF_INFO));
|
|
|
|
if (FileListPtr == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
FileListHeadPtr = FileListPtr;
|
|
memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
|
|
FileListPtr->NextBsfInfo = NULL;
|
|
|
|
remove (BSF_SYM_FILE);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
ParseAndUpdateComponents (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function intializes the relevant global variable which is being
|
|
used to store the information retrieved from INF file.
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - A pointer to the BSF Info Structure
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
UINT64 StringValue;
|
|
|
|
while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
|
|
|
|
if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "F") == 0) {
|
|
BsfInfo->LocationType = FIRST_VTF;
|
|
} else if (_stricmp (*TokenStr, "S") == 0) {
|
|
BsfInfo->LocationType = SECOND_VTF;
|
|
} else {
|
|
BsfInfo->LocationType = NONE;
|
|
printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
|
|
}
|
|
} else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
|
|
TokenStr++;
|
|
if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
|
|
printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
|
|
return ;
|
|
}
|
|
|
|
BsfInfo->CompType = (UINT8) StringValue;
|
|
} else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "-") == 0) {
|
|
BsfInfo->VersionPresent = FALSE;
|
|
BsfInfo->MajorVer = 0;
|
|
BsfInfo->MinorVer = 0;
|
|
} else {
|
|
BsfInfo->VersionPresent = TRUE;
|
|
ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
|
|
}
|
|
} else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
|
|
TokenStr++;
|
|
strcpy (BsfInfo->CompBinName, *TokenStr);
|
|
} else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
|
|
TokenStr++;
|
|
strcpy (BsfInfo->CompSymName, *TokenStr);
|
|
} else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "-") == 0) {
|
|
BsfInfo->PreferredSize = FALSE;
|
|
BsfInfo->CompSize = 0;
|
|
} else {
|
|
BsfInfo->PreferredSize = TRUE;
|
|
if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
|
|
printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
|
|
return ;
|
|
}
|
|
|
|
BsfInfo->CompSize = (UINTN) StringValue;
|
|
}
|
|
|
|
} else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "1") == 0) {
|
|
BsfInfo->CheckSumRequired = 1;
|
|
} else if (_stricmp (*TokenStr, "0") == 0) {
|
|
BsfInfo->CheckSumRequired = 0;
|
|
} else {
|
|
printf ("\nERROR: Bad information in INF file about Checksum required field");
|
|
}
|
|
}
|
|
|
|
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
|
|
|
|
--*/
|
|
{
|
|
UINTN SectionOptionFlag;
|
|
UINTN SectionCompFlag;
|
|
|
|
SectionOptionFlag = 0;
|
|
SectionCompFlag = 0;
|
|
TokenStr = OrgStrTokPtr;
|
|
while (*TokenStr != NULL) {
|
|
if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
|
|
SectionOptionFlag = 1;
|
|
SectionCompFlag = 0;
|
|
}
|
|
|
|
if (_stricmp (*TokenStr, "[COMPONENTS]") == 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->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
|
|
if (FileListPtr->NextBsfInfo == NULL) {
|
|
printf ("Error: Out of memory resources.\n");
|
|
break;
|
|
}
|
|
FileListPtr = FileListPtr->NextBsfInfo;
|
|
memset (FileListPtr, 0, sizeof (PARSED_BSF_INFO));
|
|
FileListPtr->NextBsfInfo = NULL;
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
TokenStr++;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetBsfRelatedInfoFromInfFile (
|
|
IN CHAR8 *FileName
|
|
)
|
|
/*++
|
|
|
|
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 BSF
|
|
|
|
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 informations
|
|
EFI_OUT_OF_RESOURCES - Malloc Failed
|
|
EFI_SUCCESS - The function completed successfully
|
|
|
|
--*/
|
|
{
|
|
FILE *Fp;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
Fp = fopen (FileName, "r");
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Error in opening %s file\n", FileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
ValidLineCount (Fp);
|
|
|
|
if (ValidLineNum == 0) {
|
|
printf ("\nERROR: File doesn't contain any valid informations");
|
|
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) {
|
|
free (OrgStrTokPtr);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
memset (*TokenStr, 0, FILE_NAME_SIZE);
|
|
// free (*TokenStr);
|
|
TokenStr++;
|
|
}
|
|
|
|
TokenStr = NULL;
|
|
TokenStr = OrgStrTokPtr;
|
|
fseek (Fp, 0L, SEEK_SET);
|
|
|
|
Status = InitializeComps ();
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
free (OrgStrTokPtr);
|
|
return Status;
|
|
}
|
|
|
|
ParseInputFile (Fp);
|
|
InitializeInFileInfo ();
|
|
|
|
if (Fp) {
|
|
fclose (Fp);
|
|
}
|
|
free (OrgStrTokPtr);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
GetRelativeAddressInBsfBuffer (
|
|
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 BSF
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
--*/
|
|
{
|
|
UINT64 TempAddress;
|
|
UINT8 *LocalBuff;
|
|
|
|
if (LocType == FIRST_VTF) {
|
|
LocalBuff = (UINT8 *) Bsf1EndBuffer;
|
|
TempAddress = Fv1EndAddress - Address;
|
|
*RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
|
|
} else {
|
|
LocalBuff = (UINT8 *) Bsf2EndBuffer;
|
|
TempAddress = Fv2EndAddress - Address;
|
|
*RelativeAddress = (UINTN) LocalBuff - (UINTN) TempAddress;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetComponentVersionInfo (
|
|
IN OUT PARSED_BSF_INFO *BsfInfo,
|
|
IN UINT8 *Buffer
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
This function will extract the version information from File
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - A Pointer to the BSF 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 (BsfInfo->CompType) {
|
|
|
|
case COMP_TYPE_FIT_PAL_A:
|
|
case COMP_TYPE_FIT_PAL_B:
|
|
memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));
|
|
BsfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);
|
|
BsfInfo->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 BSF 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 BSF buffer.
|
|
//
|
|
GetRelativeAddressInBsfBuffer (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 BSF
|
|
// Buffer.
|
|
//
|
|
GetRelativeAddressInBsfBuffer (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 BSF buffer.
|
|
//
|
|
GetRelativeAddressInBsfBuffer (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 BSF
|
|
// Buffer.
|
|
//
|
|
GetRelativeAddressInBsfBuffer (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;
|
|
}
|
|
|
|
INTN
|
|
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 informations 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
|
|
//
|
|
Bsf1LastStartAddress -= 0x10;
|
|
Bsf1TotalSize += 0x10;
|
|
|
|
GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &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 BSF component will reside outside the BSF, we will not have its
|
|
// binary image while creating BSF, hence we will not perform checksum at
|
|
// this time. Once Firmware Volume is being created which will contain this
|
|
// BSF, it will fix the FIT table for all the non BSF component and hence
|
|
// checksum
|
|
//
|
|
CompFitPtr->CheckSum = 0;
|
|
}
|
|
|
|
EFI_STATUS
|
|
UpdateFitEntryForNonBSFComp (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function updates the information about non BSF component in FIT TABLE.
|
|
Since non BSF componets binaries are not part of BSF binary, we would still
|
|
be required to update its location information in Firmware Volume, inside
|
|
FIT table.
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - Pointer to BSF 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) {
|
|
printf ("\nERROR: 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 = BsfInfo->CompSize;
|
|
CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
|
|
CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
|
|
|
|
//
|
|
// Since non BSF component will reside outside the BSF, we will not have its
|
|
// binary image while creating BSF, hence we will not perform checksum at
|
|
// this time. Once Firmware Volume is being created which will contain this
|
|
// BSF, it will fix the FIT table for all the non BSF 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 BSF 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_BSF_INFO *BsfInfo,
|
|
IN UINT64 *CompStartAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function updated the architectural entry point in IPF, SALE_ENTRY.
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - Pointer to BSF 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 (BsfInfo->CompSymName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Error in opening file");
|
|
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 (_stricmp (Token, "SALE_ENTRY") == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
Offset = strtoul (OffsetStr, NULL, 16);
|
|
|
|
*CompStartAddress += Offset;
|
|
SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
|
|
|
|
GetRelativeAddressInBsfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
|
|
|
|
memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateAndUpdateComponent (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the binary file for each components and update them
|
|
in BSF Buffer as well as in FIT table. If the component is located in non
|
|
BSF area, only the FIT table address will be updated
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - 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 (BsfInfo->LocationType == NONE) {
|
|
UpdateFitEntryForNonBSFComp (BsfInfo);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Fp = fopen (BsfInfo->CompBinName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = _filelength (fileno (Fp));
|
|
|
|
if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
|
|
|
|
//
|
|
// BUGBUG: Satish to correct
|
|
//
|
|
FileSize -= SIZE_OF_PAL_HEADER;
|
|
}
|
|
|
|
if (BsfInfo->PreferredSize) {
|
|
if (FileSize > BsfInfo->CompSize) {
|
|
printf ("\nERROR: The component size is more than specified size");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = BsfInfo->CompSize;
|
|
}
|
|
|
|
Buffer = malloc ((UINTN) FileSize);
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Buffer, 0, (UINTN) FileSize);
|
|
|
|
if ((BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (BsfInfo->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 (!BsfInfo->VersionPresent) {
|
|
GetComponentVersionInfo (BsfInfo, 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 (BsfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
|
|
if (!BsfInfo->VersionPresent) {
|
|
GetComponentVersionInfo (BsfInfo, Buffer);
|
|
}
|
|
}
|
|
|
|
if (BsfInfo->LocationType == SECOND_VTF) {
|
|
|
|
CompStartAddress = (Bsf2LastStartAddress - FileSize);
|
|
} else {
|
|
CompStartAddress = (Bsf1LastStartAddress - FileSize);
|
|
}
|
|
|
|
if (BsfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
|
|
Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
|
|
} else {
|
|
Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
|
|
}
|
|
|
|
if (!Aligncheck) {
|
|
CompStartAddress -= NumAdjustByte;
|
|
}
|
|
|
|
if (BsfInfo->LocationType == SECOND_VTF) {
|
|
Bsf2LastStartAddress = CompStartAddress;
|
|
Bsf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
|
|
Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
|
|
} else {
|
|
Bsf1LastStartAddress = CompStartAddress;
|
|
Bsf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
|
|
Status = UpdateBsfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
GetNextAvailableFitPtr (&CompFitPtr);
|
|
|
|
CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
|
|
assert ((FileSize % 16) == 0);
|
|
CompFitPtr->CompSize = (UINT32) (FileSize / 16);
|
|
CompFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
|
|
CompFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
|
|
if (BsfInfo->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, BSF_SYM_FILE, BsfInfo->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
|
|
// BSF till we work out how to determine the SALE_ENTRY through it. We will need
|
|
// to clarify so many related questions
|
|
// !!!!!!!!!!!!!!!!!!!!!!!
|
|
if (BsfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
|
|
Status = UpdateEntryPoint (BsfInfo, &CompStartAddress);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateAndUpdatePAL_A (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the binary file for each components and update them
|
|
in BSF Buffer as well as FIT table
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - 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 (BsfInfo->CompBinName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = _filelength (fileno (Fp));
|
|
FileSize -= SIZE_OF_PAL_HEADER;
|
|
|
|
if (BsfInfo->PreferredSize) {
|
|
if (FileSize > BsfInfo->CompSize) {
|
|
printf ("\nERROR: The PAL_A Size is more than specified size");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = BsfInfo->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 (!BsfInfo->VersionPresent) {
|
|
GetComponentVersionInfo (BsfInfo, 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);
|
|
Bsf1LastStartAddress = PalStartAddress;
|
|
Bsf1TotalSize += (UINT32) FileSize;
|
|
Status = UpdateBsfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
|
|
|
|
AbsAddress = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
|
|
GetRelativeAddressInBsfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
|
|
PalFitPtr = (FIT_TABLE *) RelativeAddress;
|
|
PalFitPtr->CompAddress = PalStartAddress | IPF_CACHE_BIT;
|
|
assert ((FileSize % 16) == 0);
|
|
PalFitPtr->CompSize = (UINT32) (FileSize / 16);
|
|
PalFitPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->MinorVer);
|
|
PalFitPtr->CvAndType = CV_N_TYPE (BsfInfo->CheckSumRequired, BsfInfo->CompType);
|
|
if (BsfInfo->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, BSF_SYM_FILE, BsfInfo->CompSymName);
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
//
|
|
// At this time, SYM files are not required, so continue on error.
|
|
//
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateFitTableAndInitialize (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function creates and intializes FIT table which would be used to
|
|
add component info inside this
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - 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 (!BsfInfo->PreferredSize) {
|
|
printf ("\nERROR: FIT could not be allocated becuase there are no size information");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if ((BsfInfo->CompSize % 16) != 0) {
|
|
printf ("\nERROR: Invalid Fit Table Size, not multiple of 16 bytes. Please correct the size");
|
|
}
|
|
|
|
PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
|
|
GetRelativeAddressInBsfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
|
|
PalFitPtr = (FIT_TABLE *) RelativeAddress;
|
|
PalFitTableAdd = (PalFitPtr->CompAddress - BsfInfo->CompSize);
|
|
|
|
FitTableAdd = (PalFitPtr->CompAddress - 0x10) - BsfInfo->CompSize;
|
|
FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
|
|
GetRelativeAddressInBsfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
|
|
*(UINT64 *) RelativeAddress = FitTableAdd;
|
|
|
|
GetRelativeAddressInBsfBuffer (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 (((BsfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
|
|
FitStartPtr->CompSize = (BsfInfo->CompSize & 0x00FFFFFF) / 16;
|
|
FitStartPtr->CompVersion = MAKE_VERSION (BsfInfo->MajorVer, BsfInfo->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 (BsfInfo->CheckSumRequired, BsfInfo->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++;
|
|
}
|
|
|
|
Bsf1TotalSize += BsfInfo->CompSize;
|
|
Bsf1LastStartAddress -= BsfInfo->CompSize;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
WriteBsfBinary (
|
|
IN CHAR8 *FileName,
|
|
IN UINT32 BsfSize,
|
|
IN LOC_TYPE LocType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write Firmware Volume from memory to a file.
|
|
|
|
Arguments:
|
|
|
|
FileName - Output File Name which needed to be created/
|
|
BsfSize - FileSize
|
|
LocType - The type of the BSF
|
|
|
|
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 *BsfBuffer;
|
|
UINTN RelativeAddress;
|
|
|
|
if (LocType == FIRST_VTF) {
|
|
GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
|
|
BsfBuffer = (VOID *) RelativeAddress;
|
|
} else {
|
|
GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &RelativeAddress, SECOND_VTF);
|
|
BsfBuffer = (VOID *) RelativeAddress;
|
|
}
|
|
|
|
Fp = fopen (FileName, "w+b");
|
|
if (Fp == NULL) {
|
|
printf ("Error in opening file %s\n", FileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
NumByte = fwrite (BsfBuffer, sizeof (UINT8), (UINTN) BsfSize, Fp);
|
|
|
|
if (Fp) {
|
|
fclose (Fp);
|
|
}
|
|
|
|
if (NumByte != (sizeof (UINT8) * BsfSize)) {
|
|
printf ("\nERROR: Could not copy buffer into file %s ", FileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
UpdateBsfBuffer (
|
|
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 BSF
|
|
|
|
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) < (Bsf1LastStartAddress | IPF_CACHE_BIT)) {
|
|
printf ("ERROR: Start Address is less then the BSF start address\n");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
LocalBufferPtrToWrite = (UINT8 *) Bsf1EndBuffer;
|
|
LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
|
|
} else {
|
|
if ((StartAddress | IPF_CACHE_BIT) < (Bsf2LastStartAddress | IPF_CACHE_BIT)) {
|
|
printf ("ERROR: Start Address is less then the BSF start address\n");
|
|
return EFI_ABORTED;
|
|
}
|
|
LocalBufferPtrToWrite = (UINT8 *) Bsf2EndBuffer;
|
|
LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
|
|
}
|
|
|
|
memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
UpdateFfsHeader (
|
|
IN UINT32 TotalBsfSize,
|
|
IN LOC_TYPE LocType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update the Firmware Volume Buffer with requested buffer data
|
|
|
|
Arguments:
|
|
|
|
TotalBsfSize - Size of the BSF
|
|
Fileoffset - The start of the file relative to the start of the FV.
|
|
LocType - The type of the BSF
|
|
|
|
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 BSF file header location
|
|
//
|
|
if (LocType == FIRST_VTF) {
|
|
GetRelativeAddressInBsfBuffer (Bsf1LastStartAddress, &RelativeAddress, FIRST_VTF);
|
|
FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
|
|
} else {
|
|
GetRelativeAddressInBsfBuffer (Bsf2LastStartAddress, &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_FREEFORM;
|
|
FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
|
|
|
|
//
|
|
// Now FileSize includes the EFI_FFS_FILE_HEADER
|
|
//
|
|
FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
|
|
FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
|
|
FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 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, TotalBsfSize);
|
|
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 BSF 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 BSF 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 *LocalBsfBuffer;
|
|
UINTN FileSize;
|
|
UINTN NumByteRead;
|
|
FILE *Fp;
|
|
|
|
if (!strcmp (FileName, "")) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Fp = fopen (FileName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Unable to open the file %s", FileName);
|
|
}
|
|
|
|
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);
|
|
|
|
LocalBsfBuffer = (UINT8 *) Bsf1EndBuffer - SIZE_IA32_RESET_VECT;
|
|
memcpy (LocalBsfBuffer, Buffer, FileSize);
|
|
|
|
if (Buffer) {
|
|
free (Buffer);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
CleanUpMemory (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function cleans up any allocated buffer
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Returns:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
PARSED_BSF_INFO *TempFileListPtr;
|
|
|
|
if (Bsf1Buffer) {
|
|
free (Bsf1Buffer);
|
|
}
|
|
|
|
if (Bsf2Buffer) {
|
|
free (Bsf2Buffer);
|
|
}
|
|
|
|
//
|
|
// Cleanup the buffer which was allocated to read the file names from FV.INF
|
|
//
|
|
FileListPtr = FileListHeadPtr;
|
|
while (FileListPtr != NULL) {
|
|
TempFileListPtr = FileListPtr->NextBsfInfo;
|
|
free (FileListPtr);
|
|
FileListPtr = TempFileListPtr;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
ProcessAndCreateBsf (
|
|
IN UINT64 Size
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function process the link list created during INF file parsing
|
|
and create component in BSF and updates its info in FIT table
|
|
|
|
Arguments:
|
|
|
|
Size - Size of the Firmware Volume of which, this BSF belongs to.
|
|
|
|
Returns:
|
|
|
|
EFI_UNSUPPORTED - Unknown FIT type
|
|
EFI_SUCCESS - The function completed successfully
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
PARSED_BSF_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:
|
|
Status = CreateFitTableAndInitialize (ParsedInfoPtr);
|
|
break;
|
|
|
|
//
|
|
// COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
|
|
//
|
|
case COMP_TYPE_FIT_PAL_A:
|
|
Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
|
|
|
|
//
|
|
// Based on BSF 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 BSF will be
|
|
// of part.
|
|
//
|
|
if (Status == EFI_SUCCESS) {
|
|
UpdateFitEntryForFwVolume (Size);
|
|
}
|
|
break;
|
|
|
|
case COMP_TYPE_FIT_FV_BOOT:
|
|
//
|
|
// 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 BSF and create appropriate entry about this
|
|
// component in FIT Entry.
|
|
//
|
|
Status = CreateAndUpdateComponent (ParsedInfoPtr);
|
|
if (EFI_ERROR (Status)) {
|
|
printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
|
|
}
|
|
break;
|
|
}
|
|
|
|
ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GenerateBsfImage (
|
|
IN UINT64 StartAddress1,
|
|
IN UINT64 Size1,
|
|
IN UINT64 StartAddress2,
|
|
IN UINT64 Size2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the main function which will be called from application.
|
|
|
|
Arguments:
|
|
|
|
StartAddress1 - The start address of the first BSF
|
|
Size1 - The size of the first BSF
|
|
StartAddress2 - The start address of the second BSF
|
|
Size2 - The size of the second BSF
|
|
|
|
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:
|
|
GetBsfRelatedInfoFromInfFile
|
|
ProcessAndCreateBsf
|
|
UpdateIA32ResetVector
|
|
UpdateFfsHeader
|
|
WriteBsfBinary
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
CHAR8 OutFileName1[FILE_NAME_SIZE];
|
|
CHAR8 OutFileName2[FILE_NAME_SIZE];
|
|
BOOLEAN SecondBSF;
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
if (StartAddress2 == 0) {
|
|
SecondBSF = FALSE;
|
|
} else {
|
|
SecondBSF = TRUE;
|
|
}
|
|
Fv1BaseAddress = StartAddress1;
|
|
Fv1EndAddress = Fv1BaseAddress + Size1;
|
|
|
|
memset (OutFileName1, 0, FILE_NAME_SIZE);
|
|
sprintf (
|
|
OutFileName1,
|
|
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
|
|
Bsf1NameGuid.Data1,
|
|
Bsf1NameGuid.Data2,
|
|
Bsf1NameGuid.Data3,
|
|
Bsf1NameGuid.Data4[0],
|
|
Bsf1NameGuid.Data4[1],
|
|
Bsf1NameGuid.Data4[2],
|
|
Bsf1NameGuid.Data4[3],
|
|
Bsf1NameGuid.Data4[4],
|
|
Bsf1NameGuid.Data4[5],
|
|
Bsf1NameGuid.Data4[6],
|
|
Bsf1NameGuid.Data4[7],
|
|
BSF_OUTPUT_FILE
|
|
);
|
|
|
|
//
|
|
// The image buffer for the First BSF
|
|
//
|
|
Bsf1Buffer = malloc ((UINTN) Size1);
|
|
if (Bsf1Buffer == NULL) {
|
|
printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Bsf1Buffer, 0x00, (UINTN) Size1);
|
|
Bsf1EndBuffer = (UINT8 *) Bsf1Buffer + Size1;
|
|
Bsf1LastStartAddress = Fv1EndAddress | IPF_CACHE_BIT;
|
|
|
|
if (SecondBSF) {
|
|
Fv2BaseAddress = StartAddress2;
|
|
Fv2EndAddress = Fv2BaseAddress + Size2;
|
|
|
|
memset (OutFileName2, 0, FILE_NAME_SIZE);
|
|
sprintf (
|
|
OutFileName2,
|
|
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
|
|
Bsf2NameGuid.Data1,
|
|
Bsf2NameGuid.Data2,
|
|
Bsf2NameGuid.Data3,
|
|
Bsf2NameGuid.Data4[0],
|
|
Bsf2NameGuid.Data4[1],
|
|
Bsf2NameGuid.Data4[2],
|
|
Bsf2NameGuid.Data4[3],
|
|
Bsf2NameGuid.Data4[4],
|
|
Bsf2NameGuid.Data4[5],
|
|
Bsf2NameGuid.Data4[6],
|
|
Bsf2NameGuid.Data4[7],
|
|
BSF_OUTPUT_FILE
|
|
);
|
|
|
|
//
|
|
// The image buffer for the second BSF
|
|
//
|
|
Bsf2Buffer = malloc ((UINTN) Size2);
|
|
if (Bsf2Buffer == NULL) {
|
|
printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Bsf2Buffer, 0x00, (UINTN) Size2);
|
|
Bsf2EndBuffer = (UINT8 *) Bsf2Buffer + Size2;
|
|
Bsf2LastStartAddress = Fv2EndAddress | IPF_CACHE_BIT;
|
|
}
|
|
|
|
Status = GetBsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
|
|
if (Status != EFI_SUCCESS) {
|
|
printf ("\nERROR: Error in parsing input file");
|
|
CleanUpMemory ();
|
|
return Status;
|
|
}
|
|
|
|
Status = ProcessAndCreateBsf (Size1);
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory ();
|
|
return Status;
|
|
}
|
|
|
|
Status = UpdateIA32ResetVector (IA32BinFile, Bsf1TotalSize);
|
|
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
|
|
//
|
|
Bsf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
|
|
Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
|
|
Status = UpdateFfsHeader (Bsf1TotalSize, FIRST_VTF);
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory ();
|
|
return Status;
|
|
}
|
|
//
|
|
// Update the BSF buffer into specified BSF binary file
|
|
//
|
|
Status = WriteBsfBinary (OutFileName1, Bsf1TotalSize, FIRST_VTF);
|
|
|
|
if (SecondBSF) {
|
|
Bsf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
|
|
Bsf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
|
|
Status = UpdateFfsHeader (Bsf2TotalSize, SECOND_VTF);
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory ();
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Update the BSF buffer into specified BSF binary file
|
|
//
|
|
Status = WriteBsfBinary (OutFileName2, Bsf2TotalSize, SECOND_VTF);
|
|
}
|
|
|
|
CleanUpMemory ();
|
|
printf ("\n");
|
|
|
|
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;
|
|
CHAR8 OutFileName1[FILE_NAME_SIZE];
|
|
|
|
StartAddressPtr = malloc (sizeof (UINT64));
|
|
if (StartAddressPtr == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
*StartAddressPtr = StartAddress;
|
|
|
|
memset (OutFileName1, 0, FILE_NAME_SIZE);
|
|
|
|
sprintf (
|
|
OutFileName1,
|
|
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
|
|
Bsf1NameGuid.Data1,
|
|
Bsf1NameGuid.Data2,
|
|
Bsf1NameGuid.Data3,
|
|
Bsf1NameGuid.Data4[0],
|
|
Bsf1NameGuid.Data4[1],
|
|
Bsf1NameGuid.Data4[2],
|
|
Bsf1NameGuid.Data4[3],
|
|
Bsf1NameGuid.Data4[4],
|
|
Bsf1NameGuid.Data4[5],
|
|
Bsf1NameGuid.Data4[6],
|
|
Bsf1NameGuid.Data4[7],
|
|
BSF_OUTPUT_FILE
|
|
);
|
|
|
|
Fp = fopen (OutFileName1, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Error opening file ");
|
|
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);
|
|
}
|
|
|
|
printf ("\n");
|
|
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);
|
|
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);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
StartLocation = ftell (DestFile);
|
|
|
|
if (StartLocation == 0) {
|
|
fprintf (DestFile, "TEXTSYM format | V1.0\n");
|
|
} else if (StartLocation == -1) {
|
|
fclose (SourceFile);
|
|
fclose (DestFile);
|
|
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);
|
|
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;
|
|
|
|
fprintf (DestFile, "%s | %016I64X | %s | %s%s\n", Type, TokenAddress, Section, BaseToken, Token);
|
|
}
|
|
}
|
|
|
|
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
|
|
//
|
|
GetRelativeAddressInBsfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
|
|
FitTableAdd = *(UINTN *) RelativeAddress;
|
|
|
|
GetRelativeAddressInBsfBuffer (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
|
|
PrintUtilityInfo (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the standard utility information to SDTOUT
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
printf (
|
|
"%s, EFI 2.0 BootStrap File Generation Utility. Version %i.%i, %s.\n\n",
|
|
UTILITY_NAME,
|
|
UTILITY_MAJOR_VERSION,
|
|
UTILITY_MINOR_VERSION,
|
|
UTILITY_DATE
|
|
);
|
|
}
|
|
|
|
VOID
|
|
PrintUsage (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Displays the utility usage syntax to STDOUT
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
printf (
|
|
"Usage: %s -B BaseAddress -S FwVolumeSize\n",
|
|
UTILITY_NAME
|
|
);
|
|
printf (" Where:\n");
|
|
printf ("\tBaseAddress is the starting address of Firmware Volume where\n\tBoot Strapped Image will reside.\n\n");
|
|
printf ("\tFwVolumeSize is the size of Firmware Volume.\n\n");
|
|
}
|
|
|
|
EFI_STATUS
|
|
main (
|
|
IN UINTN argc,
|
|
IN CHAR8 **argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This utility uses GenBsfImage.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 FirstRoundB;
|
|
BOOLEAN FirstRoundS;
|
|
EFI_STATUS Status;
|
|
BOOLEAN IsIA32;
|
|
|
|
//
|
|
// Display utility information
|
|
//
|
|
PrintUtilityInfo ();
|
|
|
|
//
|
|
// Verify the correct number of IA32 arguments
|
|
//
|
|
IsIA32 = FALSE;
|
|
if (argc == IA32_ARGS) {
|
|
//
|
|
// Now this tool is not used for IA32 platform, if it will be used in future,
|
|
// the IA32-specific functions need to be updated and verified, the updating can
|
|
// refer to IPF relevant functions)
|
|
//
|
|
printf ("ERROR: Now this tool does not support the IA32 platform!\n");
|
|
printf ("ERROR: And the IA32-specific functions need to be updated and verified!\n");
|
|
return 5;
|
|
|
|
/*
|
|
StartAddress1 = 0;
|
|
IsIA32 = TRUE;
|
|
|
|
//
|
|
// Parse the command line arguments
|
|
//
|
|
for (Index = 1; Index < IA32_ARGS; Index += 2) {
|
|
|
|
//
|
|
// Make sure argument pair begin with - or /
|
|
//
|
|
if (argv[Index][0] != '-' && argv[Index][0] != '/') {
|
|
PrintUsage ();
|
|
printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Make sure argument specifier is only one letter
|
|
//
|
|
if (argv[Index][2] != 0) {
|
|
PrintUsage ();
|
|
printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Determine argument to read
|
|
//
|
|
switch (argv[Index][1]) {
|
|
|
|
case 't':
|
|
case 'T':
|
|
Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
|
|
if (Status != EFI_SUCCESS) {
|
|
printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
PrintUsage ();
|
|
printf ("Unrecognized IA32 argument \"%s\".\n", argv[Index]);
|
|
IsIA32 = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (IsIA32) {
|
|
//
|
|
// Call the GenBsfImage
|
|
//
|
|
Status = Generate32BsfImage (StartAddress1);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
switch (Status) {
|
|
|
|
case EFI_INVALID_PARAMETER:
|
|
printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
|
|
break;
|
|
|
|
case EFI_ABORTED:
|
|
printf ("\nERROR: Error detected while creating the file image.\n");
|
|
break;
|
|
|
|
case EFI_OUT_OF_RESOURCES:
|
|
printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
|
|
break;
|
|
|
|
case EFI_VOLUME_CORRUPTED:
|
|
printf ("\nERROR: No base address was specified \n");
|
|
break;
|
|
|
|
default:
|
|
printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
|
|
break;
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
*/
|
|
}
|
|
|
|
//
|
|
// Verify the correct number of arguments
|
|
//
|
|
if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {
|
|
PrintUsage ();
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Initialize variables
|
|
//
|
|
StartAddress1 = 0;
|
|
StartAddress2 = 0;
|
|
FwVolSize1 = 0;
|
|
FwVolSize2 = 0;
|
|
FirstRoundB = TRUE;
|
|
FirstRoundS = TRUE;
|
|
|
|
//
|
|
// Parse the command line arguments
|
|
//
|
|
for (Index = 1; Index < argc; Index += 2) {
|
|
|
|
//
|
|
// Make sure argument pair begin with - or /
|
|
//
|
|
if (argv[Index][0] != '-' && argv[Index][0] != '/') {
|
|
PrintUsage ();
|
|
printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Make sure argument specifier is only one letter
|
|
//
|
|
if (argv[Index][2] != 0) {
|
|
PrintUsage ();
|
|
printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Determine argument to read
|
|
//
|
|
switch (argv[Index][1]) {
|
|
|
|
case 'B':
|
|
case 'b':
|
|
if (FirstRoundB) {
|
|
Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
|
|
FirstRoundB = FALSE;
|
|
} else {
|
|
Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
|
|
}
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
printf ("\nERROR: Bad start of address \"%s\"\n", argv[Index + 1]);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
case 'S':
|
|
case 's':
|
|
if (FirstRoundS) {
|
|
Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
|
|
FirstRoundS = FALSE;
|
|
} else {
|
|
Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
|
|
}
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
printf ("\nERROR: Bad size \"%s\"\n", argv[Index + 1]);
|
|
return 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
PrintUsage ();
|
|
printf ("ERROR: Unrecognized argument \"%s\".\n", argv[Index]);
|
|
return 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Call the GenBsfImage
|
|
//
|
|
Status = GenerateBsfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
switch (Status) {
|
|
|
|
case EFI_INVALID_PARAMETER:
|
|
printf ("\nERROR: Invalid parameter passed to GenBsfImage function .\n");
|
|
break;
|
|
|
|
case EFI_ABORTED:
|
|
printf ("\nERROR: Error detected while creating the file image.\n");
|
|
break;
|
|
|
|
case EFI_OUT_OF_RESOURCES:
|
|
printf ("\nERROR: GenBsfImage function could not allocate required resources.\n");
|
|
break;
|
|
|
|
case EFI_VOLUME_CORRUPTED:
|
|
printf ("\nERROR: No base address was specified \n");
|
|
break;
|
|
|
|
default:
|
|
printf ("\nERROR: GenBsfImage function returned unknown status %X.\n", Status);
|
|
break;
|
|
}
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
EFI_STATUS
|
|
Generate32BsfImage (
|
|
IN UINT64 BootFileStartAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the main IA32 function which will be called from application.
|
|
(Now this tool is not used for IA32 platform, if it will be used in future,
|
|
the relative functions need to be updated, the updating can refer to IPF
|
|
functions)
|
|
|
|
Arguments:
|
|
|
|
BootFileStartAddress - Top Address of Boot File
|
|
|
|
Returns:
|
|
|
|
The return value can be any of the values
|
|
returned by the calls to following functions:
|
|
Get32BsfRelatedInfoFromInfFile
|
|
CreateBsfBuffer
|
|
ProcessAndCreate32Bsf
|
|
Update32FfsHeader
|
|
WriteBsfBinary
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 BsfSize;
|
|
CHAR8 OutFileName[FILE_NAME_SIZE];
|
|
|
|
EFI_GUID BsfNameGuid = EFI_IA32_BOOT_STRAP_GUID;
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
memset (OutFileName, 0, FILE_NAME_SIZE);
|
|
|
|
sprintf (
|
|
OutFileName, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s",
|
|
BsfNameGuid.Data1,
|
|
BsfNameGuid.Data2,
|
|
BsfNameGuid.Data3,
|
|
BsfNameGuid.Data4[0],
|
|
BsfNameGuid.Data4[1],
|
|
BsfNameGuid.Data4[2],
|
|
BsfNameGuid.Data4[3],
|
|
BsfNameGuid.Data4[4],
|
|
BsfNameGuid.Data4[5],
|
|
BsfNameGuid.Data4[6],
|
|
BsfNameGuid.Data4[7],
|
|
BSF_OUTPUT_FILE
|
|
);
|
|
|
|
|
|
Status = Get32BsfRelatedInfoFromInfFile (BSF_INPUT_FILE);
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
printf ("\nERROR: Error in parsing input file");
|
|
CleanUpMemory ();
|
|
return Status;
|
|
}
|
|
|
|
if (GetTotal32BsfSize (&BsfSize) == EFI_SUCCESS) {
|
|
Bsf1Buffer = malloc ((UINTN) BsfSize);
|
|
if (Bsf1Buffer == NULL) {
|
|
printf ("\nERROR: Not enough resource to create memory mapped file for Boot Strap File");
|
|
CleanUpMemory ();
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Bsf1Buffer, 0x00, (UINTN) BsfSize);
|
|
} else {
|
|
printf ("\nERROR: Could not get BSF size.");
|
|
CleanUpMemory ();
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
//VTF must align properly
|
|
//
|
|
Bsf1LastStartAddress = BootFileStartAddress - BsfSize;
|
|
Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
|
|
BsfSize = (UINT32)BootFileStartAddress - (UINT32)Bsf1LastStartAddress;
|
|
Bsf1LastStartAddress = BsfSize;
|
|
BufferToTop = (UINT32)BootFileStartAddress - BsfSize;
|
|
|
|
Status = ProcessAndCreate32Bsf (BsfSize);
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory();
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Write the FFS header
|
|
//
|
|
Status = Update32FfsHeader (BsfSize);
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory();
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Calculate the Start address of this BSF
|
|
//
|
|
Bsf1Buffer = (UINT8 *)Bsf1Buffer + Bsf1LastStartAddress;
|
|
|
|
//
|
|
// Update the BSF buffer into specified BSF binary file
|
|
//
|
|
Status = WriteBsfBinary (OutFileName, BsfSize - (UINT32)Bsf1LastStartAddress, FIRST_VTF);
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory();
|
|
return Status;
|
|
}
|
|
|
|
Status = Write32SoftFit (IA32_SOFT_FIT, FileListHeadPtr);
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
CleanUpMemory();
|
|
return Status;
|
|
}
|
|
|
|
CleanUpMemory ();
|
|
printf ("\n");
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetTotal32BsfSize(
|
|
IN UINT32 *BsfSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calculates total size for IA32 BSF which would be needed to create
|
|
the buffer. This will be done using Passed Info link list and looking for the
|
|
size of the components which belong to BSF. The addtional file header is accounted.
|
|
|
|
Arguments:
|
|
|
|
BSFSize - Pointer to the size of IA32 BSF
|
|
|
|
Returns:
|
|
|
|
EFI_ABORTED - Returned due to one of the following resons:
|
|
(a) Error Opening File
|
|
EFI_SUCCESS - The fuction completes successfully
|
|
|
|
--*/
|
|
{
|
|
PARSED_BSF_INFO *BsfInfo;
|
|
FILE *Fp;
|
|
UINT32 Alignment;
|
|
|
|
*BsfSize = 0;
|
|
Alignment = 0;
|
|
|
|
BsfInfo = FileListHeadPtr;
|
|
|
|
while (BsfInfo != NULL) {
|
|
if (BsfInfo->LocationType != SECOND_VTF) {
|
|
|
|
if ( BsfInfo->Align ) {
|
|
//
|
|
// Create additional align to compensate for component boundary requirements
|
|
//
|
|
Alignment = 1 << BsfInfo->Align;
|
|
*BsfSize += Alignment;
|
|
}
|
|
|
|
if (BsfInfo->PreferredSize) {
|
|
*BsfSize += BsfInfo->CompSize;
|
|
} else {
|
|
Fp = fopen (BsfInfo->CompBinName,"r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Error in opening file %s", BsfInfo->CompBinName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
*BsfSize += _filelength (fileno (Fp));
|
|
|
|
if (Fp) {
|
|
fclose (Fp);
|
|
}
|
|
}
|
|
}
|
|
BsfInfo = BsfInfo->NextBsfInfo;
|
|
}
|
|
|
|
//
|
|
// Add file header space
|
|
//
|
|
*BsfSize += sizeof (EFI_FFS_FILE_HEADER);
|
|
|
|
//
|
|
// Create additional to IA32 Seccore section header
|
|
//
|
|
*BsfSize += sizeof (EFI_COMMON_SECTION_HEADER);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
ProcessAndCreate32Bsf (
|
|
IN UINT64 Size
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function process the link list created during INF file parsing
|
|
and create component in IA32 BSF
|
|
|
|
Arguments:
|
|
|
|
Size - Size of the Firmware Volume of which, this BSF belongs to.
|
|
|
|
Returns:
|
|
|
|
EFI_UNSUPPORTED - Unknown component type
|
|
EFI_SUCCESS - The function completed successfully
|
|
|
|
--*/
|
|
{
|
|
EFI_STATUS Status;
|
|
PARSED_BSF_INFO *ParsedInfoPtr;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
ParsedInfoPtr = FileListHeadPtr;
|
|
|
|
while (ParsedInfoPtr != NULL) {
|
|
|
|
switch (ParsedInfoPtr->CompType) {
|
|
|
|
case COMP_TYPE_SECCORE:
|
|
Status = CreateAndUpdateSeccore (ParsedInfoPtr);
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Any other component type should be handled here. This will create the
|
|
// image in specified BSF
|
|
//
|
|
Status = CreateAndUpdate32Component (ParsedInfoPtr);
|
|
if (EFI_ERROR(Status)) {
|
|
printf ("ERROR: Updating %s component.\n", ParsedInfoPtr->CompName);
|
|
}
|
|
break;
|
|
}
|
|
|
|
ParsedInfoPtr = ParsedInfoPtr->NextBsfInfo;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateAndUpdateSeccore (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the binary file for seccore and update them
|
|
in IA32 BSF Buffer
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - 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.
|
|
|
|
--*/
|
|
{
|
|
UINT8 *SecbinStartAddress;
|
|
UINT8 *SecfileStartAddress;
|
|
UINT32 FileSize;
|
|
UINT64 NumByteRead;
|
|
UINT8 *Buffer;
|
|
FILE *Fp;
|
|
UINT64 TotalLength;
|
|
EFI_COMMON_SECTION_HEADER *SecHeader;
|
|
|
|
Fp = fopen (BsfInfo->CompBinName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Opening file %s", BsfInfo->CompBinName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = _filelength (fileno (Fp));
|
|
|
|
if (BsfInfo->PreferredSize) {
|
|
if (FileSize > BsfInfo->CompSize) {
|
|
printf("\nERROR: The Seccore Size is more than specified size");
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = BsfInfo->CompSize;
|
|
}
|
|
|
|
BsfInfo->CompSize = FileSize;
|
|
|
|
Buffer = malloc ((UINTN) FileSize);
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Buffer, 0, (UINTN) FileSize);
|
|
|
|
//
|
|
// Read seccore in a buffer
|
|
//
|
|
NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
|
|
fclose (Fp);
|
|
|
|
SecfileStartAddress = (UINT8 *) Bsf1Buffer + Bsf1LastStartAddress - FileSize - sizeof (EFI_COMMON_SECTION_HEADER);
|
|
if (SecfileStartAddress == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
SecbinStartAddress = SecfileStartAddress + sizeof (EFI_COMMON_SECTION_HEADER);
|
|
|
|
BsfInfo->CompPreferredAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
|
|
|
|
//
|
|
// write section header
|
|
//
|
|
memset (SecfileStartAddress, 0, sizeof (EFI_COMMON_SECTION_HEADER));
|
|
SecHeader = (EFI_COMMON_SECTION_HEADER *) SecfileStartAddress;
|
|
SecHeader->Type = EFI_SECTION_RAW;
|
|
TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + (UINT64) FileSize;
|
|
memcpy (SecHeader->Size, &TotalLength, 3);
|
|
|
|
//
|
|
// write seccore
|
|
//
|
|
memcpy (SecbinStartAddress, Buffer, (UINTN) FileSize);
|
|
|
|
if (Buffer) {
|
|
free (Buffer);
|
|
}
|
|
|
|
Bsf1LastStartAddress = SecfileStartAddress - (UINT8 *) Bsf1Buffer;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
CreateAndUpdate32Component (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads the binary file for each components. Add it at aligned address.
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - 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 failed.
|
|
|
|
--*/
|
|
{
|
|
UINT64 CompStartAddress;
|
|
UINT32 FileSize;
|
|
UINT64 NumByteRead;
|
|
UINT8 *Buffer;
|
|
FILE *Fp;
|
|
UINT8 *LocalBufferPtrToWrite;
|
|
UINT64 Alignment;
|
|
|
|
Fp = fopen (BsfInfo->CompBinName, "r+b");
|
|
|
|
if (Fp == NULL) {
|
|
printf("\nERROR: Opening file %s", BsfInfo->CompBinName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
FileSize = _filelength (fileno (Fp));
|
|
|
|
if (BsfInfo->PreferredSize) {
|
|
if (FileSize > BsfInfo->CompSize) {
|
|
printf("\nERROR: The component size is more than specified size");
|
|
return EFI_ABORTED;
|
|
}
|
|
FileSize = BsfInfo->CompSize;
|
|
}
|
|
BsfInfo->CompSize = FileSize;
|
|
|
|
Buffer = malloc ((UINTN) FileSize);
|
|
if (Buffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
memset (Buffer,0, (UINTN) FileSize);
|
|
|
|
NumByteRead = fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
|
|
fclose (Fp);
|
|
|
|
CompStartAddress = Bsf1LastStartAddress - FileSize + BufferToTop;
|
|
|
|
if (BsfInfo->Align) {
|
|
//
|
|
// Create additional align to compensate for component boundary requirements
|
|
//
|
|
Alignment = 0 - (1 << BsfInfo->Align);
|
|
CompStartAddress = CompStartAddress & Alignment;
|
|
}
|
|
|
|
BsfInfo->CompPreferredAddress = CompStartAddress;
|
|
|
|
//
|
|
// write bin
|
|
//
|
|
LocalBufferPtrToWrite = (UINT8 *) Bsf1Buffer;
|
|
Bsf1LastStartAddress = CompStartAddress - BufferToTop;
|
|
LocalBufferPtrToWrite += Bsf1LastStartAddress;
|
|
memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) FileSize);
|
|
Bsf1LastStartAddress = CompStartAddress - BufferToTop;
|
|
|
|
//
|
|
// Free the buffer
|
|
//
|
|
if (Buffer) {
|
|
free (Buffer);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
Update32FfsHeader(
|
|
IN UINT32 BsfSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Update the Firmware Volume Buffer with requested buffer data
|
|
|
|
Arguments:
|
|
|
|
BsfSize - Size of the IA32 BSF
|
|
|
|
Returns:
|
|
|
|
EFI_SUCCESS - The function completed successfully
|
|
EFI_INVALID_PARAMETER - The Ffs File Header Pointer is NULL
|
|
|
|
--*/
|
|
{
|
|
EFI_FFS_FILE_HEADER *FileHeader;
|
|
UINT32 TotalBsfSize;
|
|
EFI_GUID EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
|
|
|
|
|
|
//
|
|
// Find the BSF file header location, the bsf file must be 8 bytes aligned
|
|
//
|
|
Bsf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
|
|
Bsf1LastStartAddress += BufferToTop;
|
|
Bsf1LastStartAddress = Bsf1LastStartAddress & -8;
|
|
Bsf1LastStartAddress -= BufferToTop;
|
|
FileHeader = (EFI_FFS_FILE_HEADER*)((UINT8*)Bsf1Buffer + Bsf1LastStartAddress);
|
|
|
|
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_FREEFORM;
|
|
FileHeader->Attributes = FFS_ATTRIB_CHECKSUM;
|
|
|
|
//
|
|
// Now FileSize includes the EFI_FFS_FILE_HEADER
|
|
//
|
|
TotalBsfSize = BsfSize - (UINT32)Bsf1LastStartAddress;
|
|
FileHeader->Size[0] = (UINT8) (TotalBsfSize & 0x000000FF);
|
|
FileHeader->Size[1] = (UINT8) ((TotalBsfSize & 0x0000FF00) >> 8);
|
|
FileHeader->Size[2] = (UINT8) ((TotalBsfSize & 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, TotalBsfSize);
|
|
FileHeader->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
Get32BsfRelatedInfoFromInfFile (
|
|
IN CHAR8 *FileName
|
|
)
|
|
/*++
|
|
|
|
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 IA32 BSF
|
|
|
|
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 informations
|
|
EFI_OUT_OF_RESOURCES Malloc Failed
|
|
EFI_SUCCESS The function completed successfully
|
|
|
|
--*/
|
|
{
|
|
FILE *Fp;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
Fp = fopen (FileName, "r");
|
|
if (Fp == NULL) {
|
|
printf ("\nERROR: Error in opening %s file\n", FileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
ValidLineCount (Fp);
|
|
|
|
if (ValidLineNum == 0) {
|
|
printf ("\nERROR: File doesn't contain any valid informations");
|
|
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) {
|
|
free (OrgStrTokPtr);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
memset (*TokenStr, 0, FILE_NAME_SIZE);
|
|
// free (*TokenStr);
|
|
TokenStr++;
|
|
}
|
|
|
|
TokenStr = NULL;
|
|
TokenStr = OrgStrTokPtr;
|
|
fseek (Fp, 0L, SEEK_SET);
|
|
|
|
Status = InitializeComps();
|
|
|
|
if (Status != EFI_SUCCESS) {
|
|
free (TokenStr);
|
|
return Status;
|
|
}
|
|
ParseInputFile (Fp);
|
|
Initialize32InFileInfo ();
|
|
|
|
if (Fp) {
|
|
fclose (Fp);
|
|
}
|
|
free (TokenStr);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
Initialize32InFileInfo (
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function intializes the relevant global variable which is being
|
|
used to store the information retrieved from IA32 INF file.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Returns:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
{
|
|
UINTN SectionOptionFlag;
|
|
UINTN SectionCompFlag;
|
|
|
|
SectionOptionFlag =0 ;
|
|
SectionCompFlag = 0;
|
|
TokenStr = OrgStrTokPtr;
|
|
while (*TokenStr != NULL) {
|
|
if (_stricmp (*TokenStr, "[OPTIONS]") == 0) {
|
|
SectionOptionFlag = 1;
|
|
SectionCompFlag = 0;
|
|
}
|
|
|
|
if (_stricmp (*TokenStr, "[COMPONENTS]") == 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++;
|
|
ParseAndUpdate32Components (FileListPtr);
|
|
}
|
|
|
|
if (*TokenStr != NULL) {
|
|
FileListPtr->NextBsfInfo = malloc (sizeof (PARSED_BSF_INFO));
|
|
if (FileListPtr->NextBsfInfo == NULL) {
|
|
printf ("Error: Out of memory resources.\n");
|
|
break;
|
|
}
|
|
FileListPtr = FileListPtr->NextBsfInfo;
|
|
memset (FileListPtr, 0, sizeof(PARSED_BSF_INFO));
|
|
FileListPtr->NextBsfInfo = NULL;
|
|
continue;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
TokenStr++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ParseAndUpdate32Components (
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function intializes the relevant global variable which is being
|
|
used to store the information retrieved from INF file.
|
|
|
|
Arguments:
|
|
|
|
BsfInfo - A pointer to the BSF Info Structure
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
UINT64 StringValue;
|
|
UINT64 AlignStringValue;
|
|
|
|
while (*TokenStr != NULL && (_stricmp (*TokenStr, "COMP_NAME") != 0)) {
|
|
|
|
if (_stricmp (*TokenStr, "COMP_LOC") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "B") == 0) {
|
|
BsfInfo->LocationType = FIRST_VTF;
|
|
} else if (_stricmp (*TokenStr, "N") == 0) {
|
|
BsfInfo->LocationType = SECOND_VTF;
|
|
} else {
|
|
BsfInfo->LocationType = NONE;
|
|
printf ("\nERROR: Unknown location for component %s", BsfInfo->CompName);
|
|
}
|
|
} else if (_stricmp (*TokenStr, "COMP_TYPE") == 0) {
|
|
TokenStr++;
|
|
if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
|
|
printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
|
|
return;
|
|
}
|
|
BsfInfo->CompType = (UINT8) StringValue;
|
|
} else if (_stricmp (*TokenStr, "COMP_VER") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "-") == 0) {
|
|
BsfInfo->VersionPresent = FALSE;
|
|
BsfInfo->MajorVer = 0;
|
|
BsfInfo->MinorVer = 0;
|
|
} else {
|
|
BsfInfo->VersionPresent = TRUE;
|
|
ConvertVersionInfo (*TokenStr, &BsfInfo->MajorVer, &BsfInfo->MinorVer);
|
|
}
|
|
} else if (_stricmp (*TokenStr, "COMP_BIN") == 0) {
|
|
TokenStr++;
|
|
strcpy (BsfInfo->CompBinName, *TokenStr);
|
|
} else if (_stricmp (*TokenStr, "COMP_SYM") == 0) {
|
|
TokenStr++;
|
|
strcpy (BsfInfo->CompSymName, *TokenStr);
|
|
} else if (_stricmp (*TokenStr, "COMP_SIZE") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "-") == 0) {
|
|
BsfInfo->PreferredSize = FALSE;
|
|
BsfInfo->CompSize = 0;
|
|
} else {
|
|
BsfInfo->PreferredSize = TRUE;
|
|
if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
|
|
printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
|
|
return;
|
|
}
|
|
BsfInfo->CompSize = (UINTN) StringValue;
|
|
}
|
|
|
|
} else if (_stricmp (*TokenStr, "COMP_CS") == 0) {
|
|
TokenStr++;
|
|
if (_stricmp (*TokenStr, "1") == 0) {
|
|
BsfInfo->CheckSumRequired = 1;
|
|
} else if (_stricmp (*TokenStr, "0") == 0) {
|
|
BsfInfo->CheckSumRequired = 0;
|
|
} else {
|
|
printf ("\nERROR: Bad information in INF file about Checksum required field");
|
|
}
|
|
} else if (_stricmp (*TokenStr, "COMP_ALIGN") == 0) {
|
|
TokenStr++;
|
|
if (AsciiStringToUint64 (*TokenStr, FALSE, &AlignStringValue) != EFI_SUCCESS) {
|
|
printf ("\nERROR: Could not read a numeric value from \"%s\".", TokenStr);
|
|
return;
|
|
}
|
|
if (AlignStringValue >= 0) {
|
|
BsfInfo->Align = (UINT32) AlignStringValue;
|
|
} else {
|
|
printf ("\nERROR: invalid align \"%s\".", AlignStringValue);
|
|
return;
|
|
}
|
|
}
|
|
TokenStr++;
|
|
if (*TokenStr == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
Write32SoftFit(
|
|
IN CHAR8 *FileName,
|
|
IN PARSED_BSF_INFO *BsfInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write IA32 Firmware Volume component address from memory to a file.
|
|
|
|
Arguments:
|
|
|
|
FileName Output File Name which needed to be created/
|
|
BsfInfo Parsed info link
|
|
|
|
Returns:
|
|
|
|
EFI_ABORTED - Returned due to one of the following resons:
|
|
(a) Error Opening File
|
|
(b) Failing to copy buffers
|
|
EFI_SUCCESS - The function completes successfully
|
|
|
|
--*/
|
|
{
|
|
FILE *Fp;
|
|
|
|
Fp = fopen (FileName, "w+t");
|
|
if (Fp == NULL) {
|
|
printf ("Error in opening file %s\n", FileName);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
while (BsfInfo != NULL) {
|
|
if (strlen (BsfInfo->CompName) != 0) {
|
|
fprintf (Fp, "\n%s\n", BsfInfo->CompName);
|
|
} else {
|
|
fprintf (Fp, "\n%s\n", "Name not available");
|
|
}
|
|
|
|
fprintf (Fp, "%d\n", BsfInfo->CompPreferredAddress);
|
|
fprintf (Fp, "%d\n", BsfInfo->CompSize);
|
|
fprintf (Fp, "%d\n", BsfInfo->Align);
|
|
|
|
BsfInfo = BsfInfo->NextBsfInfo;
|
|
}
|
|
|
|
if (Fp) {
|
|
fclose (Fp);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|