Home | History | Annotate | Download | only in GenFvImage
      1 /*++
      2 
      3 Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   GenFvImageLib.c
     15 
     16 Abstract:
     17 
     18   This file contains functions required to generate a Firmware Volume.
     19 
     20 --*/
     21 
     22 //
     23 // Include files
     24 //
     25 #include "GenFvImageLib.h"
     26 #include "GenFvImageLibInternal.h"
     27 #include <string.h>
     28 #include EFI_GUID_DEFINITION (PeiPeCoffLoader)
     29 #include "EfiFirmwareFileSystem.h"
     30 #include "EfiWorkingBlockHeader.h"
     31 #include "EfiVariable.h"
     32 #include <io.h>
     33 #include <assert.h>
     34 #include "CommonLib.h"
     35 #include "FvLib.h"
     36 #include "EfiImage.h"
     37 #include "crc32.h"
     38 #include "EfiUtilityMsgs.h"
     39 #include EFI_GUID_DEFINITION (FirmwareFileSystem)
     40 #include EFI_GUID_DEFINITION (FirmwareFileSystem2)
     41 
     42 //
     43 // Define the PE/COFF loader
     44 //
     45 extern EFI_PEI_PE_COFF_LOADER_PROTOCOL  mPeCoffLoader;
     46 
     47 //
     48 // Local function prototypes
     49 //
     50 EFI_STATUS
     51 GetPe32Info (
     52   IN UINT8                  *Pe32,
     53   OUT UINT32                *EntryPoint,
     54   OUT UINT32                *BaseOfCode,
     55   OUT UINT16                *MachineType
     56   );
     57 
     58 //
     59 // Local function implementations.
     60 //
     61 #if (PI_SPECIFICATION_VERSION < 0x00010000)
     62 EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID;
     63 #else
     64 EFI_GUID  FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
     65 #endif
     66 
     67 EFI_GUID  DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f };
     68 
     69 //
     70 // This data array will be located at the base of the Firmware Volume Header (FVH)
     71 // in the boot block.  It must not exceed 14 bytes of code.  The last 2 bytes
     72 // will be used to keep the FVH checksum consistent.
     73 // This code will be run in response to a starutp IPI for HT-enabled systems.
     74 //
     75 #define SIZEOF_STARTUP_DATA_ARRAY 0x10
     76 
     77 UINT8                                   m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
     78   //
     79   // EA D0 FF 00 F0               ; far jmp F000:FFD0
     80   // 0, 0, 0, 0, 0, 0, 0, 0, 0,   ; Reserved bytes
     81   // 0, 0                         ; Checksum Padding
     82   //
     83   0xEA,
     84   0xD0,
     85   0xFF,
     86   0x0,
     87   0xF0,
     88   0x00,
     89   0x00,
     90   0x00,
     91   0x00,
     92   0x00,
     93   0x00,
     94   0x00,
     95   0x00,
     96   0x00,
     97   0x00,
     98   0x00
     99 };
    100 
    101 UINT8                                   m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
    102   //
    103   // EB CE                               ; jmp short ($-0x30)
    104   // ; (from offset 0x0 to offset 0xFFD0)
    105   // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
    106   // 0, 0                                ; Checksum Padding
    107   //
    108   0xEB,
    109   0xCE,
    110   0x00,
    111   0x00,
    112   0x00,
    113   0x00,
    114   0x00,
    115   0x00,
    116   0x00,
    117   0x00,
    118   0x00,
    119   0x00,
    120   0x00,
    121   0x00,
    122   0x00,
    123   0x00
    124 };
    125 
    126 EFI_STATUS
    127 ParseFvInf (
    128   IN MEMORY_FILE  *InfFile,
    129   IN FV_INFO      *FvInfo
    130   )
    131 /*++
    132 
    133 Routine Description:
    134 
    135   This function parses a FV.INF file and copies info into a FV_INFO structure.
    136 
    137 Arguments:
    138 
    139   InfFile         Memory file image.
    140   FvInfo          Information read from INF file.
    141 
    142 Returns:
    143 
    144   EFI_SUCCESS       INF file information successfully retrieved.
    145   EFI_ABORTED       INF file has an invalid format.
    146   EFI_NOT_FOUND     A required string was not found in the INF file.
    147 --*/
    148 {
    149   CHAR8       Value[_MAX_PATH];
    150   UINT64      Value64;
    151   UINTN       Index;
    152   EFI_STATUS  Status;
    153 
    154   //
    155   // Initialize FV info
    156   //
    157   memset (FvInfo, 0, sizeof (FV_INFO));
    158 
    159   //
    160   // Read the FV base address
    161   //
    162   Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
    163 
    164   if (Status == EFI_SUCCESS) {
    165     //
    166     // Get the base address
    167     //
    168     Status = AsciiStringToUint64 (Value, FALSE, &Value64);
    169     if (EFI_ERROR (Status)) {
    170       Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value");
    171       return EFI_ABORTED;
    172     }
    173 
    174     FvInfo->BaseAddress = Value64;
    175   } else {
    176     Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value");
    177     return EFI_ABORTED;
    178   }
    179   //
    180   // Read the FV Guid
    181   //
    182   Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value);
    183 
    184   if (Status == EFI_SUCCESS) {
    185     //
    186     // Get the guid value
    187     //
    188     Status = StringToGuid (Value, &FvInfo->FvGuid);
    189     if (EFI_ERROR (Status)) {
    190       memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
    191     }
    192   } else {
    193     memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID));
    194   }
    195   //
    196   // Read the FV file name
    197   //
    198   Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
    199 
    200   if (Status == EFI_SUCCESS) {
    201     //
    202     // copy the file name
    203     //
    204     strcpy (FvInfo->FvName, Value);
    205   } else {
    206     Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified");
    207     return EFI_ABORTED;
    208   }
    209   //
    210   // Read the Sym file name
    211   //
    212   Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value);
    213 
    214   if (Status == EFI_SUCCESS) {
    215     //
    216     // copy the file name
    217     //
    218     strcpy (FvInfo->SymName, Value);
    219   } else {
    220     //
    221     // Symbols not required, so init to NULL.
    222     //
    223     strcpy (FvInfo->SymName, "");
    224   }
    225   //
    226   // Read the read disabled capability attribute
    227   //
    228   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value);
    229 
    230   if (Status == EFI_SUCCESS) {
    231     //
    232     // Update the read disabled flag
    233     //
    234     if (strcmp (Value, TRUE_STRING) == 0) {
    235       FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP;
    236     } else if (strcmp (Value, FALSE_STRING) != 0) {
    237       Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    238       return EFI_ABORTED;
    239     }
    240   } else {
    241     Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified");
    242     return Status;
    243   }
    244   //
    245   // Read the read enabled capability attribute
    246   //
    247   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value);
    248 
    249   if (Status == EFI_SUCCESS) {
    250     //
    251     // Update the read disabled flag
    252     //
    253     if (strcmp (Value, TRUE_STRING) == 0) {
    254       FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP;
    255     } else if (strcmp (Value, FALSE_STRING) != 0) {
    256       Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    257       return EFI_ABORTED;
    258     }
    259   } else {
    260     Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified");
    261     return Status;
    262   }
    263   //
    264   // Read the read status attribute
    265   //
    266   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value);
    267 
    268   if (Status == EFI_SUCCESS) {
    269     //
    270     // Update the read disabled flag
    271     //
    272     if (strcmp (Value, TRUE_STRING) == 0) {
    273       FvInfo->FvAttributes |= EFI_FVB_READ_STATUS;
    274     } else if (strcmp (Value, FALSE_STRING) != 0) {
    275       Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    276       return EFI_ABORTED;
    277     }
    278   } else {
    279     Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified");
    280     return Status;
    281   }
    282   //
    283   // Read the write disabled capability attribute
    284   //
    285   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value);
    286 
    287   if (Status == EFI_SUCCESS) {
    288     //
    289     // Update the write disabled flag
    290     //
    291     if (strcmp (Value, TRUE_STRING) == 0) {
    292       FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP;
    293     } else if (strcmp (Value, FALSE_STRING) != 0) {
    294       Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    295       return EFI_ABORTED;
    296     }
    297   } else {
    298     Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified");
    299     return Status;
    300   }
    301   //
    302   // Read the write enabled capability attribute
    303   //
    304   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value);
    305 
    306   if (Status == EFI_SUCCESS) {
    307     //
    308     // Update the write disabled flag
    309     //
    310     if (strcmp (Value, TRUE_STRING) == 0) {
    311       FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP;
    312     } else if (strcmp (Value, FALSE_STRING) != 0) {
    313       Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    314       return EFI_ABORTED;
    315     }
    316   } else {
    317     Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified");
    318     return Status;
    319   }
    320   //
    321   // Read the write status attribute
    322   //
    323   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value);
    324 
    325   if (Status == EFI_SUCCESS) {
    326     //
    327     // Update the write disabled flag
    328     //
    329     if (strcmp (Value, TRUE_STRING) == 0) {
    330       FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS;
    331     } else if (strcmp (Value, FALSE_STRING) != 0) {
    332       Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    333       return EFI_ABORTED;
    334     }
    335   } else {
    336     Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified");
    337     return Status;
    338   }
    339   //
    340   // Read the lock capability attribute
    341   //
    342   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value);
    343 
    344   if (Status == EFI_SUCCESS) {
    345     //
    346     // Update the attribute flag
    347     //
    348     if (strcmp (Value, TRUE_STRING) == 0) {
    349       FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP;
    350     } else if (strcmp (Value, FALSE_STRING) != 0) {
    351       Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    352       return EFI_ABORTED;
    353     }
    354   } else {
    355     Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified");
    356     return Status;
    357   }
    358   //
    359   // Read the lock status attribute
    360   //
    361   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value);
    362 
    363   if (Status == EFI_SUCCESS) {
    364     //
    365     // Update the attribute flag
    366     //
    367     if (strcmp (Value, TRUE_STRING) == 0) {
    368       FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS;
    369     } else if (strcmp (Value, FALSE_STRING) != 0) {
    370       Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    371       return EFI_ABORTED;
    372     }
    373   } else {
    374     Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified");
    375     return Status;
    376   }
    377   //
    378   // Read the sticky write attribute
    379   //
    380   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value);
    381 
    382   if (Status == EFI_SUCCESS) {
    383     //
    384     // Update the attribute flag
    385     //
    386     if (strcmp (Value, TRUE_STRING) == 0) {
    387       FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE;
    388     } else if (strcmp (Value, FALSE_STRING) != 0) {
    389       Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    390       return EFI_ABORTED;
    391     }
    392   } else {
    393     Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified");
    394     return Status;
    395   }
    396   //
    397   // Read the memory mapped attribute
    398   //
    399   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value);
    400 
    401   if (Status == EFI_SUCCESS) {
    402     //
    403     // Update the attribute flag
    404     //
    405     if (strcmp (Value, TRUE_STRING) == 0) {
    406       FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED;
    407     } else if (strcmp (Value, FALSE_STRING) != 0) {
    408       Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    409       return EFI_ABORTED;
    410     }
    411   } else {
    412     Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified");
    413     return Status;
    414   }
    415   //
    416   // Read the erase polarity attribute
    417   //
    418   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value);
    419 
    420   if (Status == EFI_SUCCESS) {
    421     //
    422     // Update the attribute flag
    423     //
    424     if (strcmp (Value, ONE_STRING) == 0) {
    425       FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY;
    426     } else if (strcmp (Value, ZERO_STRING) != 0) {
    427       Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    428       return EFI_ABORTED;
    429     }
    430   } else {
    431     Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified");
    432     return Status;
    433   }
    434 
    435 #if (PI_SPECIFICATION_VERSION >= 0x00010000)
    436   //
    437   // Read the read lock capability attribute
    438   //
    439   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value);
    440 
    441   if (Status == EFI_SUCCESS) {
    442     //
    443     // Update attribute
    444     //
    445     if (strcmp (Value, TRUE_STRING) == 0) {
    446       FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP;
    447     } else if (strcmp (Value, FALSE_STRING) != 0) {
    448       Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    449       return EFI_ABORTED;
    450     }
    451   } else {
    452     Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified");
    453     return Status;
    454   }
    455 
    456   //
    457   // Read the read lock status attribute
    458   //
    459   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value);
    460 
    461   if (Status == EFI_SUCCESS) {
    462     //
    463     // Update attribute
    464     //
    465     if (strcmp (Value, TRUE_STRING) == 0) {
    466       FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS;
    467     } else if (strcmp (Value, FALSE_STRING) != 0) {
    468       Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    469       return EFI_ABORTED;
    470     }
    471   } else {
    472     Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified");
    473     return Status;
    474   }
    475 
    476   //
    477   // Read the write lock capability attribute
    478   //
    479   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value);
    480 
    481   if (Status == EFI_SUCCESS) {
    482     //
    483     // Update attribute
    484     //
    485     if (strcmp (Value, TRUE_STRING) == 0) {
    486       FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP;
    487     } else if (strcmp (Value, FALSE_STRING) != 0) {
    488       Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    489       return EFI_ABORTED;
    490     }
    491   } else {
    492     Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified");
    493     return Status;
    494   }
    495 
    496   //
    497   // Read the write lock status attribute
    498   //
    499   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value);
    500 
    501   if (Status == EFI_SUCCESS) {
    502     //
    503     // Update attribute
    504     //
    505     if (strcmp (Value, TRUE_STRING) == 0) {
    506       FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS;
    507     } else if (strcmp (Value, FALSE_STRING) != 0) {
    508       Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    509       return EFI_ABORTED;
    510     }
    511   } else {
    512     Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified");
    513     return Status;
    514   }
    515 #endif
    516 
    517 #if (PI_SPECIFICATION_VERSION < 0x00010000)
    518   //
    519   // Read the alignment capabilities attribute
    520   //
    521   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value);
    522 
    523   if (Status == EFI_SUCCESS) {
    524     //
    525     // Update attribute
    526     //
    527     if (strcmp (Value, TRUE_STRING) == 0) {
    528       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP;
    529     } else if (strcmp (Value, FALSE_STRING) != 0) {
    530       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    531       return EFI_ABORTED;
    532     }
    533   } else {
    534     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified");
    535     return Status;
    536   }
    537 
    538   //
    539   // Read the word alignment capability attribute
    540   //
    541   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value);
    542 
    543   if (Status == EFI_SUCCESS) {
    544     //
    545     // Update attribute
    546     //
    547     if (strcmp (Value, TRUE_STRING) == 0) {
    548       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2;
    549     } else if (strcmp (Value, FALSE_STRING) != 0) {
    550       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    551       return EFI_ABORTED;
    552     }
    553   } else {
    554     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified");
    555     return Status;
    556   }
    557 
    558 
    559   //
    560   // Read the dword alignment capability attribute
    561   //
    562   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value);
    563 
    564   if (Status == EFI_SUCCESS) {
    565     //
    566     // Update attribute
    567     //
    568     if (strcmp (Value, TRUE_STRING) == 0) {
    569       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4;
    570     } else if (strcmp (Value, FALSE_STRING) != 0) {
    571       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    572       return EFI_ABORTED;
    573     }
    574   } else {
    575     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified");
    576     return Status;
    577   }
    578   //
    579   // Read the word alignment capability attribute
    580   //
    581   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value);
    582 
    583   if (Status == EFI_SUCCESS) {
    584     //
    585     // Update attribute
    586     //
    587     if (strcmp (Value, TRUE_STRING) == 0) {
    588       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8;
    589     } else if (strcmp (Value, FALSE_STRING) != 0) {
    590       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    591       return EFI_ABORTED;
    592     }
    593   } else {
    594     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified");
    595     return Status;
    596   }
    597   //
    598   // Read the qword alignment capability attribute
    599   //
    600   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value);
    601 
    602   if (Status == EFI_SUCCESS) {
    603     //
    604     // Update attribute
    605     //
    606     if (strcmp (Value, TRUE_STRING) == 0) {
    607       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16;
    608     } else if (strcmp (Value, FALSE_STRING) != 0) {
    609       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    610       return EFI_ABORTED;
    611     }
    612   } else {
    613     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified");
    614     return Status;
    615   }
    616   //
    617   // Read the 32 byte alignment capability attribute
    618   //
    619   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value);
    620 
    621   if (Status == EFI_SUCCESS) {
    622     //
    623     // Update attribute
    624     //
    625     if (strcmp (Value, TRUE_STRING) == 0) {
    626       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32;
    627     } else if (strcmp (Value, FALSE_STRING) != 0) {
    628       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    629       return EFI_ABORTED;
    630     }
    631   } else {
    632     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified");
    633     return Status;
    634   }
    635   //
    636   // Read the 64 byte alignment capability attribute
    637   //
    638   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value);
    639 
    640   if (Status == EFI_SUCCESS) {
    641     //
    642     // Update attribute
    643     //
    644     if (strcmp (Value, TRUE_STRING) == 0) {
    645       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64;
    646     } else if (strcmp (Value, FALSE_STRING) != 0) {
    647       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    648       return EFI_ABORTED;
    649     }
    650   } else {
    651     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified");
    652     return Status;
    653   }
    654   //
    655   // Read the 128 byte alignment capability attribute
    656   //
    657   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value);
    658 
    659   if (Status == EFI_SUCCESS) {
    660     //
    661     // Update attribute
    662     //
    663     if (strcmp (Value, TRUE_STRING) == 0) {
    664       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128;
    665     } else if (strcmp (Value, FALSE_STRING) != 0) {
    666       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    667       return EFI_ABORTED;
    668     }
    669   } else {
    670     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified");
    671     return Status;
    672   }
    673   //
    674   // Read the 256 byte alignment capability attribute
    675   //
    676   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value);
    677 
    678   if (Status == EFI_SUCCESS) {
    679     //
    680     // Update attribute
    681     //
    682     if (strcmp (Value, TRUE_STRING) == 0) {
    683       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256;
    684     } else if (strcmp (Value, FALSE_STRING) != 0) {
    685       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    686       return EFI_ABORTED;
    687     }
    688   } else {
    689     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified");
    690     return Status;
    691   }
    692   //
    693   // Read the 512 byte alignment capability attribute
    694   //
    695   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value);
    696 
    697   if (Status == EFI_SUCCESS) {
    698     //
    699     // Update attribute
    700     //
    701     if (strcmp (Value, TRUE_STRING) == 0) {
    702       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512;
    703     } else if (strcmp (Value, FALSE_STRING) != 0) {
    704       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    705       return EFI_ABORTED;
    706     }
    707   } else {
    708     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified");
    709     return Status;
    710   }
    711   //
    712   // Read the 1K byte alignment capability attribute
    713   //
    714   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value);
    715 
    716   if (Status == EFI_SUCCESS) {
    717     //
    718     // Update attribute
    719     //
    720     if (strcmp (Value, TRUE_STRING) == 0) {
    721       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K;
    722     } else if (strcmp (Value, FALSE_STRING) != 0) {
    723       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    724       return EFI_ABORTED;
    725     }
    726   } else {
    727     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified");
    728     return Status;
    729   }
    730   //
    731   // Read the 2K byte alignment capability attribute
    732   //
    733   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value);
    734 
    735   if (Status == EFI_SUCCESS) {
    736     //
    737     // Update attribute
    738     //
    739     if (strcmp (Value, TRUE_STRING) == 0) {
    740       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K;
    741     } else if (strcmp (Value, FALSE_STRING) != 0) {
    742       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    743       return EFI_ABORTED;
    744     }
    745   } else {
    746     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified");
    747     return Status;
    748   }
    749   //
    750   // Read the 4K byte alignment capability attribute
    751   //
    752   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value);
    753 
    754   if (Status == EFI_SUCCESS) {
    755     //
    756     // Update attribute
    757     //
    758     if (strcmp (Value, TRUE_STRING) == 0) {
    759       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K;
    760     } else if (strcmp (Value, FALSE_STRING) != 0) {
    761       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    762       return EFI_ABORTED;
    763     }
    764   } else {
    765     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified");
    766     return Status;
    767   }
    768   //
    769   // Read the 8K byte alignment capability attribute
    770   //
    771   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value);
    772 
    773   if (Status == EFI_SUCCESS) {
    774     //
    775     // Update attribute
    776     //
    777     if (strcmp (Value, TRUE_STRING) == 0) {
    778       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K;
    779     } else if (strcmp (Value, FALSE_STRING) != 0) {
    780       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    781       return EFI_ABORTED;
    782     }
    783   } else {
    784     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified");
    785     return Status;
    786   }
    787   //
    788   // Read the 16K byte alignment capability attribute
    789   //
    790   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value);
    791 
    792   if (Status == EFI_SUCCESS) {
    793     //
    794     // Update attribute
    795     //
    796     if (strcmp (Value, TRUE_STRING) == 0) {
    797       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K;
    798     } else if (strcmp (Value, FALSE_STRING) != 0) {
    799       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    800       return EFI_ABORTED;
    801     }
    802   } else {
    803     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified");
    804     return Status;
    805   }
    806   //
    807   // Read the 32K byte alignment capability attribute
    808   //
    809   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value);
    810 
    811   if (Status == EFI_SUCCESS) {
    812     //
    813     // Update attribute
    814     //
    815     if (strcmp (Value, TRUE_STRING) == 0) {
    816       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K;
    817     } else if (strcmp (Value, FALSE_STRING) != 0) {
    818       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    819       return EFI_ABORTED;
    820     }
    821   } else {
    822     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified");
    823     return Status;
    824   }
    825   //
    826   // Read the 64K byte alignment capability attribute
    827   //
    828   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value);
    829 
    830   if (Status == EFI_SUCCESS) {
    831     //
    832     // Update attribute
    833     //
    834     if (strcmp (Value, TRUE_STRING) == 0) {
    835       FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K;
    836     } else if (strcmp (Value, FALSE_STRING) != 0) {
    837       Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING);
    838       return EFI_ABORTED;
    839     }
    840   } else {
    841     Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified");
    842     return Status;
    843   }
    844 
    845   if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) &&
    846       (
    847         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) ||
    848         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) ||
    849         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) ||
    850         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) ||
    851         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) ||
    852         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) ||
    853         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) ||
    854         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) ||
    855         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) ||
    856         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) ||
    857         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) ||
    858         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) ||
    859         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) ||
    860         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) ||
    861         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) ||
    862         (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K)
    863       )
    864      ){
    865     Error (
    866       NULL,
    867       0,
    868       0,
    869       "illegal combination of alignment attributes",
    870       "if %s is not %s, no individual alignments can be %s",
    871       EFI_FVB_ALIGNMENT_CAP_STRING,
    872       TRUE_STRING,
    873       TRUE_STRING
    874       );
    875     return EFI_ABORTED;
    876   }
    877 #else
    878   //
    879   // Read the PI1.0 FVB2 Alignment Capabilities Attribute
    880   //
    881   Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value);
    882 
    883   if (Status == EFI_SUCCESS) {
    884     //
    885     // Update attribute
    886     //
    887     if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) {
    888       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1;
    889     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) {
    890       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2;
    891     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) {
    892       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4;
    893     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) {
    894       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8;
    895     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) {
    896       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16;
    897     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) {
    898       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32;
    899     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) {
    900       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64;
    901     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) {
    902       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128;
    903     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) {
    904       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256;
    905     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) {
    906       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512;
    907     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) {
    908       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K;
    909     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) {
    910       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K;
    911     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) {
    912       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K;
    913     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) {
    914       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K;
    915     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) {
    916       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K;
    917     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) {
    918       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K;
    919     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) {
    920       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K;
    921     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) {
    922       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K;
    923     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) {
    924       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K;
    925     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) {
    926       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512K;
    927     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) {
    928       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M;
    929     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) {
    930       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M;
    931     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) {
    932       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M;
    933     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) {
    934       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M;
    935     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) {
    936       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M;
    937     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) {
    938       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M;
    939     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) {
    940       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M;
    941     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) {
    942       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M;
    943     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) {
    944       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M;
    945     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) {
    946       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M;
    947     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) {
    948       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G;
    949     } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) {
    950       FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G;
    951     } else {
    952       Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!");
    953       return EFI_ABORTED;
    954     }
    955   } else {
    956     Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified");
    957     return Status;
    958   }
    959 
    960 #endif
    961   //
    962   // Read block maps
    963   //
    964   for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
    965     //
    966     // Read the number of blocks
    967     //
    968     Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
    969 
    970     if (Status == EFI_SUCCESS) {
    971       if (strcmp (Value, AUTO_STRING) == 0) {
    972         Value64 = (UINT64) -1;
    973       } else {
    974         //
    975         // Update the number of blocks
    976         //
    977         Status = AsciiStringToUint64 (Value, FALSE, &Value64);
    978         if (EFI_ERROR (Status)) {
    979           Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING);
    980           return EFI_ABORTED;
    981         }
    982       }
    983 
    984       FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
    985     } else {
    986       //
    987       // If there is no number of blocks, but there is a size, then we have a mismatched pair
    988       // and should return an error.
    989       //
    990       Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
    991       if (!EFI_ERROR (Status)) {
    992         Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
    993         return EFI_ABORTED;
    994       } else {
    995         //
    996         // We are done
    997         //
    998         break;
    999       }
   1000     }
   1001     //
   1002     // Read the size of blocks
   1003     //
   1004     Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
   1005 
   1006     if (Status == EFI_SUCCESS) {
   1007       //
   1008       // Update the number of blocks
   1009       //
   1010       Status = AsciiStringToUint64 (Value, FALSE, &Value64);
   1011       if (EFI_ERROR (Status)) {
   1012         Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING);
   1013         return EFI_ABORTED;
   1014       }
   1015 
   1016       FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64;
   1017     } else {
   1018       //
   1019       // There is a number of blocks, but there is no size, so we have a mismatched pair
   1020       // and should return an error.
   1021       //
   1022       Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
   1023       return EFI_ABORTED;
   1024     }
   1025   }
   1026   //
   1027   // Read files
   1028   //
   1029   for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
   1030     //
   1031     // Read the number of blocks
   1032     //
   1033     Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
   1034 
   1035     if (Status == EFI_SUCCESS) {
   1036       //
   1037       // Add the file
   1038       //
   1039       strcpy (FvInfo->FvFiles[Index], Value);
   1040     } else {
   1041       break;
   1042     }
   1043   }
   1044 
   1045   if (FindSection (InfFile, COMPONENT_SECTION_STRING)) {
   1046     Index = 0;
   1047     while (TRUE) {
   1048       Status = FindTokenInstanceInSection (
   1049                  InfFile,
   1050                  COMPONENT_SECTION_STRING,
   1051                  Index,
   1052                  FvInfo->FvComponents[Index].ComponentName,
   1053                  Value
   1054                  );
   1055       if (EFI_ERROR (Status)) {
   1056         break;
   1057       }
   1058       Status = AsciiStringToUint64 (Value, FALSE, &Value64);
   1059       if (EFI_ERROR (Status)) {
   1060         Error (NULL, 0, 0, Value, "not a valid integer");
   1061         return EFI_ABORTED;
   1062       }
   1063 
   1064       FvInfo->FvComponents[Index].Size = (UINTN) Value64;
   1065       Index++;
   1066     }
   1067   }
   1068   //
   1069   // Compute size for easy access later
   1070   //
   1071   FvInfo->Size = 0;
   1072   for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) {
   1073     if ((FvInfo->Size == (UINTN) -1 && Index > 0) ||
   1074         (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1 && Index > 0)
   1075         ) {
   1076       //
   1077       // Error 1. more pairs after AUTO
   1078       // Error 2. AUTO appear in non-first position
   1079       //
   1080       Error (NULL, 0, 0, NULL, "cannot have more than one pair of %s and %s if %s is set to %s",
   1081         EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING,
   1082         EFI_NUM_BLOCKS_STRING, AUTO_STRING
   1083         );
   1084       return EFI_ABORTED;
   1085     }
   1086 
   1087     if (FvInfo->FvBlocks[Index].NumBlocks == (UINT32) -1) {
   1088       FvInfo->Size = (UINTN) -1;
   1089     } else {
   1090       FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength;
   1091     }
   1092   }
   1093 
   1094   if (FvInfo->Size == (UINTN) -1 && FvInfo->FvFiles[0][0] == 0) {
   1095     //
   1096     // Non FFS FV cannot set block number to AUTO
   1097     //
   1098     Error (NULL, 0, 0, "non-FFS FV", "cannot set %s to %s",   EFI_NUM_BLOCKS_STRING, AUTO_STRING);
   1099     return EFI_ABORTED;
   1100   }
   1101 
   1102   return EFI_SUCCESS;
   1103 }
   1104 
   1105 VOID
   1106 UpdateFfsFileState (
   1107   IN EFI_FFS_FILE_HEADER          *FfsFile,
   1108   IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader
   1109   )
   1110 /*++
   1111 
   1112 Routine Description:
   1113 
   1114   This function changes the FFS file attributes based on the erase polarity
   1115   of the FV.
   1116 
   1117 Arguments:
   1118 
   1119   FfsFile   File header.
   1120   FvHeader  FV header.
   1121 
   1122 Returns:
   1123 
   1124   None
   1125 
   1126 --*/
   1127 {
   1128   if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
   1129     FfsFile->State = (UINT8)~(FfsFile->State);
   1130   }
   1131 }
   1132 
   1133 EFI_STATUS
   1134 ReadFfsAlignment (
   1135   IN EFI_FFS_FILE_HEADER    *FfsFile,
   1136   IN OUT UINT32             *Alignment
   1137   )
   1138 /*++
   1139 
   1140 Routine Description:
   1141 
   1142   This function determines the alignment of the FFS input file from the file
   1143   attributes.
   1144 
   1145 Arguments:
   1146 
   1147   FfsFile       FFS file to parse
   1148   Alignment     The minimum required alignment of the FFS file, in bytes
   1149 
   1150 Returns:
   1151 
   1152   EFI_SUCCESS              The function completed successfully.
   1153   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
   1154   EFI_ABORTED              An error occurred.
   1155 
   1156 --*/
   1157 {
   1158   //
   1159   // Verify input parameters.
   1160   //
   1161   if (FfsFile == NULL || Alignment == NULL) {
   1162     return EFI_INVALID_PARAMETER;
   1163   }
   1164 
   1165   switch ((FfsFile->Attributes >> 3) & 0x07) {
   1166 
   1167   case 0:
   1168     //
   1169     // 1 byte alignment
   1170     //
   1171     *Alignment = (1 << 0);
   1172     break;
   1173 
   1174   case 1:
   1175     //
   1176     // 16 byte alignment
   1177     //
   1178     *Alignment = (1 << 4);
   1179     break;
   1180 
   1181   case 2:
   1182     //
   1183     // 128 byte alignment
   1184     //
   1185     *Alignment = (1 << 7);
   1186     break;
   1187 
   1188   case 3:
   1189     //
   1190     // 512 byte alignment
   1191     //
   1192     *Alignment = (1 << 9);
   1193     break;
   1194 
   1195   case 4:
   1196     //
   1197     // 1K byte alignment
   1198     //
   1199     *Alignment = (1 << 10);
   1200     break;
   1201 
   1202   case 5:
   1203     //
   1204     // 4K byte alignment
   1205     //
   1206     *Alignment = (1 << 12);
   1207     break;
   1208 
   1209   case 6:
   1210     //
   1211     // 32K byte alignment
   1212     //
   1213     *Alignment = (1 << 15);
   1214     break;
   1215 
   1216   case 7:
   1217     //
   1218     // 64K byte alignment
   1219     //
   1220     *Alignment = (1 << 16);
   1221     break;
   1222 
   1223   default:
   1224     Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL);
   1225     return EFI_ABORTED;
   1226   }
   1227 
   1228   return EFI_SUCCESS;
   1229 }
   1230 
   1231 EFI_STATUS
   1232 AddPadFile (
   1233   IN OUT MEMORY_FILE  *FvImage,
   1234   IN UINT32           DataAlignment
   1235   )
   1236 /*++
   1237 
   1238 Routine Description:
   1239 
   1240   This function adds a pad file to the FV image if it required to align the
   1241   data of the next file.
   1242 
   1243 Arguments:
   1244 
   1245   FvImage         The memory image of the FV to add it to.  The current offset
   1246                   must be valid.
   1247   DataAlignment   The data alignment of the next FFS file.
   1248 
   1249 Returns:
   1250 
   1251   EFI_SUCCESS              The function completed successfully.
   1252   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
   1253   EFI_OUT_OF_RESOURCES     Insufficient resources exist in the FV to complete
   1254                            the pad file add.
   1255 
   1256 --*/
   1257 {
   1258   EFI_FFS_FILE_HEADER *PadFile;
   1259   UUID                PadFileGuid;
   1260   UINTN               PadFileSize;
   1261 
   1262   //
   1263   // Verify input parameters.
   1264   //
   1265   if (FvImage == NULL) {
   1266     return EFI_INVALID_PARAMETER;
   1267   }
   1268   //
   1269   // Basic assumption is we start from an 8 byte aligned address
   1270   // and our file header is a multiple of 8 bytes
   1271   //
   1272   assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0);
   1273   assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0);
   1274 
   1275   //
   1276   // Check if a pad file is necessary
   1277   //
   1278   if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) {
   1279     return EFI_SUCCESS;
   1280   }
   1281   //
   1282   // Write pad file header
   1283   //
   1284   PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
   1285 
   1286   //
   1287   // Verify that we have enough space for the file header
   1288   //
   1289   if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
   1290     return EFI_OUT_OF_RESOURCES;
   1291   }
   1292 
   1293   UuidCreate (&PadFileGuid);
   1294   memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
   1295   memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID));
   1296   PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
   1297   PadFile->Attributes = 0;
   1298 
   1299   //
   1300   // Calculate the pad file size
   1301   //
   1302   //
   1303   // This is the earliest possible valid offset (current plus pad file header
   1304   // plus the next file header)
   1305   //
   1306   PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2);
   1307 
   1308   //
   1309   // Add whatever it takes to get to the next aligned address
   1310   //
   1311   while ((PadFileSize % DataAlignment) != 0) {
   1312     PadFileSize++;
   1313   }
   1314   //
   1315   // Subtract the next file header size
   1316   //
   1317   PadFileSize -= sizeof (EFI_FFS_FILE_HEADER);
   1318 
   1319   //
   1320   // Subtract the starting offset to get size
   1321   //
   1322   PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
   1323 
   1324   //
   1325   // Write pad file size (calculated size minus next file header size)
   1326   //
   1327   PadFile->Size[0]  = (UINT8) (PadFileSize & 0xFF);
   1328   PadFile->Size[1]  = (UINT8) ((PadFileSize >> 8) & 0xFF);
   1329   PadFile->Size[2]  = (UINT8) ((PadFileSize >> 16) & 0xFF);
   1330 
   1331   //
   1332   // Fill in checksums and state, they must be 0 for checksumming.
   1333   //
   1334   PadFile->IntegrityCheck.Checksum.Header = 0;
   1335   PadFile->IntegrityCheck.Checksum.File   = 0;
   1336   PadFile->State                          = 0;
   1337   PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
   1338   if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
   1339 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   1340     PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize);
   1341 #else
   1342     PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN)PadFile + sizeof (EFI_FFS_FILE_HEADER)), PadFileSize - sizeof (EFI_FFS_FILE_HEADER));
   1343 #endif
   1344   } else {
   1345     PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
   1346   }
   1347 
   1348   PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
   1349   UpdateFfsFileState (
   1350     (EFI_FFS_FILE_HEADER *) PadFile,
   1351     (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
   1352     );
   1353 
   1354   //
   1355   // Verify that we have enough space (including the padding
   1356   //
   1357   if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) {
   1358     return EFI_OUT_OF_RESOURCES;
   1359   }
   1360   //
   1361   // Update the current FV pointer
   1362   //
   1363   FvImage->CurrentFilePointer += PadFileSize;
   1364 
   1365   return EFI_SUCCESS;
   1366 }
   1367 
   1368 BOOLEAN
   1369 IsVtfFile (
   1370   IN EFI_FFS_FILE_HEADER    *FileBuffer
   1371   )
   1372 /*++
   1373 
   1374 Routine Description:
   1375 
   1376   This function checks the header to validate if it is a VTF file
   1377 
   1378 Arguments:
   1379 
   1380   FileBuffer     Buffer in which content of a file has been read.
   1381 
   1382 Returns:
   1383 
   1384   TRUE    If this is a VTF file
   1385   FALSE   If this is not a VTF file
   1386 
   1387 --*/
   1388 {
   1389   EFI_GUID  VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
   1390   if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) {
   1391     return TRUE;
   1392   } else {
   1393     return FALSE;
   1394   }
   1395 }
   1396 
   1397 EFI_STATUS
   1398 FfsRebaseImageRead (
   1399   IN     VOID    *FileHandle,
   1400   IN     UINTN   FileOffset,
   1401   IN OUT UINT32  *ReadSize,
   1402   OUT    VOID    *Buffer
   1403   )
   1404 /*++
   1405 
   1406 Routine Description:
   1407 
   1408   Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
   1409 
   1410 Arguments:
   1411 
   1412   FileHandle - The handle to the PE/COFF file
   1413 
   1414   FileOffset - The offset, in bytes, into the file to read
   1415 
   1416   ReadSize   - The number of bytes to read from the file starting at FileOffset
   1417 
   1418   Buffer     - A pointer to the buffer to read the data into.
   1419 
   1420 Returns:
   1421 
   1422   EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
   1423 
   1424 --*/
   1425 {
   1426   CHAR8   *Destination8;
   1427   CHAR8   *Source8;
   1428   UINT32  Length;
   1429 
   1430   Destination8  = Buffer;
   1431   Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
   1432   Length        = *ReadSize;
   1433   while (Length--) {
   1434     *(Destination8++) = *(Source8++);
   1435   }
   1436 
   1437   return EFI_SUCCESS;
   1438 }
   1439 
   1440 EFI_STATUS
   1441 RebaseFfsFile (
   1442   IN OUT EFI_FFS_FILE_HEADER    *FfsFile,
   1443   IN EFI_PHYSICAL_ADDRESS       BaseAddress
   1444   )
   1445 /*++
   1446 
   1447 Routine Description:
   1448 
   1449   This function determines if a file is XIP and should be rebased.  It will
   1450   rebase any PE32 sections found in the file using the base address.
   1451 
   1452 Arguments:
   1453 
   1454   FfsFile           A pointer to Ffs file image.
   1455   BaseAddress       The base address to use for rebasing the file image.
   1456 
   1457 Returns:
   1458 
   1459   EFI_SUCCESS             The image was properly rebased.
   1460   EFI_INVALID_PARAMETER   An input parameter is invalid.
   1461   EFI_ABORTED             An error occurred while rebasing the input file image.
   1462   EFI_OUT_OF_RESOURCES    Could not allocate a required resource.
   1463 
   1464 --*/
   1465 {
   1466   EFI_STATUS                            Status;
   1467   EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
   1468   UINTN                                 MemoryImagePointer;
   1469   UINTN                                 MemoryImagePointerAligned;
   1470 
   1471   EFI_PHYSICAL_ADDRESS                  ImageAddress;
   1472   UINT64                                ImageSize;
   1473   EFI_PHYSICAL_ADDRESS                  EntryPoint;
   1474 
   1475   UINT32                                Pe32FileSize;
   1476   UINT32                                NewPe32BaseAddress;
   1477 
   1478   UINTN                                 Index;
   1479   EFI_FILE_SECTION_POINTER              CurrentPe32Section;
   1480   UINT8                                 FileGuidString[80];
   1481 
   1482   //
   1483   // Verify input parameters
   1484   //
   1485   if (FfsFile == NULL) {
   1486     return EFI_INVALID_PARAMETER;
   1487   }
   1488   //
   1489   // Convert the GUID to a string so we can at least report which file
   1490   // if we find an error.
   1491   //
   1492   PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
   1493 
   1494   //
   1495   // Do some nominal checks on the file, then check for XIP.
   1496   //
   1497   Status = VerifyFfsFile (FfsFile);
   1498   if (EFI_ERROR (Status)) {
   1499     Error (NULL, 0, 0, "invalid FFS file", FileGuidString);
   1500     return EFI_INVALID_PARAMETER;
   1501   }
   1502 
   1503   if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
   1504       FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
   1505       FfsFile->Type != EFI_FV_FILETYPE_PEIM
   1506       ) {
   1507     //
   1508     // File is not XIP, so don't rebase
   1509     //
   1510     return EFI_SUCCESS;
   1511   }
   1512   //
   1513   // Rebase each PE32 section
   1514   //
   1515   for (Index = 1;; Index++) {
   1516     Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
   1517     if (EFI_ERROR (Status)) {
   1518       break;
   1519     }
   1520     //
   1521     // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section
   1522     //
   1523     NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile);
   1524 
   1525     //
   1526     // Initialize context
   1527     //
   1528     memset (&ImageContext, 0, sizeof (ImageContext));
   1529     ImageContext.Handle     = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
   1530     ImageContext.ImageRead  = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
   1531 
   1532     Status                  = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext);
   1533 
   1534     if (EFI_ERROR (Status)) {
   1535       Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString);
   1536       return Status;
   1537     }
   1538     //
   1539     // Allocate a buffer for the image to be loaded into.
   1540     //
   1541     Pe32FileSize              = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size);
   1542     MemoryImagePointer        = (UINTN) (malloc (Pe32FileSize + 0x1000));
   1543     MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12);
   1544     if (MemoryImagePointerAligned == 0) {
   1545       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1546       return EFI_OUT_OF_RESOURCES;
   1547     }
   1548 
   1549     //
   1550     // bugbug
   1551     //
   1552     ImageContext.ImageAddress = MemoryImagePointerAligned;
   1553     Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext);
   1554     if (EFI_ERROR (Status)) {
   1555       Error (NULL, 0, 0, "LoadImage() failure", FileGuidString);
   1556       free ((VOID *) MemoryImagePointer);
   1557       return Status;
   1558     }
   1559 
   1560     Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext);
   1561     if (EFI_ERROR (Status)) {
   1562       Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString);
   1563       free ((VOID *) MemoryImagePointer);
   1564       return Status;
   1565     }
   1566 
   1567     ImageAddress  = ImageContext.ImageAddress;
   1568     ImageSize     = ImageContext.ImageSize;
   1569     EntryPoint    = ImageContext.EntryPoint;
   1570 
   1571     if (ImageSize > Pe32FileSize) {
   1572       Error (
   1573         NULL,
   1574         0,
   1575         0,
   1576         "rebased PE32 is larger than original PE32 image",
   1577         "0x%X > 0x%X on file %s",
   1578         ImageSize,
   1579         Pe32FileSize,
   1580         FileGuidString
   1581         );
   1582       free ((VOID *) MemoryImagePointer);
   1583       return EFI_ABORTED;
   1584     }
   1585 
   1586     memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize);
   1587 
   1588     free ((VOID *) MemoryImagePointer);
   1589   }
   1590   //
   1591   // the above for loop will always exit with EFI_NOT_FOUND if it completes
   1592   // normally.  If Index == 1 at exit, then no PE32 sections were found.  If it
   1593   // exits with any other error code, then something broke...
   1594   //
   1595   if (Status != EFI_NOT_FOUND) {
   1596     Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString);
   1597     return Status;
   1598   }
   1599 
   1600   return EFI_SUCCESS;
   1601 }
   1602 
   1603 EFI_STATUS
   1604 AddSymFile (
   1605   IN UINT64               BaseAddress,
   1606   IN EFI_FFS_FILE_HEADER  *FfsFile,
   1607   IN OUT MEMORY_FILE      *SymImage,
   1608   IN CHAR8                *SourceFileName
   1609   )
   1610 /*++
   1611 
   1612 Routine Description:
   1613 
   1614   This function adds the SYM tokens in the source file to the destination file.
   1615   The SYM tokens are updated to reflect the base address.
   1616 
   1617 Arguments:
   1618 
   1619   BaseAddress     The base address for the new SYM tokens.
   1620   FfsFile         Pointer to the beginning of the FFS file in question.
   1621   SymImage        The memory file to update with symbol information.
   1622   SourceFileName  The source file.
   1623 
   1624 Returns:
   1625 
   1626   EFI_SUCCESS              The function completed successfully.
   1627   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
   1628   EFI_ABORTED              An error occurred.
   1629 
   1630 --*/
   1631 {
   1632   FILE                      *SourceFile;
   1633 
   1634   CHAR8                     Buffer[_MAX_PATH];
   1635   CHAR8                     Type[_MAX_PATH];
   1636   CHAR8                     Address[_MAX_PATH];
   1637   CHAR8                     Section[_MAX_PATH];
   1638   CHAR8                     Token[_MAX_PATH];
   1639   CHAR8                     SymFileName[_MAX_PATH];
   1640   CHAR8                     CodeModuleName[_MAX_PATH];
   1641   CHAR8                     *Ptr;
   1642 
   1643   UINT64                    TokenAddress;
   1644 
   1645   EFI_STATUS                Status;
   1646   EFI_FILE_SECTION_POINTER  Pe32Section;
   1647   UINT32                    EntryPoint;
   1648   UINT32                    BaseOfCode;
   1649   UINT16                    MachineType;
   1650 
   1651   //
   1652   // Verify input parameters.
   1653   //
   1654   if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) {
   1655     Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL);
   1656     return EFI_INVALID_PARAMETER;
   1657   }
   1658   //
   1659   // Check if we want to add this file
   1660   //
   1661   //
   1662   // Get the file name
   1663   //
   1664   strcpy (Buffer, SourceFileName);
   1665 
   1666   //
   1667   // Copy the file name for the path of the sym file and truncate the name portion.
   1668   //
   1669   strcpy (SymFileName, Buffer);
   1670   Ptr = strrchr (SymFileName, '\\');
   1671   assert (Ptr);
   1672   Ptr[0] = 0;
   1673 
   1674   //
   1675   // Find the file extension and make it lower case
   1676   //
   1677   Ptr = strrchr (SymFileName, '.');
   1678   if (Ptr != NULL) {
   1679     _strlwr (Ptr);
   1680   }
   1681   //
   1682   // Check if it is PEI file
   1683   //
   1684   if (strstr (Buffer, ".pei") != NULL) {
   1685     //
   1686     // Find the human readable portion
   1687     //
   1688     if (!strtok (Buffer, "-") ||
   1689         !strtok (NULL, "-") ||
   1690         !strtok (NULL, "-") ||
   1691         !strtok (NULL, "-") ||
   1692         !strtok (NULL, "-") ||
   1693         !strcpy (Buffer, strtok (NULL, "."))
   1694           ) {
   1695       Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL);
   1696       return EFI_ABORTED;
   1697     }
   1698     //
   1699     // Save code module name
   1700     //
   1701     strcpy (CodeModuleName, Buffer);
   1702 
   1703     //
   1704     // Add the symbol file name and extension to the file path.
   1705     //
   1706     strcat (Buffer, ".sym");
   1707     strcat (SymFileName, "\\");
   1708     strcat (SymFileName, Buffer);
   1709   } else {
   1710     //
   1711     // Only handle PEIM files.
   1712     //
   1713     return EFI_SUCCESS;
   1714   }
   1715   //
   1716   // Find PE32 section
   1717   //
   1718   Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section);
   1719 
   1720   //
   1721   // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address
   1722   //
   1723   if (Status == EFI_NOT_FOUND) {
   1724     Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section);
   1725   }
   1726 
   1727   if (Status == EFI_SUCCESS) {
   1728     Status = GetPe32Info (
   1729                (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
   1730                &EntryPoint,
   1731                &BaseOfCode,
   1732                &MachineType
   1733                );
   1734   } else {
   1735     if (Status == EFI_NOT_FOUND) {
   1736       BaseOfCode = 0x60;
   1737       Status     = EFI_SUCCESS;
   1738     } else {
   1739       Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL);
   1740       return Status;
   1741     }
   1742   }
   1743 
   1744   if (EFI_ERROR (Status)) {
   1745     Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL);
   1746     return Status;
   1747   }
   1748 
   1749   //
   1750   // Open the source file
   1751   //
   1752   SourceFile = fopen (SymFileName, "r");
   1753   if (SourceFile == NULL) {
   1754     //
   1755     // SYM files are not required.
   1756     //
   1757     return EFI_SUCCESS;
   1758   }
   1759   //
   1760   // Read the first line
   1761   //
   1762   if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) {
   1763     Buffer[0] = 0;
   1764   }
   1765   //
   1766   // Make sure it matches the expected sym format
   1767   //
   1768   if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) {
   1769     fclose (SourceFile);
   1770     Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL);
   1771     return EFI_ABORTED;
   1772   }
   1773   //
   1774   // Read in the file
   1775   //
   1776   while (feof (SourceFile) == 0) {
   1777     //
   1778     // Read a line
   1779     //
   1780     if (fscanf (
   1781           SourceFile,
   1782           "%s | %s | %s | %s\n",
   1783           Type,
   1784           Address,
   1785           Section,
   1786           Token
   1787           ) == 4) {
   1788       //
   1789       // If the token starts with "??" ignore it
   1790       //
   1791       if (Token[0] == '?' && Token[1] == '?') {
   1792         continue;
   1793       }
   1794       //
   1795       // Get the token address
   1796       //
   1797       AsciiStringToUint64 (Address, TRUE, &TokenAddress);
   1798 
   1799       //
   1800       // Add the base address
   1801       //
   1802       TokenAddress += BaseAddress;
   1803 
   1804       //
   1805       // If PE32 or TE section then find the start of code.  For PIC it is hardcoded.
   1806       //
   1807       if (Pe32Section.Pe32Section) {
   1808         //
   1809         // Add the offset of the PE32 section
   1810         //
   1811         TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile;
   1812 
   1813         //
   1814         // Add the size of the PE32 section header
   1815         //
   1816         TokenAddress += sizeof (EFI_PE32_SECTION);
   1817       } else {
   1818         //
   1819         // BUGBUG: Don't know why this is 0x28 bytes.
   1820         //
   1821         TokenAddress += 0x28;
   1822       }
   1823       //
   1824       // Add the beginning of the code
   1825       //
   1826       TokenAddress += BaseOfCode;
   1827 
   1828       sprintf (
   1829         Buffer,
   1830         "%s | %016I64X | %s | _%s%s\n",
   1831         Type,
   1832         TokenAddress,
   1833         Section,
   1834         CodeModuleName,
   1835         Token
   1836         );
   1837       memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1);
   1838       SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1);
   1839     }
   1840   }
   1841 
   1842   fclose (SourceFile);
   1843   return EFI_SUCCESS;
   1844 }
   1845 
   1846 EFI_STATUS
   1847 ReallocateFvImage (
   1848   IN OUT MEMORY_FILE         *FvImage,
   1849   IN OUT FV_INFO             *FvInfo,
   1850   IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
   1851   IN OUT UINTN               *FvImageCapacity
   1852   )
   1853 /*++
   1854 Routine Description:
   1855   Increase the size of FV image by 1 block. The routine may reallocate memory
   1856   depending on the capacity of the FV image.
   1857 
   1858 Arguments:
   1859   FvImage         The memory image of the FV to add it to.  The current offset
   1860                   must be valid.
   1861   FvInfo          Pointer to information about the FV.
   1862   VtfFileImage    A pointer to the VTF file within the FvImage.  If this is equal
   1863                   to the end of the FvImage then no VTF previously found.
   1864   FvImageCapacity Capacity of image buffer for FV.
   1865 
   1866 Returns:
   1867   EFI_SUCCESS              The function completed successfully.
   1868   EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the reallocation.
   1869 
   1870 --*/
   1871 {
   1872   CHAR8                      *FileImage;
   1873   UINTN                      OldSize;
   1874   UINTN                      IncreaseSize;
   1875   EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
   1876   BOOLEAN                    AllocateNewMemory;
   1877   EFI_FFS_FILE_HEADER        *NewVtfFileImage;
   1878   UINT32                     VtfFileLength;
   1879   UINT8                      TempByte;
   1880 
   1881   OldSize      = (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage;
   1882   IncreaseSize = FvInfo->FvBlocks[0].BlockLength;
   1883   assert (OldSize == FvInfo->FvBlocks[0].NumBlocks * FvInfo->FvBlocks[0].BlockLength);
   1884 
   1885   //
   1886   // Assume we have enough capacity
   1887   //
   1888   AllocateNewMemory = FALSE;
   1889 
   1890 
   1891   if (OldSize + IncreaseSize > *FvImageCapacity) {
   1892     AllocateNewMemory = TRUE;
   1893     //
   1894     // Increase capacity by one unit
   1895     //
   1896     *FvImageCapacity = OldSize + FV_CAPACITY_INCREASE_UNIT;
   1897     FileImage = malloc (*FvImageCapacity);
   1898 
   1899     if (FileImage == NULL) {
   1900       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1901       return EFI_OUT_OF_RESOURCES;
   1902     }
   1903 
   1904     //
   1905     // Initialize the content per FV polarity
   1906     //
   1907     if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
   1908       memset (FileImage, -1, *FvImageCapacity);
   1909     } else {
   1910       memset (FileImage, 0, *FvImageCapacity);
   1911     }
   1912 
   1913     //
   1914     // Copy the FV content before VTF
   1915     //
   1916     memcpy (FileImage, FvImage->FileImage, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage);
   1917   } else {
   1918     FileImage = FvImage->FileImage;
   1919   }
   1920 
   1921   //
   1922   // Move VTF if it exists
   1923   //
   1924   NewVtfFileImage = (EFI_FFS_FILE_HEADER *) (FileImage + ((UINTN) *VtfFileImage - (UINTN) FvImage->FileImage) + IncreaseSize);
   1925   if ((UINTN) *VtfFileImage != (UINTN) FvImage->Eof) {
   1926     //
   1927     // Exchange the VTF buffer from end to start for two purpose:
   1928     // 1. Exchange: Preserve the default value per FV polarity
   1929     // 2. End->Start: Avoid destroying the VTF data during exchanging
   1930     //
   1931     VtfFileLength = GetLength ((*VtfFileImage)->Size);
   1932     while (VtfFileLength-- != 0) {
   1933       TempByte = ((UINT8 *) VtfFileImage)[VtfFileLength];
   1934       ((UINT8 *) VtfFileImage)[VtfFileLength]    = ((UINT8 *) NewVtfFileImage)[VtfFileLength];
   1935       ((UINT8 *) NewVtfFileImage)[VtfFileLength] = TempByte;
   1936     }
   1937   }
   1938 
   1939   //
   1940   // Update VTF Pointer
   1941   //
   1942   *VtfFileImage = NewVtfFileImage;
   1943 
   1944   //
   1945   // Update FvInfo
   1946   //
   1947   FvInfo->FvBlocks[0].NumBlocks ++;
   1948 
   1949   //
   1950   // Update FV Header
   1951   //
   1952   FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FileImage;
   1953   FvHeader->FvBlockMap[0].NumBlocks = FvInfo->FvBlocks[0].NumBlocks;
   1954   FvHeader->FvLength                = OldSize + IncreaseSize;
   1955   FvHeader->Checksum                = 0;
   1956   FvHeader->Checksum                = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
   1957 
   1958   //
   1959   // Update FvImage
   1960   //
   1961   if (AllocateNewMemory) {
   1962     free (FvImage->FileImage);
   1963     FvImage->CurrentFilePointer = FileImage + (FvImage->CurrentFilePointer - FvImage->FileImage);
   1964     FvImage->FileImage          = FileImage;
   1965   }
   1966   FvImage->Eof                  = FvImage->FileImage + OldSize + IncreaseSize;
   1967 
   1968   InitializeFvLib (FvImage->FileImage, OldSize + IncreaseSize);
   1969   return EFI_SUCCESS;
   1970 }
   1971 
   1972 EFI_STATUS
   1973 AddFile (
   1974   IN OUT MEMORY_FILE          *FvImage,
   1975   IN FV_INFO                  *FvInfo,
   1976   IN UINTN                    Index,
   1977   IN OUT EFI_FFS_FILE_HEADER  **VtfFileImage,
   1978   IN OUT MEMORY_FILE          *SymImage,
   1979   IN OUT UINTN                *FvImageCapacity
   1980   )
   1981 /*++
   1982 
   1983 Routine Description:
   1984 
   1985   This function adds a file to the FV image.  The file will pad to the
   1986   appropriate alignment if required.
   1987 
   1988 Arguments:
   1989 
   1990   FvImage         The memory image of the FV to add it to.  The current offset
   1991                   must be valid.
   1992   FvInfo          Pointer to information about the FV.
   1993   Index           The file in the FvInfo file list to add.
   1994   VtfFileImage    A pointer to the VTF file within the FvImage.  If this is equal
   1995                   to the end of the FvImage then no VTF previously found.
   1996   SymImage        The memory image of the Sym file to update if symbols are present.
   1997                   The current offset must be valid.
   1998   FvImageCapacity Capacity of image buffer for FV.
   1999 
   2000 Returns:
   2001 
   2002   EFI_SUCCESS              The function completed successfully.
   2003   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
   2004   EFI_ABORTED              An error occurred.
   2005   EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.
   2006 
   2007 --*/
   2008 {
   2009   FILE                  *NewFile;
   2010   UINTN                 FileSize;
   2011   UINT8                 *FileBuffer;
   2012   UINTN                 NumBytesRead;
   2013   UINT32                CurrentFileAlignment;
   2014   EFI_STATUS            Status;
   2015   EFI_PHYSICAL_ADDRESS  CurrentFileBaseAddress;
   2016   UINT8                 VtfHeaderChecksum;
   2017   UINT8                 VtfFileChecksum;
   2018   UINT8                 FileState;
   2019   UINT32                TailSize;
   2020 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2021   EFI_FFS_FILE_TAIL     TailValue;
   2022 #endif
   2023   //
   2024   // Verify input parameters.
   2025   //
   2026   if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) {
   2027     return EFI_INVALID_PARAMETER;
   2028   }
   2029   //
   2030   // Read the file to add
   2031   //
   2032   NewFile = fopen (FvInfo->FvFiles[Index], "rb");
   2033 
   2034   if (NewFile == NULL) {
   2035     Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading");
   2036     return EFI_ABORTED;
   2037   }
   2038   //
   2039   // Get the file size
   2040   //
   2041   FileSize = _filelength (_fileno (NewFile));
   2042 
   2043   //
   2044   // Read the file into a buffer
   2045   //
   2046   FileBuffer = malloc (FileSize);
   2047   if (FileBuffer == NULL) {
   2048     Error (NULL, 0, 0, "memory allocation failure", NULL);
   2049     return EFI_OUT_OF_RESOURCES;
   2050   }
   2051 
   2052   NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
   2053 
   2054   //
   2055   // Done with the file, from this point on we will just use the buffer read.
   2056   //
   2057   fclose (NewFile);
   2058 
   2059   //
   2060   // Verify read successful
   2061   //
   2062   if (NumBytesRead != sizeof (UINT8) * FileSize) {
   2063     Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents");
   2064     Status = EFI_ABORTED;
   2065     goto Exit;
   2066   }
   2067   //
   2068   // Verify space exists to add the file
   2069   //
   2070   while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
   2071     if (FvInfo->Size != (UINTN) -1) {
   2072       Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file");
   2073       Status = EFI_OUT_OF_RESOURCES;
   2074       goto Exit;
   2075     } else {
   2076       //
   2077       // FV Size is AUTO, increase by one block
   2078       //
   2079       Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
   2080       if (EFI_ERROR (Status)) {
   2081         Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
   2082         goto Exit;
   2083       }
   2084     }
   2085   }
   2086   //
   2087   // Update the file state based on polarity of the FV.
   2088   //
   2089   UpdateFfsFileState (
   2090     (EFI_FFS_FILE_HEADER *) FileBuffer,
   2091     (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
   2092     );
   2093 
   2094   //
   2095   // If we have a VTF file, add it at the top.
   2096   //
   2097   if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
   2098     if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
   2099       //
   2100       // No previous VTF, add this one.
   2101       //
   2102       *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
   2103       //
   2104       // Sanity check. The file MUST align appropriately
   2105       //
   2106       if ((((UINTN) *VtfFileImage) & 0x07) != 0) {
   2107         Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL);
   2108       }
   2109       //
   2110       // copy VTF File Header
   2111       //
   2112       memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER));
   2113 
   2114       //
   2115       // Copy VTF body
   2116       //
   2117       memcpy (
   2118         (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER),
   2119         FileBuffer + sizeof (EFI_FFS_FILE_HEADER),
   2120         FileSize - sizeof (EFI_FFS_FILE_HEADER)
   2121         );
   2122 
   2123       //
   2124       // re-calculate the VTF File Header
   2125       //
   2126       FileState = (*VtfFileImage)->State;
   2127       (*VtfFileImage)->State = 0;
   2128       *(UINT32 *) ((*VtfFileImage)->Size) = FileSize;
   2129       (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0;
   2130       (*VtfFileImage)->IntegrityCheck.Checksum.File = 0;
   2131 
   2132       VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER));
   2133       (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum;
   2134       //
   2135       // Determine if it has a tail
   2136       //
   2137       if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
   2138         TailSize = sizeof (EFI_FFS_FILE_TAIL);
   2139       } else {
   2140         TailSize = 0;
   2141       }
   2142 
   2143       if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) {
   2144     #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2145         VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize);
   2146     #else
   2147         VtfFileChecksum = CalculateChecksum8 ((UINT8 *) ((UINTN)*VtfFileImage + sizeof (EFI_FFS_FILE_HEADER)), FileSize - TailSize - sizeof(EFI_FFS_FILE_HEADER));
   2148     #endif
   2149         (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum;
   2150       } else {
   2151         (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
   2152       }
   2153     #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2154       //
   2155       // If it has a file tail, update it
   2156       //
   2157       if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
   2158         TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference));
   2159         *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
   2160       }
   2161     #endif
   2162       (*VtfFileImage)->State = FileState;
   2163       Status = EFI_SUCCESS;
   2164       goto Exit;
   2165     } else {
   2166       //
   2167       // Already found a VTF file.
   2168       //
   2169       Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL);
   2170       Status = EFI_ABORTED;
   2171       goto Exit;
   2172     }
   2173   }
   2174   //
   2175   // Check if alignment is required
   2176   //
   2177   Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
   2178   if (EFI_ERROR (Status)) {
   2179     printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]);
   2180     Status = EFI_ABORTED;
   2181     goto Exit;
   2182   }
   2183   //
   2184   // Add pad file if necessary
   2185   //
   2186   while (EFI_ERROR (AddPadFile (FvImage, CurrentFileAlignment))) {
   2187     if (FvInfo->Size != (UINTN) -1) {
   2188       printf ("ERROR: Could not align the file data properly.\n");
   2189       Status = EFI_ABORTED;
   2190       goto Exit;
   2191     } else {
   2192       //
   2193       // FV Size is AUTO, increase by one block
   2194       //
   2195       Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
   2196       if (EFI_ERROR (Status)) {
   2197         Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
   2198         goto Exit;
   2199       }
   2200     }
   2201   }
   2202 
   2203   //
   2204   // Add file
   2205   //
   2206   while (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
   2207     if (FvInfo->Size != (UINTN) -1) {
   2208       printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]);
   2209       Status = EFI_ABORTED;
   2210       goto Exit;
   2211     } else {
   2212       //
   2213       // FV Size is AUTO, increase by one one block
   2214       //
   2215       Status = ReallocateFvImage (FvImage, FvInfo, VtfFileImage, FvImageCapacity);
   2216       if (EFI_ERROR (Status)) {
   2217         Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient resources to add the file");
   2218         goto Exit;
   2219       }
   2220     }
   2221   }
   2222 
   2223   //
   2224   // Copy the file
   2225   //
   2226   memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
   2227 
   2228   //
   2229   // If the file is XIP, rebase
   2230   //
   2231   CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage);
   2232   //
   2233   //    Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress);
   2234   //    if (EFI_ERROR(Status)) {
   2235   //      printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]);
   2236   //      return EFI_ABORTED;
   2237   //    }
   2238   //
   2239   // Update Symbol file
   2240   //
   2241   Status = AddSymFile (
   2242             CurrentFileBaseAddress,
   2243             (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer,
   2244             SymImage,
   2245             FvInfo->FvFiles[Index]
   2246             );
   2247   assert (!EFI_ERROR (Status));
   2248 
   2249   //
   2250   // Update the current pointer in the FV image
   2251   //
   2252   FvImage->CurrentFilePointer += FileSize;
   2253 
   2254   //
   2255   // Make next file start at QWord Boundry
   2256   //
   2257   while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) {
   2258     FvImage->CurrentFilePointer++;
   2259   }
   2260 
   2261 Exit:
   2262   //
   2263   // Free allocated memory.
   2264   //
   2265   free (FileBuffer);
   2266   return Status;
   2267 }
   2268 
   2269 EFI_STATUS
   2270 AddVariableBlock (
   2271   IN UINT8                    *FvImage,
   2272   IN UINTN                    Size,
   2273   IN FV_INFO                  *FvInfo
   2274   )
   2275 {
   2276   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
   2277   VARIABLE_STORE_HEADER       *VarStoreHeader;
   2278   //
   2279   // Variable block should exclude FvHeader. Since the length of
   2280   // FvHeader depends on the block map, which is variable length,
   2281   // we could only decide the actual variable block length here.
   2282   //
   2283   FvHeader                  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
   2284   FvImage                   = FvImage + FvHeader->HeaderLength;
   2285 
   2286   VarStoreHeader            = (VARIABLE_STORE_HEADER *) FvImage;
   2287 
   2288   VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE;
   2289   VarStoreHeader->Size      = Size - FvHeader->HeaderLength;
   2290   VarStoreHeader->Format    = VARIABLE_STORE_FORMATTED;
   2291   VarStoreHeader->State     = VARIABLE_STORE_HEALTHY;
   2292   VarStoreHeader->Reserved  = 0;
   2293   VarStoreHeader->Reserved1 = 0;
   2294 
   2295   return EFI_SUCCESS;
   2296 }
   2297 
   2298 EFI_STATUS
   2299 AddEventLogBlock (
   2300   IN UINT8                    *FvImage,
   2301   IN UINTN                    Size,
   2302   IN FV_INFO                  *FvInfo
   2303   )
   2304 {
   2305   return EFI_SUCCESS;
   2306 }
   2307 
   2308 EFI_STATUS
   2309 AddFTWWorkingBlock (
   2310   IN UINT8                    *FvImage,
   2311   IN UINTN                    Size,
   2312   IN FV_INFO                  *FvInfo
   2313   )
   2314 {
   2315   EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader;
   2316   UINT32                                  Crc32;
   2317 
   2318   Crc32     = 0;
   2319   FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage;
   2320   memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID));
   2321   FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
   2322   CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32);
   2323   FTWHeader->Crc = Crc32;
   2324   if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) {
   2325     FTWHeader->WorkingBlockValid    = 0;
   2326     FTWHeader->WorkingBlockInvalid  = 1;
   2327   } else {
   2328     FTWHeader->WorkingBlockValid    = 1;
   2329     FTWHeader->WorkingBlockInvalid  = 0;
   2330   }
   2331 
   2332   return EFI_SUCCESS;
   2333 }
   2334 
   2335 EFI_STATUS
   2336 AddFTWSpareBlock (
   2337   IN UINT8                    *FvImage,
   2338   IN UINTN                    Size,
   2339   IN FV_INFO                  *FvInfo
   2340   )
   2341 {
   2342   return EFI_SUCCESS;
   2343 }
   2344 
   2345 EFI_STATUS
   2346 GenNonFFSFv (
   2347   IN UINT8                    *FvImage,
   2348   IN FV_INFO                  *FvInfo
   2349   )
   2350 /*++
   2351 
   2352 Routine Description:
   2353 
   2354   This function generate the non FFS FV image, such as the working block
   2355   and spare block. How each component of the FV is built is component
   2356   specific.
   2357 
   2358 Arguments:
   2359 
   2360   FvImage       The memory image of the FV to add it to.  The current offset
   2361                 must be valid.
   2362   FvInfo        Pointer to information about the FV.
   2363 
   2364 Returns:
   2365 
   2366   EFI_SUCCESS              The function completed successfully.
   2367   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
   2368   EFI_ABORTED              An error occurred.
   2369   EFI_OUT_OF_RESOURCES     Insufficient resources exist to complete the add.
   2370 
   2371 --*/
   2372 {
   2373   UINTN                       Index;
   2374   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
   2375   UINT64                      TotalSize;
   2376 
   2377   FvHeader  = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
   2378   TotalSize = 0;
   2379 
   2380   for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) {
   2381     if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) {
   2382       AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
   2383     } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) {
   2384       AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
   2385     } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) {
   2386       AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
   2387     } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) {
   2388       AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo);
   2389     } else {
   2390       printf ("Warning: Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName);
   2391     }
   2392 
   2393     FvImage   = FvImage + FvInfo->FvComponents[Index].Size;
   2394     TotalSize = TotalSize + FvInfo->FvComponents[Index].Size;
   2395   }
   2396   //
   2397   // Index and TotalSize is zero mean there's no component, so this is an empty fv
   2398   //
   2399   if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) {
   2400     printf ("Error. Component size does not sum up to FV size.\n");
   2401     return EFI_ABORTED;
   2402   }
   2403 
   2404   return EFI_SUCCESS;
   2405 }
   2406 
   2407 EFI_STATUS
   2408 PadFvImage (
   2409   IN MEMORY_FILE          *FvImage,
   2410   IN EFI_FFS_FILE_HEADER  *VtfFileImage
   2411   )
   2412 /*++
   2413 
   2414 Routine Description:
   2415 
   2416   This function places a pad file between the last file in the FV and the VTF
   2417   file if the VTF file exists.
   2418 
   2419 Arguments:
   2420 
   2421   FvImage       Memory file for the FV memory image
   2422   VtfFileImage  The address of the VTF file.  If this is the end of the FV
   2423                 image, no VTF exists and no pad file is needed.
   2424 
   2425 Returns:
   2426 
   2427   EFI_SUCCESS             Completed successfully.
   2428   EFI_INVALID_PARAMETER   One of the input parameters was NULL.
   2429 
   2430 --*/
   2431 {
   2432   EFI_FFS_FILE_HEADER *PadFile;
   2433   UINTN               FileSize;
   2434 
   2435   //
   2436   // If there is no VTF or the VTF naturally follows the previous file without a
   2437   // pad file, then there's nothing to do
   2438   //
   2439   if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) {
   2440     return EFI_SUCCESS;
   2441   }
   2442   //
   2443   // Pad file starts at beginning of free space
   2444   //
   2445   PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
   2446 
   2447   //
   2448   // write header
   2449   //
   2450   memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER));
   2451   memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID));
   2452   PadFile->Type       = EFI_FV_FILETYPE_FFS_PAD;
   2453   PadFile->Attributes = 0;
   2454 
   2455   //
   2456   // FileSize includes the EFI_FFS_FILE_HEADER
   2457   //
   2458   FileSize          = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
   2459   PadFile->Size[0]  = (UINT8) (FileSize & 0x000000FF);
   2460   PadFile->Size[1]  = (UINT8) ((FileSize & 0x0000FF00) >> 8);
   2461   PadFile->Size[2]  = (UINT8) ((FileSize & 0x00FF0000) >> 16);
   2462 
   2463   //
   2464   // Fill in checksums and state, must be zero during checksum calculation.
   2465   //
   2466   PadFile->IntegrityCheck.Checksum.Header = 0;
   2467   PadFile->IntegrityCheck.Checksum.File   = 0;
   2468   PadFile->State                          = 0;
   2469   PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER));
   2470   if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) {
   2471 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2472     PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize);
   2473 #else
   2474     PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) ((UINTN) PadFile + sizeof (EFI_FFS_FILE_HEADER)), FileSize - sizeof (EFI_FFS_FILE_HEADER));
   2475 #endif
   2476   } else {
   2477     PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
   2478   }
   2479 
   2480   PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
   2481 
   2482   UpdateFfsFileState (
   2483     (EFI_FFS_FILE_HEADER *) PadFile,
   2484     (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
   2485     );
   2486   //
   2487   // Update the current FV pointer
   2488   //
   2489   FvImage->CurrentFilePointer = FvImage->Eof;
   2490 
   2491   return EFI_SUCCESS;
   2492 }
   2493 
   2494 EFI_STATUS
   2495 UpdateResetVector (
   2496   IN MEMORY_FILE            *FvImage,
   2497   IN FV_INFO                *FvInfo,
   2498   IN EFI_FFS_FILE_HEADER    *VtfFile
   2499   )
   2500 /*++
   2501 
   2502 Routine Description:
   2503 
   2504   This parses the FV looking for the PEI core and then plugs the address into
   2505   the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
   2506   complete an IA32 Bootstrap FV.
   2507 
   2508 Arguments:
   2509 
   2510   FvImage       Memory file for the FV memory image
   2511   FvInfo        Information read from INF file.
   2512   VtfFile       Pointer to the VTF file in the FV image.
   2513 
   2514 Returns:
   2515 
   2516   EFI_SUCCESS             Function Completed successfully.
   2517   EFI_ABORTED             Error encountered.
   2518   EFI_INVALID_PARAMETER   A required parameter was NULL.
   2519   EFI_NOT_FOUND           PEI Core file not found.
   2520 
   2521 --*/
   2522 {
   2523   EFI_FFS_FILE_HEADER       *PeiCoreFile;
   2524   EFI_FFS_FILE_HEADER       *SecCoreFile;
   2525   EFI_STATUS                Status;
   2526   EFI_FILE_SECTION_POINTER  Pe32Section;
   2527   UINT32                    EntryPoint;
   2528   UINT32                    BaseOfCode;
   2529   UINT16                    MachineType;
   2530   EFI_PHYSICAL_ADDRESS      PeiCorePhysicalAddress;
   2531   EFI_PHYSICAL_ADDRESS      SecCorePhysicalAddress;
   2532   EFI_PHYSICAL_ADDRESS      *SecCoreEntryAddressPtr;
   2533   UINT32                    *Ia32ResetAddressPtr;
   2534   UINT8                     *BytePointer;
   2535   UINT8                     *BytePointer2;
   2536   UINT16                    *WordPointer;
   2537   UINT16                    CheckSum;
   2538   UINTN                     Index;
   2539   EFI_FFS_FILE_STATE        SavedState;
   2540   UINT32                    TailSize;
   2541   UINT64                    FitAddress;
   2542   FIT_TABLE                 *FitTablePtr;
   2543 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2544   EFI_FFS_FILE_TAIL         TailValue;
   2545 #endif
   2546   //
   2547   // Verify input parameters
   2548   //
   2549   if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
   2550     return EFI_INVALID_PARAMETER;
   2551   }
   2552   //
   2553   // Initialize FV library
   2554   //
   2555   InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage);
   2556 
   2557   //
   2558   // Verify VTF file
   2559   //
   2560   Status = VerifyFfsFile (VtfFile);
   2561   if (EFI_ERROR (Status)) {
   2562     return EFI_INVALID_PARAMETER;
   2563   }
   2564   //
   2565   // Find the PEI Core
   2566   //
   2567   Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
   2568   if (EFI_ERROR (Status) || PeiCoreFile == NULL) {
   2569     Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL);
   2570     return EFI_ABORTED;
   2571   }
   2572   //
   2573   // PEI Core found, now find PE32 or TE section
   2574   //
   2575   Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
   2576   if (Status == EFI_NOT_FOUND) {
   2577     Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
   2578   }
   2579 
   2580   if (EFI_ERROR (Status)) {
   2581     Error (NULL, 0, 0, "could not find PE32 or TE section in PEI core file", NULL);
   2582     return EFI_ABORTED;
   2583   }
   2584 
   2585   Status = GetPe32Info (
   2586             (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
   2587             &EntryPoint,
   2588             &BaseOfCode,
   2589             &MachineType
   2590             );
   2591 
   2592   if (EFI_ERROR (Status)) {
   2593     Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL);
   2594     return EFI_ABORTED;
   2595   }
   2596   //
   2597   // Physical address is FV base + offset of PE32 + offset of the entry point
   2598   //
   2599   PeiCorePhysicalAddress = FvInfo->BaseAddress;
   2600   PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
   2601   PeiCorePhysicalAddress += EntryPoint;
   2602 
   2603   if (MachineType == EFI_IMAGE_MACHINE_IA64) {
   2604     //
   2605     // Update PEI_CORE address
   2606     //
   2607     //
   2608     // Set the uncached attribute bit in the physical address
   2609     //
   2610     PeiCorePhysicalAddress |= 0x8000000000000000;
   2611 
   2612     //
   2613     // Check if address is aligned on a 16 byte boundary
   2614     //
   2615     if (PeiCorePhysicalAddress & 0xF) {
   2616       printf (
   2617         "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
   2618         PeiCorePhysicalAddress
   2619         );
   2620       return EFI_ABORTED;
   2621     }
   2622     //
   2623     // First Get the FIT table address
   2624     //
   2625     FitAddress  = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF;
   2626 
   2627     FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress));
   2628 
   2629     Status      = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress);
   2630 
   2631     if (!EFI_ERROR (Status)) {
   2632       UpdateFitCheckSum (FitTablePtr);
   2633     }
   2634     //
   2635     // Find the Sec Core
   2636     //
   2637     Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
   2638     if (EFI_ERROR (Status) || SecCoreFile == NULL) {
   2639       Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL);
   2640       return EFI_ABORTED;
   2641     }
   2642     //
   2643     // Sec Core found, now find PE32 section
   2644     //
   2645     Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
   2646     if (EFI_ERROR (Status)) {
   2647       Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL);
   2648       return EFI_ABORTED;
   2649     }
   2650 
   2651     Status = GetPe32Info (
   2652               (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)),
   2653               &EntryPoint,
   2654               &BaseOfCode,
   2655               &MachineType
   2656               );
   2657     if (EFI_ERROR (Status)) {
   2658       Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL);
   2659       return EFI_ABORTED;
   2660     }
   2661     //
   2662     // Physical address is FV base + offset of PE32 + offset of the entry point
   2663     //
   2664     SecCorePhysicalAddress = FvInfo->BaseAddress;
   2665     SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage;
   2666     SecCorePhysicalAddress += EntryPoint;
   2667 
   2668     //
   2669     // Update SEC_CORE address
   2670     //
   2671     //
   2672     // Set the uncached attribute bit in the physical address
   2673     //
   2674     SecCorePhysicalAddress |= 0x8000000000000000;
   2675 
   2676     //
   2677     // Update the address
   2678     //
   2679     SecCoreEntryAddressPtr  = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET);
   2680     *SecCoreEntryAddressPtr = SecCorePhysicalAddress;
   2681 
   2682     //
   2683     // Check if address is aligned on a 16 byte boundary
   2684     //
   2685     if (SecCorePhysicalAddress & 0xF) {
   2686       printf (
   2687         "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n",
   2688         SecCorePhysicalAddress
   2689         );
   2690       return EFI_ABORTED;
   2691     }
   2692   } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) ||
   2693              (MachineType == EFI_IMAGE_MACHINE_X64)) {
   2694     //
   2695     // Get the location to update
   2696     //
   2697     Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
   2698 
   2699     //
   2700     // Write lower 32 bits of physical address
   2701     //
   2702     *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
   2703 
   2704     //
   2705     // Update the BFV base address
   2706     //
   2707     Ia32ResetAddressPtr   = (UINT32 *) ((UINTN) FvImage->Eof - 4);
   2708     *Ia32ResetAddressPtr  = (UINT32) (FvInfo->BaseAddress);
   2709 
   2710     CheckSum              = 0x0000;
   2711 
   2712     //
   2713     // Update the Startup AP in the FVH header block ZeroVector region.
   2714     //
   2715     BytePointer   = (UINT8 *) ((UINTN) FvImage->FileImage);
   2716     BytePointer2  = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray;
   2717     for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
   2718       *BytePointer++ = *BytePointer2++;
   2719     }
   2720     //
   2721     // Calculate the checksum
   2722     //
   2723     WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage);
   2724     for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
   2725       CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
   2726       WordPointer++;
   2727     }
   2728     //
   2729     // Update the checksum field
   2730     //
   2731     BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
   2732     BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2);
   2733     WordPointer   = (UINT16 *) BytePointer;
   2734     *WordPointer  = (UINT16) (0x10000 - (UINT32) CheckSum);
   2735   } else {
   2736     Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType);
   2737     return EFI_ABORTED;
   2738   }
   2739   //
   2740   // Determine if it has an FFS file tail.
   2741   //
   2742   if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
   2743     TailSize = sizeof (EFI_FFS_FILE_TAIL);
   2744   } else {
   2745     TailSize = 0;
   2746   }
   2747   //
   2748   // Now update file checksum
   2749   //
   2750   SavedState  = VtfFile->State;
   2751   VtfFile->IntegrityCheck.Checksum.File = 0;
   2752   VtfFile->State                        = 0;
   2753   if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
   2754 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2755     VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
   2756                                               (UINT8 *) VtfFile,
   2757                                               GetLength (VtfFile->Size) - TailSize
   2758                                               );
   2759 
   2760 #else
   2761     VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
   2762                                               (UINT8 *) ((UINTN)VtfFile + sizeof (EFI_FFS_FILE_HEADER)),
   2763                                               GetLength (VtfFile->Size) - TailSize - sizeof (EFI_FFS_FILE_HEADER)
   2764                                               );
   2765 #endif
   2766   } else {
   2767     VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
   2768   }
   2769 
   2770   VtfFile->State = SavedState;
   2771 
   2772 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   2773   //
   2774   // Update tail if present
   2775   //
   2776   if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
   2777     TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference));
   2778     *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
   2779   }
   2780 #endif
   2781   return EFI_SUCCESS;
   2782 }
   2783 
   2784 EFI_STATUS
   2785 GetPe32Info (
   2786   IN UINT8                  *Pe32,
   2787   OUT UINT32                *EntryPoint,
   2788   OUT UINT32                *BaseOfCode,
   2789   OUT UINT16                *MachineType
   2790   )
   2791 /*++
   2792 
   2793 Routine Description:
   2794 
   2795   Retrieves the PE32 entry point offset and machine type from PE image or TE image.
   2796   See EfiImage.h for machine types.  The entry point offset is from the beginning
   2797   of the PE32 buffer passed in.
   2798 
   2799 Arguments:
   2800 
   2801   Pe32          Beginning of the PE32.
   2802   EntryPoint    Offset from the beginning of the PE32 to the image entry point.
   2803   BaseOfCode    Base address of code.
   2804   MachineType   Magic number for the machine type.
   2805 
   2806 Returns:
   2807 
   2808   EFI_SUCCESS             Function completed successfully.
   2809   EFI_ABORTED             Error encountered.
   2810   EFI_INVALID_PARAMETER   A required parameter was NULL.
   2811   EFI_UNSUPPORTED         The operation is unsupported.
   2812 
   2813 --*/
   2814 {
   2815   EFI_IMAGE_DOS_HEADER  *DosHeader;
   2816   EFI_IMAGE_NT_HEADERS  *NtHeader;
   2817   EFI_TE_IMAGE_HEADER   *TeHeader;
   2818 
   2819   //
   2820   // Verify input parameters
   2821   //
   2822   if (Pe32 == NULL) {
   2823     return EFI_INVALID_PARAMETER;
   2824   }
   2825 
   2826   //
   2827   // First check whether it is one TE Image.
   2828   //
   2829   TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
   2830   if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
   2831     //
   2832     // By TeImage Header to get output
   2833     //
   2834     *EntryPoint  = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
   2835     *BaseOfCode  = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
   2836     *MachineType = TeHeader->Machine;
   2837   } else {
   2838     //
   2839     // Then check whether
   2840     // is the DOS header
   2841     //
   2842     DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
   2843 
   2844     //
   2845     // Verify DOS header is expected
   2846     //
   2847     if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
   2848       printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic);
   2849       return EFI_UNSUPPORTED;
   2850     }
   2851     //
   2852     // Immediately following is the NT header.
   2853     //
   2854     NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew);
   2855 
   2856     //
   2857     // Verify NT header is expected
   2858     //
   2859     if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) {
   2860       printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature);
   2861       return EFI_UNSUPPORTED;
   2862     }
   2863     //
   2864     // Get output
   2865     //
   2866     *EntryPoint   = NtHeader->OptionalHeader.AddressOfEntryPoint;
   2867     *BaseOfCode   = NtHeader->OptionalHeader.BaseOfCode;
   2868     *MachineType  = NtHeader->FileHeader.Machine;
   2869   }
   2870 
   2871   //
   2872   // Verify machine type is supported
   2873   //
   2874   if (*MachineType != EFI_IMAGE_MACHINE_IA32 &&
   2875       *MachineType != EFI_IMAGE_MACHINE_IA64 &&
   2876       *MachineType != EFI_IMAGE_MACHINE_X64) {
   2877     printf ("ERROR: Unrecognized machine type in the PE32 file.\n");
   2878     return EFI_UNSUPPORTED;
   2879   }
   2880 
   2881   return EFI_SUCCESS;
   2882 }
   2883 //
   2884 // Exposed function implementations (prototypes are defined in GenFvImageLib.h)
   2885 //
   2886 EFI_STATUS
   2887 GenerateFvImage (
   2888   IN CHAR8    *InfFileImage,
   2889   IN UINTN    InfFileSize,
   2890   OUT UINT8   **FvImage,
   2891   OUT UINTN   *FvImageSize,
   2892   OUT CHAR8   **FvFileName,
   2893   OUT UINT8   **SymImage,
   2894   OUT UINTN   *SymImageSize,
   2895   OUT CHAR8   **SymFileName
   2896   )
   2897 /*++
   2898 
   2899 Routine Description:
   2900 
   2901   This is the main function which will be called from application.
   2902 
   2903 Arguments:
   2904 
   2905   InfFileImage  Buffer containing the INF file contents.
   2906   InfFileSize   Size of the contents of the InfFileImage buffer.
   2907   FvImage       Pointer to the FV image created.
   2908   FvImageSize   Size of the FV image created and pointed to by FvImage.
   2909   FvFileName    Requested name for the FV file.
   2910   SymImage      Pointer to the Sym image created.
   2911   SymImageSize  Size of the Sym image created and pointed to by SymImage.
   2912   SymFileName   Requested name for the Sym file.
   2913 
   2914 Returns:
   2915 
   2916   EFI_SUCCESS             Function completed successfully.
   2917   EFI_OUT_OF_RESOURCES    Could not allocate required resources.
   2918   EFI_ABORTED             Error encountered.
   2919   EFI_INVALID_PARAMETER   A required parameter was NULL.
   2920 
   2921 --*/
   2922 {
   2923   EFI_STATUS                  Status;
   2924   MEMORY_FILE                 InfMemoryFile;
   2925   MEMORY_FILE                 FvImageMemoryFile;
   2926   MEMORY_FILE                 SymImageMemoryFile;
   2927   FV_INFO                     FvInfo;
   2928   UINTN                       Index;
   2929   EFI_FIRMWARE_VOLUME_HEADER  *FvHeader;
   2930   EFI_FFS_FILE_HEADER         *VtfFileImage;
   2931   UINTN                       FvImageCapacity;
   2932 
   2933   //
   2934   // Check for invalid parameter
   2935   //
   2936   if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) {
   2937     return EFI_INVALID_PARAMETER;
   2938   }
   2939   //
   2940   // Initialize file structures
   2941   //
   2942   InfMemoryFile.FileImage           = InfFileImage;
   2943   InfMemoryFile.CurrentFilePointer  = InfFileImage;
   2944   InfMemoryFile.Eof                 = InfFileImage + InfFileSize;
   2945 
   2946   //
   2947   // Parse the FV inf file for header information
   2948   //
   2949   Status = ParseFvInf (&InfMemoryFile, &FvInfo);
   2950   if (EFI_ERROR (Status)) {
   2951     printf ("ERROR: Could not parse the input INF file.\n");
   2952     return EFI_ABORTED;
   2953   }
   2954   //
   2955   // Update the file name return values
   2956   //
   2957   strcpy (*FvFileName, FvInfo.FvName);
   2958   strcpy (*SymFileName, FvInfo.SymName);
   2959 
   2960   //
   2961   // Calculate the FV size
   2962   //
   2963   if (FvInfo.Size != (UINTN) -1) {
   2964     *FvImageSize    = FvInfo.Size;
   2965     FvImageCapacity = FvInfo.Size;
   2966   } else {
   2967     //
   2968     // For auto size, set default as one block
   2969     //
   2970     FvInfo.FvBlocks[0].NumBlocks = 1;
   2971     *FvImageSize    = FvInfo.FvBlocks[0].BlockLength;
   2972     FvImageCapacity = FV_CAPACITY_INCREASE_UNIT;
   2973   }
   2974 
   2975   //
   2976   // Allocate the FV
   2977   //
   2978   *FvImage = malloc (FvImageCapacity);
   2979   if (*FvImage == NULL) {
   2980     return EFI_OUT_OF_RESOURCES;
   2981   }
   2982   //
   2983   // Allocate space for symbol file storage
   2984   //
   2985   *SymImage = malloc (SYMBOL_FILE_SIZE);
   2986   if (*SymImage == NULL) {
   2987     return EFI_OUT_OF_RESOURCES;
   2988   }
   2989   //
   2990   // Initialize the FV to the erase polarity
   2991   //
   2992   if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) {
   2993     memset (*FvImage, -1, FvImageCapacity);
   2994   } else {
   2995     memset (*FvImage, 0, FvImageCapacity);
   2996   }
   2997   //
   2998   // Initialize FV header
   2999   //
   3000   FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage;
   3001 
   3002   //
   3003   // Initialize the zero vector to all zeros.
   3004   //
   3005   memset (FvHeader->ZeroVector, 0, 16);
   3006 
   3007   //
   3008   // Copy the FFS GUID
   3009   //
   3010   memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID));
   3011 
   3012   FvHeader->FvLength    = *FvImageSize;
   3013   FvHeader->Signature   = EFI_FVH_SIGNATURE;
   3014   FvHeader->Attributes  = FvInfo.FvAttributes;
   3015 #if (PI_SPECIFICATION_VERSION < 0x00010000)
   3016   FvHeader->Revision    = EFI_FVH_REVISION;
   3017   FvHeader->Reserved[0] = 0;
   3018   FvHeader->Reserved[1] = 0;
   3019   FvHeader->Reserved[2] = 0;
   3020 #else
   3021   FvHeader->Revision    = EFI_FVH_PI_REVISION;
   3022   FvHeader->ExtHeaderOffset = 0;
   3023   FvHeader->Reserved[0] = 0;
   3024 #endif
   3025   //
   3026   // Copy firmware block map
   3027   //
   3028   for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) {
   3029     FvHeader->FvBlockMap[Index].NumBlocks   = FvInfo.FvBlocks[Index].NumBlocks;
   3030     FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength;
   3031   }
   3032   //
   3033   // Add block map terminator
   3034   //
   3035   FvHeader->FvBlockMap[Index].NumBlocks   = 0;
   3036   FvHeader->FvBlockMap[Index].BlockLength = 0;
   3037 
   3038   //
   3039   // Complete the header
   3040   //
   3041   FvHeader->HeaderLength  = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage);
   3042   FvHeader->Checksum      = 0;
   3043   FvHeader->Checksum      = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
   3044 
   3045   //
   3046   // If there is no FFS file, find and generate each components of the FV
   3047   //
   3048   if (FvInfo.FvFiles[0][0] == 0) {
   3049     Status = GenNonFFSFv (*FvImage, &FvInfo);
   3050     if (EFI_ERROR (Status)) {
   3051       printf ("ERROR: Could not generate NonFFS FV.\n");
   3052       free (*FvImage);
   3053       return EFI_ABORTED;
   3054     }
   3055 
   3056     return EFI_SUCCESS;
   3057   }
   3058   //
   3059   // Initialize our "file" view of the buffer
   3060   //
   3061   FvImageMemoryFile.FileImage           = *FvImage;
   3062   FvImageMemoryFile.CurrentFilePointer  = *FvImage + FvHeader->HeaderLength;
   3063   FvImageMemoryFile.Eof                 = *FvImage +*FvImageSize;
   3064 
   3065   //
   3066   // Initialize our "file" view of the symbol file.
   3067   //
   3068   SymImageMemoryFile.FileImage          = *SymImage;
   3069   SymImageMemoryFile.CurrentFilePointer = *SymImage;
   3070   SymImageMemoryFile.Eof                = *FvImage + SYMBOL_FILE_SIZE;
   3071 
   3072   //
   3073   // Initialize the FV library.
   3074   //
   3075   InitializeFvLib (FvImageMemoryFile.FileImage, *FvImageSize);
   3076 
   3077   //
   3078   // Files start on 8 byte alignments, so move to the next 8 byte aligned
   3079   // address.  For now, just assert if it isn't.  Currently FV header is
   3080   // always a multiple of 8 bytes.
   3081   // BUGBUG: Handle this better
   3082   //
   3083   assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0);
   3084 
   3085   //
   3086   // Initialize the VTF file address.
   3087   //
   3088   VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
   3089 
   3090   //
   3091   // Add files to FV
   3092   //
   3093   for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) {
   3094     //
   3095     // Add the file
   3096     //
   3097     Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile, &FvImageCapacity);
   3098 
   3099     //
   3100     // Update FvImageSize and FvImage as they may be changed in AddFile routine
   3101     //
   3102     if (FvInfo.Size == (UINTN) -1) {
   3103       *FvImageSize = FvInfo.FvBlocks[0].NumBlocks * FvInfo.FvBlocks[0].BlockLength;
   3104       *FvImage     = FvImageMemoryFile.FileImage;
   3105     }
   3106 
   3107     //
   3108     // Exit if error detected while adding the file
   3109     //
   3110     if (EFI_ERROR (Status)) {
   3111       printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]);
   3112       free (*FvImage);
   3113       return EFI_ABORTED;
   3114     }
   3115   }
   3116   //
   3117   // If there is a VTF file, some special actions need to occur.
   3118   //
   3119   if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
   3120     //
   3121     // Pad from the end of the last file to the beginning of the VTF file.
   3122     //
   3123     Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
   3124     if (EFI_ERROR (Status)) {
   3125       printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n");
   3126       free (*FvImage);
   3127       return EFI_ABORTED;
   3128     }
   3129     //
   3130     // Update reset vector (SALE_ENTRY for IPF)
   3131     // Now for IA32 and IA64 platform, the fv which has bsf file must have the
   3132     // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the
   3133     // reset vector. If the PEI Core is found, the VTF file will probably get
   3134     // corrupted by updating the entry point.
   3135     //
   3136     if ((FvInfo.BaseAddress + *FvImageSize) == FV_IMAGES_TOP_ADDRESS) {
   3137       Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage);
   3138       if (EFI_ERROR(Status)) {
   3139         printf ("ERROR: Could not update the reset vector.\n");
   3140         free (*FvImage);
   3141         return EFI_ABORTED;
   3142       }
   3143     }
   3144   }
   3145   //
   3146   // Determine final Sym file size
   3147   //
   3148   *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage;
   3149 
   3150   return EFI_SUCCESS;
   3151 }
   3152 
   3153 EFI_STATUS
   3154 UpdatePeiCoreEntryInFit (
   3155   IN FIT_TABLE     *FitTablePtr,
   3156   IN UINT64        PeiCorePhysicalAddress
   3157   )
   3158 /*++
   3159 
   3160 Routine Description:
   3161 
   3162   This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
   3163   Sec to Pei Core
   3164 
   3165 Arguments:
   3166 
   3167   FitTablePtr             - The pointer of FIT_TABLE.
   3168   PeiCorePhysicalAddress  - The address of Pei Core entry.
   3169 
   3170 Returns:
   3171 
   3172   EFI_SUCCESS             - The PEI_CORE FIT entry was updated successfully.
   3173   EFI_NOT_FOUND           - Not found the PEI_CORE FIT entry.
   3174 
   3175 --*/
   3176 {
   3177   FIT_TABLE *TmpFitPtr;
   3178   UINTN     Index;
   3179   UINTN     NumFitComponents;
   3180 
   3181   TmpFitPtr         = FitTablePtr;
   3182   NumFitComponents  = TmpFitPtr->CompSize;
   3183 
   3184   for (Index = 0; Index < NumFitComponents; Index++) {
   3185     if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
   3186       TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
   3187       return EFI_SUCCESS;
   3188     }
   3189 
   3190     TmpFitPtr++;
   3191   }
   3192 
   3193   return EFI_NOT_FOUND;
   3194 }
   3195 
   3196 VOID
   3197 UpdateFitCheckSum (
   3198   IN FIT_TABLE   *FitTablePtr
   3199   )
   3200 /*++
   3201 
   3202 Routine Description:
   3203 
   3204   This function is used to update the checksum for FIT.
   3205 
   3206 
   3207 Arguments:
   3208 
   3209   FitTablePtr             - The pointer of FIT_TABLE.
   3210 
   3211 Returns:
   3212 
   3213   None.
   3214 
   3215 --*/
   3216 {
   3217   if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
   3218     FitTablePtr->CheckSum = 0;
   3219     FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
   3220   }
   3221 }
   3222