git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2196 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			3533 lines
		
	
	
		
			87 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			3533 lines
		
	
	
		
			87 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
 | |
| Version (
 | |
|   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.\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
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   Version();
 | |
|   
 | |
|   printf (
 | |
|     "\nUsage: %s -B BaseAddress -S FwVolumeSize\n",
 | |
|     UTILITY_NAME
 | |
|     );
 | |
|   printf ("  Where:\n");
 | |
|   printf ("     BaseAddress is the starting address of Firmware Volume where Boot\n");
 | |
|   printf ("              Strapped Image will reside.\n");
 | |
|   printf ("     FwVolumeSize is the size of Firmware Volume.\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;
 | |
| 
 | |
|   //
 | |
|   // 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] != '/') {
 | |
|         Usage ();
 | |
|         printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
 | |
|         return 1;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Make sure argument specifier is only one letter
 | |
|       //
 | |
|       if (argv[Index][2] != 0) {
 | |
|         Usage ();
 | |
|         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:
 | |
|         Usage ();
 | |
|         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 == 1) {
 | |
|     Usage();
 | |
|     return 1;
 | |
|   }
 | |
|   
 | |
|   if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
 | |
|       (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
 | |
|     Usage();
 | |
|     return 1;
 | |
|   }
 | |
|   
 | |
|   if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
 | |
|     Version();
 | |
|     return 1;
 | |
|   }
 | |
|  
 | |
|   if (argc != ONE_BSF_ARGS && argc != TWO_BSF_ARGS) {
 | |
|     Usage ();
 | |
|     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] != '/') {
 | |
|       Usage ();
 | |
|       printf ("ERROR: Argument pair must begin with \"-\" or \"/\"\n");
 | |
|       return 1;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Make sure argument specifier is only one letter
 | |
|     //
 | |
|     if (argv[Index][2] != 0) {
 | |
|       Usage ();
 | |
|       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:
 | |
|       Usage ();
 | |
|       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;
 | |
| }
 |