Inherit the authentication status from FV. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Chao Zhang <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed by: Chao Zhang <chao.b.zhang@intel.com>
		
			
				
	
	
		
			633 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			633 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implements functions to read firmware file.
 | |
| 
 | |
|   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions
 | |
|   of the BSD License which accompanies this distribution.  The
 | |
|   full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "FwVolDriver.h"
 | |
| 
 | |
| /**
 | |
| Required Alignment             Alignment Value in FFS         Alignment Value in
 | |
| (bytes)                        Attributes Field               Firmware Volume Interfaces
 | |
| 1                                    0                                     0
 | |
| 16                                   1                                     4
 | |
| 128                                  2                                     7
 | |
| 512                                  3                                     9
 | |
| 1 KB                                 4                                     10
 | |
| 4 KB                                 5                                     12
 | |
| 32 KB                                6                                     15
 | |
| 64 KB                                7                                     16
 | |
| **/
 | |
| UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16};
 | |
| 
 | |
| /**
 | |
|   Convert the FFS File Attributes to FV File Attributes.
 | |
| 
 | |
|   @param  FfsAttributes              The attributes of UINT8 type.
 | |
| 
 | |
|   @return The attributes of EFI_FV_FILE_ATTRIBUTES
 | |
| 
 | |
| **/
 | |
| EFI_FV_FILE_ATTRIBUTES
 | |
| FfsAttributes2FvFileAttributes (
 | |
|   IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes
 | |
|   )
 | |
