mirror of
				https://github.com/acidanthera/audk.git
				synced 2025-10-30 02:33:44 +01:00 
			
		
		
		
	The original code will assert when dealing with those empty FVs. The fix is used to solve this bug. Cc: Chao Zhang <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Chao Zhang <chao.b.zhang@intel.com>
		
			
				
	
	
		
			1033 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1033 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This driver uses the EFI_FIRMWARE_VOLUME2_PROTOCOL to expose files in firmware
 | |
|   volumes via the the EFI_SIMPLE_FILESYSTEM_PROTOCOL and EFI_FILE_PROTOCOL.
 | |
| 
 | |
|   It will expose a single directory, containing one file for each file in the firmware
 | |
|   volume. If a file has a UI section, its contents will be used as a filename.
 | |
|   Otherwise, a string representation of the GUID will be used.
 | |
|   Files of an executable type (That is PEIM, DRIVER, COMBINED_PEIM_DRIVER and APPLICATION)
 | |
|   will have ".efi" added to their filename.
 | |
| 
 | |
|   Its primary intended use is to be able to start EFI applications embedded in FVs
 | |
|   from the UEFI shell. It is entirely read-only.
 | |
| 
 | |
| Copyright (c) 2014, ARM Limited. All rights reserved.
 | |
| Copyright (c) 2014 - 2015, 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 "FvSimpleFileSystemInternal.h"
 | |
| 
 | |
| //
 | |
| // Template for EFI_FILE_SYSTEM_INFO data structure.
 | |
| //
 | |
| EFI_FILE_SYSTEM_INFO mFsInfoTemplate = {
 | |
|   0,    // Populate at runtime
 | |
|   TRUE, // Read-only
 | |
|   0,    // Don't know volume size
 | |
|   0,    // No free space
 | |
|   0,    // Don't know block size
 | |
|   L""   // Populate at runtime
 | |
| };
 | |
| 
 | |
| //
 | |
| // Template for EFI_FILE_PROTOCOL data structure.
 | |
| //
 | |
