2 Implements functions to read firmware file.
4 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "FwVolDriver.h"
20 Required Alignment Alignment Value in FFS FFS_ATTRIB_DATA_ALIGNMENT2 Alignment Value in
21 (bytes) Attributes Field in FFS Attributes Field Firmware Volume Interfaces
39 UINT8 mFvAttributes
[] = {0, 4, 7, 9, 10, 12, 15, 16};
40 UINT8 mFvAttributes2
[] = {17, 18, 19, 20, 21, 22, 23, 24};
43 Convert the FFS File Attributes to FV File Attributes.
45 @param FfsAttributes The attributes of UINT8 type.
47 @return The attributes of EFI_FV_FILE_ATTRIBUTES
50 EFI_FV_FILE_ATTRIBUTES
51 FfsAttributes2FvFileAttributes (
52 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
56 EFI_FV_FILE_ATTRIBUTES FileAttribute
;
58 DataAlignment
= (UINT8
) ((FfsAttributes
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3);
59 ASSERT (DataAlignment
< 8);
61 if ((FfsAttributes
& FFS_ATTRIB_DATA_ALIGNMENT_2
) != 0) {
62 FileAttribute
= (EFI_FV_FILE_ATTRIBUTES
) mFvAttributes2
[DataAlignment
];
64 FileAttribute
= (EFI_FV_FILE_ATTRIBUTES
) mFvAttributes
[DataAlignment
];
67 if ((FfsAttributes
& FFS_ATTRIB_FIXED
) == FFS_ATTRIB_FIXED
) {
68 FileAttribute
|= EFI_FV_FILE_ATTRIB_FIXED
;
75 Given the input key, search for the next matching file in the volume.
77 @param This Indicates the calling context.
78 @param Key Key is a pointer to a caller allocated
79 buffer that contains implementation specific
80 data that is used to track where to begin
81 the search for the next file. The size of
82 the buffer must be at least This->KeySize
83 bytes long. To reinitialize the search and
84 begin from the beginning of the firmware
85 volume, the entire buffer must be cleared to
86 zero. Other than clearing the buffer to
87 initiate a new search, the caller must not
88 modify the data in the buffer between calls
90 @param FileType FileType is a pointer to a caller allocated
91 EFI_FV_FILETYPE. The GetNextFile() API can
92 filter it's search for files based on the
93 value of *FileType input. A *FileType input
94 of 0 causes GetNextFile() to search for
95 files of all types. If a file is found, the
96 file's type is returned in *FileType.
97 *FileType is not modified if no file is
99 @param NameGuid NameGuid is a pointer to a caller allocated
100 EFI_GUID. If a file is found, the file's
101 name is returned in *NameGuid. *NameGuid is
102 not modified if no file is found.
103 @param Attributes Attributes is a pointer to a caller
104 allocated EFI_FV_FILE_ATTRIBUTES. If a file
105 is found, the file's attributes are returned
106 in *Attributes. *Attributes is not modified
108 @param Size Size is a pointer to a caller allocated
109 UINTN. If a file is found, the file's size
110 is returned in *Size. *Size is not modified
113 @retval EFI_SUCCESS Successfully find the file.
114 @retval EFI_DEVICE_ERROR Device error.
115 @retval EFI_ACCESS_DENIED Fv could not read.
116 @retval EFI_NOT_FOUND No matching file found.
117 @retval EFI_INVALID_PARAMETER Invalid parameter
123 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
125 IN OUT EFI_FV_FILETYPE
*FileType
,
126 OUT EFI_GUID
*NameGuid
,
127 OUT EFI_FV_FILE_ATTRIBUTES
*Attributes
,
133 EFI_FV_ATTRIBUTES FvAttributes
;
134 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
137 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
139 FvDevice
= FV_DEVICE_FROM_THIS (This
);
141 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
142 if (EFI_ERROR (Status
)) {
146 KeyValue
= (UINTN
*) Key
;
147 FfsFileHeader
= NULL
;
150 // Check if read operation is enabled
152 if ((FvAttributes
& EFI_FV2_READ_STATUS
) == 0) {
153 return EFI_ACCESS_DENIED
;
156 if (*FileType
> EFI_FV_FILETYPE_SMM_CORE
) {
158 // File type needs to be in 0 - 0x0D
160 return EFI_NOT_FOUND
;
164 if (*KeyValue
== 0) {
166 // Search for 1st matching file
168 Link
= &FvDevice
->FfsFileListHeader
;
169 if (Link
->ForwardLink
== &FvDevice
->FfsFileListHeader
) {
170 return EFI_NOT_FOUND
;
173 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Link
->ForwardLink
;
174 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
179 *KeyValue
= (UINTN
) FfsFileEntry
;
182 // we ignore pad files
184 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
188 if (*FileType
== 0) {
192 if (*FileType
== FfsFileHeader
->Type
) {
198 // Getting link from last Ffs
200 Link
= (LIST_ENTRY
*) (*KeyValue
);
201 if (Link
->ForwardLink
== &FvDevice
->FfsFileListHeader
) {
202 return EFI_NOT_FOUND
;
205 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Link
->ForwardLink
;
206 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
211 *KeyValue
= (UINTN
) FfsFileEntry
;
214 // we ignore pad files
216 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
220 if (*FileType
== EFI_FV_FILETYPE_ALL
) {
224 if (*FileType
== FfsFileHeader
->Type
) {
228 } while (Link
->ForwardLink
!= &FvDevice
->FfsFileListHeader
);
231 // Cache this file entry
233 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
235 *FileType
= FfsFileHeader
->Type
;
236 CopyGuid (NameGuid
, &FfsFileHeader
->Name
);
237 *Attributes
= FfsAttributes2FvFileAttributes (FfsFileHeader
->Attributes
);
238 if ((FvDevice
->FwVolHeader
->Attributes
& EFI_FVB2_MEMORY_MAPPED
) == EFI_FVB2_MEMORY_MAPPED
) {
239 *Attributes
|= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED
;
243 // we need to substract the header size
245 if (IS_FFS_FILE2 (FfsFileHeader
)) {
246 *Size
= FFS_FILE2_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
248 *Size
= FFS_FILE_SIZE (FfsFileHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
251 if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid
, NameGuid
)) {
253 // specially deal with VTF file
258 if (IS_FFS_FILE2 (FfsFileHeader
)) {
259 SrcPtr
= ((UINT8
*) FfsFileHeader
) + sizeof (EFI_FFS_FILE_HEADER2
);
261 SrcPtr
= ((UINT8
*) FfsFileHeader
) + sizeof (EFI_FFS_FILE_HEADER
);
265 Tmp
= *(UINT32
*) SrcPtr
;
279 Locates a file in the firmware volume and
280 copies it to the supplied buffer.
282 @param This Indicates the calling context.
283 @param NameGuid Pointer to an EFI_GUID, which is the
285 @param Buffer Buffer is a pointer to pointer to a buffer
286 in which the file or section contents or are
288 @param BufferSize BufferSize is a pointer to caller allocated
289 UINTN. On input *BufferSize indicates the
290 size in bytes of the memory region pointed
291 to by Buffer. On output, *BufferSize
292 contains the number of bytes required to
294 @param FoundType FoundType is a pointer to a caller allocated
295 EFI_FV_FILETYPE that on successful return
296 from Read() contains the type of file read.
297 This output reflects the file type
298 irrespective of the value of the SectionType
300 @param FileAttributes FileAttributes is a pointer to a caller
301 allocated EFI_FV_FILE_ATTRIBUTES. On
302 successful return from Read(),
303 *FileAttributes contains the attributes of
305 @param AuthenticationStatus AuthenticationStatus is a pointer to a
306 caller allocated UINTN in which the
307 authentication status is returned.
309 @retval EFI_SUCCESS Successfully read to memory buffer.
310 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
311 @retval EFI_NOT_FOUND Not found.
312 @retval EFI_DEVICE_ERROR Device error.
313 @retval EFI_ACCESS_DENIED Could not read.
314 @retval EFI_INVALID_PARAMETER Invalid parameter.
315 @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
321 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
322 IN CONST EFI_GUID
*NameGuid
,
323 IN OUT VOID
**Buffer
,
324 IN OUT UINTN
*BufferSize
,
325 OUT EFI_FV_FILETYPE
*FoundType
,
326 OUT EFI_FV_FILE_ATTRIBUTES
*FileAttributes
,
327 OUT UINT32
*AuthenticationStatus
333 EFI_GUID SearchNameGuid
;
334 EFI_FV_ATTRIBUTES FvAttributes
;
335 EFI_FV_FILETYPE LocalFoundType
;
336 EFI_FV_FILE_ATTRIBUTES LocalAttributes
;
339 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
340 EFI_FFS_FILE_HEADER
*FfsHeader
;
343 if (NULL
== This
|| NULL
== NameGuid
) {
344 return EFI_INVALID_PARAMETER
;
347 FvDevice
= FV_DEVICE_FROM_THIS (This
);
349 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
350 if (EFI_ERROR (Status
)) {
354 // First check to see that FV is enabled for reads...
356 if (0 == (FvAttributes
& EFI_FV2_READ_STATUS
)) {
357 return EFI_ACCESS_DENIED
;
363 // Check if the file was read last time.
365 FfsFileEntry
= FvDevice
->CurrentFfsFile
;
367 if (FfsFileEntry
!= NULL
) {
368 FfsHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
371 if ((FfsFileEntry
== NULL
) || (!CompareGuid (&FfsHeader
->Name
, NameGuid
))) {
373 // If not match or no file cached, search this file
378 Status
= This
->GetNextFile (
386 if (EFI_ERROR (Status
)) {
387 return EFI_NOT_FOUND
;
389 } while (!CompareGuid (&SearchNameGuid
, NameGuid
));
394 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Key
;
399 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
401 FfsHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
405 // Get File Size of the cached file
407 if (IS_FFS_FILE2 (FfsHeader
)) {
408 FileSize
= FFS_FILE2_SIZE (FfsHeader
) - sizeof (EFI_FFS_FILE_HEADER2
);
410 FileSize
= FFS_FILE_SIZE (FfsHeader
) - sizeof (EFI_FFS_FILE_HEADER
);
416 *FoundType
= FfsHeader
->Type
;
417 *FileAttributes
= FfsAttributes2FvFileAttributes (FfsHeader
->Attributes
);
418 if ((FvDevice
->FwVolHeader
->Attributes
& EFI_FVB2_MEMORY_MAPPED
) == EFI_FVB2_MEMORY_MAPPED
) {
419 *FileAttributes
|= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED
;
422 // Inherit the authentication status.
424 *AuthenticationStatus
= FvDevice
->AuthenticationStatus
;
427 // If Buffer is NULL, we only want to get some information
429 if (Buffer
== NULL
) {
430 *BufferSize
= FileSize
;
434 if (IS_FFS_FILE2 (FfsHeader
)) {
435 SrcPtr
= ((UINT8
*) FfsHeader
) + sizeof (EFI_FFS_FILE_HEADER2
);
437 SrcPtr
= ((UINT8
*) FfsHeader
) + sizeof (EFI_FFS_FILE_HEADER
);
440 if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid
, NameGuid
)) {
442 // specially deal with VTF file
446 while (FileSize
>= 4) {
447 Tmp
= *(UINT32
*) SrcPtr
;
457 // If we drop out of the above loop, we've found the correct file header...
459 if (*Buffer
== NULL
) {
460 FileBuffer
= AllocateCopyPool (FileSize
, SrcPtr
);
461 if (FileBuffer
== NULL
) {
462 return EFI_OUT_OF_RESOURCES
;
465 *BufferSize
= FileSize
;
466 *Buffer
= FileBuffer
;
471 // If the user's buffer is smaller than the file size, then copy as much
472 // as we can and return an appropriate status.
474 if (FileSize
> *BufferSize
) {
475 CopyMem (*Buffer
, SrcPtr
, *BufferSize
);
476 *BufferSize
= FileSize
;
477 return EFI_WARN_BUFFER_TOO_SMALL
;
480 // User's buffer size is ok, so copy the entire file to their buffer.
482 *BufferSize
= FileSize
;
483 CopyMem (*Buffer
, SrcPtr
, *BufferSize
);
489 Locates a section in a given FFS File and
490 copies it to the supplied buffer (not including section header).
492 @param This Indicates the calling context.
493 @param NameGuid Pointer to an EFI_GUID, which is the
495 @param SectionType Indicates the section type to return.
496 @param SectionInstance Indicates which instance of sections with a
497 type of SectionType to return.
498 @param Buffer Buffer is a pointer to pointer to a buffer
499 in which the file or section contents or are
501 @param BufferSize BufferSize is a pointer to caller allocated
503 @param AuthenticationStatus AuthenticationStatus is a pointer to a
504 caller allocated UINT32 in which the
505 authentication status is returned.
507 @retval EFI_SUCCESS Successfully read the file section into
509 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
510 @retval EFI_NOT_FOUND Section not found.
511 @retval EFI_DEVICE_ERROR Device error.
512 @retval EFI_ACCESS_DENIED Could not read.
513 @retval EFI_INVALID_PARAMETER Invalid parameter.
519 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
520 IN CONST EFI_GUID
*NameGuid
,
521 IN EFI_SECTION_TYPE SectionType
,
522 IN UINTN SectionInstance
,
523 IN OUT VOID
**Buffer
,
524 IN OUT UINTN
*BufferSize
,
525 OUT UINT32
*AuthenticationStatus
530 EFI_FV_ATTRIBUTES FvAttributes
;
531 EFI_FV_FILETYPE FileType
;
532 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
535 EFI_SECTION_EXTRACTION_PROTOCOL
*Sep
;
538 if (NULL
== This
|| NULL
== NameGuid
|| Buffer
== NULL
) {
539 return EFI_INVALID_PARAMETER
;
542 FvDevice
= FV_DEVICE_FROM_THIS (This
);
544 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
545 if (EFI_ERROR (Status
)) {
549 // First check to see that FV is enabled for reads...
551 if (0 == (FvAttributes
& EFI_FV2_READ_STATUS
)) {
552 return EFI_ACCESS_DENIED
;
555 // Read the whole file into buffer
558 Status
= This
->ReadFile (
561 (VOID
**) &FileBuffer
,
568 if (EFI_ERROR (Status
)) {
572 // Check to see that the file actually HAS sections before we go any further.
574 if (FileType
== EFI_FV_FILETYPE_RAW
) {
575 FreePool (FileBuffer
);
576 return EFI_NOT_FOUND
;
579 // Located the protocol
581 Status
= gBS
->LocateProtocol (
582 &gEfiSectionExtractionProtocolGuid
,
586 if (EFI_ERROR (Status
)) {
587 FreePool (FileBuffer
);
591 Status
= Sep
->OpenSectionStream (
598 if (EFI_ERROR (Status
)) {
599 FreePool (FileBuffer
);
603 if (SectionType
== 0) {
605 // We need the whole section stream
607 Status
= Sep
->GetSection (
618 Status
= Sep
->GetSection (
630 if (!EFI_ERROR (Status
)) {
632 // Inherit the authentication status.
634 *AuthenticationStatus
|= FvDevice
->AuthenticationStatus
;
638 // Handle AuthenticationStatus if necessary
640 Sep
->CloseSectionStream (Sep
, StreamHandle
);
642 FreePool (FileBuffer
);