Home | History | Annotate | Download | only in GenVtf
      1 /** @file
      2 This file contains functions required to generate a boot strap file (BSF) also
      3 known as the Volume Top File (VTF)
      4 
      5 Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials are licensed and made available
      7 under the terms and conditions of the BSD License which accompanies this
      8 distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 //
     17 //
     18 //
     19 #include <FvLib.h>
     20 #include <Common/UefiBaseTypes.h>
     21 #include "GenVtf.h"
     22 #include <Guid/PiFirmwareFileSystem.h>
     23 #include "CommonLib.h"
     24 #include "EfiUtilityMsgs.h"
     25 
     26 //
     27 // Global variables
     28 //
     29 UINTN SectionOptionFlag = 0;
     30 UINTN SectionCompFlag = 0;
     31 
     32 UINT64        DebugLevel;
     33 BOOLEAN       DebugMode;
     34 
     35 BOOLEAN     QuietMode = FALSE;
     36 
     37 BOOLEAN     VTF_OUTPUT = FALSE;
     38 CHAR8       *OutFileName1;
     39 CHAR8       *OutFileName2;
     40 CHAR8       *SymFileName;
     41 
     42 CHAR8           **TokenStr;
     43 CHAR8           **OrgStrTokPtr;
     44 
     45 PARSED_VTF_INFO *FileListPtr;
     46 PARSED_VTF_INFO *FileListHeadPtr;
     47 
     48 VOID            *Vtf1Buffer;
     49 VOID            *Vtf1EndBuffer;
     50 VOID            *Vtf2Buffer;
     51 VOID            *Vtf2EndBuffer;
     52 
     53 UINTN           ValidLineNum        = 0;
     54 UINTN           ValidFFDFileListNum = 0;
     55 
     56 //
     57 // Section Description and their number of occurences in *.INF file
     58 //
     59 UINTN           NumFvFiles        = 0;
     60 UINTN           SectionOptionNum  = 0;
     61 
     62 //
     63 // Global flag which will check for VTF Present, if yes then will be used
     64 // to decide about adding FFS header to pad data
     65 //
     66 BOOLEAN         VTFPresent = FALSE;
     67 BOOLEAN         SecondVTF = FALSE;
     68 
     69 //
     70 // Address related information
     71 //
     72 UINT64          Fv1BaseAddress        = 0;
     73 UINT64          Fv2BaseAddress        = 0;
     74 UINT64          Fv1EndAddress         = 0;
     75 UINT64          Fv2EndAddress         = 0;
     76 UINT32          Vtf1TotalSize         = SIZE_TO_OFFSET_PAL_A_END;
     77 UINT64          Vtf1LastStartAddress  = 0;
     78 UINT32          Vtf2TotalSize         = 0;
     79 UINT64          Vtf2LastStartAddress  = 0;
     80 
     81 UINT32          BufferToTop           = 0;
     82 
     83 //
     84 // IA32 Reset Vector Bin name
     85 //
     86 CHAR8           IA32BinFile[FILE_NAME_SIZE];
     87 
     88 //
     89 // Function Implementations
     90 //
     91 EFI_STATUS
     92 ConvertVersionInfo (
     93   IN      CHAR8     *Str,
     94   IN OUT  UINT8     *MajorVer,
     95   IN OUT  UINT8     *MinorVer
     96   )
     97 /*++
     98 Routine Description:
     99 
    100   This function split version to major version and minor version
    101 
    102 Arguments:
    103 
    104   Str      - String representing in form XX.XX
    105   MajorVer - The major version
    106   MinorVer - The minor version
    107 
    108 Returns:
    109 
    110   EFI_SUCCESS  - The function completed successfully.
    111 
    112 --*/
    113 {
    114   CHAR8  TemStr[5] = "0000";
    115   unsigned Major;
    116   unsigned Minor;
    117   UINTN Length;
    118 
    119   Major = 0;
    120   Minor = 0;
    121 
    122   if (strstr (Str, ".") != NULL) {
    123     sscanf (
    124       Str,
    125       "%02x.%02x",
    126       &Major,
    127       &Minor
    128       );
    129   } else {
    130     Length = strlen(Str);
    131     if (Length < 4) {
    132       strncpy (TemStr + 4 - Length, Str, Length);
    133     } else {
    134       strncpy (TemStr, Str + Length - 4, 4);
    135     }
    136 
    137     sscanf (
    138       TemStr,
    139       "%02x%02x",
    140       &Major,
    141       &Minor
    142       );
    143   }
    144 
    145   *MajorVer = (UINT8) Major;
    146   *MinorVer = (UINT8) Minor;
    147   return EFI_SUCCESS;
    148 }
    149 
    150 VOID
    151 TrimLine (
    152   IN  CHAR8 *Line
    153   )
    154 /*++
    155 Routine Description:
    156 
    157   This function cleans up the line by removing all whitespace and
    158   comments
    159 
    160 Arguments:
    161 
    162   Line   - The pointer of the string
    163 
    164 Returns:
    165 
    166   None
    167 
    168 --*/
    169 {
    170   CHAR8 TmpLine[FILE_NAME_SIZE];
    171   CHAR8 Char;
    172   CHAR8 *Ptr0;
    173   UINTN Index;
    174   UINTN Index2;
    175 
    176   //
    177   // Change '#' to '//' for Comment style
    178   //
    179   if (((Ptr0 = strchr (Line, '#')) != NULL) || ((Ptr0 = strstr (Line, "//")) != NULL)) {
    180     Line[Ptr0 - Line] = 0;
    181   }
    182 
    183   //
    184   // Initialize counters
    185   //
    186   Index   = 0;
    187   Index2  = 0;
    188 
    189   while ((Char = Line[Index]) != 0) {
    190     if ((Char != ' ') && (Char != '\t') && (Char != '\n') && (Char != '\r')) {
    191       TmpLine[Index2++] = Char;
    192     }
    193     Index++;
    194   }
    195 
    196   TmpLine[Index2] = 0;
    197   strcpy (Line, TmpLine);
    198 }
    199 
    200 VOID
    201 ValidLineCount (
    202   IN  FILE *Fp
    203   )
    204 /*++
    205 
    206 Routine Description:
    207 
    208   This function calculated number of valid lines in a input file.
    209 
    210 Arguments:
    211 
    212   Fp    - Pointer to a file handle which has been opened.
    213 
    214 Returns:
    215 
    216   None
    217 
    218 --*/
    219 {
    220   CHAR8 Buff[FILE_NAME_SIZE];
    221   while (fgets(Buff, sizeof (Buff), Fp)) {
    222     TrimLine (Buff);
    223     if (Buff[0] == 0) {
    224       continue;
    225     }
    226     ValidLineNum++;
    227   }
    228 }
    229 
    230 EFI_STATUS
    231 ParseInputFile (
    232   IN  FILE *Fp
    233   )
    234 /*++
    235 
    236 Routine Description:
    237 
    238   This function parses the input file and tokenize the string
    239 
    240 Arguments:
    241 
    242   Fp    - Pointer to a file handle which has been opened.
    243 
    244 Returns:
    245 
    246   None
    247 
    248 --*/
    249 {
    250   CHAR8 *Token;
    251   CHAR8 Buff[FILE_NAME_SIZE + 1];
    252   CHAR8 Delimit[] = "=";
    253 
    254   Buff [FILE_NAME_SIZE] = '\0';
    255   Token = NULL;
    256 
    257   while (fgets (Buff, FILE_NAME_SIZE, Fp) != NULL) {
    258     TrimLine (Buff);
    259     if (Buff[0] == 0) {
    260       continue;
    261     }
    262     Token = strtok (Buff, Delimit);
    263     while (Token != NULL) {
    264       strcpy (*TokenStr, Token);
    265       TokenStr ++;
    266       Token = strtok (NULL, Delimit);
    267     }
    268   }
    269   return EFI_SUCCESS;
    270 }
    271 
    272 EFI_STATUS
    273 InitializeComps (
    274   VOID
    275   )
    276 /*++
    277 
    278 Routine Description:
    279 
    280   This function initializes the relevant global variable which is being
    281   used to store the information retrieved from INF file.  This also initializes
    282   the VTF symbol file.
    283 
    284 Arguments:
    285 
    286   None
    287 
    288 Returns:
    289 
    290   EFI_SUCCESS            - The function completed successfully
    291   EFI_OUT_OF_RESOURCES   - Malloc failed.
    292 
    293 --*/
    294 {
    295 
    296   FileListPtr = malloc (sizeof (PARSED_VTF_INFO));
    297 
    298   if (FileListPtr == NULL) {
    299     return EFI_OUT_OF_RESOURCES;
    300   }
    301 
    302   FileListHeadPtr = FileListPtr;
    303   memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
    304   FileListPtr->NextVtfInfo = NULL;
    305 
    306   remove (SymFileName);
    307   return EFI_SUCCESS;
    308 }
    309 
    310 VOID
    311 ParseAndUpdateComponents (
    312   IN  PARSED_VTF_INFO   *VtfInfo
    313   )
    314 /*++
    315 
    316 Routine Description:
    317 
    318   This function initializes the relevant global variable which is being
    319   used to store the information retrieved from INF file.
    320 
    321 Arguments:
    322 
    323   VtfInfo  - A pointer to the VTF Info Structure
    324 
    325 
    326 Returns:
    327 
    328   None
    329 
    330 --*/
    331 {
    332   UINT64  StringValue;
    333 
    334   while (*TokenStr != NULL && (strnicmp (*TokenStr, "COMP_NAME", 9) != 0)) {
    335 
    336     if (strnicmp (*TokenStr, "COMP_LOC", 8) == 0) {
    337       TokenStr++;
    338       if (strnicmp (*TokenStr, "F", 1) == 0) {
    339         VtfInfo->LocationType = FIRST_VTF;
    340       } else if (strnicmp (*TokenStr, "S", 1) == 0) {
    341         VtfInfo->LocationType = SECOND_VTF;
    342       } else {
    343         VtfInfo->LocationType = NONE;
    344       }
    345     } else if (strnicmp (*TokenStr, "COMP_TYPE", 9) == 0) {
    346       TokenStr++;
    347       if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
    348         Error (NULL, 0, 5001, "Cannot get: \"0x%s\".", *TokenStr);
    349         return ;
    350       }
    351 
    352       VtfInfo->CompType = (UINT8) StringValue;
    353     } else if (strnicmp (*TokenStr, "COMP_VER", 8) == 0) {
    354       TokenStr++;
    355       if (strnicmp (*TokenStr, "-", 1) == 0) {
    356         VtfInfo->VersionPresent = FALSE;
    357         VtfInfo->MajorVer       = 0;
    358         VtfInfo->MinorVer       = 0;
    359       } else {
    360         VtfInfo->VersionPresent = TRUE;
    361         ConvertVersionInfo (*TokenStr, &VtfInfo->MajorVer, &VtfInfo->MinorVer);
    362       }
    363     } else if (strnicmp (*TokenStr, "COMP_BIN", 8) == 0) {
    364       TokenStr++;
    365       strcpy (VtfInfo->CompBinName, *TokenStr);
    366     } else if (strnicmp (*TokenStr, "COMP_SYM", 8) == 0) {
    367       TokenStr++;
    368       strcpy (VtfInfo->CompSymName, *TokenStr);
    369     } else if (strnicmp (*TokenStr, "COMP_SIZE", 9) == 0) {
    370       TokenStr++;
    371       if (strnicmp (*TokenStr, "-", 1) == 0) {
    372         VtfInfo->PreferredSize  = FALSE;
    373         VtfInfo->CompSize       = 0;
    374       } else {
    375         VtfInfo->PreferredSize = TRUE;
    376         if (AsciiStringToUint64 (*TokenStr, FALSE, &StringValue) != EFI_SUCCESS) {
    377           Error (NULL, 0, 5001, "Parse error", "Cannot get: %s.", TokenStr);
    378           return ;
    379         }
    380 
    381         VtfInfo->CompSize = (UINTN) StringValue;
    382       }
    383 
    384     } else if (strnicmp (*TokenStr, "COMP_CS", 7) == 0) {
    385       TokenStr++;
    386       if (strnicmp (*TokenStr, "1", 1) == 0) {
    387         VtfInfo->CheckSumRequired = 1;
    388       } else if (strnicmp (*TokenStr, "0", 1) == 0) {
    389         VtfInfo->CheckSumRequired = 0;
    390       } else {
    391         Error (NULL, 0, 3000, "Invaild", "Bad value in INF file required field: Checksum, the value must be '0' or '1'.");
    392       }
    393     }
    394 
    395     TokenStr++;
    396     if (*TokenStr == NULL) {
    397       break;
    398     }
    399   }
    400 }
    401 
    402 VOID
    403 InitializeInFileInfo (
    404   VOID
    405   )
    406 /*++
    407 
    408 Routine Description:
    409 
    410   This function intializes the relevant global variable which is being
    411   used to store the information retrieved from INF file.
    412 
    413 Arguments:
    414 
    415   NONE
    416 
    417 Returns:
    418 
    419   NONE
    420 
    421 --*/
    422 {
    423 
    424   SectionOptionFlag = 0;
    425   SectionCompFlag   = 0;
    426   TokenStr          = OrgStrTokPtr;
    427 
    428   while (*TokenStr != NULL) {
    429     if (strnicmp (*TokenStr, "[OPTIONS]", 9) == 0) {
    430       SectionOptionFlag = 1;
    431       SectionCompFlag   = 0;
    432     }
    433 
    434     if (strnicmp (*TokenStr, "[COMPONENTS]", 12) == 0) {
    435       if (FileListPtr == NULL) {
    436         FileListPtr = FileListHeadPtr;
    437       }
    438 
    439       SectionCompFlag   = 1;
    440       SectionOptionFlag = 0;
    441       TokenStr++;
    442     }
    443 
    444     if (SectionOptionFlag) {
    445       if (stricmp (*TokenStr, "IA32_RST_BIN") == 0) {
    446         TokenStr++;
    447         strcpy (IA32BinFile, *TokenStr);
    448       }
    449     }
    450 
    451     if (SectionCompFlag) {
    452       if (stricmp (*TokenStr, "COMP_NAME") == 0) {
    453         TokenStr++;
    454         strcpy (FileListPtr->CompName, *TokenStr);
    455         TokenStr++;
    456         ParseAndUpdateComponents (FileListPtr);
    457       }
    458 
    459       if (*TokenStr != NULL) {
    460         FileListPtr->NextVtfInfo  = malloc (sizeof (PARSED_VTF_INFO));
    461         if (FileListPtr->NextVtfInfo == NULL) {
    462           Error (NULL, 0, 4003, "Resource", "Out of memory resources.", NULL);
    463           break;
    464         }
    465         FileListPtr = FileListPtr->NextVtfInfo;
    466         memset (FileListPtr, 0, sizeof (PARSED_VTF_INFO));
    467         FileListPtr->NextVtfInfo = NULL;
    468         continue;
    469       } else {
    470         break;
    471       }
    472     }
    473 
    474     TokenStr++;
    475   }
    476 }
    477 
    478 EFI_STATUS
    479 GetVtfRelatedInfoFromInfFile (
    480   IN FILE *FilePointer
    481   )
    482 /*++
    483 
    484 Routine Description:
    485 
    486   This function reads the input file, parse it and create a list of tokens
    487   which is parsed and used, to intialize the data related to VTF
    488 
    489 Arguments:
    490 
    491   FileName  - FileName which needed to be read to parse data
    492 
    493 Returns:
    494 
    495   EFI_ABORTED           - Error in opening file
    496   EFI_INVALID_PARAMETER - File doesn't contain any valid information
    497   EFI_OUT_OF_RESOURCES  - Malloc Failed
    498   EFI_SUCCESS           - The function completed successfully
    499 
    500 --*/
    501 {
    502   FILE        *Fp;
    503   UINTN       Index;
    504   UINTN       Index1;
    505   EFI_STATUS  Status;
    506 
    507   Status = EFI_SUCCESS;
    508   Fp = FilePointer;
    509   if (Fp == NULL) {
    510     Error (NULL, 0, 2000, "Invalid parameter", "BSF INF file is invalid!");
    511     return EFI_ABORTED;
    512   }
    513 
    514   ValidLineCount (Fp);
    515 
    516   if (ValidLineNum == 0) {
    517     Error (NULL, 0, 2000, "Invalid parameter", "File does not contain any valid information!");
    518     return EFI_INVALID_PARAMETER;
    519   }
    520 
    521   TokenStr = (CHAR8 **) malloc (sizeof (UINTN) * (2 * ValidLineNum + 1));
    522 
    523   if (TokenStr == NULL) {
    524     return EFI_OUT_OF_RESOURCES;
    525   }
    526 
    527   memset (TokenStr, 0, (sizeof (UINTN) * (2 * ValidLineNum + 1)));
    528   OrgStrTokPtr = TokenStr;
    529 
    530   for (Index = 0; Index < (2 * ValidLineNum); Index++) {
    531     *TokenStr = (CHAR8*)malloc (sizeof (CHAR8) * FILE_NAME_SIZE);
    532 
    533     if (*TokenStr == NULL) {
    534       Status = EFI_OUT_OF_RESOURCES;
    535       goto ParseFileError;
    536     }
    537 
    538     memset (*TokenStr, 0, FILE_NAME_SIZE);
    539     TokenStr++;
    540   }
    541 
    542   TokenStr  = OrgStrTokPtr;
    543   fseek (Fp, 0L, SEEK_SET);
    544 
    545   Status = InitializeComps ();
    546 
    547   if (Status != EFI_SUCCESS) {
    548     goto ParseFileError;
    549   }
    550 
    551   Status = ParseInputFile (Fp);
    552   if (Status != EFI_SUCCESS) {
    553     goto ParseFileError;
    554   }
    555 
    556   InitializeInFileInfo ();
    557 
    558 ParseFileError:
    559 
    560   for (Index1 = 0; Index1 < Index; Index1 ++) {
    561     free (OrgStrTokPtr[Index1]);
    562   }
    563 
    564   free (OrgStrTokPtr);
    565 
    566   return Status;
    567 }
    568 
    569 VOID
    570 GetRelativeAddressInVtfBuffer (
    571   IN      UINT64     Address,
    572   IN OUT  UINTN      *RelativeAddress,
    573   IN      LOC_TYPE   LocType
    574   )
    575 /*++
    576 
    577 Routine Description:
    578 
    579   This function checks for the address alignmnet for specified data boundary. In
    580   case the address is not aligned, it returns FALSE and the amount of data in
    581   terms of byte needed to adjust to get the boundary alignmnet. If data is
    582   aligned, TRUE will be returned.
    583 
    584 Arguments:
    585 
    586   Address             - The address of the flash map space
    587   RelativeAddress     - The relative address of the Buffer
    588   LocType             - The type of the VTF
    589 
    590 
    591 Returns:
    592 
    593 
    594 --*/
    595 {
    596   UINT64  TempAddress;
    597   UINT8   *LocalBuff;
    598 
    599   if (LocType == FIRST_VTF) {
    600     LocalBuff         = (UINT8 *) Vtf1EndBuffer;
    601     TempAddress       = Fv1EndAddress - Address;
    602     *RelativeAddress  = (UINTN) LocalBuff - (UINTN) TempAddress;
    603   } else {
    604     LocalBuff         = (UINT8 *) Vtf2EndBuffer;
    605     TempAddress       = Fv2EndAddress - Address;
    606     *RelativeAddress  = (UINTN) LocalBuff - (UINTN) TempAddress;
    607   }
    608 }
    609 
    610 EFI_STATUS
    611 GetComponentVersionInfo (
    612   IN  OUT PARSED_VTF_INFO   *VtfInfo,
    613   IN      UINT8             *Buffer
    614   )
    615 /*++
    616 Routine Description:
    617 
    618   This function will extract the version information from File
    619 
    620 Arguments:
    621 
    622   VtfInfo  - A Pointer to the VTF Info Structure
    623   Buffer   - A Pointer to type UINT8
    624 
    625 Returns:
    626 
    627    EFI_SUCCESS           - The function completed successfully
    628    EFI_INVALID_PARAMETER - The parameter is invalid
    629 
    630 --*/
    631 {
    632   UINT16      VersionInfo;
    633   EFI_STATUS  Status;
    634 
    635   switch (VtfInfo->CompType) {
    636 
    637   case COMP_TYPE_FIT_PAL_A:
    638   case COMP_TYPE_FIT_PAL_B:
    639     memcpy (&VersionInfo, (Buffer + 8), sizeof (UINT16));
    640     VtfInfo->MajorVer = (UINT8) ((VersionInfo & 0xFF00) >> 8);
    641     VtfInfo->MinorVer = (UINT8) (VersionInfo & 0x00FF);
    642     Status            = EFI_SUCCESS;
    643     break;
    644 
    645   default:
    646     Status = EFI_INVALID_PARAMETER;
    647     break;
    648   }
    649 
    650   return Status;
    651 }
    652 
    653 BOOLEAN
    654 CheckAddressAlignment (
    655   IN      UINT64  Address,
    656   IN      UINT64  AlignmentData,
    657   IN OUT  UINT64  *AlignAdjustByte
    658   )
    659 /*++
    660 
    661 Routine Description:
    662 
    663   This function checks for the address alignmnet for specified data boundary. In
    664   case the address is not aligned, it returns FALSE and the amount of data in
    665   terms of byte needed to adjust to get the boundary alignmnet. If data is
    666   aligned, TRUE will be returned.
    667 
    668 Arguments:
    669 
    670   Address              - Pointer to buffer containing byte data of component.
    671   AlignmentData        - DataSize for which address needed to be aligned
    672   AlignAdjustByte      - Number of bytes needed to adjust alignment.
    673 
    674 Returns:
    675 
    676   TRUE                 - Address is aligned to specific data size boundary
    677   FALSE                - Address in not aligned to specified data size boundary
    678                        - Add/Subtract AlignAdjustByte to aling the address.
    679 
    680 --*/
    681 {
    682   //
    683   // Check if the assigned address is on address boundary. If not, it will
    684   // return the remaining byte required to adjust the address for specified
    685   // address boundary
    686   //
    687   *AlignAdjustByte = (Address % AlignmentData);
    688 
    689   if (*AlignAdjustByte == 0) {
    690     return TRUE;
    691   } else {
    692     return FALSE;
    693   }
    694 }
    695 
    696 EFI_STATUS
    697 GetFitTableStartAddress (
    698   IN OUT  FIT_TABLE   **FitTable
    699   )
    700 /*++
    701 
    702 Routine Description:
    703 
    704   Get the FIT table start address in VTF Buffer
    705 
    706 Arguments:
    707 
    708   FitTable    - Pointer to available fit table where new component can be added
    709 
    710 Returns:
    711 
    712   EFI_SUCCESS - The function completed successfully
    713 
    714 --*/
    715 {
    716   UINT64  FitTableAdd;
    717   UINT64  FitTableAddOffset;
    718   UINTN   RelativeAddress;
    719 
    720   //
    721   // Read the Fit Table address from Itanium-based address map.
    722   //
    723   FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
    724 
    725   //
    726   // Translate this Itanium-based address in terms of local buffer address which
    727   // contains the image for Boot Strapped File. The relative address will be
    728   // the address of fit table VTF buffer.
    729   //
    730   GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
    731   FitTableAdd = *(UINTN *) RelativeAddress;
    732 
    733   //
    734   // The FitTableAdd is the extracted Itanium based address pointing to FIT
    735   // table. The relative address will return its actual location in VTF
    736   // Buffer.
    737   //
    738   GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
    739 
    740   *FitTable = (FIT_TABLE *) RelativeAddress;
    741 
    742   return EFI_SUCCESS;
    743 }
    744 
    745 EFI_STATUS
    746 GetNextAvailableFitPtr (
    747   IN  FIT_TABLE   **FitPtr
    748   )
    749 /*++
    750 
    751 Routine Description:
    752 
    753   Get the FIT table address and locate the free space in fit where we can add
    754   new component. In this process, this function locates the fit table using
    755   Fit pointer in Itanium-based address map (as per Intel?Itanium(TM) SAL spec)
    756   and locate the available location in FIT table to be used by new components.
    757   If there are any Fit table which areg not being used contains ComponentType
    758   field as 0x7F. If needed we can change this and spec this out.
    759 
    760 Arguments:
    761 
    762   FitPtr    - Pointer to available fit table where new component can be added
    763 
    764 Returns:
    765 
    766   EFI_SUCCESS  - The function completed successfully
    767 
    768 --*/
    769 {
    770   FIT_TABLE *TmpFitPtr;
    771   UINT64    FitTableAdd;
    772   UINT64    FitTableAddOffset;
    773   UINTN     Index;
    774   UINTN     NumFitComponents;
    775   UINTN     RelativeAddress;
    776 
    777   //
    778   // Read the Fit Table address from Itanium-based address map.
    779   //
    780   FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
    781 
    782   //
    783   // Translate this Itanium-based address in terms of local buffer address which
    784   // contains the image for Boot Strapped File. The relative address will be
    785   // the address of fit table VTF buffer.
    786   //
    787   GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
    788   FitTableAdd = *(UINTN *) RelativeAddress;
    789 
    790   //
    791   // The FitTableAdd is the extracted Itanium based address pointing to FIT
    792   // table. The relative address will return its actual location in VTF
    793   // Buffer.
    794   //
    795   GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
    796 
    797   TmpFitPtr         = (FIT_TABLE *) RelativeAddress;
    798   NumFitComponents  = TmpFitPtr->CompSize;
    799 
    800   for (Index = 0; Index < NumFitComponents; Index++) {
    801     if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_UNUSED) {
    802       *FitPtr = TmpFitPtr;
    803       break;
    804     }
    805 
    806     TmpFitPtr++;
    807   }
    808 
    809   return EFI_SUCCESS;
    810 }
    811 
    812 int
    813 CompareItems (
    814   IN const VOID  *Arg1,
    815   IN const VOID  *Arg2
    816   )
    817 /*++
    818 
    819 Routine Description:
    820 
    821     This function is used by qsort to sort the FIT table based upon Component
    822     Type in their incresing order.
    823 
    824 Arguments:
    825 
    826     Arg1  -   Pointer to Arg1
    827     Arg2  -   Pointer to Arg2
    828 
    829 Returns:
    830 
    831     None
    832 
    833 --*/
    834 {
    835   if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) > (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
    836     return 1;
    837   } else if ((((FIT_TABLE *) Arg1)->CvAndType & FIT_TYPE_MASK) < (((FIT_TABLE *) Arg2)->CvAndType & FIT_TYPE_MASK)) {
    838     return -1;
    839   } else {
    840     return 0;
    841   }
    842 }
    843 
    844 VOID
    845 SortFitTable (
    846   IN  VOID
    847   )
    848 /*++
    849 
    850 Routine Description:
    851 
    852     This function is used by qsort to sort the FIT table based upon Component
    853     Type in their incresing order.
    854 
    855 Arguments:
    856 
    857     VOID
    858 
    859 Returns:
    860 
    861     None
    862 
    863 --*/
    864 {
    865   FIT_TABLE *FitTable;
    866   FIT_TABLE *TmpFitPtr;
    867   UINTN     NumFitComponents;
    868   UINTN     Index;
    869 
    870   GetFitTableStartAddress (&FitTable);
    871   TmpFitPtr         = FitTable;
    872   NumFitComponents  = 0;
    873   for (Index = 0; Index < FitTable->CompSize; Index++) {
    874     if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) != COMP_TYPE_FIT_UNUSED) {
    875       NumFitComponents += 1;
    876     }
    877     TmpFitPtr++;
    878   }
    879   qsort ((VOID *) FitTable, NumFitComponents, sizeof (FIT_TABLE), CompareItems);
    880 }
    881 
    882 VOID
    883 UpdateFitEntryForFwVolume (
    884   IN  UINT64  Size
    885   )
    886 /*++
    887 
    888 Routine Description:
    889 
    890   This function updates the information about Firmware Volume  in FIT TABLE.
    891   This FIT table has to be immediately below the PAL_A Start and it contains
    892   component type and address information. Other information can't be
    893   created this time so we would need to fix it up..
    894 
    895 
    896 Arguments:
    897 
    898   Size   - Firmware Volume Size
    899 
    900 Returns:
    901 
    902   VOID
    903 
    904 --*/
    905 {
    906   FIT_TABLE *CompFitPtr;
    907   UINTN     RelativeAddress;
    908 
    909   //
    910   // FV Fit table will be located at PAL_A Startaddress - 16 byte location
    911   //
    912   Vtf1LastStartAddress -= 0x10;
    913   Vtf1TotalSize += 0x10;
    914 
    915   GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
    916 
    917   CompFitPtr              = (FIT_TABLE *) RelativeAddress;
    918   CompFitPtr->CompAddress = Fv1BaseAddress;
    919 
    920   //
    921   // Since we don't have any information about its location in Firmware Volume,
    922   // initialize address to 0. This will be updated once Firmware Volume is
    923   // being build and its current address will be fixed in FIT table. Currently
    924   // we haven't implemented it so far and working on architectural clarafication
    925   //
    926   //
    927   // Firmware Volume Size in 16 byte block
    928   //
    929   CompFitPtr->CompSize = ((UINT32) Size) / 16;
    930 
    931   //
    932   // Since Firmware Volume does not exist by the time we create this FIT info
    933   // this should be fixedup from Firmware Volume creation tool. We haven't
    934   // worked out a method so far.
    935   //
    936   CompFitPtr->CompVersion = MAKE_VERSION (0, 0);
    937 
    938   //
    939   // Since we don't have any info about this file, we are making sure that
    940   // checksum is not needed.
    941   //
    942   CompFitPtr->CvAndType = CV_N_TYPE (0, COMP_TYPE_FIT_FV_BOOT);
    943 
    944   //
    945   // Since non VTF component will reside outside the VTF, we will not have its
    946   // binary image while creating VTF, hence we will not perform checksum at
    947   // this time. Once Firmware Volume is being created which will contain this
    948   // VTF, it will fix the FIT table for all the non VTF component and hence
    949   // checksum
    950   //
    951   CompFitPtr->CheckSum = 0;
    952 }
    953 
    954 EFI_STATUS
    955 UpdateFitEntryForNonVTFComp (
    956   IN  PARSED_VTF_INFO   *VtfInfo
    957   )
    958 /*++
    959 
    960 Routine Description:
    961 
    962   This function updates the information about non VTF component in FIT TABLE.
    963   Since non VTF componets binaries are not part of VTF binary, we would still
    964   be required to update its location information in Firmware Volume, inside
    965   FIT table.
    966 
    967 Arguments:
    968 
    969   VtfInfo    - Pointer to VTF Info Structure
    970 
    971 Returns:
    972 
    973   EFI_ABORTED  - The function fails to update the component in FIT
    974   EFI_SUCCESS  - The function completed successfully
    975 
    976 --*/
    977 {
    978   FIT_TABLE *CompFitPtr;
    979 
    980   //
    981   // Scan the FIT table for available space
    982   //
    983   GetNextAvailableFitPtr (&CompFitPtr);
    984   if (CompFitPtr == NULL) {
    985     Error (NULL, 0, 5003, "Invalid", "Can't update this component in FIT");
    986     return EFI_ABORTED;
    987   }
    988 
    989   //
    990   // Since we don't have any information about its location in Firmware Volume,
    991   // initialize address to 0. This will be updated once Firmware Volume is
    992   // being build and its current address will be fixed in FIT table
    993   //
    994   CompFitPtr->CompAddress = 0;
    995   CompFitPtr->CompSize    = VtfInfo->CompSize;
    996   CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
    997   CompFitPtr->CvAndType   = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
    998 
    999   //
   1000   // Since non VTF component will reside outside the VTF, we will not have its
   1001   // binary image while creating VTF, hence we will not perform checksum at
   1002   // this time. Once Firmware Volume is being created which will contain this
   1003   // VTF, it will fix the FIT table for all the non VTF component and hence
   1004   // checksum
   1005   //
   1006   CompFitPtr->CheckSum = 0;
   1007 
   1008   //
   1009   // Fit Type is FV_BOOT which means Firmware Volume, we initialize this to base
   1010   // address of Firmware Volume in which this VTF will be attached.
   1011   //
   1012   if ((CompFitPtr->CvAndType & 0x7F) == COMP_TYPE_FIT_FV_BOOT) {
   1013     CompFitPtr->CompAddress = Fv1BaseAddress;
   1014   }
   1015 
   1016   return EFI_SUCCESS;
   1017 }
   1018 
   1019 //
   1020 // !!!WARNING
   1021 // This function is updating the SALE_ENTRY in Itanium address space as per SAL
   1022 // spec. SALE_ENTRY is being read from SYM file of PEICORE. Once the PEI
   1023 // CORE moves in Firmware Volume, we would need to modify this function to be
   1024 // used with a API which will detect PEICORE component while building Firmware
   1025 // Volume and update its entry in FIT table as well as in Itanium address space
   1026 // as per Intel?Itanium(TM) SAL address space
   1027 //
   1028 EFI_STATUS
   1029 UpdateEntryPoint (
   1030   IN  PARSED_VTF_INFO   *VtfInfo,
   1031   IN  UINT64            *CompStartAddress
   1032   )
   1033 /*++
   1034 
   1035 Routine Description:
   1036 
   1037   This function updated the architectural entry point in IPF, SALE_ENTRY.
   1038 
   1039 Arguments:
   1040 
   1041   VtfInfo            - Pointer to VTF Info Structure
   1042   CompStartAddress   - Pointer to Component Start Address
   1043 
   1044 Returns:
   1045 
   1046   EFI_INVALID_PARAMETER  - The parameter is invalid
   1047   EFI_SUCCESS            - The function completed successfully
   1048 
   1049 --*/
   1050 {
   1051   UINTN   RelativeAddress;
   1052   UINT64  SalEntryAdd;
   1053   FILE    *Fp;
   1054   UINTN   Offset;
   1055 
   1056   CHAR8   Buff[FILE_NAME_SIZE];
   1057   CHAR8   Buff1[10];
   1058   CHAR8   Buff2[10];
   1059   CHAR8   OffsetStr[30];
   1060   CHAR8   Buff3[10];
   1061   CHAR8   Buff4[10];
   1062   CHAR8   Buff5[10];
   1063   CHAR8   Token[50];
   1064 
   1065   Fp = fopen (LongFilePath (VtfInfo->CompSymName), "rb");
   1066 
   1067   if (Fp == NULL) {
   1068     Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompSymName);
   1069     return EFI_INVALID_PARAMETER;
   1070   }
   1071 
   1072   while (fgets (Buff, sizeof (Buff), Fp) != NULL) {
   1073     fscanf (
   1074       Fp,
   1075       "%s %s %s %s %s %s %s",
   1076       Buff1,
   1077       Buff2,
   1078       OffsetStr,
   1079       Buff3,
   1080       Buff4,
   1081       Buff5,
   1082       Token
   1083       );
   1084     if (strnicmp (Token, "SALE_ENTRY", 10) == 0) {
   1085       break;
   1086     }
   1087   }
   1088 
   1089   Offset = strtoul (OffsetStr, NULL, 16);
   1090 
   1091   *CompStartAddress += Offset;
   1092   SalEntryAdd = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT);
   1093 
   1094   GetRelativeAddressInVtfBuffer (SalEntryAdd, &RelativeAddress, FIRST_VTF);
   1095 
   1096   memcpy ((VOID *) RelativeAddress, (VOID *) CompStartAddress, sizeof (UINT64));
   1097 
   1098   if (Fp != NULL) {
   1099     fclose (Fp);
   1100   }
   1101 
   1102   return EFI_SUCCESS;
   1103 }
   1104 
   1105 EFI_STATUS
   1106 CreateAndUpdateComponent (
   1107   IN  PARSED_VTF_INFO   *VtfInfo
   1108   )
   1109 /*++
   1110 
   1111 Routine Description:
   1112 
   1113   This function reads the binary file for each components and update them
   1114   in VTF Buffer as well as in FIT table. If the component is located in non
   1115   VTF area, only the FIT table address will be updated
   1116 
   1117 Arguments:
   1118 
   1119   VtfInfo    - Pointer to Parsed Info
   1120 
   1121 Returns:
   1122 
   1123   EFI_SUCCESS      - The function completed successful
   1124   EFI_ABORTED      - Aborted due to one of the many reasons like:
   1125                       (a) Component Size greater than the specified size.
   1126                       (b) Error opening files.
   1127 
   1128   EFI_INVALID_PARAMETER     Value returned from call to UpdateEntryPoint()
   1129   EFI_OUT_OF_RESOURCES      Memory allocation failure.
   1130 
   1131 --*/
   1132 {
   1133   EFI_STATUS  Status;
   1134   UINT64      CompStartAddress;
   1135   UINT64      FileSize;
   1136   UINT64      NumAdjustByte;
   1137   UINT8       *Buffer;
   1138   FILE        *Fp;
   1139   FIT_TABLE   *CompFitPtr;
   1140   BOOLEAN     Aligncheck;
   1141 
   1142   if (VtfInfo->LocationType == NONE) {
   1143     UpdateFitEntryForNonVTFComp (VtfInfo);
   1144     return EFI_SUCCESS;
   1145   }
   1146 
   1147   Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");
   1148 
   1149   if (Fp == NULL) {
   1150     Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
   1151     return EFI_ABORTED;
   1152   }
   1153 
   1154   FileSize = _filelength (fileno (Fp));
   1155   if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
   1156 
   1157     //
   1158     // BUGBUG: Satish to correct
   1159     //
   1160     FileSize -= SIZE_OF_PAL_HEADER;
   1161   }
   1162 
   1163   if (VtfInfo->PreferredSize) {
   1164     if (FileSize > VtfInfo->CompSize) {
   1165       Error (NULL, 0, 2000, "Invalid parameter", "The component size is more than specified size.");
   1166       return EFI_ABORTED;
   1167     }
   1168 
   1169     FileSize = VtfInfo->CompSize;
   1170   }
   1171 
   1172   Buffer = malloc ((UINTN) FileSize);
   1173   if (Buffer == NULL) {
   1174     return EFI_OUT_OF_RESOURCES;
   1175   }
   1176   memset (Buffer, 0, (UINTN) FileSize);
   1177 
   1178   if ((VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) || (VtfInfo->CompType == COMP_TYPE_FIT_PAL_A_SPECIFIC)) {
   1179 
   1180     //
   1181     // Read first 64 bytes of PAL header and use it to find version info
   1182     //
   1183     fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
   1184 
   1185     //
   1186     // PAL header contains the version info. Currently, we will use the header
   1187     // to read version info and then discard.
   1188     //
   1189     if (!VtfInfo->VersionPresent) {
   1190       GetComponentVersionInfo (VtfInfo, Buffer);
   1191     }
   1192   }
   1193 
   1194   fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
   1195   fclose (Fp);
   1196 
   1197   //
   1198   // If it is non PAL_B component, pass the entire buffer to get the version
   1199   // info and implement any specific case inside GetComponentVersionInfo.
   1200   //
   1201   if (VtfInfo->CompType != COMP_TYPE_FIT_PAL_B) {
   1202     if (!VtfInfo->VersionPresent) {
   1203       GetComponentVersionInfo (VtfInfo, Buffer);
   1204     }
   1205   }
   1206 
   1207   if (VtfInfo->LocationType == SECOND_VTF) {
   1208 
   1209     CompStartAddress = (Vtf2LastStartAddress - FileSize);
   1210   } else {
   1211     CompStartAddress = (Vtf1LastStartAddress - FileSize);
   1212   }
   1213 
   1214   if (VtfInfo->CompType == COMP_TYPE_FIT_PAL_B) {
   1215     Aligncheck = CheckAddressAlignment (CompStartAddress, 32 * 1024, &NumAdjustByte);
   1216   } else {
   1217     Aligncheck = CheckAddressAlignment (CompStartAddress, 8, &NumAdjustByte);
   1218   }
   1219 
   1220   if (!Aligncheck) {
   1221     CompStartAddress -= NumAdjustByte;
   1222   }
   1223 
   1224   if (VtfInfo->LocationType == SECOND_VTF && SecondVTF == TRUE) {
   1225     Vtf2LastStartAddress = CompStartAddress;
   1226     Vtf2TotalSize += (UINT32) (FileSize + NumAdjustByte);
   1227     Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, SECOND_VTF);
   1228   } else if (VtfInfo->LocationType == FIRST_VTF) {
   1229     Vtf1LastStartAddress = CompStartAddress;
   1230     Vtf1TotalSize += (UINT32) (FileSize + NumAdjustByte);
   1231     Status = UpdateVtfBuffer (CompStartAddress, Buffer, FileSize, FIRST_VTF);
   1232   } else {
   1233     Error (NULL, 0, 2000,"Invalid Parameter", "There's component in second VTF so second BaseAddress and Size must be specified!");
   1234     return EFI_INVALID_PARAMETER;
   1235   }
   1236 
   1237   if (EFI_ERROR (Status)) {
   1238     return EFI_ABORTED;
   1239   }
   1240 
   1241   GetNextAvailableFitPtr (&CompFitPtr);
   1242 
   1243   CompFitPtr->CompAddress = CompStartAddress | IPF_CACHE_BIT;
   1244   if ((FileSize % 16) != 0) {
   1245     Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
   1246     return EFI_INVALID_PARAMETER;
   1247   }
   1248   //assert ((FileSize % 16) == 0);
   1249   CompFitPtr->CompSize    = (UINT32) (FileSize / 16);
   1250   CompFitPtr->CompVersion = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
   1251   CompFitPtr->CvAndType   = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
   1252   if (VtfInfo->CheckSumRequired) {
   1253     CompFitPtr->CheckSum  = 0;
   1254     CompFitPtr->CheckSum  = CalculateChecksum8 (Buffer, (UINTN) FileSize);
   1255   }
   1256 
   1257   //
   1258   // Free the buffer
   1259   //
   1260   if (Buffer) {
   1261     free (Buffer);
   1262   }
   1263 
   1264   //
   1265   // Update the SYM file for this component based on it's start address.
   1266   //
   1267   Status = UpdateSymFile (CompStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
   1268   if (EFI_ERROR (Status)) {
   1269 
   1270     //
   1271     // At this time, SYM files are not required, so continue on error.
   1272     //
   1273   }
   1274 
   1275   // !!!!!!!!!!!!!!!!!!!!!
   1276   // BUGBUG:
   1277   // This part of the code is a temporary line since PEICORE is going to be inside
   1278   // VTF till we work out how to determine the SALE_ENTRY through it. We will need
   1279   // to clarify so many related questions
   1280   // !!!!!!!!!!!!!!!!!!!!!!!
   1281 
   1282   if (VtfInfo->CompType == COMP_TYPE_FIT_PEICORE) {
   1283     Status = UpdateEntryPoint (VtfInfo, &CompStartAddress);
   1284   }
   1285 
   1286   return Status;
   1287 }
   1288 
   1289 EFI_STATUS
   1290 CreateAndUpdatePAL_A (
   1291   IN  PARSED_VTF_INFO   *VtfInfo
   1292   )
   1293 /*++
   1294 
   1295 Routine Description:
   1296 
   1297   This function reads the binary file for each components and update them
   1298   in VTF Buffer as well as FIT table
   1299 
   1300 Arguments:
   1301 
   1302   VtfInfo    - Pointer to Parsed Info
   1303 
   1304 Returns:
   1305 
   1306   EFI_ABORTED           - Due to one of the following reasons:
   1307                            (a)Error Opening File
   1308                            (b)The PAL_A Size is more than specified size status
   1309                               One of the values mentioned below returned from
   1310                               call to UpdateSymFile
   1311   EFI_SUCCESS           - The function completed successfully.
   1312   EFI_INVALID_PARAMETER - One of the input parameters was invalid.
   1313   EFI_ABORTED           - An error occurred.UpdateSymFile
   1314   EFI_OUT_OF_RESOURCES  - Memory allocation failed.
   1315 
   1316 --*/
   1317 {
   1318   EFI_STATUS  Status;
   1319   UINT64      PalStartAddress;
   1320   UINT64      AbsAddress;
   1321   UINTN       RelativeAddress;
   1322   UINT64      FileSize;
   1323   UINT8       *Buffer;
   1324   FILE        *Fp;
   1325   FIT_TABLE   *PalFitPtr;
   1326 
   1327   Fp = fopen (LongFilePath (VtfInfo->CompBinName), "rb");
   1328 
   1329   if (Fp == NULL) {
   1330     Error (NULL, 0, 0001, "Error opening file", VtfInfo->CompBinName);
   1331     return EFI_ABORTED;
   1332   }
   1333 
   1334   FileSize = _filelength (fileno (Fp));
   1335   if (FileSize < 64) {
   1336     Error (NULL, 0, 2000, "Invalid parameter", "PAL_A bin header is 64 bytes, so the Bin size must be larger than 64 bytes!");
   1337     return EFI_INVALID_PARAMETER;
   1338   }
   1339   FileSize -= SIZE_OF_PAL_HEADER;
   1340 
   1341 
   1342   if (VtfInfo->PreferredSize) {
   1343     if (FileSize > VtfInfo->CompSize) {
   1344       Error (NULL, 0, 2000, "Invalid parameter", "The PAL_A Size is more than the specified size.");
   1345       return EFI_ABORTED;
   1346     }
   1347 
   1348     FileSize = VtfInfo->CompSize;
   1349   }
   1350 
   1351   Buffer = malloc ((UINTN) FileSize);
   1352   if (Buffer == NULL) {
   1353     return EFI_OUT_OF_RESOURCES;
   1354   }
   1355   memset (Buffer, 0, (UINTN) FileSize);
   1356 
   1357   //
   1358   // Read, Get version Info and discard the PAL header.
   1359   //
   1360   fread (Buffer, sizeof (UINT8), SIZE_OF_PAL_HEADER, Fp);
   1361 
   1362   //
   1363   // Extract the version info from header of PAL_A. Once done, discrad this buffer
   1364   //
   1365   if (!VtfInfo->VersionPresent) {
   1366     GetComponentVersionInfo (VtfInfo, Buffer);
   1367   }
   1368 
   1369   //
   1370   // Read PAL_A file in a buffer
   1371   //
   1372   fread (Buffer, sizeof (UINT8), (UINTN) FileSize, Fp);
   1373   fclose (Fp);
   1374 
   1375   PalStartAddress       = Fv1EndAddress - (SIZE_TO_OFFSET_PAL_A_END + FileSize);
   1376   Vtf1LastStartAddress  = PalStartAddress;
   1377   Vtf1TotalSize += (UINT32) FileSize;
   1378   Status      = UpdateVtfBuffer (PalStartAddress, Buffer, FileSize, FIRST_VTF);
   1379 
   1380   AbsAddress  = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
   1381   GetRelativeAddressInVtfBuffer (AbsAddress, &RelativeAddress, FIRST_VTF);
   1382   PalFitPtr               = (FIT_TABLE *) RelativeAddress;
   1383   PalFitPtr->CompAddress  = PalStartAddress | IPF_CACHE_BIT;
   1384   //assert ((FileSize % 16) == 0);
   1385   if ((FileSize % 16) != 0) {
   1386     Error (NULL, 0, 2000, "Invalid parameter", "Binary FileSize must be a multiple of 16.");
   1387     return EFI_INVALID_PARAMETER;
   1388   }
   1389 
   1390   PalFitPtr->CompSize     = (UINT32) (FileSize / 16);
   1391   PalFitPtr->CompVersion  = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
   1392   PalFitPtr->CvAndType    = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
   1393   if (VtfInfo->CheckSumRequired) {
   1394     PalFitPtr->CheckSum = 0;
   1395     PalFitPtr->CheckSum = CalculateChecksum8 (Buffer, (UINTN) FileSize);
   1396   }
   1397 
   1398   if (Buffer) {
   1399     free (Buffer);
   1400   }
   1401 
   1402   //
   1403   // Update the SYM file for this component based on it's start address.
   1404   //
   1405   Status = UpdateSymFile (PalStartAddress, SymFileName, VtfInfo->CompSymName, FileSize);
   1406   if (EFI_ERROR (Status)) {
   1407 
   1408     //
   1409     // At this time, SYM files are not required, so continue on error.
   1410     //
   1411   }
   1412 
   1413   return Status;
   1414 }
   1415 
   1416 EFI_STATUS
   1417 CreateFitTableAndInitialize (
   1418   IN  PARSED_VTF_INFO   *VtfInfo
   1419   )
   1420 /*++
   1421 
   1422 Routine Description:
   1423 
   1424   This function creates and intializes FIT table which would be used to
   1425   add component info inside this
   1426 
   1427 Arguments:
   1428 
   1429   VtfInfo    - Pointer to Parsed Info
   1430 
   1431 Returns:
   1432 
   1433   EFI_ABORTED  - Aborted due to no size information
   1434   EFI_SUCCESS  - The function completed successfully
   1435 
   1436 --*/
   1437 {
   1438   UINT64    PalFitTableAdd;
   1439   UINT64    FitTableAdd;
   1440   UINT64    FitTableAddressOffset;
   1441   FIT_TABLE *PalFitPtr;
   1442   FIT_TABLE *FitStartPtr;
   1443   UINTN     NumFitComp;
   1444   UINTN     RelativeAddress;
   1445   UINTN     Index;
   1446 
   1447   if (!VtfInfo->PreferredSize) {
   1448     Error (NULL, 0, 2000, "Invalid parameter", "FIT could not be allocated because there is no size information.");
   1449     return EFI_ABORTED;
   1450   }
   1451 
   1452   if ((VtfInfo->CompSize % 16) != 0) {
   1453     Error (NULL, 0, 2000, "Invalid parameter", "Invalid FIT Table Size, it is not a multiple of 16 bytes. Please correct the size.");
   1454   }
   1455 
   1456   PalFitTableAdd = Fv1EndAddress - SIZE_TO_PAL_A_FIT;
   1457   GetRelativeAddressInVtfBuffer (PalFitTableAdd, &RelativeAddress, FIRST_VTF);
   1458   PalFitPtr             = (FIT_TABLE *) RelativeAddress;
   1459   PalFitTableAdd        = (PalFitPtr->CompAddress - VtfInfo->CompSize);
   1460 
   1461   FitTableAdd           = (PalFitPtr->CompAddress - 0x10) - VtfInfo->CompSize;
   1462   FitTableAddressOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
   1463   GetRelativeAddressInVtfBuffer (FitTableAddressOffset, &RelativeAddress, FIRST_VTF);
   1464   *(UINT64 *) RelativeAddress = FitTableAdd;
   1465 
   1466   GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
   1467 
   1468   //
   1469   // Update Fit Table with FIT Signature and FIT info in first 16 bytes.
   1470   //
   1471   FitStartPtr = (FIT_TABLE *) RelativeAddress;
   1472 
   1473   strncpy ((CHAR8 *) &FitStartPtr->CompAddress, FIT_SIGNATURE, 8);  // "_FIT_   "
   1474   assert (((VtfInfo->CompSize & 0x00FFFFFF) % 16) == 0);
   1475   FitStartPtr->CompSize     = (VtfInfo->CompSize & 0x00FFFFFF) / 16;
   1476   FitStartPtr->CompVersion  = MAKE_VERSION (VtfInfo->MajorVer, VtfInfo->MinorVer);
   1477 
   1478   //
   1479   // BUGBUG: If a checksum is required, add code to checksum the FIT table.  Also
   1480   // determine what to do for things like the FV component that aren't easily checksummed.
   1481   // The checksum will be done once we are done with all the componet update in the FIT
   1482   // table
   1483   //
   1484   FitStartPtr->CvAndType  = CV_N_TYPE (VtfInfo->CheckSumRequired, VtfInfo->CompType);
   1485 
   1486   NumFitComp              = FitStartPtr->CompSize;
   1487 
   1488   FitStartPtr++;
   1489 
   1490   //
   1491   // Intialize remaining FIT table space to UNUSED fit component type
   1492   // so that when we need to create a FIT entry for a component, we can
   1493   // locate a free one and use it.
   1494   //
   1495   for (Index = 0; Index < (NumFitComp - 1); Index++) {
   1496     FitStartPtr->CvAndType = 0x7F;  // Initialize all with UNUSED
   1497     FitStartPtr++;
   1498   }
   1499 
   1500   Vtf1TotalSize += VtfInfo->CompSize;
   1501   Vtf1LastStartAddress -= VtfInfo->CompSize;
   1502 
   1503   return EFI_SUCCESS;
   1504 }
   1505 
   1506 EFI_STATUS
   1507 WriteVtfBinary (
   1508   IN CHAR8     *FileName,
   1509   IN UINT32    VtfSize,
   1510   IN LOC_TYPE  LocType
   1511   )
   1512 /*++
   1513 
   1514 Routine Description:
   1515 
   1516   Write Firmware Volume from memory to a file.
   1517 
   1518 Arguments:
   1519 
   1520   FileName     - Output File Name which needed to be created/
   1521   VtfSize      - FileSize
   1522   LocType      - The type of the VTF
   1523 
   1524 Returns:
   1525 
   1526   EFI_ABORTED - Returned due to one of the following resons:
   1527                  (a) Error Opening File
   1528                  (b) Failing to copy buffers
   1529   EFI_SUCCESS - The fuction completes successfully
   1530 
   1531 --*/
   1532 {
   1533   FILE  *Fp;
   1534   UINTN NumByte;
   1535   VOID  *VtfBuffer;
   1536   UINTN RelativeAddress;
   1537 
   1538   if (LocType == FIRST_VTF) {
   1539     GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
   1540     VtfBuffer = (VOID *) RelativeAddress;
   1541   } else {
   1542     GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
   1543     VtfBuffer = (VOID *) RelativeAddress;
   1544   }
   1545 
   1546   Fp = fopen (LongFilePath (FileName), "wb");
   1547   if (Fp == NULL) {
   1548     Error (NULL, 0, 0001, "Error opening file", FileName);
   1549     return EFI_ABORTED;
   1550   }
   1551 
   1552   NumByte = fwrite (VtfBuffer, sizeof (UINT8), (UINTN) VtfSize, Fp);
   1553 
   1554   if (Fp) {
   1555     fclose (Fp);
   1556   }
   1557 
   1558   if (NumByte != (sizeof (UINT8) * VtfSize)) {
   1559     Error (NULL, 0, 0002, "Error writing file", FileName);
   1560     return EFI_ABORTED;
   1561   }
   1562 
   1563   return EFI_SUCCESS;
   1564 }
   1565 
   1566 EFI_STATUS
   1567 UpdateVtfBuffer (
   1568   IN  UINT64   StartAddress,
   1569   IN  UINT8    *Buffer,
   1570   IN  UINT64   DataSize,
   1571   IN LOC_TYPE  LocType
   1572   )
   1573 /*++
   1574 
   1575 Routine Description:
   1576 
   1577   Update the Firmware Volume Buffer with requested buffer data
   1578 
   1579 Arguments:
   1580 
   1581   StartAddress   - StartAddress in buffer. This number will automatically
   1582                   point to right address in buffer where data needed
   1583                   to be updated.
   1584   Buffer         - Buffer pointer from data will be copied to memory mapped buffer.
   1585   DataSize       - Size of the data needed to be copied.
   1586   LocType        - The type of the VTF: First or Second
   1587 
   1588 Returns:
   1589 
   1590   EFI_ABORTED  - The input parameter is error
   1591   EFI_SUCCESS  - The function completed successfully
   1592 
   1593 --*/
   1594 {
   1595   UINT8 *LocalBufferPtrToWrite;
   1596 
   1597   if (LocType == FIRST_VTF) {
   1598     if ((StartAddress | IPF_CACHE_BIT) < (Vtf1LastStartAddress | IPF_CACHE_BIT)) {
   1599       Error (NULL, 0, 2000, "Invalid parameter", "Start Address is less than the VTF start address.");
   1600       return EFI_ABORTED;
   1601     }
   1602 
   1603     LocalBufferPtrToWrite = (UINT8 *) Vtf1EndBuffer;
   1604 
   1605     LocalBufferPtrToWrite -= (Fv1EndAddress - StartAddress);
   1606 
   1607   } else {
   1608 
   1609     if ((StartAddress | IPF_CACHE_BIT) < (Vtf2LastStartAddress | IPF_CACHE_BIT)) {
   1610       Error (NULL, 0, 2000, "Invalid parameter", "Error StartAddress");
   1611       return EFI_ABORTED;
   1612     }
   1613     LocalBufferPtrToWrite = (UINT8 *) Vtf2EndBuffer;
   1614     LocalBufferPtrToWrite -= (Fv2EndAddress - StartAddress);
   1615   }
   1616 
   1617   memcpy (LocalBufferPtrToWrite, Buffer, (UINTN) DataSize);
   1618 
   1619   return EFI_SUCCESS;
   1620 }
   1621 
   1622 EFI_STATUS
   1623 UpdateFfsHeader (
   1624   IN UINT32         TotalVtfSize,
   1625   IN LOC_TYPE       LocType
   1626   )
   1627 /*++
   1628 
   1629 Routine Description:
   1630 
   1631   Update the Firmware Volume Buffer with requested buffer data
   1632 
   1633 Arguments:
   1634 
   1635   TotalVtfSize     - Size of the VTF
   1636   Fileoffset       - The start of the file relative to the start of the FV.
   1637   LocType          - The type of the VTF
   1638 
   1639 Returns:
   1640 
   1641   EFI_SUCCESS            - The function completed successfully
   1642   EFI_INVALID_PARAMETER  - The Ffs File Header Pointer is NULL
   1643 
   1644 --*/
   1645 {
   1646   EFI_FFS_FILE_HEADER *FileHeader;
   1647   UINTN               RelativeAddress;
   1648   EFI_GUID            EfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
   1649 
   1650   //
   1651   // Find the VTF file header location
   1652   //
   1653   if (LocType == FIRST_VTF) {
   1654     GetRelativeAddressInVtfBuffer (Vtf1LastStartAddress, &RelativeAddress, FIRST_VTF);
   1655     FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
   1656   } else {
   1657     GetRelativeAddressInVtfBuffer (Vtf2LastStartAddress, &RelativeAddress, SECOND_VTF);
   1658     FileHeader = (EFI_FFS_FILE_HEADER *) RelativeAddress;
   1659   }
   1660 
   1661   if (FileHeader == NULL) {
   1662     return EFI_INVALID_PARAMETER;
   1663   }
   1664 
   1665   //
   1666   // write header
   1667   //
   1668   memset (FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
   1669   memcpy (&FileHeader->Name, &EfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID));
   1670   FileHeader->Type        = EFI_FV_FILETYPE_RAW;
   1671   FileHeader->Attributes  = FFS_ATTRIB_CHECKSUM;
   1672 
   1673   //
   1674   // Now FileSize includes the EFI_FFS_FILE_HEADER
   1675   //
   1676   FileHeader->Size[0] = (UINT8) (TotalVtfSize & 0x000000FF);
   1677   FileHeader->Size[1] = (UINT8) ((TotalVtfSize & 0x0000FF00) >> 8);
   1678   FileHeader->Size[2] = (UINT8) ((TotalVtfSize & 0x00FF0000) >> 16);
   1679 
   1680   //
   1681   // Fill in checksums and state, all three must be zero for the checksums.
   1682   //
   1683   FileHeader->IntegrityCheck.Checksum.Header  = 0;
   1684   FileHeader->IntegrityCheck.Checksum.File    = 0;
   1685   FileHeader->State                           = 0;
   1686   FileHeader->IntegrityCheck.Checksum.Header  = CalculateChecksum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
   1687   FileHeader->IntegrityCheck.Checksum.File    = CalculateChecksum8 ((UINT8 *) (FileHeader + 1), TotalVtfSize - sizeof (EFI_FFS_FILE_HEADER));
   1688   FileHeader->State                           = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
   1689 
   1690   return EFI_SUCCESS;
   1691 }
   1692 
   1693 EFI_STATUS
   1694 ValidateAddressAndSize (
   1695   IN  UINT64  BaseAddress,
   1696   IN  UINT64  FwVolSize
   1697   )
   1698 /*++
   1699 
   1700 Routine Description:
   1701 
   1702   Update the Firmware Volume Buffer with requested buffer data
   1703 
   1704 Arguments:
   1705 
   1706   BaseAddress    - Base address for the Fw Volume.
   1707 
   1708   FwVolSize      - Total Size of the FwVolume to which VTF will be attached..
   1709 
   1710 Returns:
   1711 
   1712   EFI_SUCCESS     - The function completed successfully
   1713   EFI_UNSUPPORTED - The input parameter is error
   1714 
   1715 --*/
   1716 {
   1717   if ((FwVolSize > 0x40) && ((BaseAddress + FwVolSize) % 8 == 0)) {
   1718     return EFI_SUCCESS;
   1719   }
   1720 
   1721   return EFI_UNSUPPORTED;
   1722 }
   1723 
   1724 EFI_STATUS
   1725 UpdateIA32ResetVector (
   1726   IN  CHAR8   *FileName,
   1727   IN  UINT64  FirstFwVSize
   1728   )
   1729 /*++
   1730 
   1731 Routine Description:
   1732 
   1733   Update the 16 byte IA32 Reset vector to maintain the compatibility
   1734 
   1735 Arguments:
   1736 
   1737   FileName     - Binary file name which contains the IA32 Reset vector info..
   1738   FirstFwVSize - Total Size of the FwVolume to which VTF will be attached..
   1739 
   1740 Returns:
   1741 
   1742   EFI_SUCCESS            - The function completed successfully
   1743   EFI_ABORTED            - Invalid File Size
   1744   EFI_INVALID_PARAMETER  - Bad File Name
   1745   EFI_OUT_OF_RESOURCES   - Memory allocation failed.
   1746 
   1747 --*/
   1748 {
   1749   UINT8 *Buffer;
   1750   UINT8 *LocalVtfBuffer;
   1751   UINTN FileSize;
   1752   FILE  *Fp;
   1753 
   1754   if (!strcmp (FileName, "")) {
   1755     return EFI_INVALID_PARAMETER;
   1756   }
   1757 
   1758   Fp = fopen (LongFilePath (FileName), "rb");
   1759 
   1760   if (Fp == NULL) {
   1761     Error (NULL, 0, 0001, "Error opening file", FileName);
   1762     return EFI_ABORTED;
   1763   }
   1764 
   1765   FileSize = _filelength (fileno (Fp));
   1766 
   1767   if (FileSize > 16) {
   1768     return EFI_ABORTED;
   1769   }
   1770 
   1771   Buffer = malloc (FileSize);
   1772   if (Buffer == NULL) {
   1773     return EFI_OUT_OF_RESOURCES;
   1774   }
   1775 
   1776   fread (Buffer, sizeof (UINT8), FileSize, Fp);
   1777 
   1778   LocalVtfBuffer  = (UINT8 *) Vtf1EndBuffer - SIZE_IA32_RESET_VECT;
   1779   memcpy (LocalVtfBuffer, Buffer, FileSize);
   1780 
   1781   if (Buffer) {
   1782     free (Buffer);
   1783   }
   1784 
   1785   if (Fp != NULL) {
   1786     fclose (Fp);
   1787   }
   1788   return EFI_SUCCESS;
   1789 }
   1790 
   1791 VOID
   1792 CleanUpMemory (
   1793   VOID
   1794   )
   1795 /*++
   1796 
   1797 Routine Description:
   1798 
   1799   This function cleans up any allocated buffer
   1800 
   1801 Arguments:
   1802 
   1803   NONE
   1804 
   1805 Returns:
   1806 
   1807   NONE
   1808 
   1809 --*/
   1810 {
   1811   PARSED_VTF_INFO *TempFileListPtr;
   1812 
   1813   if (Vtf1Buffer) {
   1814     free (Vtf1Buffer);
   1815   }
   1816 
   1817   if (Vtf2Buffer) {
   1818     free (Vtf2Buffer);
   1819   }
   1820 
   1821   //
   1822   // Cleanup the buffer which was allocated to read the file names from FV.INF
   1823   //
   1824   FileListPtr = FileListHeadPtr;
   1825   while (FileListPtr != NULL) {
   1826     TempFileListPtr = FileListPtr->NextVtfInfo;
   1827     free (FileListPtr);
   1828     FileListPtr = TempFileListPtr;
   1829   }
   1830 }
   1831 
   1832 EFI_STATUS
   1833 ProcessAndCreateVtf (
   1834   IN  UINT64  Size
   1835   )
   1836 /*++
   1837 
   1838 Routine Description:
   1839 
   1840   This function process the link list created during INF file parsing
   1841   and create component in VTF and updates its info in FIT table
   1842 
   1843 Arguments:
   1844 
   1845   Size   - Size of the Firmware Volume of which, this VTF belongs to.
   1846 
   1847 Returns:
   1848 
   1849   EFI_UNSUPPORTED - Unknown FIT type
   1850   EFI_SUCCESS     - The function completed successfully
   1851 
   1852 --*/
   1853 {
   1854   EFI_STATUS      Status;
   1855   PARSED_VTF_INFO *ParsedInfoPtr;
   1856 
   1857   Status        = EFI_SUCCESS;
   1858 
   1859   ParsedInfoPtr = FileListHeadPtr;
   1860 
   1861   while (ParsedInfoPtr != NULL) {
   1862 
   1863     switch (ParsedInfoPtr->CompType) {
   1864     //
   1865     // COMP_TYPE_FIT_HEADER is a special case, hence handle it here
   1866     //
   1867     case COMP_TYPE_FIT_HEADER:
   1868       //COMP_TYPE_FIT_HEADER          0x00
   1869       Status = CreateFitTableAndInitialize (ParsedInfoPtr);
   1870       break;
   1871 
   1872     //
   1873     // COMP_TYPE_FIT_PAL_A is a special case, hence handle it here
   1874     //
   1875     case COMP_TYPE_FIT_PAL_A:
   1876       //COMP_TYPE_FIT_PAL_A           0x0F
   1877       Status = CreateAndUpdatePAL_A (ParsedInfoPtr);
   1878 
   1879       //
   1880       // Based on VTF specification, once the PAL_A component has been written,
   1881       // update the Firmware Volume info as FIT table. This will be utilized
   1882       // to extract the Firmware Volume Start address where this VTF will be
   1883       // of part.
   1884       //
   1885       if (Status == EFI_SUCCESS) {
   1886         UpdateFitEntryForFwVolume (Size);
   1887       }
   1888       break;
   1889 
   1890     case COMP_TYPE_FIT_FV_BOOT:
   1891       //COMP_TYPE_FIT_FV_BOOT         0x7E
   1892       //
   1893       // Since FIT entry for Firmware Volume has been created and it is
   1894       // located at (PAL_A start - 16 byte). So we will not process any
   1895       // Firmware Volume related entry from INF file
   1896       //
   1897       Status = EFI_SUCCESS;
   1898       break;
   1899 
   1900     default:
   1901       //
   1902       // Any other component type should be handled here. This will create the
   1903       // image in specified VTF and create appropriate entry about this
   1904       // component in FIT Entry.
   1905       //
   1906       Status = CreateAndUpdateComponent (ParsedInfoPtr);
   1907       if (EFI_ERROR (Status)) {
   1908         Error (NULL, 0, 0002, "Error updating component", ParsedInfoPtr->CompName);
   1909         return EFI_ABORTED;
   1910       } else {
   1911       break;}
   1912     }
   1913 
   1914     ParsedInfoPtr = ParsedInfoPtr->NextVtfInfo;
   1915   }
   1916   return Status;
   1917 }
   1918 
   1919 EFI_STATUS
   1920 GenerateVtfImage (
   1921   IN  UINT64  StartAddress1,
   1922   IN  UINT64  Size1,
   1923   IN  UINT64  StartAddress2,
   1924   IN  UINT64  Size2,
   1925   IN  FILE    *fp
   1926   )
   1927 /*++
   1928 
   1929 Routine Description:
   1930 
   1931   This is the main function which will be called from application.
   1932 
   1933 Arguments:
   1934 
   1935   StartAddress1  - The start address of the first VTF
   1936   Size1          - The size of the first VTF
   1937   StartAddress2  - The start address of the second VTF
   1938   Size2          - The size of the second VTF
   1939   fp             - The pointer to BSF inf file
   1940 
   1941 Returns:
   1942 
   1943   EFI_OUT_OF_RESOURCES - Can not allocate memory
   1944   The return value can be any of the values
   1945   returned by the calls to following functions:
   1946       GetVtfRelatedInfoFromInfFile
   1947       ProcessAndCreateVtf
   1948       UpdateIA32ResetVector
   1949       UpdateFfsHeader
   1950       WriteVtfBinary
   1951 
   1952 --*/
   1953 {
   1954   EFI_STATUS  Status;
   1955   FILE            *VtfFP;
   1956 
   1957   Status          = EFI_UNSUPPORTED;
   1958   VtfFP = fp;
   1959 
   1960   if (StartAddress2 == 0) {
   1961     SecondVTF = FALSE;
   1962   } else {
   1963     SecondVTF = TRUE;
   1964   }
   1965 
   1966   Fv1BaseAddress        = StartAddress1;
   1967   Fv1EndAddress         = Fv1BaseAddress + Size1;
   1968   if (Fv1EndAddress != 0x100000000ULL || Size1 < 0x100000) {
   1969     Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
   1970     if (Size1 < 0x100000) {
   1971       Error (NULL, 0, 2000, "Invalid parameter", "The FwVolumeSize must be larger than 1M!");
   1972     } else if (SecondVTF != TRUE) {
   1973       Error (NULL, 0, 2000, "Invalid parameter", "BaseAddress + FwVolumeSize must equal 0x100000000!");
   1974     }
   1975     Usage();
   1976     return EFI_INVALID_PARAMETER;
   1977   }
   1978 
   1979   //
   1980   // The image buffer for the First VTF
   1981   //
   1982   Vtf1Buffer = malloc ((UINTN) Size1);
   1983   if (Vtf1Buffer == NULL) {
   1984     Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
   1985     return EFI_OUT_OF_RESOURCES;
   1986   }
   1987   memset (Vtf1Buffer, 0x00, (UINTN) Size1);
   1988   Vtf1EndBuffer         = (UINT8 *) Vtf1Buffer + Size1;
   1989   Vtf1LastStartAddress  = Fv1EndAddress | IPF_CACHE_BIT;
   1990 
   1991   if (SecondVTF) {
   1992     Fv2BaseAddress        = StartAddress2;
   1993     Fv2EndAddress         = Fv2BaseAddress + Size2;
   1994     if (Fv2EndAddress != StartAddress1) {
   1995       Error (NULL, 0, 2000, "Invalid parameter", "Error BaseAddress and Size parameters!");
   1996       if (SecondVTF == TRUE) {
   1997         Error (NULL, 0, 2000, "Invalid parameter", "FirstBaseAddress + FirstFwVolumeSize must equal 0x100000000!");
   1998         Error (NULL, 0, 2000, "Invalid parameter", "SecondBaseAddress + SecondFwVolumeSize must equal FirstBaseAddress!");
   1999       }
   2000       Usage();
   2001       return EFI_INVALID_PARAMETER;
   2002     }
   2003 
   2004     //
   2005     // The image buffer for the second VTF
   2006     //
   2007     Vtf2Buffer = malloc ((UINTN) Size2);
   2008     if (Vtf2Buffer == NULL) {
   2009       Error (NULL, 0, 4001, "Resource", "Not enough resources available to create memory mapped file for the Boot Strap File!");
   2010       return EFI_OUT_OF_RESOURCES;
   2011     }
   2012     memset (Vtf2Buffer, 0x00, (UINTN) Size2);
   2013     Vtf2EndBuffer         = (UINT8 *) Vtf2Buffer + Size2;
   2014     Vtf2LastStartAddress  = Fv2EndAddress | IPF_CACHE_BIT;
   2015   }
   2016 
   2017   Status = GetVtfRelatedInfoFromInfFile (VtfFP);
   2018 
   2019   if (Status != EFI_SUCCESS) {
   2020     Error (NULL, 0, 0003, "Error parsing file", "the input file.");
   2021     CleanUpMemory ();
   2022     return Status;
   2023   }
   2024 
   2025   Status = ProcessAndCreateVtf (Size1);
   2026   if (Status != EFI_SUCCESS) {
   2027     CleanUpMemory ();
   2028     return Status;
   2029   }
   2030 
   2031   if (SectionOptionFlag) {
   2032     Status = UpdateIA32ResetVector (IA32BinFile, Vtf1TotalSize);
   2033     if (Status != EFI_SUCCESS) {
   2034       CleanUpMemory ();
   2035       return Status;
   2036     }
   2037   }
   2038 
   2039   //
   2040   // Re arrange the FIT Table for Ascending order of their FIT Type..
   2041   //
   2042   SortFitTable ();
   2043 
   2044   //
   2045   // All components have been updated in FIT table. Now perform the FIT table
   2046   // checksum. The following function will check if Checksum is required,
   2047   // if yes, then it will perform the checksum otherwise not.
   2048   //
   2049   CalculateFitTableChecksum ();
   2050 
   2051   //
   2052   // Write the FFS header
   2053   //
   2054   Vtf1TotalSize += sizeof (EFI_FFS_FILE_HEADER);
   2055   Vtf1LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
   2056 
   2057   Status = UpdateFfsHeader (Vtf1TotalSize, FIRST_VTF);
   2058   if (Status != EFI_SUCCESS) {
   2059     CleanUpMemory ();
   2060     return Status;
   2061   }
   2062   //
   2063   // Update the VTF buffer into specified VTF binary file
   2064   //
   2065   Status  = WriteVtfBinary (OutFileName1, Vtf1TotalSize, FIRST_VTF);
   2066 
   2067   if (SecondVTF) {
   2068     Vtf2TotalSize += sizeof (EFI_FFS_FILE_HEADER);
   2069     Vtf2LastStartAddress -= sizeof (EFI_FFS_FILE_HEADER);
   2070     Status = UpdateFfsHeader (Vtf2TotalSize, SECOND_VTF);
   2071     if (Status != EFI_SUCCESS) {
   2072       CleanUpMemory ();
   2073       return Status;
   2074     }
   2075 
   2076     //
   2077     // Update the VTF buffer into specified VTF binary file
   2078     //
   2079     Status  = WriteVtfBinary (OutFileName2, Vtf2TotalSize, SECOND_VTF);
   2080   }
   2081 
   2082   CleanUpMemory ();
   2083 
   2084   return Status;
   2085 }
   2086 
   2087 EFI_STATUS
   2088 PeimFixupInFitTable (
   2089   IN  UINT64  StartAddress
   2090   )
   2091 /*++
   2092 
   2093 Routine Description:
   2094 
   2095   This function is an entry point to fixup SAL-E entry point.
   2096 
   2097 Arguments:
   2098 
   2099   StartAddress - StartAddress for PEIM.....
   2100 
   2101 Returns:
   2102 
   2103   EFI_SUCCESS          - The function completed successfully
   2104   EFI_ABORTED          - Error Opening File
   2105   EFI_OUT_OF_RESOURCES - System out of resources for memory allocation.
   2106 
   2107 --*/
   2108 {
   2109   EFI_STATUS  Status;
   2110   FILE        *Fp;
   2111   UINT64      *StartAddressPtr;
   2112   UINTN       FirstFwVSize;
   2113 
   2114   StartAddressPtr   = malloc (sizeof (UINT64));
   2115   if (StartAddressPtr == NULL) {
   2116     return EFI_OUT_OF_RESOURCES;
   2117   }
   2118   *StartAddressPtr = StartAddress;
   2119 
   2120   Fp = fopen (LongFilePath (OutFileName1), "rb");
   2121 
   2122   if (Fp == NULL) {
   2123     Error (NULL, 0, 0001, "Error opening file", OutFileName1);
   2124     if (StartAddressPtr) {
   2125       free (StartAddressPtr);
   2126     }
   2127     return EFI_ABORTED;
   2128   }
   2129 
   2130   FirstFwVSize = _filelength (fileno (Fp));
   2131   fseek (Fp, (long) (FirstFwVSize - (UINTN) (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT)), SEEK_SET);
   2132   fwrite ((VOID *) StartAddressPtr, sizeof (UINT64), 1, Fp);
   2133 
   2134   if (Fp) {
   2135     fclose (Fp);
   2136   }
   2137 
   2138   if (StartAddressPtr) {
   2139     free (StartAddressPtr);
   2140   }
   2141 
   2142   Status = EFI_SUCCESS;
   2143   return Status;
   2144 }
   2145 
   2146 EFI_STATUS
   2147 UpdateSymFile (
   2148   IN UINT64 BaseAddress,
   2149   IN CHAR8  *DestFileName,
   2150   IN CHAR8  *SourceFileName,
   2151   IN UINT64 FileSize
   2152 
   2153   )
   2154 /*++
   2155 
   2156 Routine Description:
   2157 
   2158   This function adds the SYM tokens in the source file to the destination file.
   2159   The SYM tokens are updated to reflect the base address.
   2160 
   2161 Arguments:
   2162 
   2163   BaseAddress    - The base address for the new SYM tokens.
   2164   DestFileName   - The destination file.
   2165   SourceFileName - The source file.
   2166   FileSize       - Size of bin file.
   2167 
   2168 Returns:
   2169 
   2170   EFI_SUCCESS             - The function completed successfully.
   2171   EFI_INVALID_PARAMETER   - One of the input parameters was invalid.
   2172   EFI_ABORTED             - An error occurred.
   2173 
   2174 --*/
   2175 {
   2176   FILE    *SourceFile;
   2177   FILE    *DestFile;
   2178   CHAR8   Buffer[MAX_LONG_FILE_PATH];
   2179   CHAR8   Type[MAX_LONG_FILE_PATH];
   2180   CHAR8   Address[MAX_LONG_FILE_PATH];
   2181   CHAR8   Section[MAX_LONG_FILE_PATH];
   2182   CHAR8   Token[MAX_LONG_FILE_PATH];
   2183   CHAR8   BaseToken[MAX_LONG_FILE_PATH];
   2184   UINT64  TokenAddress;
   2185   long    StartLocation;
   2186 
   2187   //
   2188   // Verify input parameters.
   2189   //
   2190   if (BaseAddress == 0 || DestFileName == NULL || SourceFileName == NULL) {
   2191     return EFI_INVALID_PARAMETER;
   2192   }
   2193 
   2194   //
   2195   // Open the source file
   2196   //
   2197   SourceFile = fopen (LongFilePath (SourceFileName), "r");
   2198   if (SourceFile == NULL) {
   2199 
   2200     //
   2201     // SYM files are not required.
   2202     //
   2203     return EFI_SUCCESS;
   2204   }
   2205 
   2206   //
   2207   // Use the file name minus extension as the base for tokens
   2208   //
   2209   strcpy (BaseToken, SourceFileName);
   2210   strtok (BaseToken, ". \t\n");
   2211   strcat (BaseToken, "__");
   2212 
   2213   //
   2214   // Open the destination file
   2215   //
   2216   DestFile = fopen (LongFilePath (DestFileName), "a+");
   2217   if (DestFile == NULL) {
   2218     fclose (SourceFile);
   2219     Error (NULL, 0, 0001, "Error opening file", DestFileName);
   2220     return EFI_ABORTED;
   2221   }
   2222 
   2223   //
   2224   // If this is the beginning of the output file, write the symbol format info.
   2225   //
   2226   if (fseek (DestFile, 0, SEEK_END) != 0) {
   2227     fclose (SourceFile);
   2228     fclose (DestFile);
   2229     Error (NULL, 0, 2000, "Invalid parameter", "not at the beginning of the output file.");
   2230     return EFI_ABORTED;
   2231   }
   2232 
   2233   StartLocation = ftell (DestFile);
   2234 
   2235   if (StartLocation == 0) {
   2236     fprintf (DestFile, "TEXTSYM format | V1.0\n");
   2237   } else if (StartLocation == -1) {
   2238     fclose (SourceFile);
   2239     fclose (DestFile);
   2240     Error (NULL, 0, 2000, "Invalid parameter", "StartLocation error");
   2241     return EFI_ABORTED;
   2242   }
   2243 
   2244   //
   2245   // Read the first line
   2246   //
   2247   if (fgets (Buffer, MAX_LONG_FILE_PATH, SourceFile) == NULL) {
   2248     Buffer[0] = 0;
   2249   }
   2250 
   2251   //
   2252   // Make sure it matches the expected sym format
   2253   //
   2254   if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
   2255     fclose (SourceFile);
   2256     fclose (DestFile);
   2257     Error (NULL, 0, 2000, "Invalid parameter", "The symbol file does not match the expected TEXTSYM format (V1.0.)");
   2258     return EFI_ABORTED;
   2259   }
   2260 
   2261   //
   2262   // Read in the file
   2263   //
   2264   while (feof (SourceFile) == 0) {
   2265 
   2266     //
   2267     // Read a line
   2268     //
   2269     if (fscanf (SourceFile, "%s | %s | %s | %s\n", Type, Address, Section, Token) == 4) {
   2270 
   2271       //
   2272       // Get the token address
   2273       //
   2274       AsciiStringToUint64 (Address, TRUE, &TokenAddress);
   2275       if (TokenAddress > FileSize) {
   2276         //
   2277         // Symbol offset larger than FileSize. This Symbol can't be in Bin file. Don't print them.
   2278         //
   2279         break;
   2280       }
   2281 
   2282       //
   2283       // Add the base address, the size of the FFS file header and the size of the peim header.
   2284       //
   2285       TokenAddress += BaseAddress &~IPF_CACHE_BIT;
   2286 
   2287       fprintf (DestFile, "%s | %016llX | ", Type, (unsigned long long) TokenAddress);
   2288       fprintf (DestFile, "%s | %s\n    %s\n", Section, Token, BaseToken);
   2289     }
   2290   }
   2291 
   2292   fclose (SourceFile);
   2293   fclose (DestFile);
   2294   return EFI_SUCCESS;
   2295 }
   2296 
   2297 EFI_STATUS
   2298 CalculateFitTableChecksum (
   2299   VOID
   2300   )
   2301 /*++
   2302 
   2303 Routine Description:
   2304 
   2305   This function will perform byte checksum on the FIT table, if the the checksum required
   2306   field is set to CheckSum required. If the checksum is not required then checksum byte
   2307   will have value as 0;.
   2308 
   2309 Arguments:
   2310 
   2311   NONE
   2312 
   2313 Returns:
   2314 
   2315   Status       - Value returned by call to CalculateChecksum8 ()
   2316   EFI_SUCCESS  - The function completed successfully
   2317 
   2318 --*/
   2319 {
   2320   FIT_TABLE *TmpFitPtr;
   2321   UINT64    FitTableAdd;
   2322   UINT64    FitTableAddOffset;
   2323   UINTN     RelativeAddress;
   2324   UINTN     Size;
   2325 
   2326   //
   2327   // Read the Fit Table address from Itanium-based address map.
   2328   //
   2329   FitTableAddOffset = Fv1EndAddress - (SIZE_IA32_RESET_VECT + SIZE_SALE_ENTRY_POINT + SIZE_FIT_TABLE_ADD);
   2330 
   2331   //
   2332   // Translate this Itanium-based address in terms of local buffer address which
   2333   // contains the image for Boot Strapped File
   2334   //
   2335   GetRelativeAddressInVtfBuffer (FitTableAddOffset, &RelativeAddress, FIRST_VTF);
   2336   FitTableAdd = *(UINTN *) RelativeAddress;
   2337 
   2338   GetRelativeAddressInVtfBuffer (FitTableAdd, &RelativeAddress, FIRST_VTF);
   2339 
   2340   TmpFitPtr = (FIT_TABLE *) RelativeAddress;
   2341 
   2342   Size      = TmpFitPtr->CompSize * 16;
   2343 
   2344   if ((TmpFitPtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
   2345     TmpFitPtr->CheckSum = 0;
   2346     TmpFitPtr->CheckSum = CalculateChecksum8 ((UINT8 *) TmpFitPtr, Size);
   2347   } else {
   2348     TmpFitPtr->CheckSum = 0;
   2349   }
   2350 
   2351   return EFI_SUCCESS;
   2352 }
   2353 
   2354 VOID
   2355 Version (
   2356   VOID
   2357   )
   2358 /*++
   2359 
   2360 Routine Description:
   2361 
   2362   Displays the standard utility information to SDTOUT
   2363 
   2364 Arguments:
   2365 
   2366   None
   2367 
   2368 Returns:
   2369 
   2370   None
   2371 
   2372 --*/
   2373 {
   2374   fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
   2375 }
   2376 
   2377 VOID
   2378 Usage (
   2379   VOID
   2380   )
   2381 /*++
   2382 
   2383 Routine Description:
   2384 
   2385   Displays the utility usage syntax to STDOUT
   2386 
   2387 Arguments:
   2388 
   2389   None
   2390 
   2391 Returns:
   2392 
   2393   None
   2394 
   2395 --*/
   2396 {
   2397   //
   2398   // Summary usage
   2399   //
   2400   fprintf (stdout, "Usage: %s [options] <-f input_file> <-r BaseAddress> <-s FwVolumeSize>\n\n", UTILITY_NAME);
   2401 
   2402   //
   2403   // Copyright declaration
   2404   //
   2405   fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
   2406   //
   2407   // Details Option
   2408   //
   2409   fprintf (stdout, "Options:\n");
   2410   fprintf (stdout, "  -f Input_file,   --filename Input_file\n\
   2411                         Input_file is name of the BS Image INF file\n");
   2412   fprintf (stdout, "  -r BaseAddress,  --baseaddr BaseAddress\n\
   2413                         BaseAddress is the starting address of Firmware Volume\n\
   2414                         where Boot Strapped Image will reside.\n");
   2415   fprintf (stdout, "  -s FwVolumeSize, --size FwVolumeSize\n\
   2416                         FwVolumeSize is the size of Firmware Volume.\n");
   2417   fprintf (stdout, "  -o FileName,     --output FileName\n\
   2418                         File will be created to store the ouput content.\n");
   2419   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");
   2420   fprintf (stdout, "  --version             Show program's version number and exit.\n");
   2421   fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
   2422   fprintf (stdout, "  -q, --quiet           Disable all messages except FATAL ERRORS.\n");
   2423   fprintf (stdout, "  -d, --debug [#, 0-9]  Enable debug messages at level #.\n");
   2424 }
   2425 
   2426 int
   2427 main (
   2428   IN  int  argc,
   2429   IN  char  **argv
   2430   )
   2431 /*++
   2432 
   2433 Routine Description:
   2434 
   2435   This utility uses GenVtf.dll to build a Boot Strap File Image which will be
   2436   part of firmware volume image.
   2437 
   2438 Arguments:
   2439 
   2440   argc   - The count of the parameters
   2441   argv   - The parameters
   2442 
   2443 
   2444 Returns:
   2445 
   2446   0   - No error conditions detected.
   2447   1   - One or more of the input parameters is invalid.
   2448   2   - A resource required by the utility was unavailable.
   2449       - Most commonly this will be memory allocation or file creation.
   2450   3   - GenFvImage.dll could not be loaded.
   2451   4   - Error executing the GenFvImage dll.
   2452   5   - Now this tool does not support the IA32 platform
   2453 
   2454 --*/
   2455 {
   2456   UINT8          Index;
   2457   UINT64         StartAddress1;
   2458   UINT64         StartAddress2;
   2459   UINT64         FwVolSize1;
   2460   UINT64         FwVolSize2;
   2461   BOOLEAN       FirstRoundO;
   2462   BOOLEAN       FirstRoundB;
   2463   BOOLEAN       FirstRoundS;
   2464   EFI_STATUS    Status;
   2465   FILE          *VtfFP;
   2466   CHAR8         *VtfFileName;
   2467 
   2468   SetUtilityName (UTILITY_NAME);
   2469 
   2470   //
   2471   // Initialize variables
   2472   //
   2473   StartAddress1 = 0;
   2474   StartAddress2 = 0;
   2475   FwVolSize1    = 0;
   2476   FwVolSize2    = 0;
   2477   FirstRoundB   = TRUE;
   2478   FirstRoundS   = TRUE;
   2479   FirstRoundO   = TRUE;
   2480   DebugMode     = FALSE;
   2481   OutFileName1  = NULL;
   2482   OutFileName2  = NULL;
   2483   VtfFP = NULL;
   2484   DebugLevel = 0;
   2485 
   2486   //
   2487   // Verify the correct number of arguments
   2488   //
   2489   if (argc == 1) {
   2490     Usage();
   2491     return 0;
   2492   }
   2493 
   2494   if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
   2495     Usage();
   2496     return 0;
   2497   }
   2498 
   2499   if ((strcmp(argv[1], "--version") == 0)) {
   2500     Version();
   2501     return 0;
   2502   }
   2503 
   2504   //
   2505   // Parse the command line arguments
   2506   //
   2507   for (Index = 1; Index < argc; Index += 2) {
   2508     if ((stricmp (argv[Index], "-o") == 0) || (stricmp (argv[Index], "--output") == 0)) {
   2509       if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
   2510         Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
   2511         goto ERROR;
   2512       }
   2513       //
   2514       // Get the output file name
   2515       //
   2516       VTF_OUTPUT = TRUE;
   2517       if (FirstRoundO) {
   2518         //
   2519         // It's the first output file name
   2520         //
   2521         OutFileName1 = (CHAR8 *)argv[Index+1];
   2522         FirstRoundO = FALSE;
   2523       } else {
   2524         //
   2525         //It's the second output file name
   2526         //
   2527         OutFileName2 = (CHAR8 *)argv[Index+1];
   2528       }
   2529       continue;
   2530     }
   2531 
   2532     if ((stricmp (argv[Index], "-f") == 0) || (stricmp (argv[Index], "--filename") == 0)) {
   2533       if (argv[Index + 1] == NULL || argv[Index + 1][0] == '-') {
   2534         Error (NULL, 0, 1003, "Invalid option value", "BS Image INF file is missing for -f option");
   2535         goto ERROR;
   2536       }
   2537       //
   2538       // Get the input VTF file name
   2539       //
   2540       VtfFileName = argv[Index+1];
   2541       VtfFP = fopen (LongFilePath (VtfFileName), "rb");
   2542       if (VtfFP == NULL) {
   2543         Error (NULL, 0, 0001, "Error opening file", VtfFileName);
   2544         goto ERROR;
   2545       }
   2546       continue;
   2547     }
   2548 
   2549     if ((stricmp (argv[Index], "-r") == 0) || (stricmp (argv[Index], "--baseaddr") == 0)) {
   2550       if (FirstRoundB) {
   2551         Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress1);
   2552         FirstRoundB = FALSE;
   2553       } else {
   2554         Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &StartAddress2);
   2555       }
   2556       if (Status != EFI_SUCCESS) {
   2557         Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV start address.", argv[Index + 1]);
   2558         goto ERROR;
   2559       }
   2560       continue;
   2561     }
   2562 
   2563     if ((stricmp (argv[Index], "-s") == 0) || (stricmp (argv[Index], "--size") == 0)) {
   2564       if (FirstRoundS) {
   2565         Status      = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize1);
   2566         FirstRoundS = FALSE;
   2567       } else {
   2568         Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &FwVolSize2);
   2569     	  SecondVTF = TRUE;
   2570       }
   2571 
   2572       if (Status != EFI_SUCCESS) {
   2573         Error (NULL, 0, 2000, "Invalid option value", "%s is Bad FV size.", argv[Index + 1]);
   2574         goto ERROR;
   2575       }
   2576       continue;
   2577     }
   2578 
   2579     if ((stricmp (argv[Index], "-v") == 0) || (stricmp (argv[Index], "--verbose") == 0)) {
   2580 	    VerboseMode = TRUE;
   2581 	    Index--;
   2582       continue;
   2583     }
   2584 
   2585     if ((stricmp (argv[Index], "-q") == 0) || (stricmp (argv[Index], "--quiet") == 0)) {
   2586       QuietMode = TRUE;
   2587       Index--;
   2588       continue;
   2589     }
   2590 
   2591     if ((stricmp (argv[Index], "-d") == 0) || (stricmp (argv[Index], "--debug") == 0)) {
   2592       //
   2593       // debug level specified
   2594       //
   2595       Status = AsciiStringToUint64(argv[Index + 1], FALSE, &DebugLevel);
   2596       if (EFI_ERROR (Status)) {
   2597         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[Index], argv[Index + 1]);
   2598         goto ERROR;
   2599       }
   2600       if (DebugLevel > 9)  {
   2601         Error (NULL, 0, 2000, "Invalid option value", "Unrecognized argument %s.", argv[Index + 1]);
   2602         goto ERROR;
   2603       }
   2604       if((DebugLevel <= 9) &&(DebugLevel >= 5)) {
   2605         DebugMode = TRUE;
   2606       } else {
   2607         DebugMode = FALSE;
   2608       }
   2609       continue;
   2610     }
   2611 
   2612     Error (NULL, 0, 2000, "Invalid parameter", "Unrecognized argument %s.", argv[Index]);
   2613     goto ERROR;
   2614   }
   2615 
   2616   if (VtfFP == NULL) {
   2617     Error (NULL, 0, 2000, "Invalid parameter", "No BS Image INF file is specified");
   2618     goto ERROR;
   2619   }
   2620 
   2621   if (FirstRoundB) {
   2622     Error (NULL, 0, 2000, "Invalid parameter", "No FV base address is specified");
   2623     goto ERROR;
   2624   }
   2625 
   2626   if (FirstRoundS) {
   2627     Error (NULL, 0, 2000, "Invalid parameter", "No FV Size is specified");
   2628     goto ERROR;
   2629   }
   2630   //
   2631   // All Parameters has been parsed, now set the message print level
   2632   //
   2633   if (QuietMode) {
   2634     SetPrintLevel(40);
   2635   } else if (VerboseMode) {
   2636     SetPrintLevel(15);
   2637   } else if (DebugMode) {
   2638     SetPrintLevel(DebugLevel);
   2639   }
   2640 
   2641   if (VerboseMode) {
   2642     VerboseMsg("%s tool start.\n", UTILITY_NAME);
   2643   }
   2644 
   2645   if (VTF_OUTPUT == FALSE) {
   2646     if (SecondVTF == TRUE) {
   2647       OutFileName1 = VTF_OUTPUT_FILE1;
   2648       OutFileName2 = VTF_OUTPUT_FILE2;
   2649 	  } else {
   2650       OutFileName1 = VTF_OUTPUT_FILE1;
   2651     }
   2652     SymFileName = VTF_SYM_FILE;
   2653   } else {
   2654     INTN OutFileNameLen = strlen(OutFileName1);
   2655     INTN Index;
   2656 
   2657     for (Index = OutFileNameLen; Index > 0; --Index) {
   2658       if (OutFileName1[Index] == '/' || OutFileName1[Index] == '\\') {
   2659         break;
   2660       }
   2661     }
   2662     if (Index == 0) {
   2663       SymFileName = VTF_SYM_FILE;
   2664     } else {
   2665       INTN SymFileNameLen = Index + 1 + strlen(VTF_SYM_FILE);
   2666       SymFileName = malloc(SymFileNameLen + 1);
   2667       memcpy(SymFileName, OutFileName1, Index + 1);
   2668       memcpy(SymFileName + Index + 1, VTF_SYM_FILE, strlen(VTF_SYM_FILE));
   2669       SymFileName[SymFileNameLen] = '\0';
   2670     }
   2671     if (DebugMode) {
   2672       DebugMsg(UTILITY_NAME, 0, DebugLevel, SymFileName, NULL);
   2673     }
   2674   }
   2675 
   2676   //
   2677   // Call the GenVtfImage
   2678   //
   2679   if (DebugMode) {
   2680     DebugMsg(UTILITY_NAME, 0, DebugLevel, "Start to generate the VTF image\n", NULL);
   2681   }
   2682   Status = GenerateVtfImage (StartAddress1, FwVolSize1, StartAddress2, FwVolSize2, VtfFP);
   2683 
   2684   if (EFI_ERROR (Status)) {
   2685     switch (Status) {
   2686 
   2687     case EFI_INVALID_PARAMETER:
   2688       Error (NULL, 0, 2000, "Invalid parameter", "Invalid parameter passed to GenVtf function.");
   2689       break;
   2690 
   2691     case EFI_ABORTED:
   2692       Error (NULL, 0, 3000, "Invalid", "Error detected while creating the file image.");
   2693       break;
   2694 
   2695     case EFI_OUT_OF_RESOURCES:
   2696       Error (NULL, 0, 4002, "Resource", "GenVtfImage function could not allocate required resources.");
   2697       break;
   2698 
   2699     case EFI_VOLUME_CORRUPTED:
   2700       Error (NULL, 0, 3000, "Invalid", "No base address was specified.");
   2701       break;
   2702 
   2703     default:
   2704       Error (NULL, 0, 3000, "Invalid", "GenVtfImage function returned unknown status %x.", (int) Status );
   2705       break;
   2706     }
   2707   }
   2708 ERROR:
   2709   if (VtfFP != NULL) {
   2710     fclose (VtfFP);
   2711   }
   2712 
   2713   if (DebugMode) {
   2714     DebugMsg(UTILITY_NAME, 0, DebugLevel, "VTF image generated successful\n", NULL);
   2715   }
   2716 
   2717   if (VerboseMode) {
   2718     VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
   2719   }
   2720   return GetUtilityStatus();
   2721 }
   2722