From 69bfe075b5c3f6b17ce269950d1f8c9aab18e2de Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 17 Jul 2018 15:42:15 -0400 Subject: General Filesystem and Save Data Fixes (#670) --- src/core/hle/service/filesystem/filesystem.cpp | 77 ++++++++++++++--------- src/core/hle/service/filesystem/filesystem.h | 48 ++++++--------- src/core/hle/service/filesystem/fsp_srv.cpp | 85 ++++++++++++++++++-------- src/core/hle/service/filesystem/fsp_srv.h | 2 - 4 files changed, 125 insertions(+), 87 deletions(-) (limited to 'src/core/hle/service/filesystem') diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index f58b518b6..902256757 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -4,6 +4,7 @@ #include #include "common/file_util.h" +#include "core/file_sys/errors.h" #include "core/file_sys/filesystem.h" #include "core/file_sys/savedata_factory.h" #include "core/file_sys/sdmc_factory.h" @@ -16,57 +17,77 @@ namespace Service::FileSystem { * Map of registered file systems, identified by type. Once an file system is registered here, it * is never removed until UnregisterFileSystems is called. */ -static boost::container::flat_map> filesystem_map; - -ResultCode RegisterFileSystem(std::unique_ptr&& factory, Type type) { - auto result = filesystem_map.emplace(type, std::move(factory)); +static std::unique_ptr romfs_factory; +static std::unique_ptr save_data_factory; +static std::unique_ptr sdmc_factory; + +ResultCode RegisterRomFS(std::unique_ptr&& factory) { + ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second RomFS"); + romfs_factory = std::move(factory); + LOG_DEBUG(Service_FS, "Registered RomFS"); + return RESULT_SUCCESS; +} - bool inserted = result.second; - ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); +ResultCode RegisterSaveData(std::unique_ptr&& factory) { + ASSERT_MSG(romfs_factory == nullptr, "Tried to register a second save data"); + save_data_factory = std::move(factory); + LOG_DEBUG(Service_FS, "Registered save data"); + return RESULT_SUCCESS; +} - auto& filesystem = result.first->second; - LOG_DEBUG(Service_FS, "Registered file system {} with id code 0x{:08X}", filesystem->GetName(), - static_cast(type)); +ResultCode RegisterSDMC(std::unique_ptr&& factory) { + ASSERT_MSG(sdmc_factory == nullptr, "Tried to register a second SDMC"); + sdmc_factory = std::move(factory); + LOG_DEBUG(Service_FS, "Registered SDMC"); return RESULT_SUCCESS; } -ResultVal> OpenFileSystem(Type type, - FileSys::Path& path) { - LOG_TRACE(Service_FS, "Opening FileSystem with type={}", static_cast(type)); +ResultVal> OpenRomFS(u64 title_id) { + LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}", title_id); - auto itr = filesystem_map.find(type); - if (itr == filesystem_map.end()) { + if (romfs_factory == nullptr) { // TODO(bunnei): Find a better error code for this return ResultCode(-1); } - return itr->second->Open(path); + return romfs_factory->Open(title_id); } -ResultCode FormatFileSystem(Type type) { - LOG_TRACE(Service_FS, "Formatting FileSystem with type={}", static_cast(type)); +ResultVal> OpenSaveData( + FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct) { + LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", + static_cast(space), SaveStructDebugInfo(save_struct)); - auto itr = filesystem_map.find(type); - if (itr == filesystem_map.end()) { - // TODO(bunnei): Find a better error code for this - return ResultCode(-1); + if (save_data_factory == nullptr) { + return ResultCode(ErrorModule::FS, FileSys::ErrCodes::SaveDataNotFound); + } + + return save_data_factory->Open(space, save_struct); +} + +ResultVal> OpenSDMC() { + LOG_TRACE(Service_FS, "Opening SDMC"); + + if (sdmc_factory == nullptr) { + return ResultCode(ErrorModule::FS, FileSys::ErrCodes::SdCardNotFound); } - FileSys::Path unused; - return itr->second->Format(unused); + return sdmc_factory->Open(); } void RegisterFileSystems() { - filesystem_map.clear(); + romfs_factory = nullptr; + save_data_factory = nullptr; + sdmc_factory = nullptr; std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX); std::string sd_directory = FileUtil::GetUserPath(D_SDMC_IDX); - auto savedata = std::make_unique(std::move(nand_directory)); - RegisterFileSystem(std::move(savedata), Type::SaveData); + auto savedata = std::make_unique(std::move(nand_directory)); + save_data_factory = std::move(savedata); - auto sdcard = std::make_unique(std::move(sd_directory)); - RegisterFileSystem(std::move(sdcard), Type::SDMC); + auto sdcard = std::make_unique(std::move(sd_directory)); + sdmc_factory = std::move(sdcard); } void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 56d26146e..45272d326 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h @@ -6,12 +6,13 @@ #include #include "common/common_types.h" +#include "core/file_sys/romfs_factory.h" +#include "core/file_sys/savedata_factory.h" +#include "core/file_sys/sdmc_factory.h" #include "core/hle/result.h" namespace FileSys { class FileSystemBackend; -class FileSystemFactory; -class Path; } // namespace FileSys namespace Service { @@ -22,35 +23,20 @@ class ServiceManager; namespace FileSystem { -/// Supported FileSystem types -enum class Type { - RomFS = 1, - SaveData = 2, - SDMC = 3, -}; - -/** - * Registers a FileSystem, instances of which can later be opened using its IdCode. - * @param factory FileSystem backend interface to use - * @param type Type used to access this type of FileSystem - */ -ResultCode RegisterFileSystem(std::unique_ptr&& factory, Type type); - -/** - * Opens a file system - * @param type Type of the file system to open - * @param path Path to the file system, used with Binary paths - * @return FileSys::FileSystemBackend interface to the file system - */ -ResultVal> OpenFileSystem(Type type, - FileSys::Path& path); - -/** - * Formats a file system - * @param type Type of the file system to format - * @return ResultCode of the operation - */ -ResultCode FormatFileSystem(Type type); +ResultCode RegisterRomFS(std::unique_ptr&& factory); +ResultCode RegisterSaveData(std::unique_ptr&& factory); +ResultCode RegisterSDMC(std::unique_ptr&& factory); + +// TODO(DarkLordZach): BIS Filesystem +// ResultCode RegisterBIS(std::unique_ptr&& factory); + +ResultVal> OpenRomFS(u64 title_id); +ResultVal> OpenSaveData( + FileSys::SaveDataSpaceId space, FileSys::SaveDataDescriptor save_struct); +ResultVal> OpenSDMC(); + +// TODO(DarkLordZach): BIS Filesystem +// ResultVal> OpenBIS(); /// Registers all Filesystem services with the specified service manager. void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 82efe7f7d..22d3e645d 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -13,11 +13,21 @@ #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/filesystem/fsp_srv.h" namespace Service::FileSystem { +enum class StorageId : u8 { + None = 0, + Host = 1, + GameCard = 2, + NandSystem = 3, + NandUser = 4, + SdCard = 5 +}; + class IStorage final : public ServiceFramework { public: IStorage(std::unique_ptr&& backend) @@ -487,17 +497,6 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { RegisterHandlers(functions); } -void FSP_SRV::TryLoadRomFS() { - if (romfs) { - return; - } - FileSys::Path unused; - auto res = OpenFileSystem(Type::RomFS, unused); - if (res.Succeeded()) { - romfs = std::move(res.Unwrap()); - } -} - void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); @@ -508,8 +507,7 @@ void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - FileSys::Path unused; - auto filesystem = OpenFileSystem(Type::SDMC, unused).Unwrap(); + IFileSystem filesystem(OpenSDMC().Unwrap()); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); @@ -519,23 +517,26 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto save_struct = rp.PopRaw>(); + auto save_struct = rp.PopRaw(); auto save_create_struct = rp.PopRaw>(); u128 uid = rp.PopRaw(); - LOG_WARNING(Service_FS, "(STUBBED) called uid = {:016X}{:016X}", uid[1], uid[0]); + LOG_WARNING(Service_FS, "(STUBBED) called save_struct = {}, uid = {:016X}{:016X}", + save_struct.DebugInfo(), uid[1], uid[0]); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_FS, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + + auto space_id = rp.PopRaw(); + auto unk = rp.Pop(); + LOG_INFO(Service_FS, "called with unknown={:08X}", unk); + auto save_struct = rp.PopRaw(); - // TODO(Subv): Read the input parameters and mount the requested savedata instead of always - // mounting the current process' savedata. - FileSys::Path unused; - auto filesystem = OpenFileSystem(Type::SaveData, unused); + auto filesystem = OpenSaveData(space_id, save_struct); if (filesystem.Failed()) { IPC::ResponseBuilder rb{ctx, 2, 0, 0}; @@ -559,8 +560,8 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_FS, "called"); - TryLoadRomFS(); - if (!romfs) { + auto romfs = OpenRomFS(Core::System::GetInstance().CurrentProcess()->program_id); + if (romfs.Failed()) { // TODO (bunnei): Find the right error code to use here LOG_CRITICAL(Service_FS, "no file system interface available!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -568,8 +569,8 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { return; } - // Attempt to open a StorageBackend interface to the RomFS - auto storage = romfs->OpenFile({}, {}); + auto storage = romfs.Unwrap()->OpenFile({}, {}); + if (storage.Failed()) { LOG_CRITICAL(Service_FS, "no storage interface available!"); IPC::ResponseBuilder rb{ctx, 2}; @@ -583,8 +584,40 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { } void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_FS, "(STUBBED) called, using OpenDataStorageByCurrentProcess"); - OpenDataStorageByCurrentProcess(ctx); + IPC::RequestParser rp{ctx}; + + auto storage_id = rp.PopRaw(); + auto title_id = rp.PopRaw(); + + LOG_DEBUG(Service_FS, "called with storage_id={:02X}, title_id={:016X}", + static_cast(storage_id), title_id); + if (title_id != Core::System::GetInstance().CurrentProcess()->program_id) { + LOG_CRITICAL( + Service_FS, + "Attempting to access RomFS of another title id (current={:016X}, requested={:016X}).", + Core::System::GetInstance().CurrentProcess()->program_id, title_id); + } + + auto romfs = OpenRomFS(title_id); + if (romfs.Failed()) { + LOG_CRITICAL(Service_FS, "no file system interface available!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultCode(ErrorModule::FS, FileSys::ErrCodes::RomFSNotFound)); + return; + } + + auto storage = romfs.Unwrap()->OpenFile({}, {}); + + if (storage.Failed()) { + LOG_CRITICAL(Service_FS, "no storage interface available!"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(storage.Code()); + return; + } + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::move(storage.Unwrap())); } } // namespace Service::FileSystem diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index acb78fac1..4653eee4e 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -19,8 +19,6 @@ public: ~FSP_SRV() = default; private: - void TryLoadRomFS(); - void Initialize(Kernel::HLERequestContext& ctx); void MountSdCard(Kernel::HLERequestContext& ctx); void CreateSaveData(Kernel::HLERequestContext& ctx); -- cgit v1.2.3