| EFI_FILE_PROTOCOL mFileSystemTemplate = {
 | |
|   EFI_FILE_PROTOCOL_REVISION,
 | |
|   FvSimpleFileSystemOpen,
 | |
|   FvSimpleFileSystemClose,
 | |
|   FvSimpleFileSystemDelete,
 | |
|   FvSimpleFileSystemRead,
 | |
|   FvSimpleFileSystemWrite,
 | |
|   FvSimpleFileSystemGetPosition,
 | |
|   FvSimpleFileSystemSetPosition,
 | |
|   FvSimpleFileSystemGetInfo,
 | |
|   FvSimpleFileSystemSetInfo,
 | |
|   FvSimpleFileSystemFlush
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Find and call ReadSection on the first section found of an executable type.
 | |
| 
 | |
|   @param  FvProtocol                  A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
 | |
|   @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
 | |
|                                       representing a file's info.
 | |
|   @param  BufferSize                  Pointer to a caller-allocated UINTN. It indicates the size of
 | |
|                                       the memory represented by *Buffer.
 | |
|   @param  Buffer                      Pointer to a pointer to a data buffer to contain file content.
 | |
| 
 | |
|   @retval EFI_SUCCESS                 The call completed successfully.
 | |
|   @retval EFI_WARN_BUFFER_TOO_SMALL   The buffer is too small to contain the requested output.
 | |
|   @retval EFI_ACCESS_DENIED           The firmware volume is configured to disallow reads.
 | |
|   @retval EFI_NOT_FOUND               The requested file was not found in the firmware volume.
 | |
|   @retval EFI_DEVICE_ERROR            A hardware error occurred when attempting toaccess the firmware volume.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FvFsFindExecutableSection (
 | |
|   IN     EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol,
 | |
|   IN     FV_FILESYSTEM_FILE_INFO           *FvFileInfo,
 | |
|   IN OUT UINTN                             *BufferSize,
 | |
|   IN OUT VOID                              **Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_SECTION_TYPE                    SectionType;
 | |
|   UINT32                              AuthenticationStatus;
 | |
|   EFI_STATUS                          Status;
 | |
| 
 | |
|   for (SectionType = EFI_SECTION_PE32; SectionType <= EFI_SECTION_TE; SectionType++) {
 | |
|     Status = FvProtocol->ReadSection (
 | |
|                            FvProtocol,
 | |
|                            &FvFileInfo->NameGuid,
 | |
|                            SectionType,
 | |
|                            0,
 | |
|                            Buffer,
 | |
|                            BufferSize,
 | |
|                            &AuthenticationStatus
 | |
|                            );
 | |
|     if (Status != EFI_NOT_FOUND) {
 | |
|       return Status;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get the size of the buffer that will be returned by FvFsReadFile.
 | |
| 
 | |
|   @param  FvProtocol                  A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
 | |
|   @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
 | |
|                                       representing a file's info.
 | |
| 
 | |
|   @retval EFI_SUCCESS                 The file size was gotten correctly.
 | |
|   @retval Others                      The file size wasn't gotten correctly.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FvFsGetFileSize (
 | |
|   IN     EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol,
 | |
|   IN OUT FV_FILESYSTEM_FILE_INFO           *FvFileInfo
 | |
|   )
 | |
| {
 | |
|   UINT32                         AuthenticationStatus;
 | |
|   EFI_FV_FILETYPE                FoundType;
 | |
|   EFI_FV_FILE_ATTRIBUTES         Attributes;
 | |
|   EFI_STATUS                     Status;
 | |
|   UINT8                          IgnoredByte;
 | |
|   VOID                           *IgnoredPtr;
 | |
| 
 | |
|   //
 | |
|   // To get the size of a section, we pass 0 for BufferSize. But we can't pass
 | |
|   // NULL for Buffer, as that will cause a return of INVALID_PARAMETER, and we
 | |
|   // can't pass NULL for *Buffer, as that will cause the callee to allocate
 | |
|   // a buffer of the sections size.
 | |
|   //
 | |
|   IgnoredPtr = &IgnoredByte;
 | |
|   FvFileInfo->FileInfo.FileSize = 0;
 | |
| 
 | |
|   if (FV_FILETYPE_IS_EXECUTABLE (FvFileInfo->Type)) {
 | |
|     //
 | |
|     // Get the size of the first executable section out of the file.
 | |
|     //
 | |
|     Status = FvFsFindExecutableSection (FvProtocol, FvFileInfo, (UINTN*)&FvFileInfo->FileInfo.FileSize, &IgnoredPtr);
 | |
|     if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   } else if (FvFileInfo->Type == EFI_FV_FILETYPE_FREEFORM) {
 | |
|     //
 | |
|     // Try to get the size of a raw section out of the file
 | |
|     //
 | |
|     Status = FvProtocol->ReadSection (
 | |
|                            FvProtocol,
 | |
|                            &FvFileInfo->NameGuid,
 | |
|                            EFI_SECTION_RAW,
 | |
|                            0,
 | |
|                            &IgnoredPtr,
 | |
|                            (UINTN*)&FvFileInfo->FileInfo.FileSize,
 | |
|                            &AuthenticationStatus
 | |
|                            );
 | |
|     if (Status == EFI_WARN_BUFFER_TOO_SMALL) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Didn't find a raw section, just return the whole file's size.
 | |
|       //
 | |
|       return FvProtocol->ReadFile (
 | |
|                            FvProtocol,
 | |
|                            &FvFileInfo->NameGuid,
 | |
|                            NULL,
 | |
|                            (UINTN*)&FvFileInfo->FileInfo.FileSize,
 | |
|                            &FoundType,
 | |
|                            &Attributes,
 | |
|                            &AuthenticationStatus
 | |
|                            );
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Get the size of the entire file
 | |
|     //
 | |
|     return FvProtocol->ReadFile (
 | |
|                          FvProtocol,
 | |
|                          &FvFileInfo->NameGuid,
 | |
|                          NULL,
 | |
|                          (UINTN*)&FvFileInfo->FileInfo.FileSize,
 | |
|                          &FoundType,
 | |
|                          &Attributes,
 | |
|                          &AuthenticationStatus
 | |
|                          );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper function to read a file.
 | |
| 
 | |
|   The data returned depends on the type of the underlying FV file:
 | |
|   - For executable types, the first section found that contains executable code is returned.
 | |
|   - For files of type FREEFORM, the driver attempts to return the first section of type RAW.
 | |
|     If none is found, the entire contents of the FV file are returned.
 | |
|   - On all other files the entire contents of the FV file is returned, as by
 | |
|     EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadFile.
 | |
| 
 | |
|   @param  FvProtocol                  A pointer to the EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
 | |
|   @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
 | |
|                                       representing a file's info.
 | |
|   @param  BufferSize                  Pointer to a caller-allocated UINTN. It indicates the size of
 | |
|                                       the memory represented by *Buffer.
 | |
|   @param  Buffer                      Pointer to a pointer to a data buffer to contain file content.
 | |
| 
 | |
|   @retval EFI_SUCCESS                 The call completed successfully.
 | |
|   @retval EFI_WARN_BUFFER_TOO_SMALL   The buffer is too small to contain the requested output.
 | |
|   @retval EFI_ACCESS_DENIED           The firmware volume is configured to disallow reads.
 | |
|   @retval EFI_NOT_FOUND               The requested file was not found in the firmware volume.
 | |
|   @retval EFI_DEVICE_ERROR            A hardware error occurred when attempting toaccess the firmware volume.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FvFsReadFile (
 | |
|   IN     EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol,
 | |
|   IN     FV_FILESYSTEM_FILE_INFO           *FvFileInfo,
 | |
|   IN OUT UINTN                             *BufferSize,
 | |
|   IN OUT VOID                              **Buffer
 | |
|   )
 | |
| {
 | |
|   UINT32                         AuthenticationStatus;
 | |
|   EFI_FV_FILETYPE                FoundType;
 | |
|   EFI_FV_FILE_ATTRIBUTES         Attributes;
 | |
|   EFI_STATUS                     Status;
 | |
| 
 | |
|   if (FV_FILETYPE_IS_EXECUTABLE (FvFileInfo->Type)) {
 | |
|     //
 | |
|     // Read the first executable section out of the file.
 | |
|     //
 | |
|     Status = FvFsFindExecutableSection (FvProtocol, FvFileInfo, BufferSize, Buffer);
 | |
|   } else if (FvFileInfo->Type == EFI_FV_FILETYPE_FREEFORM) {
 | |
|     //
 | |
|     // Try to read a raw section out of the file
 | |
|     //
 | |
|     Status = FvProtocol->ReadSection (
 | |
|                            FvProtocol,
 | |
|                            &FvFileInfo->NameGuid,
 | |
|                            EFI_SECTION_RAW,
 | |
|                            0,
 | |
|                            Buffer,
 | |
|                            BufferSize,
 | |
|                            &AuthenticationStatus
 | |
|                            );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       //
 | |
|       // Didn't find a raw section, just return the whole file.
 | |
|       //
 | |
|       Status = FvProtocol->ReadFile (
 | |
|                              FvProtocol,
 | |
|                              &FvFileInfo->NameGuid,
 | |
|                              Buffer,
 | |
|                              BufferSize,
 | |
|                              &FoundType,
 | |
|                              &Attributes,
 | |
|                              &AuthenticationStatus
 | |
|                              );
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Read the entire file
 | |
|     //
 | |
|     Status = FvProtocol->ReadFile (
 | |
|                            FvProtocol,
 | |
|                            &FvFileInfo->NameGuid,
 | |
|                            Buffer,
 | |
|                            BufferSize,
 | |
|                            &FoundType,
 | |
|                            &Attributes,
 | |
|                            &AuthenticationStatus
 | |
|                            );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper function for populating an EFI_FILE_INFO for a file.
 | |
| 
 | |
|   Note the CreateTime, LastAccessTime and ModificationTime fields in EFI_FILE_INFO
 | |
|   are full zero as FV2 protocol has no corresponding info to fill.
 | |
| 
 | |
|   @param  FvFileInfo                  A pointer to the FV_FILESYSTEM_FILE_INFO instance that is a struct
 | |
|                                       representing a file's info.
 | |
|   @param  BufferSize                  Pointer to a caller-allocated UINTN. It indicates the size of
 | |
|                                       the memory represented by FileInfo.
 | |
|   @param  FileInfo                    A pointer to EFI_FILE_INFO to contain the returned file info.
 | |
| 
 | |
|   @retval EFI_SUCCESS                 The call completed successfully.
 | |
|   @retval EFI_BUFFER_TOO_SMALL        The buffer is too small to contain the requested output.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| FvFsGetFileInfo (
 | |
|   IN     FV_FILESYSTEM_FILE_INFO           *FvFileInfo,
 | |
|   IN OUT UINTN                             *BufferSize,
 | |
|      OUT EFI_FILE_INFO                     *FileInfo
 | |
|   )
 | |
| {
 | |
|   UINTN                      InfoSize;
 | |
| 
 | |
|   InfoSize = (UINTN)FvFileInfo->FileInfo.Size;
 | |
|   if (*BufferSize < InfoSize) {
 | |
|     *BufferSize = InfoSize;
 | |
|     return EFI_BUFFER_TOO_SMALL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Initialize FileInfo
 | |
|   //
 | |
|   CopyMem (FileInfo, &FvFileInfo->FileInfo, InfoSize);
 | |
| 
 | |
|   *BufferSize = InfoSize;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Removes the last directory or file entry in a path by changing the last
 | |
|   L'\' to a CHAR_NULL.
 | |
| 
 | |
|   @param  Path      The pointer to the path to modify.
 | |
| 
 | |
|   @retval FALSE     Nothing was found to remove.
 | |
|   @retval TRUE      A directory or file was removed.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| RemoveLastItemFromPath (
 | |
|   IN OUT CHAR16 *Path
 | |
|   )
 | |
| {
 | |
|   CHAR16        *Walker;
 | |
|   CHAR16        *LastSlash;
 | |
|   //
 | |
|   // get directory name from path... ('chop' off extra)
 | |
|   //
 | |
|   for ( Walker = Path, LastSlash = NULL
 | |
|       ; Walker != NULL && *Walker != CHAR_NULL
 | |
|       ; Walker++
 | |
|      ){
 | |
|     if (*Walker == L'\\' && *(Walker + 1) != CHAR_NULL) {
 | |
|       LastSlash = Walker + 1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (LastSlash != NULL) {
 | |
|     *LastSlash = CHAR_NULL;
 | |
|     return (TRUE);
 | |
|   }
 | |
| 
 | |
|   return (FALSE);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function to clean up paths.
 | |
| 
 | |
|   - Single periods in the path are removed.
 | |
|   - Double periods in the path are removed along with a single parent directory.
 | |
|   - Forward slashes L'/' are converted to backward slashes L'\'.
 | |
| 
 | |
|   This will be done inline and the existing buffer may be larger than required
 | |
|   upon completion.
 | |
| 
 | |
|   @param  Path          The pointer to the string containing the path.
 | |
| 
 | |
|   @retval NULL          An error occured.
 | |
|   @return Path in all other instances.
 | |
| 
 | |
| **/
 | |
| CHAR16*
 | |
| EFIAPI
 | |
| TrimFilePathToAbsolutePath (
 | |
|   IN CHAR16 *Path
 | |
|   )
 | |
| {
 | |
|   CHAR16  *TempString;
 | |
|   UINTN   TempSize;
 | |
| 
 | |
|   if (Path == NULL) {
 | |
|     return NULL;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fix up the '/' vs '\'
 | |
|   //
 | |
|   for (TempString = Path ; (TempString != NULL) && (*TempString != CHAR_NULL); TempString++) {
 | |
|     if (*TempString == L'/') {
 | |
|       *TempString = L'\\';
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fix up the ..
 | |
|   //
 | |
|   while ((TempString = StrStr (Path, L"\\..\\")) != NULL) {
 | |
|     *TempString  = CHAR_NULL;
 | |
|     TempString  += 4;
 | |
|     RemoveLastItemFromPath (Path);
 | |
|     TempSize     = StrSize (TempString);
 | |
|     CopyMem (Path + StrLen (Path), TempString, TempSize);
 | |
|   }
 | |
| 
 | |
|   if (((TempString = StrStr (Path, L"\\..")) != NULL) && (*(TempString + 3) == CHAR_NULL)) {
 | |
|     *TempString  = CHAR_NULL;
 | |
|     RemoveLastItemFromPath (Path);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Fix up the .
 | |
|   //
 | |
|   while ((TempString = StrStr (Path, L"\\.\\")) != NULL) {
 | |
|     *TempString  = CHAR_NULL;
 | |
|     TempString  += 2;
 | |
|     TempSize     = StrSize (TempString);
 | |
|     CopyMem(Path + StrLen (Path), TempString, TempSize);
 | |
|   }
 | |
| 
 | |
|   if (((TempString = StrStr (Path, L"\\.")) != NULL) && (*(TempString + 2) == CHAR_NULL)) {
 | |
|     *(TempString + 1) = CHAR_NULL;
 | |
|   }
 | |
| 
 | |
|   while ((TempString = StrStr (Path, L"\\\\")) != NULL) {
 | |
|     *TempString  = CHAR_NULL;
 | |
|     TempString  += 1;
 | |
|     TempSize     = StrSize(TempString);
 | |
|     CopyMem(Path + StrLen(Path), TempString, TempSize);
 | |
|   }
 | |
| 
 | |
|   if (((TempString = StrStr(Path, L"\\\\")) != NULL) && (*(TempString + 1) == CHAR_NULL)) {
 | |
|     *(TempString) = CHAR_NULL;
 | |
|   }
 | |
| 
 | |
|   return Path;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Opens a new file relative to the source file's location.
 | |
| 
 | |
|   @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                      handle to the source location. This would typically be an open
 | |
|                      handle to a directory.
 | |
|   @param  NewHandle  A pointer to the location to return the opened handle for the new
 | |
|                      file.
 | |
|   @param  FileName   The Null-terminated string of the name of the file to be opened.
 | |
|                      The file name may contain the following path modifiers: "\", ".",
 | |
|                      and "..".
 | |
|   @param  OpenMode   The mode to open the file. The only valid combinations that the
 | |
|                      file may be opened with are: Read, Read/Write, or Create/Read/Write.
 | |
|   @param  Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these are the
 | |
|                      attribute bits for the newly created file.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The file was opened.
 | |
|   @retval EFI_NOT_FOUND        The specified file could not be found on the device.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_MEDIA_CHANGED    The device has a different medium in it or the medium is no
 | |
|                                longer supported.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  An attempt was made to create a file, or open a file for write
 | |
|                                when the media is write-protected.
 | |
|   @retval EFI_ACCESS_DENIED    The service denied access to the file.
 | |
|   @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemOpen (
 | |
|   IN     EFI_FILE_PROTOCOL    *This,
 | |
|      OUT EFI_FILE_PROTOCOL    **NewHandle,
 | |
|   IN     CHAR16               *FileName,
 | |
|   IN     UINT64               OpenMode,
 | |
|   IN     UINT64               Attributes
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE      *Instance;
 | |
|   FV_FILESYSTEM_FILE          *File;
 | |
|   FV_FILESYSTEM_FILE          *NewFile;
 | |
|   FV_FILESYSTEM_FILE_INFO     *FvFileInfo;
 | |
|   LIST_ENTRY                  *FvFileInfoLink;
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       FileNameLength;
 | |
|   UINTN                       NewFileNameLength;
 | |
|   CHAR16                      *FileNameWithExtension;
 | |
| 
 | |
|   //
 | |
|   // Check for a valid mode
 | |
|   //
 | |
|   switch (OpenMode) {
 | |
|   case EFI_FILE_MODE_READ:
 | |
|     break;
 | |
| 
 | |
|   default:
 | |
|     return EFI_WRITE_PROTECTED;
 | |
|   }
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   FileName = TrimFilePathToAbsolutePath (FileName);
 | |
|   if (FileName == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   if (FileName[0] == L'\\') {
 | |
|     FileName++;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check for opening root
 | |
|   //
 | |
|   if (StrCmp (FileName, L".") == 0 || StrCmp (FileName, L"") == 0) {
 | |
|     NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
 | |
|     if (NewFile == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
|     NewFile->Signature = FVFS_FILE_SIGNATURE;
 | |
|     NewFile->Instance  = Instance;
 | |
|     NewFile->FvFileInfo = File->FvFileInfo;
 | |
|     CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
 | |
|     InitializeListHead (&NewFile->Link);
 | |
|     InsertHeadList (&Instance->FileHead, &NewFile->Link);
 | |
| 
 | |
|     NewFile->DirReadNext = NULL;
 | |
|     if (!IsListEmpty (&Instance->FileInfoHead)) {
 | |
|       NewFile->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance);
 | |
|     }
 | |
| 
 | |
|     *NewHandle = &NewFile->FileProtocol;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Do a linear search for a file in the FV with a matching filename
 | |
|   //
 | |
|   Status     = EFI_NOT_FOUND;
 | |
|   FvFileInfo = NULL;
 | |
|   for (FvFileInfoLink = GetFirstNode (&Instance->FileInfoHead);
 | |
|       !IsNull (&Instance->FileInfoHead, FvFileInfoLink);
 | |
|        FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, FvFileInfoLink)) {
 | |
|     FvFileInfo = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
 | |
|     if (mUnicodeCollation->StriColl (mUnicodeCollation, &FvFileInfo->FileInfo.FileName[0], FileName) == 0) {
 | |
|       Status = EFI_SUCCESS;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // If the file has not been found check if the filename exists with an extension
 | |
|   // in case there was no extension present.
 | |
|   // FvFileSystem adds a 'virtual' extension '.EFI' to EFI applications and drivers
 | |
|   // present in the Firmware Volume
 | |
|   if (Status == EFI_NOT_FOUND) {
 | |
|     FileNameLength = StrLen (FileName);
 | |
| 
 | |
|     // Does the filename already contain the '.EFI' extension?
 | |
|     if (mUnicodeCollation->StriColl (mUnicodeCollation, FileName + FileNameLength - 4, L".efi") != 0) {
 | |
|       // No, there was no extension. So add one and search again for the file
 | |
|       // NewFileNameLength = FileNameLength + 1 + 4 = (Number of non-null character) + (file extension) + (a null character)
 | |
|       NewFileNameLength = FileNameLength + 1 + 4;
 | |
|       FileNameWithExtension = AllocateCopyPool (NewFileNameLength * 2, FileName);
 | |
|       StrCatS (FileNameWithExtension, NewFileNameLength, L".EFI");
 | |
| 
 | |
|       for (FvFileInfoLink = GetFirstNode (&Instance->FileInfoHead);
 | |
|           !IsNull (&Instance->FileInfoHead, FvFileInfoLink);
 | |
|            FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, FvFileInfoLink)) {
 | |
|         FvFileInfo = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
 | |
|         if (mUnicodeCollation->StriColl (mUnicodeCollation, &FvFileInfo->FileInfo.FileName[0], FileNameWithExtension) == 0) {
 | |
|           Status = EFI_SUCCESS;
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     NewFile = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE));
 | |
|     if (NewFile == NULL) {
 | |
|       return EFI_OUT_OF_RESOURCES;
 | |
|     }
 | |
| 
 | |
|     NewFile->Signature = FVFS_FILE_SIGNATURE;
 | |
|     NewFile->Instance  = Instance;
 | |
|     NewFile->FvFileInfo = FvFileInfo;
 | |
|     CopyMem (&NewFile->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate));
 | |
|     InitializeListHead (&NewFile->Link);
 | |
|     InsertHeadList (&Instance->FileHead, &NewFile->Link);
 | |
| 
 | |
|     *NewHandle = &NewFile->FileProtocol;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Closes a specified file handle.
 | |
| 
 | |
|   @param  This          A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                         handle to close.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The file was closed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemClose (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE      *Instance;
 | |
|   FV_FILESYSTEM_FILE          *File;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   if (File != Instance->Root) {
 | |
|     RemoveEntryList (&File->Link);
 | |
|     FreePool (File);
 | |
|   }
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reads data from a file.
 | |
| 
 | |
|   @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                      handle to read data from.
 | |
|   @param  BufferSize On input, the size of the Buffer. On output, the amount of data
 | |
|                      returned in Buffer. In both cases, the size is measured in bytes.
 | |
|   @param  Buffer     The buffer into which the data is read.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was read.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_DEVICE_ERROR     An attempt was made to read from a deleted file.
 | |
|   @retval EFI_DEVICE_ERROR     On entry, the current file position is beyond the end of the file.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
 | |
|                                entry. BufferSize has been updated with the size
 | |
|                                needed to complete the request.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemRead (
 | |
|   IN     EFI_FILE_PROTOCOL      *This,
 | |
|   IN OUT UINTN                  *BufferSize,
 | |
|      OUT VOID                   *Buffer
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE        *Instance;
 | |
|   FV_FILESYSTEM_FILE            *File;
 | |
|   EFI_STATUS                    Status;
 | |
|   LIST_ENTRY                    *FvFileInfoLink;
 | |
|   VOID                          *FileBuffer;
 | |
|   UINTN                         FileSize;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   if (File->FvFileInfo == Instance->Root->FvFileInfo) {
 | |
|     if (File->DirReadNext) {
 | |
|       //
 | |
|       // Directory read: populate Buffer with an EFI_FILE_INFO
 | |
|       //
 | |
|       Status = FvFsGetFileInfo (File->DirReadNext, BufferSize, Buffer);
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         //
 | |
|         // Successfully read a directory entry, now update the pointer to the
 | |
|         // next file, which will be read on the next call to this function
 | |
|         //
 | |
|         FvFileInfoLink = GetNextNode (&Instance->FileInfoHead, &File->DirReadNext->Link);
 | |
|         if (IsNull (&Instance->FileInfoHead, FvFileInfoLink)) {
 | |
|           //
 | |
|           // No more files left
 | |
|           //
 | |
|           File->DirReadNext = NULL;
 | |
|         } else {
 | |
|           File->DirReadNext = FVFS_FILE_INFO_FROM_LINK (FvFileInfoLink);
 | |
|         }
 | |
|       }
 | |
|       return Status;
 | |
|     } else {
 | |
|       //
 | |
|       // Directory read. All entries have been read, so return a zero-size
 | |
|       // buffer.
 | |
|       //
 | |
|       *BufferSize = 0;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   } else {
 | |
|     FileSize = (UINTN)File->FvFileInfo->FileInfo.FileSize;
 | |
| 
 | |
|     FileBuffer = AllocateZeroPool (FileSize);
 | |
|     if (FileBuffer == NULL) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     Status = FvFsReadFile (File->Instance->FvProtocol, File->FvFileInfo, &FileSize, &FileBuffer);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return EFI_DEVICE_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (*BufferSize + File->Position > FileSize) {
 | |
|       *BufferSize = (UINTN)(FileSize - File->Position);
 | |
|     }
 | |
| 
 | |
|     CopyMem (Buffer, (UINT8*)FileBuffer + File->Position, *BufferSize);
 | |
|     File->Position += *BufferSize;
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Writes data to a file.
 | |
| 
 | |
|   @param  This       A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                      handle to write data to.
 | |
|   @param  BufferSize On input, the size of the Buffer. On output, the amount of data
 | |
|                      actually written. In both cases, the size is measured in bytes.
 | |
|   @param  Buffer     The buffer of data to write.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was written.
 | |
|   @retval EFI_UNSUPPORTED      Writes to open directory files are not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The file or medium is write-protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was opened read only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemWrite (
 | |
|   IN     EFI_FILE_PROTOCOL    *This,
 | |
|   IN OUT UINTN                *BufferSize,
 | |
|   IN     VOID                 *Buffer
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE        *Instance;
 | |
|   FV_FILESYSTEM_FILE            *File;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   if (File->FvFileInfo == Instance->Root->FvFileInfo) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   } else {
 | |
|     return EFI_WRITE_PROTECTED;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns a file's current position.
 | |
| 
 | |
|   @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                           handle to get the current position on.
 | |
|   @param  Position        The address to return the file's current position value.
 | |
| 
 | |
|   @retval EFI_SUCCESS      The position was returned.
 | |
|   @retval EFI_UNSUPPORTED  The request is not valid on open directories.
 | |
|   @retval EFI_DEVICE_ERROR An attempt was made to get the position from a deleted file.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemGetPosition (
 | |
|   IN     EFI_FILE_PROTOCOL    *This,
 | |
|      OUT UINT64               *Position
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE        *Instance;
 | |
|   FV_FILESYSTEM_FILE            *File;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   if (File->FvFileInfo == Instance->Root->FvFileInfo) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   } else {
 | |
|     *Position = File->Position;
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Sets a file's current position.
 | |
| 
 | |
|   @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the
 | |
|                           file handle to set the requested position on.
 | |
|   @param  Position        The byte position from the start of the file to set.
 | |
| 
 | |
|   @retval EFI_SUCCESS      The position was set.
 | |
|   @retval EFI_UNSUPPORTED  The seek request for nonzero is not valid on open
 | |
|                            directories.
 | |
|   @retval EFI_DEVICE_ERROR An attempt was made to set the position of a deleted file.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemSetPosition (
 | |
|   IN EFI_FILE_PROTOCOL        *This,
 | |
|   IN UINT64                   Position
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_INSTANCE      *Instance;
 | |
|   FV_FILESYSTEM_FILE          *File;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
|   Instance = File->Instance;
 | |
| 
 | |
|   if (File->FvFileInfo == Instance->Root->FvFileInfo) {
 | |
|     if (Position != 0) {
 | |
|       return EFI_UNSUPPORTED;
 | |
|     }
 | |
|     //
 | |
|     // Reset directory position to first entry
 | |
|     //
 | |
|     if (File->DirReadNext) {
 | |
|       File->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance); 
 | |
|     }
 | |
|   } else if (Position == 0xFFFFFFFFFFFFFFFFull) {
 | |
|     File->Position = File->FvFileInfo->FileInfo.FileSize;
 | |
|   } else {
 | |
|     File->Position = Position;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Flushes all modified data associated with a file to a device.
 | |
| 
 | |
|   @param  This A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                handle to flush.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The data was flushed.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The file or medium is write-protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was opened read-only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemFlush (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   return EFI_WRITE_PROTECTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close and delete the file handle.
 | |
| 
 | |
|   @param  This                     A pointer to the EFI_FILE_PROTOCOL instance that is the
 | |
|                                    handle to the file to delete.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The file was closed and deleted, and the handle was closed.
 | |
|   @retval EFI_WARN_DELETE_FAILURE  The handle was closed, but the file was not deleted.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemDelete (
 | |
|   IN EFI_FILE_PROTOCOL *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS       Status;
 | |
| 
 | |
|   Status = FvSimpleFileSystemClose (This);
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return EFI_WARN_DELETE_FAILURE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Returns information about a file.
 | |
| 
 | |
|   @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                           handle the requested information is for.
 | |
|   @param  InformationType The type identifier for the information being requested.
 | |
|   @param  BufferSize      On input, the size of Buffer. On output, the amount of data
 | |
|                           returned in Buffer. In both cases, the size is measured in bytes.
 | |
|   @param  Buffer          A pointer to the data buffer to return. The buffer's type is
 | |
|                           indicated by InformationType.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The information was returned.
 | |
|   @retval EFI_UNSUPPORTED      The InformationType is not known.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
 | |
|                                BufferSize has been updated with the size needed to complete
 | |
|                                the request.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemGetInfo (
 | |
|   IN     EFI_FILE_PROTOCOL    *This,
 | |
|   IN     EFI_GUID             *InformationType,
 | |
|   IN OUT UINTN                *BufferSize,
 | |
|      OUT VOID                 *Buffer
 | |
|   )
 | |
| {
 | |
|   FV_FILESYSTEM_FILE           *File;
 | |
|   EFI_FILE_SYSTEM_INFO         *FsInfoOut;
 | |
|   EFI_FILE_SYSTEM_VOLUME_LABEL *FsVolumeLabel;
 | |
|   FV_FILESYSTEM_INSTANCE       *Instance;
 | |
|   UINTN                        Size;
 | |
|   EFI_STATUS                   Status;
 | |
| 
 | |
|   File = FVFS_FILE_FROM_FILE_THIS (This);
 | |
| 
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
 | |
|     //
 | |
|     // Return filesystem info
 | |
|     //
 | |
|     Instance = File->Instance;
 | |
| 
 | |
|     Size = sizeof (EFI_FILE_SYSTEM_INFO) + StrSize (Instance->VolumeLabel) - sizeof (CHAR16);
 | |
| 
 | |
|     if (*BufferSize < Size) {
 | |
|       *BufferSize = Size;
 | |
|       return EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Cast output buffer for convenience
 | |
|     //
 | |
|     FsInfoOut = (EFI_FILE_SYSTEM_INFO *) Buffer;
 | |
| 
 | |
|     CopyMem (FsInfoOut, &mFsInfoTemplate, sizeof (EFI_FILE_SYSTEM_INFO));
 | |
|     Status = StrnCpyS ( FsInfoOut->VolumeLabel, 
 | |
|                         (*BufferSize - OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel)) / sizeof (CHAR16), 
 | |
|                         Instance->VolumeLabel, 
 | |
|                         StrLen (Instance->VolumeLabel)
 | |
|                         );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     FsInfoOut->Size = Size;
 | |
|     return Status;
 | |
|   } else if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
 | |
|     //
 | |
|     // Return file info
 | |
|     //
 | |
|     return FvFsGetFileInfo (File->FvFileInfo, BufferSize, (EFI_FILE_INFO *) Buffer);
 | |
|   } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | |
|     //
 | |
|     // Return Volume Label
 | |
|     //
 | |
|     Instance = File->Instance;
 | |
|     Size     = sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL) + StrSize (Instance->VolumeLabel) - sizeof (CHAR16);;
 | |
|     if (*BufferSize < Size) {
 | |
|       *BufferSize = Size;
 | |
|       return EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
| 
 | |
|     FsVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL*) Buffer;
 | |
|     Status        = StrnCpyS (FsVolumeLabel->VolumeLabel, 
 | |
|                               (*BufferSize - OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel)) / sizeof (CHAR16),
 | |
|                               Instance->VolumeLabel, 
 | |
|                               StrLen (Instance->VolumeLabel)
 | |
|                               );
 | |
|     ASSERT_EFI_ERROR (Status);
 | |
|     return Status;
 | |
|   } else {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Sets information about a file.
 | |
| 
 | |
|   @param  This            A pointer to the EFI_FILE_PROTOCOL instance that is the file
 | |
|                           handle the information is for.
 | |
|   @param  InformationType The type identifier for the information being set.
 | |
|   @param  BufferSize      The size, in bytes, of Buffer.
 | |
|   @param  Buffer          A pointer to the data buffer to write. The buffer's type is
 | |
|                           indicated by InformationType.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The information was set.
 | |
|   @retval EFI_UNSUPPORTED      The InformationType is not known.
 | |
|   @retval EFI_NO_MEDIA         The device has no medium.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  InformationType is EFI_FILE_INFO_ID and the media is
 | |
|                                read-only.
 | |
|   @retval EFI_WRITE_PROTECTED  InformationType is EFI_FILE_PROTOCOL_SYSTEM_INFO_ID
 | |
|                                and the media is read only.
 | |
|   @retval EFI_WRITE_PROTECTED  InformationType is EFI_FILE_SYSTEM_VOLUME_LABEL_ID
 | |
|                                and the media is read-only.
 | |
|   @retval EFI_ACCESS_DENIED    An attempt is made to change the name of a file to a
 | |
|                                file that is already present.
 | |
|   @retval EFI_ACCESS_DENIED    An attempt is being made to change the EFI_FILE_DIRECTORY
 | |
|                                Attribute.
 | |
|   @retval EFI_ACCESS_DENIED    An attempt is being made to change the size of a directory.
 | |
|   @retval EFI_ACCESS_DENIED    InformationType is EFI_FILE_INFO_ID and the file was opened
 | |
|                                read-only and an attempt is being made to modify a field
 | |
|                                other than Attribute.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
|   @retval EFI_BAD_BUFFER_SIZE  BufferSize is smaller than the size of the type indicated
 | |
|                                by InformationType.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| FvSimpleFileSystemSetInfo (
 | |
|   IN EFI_FILE_PROTOCOL        *This,
 | |
|   IN EFI_GUID                 *InformationType,
 | |
|   IN UINTN                    BufferSize,
 | |
|   IN VOID                     *Buffer
 | |
|   )
 | |
| {
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid) || 
 | |
|       CompareGuid (InformationType, &gEfiFileInfoGuid) ||
 | |
|       CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | |
|     return EFI_WRITE_PROTECTED;
 | |
|   }
 | |
| 
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 |