From 9da91aea69569feceb23cf502c81a32a4121d362 Mon Sep 17 00:00:00 2001 From: Brendan Jackman Date: Tue, 23 Dec 2014 03:18:04 +0000 Subject: MdeModulePkg/FvSimpleFileSystem: Add a new module to provide access to executable files in FVs. This module implements Simple FileSystem protocol over Firmware Volume (FV). EFI Modules included into a FV can be listed and launched from the EFI Shell or any other EFI applications. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Brendan Jackman Signed-off-by: Feng Tian Reviewed-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16547 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/MdeModulePkg.dsc | 6 +- .../FvSimpleFileSystemDxe/ComponentName.c | 187 ++++ .../FvSimpleFileSystemDxe/FvSimpleFileSystem.c | 978 +++++++++++++++++++++ .../FvSimpleFileSystemDxe/FvSimpleFileSystem.uni | Bin 0 -> 2018 bytes .../FvSimpleFileSystemDxe.inf | 74 ++ .../FvSimpleFileSystemEntryPoint.c | 676 ++++++++++++++ .../FvSimpleFileSystemExtra.uni | Bin 0 -> 1384 bytes .../FvSimpleFileSystemInternal.h | 622 +++++++++++++ 8 files changed, 2541 insertions(+), 2 deletions(-) create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.uni create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemEntryPoint.c create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemExtra.uni create mode 100644 MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemInternal.h (limited to 'MdeModulePkg') diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 0b47698afa..702ffc2ef2 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -336,8 +336,10 @@ NULL|MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.inf } - -[Components.IA32, Components.X64, Components.IPF] + + MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf + +[Components.IA32, Components.X64, Components.IPF] MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf MdeModulePkg/Universal/EbcDxe/EbcDxe.inf diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/ComponentName.c b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/ComponentName.c new file mode 100644 index 0000000000..5ea05975ae --- /dev/null +++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/ComponentName.c @@ -0,0 +1,187 @@ +/** @file + UEFI Component Name(2) protocol implementation for FvSimpleFileSystem driver. + +Copyright (c) 2014, ARM Limited. All rights reserved. +Copyright (c) 2014, Intel Corporation. All rights reserved.
+ +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" + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gFvSimpleFileSystemComponentName = { + FvSimpleFileSystemComponentNameGetDriverName, + FvSimpleFileSystemComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gFvSimpleFileSystemComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) FvSimpleFileSystemComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) FvSimpleFileSystemComponentNameGetControllerName, + "en" +}; + +// +// Driver name table for FvSimpleFileSystem module. +// It is shared by the implementation of ComponentName & ComponentName2 Protocol. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mFvSimpleFileSystemDriverNameTable[] = { + { + "eng;en", + (CHAR16 *)L"Fv Simple File System Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mFvSimpleFileSystemDriverNameTable, + DriverName, + (BOOLEAN)(This == &gFvSimpleFileSystemComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c new file mode 100644 index 0000000000..9661cfd132 --- /dev/null +++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c @@ -0,0 +1,978 @@ +/** @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, Intel Corporation. All rights reserved.
+ +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, &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, + &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, + &FvFileInfo->FileInfo.FileSize, + &FoundType, + &Attributes, + &AuthenticationStatus + ); + } + } else { + // + // Get the size of the entire file + // + return FvProtocol->ReadFile ( + FvProtocol, + &FvFileInfo->NameGuid, + NULL, + &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 = 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; + + // + // 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[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 = 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 + // + 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) { + 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 = 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 = 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 + // + 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; +} + diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.uni b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.uni new file mode 100644 index 0000000000..fc8c9291ab Binary files /dev/null and b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.uni differ diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf new file mode 100644 index 0000000000..a648c2efc8 --- /dev/null +++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemDxe.inf @@ -0,0 +1,74 @@ +## @file +# Support for Simple File System over Firmware Volume. +# +# 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 Ltd. All rights reserved.
+# Copyright (c) 2014, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FvSimpleFileSystem + MODULE_UNI_FILE = FvSimpleFileSystem.uni + FILE_GUID = 907125c0-a5f1-11e3-a3fe-a3198b49350c + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = FvSimpleFileSystemEntryPoint + +[Sources] + + ComponentName.c + FvSimpleFileSystem.c + FvSimpleFileSystemEntryPoint.c + FvSimpleFileSystemInternal.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + BaseLib + DevicePathLib + MemoryAllocationLib + PrintLib + UefiDriverEntryPoint + UefiLib + +[Pcd] + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLang ## SOMETIMES_CONSUMES + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLang ## SOMETIMES_CONSUMES + +[Guids] + gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiFileSystemVolumeLabelInfoIdGuid ## SOMETIMES_CONSUMES ## UNDEFINED + +[Protocols] + gEfiDevicePathProtocolGuid ## TO_START + gEfiFirmwareVolume2ProtocolGuid ## TO_START + gEfiUnicodeCollationProtocolGuid ## TO_START + gEfiUnicodeCollation2ProtocolGuid ## TO_START + gEfiSimpleFileSystemProtocolGuid ## BY_START + +[UserExtensions.TianoCore."ExtraFiles"] + FvSimpleFileSystemExtra.uni \ No newline at end of file diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemEntryPoint.c b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemEntryPoint.c new file mode 100644 index 0000000000..975ab88ca1 --- /dev/null +++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemEntryPoint.c @@ -0,0 +1,676 @@ +/** @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, Intel Corporation. All rights reserved.
+ +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" + +EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation = NULL; + +// +// A Guid string is 32 hex characters with 4 hyphens and a NULL-terminated char: 37 characters total +// +#define GUID_STRING_SIZE (37 * sizeof (CHAR16)) + +#define FVFS_VOLUME_LABEL_PREFIX L"Firmware Volume: " +#define FVFS_VOLUME_LABEL_SIZE (sizeof (FVFS_VOLUME_LABEL_PREFIX) + GUID_STRING_SIZE - sizeof (CHAR16)) +#define FVFS_FALLBACK_VOLUME_LABEL L"Firmware Volume" + +// +// Template for EFI_SIMPLE_FILE_SYSTEM_PROTOCOL data structure. +// +EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mSimpleFsTemplate = { + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION, + FvSimpleFileSystemOpenVolume +}; + +// +// Template for EFI_DRIVER_BINDING_PROTOCOL data structure. +// +EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = { + FvSimpleFileSystemDriverSupported, + FvSimpleFileSystemDriverStart, + FvSimpleFileSystemDriverStop, + 0, + NULL, + NULL +}; + +/** + Open the root directory on a volume. + + @param This A pointer to the volume to open the root directory. + @param RootFile A pointer to the location to return the opened file handle for the + root directory. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not support the requested file system type. + @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_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. Any existing file handles for this volume are + no longer valid. To access the files on the new medium, the + volume must be reopened with OpenVolume(). + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **RootFile + ) +{ + EFI_STATUS Status; + FV_FILESYSTEM_FILE *Root; + CHAR16 *UiSection; + EFI_GUID NameGuid; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 Authentication; + UINTN Key; + EFI_FV_FILETYPE FileType; + UINTN Size; + FV_FILESYSTEM_INSTANCE *Instance; + FV_FILESYSTEM_FILE_INFO *FvFileInfo; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; + CHAR16 *Name; + UINTN NameLen; + UINTN NumChars; + UINTN DestMax; + + Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (This); + Status = EFI_SUCCESS; + + if (Instance->Root == NULL) { + // + // Allocate file structure for root file + // + Root = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE)); + if (Root == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Instance->Root = Root; + Root->Instance = Instance; + Root->Signature = FVFS_FILE_SIGNATURE; + CopyMem (&Root->FileProtocol, &mFileSystemTemplate, sizeof (mFileSystemTemplate)); + Root->FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO)); + if (Root->FvFileInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Root->FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO); + Root->FvFileInfo->FileInfo.Attribute = EFI_FILE_DIRECTORY | EFI_FILE_READ_ONLY; + + // + // Populate the instance's list of files. We consider anything a file that + // has a UI_SECTION, which we consider to be its filename. + // + FvProtocol = Instance->FvProtocol; + // + // Allocate Key + // + Key = 0; + + do { + FileType = EFI_FV_FILETYPE_ALL; + + Status = FvProtocol->GetNextFile ( + FvProtocol, + &Key, + &FileType, + &NameGuid, + &Attributes, + &Size + ); + if (EFI_ERROR (Status)) { + ASSERT (Status == EFI_NOT_FOUND); + break; + } + + // + // Get a file's name: If it has a UI section, use that, otherwise use + // its NameGuid. + // + UiSection = NULL; + Status = FvProtocol->ReadSection ( + FvProtocol, + &NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiSection, + &Size, + &Authentication + ); + if (!EFI_ERROR (Status)) { + Name = UiSection; + } else { + Name = AllocateZeroPool (GUID_STRING_SIZE); + if (Name == NULL) { + return EFI_OUT_OF_RESOURCES; + } + NumChars = UnicodeSPrint (Name, GUID_STRING_SIZE, L"%g", &NameGuid); + ASSERT ((NumChars + 1) * sizeof (CHAR16) == GUID_STRING_SIZE); + } + + // + // Found a file. + // Allocate a file structure and populate it. + // + NameLen = StrSize (Name); + if (FV_FILETYPE_IS_EXECUTABLE (FileType)) { + NameLen += StrSize (L".efi") - sizeof (CHAR16); + } + + FvFileInfo = AllocateZeroPool (sizeof (FV_FILESYSTEM_FILE_INFO) + NameLen - sizeof (CHAR16)); + if (FvFileInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FvFileInfo->Signature = FVFS_FILE_INFO_SIGNATURE; + InitializeListHead (&FvFileInfo->Link); + CopyMem (&FvFileInfo->NameGuid, &NameGuid, sizeof (EFI_GUID)); + FvFileInfo->Type = FileType; + + // + // Add ".efi" to filenames of drivers and applications. + // + DestMax = NameLen / sizeof (CHAR16); + Status = StrnCpyS (&FvFileInfo->FileInfo.FileName[0], DestMax, Name, StrLen (Name)); + ASSERT_EFI_ERROR (Status); + + if (FV_FILETYPE_IS_EXECUTABLE (FileType)) { + Status = StrnCatS (&FvFileInfo->FileInfo.FileName[0], DestMax, L".efi", StrLen (L".efi")); + ASSERT_EFI_ERROR (Status); + } + + FvFileInfo->FileInfo.Size = sizeof (EFI_FILE_INFO) + NameLen - sizeof (CHAR16); + Status = FvFsGetFileSize (FvProtocol, FvFileInfo); + ASSERT_EFI_ERROR (Status); + FvFileInfo->FileInfo.PhysicalSize = FvFileInfo->FileInfo.FileSize; + FvFileInfo->FileInfo.Attribute = EFI_FILE_READ_ONLY; + + InsertHeadList (&Instance->FileInfoHead, &FvFileInfo->Link); + + FreePool (Name); + + } while (TRUE); + + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + } + } + + Instance->Root->DirReadNext = FVFS_GET_FIRST_FILE_INFO (Instance); + *RootFile = &Instance->Root->FileProtocol; + return Status; +} + +/** + Worker function to initialize Unicode Collation support. + + It tries to locate Unicode Collation (2) protocol and matches it with current + platform language code. + + @param AgentHandle The handle used to open Unicode Collation (2) protocol. + @param ProtocolGuid The pointer to Unicode Collation (2) protocol GUID. + @param VariableName The name of the RFC 4646 or ISO 639-2 language variable. + @param DefaultLanguage The default language in case the RFC 4646 or ISO 639-2 language is absent. + + @retval EFI_SUCCESS The Unicode Collation (2) protocol has been successfully located. + @retval Others The Unicode Collation (2) protocol has not been located. + +**/ +EFI_STATUS +InitializeUnicodeCollationSupportWorker ( + IN EFI_HANDLE AgentHandle, + IN EFI_GUID *ProtocolGuid, + IN CONST CHAR16 *VariableName, + IN CONST CHAR8 *DefaultLanguage + ) +{ + EFI_STATUS ReturnStatus; + EFI_STATUS Status; + UINTN NumHandles; + UINTN Index; + EFI_HANDLE *Handles; + EFI_UNICODE_COLLATION_PROTOCOL *Uci; + BOOLEAN Iso639Language; + CHAR8 *Language; + CHAR8 *BestLanguage; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + ProtocolGuid, + NULL, + &NumHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Iso639Language = (BOOLEAN) (ProtocolGuid == &gEfiUnicodeCollationProtocolGuid); + GetEfiGlobalVariable2 (VariableName, (VOID**) &Language, NULL); + + ReturnStatus = EFI_UNSUPPORTED; + for (Index = 0; Index < NumHandles; Index++) { + // + // Open Unicode Collation Protocol + // + Status = gBS->OpenProtocol ( + Handles[Index], + ProtocolGuid, + (VOID **) &Uci, + AgentHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Find the best matching matching language from the supported languages + // of Unicode Collation (2) protocol. + // + BestLanguage = GetBestLanguage ( + Uci->SupportedLanguages, + Iso639Language, + (Language == NULL) ? "" : Language, + DefaultLanguage, + NULL + ); + if (BestLanguage != NULL) { + FreePool (BestLanguage); + mUnicodeCollation = Uci; + ReturnStatus = EFI_SUCCESS; + break; + } + } + + if (Language != NULL) { + FreePool (Language); + } + + FreePool (Handles); + + return ReturnStatus; +} + +/** + Initialize Unicode Collation support. + + It tries to locate Unicode Collation 2 protocol and matches it with current + platform language code. If for any reason the first attempt fails, it then tries to + use Unicode Collation Protocol. + + @param AgentHandle The handle used to open Unicode Collation (2) protocol. + + @retval EFI_SUCCESS The Unicode Collation (2) protocol has been successfully located. + @retval Others The Unicode Collation (2) protocol has not been located. + +**/ +EFI_STATUS +InitializeUnicodeCollationSupport ( + IN EFI_HANDLE AgentHandle + ) +{ + + EFI_STATUS Status; + + Status = EFI_UNSUPPORTED; + + // + // First try to use RFC 4646 Unicode Collation 2 Protocol. + // + Status = InitializeUnicodeCollationSupportWorker ( + AgentHandle, + &gEfiUnicodeCollation2ProtocolGuid, + L"PlatformLang", + (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang) + ); + // + // If the attempt to use Unicode Collation 2 Protocol fails, then we fall back + // on the ISO 639-2 Unicode Collation Protocol. + // + if (EFI_ERROR (Status)) { + Status = InitializeUnicodeCollationSupportWorker ( + AgentHandle, + &gEfiUnicodeCollationProtocolGuid, + L"Lang", + (CONST CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultLang) + ); + } + + return Status; +} + +/** + Test to see if this driver supports ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to test + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + return gBS->OpenProtocol ( + ControllerHandle, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); +} + +/** + Start this driver on ControllerHandle by opening a FV protocol and + installing a SimpleFileSystem protocol on ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; + FV_FILESYSTEM_INSTANCE *Instance; + EFI_DEVICE_PATH_PROTOCOL *FvDevicePath; + EFI_GUID *FvGuid; + UINTN NumChars; + + Status = InitializeUnicodeCollationSupport (DriverBinding->DriverBindingHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Open FV protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &FvProtocol, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Create an instance + // + Instance = AllocateZeroPool (sizeof (FV_FILESYSTEM_INSTANCE)); + if (Instance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Instance->Root = NULL; + Instance->FvProtocol = FvProtocol; + Instance->Signature = FVFS_INSTANCE_SIGNATURE; + InitializeListHead (&Instance->FileInfoHead); + InitializeListHead (&Instance->FileHead); + CopyMem (&Instance->SimpleFs, &mSimpleFsTemplate, sizeof (mSimpleFsTemplate)); + + Status = gBS->InstallProtocolInterface( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + EFI_NATIVE_INTERFACE, + &Instance->SimpleFs + ); + + // + // Decide on a filesystem volume label, which will include the FV's guid. + // Get the device path to find the FV's GUID + // + Instance->VolumeLabel = NULL; + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &FvDevicePath, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + // + // Iterate over device path until we find a firmware volume node + // + while (!IsDevicePathEndType (FvDevicePath)) { + if (DevicePathType (FvDevicePath) == MEDIA_DEVICE_PATH && + DevicePathSubType (FvDevicePath) == MEDIA_PIWG_FW_VOL_DP) { + // + // Allocate the volume label + // + Instance->VolumeLabel = AllocateZeroPool (FVFS_VOLUME_LABEL_SIZE); + // + // Check the allocation was successful + // + if (Instance->VolumeLabel != NULL) { + // + // Extract the FV's guid + // + FvGuid = &((MEDIA_FW_VOL_DEVICE_PATH *) FvDevicePath)->FvName; + // + // Build the volume label string + // + NumChars = UnicodeSPrint ( + Instance->VolumeLabel, + FVFS_VOLUME_LABEL_SIZE, + FVFS_VOLUME_LABEL_PREFIX L"%g", + FvGuid + ); + ASSERT ((NumChars + 1) * sizeof (CHAR16) == FVFS_VOLUME_LABEL_SIZE); + } + break; + } + FvDevicePath = NextDevicePathNode (FvDevicePath); + } + } + // + // If we didn't decide on a volume label, set a fallback one + // + if (Instance->VolumeLabel == NULL) { + Instance->VolumeLabel = AllocateCopyPool ( + sizeof (FVFS_FALLBACK_VOLUME_LABEL), + FVFS_FALLBACK_VOLUME_LABEL + ); + } + + return Status; +} + +/** + Stop this driver on ControllerHandle by removing SimpleFileSystem protocol and closing + the FV protocol on ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + FV_FILESYSTEM_INSTANCE *Instance; + FV_FILESYSTEM_FILE_INFO *FvFileInfo; + LIST_ENTRY *Entry; + LIST_ENTRY *DelEntry; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFile; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &SimpleFile, + DriverBinding->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Instance = FVFS_INSTANCE_FROM_SIMPLE_FS_THIS (SimpleFile); + + if (IsListEmpty (&Instance->FileHead) == FALSE) { + // + // Not all opened files are closed + // + return EFI_DEVICE_ERROR; + } + + // + // Close and uninstall protocols. + // + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiFirmwareVolume2ProtocolGuid, + gImageHandle, + ControllerHandle + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &Instance->SimpleFs + ); + ASSERT_EFI_ERROR (Status); + + // + // Free file structures + // + if (!IsListEmpty (&Instance->FileInfoHead)) { + // + // Free the Subtask list. + // + for(Entry = Instance->FileInfoHead.ForwardLink; + Entry != (&Instance->FileInfoHead); + ) { + DelEntry = Entry; + Entry = Entry->ForwardLink; + FvFileInfo = FVFS_FILE_INFO_FROM_LINK (DelEntry); + + RemoveEntryList (DelEntry); + FreePool (FvFileInfo); + } + } + + if (Instance->Root != NULL) { + // + // Root->Name is statically allocated, no need to free. + // + if (Instance->Root->FvFileInfo != NULL) { + FreePool (Instance->Root->FvFileInfo); + } + FreePool (Instance->Root); + } + + // + // Free Instance + // + if (Instance->VolumeLabel != NULL) { + FreePool (Instance->VolumeLabel); + } + FreePool (Instance); + + return EFI_SUCCESS; +} + +/** + The user Entry Point for module FvSimpleFileSystem. The user code starts with this function. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Install driver model protocol(s). + // + Status = EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &mDriverBinding, + ImageHandle, + &gFvSimpleFileSystemComponentName, + &gFvSimpleFileSystemComponentName2 + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemExtra.uni b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemExtra.uni new file mode 100644 index 0000000000..7988ee5297 Binary files /dev/null and b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemExtra.uni differ diff --git a/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemInternal.h b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemInternal.h new file mode 100644 index 0000000000..c8da5f68fd --- /dev/null +++ b/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystemInternal.h @@ -0,0 +1,622 @@ +/** @file + The internal header file of FvSimpleFileSystem driver. + +Copyright (c) 2014, ARM Limited. All rights reserved. +Copyright (c) 2014, Intel Corporation. All rights reserved.
+ +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. + +**/ + +#ifndef __FVFS_INTERNAL_H__ +#define __FVFS_INTERNAL_H__ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +typedef struct _FV_FILESYSTEM_FILE FV_FILESYSTEM_FILE; +typedef struct _FV_FILESYSTEM_FILE_INFO FV_FILESYSTEM_FILE_INFO; +typedef struct _FV_FILESYSTEM_INSTANCE FV_FILESYSTEM_INSTANCE; + +// +// Struct representing an instance of the "filesystem". There will be one of +// these structs per FV. +// +struct _FV_FILESYSTEM_INSTANCE { + UINT32 Signature; + LIST_ENTRY FileInfoHead; + LIST_ENTRY FileHead; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs; + FV_FILESYSTEM_FILE *Root; + CHAR16 *VolumeLabel; +}; + +// +// Struct representing a opening file. Each opening operation on file will +// create such an instance except for the "root directory", which will only +// be created once for each FV. +// +struct _FV_FILESYSTEM_FILE { + UINT32 Signature; + LIST_ENTRY Link; + FV_FILESYSTEM_FILE_INFO *DirReadNext; + FV_FILESYSTEM_INSTANCE *Instance; + EFI_FILE_PROTOCOL FileProtocol; + FV_FILESYSTEM_FILE_INFO *FvFileInfo; + UINT64 Position; +}; + +// +// Struct representing the info of a file. +// +struct _FV_FILESYSTEM_FILE_INFO { + UINT32 Signature; + LIST_ENTRY Link; + EFI_GUID NameGuid; + EFI_FV_FILETYPE Type; + EFI_FILE_INFO FileInfo; +}; + +#define FVFS_FILE_SIGNATURE SIGNATURE_32 ('f', 'v', 'f', 'i') +#define FVFS_FILE_INFO_SIGNATURE SIGNATURE_32 ('f', 'v', 'i', 'n') +#define FVFS_INSTANCE_SIGNATURE SIGNATURE_32 ('f', 'v', 'f', 's') + +#define FVFS_INSTANCE_FROM_SIMPLE_FS_THIS(This) CR ( \ + This, \ + FV_FILESYSTEM_INSTANCE, \ + SimpleFs, \ + FVFS_INSTANCE_SIGNATURE \ + ) + +#define FVFS_FILE_FROM_FILE_THIS(This) CR ( \ + This, \ + FV_FILESYSTEM_FILE, \ + FileProtocol, \ + FVFS_FILE_SIGNATURE \ + ) + +#define FVFS_FILE_INFO_FROM_LINK(This) CR ( \ + This, \ + FV_FILESYSTEM_FILE_INFO, \ + Link, \ + FVFS_FILE_INFO_SIGNATURE \ + ) + +#define FVFS_FILE_FROM_LINK(FileLink) CR (FileLink, FV_FILESYSTEM_FILE, Link, FVFS_FILE_SIGNATURE) + +#define FVFS_GET_FIRST_FILE(Instance) FVFS_FILE_FROM_LINK (GetFirstNode (&Instance->FileHead)) + +#define FVFS_GET_FIRST_FILE_INFO(Instance) FVFS_FILE_INFO_FROM_LINK (GetFirstNode (&Instance->FileInfoHead)) + + +#define FV_FILETYPE_IS_EXECUTABLE(Type) ((Type) == EFI_FV_FILETYPE_PEIM || \ + (Type) == EFI_FV_FILETYPE_DRIVER || \ + (Type) == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER || \ + (Type) == EFI_FV_FILETYPE_APPLICATION) + +/** + Open the root directory on a volume. + + @param This A pointer to the volume to open the root directory. + @param RootFile A pointer to the location to return the opened file handle for the + root directory. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not support the requested file system type. + @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_ACCESS_DENIED The service denied access to the file. + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources. + @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no + longer supported. Any existing file handles for this volume are + no longer valid. To access the files on the new medium, the + volume must be reopened with OpenVolume(). + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE_PROTOCOL **RootFile + ); + +/** + Test to see if this driver supports ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to test + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Start this driver on ControllerHandle by opening a FV protocol and + installing a SimpleFileSystem protocol on ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval other This driver does not support this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stop this driver on ControllerHandle by removing SimpleFileSystem protocol and closing + the FV protocol on ControllerHandle. + + @param DriverBinding Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + + @param DriverName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER DriverName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + + @param ControllerHandle[in] The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + + @param ChildHandle[in] The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + + @param Language[in] A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + + @param ControllerName[out] A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + + @retval EFI_INVALID_PARAMETER Language is NULL. + + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +FvSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +extern EFI_UNICODE_COLLATION_PROTOCOL *mUnicodeCollation; +extern EFI_FILE_PROTOCOL mFileSystemTemplate; +extern EFI_COMPONENT_NAME_PROTOCOL gFvSimpleFileSystemComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gFvSimpleFileSystemComponentName2; + +#endif \ No newline at end of file -- cgit v1.2.3