Home | History | Annotate | Download | only in Common
      1 /*++
      2 
      3 Copyright (c) 2004 - 2010, 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   FvLib.c
     15 
     16 Abstract:
     17 
     18   These functions assist in parsing and manipulating a Firmware Volume.
     19 
     20 --*/
     21 
     22 //
     23 // Include files
     24 //
     25 #include "FvLib.h"
     26 #include "CommonLib.h"
     27 #include "EfiUtilityMsgs.h"
     28 
     29 //
     30 // Module global variables
     31 //
     32 EFI_FIRMWARE_VOLUME_HEADER  *mFvHeader  = NULL;
     33 UINT32                      mFvLength   = 0;
     34 
     35 //
     36 // External function implementations
     37 //
     38 EFI_STATUS
     39 InitializeFvLib (
     40   IN VOID                         *Fv,
     41   IN UINT32                       FvLength
     42   )
     43 /*++
     44 
     45 Routine Description:
     46 
     47   This initializes the FV lib with a pointer to the FV and length.  It does not
     48   verify the FV in any way.
     49 
     50 Arguments:
     51 
     52   Fv            Buffer containing the FV.
     53   FvLength      Length of the FV
     54 
     55 Returns:
     56 
     57   EFI_SUCCESS             Function Completed successfully.
     58   EFI_INVALID_PARAMETER   A required parameter was NULL.
     59 
     60 --*/
     61 {
     62   //
     63   // Verify input arguments
     64   //
     65   if (Fv == NULL) {
     66     return EFI_INVALID_PARAMETER;
     67   }
     68 
     69   mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv;
     70   mFvLength = FvLength;
     71 
     72   return EFI_SUCCESS;
     73 }
     74 
     75 EFI_STATUS
     76 GetFvHeader (
     77   OUT EFI_FIRMWARE_VOLUME_HEADER  **FvHeader,
     78   OUT UINT32                      *FvLength
     79   )
     80 /*++
     81 
     82 Routine Description:
     83 
     84   This function returns a pointer to the current FV and the size.
     85 
     86 Arguments:
     87 
     88   FvHeader      Pointer to the FV buffer.
     89   FvLength      Length of the FV
     90 
     91 Returns:
     92 
     93   EFI_SUCCESS             Function Completed successfully.
     94   EFI_INVALID_PARAMETER   A required parameter was NULL.
     95   EFI_ABORTED             The library needs to be initialized.
     96 
     97 --*/
     98 {
     99   //
    100   // Verify library has been initialized.
    101   //
    102   if (mFvHeader == NULL || mFvLength == 0) {
    103     return EFI_ABORTED;
    104   }
    105   //
    106   // Verify input arguments
    107   //
    108   if (FvHeader == NULL) {
    109     return EFI_INVALID_PARAMETER;
    110   }
    111 
    112   *FvHeader = mFvHeader;
    113   return EFI_SUCCESS;
    114 }
    115 
    116 EFI_STATUS
    117 GetNextFile (
    118   IN EFI_FFS_FILE_HEADER          *CurrentFile,
    119   OUT EFI_FFS_FILE_HEADER         **NextFile
    120   )
    121 /*++
    122 
    123 Routine Description:
    124 
    125   This function returns the next file.  If the current file is NULL, it returns
    126   the first file in the FV.  If the function returns EFI_SUCCESS and the file
    127   pointer is NULL, then there are no more files in the FV.
    128 
    129 Arguments:
    130 
    131   CurrentFile   Pointer to the current file, must be within the current FV.
    132   NextFile      Pointer to the next file in the FV.
    133 
    134 Returns:
    135 
    136   EFI_SUCCESS             Function completed successfully.
    137   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.
    138   EFI_ABORTED             The library needs to be initialized.
    139 
    140 --*/
    141 {
    142   EFI_STATUS  Status;
    143 
    144   //
    145   // Verify library has been initialized.
    146   //
    147   if (mFvHeader == NULL || mFvLength == 0) {
    148     return EFI_ABORTED;
    149   }
    150   //
    151   // Verify input arguments
    152   //
    153   if (NextFile == NULL) {
    154     return EFI_INVALID_PARAMETER;
    155   }
    156   //
    157   // Verify FV header
    158   //
    159   Status = VerifyFv (mFvHeader);
    160   if (EFI_ERROR (Status)) {
    161     return EFI_ABORTED;
    162   }
    163   //
    164   // Get first file
    165   //
    166   if (CurrentFile == NULL) {
    167     CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength);
    168 
    169     //
    170     // Verify file is valid
    171     //
    172     Status = VerifyFfsFile (CurrentFile);
    173     if (EFI_ERROR (Status)) {
    174       //
    175       // no files in this FV
    176       //
    177       *NextFile = NULL;
    178       return EFI_SUCCESS;
    179     } else {
    180       //
    181       // Verify file is in this FV.
    182       //
    183       if ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) {
    184         *NextFile = NULL;
    185         return EFI_SUCCESS;
    186       }
    187 
    188       *NextFile = CurrentFile;
    189       return EFI_SUCCESS;
    190     }
    191   }
    192   //
    193   // Verify current file is in range
    194   //
    195   if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) ||
    196       ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength)
    197      ) {
    198     return EFI_INVALID_PARAMETER;
    199   }
    200   //
    201   // Get next file, compensate for 8 byte alignment if necessary.
    202   //
    203   *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3));
    204 
    205   //
    206   // Verify file is in this FV.
    207   //
    208   if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) ||
    209       ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength)
    210      ) {
    211     *NextFile = NULL;
    212     return EFI_SUCCESS;
    213   }
    214   //
    215   // Verify file is valid
    216   //
    217   Status = VerifyFfsFile (*NextFile);
    218   if (EFI_ERROR (Status)) {
    219     //
    220     // no more files in this FV
    221     //
    222     *NextFile = NULL;
    223     return EFI_SUCCESS;
    224   }
    225 
    226   return EFI_SUCCESS;
    227 }
    228 
    229 EFI_STATUS
    230 GetFileByName (
    231   IN EFI_GUID                     *FileName,
    232   OUT EFI_FFS_FILE_HEADER         **File
    233   )
    234 /*++
    235 
    236 Routine Description:
    237 
    238   Find a file by name.  The function will return NULL if the file is not found.
    239 
    240 Arguments:
    241 
    242   FileName    The GUID file name of the file to search for.
    243   File        Return pointer.  In the case of an error, contents are undefined.
    244 
    245 Returns:
    246 
    247   EFI_SUCCESS             The function completed successfully.
    248   EFI_ABORTED             An error was encountered.
    249   EFI_INVALID_PARAMETER   One of the parameters was NULL.
    250 
    251 --*/
    252 {
    253   EFI_FFS_FILE_HEADER *CurrentFile;
    254   EFI_STATUS          Status;
    255 
    256   //
    257   // Verify library has been initialized.
    258   //
    259   if (mFvHeader == NULL || mFvLength == 0) {
    260     return EFI_ABORTED;
    261   }
    262   //
    263   // Verify input parameters
    264   //
    265   if (FileName == NULL || File == NULL) {
    266     return EFI_INVALID_PARAMETER;
    267   }
    268   //
    269   // Verify FV header
    270   //
    271   Status = VerifyFv (mFvHeader);
    272   if (EFI_ERROR (Status)) {
    273     return EFI_ABORTED;
    274   }
    275   //
    276   // Get the first file
    277   //
    278   Status = GetNextFile (NULL, &CurrentFile);
    279   if (EFI_ERROR (Status)) {
    280     Error (NULL, 0, 0, "error parsing the FV", NULL);
    281     return EFI_ABORTED;
    282   }
    283   //
    284   // Loop as long as we have a valid file
    285   //
    286   while (CurrentFile) {
    287     if (!CompareGuid (&CurrentFile->Name, FileName)) {
    288       *File = CurrentFile;
    289       return EFI_SUCCESS;
    290     }
    291 
    292     Status = GetNextFile (CurrentFile, &CurrentFile);
    293     if (EFI_ERROR (Status)) {
    294       Error (NULL, 0, 0, "error parsing the FV", NULL);
    295       return EFI_ABORTED;
    296     }
    297   }
    298   //
    299   // File not found in this FV.
    300   //
    301   *File = NULL;
    302   return EFI_SUCCESS;
    303 }
    304 
    305 EFI_STATUS
    306 GetFileByType (
    307   IN EFI_FV_FILETYPE              FileType,
    308   IN UINTN                        Instance,
    309   OUT EFI_FFS_FILE_HEADER         **File
    310   )
    311 /*++
    312 
    313 Routine Description:
    314 
    315   Find a file by type and instance.  An instance of 1 is the first instance.
    316   The function will return NULL if a matching file cannot be found.
    317   File type EFI_FV_FILETYPE_ALL means any file type is valid.
    318 
    319 Arguments:
    320 
    321   FileType    Type of file to search for.
    322   Instance    Instace of the file type to return.
    323   File        Return pointer.  In the case of an error, contents are undefined.
    324 
    325 Returns:
    326 
    327   EFI_SUCCESS             The function completed successfully.
    328   EFI_ABORTED             An error was encountered.
    329   EFI_INVALID_PARAMETER   One of the parameters was NULL.
    330 
    331 --*/
    332 {
    333   EFI_FFS_FILE_HEADER *CurrentFile;
    334   EFI_STATUS          Status;
    335   UINTN               FileCount;
    336 
    337   //
    338   // Verify library has been initialized.
    339   //
    340   if (mFvHeader == NULL || mFvLength == 0) {
    341     return EFI_ABORTED;
    342   }
    343   //
    344   // Verify input parameters
    345   //
    346   if (File == NULL) {
    347     return EFI_INVALID_PARAMETER;
    348   }
    349   //
    350   // Verify FV header
    351   //
    352   Status = VerifyFv (mFvHeader);
    353   if (EFI_ERROR (Status)) {
    354     return EFI_ABORTED;
    355   }
    356   //
    357   // Initialize the number of matching files found.
    358   //
    359   FileCount = 0;
    360 
    361   //
    362   // Get the first file
    363   //
    364   Status = GetNextFile (NULL, &CurrentFile);
    365   if (EFI_ERROR (Status)) {
    366     Error (NULL, 0, 0, "error parsing FV", NULL);
    367     return EFI_ABORTED;
    368   }
    369   //
    370   // Loop as long as we have a valid file
    371   //
    372   while (CurrentFile) {
    373     if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) {
    374       FileCount++;
    375     }
    376 
    377     if (FileCount == Instance) {
    378       *File = CurrentFile;
    379       return EFI_SUCCESS;
    380     }
    381 
    382     Status = GetNextFile (CurrentFile, &CurrentFile);
    383     if (EFI_ERROR (Status)) {
    384       Error (NULL, 0, 0, "error parsing the FV", NULL);
    385       return EFI_ABORTED;
    386     }
    387   }
    388 
    389   *File = NULL;
    390   return EFI_SUCCESS;
    391 }
    392 
    393 EFI_STATUS
    394 SearchSectionByType (
    395   IN EFI_FILE_SECTION_POINTER  FirstSection,
    396   IN UINT8                     *SearchEnd,
    397   IN EFI_SECTION_TYPE          SectionType,
    398   IN OUT UINTN                 *StartIndex,
    399   IN UINTN                     Instance,
    400   OUT EFI_FILE_SECTION_POINTER *Section
    401   )
    402 /*++
    403 
    404 Routine Description:
    405 
    406   Helper function to search a sequence of sections from the section pointed
    407   by FirstSection to SearchEnd for the Instance-th section of type SectionType.
    408   The current counter is saved in StartIndex and when the section is found, it's
    409   saved in Section. GUID-defined sections, if special processing is not required,
    410   are searched recursively in a depth-first manner.
    411 
    412 Arguments:
    413 
    414   FirstSection The first section to start searching from.
    415   SearchEnd    The end address to stop search.
    416   SectionType  The type of section to search.
    417   StartIndex   The current counter is saved.
    418   Instance     The requested n-th section number.
    419   Section      The found section returned.
    420 
    421 Returns:
    422 
    423   EFI_SUCCESS             The function completed successfully.
    424   EFI_NOT_FOUND           The section is not found.
    425 --*/
    426 {
    427   EFI_FILE_SECTION_POINTER  CurrentSection;
    428   EFI_FILE_SECTION_POINTER  InnerSection;
    429   EFI_STATUS                Status;
    430   UINTN                     SectionSize;
    431 
    432   CurrentSection = FirstSection;
    433 
    434   while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) {
    435     if (CurrentSection.CommonHeader->Type == SectionType) {
    436       (*StartIndex)++;
    437     }
    438 
    439     if (*StartIndex == Instance) {
    440       *Section = CurrentSection;
    441       return EFI_SUCCESS;
    442     }
    443     //
    444     // If the requesting section is not GUID-defined and
    445     // we find a GUID-defined section that doesn't need
    446     // special processing, go ahead to search the requesting
    447     // section inside the GUID-defined section.
    448     //
    449     if (SectionType != EFI_SECTION_GUID_DEFINED &&
    450         CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED &&
    451         !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) {
    452       InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *)
    453         ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset);
    454       SectionSize = CurrentSection.CommonHeader->Size[0] +
    455         (CurrentSection.CommonHeader->Size[1] << 8) +
    456         (CurrentSection.CommonHeader->Size[2] << 16);
    457       Status = SearchSectionByType (
    458                  InnerSection,
    459                  (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize),
    460                  SectionType,
    461                  StartIndex,
    462                  Instance,
    463                  Section
    464                  );
    465       if (!EFI_ERROR (Status)) {
    466         return EFI_SUCCESS;
    467       }
    468     }
    469     //
    470     // Find next section (including compensating for alignment issues.
    471     //
    472     CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2));
    473   }
    474 
    475   return EFI_NOT_FOUND;
    476 }
    477 
    478 EFI_STATUS
    479 GetSectionByType (
    480   IN EFI_FFS_FILE_HEADER          *File,
    481   IN EFI_SECTION_TYPE             SectionType,
    482   IN UINTN                        Instance,
    483   OUT EFI_FILE_SECTION_POINTER    *Section
    484   )
    485 /*++
    486 
    487 Routine Description:
    488 
    489   Find a section in a file by type and instance.  An instance of 1 is the first
    490   instance.  The function will return NULL if a matching section cannot be found.
    491   GUID-defined sections, if special processing is not needed, are handled in a
    492   depth-first manner.
    493 
    494 Arguments:
    495 
    496   File        The file to search.
    497   SectionType Type of file to search for.
    498   Instance    Instace of the section to return.
    499   Section     Return pointer.  In the case of an error, contents are undefined.
    500 
    501 Returns:
    502 
    503   EFI_SUCCESS             The function completed successfully.
    504   EFI_ABORTED             An error was encountered.
    505   EFI_INVALID_PARAMETER   One of the parameters was NULL.
    506   EFI_NOT_FOUND           No found.
    507 --*/
    508 {
    509   EFI_FILE_SECTION_POINTER  CurrentSection;
    510   EFI_STATUS                Status;
    511   UINTN                     SectionCount;
    512 
    513   //
    514   // Verify input parameters
    515   //
    516   if (File == NULL || Instance == 0) {
    517     return EFI_INVALID_PARAMETER;
    518   }
    519   //
    520   // Verify FFS header
    521   //
    522   Status = VerifyFfsFile (File);
    523   if (EFI_ERROR (Status)) {
    524     Error (NULL, 0, 0, "invalid FFS file", NULL);
    525     return EFI_ABORTED;
    526   }
    527   //
    528   // Initialize the number of matching sections found.
    529   //
    530   SectionCount = 0;
    531 
    532   //
    533   // Get the first section
    534   //
    535   CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER));
    536 
    537   Status = SearchSectionByType (
    538              CurrentSection,
    539              (UINT8 *) ((UINTN) File + GetLength (File->Size)),
    540              SectionType,
    541              &SectionCount,
    542              Instance,
    543              Section
    544              );
    545 
    546   if (!EFI_ERROR (Status)) {
    547     return EFI_SUCCESS;
    548   } else {
    549     //
    550     // Section not found
    551     //
    552     (*Section).Code16Section = NULL;
    553     return EFI_NOT_FOUND;
    554   }
    555 }
    556 //
    557 // will not parse compressed sections
    558 //
    559 EFI_STATUS
    560 VerifyFv (
    561   IN EFI_FIRMWARE_VOLUME_HEADER   *FvHeader
    562   )
    563 /*++
    564 
    565 Routine Description:
    566 
    567   Verify the current pointer points to a valid FV header.
    568 
    569 Arguments:
    570 
    571   FvHeader     Pointer to an alleged FV file.
    572 
    573 Returns:
    574 
    575   EFI_SUCCESS             The FV header is valid.
    576   EFI_VOLUME_CORRUPTED    The FV header is not valid.
    577   EFI_INVALID_PARAMETER   A required parameter was NULL.
    578   EFI_ABORTED             Operation aborted.
    579 
    580 --*/
    581 {
    582   UINT16  Checksum;
    583 
    584   //
    585   // Verify input parameters
    586   //
    587   if (FvHeader == NULL) {
    588     return EFI_INVALID_PARAMETER;
    589   }
    590 
    591   if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
    592     Error (NULL, 0, 0, "invalid FV header signature", NULL);
    593     return EFI_VOLUME_CORRUPTED;
    594   }
    595   //
    596   // Verify header checksum
    597   //
    598   Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
    599 
    600   if (Checksum != 0) {
    601     Error (NULL, 0, 0, "invalid FV header checksum", NULL);
    602     return EFI_ABORTED;
    603   }
    604 
    605   return EFI_SUCCESS;
    606 }
    607 
    608 EFI_STATUS
    609 VerifyFfsFile (
    610   IN EFI_FFS_FILE_HEADER  *FfsHeader
    611   )
    612 /*++
    613 
    614 Routine Description:
    615 
    616   Verify the current pointer points to a FFS file header.
    617 
    618 Arguments:
    619 
    620   FfsHeader     Pointer to an alleged FFS file.
    621 
    622 Returns:
    623 
    624   EFI_SUCCESS           The Ffs header is valid.
    625   EFI_NOT_FOUND         This "file" is the beginning of free space.
    626   EFI_VOLUME_CORRUPTED  The Ffs header is not valid.
    627   EFI_ABORTED           The erase polarity is not known.
    628 
    629 --*/
    630 {
    631   BOOLEAN             ErasePolarity;
    632   EFI_STATUS          Status;
    633   EFI_FFS_FILE_HEADER BlankHeader;
    634   UINT8               Checksum;
    635   UINT32              FileLength;
    636   UINT32              OccupiedFileLength;
    637   UINT8               SavedChecksum;
    638   UINT8               SavedState;
    639   UINT8               FileGuidString[80];
    640   UINT32              TailSize;
    641 #if (PI_SPECIFICATION_VERSION < 0x00010000)
    642   EFI_FFS_FILE_TAIL   *Tail;
    643 #endif
    644 
    645   //
    646   // Verify library has been initialized.
    647   //
    648   if (mFvHeader == NULL || mFvLength == 0) {
    649     return EFI_ABORTED;
    650   }
    651   //
    652   // Verify FV header
    653   //
    654   Status = VerifyFv (mFvHeader);
    655   if (EFI_ERROR (Status)) {
    656     return EFI_ABORTED;
    657   }
    658   //
    659   // Get the erase polarity.
    660   //
    661   Status = GetErasePolarity (&ErasePolarity);
    662   if (EFI_ERROR (Status)) {
    663     return EFI_ABORTED;
    664   }
    665   //
    666   // Check if we have free space
    667   //
    668   if (ErasePolarity) {
    669     memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));
    670   } else {
    671     memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
    672   }
    673 
    674   if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {
    675     return EFI_NOT_FOUND;
    676   }
    677   //
    678   // Convert the GUID to a string so we can at least report which file
    679   // if we find an error.
    680   //
    681   PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE);
    682   if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
    683     TailSize = sizeof (EFI_FFS_FILE_TAIL);
    684   } else {
    685     TailSize = 0;
    686   }
    687   //
    688   // Verify file header checksum
    689   //
    690   SavedState = FfsHeader->State;
    691   FfsHeader->State = 0;
    692   SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File;
    693   FfsHeader->IntegrityCheck.Checksum.File = 0;
    694   Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER));
    695   FfsHeader->State = SavedState;
    696   FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum;
    697   if (Checksum != 0) {
    698     Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum");
    699     return EFI_ABORTED;
    700   }
    701   //
    702   // Verify file checksum
    703   //
    704   if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
    705     //
    706     // Verify file data checksum
    707     //
    708     FileLength          = GetLength (FfsHeader->Size);
    709     OccupiedFileLength  = (FileLength + 0x07) & (-1 << 3);
    710 #if (PI_SPECIFICATION_VERSION < 0x00010000)
    711     Checksum            = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize);
    712     Checksum            = (UINT8) (Checksum - FfsHeader->State);
    713 #else
    714     Checksum            = CalculateSum8 ((UINT8 *) ((UINTN)FfsHeader + sizeof (EFI_FFS_FILE_HEADER)), FileLength - TailSize - sizeof (EFI_FFS_FILE_HEADER));
    715     Checksum            =  Checksum + (UINT8)FfsHeader->IntegrityCheck.Checksum.File;
    716 #endif
    717     if (Checksum != 0) {
    718       Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum");
    719       return EFI_ABORTED;
    720     }
    721   } else {
    722     //
    723     // File does not have a checksum
    724     // Verify contents are 0x5A(Framework) and 0xAA(PI 1.0) as spec'd
    725     //
    726     if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
    727       Error (NULL, 0, 0, FileGuidString, "invalid fixed file checksum");
    728       return EFI_ABORTED;
    729     }
    730   }
    731 #if (PI_SPECIFICATION_VERSION < 0x00010000)
    732   //
    733   // Check if the tail is present and verify it if it is.
    734   //
    735   if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
    736     //
    737     // Verify tail is complement of integrity check field in the header.
    738     //
    739     Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL));
    740     if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) {
    741       Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail");
    742       return EFI_ABORTED;
    743     }
    744   }
    745 #endif
    746   return EFI_SUCCESS;
    747 }
    748 
    749 UINT32
    750 GetLength (
    751   UINT8     *ThreeByteLength
    752   )
    753 /*++
    754 
    755 Routine Description:
    756 
    757   Converts a three byte length value into a UINT32.
    758 
    759 Arguments:
    760 
    761   ThreeByteLength   Pointer to the first of the 3 byte length.
    762 
    763 Returns:
    764 
    765   UINT32      Size of the section
    766 
    767 --*/
    768 {
    769   UINT32  Length;
    770 
    771   if (ThreeByteLength == NULL) {
    772     return 0;
    773   }
    774 
    775   Length  = *((UINT32 *) ThreeByteLength);
    776   Length  = Length & 0x00FFFFFF;
    777 
    778   return Length;
    779 }
    780 
    781 EFI_STATUS
    782 GetErasePolarity (
    783   OUT BOOLEAN   *ErasePolarity
    784   )
    785 /*++
    786 
    787 Routine Description:
    788 
    789   This function returns with the FV erase polarity.  If the erase polarity
    790   for a bit is 1, the function return TRUE.
    791 
    792 Arguments:
    793 
    794   ErasePolarity   A pointer to the erase polarity.
    795 
    796 Returns:
    797 
    798   EFI_SUCCESS              The function completed successfully.
    799   EFI_INVALID_PARAMETER    One of the input parameters was invalid.
    800   EFI_ABORTED              Operation aborted.
    801 
    802 --*/
    803 {
    804   EFI_STATUS  Status;
    805 
    806   //
    807   // Verify library has been initialized.
    808   //
    809   if (mFvHeader == NULL || mFvLength == 0) {
    810     return EFI_ABORTED;
    811   }
    812   //
    813   // Verify FV header
    814   //
    815   Status = VerifyFv (mFvHeader);
    816   if (EFI_ERROR (Status)) {
    817     return EFI_ABORTED;
    818   }
    819   //
    820   // Verify input parameters.
    821   //
    822   if (ErasePolarity == NULL) {
    823     return EFI_INVALID_PARAMETER;
    824   }
    825 
    826   if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) {
    827     *ErasePolarity = TRUE;
    828   } else {
    829     *ErasePolarity = FALSE;
    830   }
    831 
    832   return EFI_SUCCESS;
    833 }
    834 
    835 UINT8
    836 GetFileState (
    837   IN BOOLEAN              ErasePolarity,
    838   IN EFI_FFS_FILE_HEADER  *FfsHeader
    839   )
    840 /*++
    841 
    842 Routine Description:
    843 
    844   This function returns a the highest state bit in the FFS that is set.
    845   It in no way validate the FFS file.
    846 
    847 Arguments:
    848 
    849   ErasePolarity The erase polarity for the file state bits.
    850   FfsHeader     Pointer to a FFS file.
    851 
    852 Returns:
    853 
    854   UINT8   The hightest set state of the file.
    855 
    856 --*/
    857 {
    858   UINT8 FileState;
    859   UINT8 HighestBit;
    860 
    861   FileState = FfsHeader->State;
    862 
    863   if (ErasePolarity) {
    864     FileState = (UINT8)~FileState;
    865   }
    866 
    867   HighestBit = 0x80;
    868   while (HighestBit != 0 && (HighestBit & FileState) == 0) {
    869     HighestBit >>= 1;
    870   }
    871 
    872   return HighestBit;
    873 }
    874