/** 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 == 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 = 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; }
/** 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; }