From d8c18a54e820af4f88eb6517dc0dfe9e49be60a4 Mon Sep 17 00:00:00 2001 From: yuzubot Date: Mon, 28 Oct 2019 12:01:12 +0000 Subject: [PATCH] "Merge Tagged PR 2933" --- src/core/CMakeLists.txt | 2 + src/core/file_sys/vfs_ro_layer.cpp | 181 +++++++++ src/core/file_sys/vfs_ro_layer.h | 73 ++++ .../hle/service/filesystem/filesystem.cpp | 3 +- src/core/hle/service/filesystem/fsp_srv.cpp | 382 ++++++++++++++++-- src/core/hle/service/filesystem/fsp_srv.h | 18 +- 6 files changed, 618 insertions(+), 41 deletions(-) create mode 100644 src/core/file_sys/vfs_ro_layer.cpp create mode 100644 src/core/file_sys/vfs_ro_layer.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4f6a87b0a7..bd2a8510cd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -108,6 +108,8 @@ add_library(core STATIC file_sys/vfs_offset.h file_sys/vfs_real.cpp file_sys/vfs_real.h + file_sys/vfs_ro_layer.cpp + file_sys/vfs_ro_layer.h file_sys/vfs_static.h file_sys/vfs_types.h file_sys/vfs_vector.cpp diff --git a/src/core/file_sys/vfs_ro_layer.cpp b/src/core/file_sys/vfs_ro_layer.cpp new file mode 100644 index 0000000000..c673bd6b9f --- /dev/null +++ b/src/core/file_sys/vfs_ro_layer.cpp @@ -0,0 +1,181 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/file_sys/vfs_ro_layer.h" + +namespace FileSys { + +ReadOnlyVfsFileLayer::ReadOnlyVfsFileLayer(VirtualFile base) : base(std::move(base)) {} + +ReadOnlyVfsFileLayer::~ReadOnlyVfsFileLayer() = default; + +std::string ReadOnlyVfsFileLayer::GetName() const { + return base->GetName(); +} + +std::size_t ReadOnlyVfsFileLayer::GetSize() const { + return base->GetSize(); +} + +bool ReadOnlyVfsFileLayer::Resize(std::size_t new_size) { + return false; +} + +std::shared_ptr ReadOnlyVfsFileLayer::GetContainingDirectory() const { + // Make containing read-only to prevent escaping the layer by getting containing and then + // getting this file again. + return std::make_shared(base->GetContainingDirectory()); +} + +bool ReadOnlyVfsFileLayer::IsWritable() const { + return false; +} + +bool ReadOnlyVfsFileLayer::IsReadable() const { + return base->IsReadable(); +} + +std::size_t ReadOnlyVfsFileLayer::Read(u8* data, std::size_t length, std::size_t offset) const { + return base->Read(data, length, offset); +} + +std::size_t ReadOnlyVfsFileLayer::Write(const u8* data, std::size_t length, std::size_t offset) { + return 0; +} + +bool ReadOnlyVfsFileLayer::Rename(std::string_view name) { + return false; +} + +std::string ReadOnlyVfsFileLayer::GetFullPath() const { + return base->GetFullPath(); +} + +ReadOnlyVfsDirectoryLayer::ReadOnlyVfsDirectoryLayer(VirtualDir base) : base(std::move(base)) {} + +ReadOnlyVfsDirectoryLayer::~ReadOnlyVfsDirectoryLayer() = default; + +std::vector> ReadOnlyVfsDirectoryLayer::GetFiles() const { + std::vector out; + const auto in = base->GetFiles(); + std::transform(in.begin(), in.end(), std::back_inserter(out), + [](const VirtualFile& i) { return std::make_shared(i); }); + return out; +} + +std::vector> ReadOnlyVfsDirectoryLayer::GetSubdirectories() const { + std::vector out; + const auto in = base->GetSubdirectories(); + std::transform(in.begin(), in.end(), std::back_inserter(out), [](const VirtualDir& i) { + return std::make_shared(i); + }); + return out; +} + +std::string ReadOnlyVfsDirectoryLayer::GetName() const { + return base->GetName(); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetParentDirectory() const { + return std::make_shared(base->GetParentDirectory()); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetFileRelative(std::string_view path) const { + return std::make_shared(base->GetFileRelative(path)); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetFileAbsolute(std::string_view path) const { + return std::make_shared(base->GetFileAbsolute(path)); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetDirectoryRelative( + std::string_view path) const { + return std::make_shared(base->GetDirectoryRelative(path)); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetDirectoryAbsolute( + std::string_view path) const { + return std::make_shared(base->GetDirectoryAbsolute(path)); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetFile(std::string_view name) const { + return std::make_shared(base->GetFile(name)); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::GetSubdirectory( + std::string_view name) const { + return std::make_shared(base->GetSubdirectory(name)); +} + +bool ReadOnlyVfsDirectoryLayer::IsRoot() const { + return base->IsRoot(); +} + +std::size_t ReadOnlyVfsDirectoryLayer::GetSize() const { + return base->GetSize(); +} + +bool ReadOnlyVfsDirectoryLayer::Copy(std::string_view src, std::string_view dest) { + return false; +} + +std::string ReadOnlyVfsDirectoryLayer::GetFullPath() const { + return base->GetFullPath(); +} + +bool ReadOnlyVfsDirectoryLayer::IsWritable() const { + return false; +} + +bool ReadOnlyVfsDirectoryLayer::IsReadable() const { + return base->IsReadable(); +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateSubdirectory(std::string_view name) { + return nullptr; +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateFile(std::string_view name) { + return nullptr; +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateFileAbsolute(std::string_view path) { + return nullptr; +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateFileRelative(std::string_view path) { + return nullptr; +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateDirectoryAbsolute( + std::string_view path) { + return nullptr; +} + +std::shared_ptr ReadOnlyVfsDirectoryLayer::CreateDirectoryRelative( + std::string_view path) { + return nullptr; +} + +bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectory(std::string_view name) { + return false; +} + +bool ReadOnlyVfsDirectoryLayer::DeleteSubdirectoryRecursive(std::string_view name) { + return false; +} + +bool ReadOnlyVfsDirectoryLayer::CleanSubdirectoryRecursive(std::string_view name) { + return false; +} + +bool ReadOnlyVfsDirectoryLayer::DeleteFile(std::string_view name) { + return false; +} + +bool ReadOnlyVfsDirectoryLayer::Rename(std::string_view name) { + return false; +} + +} // namespace FileSys \ No newline at end of file diff --git a/src/core/file_sys/vfs_ro_layer.h b/src/core/file_sys/vfs_ro_layer.h new file mode 100644 index 0000000000..b157d3effc --- /dev/null +++ b/src/core/file_sys/vfs_ro_layer.h @@ -0,0 +1,73 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "core/file_sys/vfs.h" + +namespace FileSys { + +// Class that wraps a VfsFile making it read-only +class ReadOnlyVfsFileLayer : public VfsFile { +public: + explicit ReadOnlyVfsFileLayer(VirtualFile base); + ~ReadOnlyVfsFileLayer() override; + + std::string GetName() const override; + std::size_t GetSize() const override; + bool Resize(std::size_t new_size) override; + std::shared_ptr GetContainingDirectory() const override; + bool IsWritable() const override; + bool IsReadable() const override; + std::size_t Read(u8* data, std::size_t length, std::size_t offset) const override; + std::size_t Write(const u8* data, std::size_t length, std::size_t offset) override; + bool Rename(std::string_view name) override; + + std::string GetFullPath() const override; + +private: + VirtualFile base; +}; + +// Class that wraps a VfsDirectory making it and its children read only. +class ReadOnlyVfsDirectoryLayer : public ReadOnlyVfsDirectory { +public: + explicit ReadOnlyVfsDirectoryLayer(VirtualDir base); + ~ReadOnlyVfsDirectoryLayer() override; + + std::vector> GetFiles() const override; + std::vector> GetSubdirectories() const override; + std::string GetName() const override; + std::shared_ptr GetParentDirectory() const override; + + std::shared_ptr GetFileRelative(std::string_view path) const override; + std::shared_ptr GetFileAbsolute(std::string_view path) const override; + std::shared_ptr GetDirectoryRelative(std::string_view path) const override; + std::shared_ptr GetDirectoryAbsolute(std::string_view path) const override; + std::shared_ptr GetFile(std::string_view name) const override; + std::shared_ptr GetSubdirectory(std::string_view name) const override; + bool IsRoot() const override; + std::size_t GetSize() const override; + bool Copy(std::string_view src, std::string_view dest) override; + std::string GetFullPath() const override; + bool IsWritable() const override; + bool IsReadable() const override; + std::shared_ptr CreateSubdirectory(std::string_view name) override; + std::shared_ptr CreateFile(std::string_view name) override; + std::shared_ptr CreateFileAbsolute(std::string_view path) override; + std::shared_ptr CreateFileRelative(std::string_view path) override; + std::shared_ptr CreateDirectoryAbsolute(std::string_view path) override; + std::shared_ptr CreateDirectoryRelative(std::string_view path) override; + bool DeleteSubdirectory(std::string_view name) override; + bool DeleteSubdirectoryRecursive(std::string_view name) override; + bool CleanSubdirectoryRecursive(std::string_view name) override; + bool DeleteFile(std::string_view name) override; + bool Rename(std::string_view name) override; + +private: + VirtualDir base; +}; + +} // namespace FileSys \ No newline at end of file diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 11e5c56b7a..7d9baefb30 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -722,8 +722,7 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove void InstallInterfaces(Core::System& system) { std::make_shared()->InstallAsService(system.ServiceManager()); std::make_shared()->InstallAsService(system.ServiceManager()); - std::make_shared(system.GetFileSystemController(), system.GetReporter()) - ->InstallAsService(system.ServiceManager()); + std::make_shared(system)->InstallAsService(system.ServiceManager()); } } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index cbd5466c12..9f9c3fe2d8 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -14,17 +14,22 @@ #include "common/hex_util.h" #include "common/logging/log.h" #include "common/string_util.h" +#include "core/file_sys/content_archive.h" #include "core/file_sys/directory.h" #include "core/file_sys/errors.h" #include "core/file_sys/mode.h" #include "core/file_sys/nca_metadata.h" #include "core/file_sys/patch_manager.h" +#include "core/file_sys/registered_cache.h" +#include "core/file_sys/romfs.h" #include "core/file_sys/romfs_factory.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/system_archive/system_archive.h" #include "core/file_sys/vfs.h" +#include "core/file_sys/vfs_ro_layer.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/process.h" +#include "core/hle/kernel/readable_event.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" #include "core/reporter.h" @@ -54,6 +59,12 @@ enum class FileSystemType : u8 { ApplicationPackage = 7, }; +enum class SaveDataOpenMode { + Normal, + ReadOnly, + System, +}; + class IStorage final : public ServiceFramework { public: explicit IStorage(FileSys::VirtualFile backend_) @@ -503,14 +514,17 @@ private: class ISaveDataInfoReader final : public ServiceFramework { public: - explicit ISaveDataInfoReader(FileSys::SaveDataSpaceId space, FileSystemController& fsc) + explicit ISaveDataInfoReader(FileSystemController& fsc, + std::vector spaces) : ServiceFramework("ISaveDataInfoReader"), fsc(fsc) { static const FunctionInfo functions[] = { {0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"}, }; RegisterHandlers(functions); - FindAllSaves(space); + for (const auto& space : spaces) { + FindAllSaves(space); + } } void ReadSaveDataInfo(Kernel::HLERequestContext& ctx) { @@ -650,8 +664,31 @@ private: u64 next_entry_index = 0; }; -FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) - : ServiceFramework("fsp-srv"), fsc(fsc), reporter(reporter) { +class IEventNotifier final : public ServiceFramework { +public: + explicit IEventNotifier(Kernel::SharedPtr event) + : ServiceFramework{"IEventNotifier"}, event(std::move(event)) { + static const FunctionInfo functions[] = { + {0, &IEventNotifier::GetEventHandle, "GetEventHandle"}, + }; + + RegisterHandlers(functions); + } + +private: + void GetEventHandle(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(event); + } + + Kernel::SharedPtr event; +}; + +FSP_SRV::FSP_SRV(Core::System& system) + : ServiceFramework("fsp-srv"), system(system), fsc(system.GetFileSystemController()) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenFileSystem"}, @@ -660,15 +697,15 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) {7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"}, {8, nullptr, "OpenFileSystemWithId"}, {9, nullptr, "OpenDataFileSystemByApplicationId"}, - {11, nullptr, "OpenBisFileSystem"}, - {12, nullptr, "OpenBisStorage"}, - {13, nullptr, "InvalidateBisCache"}, + {11, &FSP_SRV::OpenBisFileSystem, "OpenBisFileSystem"}, + {12, &FSP_SRV::OpenBisStorage, "OpenBisStorage"}, + {13, &FSP_SRV::InvalidateBisCache, "InvalidateBisCache"}, {17, nullptr, "OpenHostFileSystem"}, {18, &FSP_SRV::OpenSdCardFileSystem, "OpenSdCardFileSystem"}, {19, nullptr, "FormatSdCardFileSystem"}, {21, nullptr, "DeleteSaveDataFileSystem"}, {22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"}, - {23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"}, + {23, &FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId, "CreateSaveDataFileSystemBySystemSaveDataId"}, {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"}, {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"}, {26, nullptr, "FormatSdCardDryRun"}, @@ -681,12 +718,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) {34, nullptr, "GetCacheStorageSize"}, {35, nullptr, "CreateSaveDataFileSystemByHashSalt"}, {51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"}, - {52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"}, + {52, &FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId, "OpenSaveDataFileSystemBySystemSaveDataId"}, {53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"}, {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, {58, nullptr, "ReadSaveDataFileSystemExtraData"}, {59, nullptr, "WriteSaveDataFileSystemExtraData"}, - {60, nullptr, "OpenSaveDataInfoReader"}, + {60, &FSP_SRV::OpenSaveDataInfoReader, "OpenSaveDataInfoReader"}, {61, &FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId, "OpenSaveDataInfoReaderBySaveDataSpaceId"}, {62, nullptr, "OpenCacheStorageList"}, {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, @@ -699,8 +736,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) {82, nullptr, "OpenSaveDataTransferManagerVersion2"}, {83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"}, {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"}, - {100, nullptr, "OpenImageDirectoryFileSystem"}, - {110, nullptr, "OpenContentStorageFileSystem"}, + {100, &FSP_SRV::OpenImageDirectoryFileSystem, "OpenImageDirectoryFileSystem"}, + {110, &FSP_SRV::OpenContentStorageFileSystem, "OpenContentStorageFileSystem"}, {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"}, {130, nullptr, "OpenCustomStorageFileSystem"}, {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, @@ -710,8 +747,8 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) {204, nullptr, "OpenDataFileSystemByProgramIndex"}, {205, nullptr, "OpenDataStorageByProgramIndex"}, {400, nullptr, "OpenDeviceOperator"}, - {500, nullptr, "OpenSdCardDetectionEventNotifier"}, - {501, nullptr, "OpenGameCardDetectionEventNotifier"}, + {500, &FSP_SRV::OpenSdCardDetectionEventNotifier, "OpenSdCardDetectionEventNotifier"}, + {501, &FSP_SRV::OpenGameCardDetectionEventNotifier, "OpenGameCardDetectionEventNotifier"}, {510, nullptr, "OpenSystemDataUpdateEventNotifier"}, {511, nullptr, "NotifySystemDataUpdateEvent"}, {520, nullptr, "SimulateGameCardDetectionEvent"}, @@ -733,7 +770,7 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) {615, nullptr, "QuerySaveDataInternalStorageTotalSize"}, {616, nullptr, "GetSaveDataCommitId"}, {617, nullptr, "UnregisterExternalKey"}, - {620, nullptr, "SetSdCardEncryptionSeed"}, + {620, &FSP_SRV::SetSdCardEncryptionSeed, "SetSdCardEncryptionSeed"}, {630, nullptr, "SetSdCardAccessibility"}, {631, nullptr, "IsSdCardAccessible"}, {640, nullptr, "IsSignedSystemPartitionOnSdCardValid"}, @@ -762,6 +799,12 @@ FSP_SRV::FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter) }; // clang-format on RegisterHandlers(functions); + + auto& kernel{system.Kernel()}; + sd_card_detection_event = Kernel::WritableEvent::CreateEventPair( + kernel, Kernel::ResetType::Automatic, "fsp-srv:SdCardDetectionEvent"); + game_card_detection_event = Kernel::WritableEvent::CreateEventPair( + kernel, Kernel::ResetType::Automatic, "fsp-srv:GameCardDetectionEvent"); } FSP_SRV::~FSP_SRV() = default; @@ -781,11 +824,134 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) { const auto type = rp.PopRaw(); const auto title_id = rp.PopRaw(); - LOG_WARNING(Service_FS, "(STUBBED) called with type={}, title_id={:016X}", - static_cast(type), title_id); + LOG_DEBUG(Service_FS, "called with type={}, title_id={:016X}", static_cast(type), title_id); - IPC::ResponseBuilder rb{ctx, 2, 0, 0}; - rb.Push(ResultCode(-1)); + const auto& prov{system.GetContentProvider()}; + + FileSys::PatchManager pm{title_id}; + FileSys::ContentRecordType cr_type; + + switch (type) { + case FileSystemType::ApplicationPackage: + case FileSystemType::Logo: + cr_type = FileSys::ContentRecordType::Program; + break; + case FileSystemType::ContentControl: + cr_type = FileSys::ContentRecordType::Control; + break; + case FileSystemType::ContentManual: + cr_type = FileSys::ContentRecordType::HtmlDocument; + break; + case FileSystemType::ContentMeta: + cr_type = FileSys::ContentRecordType::Meta; + break; + case FileSystemType::ContentData: + cr_type = FileSys::ContentRecordType::Data; + break; + default: + LOG_WARNING(Service_FS, "called with invalid filesystem type!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_INVALID_ARGUMENT); + return; + } + + const auto& nca{prov.GetEntry(title_id, cr_type)}; + if (nca == nullptr) { + LOG_WARNING(Service_FS, "NCA requested doesn't exist in content provider!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_INVALID_ARGUMENT); + return; + } + + FileSys::VirtualDir dir; + + if (type == FileSystemType::ApplicationPackage) { + dir = nca->GetExeFS(); + if (dir != nullptr) + dir = pm.PatchExeFS(dir); + } else if (type == FileSystemType::Logo) { + dir = nca->GetSubdirectories()[1]; + } else if (type == FileSystemType::ContentControl || type == FileSystemType::ContentManual || + type == FileSystemType::ContentData) { + if (nca->GetRomFS() != nullptr) { + const auto romfs = pm.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), cr_type); + if (romfs != nullptr) + dir = FileSys::ExtractRomFS(romfs); + } + } else { + dir = nca->GetSubdirectories()[0]; + } + + if (dir == nullptr) { + LOG_WARNING(Service_FS, "couldn't get requested NCA section!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_INVALID_ARGUMENT); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::make_shared( + dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host))); +} + +void FSP_SRV::OpenBisFileSystem(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto partition = rp.PopRaw(); + + LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast(partition)); + + auto dir = fsc.OpenBISPartition(partition); + + if (dir.Failed()) { + LOG_ERROR(Service_FS, + "Failed to mount BIS filesystem for partition_id={:08X}! Could be invalid " + "argument or uninitialized system.", + static_cast(partition)); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(dir.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + + IFileSystem fs(dir.Unwrap(), SizeGetter::FromStorageId(fsc, FileSys::StorageId::Host)); + rb.PushIpcInterface(std::move(fs)); +} + +void FSP_SRV::OpenBisStorage(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto partition = rp.PopRaw(); + + LOG_DEBUG(Service_FS, "called with partition_id={:08X}", static_cast(partition)); + + auto file = fsc.OpenBISPartitionStorage(partition); + + if (file.Failed()) { + LOG_ERROR(Service_FS, + "Failed to mount BIS storage for partition_id={:08X}! Could be invalid " + "argument or uninitialized system.", + static_cast(partition)); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(file.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + + IStorage fs(file.Unwrap()); + rb.PushIpcInterface(std::move(fs)); +} + +void FSP_SRV::InvalidateBisCache(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + // Exists for SDK compatibility -- We do not emulate a BIS cache. + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); } void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { @@ -815,44 +981,103 @@ void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } -void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { - LOG_INFO(Service_FS, "called."); +void FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto save_struct = rp.PopRaw(); + auto save_create_struct = rp.PopRaw>(); + + LOG_DEBUG(Service_FS, "called save_struct = {}", save_struct.DebugInfo()); + + const auto dir = fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandSystem, save_struct); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(dir.Code()); +} + +namespace { + +FileSys::StorageId StorageFromSaveDataSpace(FileSys::SaveDataSpaceId space) { + switch (space) { + case FileSys::SaveDataSpaceId::NandSystem: + case FileSys::SaveDataSpaceId::ProperSystem: + case FileSys::SaveDataSpaceId::TemporaryStorage: + return FileSys::StorageId::NandSystem; + case FileSys::SaveDataSpaceId::NandUser: + return FileSys::StorageId::NandUser; + case FileSys::SaveDataSpaceId::SdCardSystem: + case FileSys::SaveDataSpaceId::SdCardUser: + return FileSys::StorageId::SdCard; + default: + return FileSys::StorageId::None; + } +} + +template +void OpenSaveDataFileSystemGeneric(Kernel::HLERequestContext& ctx, FileSystemController& fsc) { + IPC::RequestParser rp{ctx}; struct Parameters { FileSys::SaveDataSpaceId save_data_space_id; FileSys::SaveDataDescriptor descriptor; }; - IPC::RequestParser rp{ctx}; const auto parameters = rp.PopRaw(); - auto dir = fsc.OpenSaveData(parameters.save_data_space_id, parameters.descriptor); + if (dir.Failed()) { - IPC::ResponseBuilder rb{ctx, 2, 0, 0}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); return; } - FileSys::StorageId id; - if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::NandUser) { - id = FileSys::StorageId::NandUser; - } else if (parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardSystem || - parameters.save_data_space_id == FileSys::SaveDataSpaceId::SdCardUser) { - id = FileSys::StorageId::SdCard; - } else { - id = FileSys::StorageId::NandSystem; + auto diru = dir.Unwrap(); + + if (diru == nullptr) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); + return; } - IFileSystem filesystem(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id)); + if constexpr (mode == SaveDataOpenMode::ReadOnly) { + diru = std::make_shared(diru); + } + + IFileSystem filesystem( + std::move(diru), + SizeGetter::FromStorageId(fsc, StorageFromSaveDataSpace(parameters.save_data_space_id))); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(std::move(filesystem)); } +} // namespace + +void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { + OpenSaveDataFileSystemGeneric(ctx, fsc); +} + void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); - OpenSaveDataFileSystem(ctx); + OpenSaveDataFileSystemGeneric(ctx, fsc); +} + +void FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx) { + OpenSaveDataFileSystemGeneric(ctx, fsc); +} + +void FSP_SRV::OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface( + std::make_shared(fsc, std::vector{ + FileSys::SaveDataSpaceId::NandSystem, + FileSys::SaveDataSpaceId::NandUser, + FileSys::SaveDataSpaceId::TemporaryStorage, + FileSys::SaveDataSpaceId::SdCardUser, + })); } void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { @@ -862,7 +1087,64 @@ void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(std::make_shared(space, fsc)); + rb.PushIpcInterface( + std::make_shared(fsc, std::vector{space})); +} + +void FSP_SRV::OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto storage = rp.PopRaw(); + LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast(storage)); + + auto dir = fsc.GetImageDirectory(storage); + + if (dir == nullptr) { + LOG_ERROR(Service_FS, "The image directory requested was invalid!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_INVALID_ARGUMENT); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::make_shared( + std::move(dir), SizeGetter::FromStorageId(fsc, storage == ImageDirectoryId::NAND + ? FileSys::StorageId::NandUser + : FileSys::StorageId::SdCard))); +} + +void FSP_SRV::OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto storage = rp.PopRaw(); + + LOG_DEBUG(Service_FS, "called, storage={:08X}", static_cast(storage)); + + auto dir = fsc.GetContentDirectory(storage); + + if (dir == nullptr) { + LOG_ERROR(Service_FS, "The content storage requested was invalid!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(FileSys::ERROR_INVALID_ARGUMENT); + return; + } + + FileSys::StorageId storage_id = FileSys::StorageId::None; + switch (storage) { + case ContentStorageId::SdCard: + storage_id = FileSys::StorageId::SdCard; + break; + case ContentStorageId::User: + storage_id = FileSys::StorageId::NandUser; + break; + case ContentStorageId::System: + storage_id = FileSys::StorageId::NandSystem; + break; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface( + std::make_shared(std::move(dir), SizeGetter::FromStorageId(fsc, storage_id))); } void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { @@ -961,7 +1243,7 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called, log='{}'", log); - reporter.SaveFilesystemAccessReport(log_mode, std::move(log)); + system.GetReporter().SaveFilesystemAccessReport(log_mode, std::move(log)); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -976,4 +1258,30 @@ void FSP_SRV::GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx) { rb.Push(access_log_program_index); } +void FSP_SRV::OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::make_shared(sd_card_detection_event.readable)); +} + +void FSP_SRV::OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_FS, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::make_shared(game_card_detection_event.readable)); +} + +void FSP_SRV::SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto seed = rp.PopRaw(); + + LOG_INFO(Service_FS, "called with seed={:016X}{:016X}", seed[1], seed[0]); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index d52b55999a..ac1c3d1cf8 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -5,6 +5,7 @@ #pragma once #include +#include "core/hle/kernel/writable_event.h" #include "core/hle/service/service.h" namespace Core { @@ -32,17 +33,25 @@ enum class LogMode : u32 { class FSP_SRV final : public ServiceFramework { public: - explicit FSP_SRV(FileSystemController& fsc, const Core::Reporter& reporter); + explicit FSP_SRV(Core::System& system); ~FSP_SRV() override; private: void SetCurrentProcess(Kernel::HLERequestContext& ctx); void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx); + void OpenBisFileSystem(Kernel::HLERequestContext& ctx); + void OpenBisStorage(Kernel::HLERequestContext& ctx); + void InvalidateBisCache(Kernel::HLERequestContext& ctx); void OpenSdCardFileSystem(Kernel::HLERequestContext& ctx); void CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx); + void CreateSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx); void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx); + void OpenSaveDataFileSystemBySystemSaveDataId(Kernel::HLERequestContext& ctx); void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); + void OpenSaveDataInfoReader(Kernel::HLERequestContext& ctx); void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); + void OpenImageDirectoryFileSystem(Kernel::HLERequestContext& ctx); + void OpenContentStorageFileSystem(Kernel::HLERequestContext& ctx); void SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); @@ -50,7 +59,11 @@ private: void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx); void GetAccessLogVersionInfo(Kernel::HLERequestContext& ctx); + void OpenSdCardDetectionEventNotifier(Kernel::HLERequestContext& ctx); + void OpenGameCardDetectionEventNotifier(Kernel::HLERequestContext& ctx); + void SetSdCardEncryptionSeed(Kernel::HLERequestContext& ctx); + Core::System& system; FileSystemController& fsc; FileSys::VirtualFile romfs; @@ -58,7 +71,8 @@ private: u32 access_log_program_index = 0; LogMode log_mode = LogMode::LogToSdCard; - const Core::Reporter& reporter; + Kernel::EventPair sd_card_detection_event; + Kernel::EventPair game_card_detection_event; }; } // namespace Service::FileSystem