Home | History | Annotate | Download | only in Sec
      1 /**@file
      2 
      3 Copyright (c) 2006, 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   FwVol.c
     14 
     15 Abstract:
     16   A simple FV stack so the SEC can extract the SEC Core from an
     17   FV.
     18 
     19 **/
     20 
     21 #include "SecMain.h"
     22 
     23 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
     24   (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
     25 
     26 EFI_FFS_FILE_STATE
     27 GetFileState (
     28   IN UINT8                ErasePolarity,
     29   IN EFI_FFS_FILE_HEADER  *FfsHeader
     30   )
     31 /*++
     32 
     33 Routine Description:
     34   Returns the highest bit set of the State field
     35 
     36 Arguments:
     37   ErasePolarity   - Erase Polarity  as defined by EFI_FVB_ERASE_POLARITY
     38                     in the Attributes field.
     39   FfsHeader       - Pointer to FFS File Header.
     40 
     41 Returns:
     42   Returns the highest bit in the State field
     43 
     44 --*/
     45 {
     46   EFI_FFS_FILE_STATE  FileState;
     47   EFI_FFS_FILE_STATE  HighestBit;
     48 
     49   FileState = FfsHeader->State;
     50 
     51   if (ErasePolarity != 0) {
     52     FileState = (EFI_FFS_FILE_STATE)~FileState;
     53   }
     54 
     55   HighestBit = 0x80;
     56   while (HighestBit != 0 && (HighestBit & FileState) == 0) {
     57     HighestBit >>= 1;
     58   }
     59 
     60   return HighestBit;
     61 }
     62 
     63 UINT8
     64 CalculateHeaderChecksum (
     65   IN EFI_FFS_FILE_HEADER  *FileHeader
     66   )
     67 /*++
     68 
     69 Routine Description:
     70   Calculates the checksum of the header of a file.
     71 
     72 Arguments:
     73   FileHeader       - Pointer to FFS File Header.
     74 
     75 Returns:
     76   Checksum of the header.
     77 
     78 --*/
     79 {
     80   UINT8 *ptr;
     81   UINTN Index;
     82   UINT8 Sum;
     83 
     84   Sum = 0;
     85   ptr = (UINT8 *) FileHeader;
     86 
     87   for (Index = 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index += 4) {
     88     Sum = (UINT8) (Sum + ptr[Index]);
     89     Sum = (UINT8) (Sum + ptr[Index + 1]);
     90     Sum = (UINT8) (Sum + ptr[Index + 2]);
     91     Sum = (UINT8) (Sum + ptr[Index + 3]);
     92   }
     93 
     94   for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) {
     95     Sum = (UINT8) (Sum + ptr[Index]);
     96   }
     97   //
     98   // State field (since this indicates the different state of file).
     99   //
    100   Sum = (UINT8) (Sum - FileHeader->State);
    101   //
    102   // Checksum field of the file is not part of the header checksum.
    103   //
    104   Sum = (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File);
    105 
    106   return Sum;
    107 }
    108 
    109 EFI_STATUS
    110 SecFfsFindNextFile (
    111   IN EFI_FV_FILETYPE             SearchType,
    112   IN EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader,
    113   IN OUT EFI_FFS_FILE_HEADER     **FileHeader
    114   )
    115 /*++
    116 
    117 Routine Description:
    118     Given the input file pointer, search for the next matching file in the
    119     FFS volume as defined by SearchType. The search starts from FileHeader inside
    120     the Firmware Volume defined by FwVolHeader.
    121 
    122 Arguments:
    123     SearchType - Filter to find only files of this type.
    124                  Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
    125     FwVolHeader - Pointer to the FV header of the volume to search.
    126                   This parameter must point to a valid FFS volume.
    127     FileHeader  - Pointer to the current file from which to begin searching.
    128                   This pointer will be updated upon return to reflect the file
    129                   found.
    130 
    131 Returns:
    132     EFI_NOT_FOUND - No files matching the search criteria were found
    133     EFI_SUCCESS
    134 
    135 --*/
    136 {
    137   EFI_FFS_FILE_HEADER *FfsFileHeader;
    138   UINT32              FileLength;
    139   UINT32              FileOccupiedSize;
    140   UINT32              FileOffset;
    141   UINT64              FvLength;
    142   UINT8               ErasePolarity;
    143   UINT8               FileState;
    144 
    145   FvLength = FwVolHeader->FvLength;
    146   if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
    147     ErasePolarity = 1;
    148   } else {
    149     ErasePolarity = 0;
    150   }
    151   //
    152   // If FileHeader is not specified (NULL) start with the first file in the
    153   // firmware volume.  Otherwise, start from the FileHeader.
    154   //
    155   if (*FileHeader == NULL) {
    156     FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength);
    157   } else {
    158     //
    159     // Length is 24 bits wide so mask upper 8 bits
    160     // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
    161     //
    162     FileLength        = *(UINT32 *) (*FileHeader)->Size & 0x00FFFFFF;
    163     FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    164     FfsFileHeader     = (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader + FileOccupiedSize);
    165   }
    166 
    167   FileOffset = (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader);
    168 
    169   while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
    170     //
    171     // Get FileState which is the highest bit of the State
    172     //
    173     FileState = GetFileState (ErasePolarity, FfsFileHeader);
    174 
    175     switch (FileState) {
    176 
    177     case EFI_FILE_HEADER_INVALID:
    178       FileOffset += sizeof (EFI_FFS_FILE_HEADER);
    179       FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
    180       break;
    181 
    182     case EFI_FILE_DATA_VALID:
    183     case EFI_FILE_MARKED_FOR_UPDATE:
    184       if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
    185         FileLength        = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    186         FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    187 
    188         if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) {
    189 
    190           *FileHeader = FfsFileHeader;
    191 
    192           return EFI_SUCCESS;
    193         }
    194 
    195         FileOffset += FileOccupiedSize;
    196         FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
    197       } else {
    198         return EFI_NOT_FOUND;
    199       }
    200       break;
    201 
    202     case EFI_FILE_DELETED:
    203       FileLength        = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    204       FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    205       FileOffset += FileOccupiedSize;
    206       FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
    207       break;
    208 
    209     default:
    210       return EFI_NOT_FOUND;
    211 
    212     }
    213   }
    214 
    215   return EFI_NOT_FOUND;
    216 }
    217 
    218 EFI_STATUS
    219 SecFfsFindSectionData (
    220   IN EFI_SECTION_TYPE      SectionType,
    221   IN EFI_FFS_FILE_HEADER   *FfsFileHeader,
    222   IN OUT VOID              **SectionData
    223   )
    224 /*++
    225 
    226 Routine Description:
    227     Given the input file pointer, search for the next matching section in the
    228     FFS volume.
    229 
    230 Arguments:
    231     SearchType    - Filter to find only sections of this type.
    232     FfsFileHeader - Pointer to the current file to search.
    233     SectionData   - Pointer to the Section matching SectionType in FfsFileHeader.
    234                      NULL if section not found
    235 
    236 Returns:
    237     EFI_NOT_FOUND - No files matching the search criteria were found
    238     EFI_SUCCESS
    239 
    240 --*/
    241 {
    242   UINT32                    FileSize;
    243   EFI_COMMON_SECTION_HEADER *Section;
    244   UINT32                    SectionLength;
    245   UINT32                    ParsedLength;
    246 
    247   //
    248   // Size is 24 bits wide so mask upper 8 bits.
    249   //    Does not include FfsFileHeader header size
    250   // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
    251   //
    252   Section   = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1);
    253   FileSize  = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    254   FileSize -= sizeof (EFI_FFS_FILE_HEADER);
    255 
    256   *SectionData  = NULL;
    257   ParsedLength  = 0;
    258   while (ParsedLength < FileSize) {
    259     if (Section->Type == SectionType) {
    260       *SectionData = (VOID *) (Section + 1);
    261       return EFI_SUCCESS;
    262     }
    263     //
    264     // Size is 24 bits wide so mask upper 8 bits.
    265     // SectionLength is adjusted it is 4 byte aligned.
    266     // Go to the next section
    267     //
    268     SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF;
    269     SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
    270 
    271     ParsedLength += SectionLength;
    272     Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
    273   }
    274 
    275   return EFI_NOT_FOUND;
    276 }
    277 
    278 EFI_STATUS
    279 SecFfsFindPeiCore (
    280   IN  EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader,
    281   OUT VOID                        **Pe32Data
    282   )
    283 /*++
    284 
    285 Routine Description:
    286   Given the pointer to the Firmware Volume Header find the SEC
    287   core and return it's PE32 image.
    288 
    289 Arguments:
    290   FwVolHeader - Pointer to memory mapped FV
    291   Pe32Data - Pointer to SEC PE32 iamge.
    292 
    293 Returns:
    294   EFI_SUCCESS - Pe32Data is valid
    295   other       - Failure
    296 
    297 --*/
    298 {
    299   EFI_STATUS          Status;
    300   EFI_FFS_FILE_HEADER *FileHeader;
    301   EFI_FV_FILETYPE     SearchType;
    302 
    303   SearchType  = EFI_FV_FILETYPE_PEI_CORE;
    304   FileHeader  = NULL;
    305   do {
    306     Status = SecFfsFindNextFile (SearchType, FwVolHeader, &FileHeader);
    307     if (!EFI_ERROR (Status)) {
    308       Status = SecFfsFindSectionData (EFI_SECTION_PE32, FileHeader, Pe32Data);
    309       return Status;
    310     }
    311   } while (!EFI_ERROR (Status));
    312 
    313   return Status;
    314 }
    315