| {
 | |
|   UINT8                     DataAlignment;
 | |
|   EFI_FV_FILE_ATTRIBUTES    FileAttribute;
 | |
| 
 | |
|   DataAlignment = (UINT8) ((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
 | |
|   ASSERT (DataAlignment < 8);
 | |
| 
 | |
|   FileAttribute = (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[DataAlignment];
 | |
| 
 | |
|   if ((FfsAttributes & FFS_ATTRIB_FIXED) == FFS_ATTRIB_FIXED) {
 | |
|     FileAttribute |= EFI_FV_FILE_ATTRIB_FIXED;
 | |
|   }
 | |
| 
 | |
|   return FileAttribute;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Given the input key, search for the next matching file in the volume.
 | |
| 
 | |
|   @param  This                       Indicates the calling context.
 | |
|   @param  Key                        Key is a pointer to a caller allocated
 | |
|                                      buffer that contains implementation specific
 | |
|                                      data that is used to track where to begin
 | |
|                                      the search for the next file. The size of
 | |
|                                      the buffer must be at least This->KeySize
 | |
|                                      bytes long. To reinitialize the search and
 | |
|                                      begin from the beginning of the firmware
 | |
|                                      volume, the entire buffer must be cleared to
 | |
|                                      zero. Other than clearing the buffer to
 | |
|                                      initiate a new search, the caller must not
 | |
|                                      modify the data in the buffer between calls
 | |
|                                      to GetNextFile().
 | |
|   @param  FileType                   FileType is a pointer to a caller allocated
 | |
|                                      EFI_FV_FILETYPE. The GetNextFile() API can
 | |
|                                      filter it's search for files based on the
 | |
|                                      value of *FileType input. A *FileType input
 | |
|                                      of 0 causes GetNextFile() to search for
 | |
|                                      files of all types.  If a file is found, the
 | |
|                                      file's type is returned in *FileType.
 | |
|                                      *FileType is not modified if no file is
 | |
|                                      found.
 | |
|   @param  NameGuid                   NameGuid is a pointer to a caller allocated
 | |
|                                      EFI_GUID. If a file is found, the file's
 | |
|                                      name is returned in *NameGuid.  *NameGuid is
 | |
|                                      not modified if no file is found.
 | |
|   @param  Attributes                 Attributes is a pointer to a caller
 | |
|                                      allocated EFI_FV_FILE_ATTRIBUTES.  If a file
 | |
|                                      is found, the file's attributes are returned
 | |
|                                      in *Attributes. *Attributes is not modified
 | |
|                                      if no file is found.
 | |
|   @param  Size                       Size is a pointer to a caller allocated
 | |
|                                      UINTN. If a file is found, the file's size
 | |
|                                      is returned in *Size. *Size is not modified
 | |
|                                      if no file is found.
 | |
| 
 | |
|   @retval EFI_SUCCESS                Successfully find the file.
 | |
|   @retval EFI_DEVICE_ERROR           Device error.
 | |
|   @retval EFI_ACCESS_DENIED          Fv could not read.
 | |
|   @retval EFI_NOT_FOUND              No matching file found.
 | |
|   @retval EFI_INVALID_PARAMETER      Invalid parameter
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| 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
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS          Status;
 | |
|   FV_DEVICE           *FvDevice;
 | |
|   EFI_FV_ATTRIBUTES   FvAttributes;
 | |
|   EFI_FFS_FILE_HEADER *FfsFileHeader;
 | |
|   UINTN               *KeyValue;
 | |
|   LIST_ENTRY      *Link;
 | |
|   FFS_FILE_LIST_ENTRY *FfsFileEntry;
 | |
| 
 | |
|   FvDevice  = FV_DEVICE_FROM_THIS (This);
 | |
| 
 | |
|   Status    = This->GetVolumeAttributes (This, &FvAttributes);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   KeyValue      = (UINTN *) Key;
 | |
|   FfsFileHeader = NULL;
 | |
| 
 | |
|   //
 | |
|   // Check if read operation is enabled
 | |
|   //
 | |
|   if ((FvAttributes & EFI_FV2_READ_STATUS) == 0) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
 | |
|     //
 | |
|     // File type needs to be in 0 - 0x0D
 | |
|     //
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   do {
 | |
|     if (*KeyValue == 0) {
 | |
|       //
 | |
|       // Search for 1st matching file
 | |
|       //
 | |
|       Link = &FvDevice->FfsFileListHeader;
 | |
|       if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
| 
 | |
|       FfsFileEntry  = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink;
 | |
|       FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
 | |
| 
 | |
|       //
 | |
|       // remember the key
 | |
|       //
 | |
|       *KeyValue = (UINTN) FfsFileEntry;
 | |
| 
 | |
|       //
 | |
|       // we ignore pad files
 | |
|       //
 | |
|       if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (*FileType == 0) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (*FileType == FfsFileHeader->Type) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|     } else {
 | |
|       //
 | |
|       // Getting link from last Ffs
 | |
|       //
 | |
|       Link = (LIST_ENTRY *) (*KeyValue);
 | |
|       if (Link->ForwardLink == &FvDevice->FfsFileListHeader) {
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
| 
 | |
|       FfsFileEntry  = (FFS_FILE_LIST_ENTRY *) Link->ForwardLink;
 | |
|       FfsFileHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
 | |
| 
 | |
|       //
 | |
|       // remember the key
 | |
|       //
 | |
|       *KeyValue = (UINTN) FfsFileEntry;
 | |
| 
 | |
|       //
 | |
|       // we ignore pad files
 | |
|       //
 | |
|       if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       if (*FileType == EFI_FV_FILETYPE_ALL) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (*FileType == FfsFileHeader->Type) {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   } while (Link->ForwardLink != &FvDevice->FfsFileListHeader);
 | |
| 
 | |
|   //
 | |
|   // Cache this file entry
 | |
|   //
 | |
|   FvDevice->CurrentFfsFile  = FfsFileEntry;
 | |
| 
 | |
|   *FileType                 = FfsFileHeader->Type;
 | |
|   CopyGuid (NameGuid, &FfsFileHeader->Name);
 | |
|   *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes);
 | |
|    if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
 | |
|      *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
 | |
|    }
 | |
| 
 | |
|   //
 | |
|   // we need to substract the header size
 | |
|   //
 | |
|   if (IS_FFS_FILE2 (FfsFileHeader)) {
 | |
|     *Size = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
 | |
|   } else {
 | |
|     *Size = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) {
 | |
|     //
 | |
|     // specially deal with VTF file
 | |
|     //
 | |
|     UINT8   *SrcPtr;
 | |
|     UINT32  Tmp;
 | |
| 
 | |
|     if (IS_FFS_FILE2 (FfsFileHeader)) {
 | |
|       SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER2);
 | |
|     } else {
 | |
|       SrcPtr = ((UINT8 *) FfsFileHeader) + sizeof (EFI_FFS_FILE_HEADER);
 | |
|     }
 | |
| 
 | |
|     while (*Size >= 4) {
 | |
|       Tmp = *(UINT32 *) SrcPtr;
 | |
|       if (Tmp == 0) {
 | |
|         SrcPtr += 4;
 | |
|         (*Size) -= 4;
 | |
|       } else {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Locates a file in the firmware volume and
 | |
|   copies it to the supplied buffer.
 | |
| 
 | |
|   @param  This                       Indicates the calling context.
 | |
|   @param  NameGuid                   Pointer to an EFI_GUID, which is the
 | |
|                                      filename.
 | |
|   @param  Buffer                     Buffer is a pointer to pointer to a buffer
 | |
|                                      in which the file or section contents or are
 | |
|                                      returned.
 | |
|   @param  BufferSize                 BufferSize is a pointer to caller allocated
 | |
|                                      UINTN. On input *BufferSize indicates the
 | |
|                                      size in bytes of the memory region pointed
 | |
|                                      to by Buffer. On output, *BufferSize
 | |
|                                      contains the number of bytes required to
 | |
|                                      read the file.
 | |
|   @param  FoundType                  FoundType is a pointer to a caller allocated
 | |
|                                      EFI_FV_FILETYPE that on successful return
 | |
|                                      from Read() contains the type of file read.
 | |
|                                      This output reflects the file type
 | |
|                                      irrespective of the value of the SectionType
 | |
|                                      input.
 | |
|   @param  FileAttributes             FileAttributes is a pointer to a caller
 | |
|                                      allocated EFI_FV_FILE_ATTRIBUTES.  On
 | |
|                                      successful return from Read(),
 | |
|                                      *FileAttributes contains the attributes of
 | |
|                                      the file read.
 | |
|   @param  AuthenticationStatus       AuthenticationStatus is a pointer to a
 | |
|                                      caller allocated UINTN in which the
 | |
|                                      authentication status is returned.
 | |
| 
 | |
|   @retval EFI_SUCCESS                Successfully read to memory buffer.
 | |
|   @retval EFI_WARN_BUFFER_TOO_SMALL  Buffer too small.
 | |
|   @retval EFI_NOT_FOUND              Not found.
 | |
|   @retval EFI_DEVICE_ERROR           Device error.
 | |
|   @retval EFI_ACCESS_DENIED          Could not read.
 | |
|   @retval EFI_INVALID_PARAMETER      Invalid parameter.
 | |
|   @retval EFI_OUT_OF_RESOURCES       Not enough buffer to be allocated.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| 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
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS              Status;
 | |
|   FV_DEVICE               *FvDevice;
 | |
|   UINTN                   Key;
 | |
|   EFI_GUID                SearchNameGuid;
 | |
|   EFI_FV_ATTRIBUTES       FvAttributes;
 | |
|   EFI_FV_FILETYPE         LocalFoundType;
 | |
|   EFI_FV_FILE_ATTRIBUTES  LocalAttributes;
 | |
|   UINTN                   FileSize;
 | |
|   UINT8                   *SrcPtr;
 | |
|   FFS_FILE_LIST_ENTRY     *FfsFileEntry;
 | |
|   EFI_FFS_FILE_HEADER     *FfsHeader;
 | |
|   UINT8                   *FileBuffer;
 | |
| 
 | |
|   if (NULL == This || NULL == NameGuid) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FvDevice  = FV_DEVICE_FROM_THIS (This);
 | |
| 
 | |
|   Status    = This->GetVolumeAttributes (This, &FvAttributes);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // First check to see that FV is enabled for reads...
 | |
|   //
 | |
|   if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   FfsHeader = NULL;
 | |
| 
 | |
|   //
 | |
|   // Check if the file was read last time.
 | |
|   //
 | |
|   FfsFileEntry = FvDevice->CurrentFfsFile;
 | |
| 
 | |
|   if (FfsFileEntry != NULL) {
 | |
|     FfsHeader = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
 | |
|   }
 | |
| 
 | |
|   if ((FfsFileEntry == NULL) || (!CompareGuid (&FfsHeader->Name, NameGuid))) {
 | |
|     //
 | |
|     // If not match or no file cached, search this file
 | |
|     //
 | |
|     Key = 0;
 | |
|     do {
 | |
|       LocalFoundType = 0;
 | |
|       Status = This->GetNextFile (
 | |
|                       This,
 | |
|                       &Key,
 | |
|                       &LocalFoundType,
 | |
|                       &SearchNameGuid,
 | |
|                       &LocalAttributes,
 | |
|                       &FileSize
 | |
|                       );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         return EFI_NOT_FOUND;
 | |
|       }
 | |
|     } while (!CompareGuid (&SearchNameGuid, NameGuid));
 | |
| 
 | |
|     //
 | |
|     // Get file entry
 | |
|     //
 | |
|     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) Key;
 | |
| 
 | |
|     //
 | |
|     // Update the cache
 | |
|     //
 | |
|     FvDevice->CurrentFfsFile  = FfsFileEntry;
 | |
| 
 | |
|     FfsHeader                 = (EFI_FFS_FILE_HEADER *) FfsFileEntry->FfsHeader;
 | |
| 
 | |
|   } else {
 | |
|     //
 | |
|     // Get File Size of the cached file
 | |
|     //
 | |
|     if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|       FileSize = FFS_FILE2_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER2);
 | |
|     } else {
 | |
|       FileSize = FFS_FILE_SIZE (FfsHeader) - sizeof (EFI_FFS_FILE_HEADER);
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Get file info
 | |
|   //
 | |
|   *FoundType            = FfsHeader->Type;
 | |
|   *FileAttributes       = FfsAttributes2FvFileAttributes (FfsHeader->Attributes);
 | |
|    if ((FvDevice->FwVolHeader->Attributes & EFI_FVB2_MEMORY_MAPPED) == EFI_FVB2_MEMORY_MAPPED) {
 | |
|      *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
 | |
|    }
 | |
|   //
 | |
|   // Inherit the authentication status.
 | |
|   //
 | |
|   *AuthenticationStatus = FvDevice->AuthenticationStatus;
 | |
| 
 | |
|   //
 | |
|   // If Buffer is NULL, we only want to get some information
 | |
|   //
 | |
|   if (Buffer == NULL) {
 | |
|     *BufferSize = FileSize;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (IS_FFS_FILE2 (FfsHeader)) {
 | |
|     SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);
 | |
|   } else {
 | |
|     SrcPtr = ((UINT8 *) FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (&gEfiFirmwareVolumeTopFileGuid, NameGuid)) {
 | |
|     //
 | |
|     // specially deal with VTF file
 | |
|     //
 | |
|     UINT32  Tmp;
 | |
| 
 | |
|     while (FileSize >= 4) {
 | |
|       Tmp = *(UINT32 *) SrcPtr;
 | |
|       if (Tmp == 0) {
 | |
|         SrcPtr += 4;
 | |
|         FileSize -= 4;
 | |
|       } else {
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // If we drop out of the above loop, we've found the correct file header...
 | |
|   //
 | |
|   if (*Buffer == NULL) {
 | |
|     FileBuffer = AllocateCopyPool (FileSize, SrcPtr);
 | |
|     if (FileBuffer == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     *BufferSize = FileSize;
 | |
|     *Buffer     = FileBuffer;
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
|   //
 | |
|   // If the user's buffer is smaller than the file size, then copy as much
 | |
|   // as we can and return an appropriate status.
 | |
|   //
 | |
|   if (FileSize > *BufferSize) {
 | |
|     CopyMem (*Buffer, SrcPtr, *BufferSize);
 | |
|     *BufferSize = FileSize;
 | |
|     return EFI_WARN_BUFFER_TOO_SMALL;
 | |
|   }
 | |
|   //
 | |
|   // User's buffer size is ok, so copy the entire file to their buffer.
 | |
|   //
 | |
|   *BufferSize = FileSize;
 | |
|   CopyMem (*Buffer, SrcPtr, *BufferSize);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Locates a section in a given FFS File and
 | |
|   copies it to the supplied buffer (not including section header).
 | |
| 
 | |
|   @param  This                       Indicates the calling context.
 | |
|   @param  NameGuid                   Pointer to an EFI_GUID, which is the
 | |
|                                      filename.
 | |
|   @param  SectionType                Indicates the section type to return.
 | |
|   @param  SectionInstance            Indicates which instance of sections with a
 | |
|                                      type of SectionType to return.
 | |
|   @param  Buffer                     Buffer is a pointer to pointer to a buffer
 | |
|                                      in which the file or section contents or are
 | |
|                                      returned.
 | |
|   @param  BufferSize                 BufferSize is a pointer to caller allocated
 | |
|                                      UINTN.
 | |
|   @param  AuthenticationStatus       AuthenticationStatus is a pointer to a
 | |
|                                      caller allocated UINT32 in which the
 | |
|                                      authentication status is returned.
 | |
| 
 | |
|   @retval EFI_SUCCESS                Successfully read the file section into
 | |
|                                      buffer.
 | |
|   @retval EFI_WARN_BUFFER_TOO_SMALL  Buffer too small.
 | |
|   @retval EFI_NOT_FOUND              Section not found.
 | |
|   @retval EFI_DEVICE_ERROR           Device error.
 | |
|   @retval EFI_ACCESS_DENIED          Could not read.
 | |
|   @retval EFI_INVALID_PARAMETER      Invalid parameter.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| 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
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   FV_DEVICE                       *FvDevice;
 | |
|   EFI_FV_ATTRIBUTES               FvAttributes;
 | |
|   EFI_FV_FILETYPE                 FileType;
 | |
|   EFI_FV_FILE_ATTRIBUTES          FileAttributes;
 | |
|   UINTN                           FileSize;
 | |
|   UINT8                           *FileBuffer;
 | |
|   EFI_SECTION_EXTRACTION_PROTOCOL *Sep;
 | |
|   UINTN                           StreamHandle;
 | |
| 
 | |
|   if (NULL == This || NULL == NameGuid || Buffer == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FvDevice  = FV_DEVICE_FROM_THIS (This);
 | |
| 
 | |
|   Status    = This->GetVolumeAttributes (This, &FvAttributes);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // First check to see that FV is enabled for reads...
 | |
|   //
 | |
|   if (0 == (FvAttributes & EFI_FV2_READ_STATUS)) {
 | |
|     return EFI_ACCESS_DENIED;
 | |
|   }
 | |
|   //
 | |
|   // Read the whole file into buffer
 | |
|   //
 | |
|   FileBuffer = NULL;
 | |
|   Status = This->ReadFile (
 | |
|                   This,
 | |
|                   NameGuid,
 | |
|                   (VOID **) &FileBuffer,
 | |
|                   &FileSize,
 | |
|                   &FileType,
 | |
|                   &FileAttributes,
 | |
|                   AuthenticationStatus
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
|   //
 | |
|   // Check to see that the file actually HAS sections before we go any further.
 | |
|   //
 | |
|   if (FileType == EFI_FV_FILETYPE_RAW) {
 | |
|     FreePool (FileBuffer);
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
|   //
 | |
|   // Located the protocol
 | |
|   //
 | |
|   Status = gBS->LocateProtocol (
 | |
|                   &gEfiSectionExtractionProtocolGuid,
 | |
|                   NULL,
 | |
|                   (VOID **) &Sep
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (FileBuffer);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = Sep->OpenSectionStream (
 | |
|                   Sep,
 | |
|                   FileSize,
 | |
|                   FileBuffer,
 | |
|                   &StreamHandle
 | |
|                   );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (FileBuffer);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   if (SectionType == 0) {
 | |
|     //
 | |
|     // We need the whole section stream
 | |
|     //
 | |
|     Status = Sep->GetSection (
 | |
|                     Sep,
 | |
|                     StreamHandle,
 | |
|                     NULL,
 | |
|                     NULL,
 | |
|                     0,
 | |
|                     Buffer,
 | |
|                     BufferSize,
 | |
|                     AuthenticationStatus
 | |
|                     );
 | |
|   } else {
 | |
|     Status = Sep->GetSection (
 | |
|                     Sep,
 | |
|                     StreamHandle,
 | |
|                     &SectionType,
 | |
|                     NULL,
 | |
|                     SectionInstance,
 | |
|                     Buffer,
 | |
|                     BufferSize,
 | |
|                     AuthenticationStatus
 | |
|                     );
 | |
|   }
 | |
| 
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Inherit the authentication status.
 | |
|     //
 | |
|     *AuthenticationStatus |= FvDevice->AuthenticationStatus;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Handle AuthenticationStatus if necessary
 | |
|   //
 | |
|   Sep->CloseSectionStream (Sep, StreamHandle);
 | |
| 
 | |
|   FreePool (FileBuffer);
 | |
| 
 | |
|   return Status;
 | |
| }
 |