• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Implements functions to read firmware file
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "DxeMain.h"
16 #include "FwVolDriver.h"
17 
18 /**
19 Required Alignment             Alignment Value in FFS         Alignment Value in
20 (bytes)                        Attributes Field               Firmware Volume Interfaces
21 1                                    0                                     0
22 16                                   1                                     4
23 128                                  2                                     7
24 512                                  3                                     9
25 1 KB                                 4                                     10
26 4 KB                                 5                                     12
27 32 KB                                6                                     15
28 64 KB                                7                                     16
29 **/
30 UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
31 
32 /**
33   Convert the FFS File Attributes to FV File Attributes
34 
35   @param  FfsAttributes              The attributes of UINT8 type.
36 
37   @return The attributes of EFI_FV_FILE_ATTRIBUTES
38 
39 **/
40 EFI_FV_FILE_ATTRIBUTES
FfsAttributes2FvFileAttributes(IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes)41 FfsAttributes2FvFileAttributes (
42   IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
43   )
44 {
45   UINT8                     DataAlignment;
46   EFI_FV_FILE_ATTRIBUTES    FileAttribute;
47 
48   DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
49   ASSERT (DataAlignment < 8);
50 
51   FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment];
52 
53   if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) {
54     FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED;
55   }
56 
57   return FileAttribute;
58 }
59 
60 /**
61   Given the input key, search for the next matching file in the volume.
62 
63   @param  This                       Indicates the calling context.
64   @param  Key                        Key is a pointer to a caller allocated
65                                      buffer that contains implementation specific
66                                      data that is used to track where to begin
67                                      the search for the next file. The size of
68                                      the buffer must be at least This->KeySize
69                                      bytes long. To reinitialize the search and
70                                      begin from the beginning of the firmware
71                                      volume, the entire buffer must be cleared to
72                                      zero. Other than clearing the buffer to
73                                      initiate a new search, the caller must not
74                                      modify the data in the buffer between calls
75                                      to GetNextFile().
76   @param  FileType                   FileType is a pointer to a caller allocated
77                                      EFI_FV_FILETYPE. The GetNextFile() API can
78                                      filter it's search for files based on the
79                                      value of *FileType input. A *FileType input
80                                      of 0 causes GetNextFile() to search for
81                                      files of all types.  If a file is found, the
82                                      file's type is returned in *FileType.
83                                      *FileType is not modified if no file is
84                                      found.
85   @param  NameGuid                   NameGuid is a pointer to a caller allocated
86                                      EFI_GUID. If a file is found, the file's
87                                      name is returned in *NameGuid.  *NameGuid is
88                                      not modified if no file is found.
89   @param  Attributes                 Attributes is a pointer to a caller
90                                      allocated EFI_FV_FILE_ATTRIBUTES.  If a file
91                                      is found, the file's attributes are returned
92                                      in *Attributes. *Attributes is not modified
93                                      if no file is found.
94   @param  Size                       Size is a pointer to a caller allocated
95                                      UINTN. If a file is found, the file's size
96                                      is returned in *Size. *Size is not modified
97                                      if no file is found.
98 
99   @retval EFI_SUCCESS                Successfully find the file.
100   @retval EFI_DEVICE_ERROR           Device error.
101   @retval EFI_ACCESS_DENIED          Fv could not read.
102   @retval EFI_NOT_FOUND              No matching file found.
103   @retval EFI_INVALID_PARAMETER      Invalid parameter
104 
105 **/
106 EFI_STATUS
107 EFIAPI
FvGetNextFile(IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL * This,IN OUT VOID * Key,IN OUT EFI_FV_FILETYPE * FileType,OUT EFI_GUID * NameGuid,OUT EFI_FV_FILE_ATTRIBUTES * Attributes,OUT UINTN * Size)108 FvGetNextFile (
109   IN CONST   EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
110   IN OUT     VOID                          *Key,
111   IN OUT     EFI_FV_FILETYPE               *FileType,
112   OUT        EFI_GUID                      *NameGuid,
113   OUT        EFI_FV_FILE_ATTRIBUTES        *Attributes,
114   OUT        UINTN                         *Size
115   )
116 {
117   EFI_STATUS                                  Status;
118   FV_DEVICE                                   *FvDevice;
119   EFI_FV_ATTRIBUTES                           FvAttributes;
120   EFI_FFS_FILE_HEADER                         *FfsFileHeader;
121   UINTN                                       *KeyValue;
122   LIST_ENTRY                                  *Link;
123   FFS_FILE_LIST_ENTRY                         *FfsFileEntry;
124 
125   FvDevice = FV_DEVICE_FROM_THIS (This);
126 
127   Status = FvGetVolumeAttributes (This, &FvAttributes);
128   if (EFI_ERROR (Status)){
129     return Status;
130   }
131 
132   //
133   // Check if read operation is enabled
134   //
135   if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {
136     return EFI_ACCESS_DENIED;
137   }
138 
139   if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
140     //
141     // File type needs to be in 0 - 0x0D
142     //
143     return EFI_NOT_FOUND;
144   }
145 
146   KeyValue = (UINTN *)Key;
147   for (;;) {
148     if (*KeyValue == 0) {
149       //
150       // Search for 1st matching file
151       //
152       Link = &FvDevice->FfsFileListHeader;
153     } else {
154       //
155       // Key is pointer to FFsFileEntry, so get next one
156       //
157       Link = (LIST_ENTRY *)(*KeyValue);
158     }
159 
160     if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
161       //
162       // Next is end of list so we did not find data
163       //
164       return EFI_NOT_FOUND;
165     }
166 
167     FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink;
168     FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader;
169 
170     //
171     // remember the key
172     //
173     *KeyValue = (UINTN)FfsFileEntry;
174 
175     if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
176       //
177       // we ignore pad files
178       //
179       continue;
180     }
181 
182     if (*FileType == EFI_FV_FILETYPE_ALL) {
183       //
184       // Process all file types so we have a match
185       //
186       break;
187     }
188 
189     if (*FileType == FfsFileHeader->Type) {
190       //
191       // Found a matching file type
192       //
193       break;
194     }
195 
196   }
197 
198   //
199   // Return FileType, NameGuid, and Attributes
200   //
201   *FileType = FfsFileHeader->Type;
202   CopyGuid (NameGuid, &FfsFileHeader->Name);
203   *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
204   if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
205     *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
206   }
207 
208   //
209   // we need to substract the header size
210   //
211   if (IS_FFS_FILE2 (FfsFileHeader)) {
212     *Size = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
213   } else {
214     *Size = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
215   }
216 
217   return EFI_SUCCESS;
218 }
219 
220 
221 
222 /**
223   Locates a file in the firmware volume and
224   copies it to the supplied buffer.
225 
226   @param  This                       Indicates the calling context.
227   @param  NameGuid                   Pointer to an EFI_GUID, which is the
228                                      filename.
229   @param  Buffer                     Buffer is a pointer to pointer to a buffer
230                                      in which the file or section contents or are
231                                      returned.
232   @param  BufferSize                 BufferSize is a pointer to caller allocated
233                                      UINTN. On input *BufferSize indicates the
234                                      size in bytes of the memory region pointed
235                                      to by Buffer. On output, *BufferSize
236                                      contains the number of bytes required to
237                                      read the file.
238   @param  FoundType                  FoundType is a pointer to a caller allocated
239                                      EFI_FV_FILETYPE that on successful return
240                                      from Read() contains the type of file read.
241                                      This output reflects the file type
242                                      irrespective of the value of the SectionType
243                                      input.
244   @param  FileAttributes             FileAttributes is a pointer to a caller
245                                      allocated EFI_FV_FILE_ATTRIBUTES.  On
246                                      successful return from Read(),
247                                      *FileAttributes contains the attributes of
248                                      the file read.
249   @param  AuthenticationStatus       AuthenticationStatus is a pointer to a
250                                      caller allocated UINTN in which the
251                                      authentication status is returned.
252 
253   @retval EFI_SUCCESS                Successfully read to memory buffer.
254   @retval EFI_WARN_BUFFER_TOO_SMALL  Buffer too small.
255   @retval EFI_NOT_FOUND              Not found.
256   @retval EFI_DEVICE_ERROR           Device error.
257   @retval EFI_ACCESS_DENIED          Could not read.
258   @retval EFI_INVALID_PARAMETER      Invalid parameter.
259   @retval EFI_OUT_OF_RESOURCES       Not enough buffer to be allocated.
260 
261 **/
262 EFI_STATUS
263 EFIAPI
FvReadFile(IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL * This,IN CONST EFI_GUID * NameGuid,IN OUT VOID ** Buffer,IN OUT UINTN * BufferSize,OUT EFI_FV_FILETYPE * FoundType,OUT EFI_FV_FILE_ATTRIBUTES * FileAttributes,OUT UINT32 * AuthenticationStatus)264 FvReadFile (
265   IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
266   IN CONST EFI_GUID                      *NameGuid,
267   IN OUT   VOID                          **Buffer,
268   IN OUT   UINTN                         *BufferSize,
269   OUT      EFI_FV_FILETYPE               *FoundType,
270   OUT      EFI_FV_FILE_ATTRIBUTES        *FileAttributes,
271   OUT      UINT32                        *AuthenticationStatus
272   )
273 {
274   EFI_STATUS                        Status;
275   FV_DEVICE                         *FvDevice;
276   EFI_GUID                          SearchNameGuid;
277   EFI_FV_FILETYPE                   LocalFoundType;
278   EFI_FV_FILE_ATTRIBUTES            LocalAttributes;
279   UINTN                             FileSize;
280   UINT8                             *SrcPtr;
281   EFI_FFS_FILE_HEADER               *FfsHeader;
282   UINTN                             InputBufferSize;
283   UINTN                             WholeFileSize;
284 
285   if (NameGuid == NULL) {
286     return EFI_INVALID_PARAMETER;
287   }
288 
289   FvDevice = FV_DEVICE_FROM_THIS (This);
290 
291 
292   //
293   // Keep looking until we find the matching NameGuid.
294   // The Key is really a FfsFileEntry
295   //
296   FvDevice->LastKey = 0;
297   do {
298     LocalFoundType = 0;
299     Status = FvGetNextFile (
300               This,
301               &FvDevice->LastKey,
302               &LocalFoundType,
303               &SearchNameGuid,
304               &LocalAttributes,
305               &FileSize
306               );
307     if (EFI_ERROR (Status)) {
308       return EFI_NOT_FOUND;
309     }
310   } while (!CompareGuid (&SearchNameGuid, NameGuid));
311 
312   //
313   // Get a pointer to the header
314   //
315   FfsHeader = FvDevice->LastKey->FfsHeader;
316   if (FvDevice->IsMemoryMapped) {
317     //
318     // Memory mapped FV has not been cached, so here is to cache by file.
319     //
320     if (!FvDevice->LastKey->FileCached) {
321       //
322       // Cache FFS file to memory buffer.
323       //
324       WholeFileSize = IS_FFS_FILE2 (FfsHeader) ? FFS_FILE2_SIZE (FfsHeader): FFS_FILE_SIZE (FfsHeader);
325       FfsHeader = AllocateCopyPool (WholeFileSize, FfsHeader);
326       if (FfsHeader == NULL) {
327         return EFI_OUT_OF_RESOURCES;
328       }
329       //
330       // Let FfsHeader in FfsFileEntry point to the cached file buffer.
331       //
332       FvDevice->LastKey->FfsHeader = FfsHeader;
333       FvDevice->LastKey->FileCached = TRUE;
334     }
335   }
336 
337   //
338   // Remember callers buffer size
339   //
340   InputBufferSize = *BufferSize;
341 
342   //
343   // Calculate return values
344   //
345   *FoundType = FfsHeader->Type;
346   *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
347    if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
348      *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
349    }
350   //
351   // Inherit the authentication status.
352   //
353   *AuthenticationStatus = FvDevice->AuthenticationStatus;
354   *BufferSize = FileSize;
355 
356   if (Buffer == NULL) {
357     //
358     // If Buffer is NULL, we only want to get the information collected so far
359     //
360     return EFI_SUCCESS;
361   }
362 
363   //
364   // Skip over file header
365   //
366   if (IS_FFS_FILE2 (FfsHeader)) {
367     SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);
368   } else {
369     SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
370   }
371 
372   Status = EFI_SUCCESS;
373   if (*Buffer == NULL) {
374     //
375     // Caller passed in a pointer so allocate buffer for them
376     //
377     *Buffer = AllocatePool (FileSize);
378     if (*Buffer == NULL) {
379       return EFI_OUT_OF_RESOURCES;
380     }
381   } else if (FileSize > InputBufferSize) {
382     //
383     // Callers buffer was not big enough
384     //
385     Status = EFI_WARN_BUFFER_TOO_SMALL;
386     FileSize = InputBufferSize;
387   }
388 
389   //
390   // Copy data into callers buffer
391   //
392   CopyMem (*Buffer, SrcPtr, FileSize);
393 
394   return Status;
395 }
396 
397 
398 
399 /**
400   Locates a section in a given FFS File and
401   copies it to the supplied buffer (not including section header).
402 
403   @param  This                       Indicates the calling context.
404   @param  NameGuid                   Pointer to an EFI_GUID, which is the
405                                      filename.
406   @param  SectionType                Indicates the section type to return.
407   @param  SectionInstance            Indicates which instance of sections with a
408                                      type of SectionType to return.
409   @param  Buffer                     Buffer is a pointer to pointer to a buffer
410                                      in which the file or section contents or are
411                                      returned.
412   @param  BufferSize                 BufferSize is a pointer to caller allocated
413                                      UINTN.
414   @param  AuthenticationStatus       AuthenticationStatus is a pointer to a
415                                      caller allocated UINT32 in which the
416                                      authentication status is returned.
417 
418   @retval EFI_SUCCESS                Successfully read the file section into
419                                      buffer.
420   @retval EFI_WARN_BUFFER_TOO_SMALL  Buffer too small.
421   @retval EFI_NOT_FOUND              Section not found.
422   @retval EFI_DEVICE_ERROR           Device error.
423   @retval EFI_ACCESS_DENIED          Could not read.
424   @retval EFI_INVALID_PARAMETER      Invalid parameter.
425 
426 **/
427 EFI_STATUS
428 EFIAPI
FvReadFileSection(IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL * This,IN CONST EFI_GUID * NameGuid,IN EFI_SECTION_TYPE SectionType,IN UINTN SectionInstance,IN OUT VOID ** Buffer,IN OUT UINTN * BufferSize,OUT UINT32 * AuthenticationStatus)429 FvReadFileSection (
430   IN CONST  EFI_FIRMWARE_VOLUME2_PROTOCOL  *This,
431   IN CONST  EFI_GUID                       *NameGuid,
432   IN        EFI_SECTION_TYPE               SectionType,
433   IN        UINTN                          SectionInstance,
434   IN OUT    VOID                           **Buffer,
435   IN OUT    UINTN                          *BufferSize,
436   OUT       UINT32                         *AuthenticationStatus
437   )
438 {
439   EFI_STATUS                        Status;
440   FV_DEVICE                         *FvDevice;
441   EFI_FV_FILETYPE                   FileType;
442   EFI_FV_FILE_ATTRIBUTES            FileAttributes;
443   UINTN                             FileSize;
444   UINT8                             *FileBuffer;
445   FFS_FILE_LIST_ENTRY               *FfsEntry;
446 
447   if (NameGuid == NULL || Buffer == NULL) {
448     return EFI_INVALID_PARAMETER;
449   }
450 
451   FvDevice = FV_DEVICE_FROM_THIS (This);
452 
453   //
454   // Read the file
455   //
456   Status = FvReadFile (
457             This,
458             NameGuid,
459             NULL,
460             &FileSize,
461             &FileType,
462             &FileAttributes,
463             AuthenticationStatus
464             );
465   //
466   // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
467   //
468   FfsEntry = (FFS_FILE_LIST_ENTRY *) FvDevice->LastKey;
469 
470   if (EFI_ERROR (Status)) {
471     return Status;
472   }
473   if (IS_FFS_FILE2 (FfsEntry->FfsHeader)) {
474     FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);
475   } else {
476     FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
477   }
478   //
479   // Check to see that the file actually HAS sections before we go any further.
480   //
481   if (FileType == EFI_FV_FILETYPE_RAW) {
482     Status = EFI_NOT_FOUND;
483     goto Done;
484   }
485 
486   //
487   // Use FfsEntry to cache Section Extraction Protocol Information
488   //
489   if (FfsEntry->StreamHandle == 0) {
490     Status = OpenSectionStream (
491                FileSize,
492                FileBuffer,
493                &FfsEntry->StreamHandle
494                );
495     if (EFI_ERROR (Status)) {
496       goto Done;
497     }
498   }
499 
500   //
501   // If SectionType == 0 We need the whole section stream
502   //
503   Status = GetSection (
504              FfsEntry->StreamHandle,
505              (SectionType == 0) ? NULL : &SectionType,
506              NULL,
507              (SectionType == 0) ? 0 : SectionInstance,
508              Buffer,
509              BufferSize,
510              AuthenticationStatus,
511              FvDevice->IsFfs3Fv
512              );
513 
514   if (!EFI_ERROR (Status)) {
515     //
516     // Inherit the authentication status.
517     //
518     *AuthenticationStatus |= FvDevice->AuthenticationStatus;
519   }
520 
521   //
522   // Close of stream defered to close of FfsHeader list to allow SEP to cache data
523   //
524 
525 Done:
526   return Status;
527 }
528 
529 
530