summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c')
-rw-r--r--MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c2082
1 files changed, 1041 insertions, 1041 deletions
diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
index 0252db19ad..623cd59d35 100644
--- a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
+++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
@@ -1,1041 +1,1041 @@
-/** @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 - 2018, Intel Corporation. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#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 occurred.
- @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 = AllocatePool (NewFileNameLength * 2);
- StrCpyS (FileNameWithExtension, NewFileNameLength, 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)) {
- FreePool (FileBuffer);
- return EFI_DEVICE_ERROR;
- }
-
- if (*BufferSize + File->Position > FileSize) {
- *BufferSize = (UINTN)(FileSize - File->Position);
- }
-
- CopyMem (Buffer, (UINT8 *)FileBuffer + File->Position, *BufferSize);
- File->Position += *BufferSize;
-
- FreePool (FileBuffer);
-
- 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;
-}
+/** @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 - 2018, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 occurred.
+ @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 = AllocatePool (NewFileNameLength * 2);
+ StrCpyS (FileNameWithExtension, NewFileNameLength, 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)) {
+ FreePool (FileBuffer);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (*BufferSize + File->Position > FileSize) {
+ *BufferSize = (UINTN)(FileSize - File->Position);
+ }
+
+ CopyMem (Buffer, (UINT8 *)FileBuffer + File->Position, *BufferSize);
+ File->Position += *BufferSize;
+
+ FreePool (FileBuffer);
+
+ 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;
+}