• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
GetFileState(IN UINT8 ErasePolarity,IN EFI_FFS_FILE_HEADER * FfsHeader)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
CalculateHeaderChecksum(IN EFI_FFS_FILE_HEADER * FileHeader)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
SecFfsFindNextFile(IN EFI_FV_FILETYPE SearchType,IN EFI_FIRMWARE_VOLUME_HEADER * FwVolHeader,IN OUT EFI_FFS_FILE_HEADER ** FileHeader)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
SecFfsFindSectionData(IN EFI_SECTION_TYPE SectionType,IN EFI_FFS_FILE_HEADER * FfsFileHeader,IN OUT VOID ** SectionData)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
SecFfsFindPeiCore(IN EFI_FIRMWARE_VOLUME_HEADER * FwVolHeader,OUT VOID ** Pe32Data)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