2 Implements functions to read firmware file.
4 Copyright (c) 2006 - 2010, 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"
19 UINT8 mFvAttributes
[] = { 0, 4, 7, 9, 10, 12, 15, 16 };
22 Convert the FFS File Attributes to FV File Attributes.
24 @param FfsAttributes The attributes of UINT8 type.
26 @return The attributes of EFI_FV_FILE_ATTRIBUTES
29 EFI_FV_FILE_ATTRIBUTES
30 FfsAttributes2FvFileAttributes (
31 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
34 FfsAttributes
= (EFI_FFS_FILE_ATTRIBUTES
) ((FfsAttributes
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3);
35 ASSERT (FfsAttributes
< 8);
36 return (EFI_FV_FILE_ATTRIBUTES
) mFvAttributes
[FfsAttributes
];
40 Given the input key, search for the next matching file in the volume.
42 @param This Indicates the calling context.
43 @param Key Key is a pointer to a caller allocated
44 buffer that contains implementation specific
45 data that is used to track where to begin
46 the search for the next file. The size of
47 the buffer must be at least This->KeySize
48 bytes long. To reinitialize the search and
49 begin from the beginning of the firmware
50 volume, the entire buffer must be cleared to
51 zero. Other than clearing the buffer to
52 initiate a new search, the caller must not
53 modify the data in the buffer between calls
55 @param FileType FileType is a pointer to a caller allocated
56 EFI_FV_FILETYPE. The GetNextFile() API can
57 filter it's search for files based on the
58 value of *FileType input. A *FileType input
59 of 0 causes GetNextFile() to search for
60 files of all types. If a file is found, the
61 file's type is returned in *FileType.
62 *FileType is not modified if no file is
64 @param NameGuid NameGuid is a pointer to a caller allocated
65 EFI_GUID. If a file is found, the file's
66 name is returned in *NameGuid. *NameGuid is
67 not modified if no file is found.
68 @param Attributes Attributes is a pointer to a caller
69 allocated EFI_FV_FILE_ATTRIBUTES. If a file
70 is found, the file's attributes are returned
71 in *Attributes. *Attributes is not modified
73 @param Size Size is a pointer to a caller allocated
74 UINTN. If a file is found, the file's size
75 is returned in *Size. *Size is not modified
78 @retval EFI_SUCCESS Successfully find the file.
79 @retval EFI_DEVICE_ERROR Device error.
80 @retval EFI_ACCESS_DENIED Fv could not read.
81 @retval EFI_NOT_FOUND No matching file found.
82 @retval EFI_INVALID_PARAMETER Invalid parameter
88 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
90 IN OUT EFI_FV_FILETYPE
*FileType
,
91 OUT EFI_GUID
*NameGuid
,
92 OUT EFI_FV_FILE_ATTRIBUTES
*Attributes
,
98 EFI_FV_ATTRIBUTES FvAttributes
;
99 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
102 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
105 FvDevice
= FV_DEVICE_FROM_THIS (This
);
107 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
108 if (EFI_ERROR (Status
)) {
112 KeyValue
= (UINTN
*) Key
;
113 FfsFileHeader
= NULL
;
116 // Check if read operation is enabled
118 if ((FvAttributes
& EFI_FV2_READ_STATUS
) == 0) {
119 return EFI_ACCESS_DENIED
;
122 if (*FileType
> EFI_FV_FILETYPE_SMM_CORE
) {
124 // File type needs to be in 0 - 0x0D
126 return EFI_NOT_FOUND
;
130 if (*KeyValue
== 0) {
132 // Search for 1st matching file
134 Link
= &FvDevice
->FfsFileListHeader
;
135 if (Link
->ForwardLink
== &FvDevice
->FfsFileListHeader
) {
136 return EFI_NOT_FOUND
;
139 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Link
->ForwardLink
;
140 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
145 *KeyValue
= (UINTN
) FfsFileEntry
;
148 // we ignore pad files
150 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
154 if (*FileType
== 0) {
158 if (*FileType
== FfsFileHeader
->Type
) {
164 // Getting link from last Ffs
166 Link
= (LIST_ENTRY
*) (*KeyValue
);
167 if (Link
->ForwardLink
== &FvDevice
->FfsFileListHeader
) {
168 return EFI_NOT_FOUND
;
171 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Link
->ForwardLink
;
172 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
177 *KeyValue
= (UINTN
) FfsFileEntry
;
180 // we ignore pad files
182 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
186 if (*FileType
== EFI_FV_FILETYPE_ALL
) {
190 if (*FileType
== FfsFileHeader
->Type
) {
194 } while (Link
->ForwardLink
!= &FvDevice
->FfsFileListHeader
);
197 // Cache this file entry
199 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
201 *FileType
= FfsFileHeader
->Type
;
202 CopyGuid (NameGuid
, &FfsFileHeader
->Name
);
203 *Attributes
= FfsAttributes2FvFileAttributes (FfsFileHeader
->Attributes
);
205 FileLength
= *(UINT32
*) FfsFileHeader
->Size
& 0x00FFFFFF;
208 // we need to substract the header size
210 *Size
= FileLength
- sizeof (EFI_FFS_FILE_HEADER
);
212 if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid
, NameGuid
)) {
214 // specially deal with VTF file
219 SrcPtr
= (UINT8
*) FfsFileHeader
;
220 SrcPtr
+= sizeof (EFI_FFS_FILE_HEADER
);
223 Tmp
= *(UINT32
*) SrcPtr
;
237 Locates a file in the firmware volume and
238 copies it to the supplied buffer.
240 @param This Indicates the calling context.
241 @param NameGuid Pointer to an EFI_GUID, which is the
243 @param Buffer Buffer is a pointer to pointer to a buffer
244 in which the file or section contents or are
246 @param BufferSize BufferSize is a pointer to caller allocated
247 UINTN. On input *BufferSize indicates the
248 size in bytes of the memory region pointed
249 to by Buffer. On output, *BufferSize
250 contains the number of bytes required to
252 @param FoundType FoundType is a pointer to a caller allocated
253 EFI_FV_FILETYPE that on successful return
254 from Read() contains the type of file read.
255 This output reflects the file type
256 irrespective of the value of the SectionType
258 @param FileAttributes FileAttributes is a pointer to a caller
259 allocated EFI_FV_FILE_ATTRIBUTES. On
260 successful return from Read(),
261 *FileAttributes contains the attributes of
263 @param AuthenticationStatus AuthenticationStatus is a pointer to a
264 caller allocated UINTN in which the
265 authentication status is returned.
267 @retval EFI_SUCCESS Successfully read to memory buffer.
268 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
269 @retval EFI_NOT_FOUND Not found.
270 @retval EFI_DEVICE_ERROR Device error.
271 @retval EFI_ACCESS_DENIED Could not read.
272 @retval EFI_INVALID_PARAMETER Invalid parameter.
273 @retval EFI_OUT_OF_RESOURCES Not enough buffer to be allocated.
279 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
280 IN CONST EFI_GUID
*NameGuid
,
281 IN OUT VOID
**Buffer
,
282 IN OUT UINTN
*BufferSize
,
283 OUT EFI_FV_FILETYPE
*FoundType
,
284 OUT EFI_FV_FILE_ATTRIBUTES
*FileAttributes
,
285 OUT UINT32
*AuthenticationStatus
291 EFI_GUID SearchNameGuid
;
292 EFI_FV_ATTRIBUTES FvAttributes
;
293 EFI_FV_FILETYPE LocalFoundType
;
294 EFI_FV_FILE_ATTRIBUTES LocalAttributes
;
297 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
298 EFI_FFS_FILE_HEADER
*FfsHeader
;
301 if (NULL
== This
|| NULL
== NameGuid
) {
302 return EFI_INVALID_PARAMETER
;
305 FvDevice
= FV_DEVICE_FROM_THIS (This
);
307 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
308 if (EFI_ERROR (Status
)) {
312 // First check to see that FV is enabled for reads...
314 if (0 == (FvAttributes
& EFI_FV2_READ_STATUS
)) {
315 return EFI_ACCESS_DENIED
;
321 // Check if the file was read last time.
323 FfsFileEntry
= FvDevice
->CurrentFfsFile
;
325 if (FfsFileEntry
!= NULL
) {
326 FfsHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
329 if ((FfsFileEntry
== NULL
) || (!CompareGuid (&FfsHeader
->Name
, NameGuid
))) {
331 // If not match or no file cached, search this file
336 Status
= This
->GetNextFile (
344 if (EFI_ERROR (Status
)) {
345 return EFI_NOT_FOUND
;
347 } while (!CompareGuid (&SearchNameGuid
, NameGuid
));
352 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*) Key
;
357 FvDevice
->CurrentFfsFile
= FfsFileEntry
;
359 FfsHeader
= (EFI_FFS_FILE_HEADER
*) FfsFileEntry
->FfsHeader
;
363 // Get File Size of the cached file
365 FileSize
= *(UINT32
*) FfsHeader
->Size
& 0x00FFFFFF;
366 FileSize
-= sizeof (EFI_FFS_FILE_HEADER
);
371 *FoundType
= FfsHeader
->Type
;
372 *FileAttributes
= FfsAttributes2FvFileAttributes (FfsHeader
->Attributes
);
373 *AuthenticationStatus
= 0;
376 // If Buffer is NULL, we only want to get some information
378 if (Buffer
== NULL
) {
379 *BufferSize
= FileSize
;
383 SrcPtr
= (UINT8
*) FfsHeader
;
384 SrcPtr
+= sizeof (EFI_FFS_FILE_HEADER
);
386 if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid
, NameGuid
)) {
388 // specially deal with VTF file
392 while (FileSize
>= 4) {
393 Tmp
= *(UINT32
*) SrcPtr
;
403 // If we drop out of the above loop, we've found the correct file header...
405 if (*Buffer
== NULL
) {
406 FileBuffer
= AllocateCopyPool (FileSize
, SrcPtr
);
407 if (FileBuffer
== NULL
) {
408 return EFI_OUT_OF_RESOURCES
;
411 *BufferSize
= FileSize
;
412 *Buffer
= FileBuffer
;
417 // If the user's buffer is smaller than the file size, then copy as much
418 // as we can and return an appropriate status.
420 if (FileSize
> *BufferSize
) {
421 CopyMem (*Buffer
, SrcPtr
, *BufferSize
);
422 *BufferSize
= FileSize
;
423 return EFI_WARN_BUFFER_TOO_SMALL
;
426 // User's buffer size is ok, so copy the entire file to their buffer.
428 *BufferSize
= FileSize
;
429 CopyMem (*Buffer
, SrcPtr
, *BufferSize
);
435 Locates a section in a given FFS File and
436 copies it to the supplied buffer (not including section header).
438 @param This Indicates the calling context.
439 @param NameGuid Pointer to an EFI_GUID, which is the
441 @param SectionType Indicates the section type to return.
442 @param SectionInstance Indicates which instance of sections with a
443 type of SectionType to return.
444 @param Buffer Buffer is a pointer to pointer to a buffer
445 in which the file or section contents or are
447 @param BufferSize BufferSize is a pointer to caller allocated
449 @param AuthenticationStatus AuthenticationStatus is a pointer to a
450 caller allocated UINT32 in which the
451 authentication status is returned.
453 @retval EFI_SUCCESS Successfully read the file section into
455 @retval EFI_WARN_BUFFER_TOO_SMALL Buffer too small.
456 @retval EFI_NOT_FOUND Section not found.
457 @retval EFI_DEVICE_ERROR Device error.
458 @retval EFI_ACCESS_DENIED Could not read.
459 @retval EFI_INVALID_PARAMETER Invalid parameter.
465 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
466 IN CONST EFI_GUID
*NameGuid
,
467 IN EFI_SECTION_TYPE SectionType
,
468 IN UINTN SectionInstance
,
469 IN OUT VOID
**Buffer
,
470 IN OUT UINTN
*BufferSize
,
471 OUT UINT32
*AuthenticationStatus
475 EFI_FV_ATTRIBUTES FvAttributes
;
476 EFI_FV_FILETYPE FileType
;
477 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
480 EFI_SECTION_EXTRACTION_PROTOCOL
*Sep
;
483 if (NULL
== This
|| NULL
== NameGuid
|| Buffer
== NULL
) {
484 return EFI_INVALID_PARAMETER
;
487 Status
= This
->GetVolumeAttributes (This
, &FvAttributes
);
488 if (EFI_ERROR (Status
)) {
492 // First check to see that FV is enabled for reads...
494 if (0 == (FvAttributes
& EFI_FV2_READ_STATUS
)) {
495 return EFI_ACCESS_DENIED
;
498 // Read the whole file into buffer
501 Status
= This
->ReadFile (
504 (VOID
**) &FileBuffer
,
511 if (EFI_ERROR (Status
)) {
515 // Check to see that the file actually HAS sections before we go any further.
517 if (FileType
== EFI_FV_FILETYPE_RAW
) {
518 FreePool (FileBuffer
);
519 return EFI_NOT_FOUND
;
522 // Located the protocol
524 Status
= gBS
->LocateProtocol (
525 &gEfiSectionExtractionProtocolGuid
,
529 if (EFI_ERROR (Status
)) {
530 FreePool (FileBuffer
);
534 Status
= Sep
->OpenSectionStream (
541 if (EFI_ERROR (Status
)) {
542 FreePool (FileBuffer
);
546 if (SectionType
== 0) {
548 // We need the whole section stream
550 Status
= Sep
->GetSection (
561 Status
= Sep
->GetSection (
573 // Handle AuthenticationStatus if necessary
575 Sep
->CloseSectionStream (Sep
, StreamHandle
);
577 FreePool (FileBuffer
);