3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. 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
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.
18 Implements read firmware file
26 Required Alignment Alignment Value in FFS Alignment Value in
27 (bytes) Attributes Field Firmware Volume Interfaces
42 UINT8 mFvAttributes
[] = {0, 4, 7, 9, 10, 12, 15, 16};
46 EFI_FV_FILE_ATTRIBUTES
47 FfsAttributes2FvFileAttributes (
48 IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
53 Convert the FFS File Attributes to FV File Attributes
56 FfsAttributes - The attributes of UINT8 type.
59 The attributes of EFI_FV_FILE_ATTRIBUTES
63 FfsAttributes
= (EFI_FFS_FILE_ATTRIBUTES
)((FfsAttributes
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3);
64 ASSERT (FfsAttributes
< 8);
66 return (EFI_FV_FILE_ATTRIBUTES
) mFvAttributes
[FfsAttributes
];
73 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
75 IN OUT EFI_FV_FILETYPE
*FileType
,
76 OUT EFI_GUID
*NameGuid
,
77 OUT EFI_FV_FILE_ATTRIBUTES
*Attributes
,
83 Given the input key, search for the next matching file in the volume.
86 This - Indicates the calling context.
87 FileType - FileType is a pointer to a caller allocated
88 EFI_FV_FILETYPE. The GetNextFile() API can filter it's
89 search for files based on the value of *FileType input.
90 A *FileType input of 0 causes GetNextFile() to search for
91 files of all types. If a file is found, the file's type
92 is returned in *FileType. *FileType is not modified if
94 Key - Key is a pointer to a caller allocated buffer that
95 contains implementation specific data that is used to
96 track where to begin the search for the next file.
97 The size of the buffer must be at least This->KeySize
98 bytes long. To reinitialize the search and begin from
99 the beginning of the firmware volume, the entire buffer
100 must be cleared to zero. Other than clearing the buffer
101 to initiate a new search, the caller must not modify the
102 data in the buffer between calls to GetNextFile().
103 NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID.
104 If a file is found, the file's name is returned in
105 *NameGuid. *NameGuid is not modified if no file is
107 Attributes - Attributes is a pointer to a caller allocated
108 EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's
109 attributes are returned in *Attributes. *Attributes is
110 not modified if no file is found.
111 Size - Size is a pointer to a caller allocated UINTN.
112 If a file is found, the file's size is returned in *Size.
113 *Size is not modified if no file is found.
116 EFI_SUCCESS - Successfully find the file.
117 EFI_DEVICE_ERROR - Device error.
118 EFI_ACCESS_DENIED - Fv could not read.
119 EFI_NOT_FOUND - No matching file found.
120 EFI_INVALID_PARAMETER - Invalid parameter
126 EFI_FV_ATTRIBUTES FvAttributes
;
127 EFI_FFS_FILE_HEADER
*FfsFileHeader
;
130 FFS_FILE_LIST_ENTRY
*FfsFileEntry
;
133 FvDevice
= FV_DEVICE_FROM_THIS (This
);
135 Status
= FvGetVolumeAttributes (This
, &FvAttributes
);
136 if (EFI_ERROR (Status
)){
141 // Check if read operation is enabled
143 if ((FvAttributes
& EFI_FV2_READ_STATUS
) == 0) {
144 return EFI_ACCESS_DENIED
;
147 if (*FileType
> EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
) {
149 // File type needs to be in 0 - 0x0B
151 return EFI_INVALID_PARAMETER
;
154 KeyValue
= (UINTN
*)Key
;
156 if (*KeyValue
== 0) {
158 // Search for 1st matching file
160 Link
= &FvDevice
->FfsFileListHeader
;
163 // Key is pointer to FFsFileEntry, so get next one
165 Link
= (LIST_ENTRY
*)(*KeyValue
);
168 if (Link
->ForwardLink
== &FvDevice
->FfsFileListHeader
) {
170 // Next is end of list so we did not find data
172 return EFI_NOT_FOUND
;
175 FfsFileEntry
= (FFS_FILE_LIST_ENTRY
*)Link
->ForwardLink
;
176 FfsFileHeader
= (EFI_FFS_FILE_HEADER
*)FfsFileEntry
->FfsHeader
;
181 *KeyValue
= (UINTN
)FfsFileEntry
;
183 if (FfsFileHeader
->Type
== EFI_FV_FILETYPE_FFS_PAD
) {
185 // we ignore pad files
190 if (*FileType
== 0) {
192 // Process all file types so we have a match
197 if (*FileType
== FfsFileHeader
->Type
) {
199 // Found a matching file type
207 // Return FileType, NameGuid, and Attributes
209 *FileType
= FfsFileHeader
->Type
;
210 CopyMem (NameGuid
, &FfsFileHeader
->Name
, sizeof (EFI_GUID
));
211 *Attributes
= FfsAttributes2FvFileAttributes (FfsFileHeader
->Attributes
);
214 // Read four bytes out of the 3 byte array and throw out extra data
216 FileLength
= *(UINT32
*)&FfsFileHeader
->Size
[0] & 0x00FFFFFF;
219 // we need to substract the header size
221 *Size
= FileLength
- sizeof(EFI_FFS_FILE_HEADER
);
230 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
231 IN CONST EFI_GUID
*NameGuid
,
232 IN OUT VOID
**Buffer
,
233 IN OUT UINTN
*BufferSize
,
234 OUT EFI_FV_FILETYPE
*FoundType
,
235 OUT EFI_FV_FILE_ATTRIBUTES
*FileAttributes
,
236 OUT UINT32
*AuthenticationStatus
241 Locates a file in the firmware volume and
242 copies it to the supplied buffer.
245 This - Indicates the calling context.
246 NameGuid - Pointer to an EFI_GUID, which is the filename.
247 Buffer - Buffer is a pointer to pointer to a buffer in
248 which the file or section contents or are returned.
249 BufferSize - BufferSize is a pointer to caller allocated
250 UINTN. On input *BufferSize indicates the size
251 in bytes of the memory region pointed to by
252 Buffer. On output, *BufferSize contains the number
253 of bytes required to read the file.
254 FoundType - FoundType is a pointer to a caller allocated
255 EFI_FV_FILETYPE that on successful return from Read()
256 contains the type of file read. This output reflects
257 the file type irrespective of the value of the
259 FileAttributes - FileAttributes is a pointer to a caller allocated
260 EFI_FV_FILE_ATTRIBUTES. On successful return from
261 Read(), *FileAttributes contains the attributes of
263 AuthenticationStatus - AuthenticationStatus is a pointer to a caller
264 allocated UINTN in which the authentication status
267 EFI_SUCCESS - Successfully read to memory buffer.
268 EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
269 EFI_NOT_FOUND - Not found.
270 EFI_DEVICE_ERROR - Device error.
271 EFI_ACCESS_DENIED - Could not read.
272 EFI_INVALID_PARAMETER - Invalid parameter.
273 EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated.
279 EFI_GUID SearchNameGuid
;
280 EFI_FV_FILETYPE LocalFoundType
;
281 EFI_FV_FILE_ATTRIBUTES LocalAttributes
;
284 EFI_FFS_FILE_HEADER
*FfsHeader
;
285 UINTN InputBufferSize
;
287 if (NULL
== NameGuid
) {
288 return EFI_INVALID_PARAMETER
;
291 FvDevice
= FV_DEVICE_FROM_THIS (This
);
295 // Keep looking until we find the matching NameGuid.
296 // The Key is really an FfsFileEntry
298 FvDevice
->LastKey
= 0;
301 Status
= FvGetNextFile (
309 if (EFI_ERROR (Status
)) {
310 return EFI_NOT_FOUND
;
312 } while (!CompareGuid (&SearchNameGuid
, NameGuid
));
315 // Get a pointer to the header
317 FfsHeader
= FvDevice
->LastKey
->FfsHeader
;
320 // Remember callers buffer size
322 InputBufferSize
= *BufferSize
;
325 // Calculate return values
327 *FoundType
= FfsHeader
->Type
;
328 *FileAttributes
= FfsAttributes2FvFileAttributes (FfsHeader
->Attributes
);
329 *AuthenticationStatus
= 0;
330 *BufferSize
= FileSize
;
332 if (Buffer
== NULL
) {
334 // If Buffer is NULL, we only want to get the information colected so far
340 // Skip over file header
342 SrcPtr
= ((UINT8
*)FfsHeader
) + sizeof (EFI_FFS_FILE_HEADER
);
344 Status
= EFI_SUCCESS
;
345 if (*Buffer
== NULL
) {
347 // Caller passed in a pointer so allocate buffer for them
349 *Buffer
= CoreAllocateBootServicesPool (FileSize
);
350 if (*Buffer
== NULL
) {
351 return EFI_OUT_OF_RESOURCES
;
353 } else if (FileSize
> InputBufferSize
) {
355 // Callers buffer was not big enough
357 Status
= EFI_WARN_BUFFER_TOO_SMALL
;
358 FileSize
= InputBufferSize
;
362 // Copy data into callers buffer
364 CopyMem (*Buffer
, SrcPtr
, FileSize
);
373 IN CONST EFI_FIRMWARE_VOLUME2_PROTOCOL
*This
,
374 IN CONST EFI_GUID
*NameGuid
,
375 IN EFI_SECTION_TYPE SectionType
,
376 IN UINTN SectionInstance
,
377 IN OUT VOID
**Buffer
,
378 IN OUT UINTN
*BufferSize
,
379 OUT UINT32
*AuthenticationStatus
384 Locates a section in a given FFS File and
385 copies it to the supplied buffer (not including section header).
388 This - Indicates the calling context.
389 NameGuid - Pointer to an EFI_GUID, which is the filename.
390 SectionType - Indicates the section type to return.
391 SectionInstance - Indicates which instance of sections with a type of
392 SectionType to return.
393 Buffer - Buffer is a pointer to pointer to a buffer in which
394 the file or section contents or are returned.
395 BufferSize - BufferSize is a pointer to caller allocated UINTN.
396 AuthenticationStatus -AuthenticationStatus is a pointer to a caller
397 allocated UINT32 in which the authentication status
401 EFI_SUCCESS - Successfully read the file section into buffer.
402 EFI_WARN_BUFFER_TOO_SMALL - Buffer too small.
403 EFI_NOT_FOUND - Section not found.
404 EFI_DEVICE_ERROR - Device error.
405 EFI_ACCESS_DENIED - Could not read.
406 EFI_INVALID_PARAMETER - Invalid parameter.
412 EFI_FV_FILETYPE FileType
;
413 EFI_FV_FILE_ATTRIBUTES FileAttributes
;
416 EFI_SECTION_EXTRACTION_PROTOCOL
*Sep
;
417 FFS_FILE_LIST_ENTRY
*FfsEntry
;
419 if (NULL
== NameGuid
|| Buffer
== NULL
) {
420 return EFI_INVALID_PARAMETER
;
423 FvDevice
= FV_DEVICE_FROM_THIS (This
);
426 // Read the whole file into buffer
429 Status
= FvReadFile (
432 (VOID
**)&FileBuffer
,
439 // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file.
441 FfsEntry
= (FFS_FILE_LIST_ENTRY
*)FvDevice
->LastKey
;
443 if (EFI_ERROR (Status
)) {
448 // Check to see that the file actually HAS sections before we go any further.
450 if (FileType
== EFI_FV_FILETYPE_RAW
) {
451 Status
= EFI_NOT_FOUND
;
456 // Use FfsEntry to cache Section Extraction Protocol Inforomation
458 if (FfsEntry
->StreamHandle
== 0) {
460 // Located the protocol
462 Status
= CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid
, NULL
, (VOID
**)&Sep
);
464 // Section Extraction Protocol is part of Dxe Core so this should never fail
466 ASSERT_EFI_ERROR (Status
);
468 Status
= Sep
->OpenSectionStream (
472 &FfsEntry
->StreamHandle
474 if (EFI_ERROR (Status
)) {
481 // Get cached copy of Sep
487 // If SectionType == 0 We need the whole section stream
489 Status
= Sep
->GetSection (
491 FfsEntry
->StreamHandle
,
492 (SectionType
== 0) ? NULL
: &SectionType
,
494 (SectionType
== 0) ? 0 : SectionInstance
,
501 // Close of stream defered to close of FfsHeader list to allow SEP to cache data
505 CoreFreePool (FileBuffer
);