From d64b7d7dfda8123cc8e0d6abaf358a4a08ba795c Mon Sep 17 00:00:00 2001 From: David Marcec Date: Tue, 16 Jan 2018 19:20:12 -0800 Subject: [PATCH] filesystem: Implement basic IStorage functionality. --- src/core/CMakeLists.txt | 4 + .../hle/service/filesystem/filesystem.cpp | 54 +++++++ src/core/hle/service/filesystem/filesystem.h | 41 ++++++ src/core/hle/service/filesystem/fsp_srv.cpp | 132 ++++++++++++++++++ src/core/hle/service/filesystem/fsp_srv.h | 25 ++++ src/core/hle/service/service.cpp | 2 + 6 files changed, 258 insertions(+) create mode 100644 src/core/hle/service/filesystem/filesystem.cpp create mode 100644 src/core/hle/service/filesystem/filesystem.h create mode 100644 src/core/hle/service/filesystem/fsp_srv.cpp create mode 100644 src/core/hle/service/filesystem/fsp_srv.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5ff1311a29..433e7e596b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -97,6 +97,10 @@ add_library(core STATIC hle/service/audio/audio.h hle/service/audio/audout_u.cpp hle/service/audio/audout_u.h + hle/service/filesystem/filesystem.cpp + hle/service/filesystem/filesystem.h + hle/service/filesystem/fsp_srv.cpp + hle/service/filesystem/fsp_srv.h hle/service/hid/hid.cpp hle/service/hid/hid.h hle/service/lm/lm.cpp diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp new file mode 100644 index 0000000000..4b47548fd3 --- /dev/null +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -0,0 +1,54 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include "core/file_sys/filesystem.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/fsp_srv.h" + +namespace Service { +namespace 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)); + + bool inserted = result.second; + ASSERT_MSG(inserted, "Tried to register more than one system with same id code"); + + auto& filesystem = result.first->second; + LOG_DEBUG(Service_FS, "Registered file system %s with id code 0x%08X", + filesystem->GetName().c_str(), static_cast(type)); + return RESULT_SUCCESS; +} + +ResultVal> OpenFileSystem(Type type, + FileSys::Path& path) { + LOG_TRACE(Service_FS, "Opening FileSystem with type=%d", type); + + auto itr = filesystem_map.find(type); + if (itr == filesystem_map.end()) { + // TODO(bunnei): Find a better error code for this + return ResultCode(-1); + } + + return itr->second->Open(path); +} + +void UnregisterFileSystems() { + filesystem_map.clear(); +} + +void InstallInterfaces(SM::ServiceManager& service_manager) { + UnregisterFileSystems(); + std::make_shared()->InstallAsService(service_manager); +} + +} // namespace FileSystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h new file mode 100644 index 0000000000..52db83e62e --- /dev/null +++ b/src/core/hle/service/filesystem/filesystem.h @@ -0,0 +1,41 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/file_sys/filesystem.h" +#include "core/hle/result.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace FileSystem { + +/// Supported FileSystem types +enum class Type { + RomFS = 1, +}; + +/** + * 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); + +/// Registers all Filesystem services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp new file mode 100644 index 0000000000..47a97f0fdb --- /dev/null +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -0,0 +1,132 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/core.h" +#include "core/file_sys/filesystem.h" +#include "core/file_sys/storage.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/client_session.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/filesystem/fsp_srv.h" + +namespace Service { +namespace FileSystem { + +class IStorage final : public ServiceFramework { +public: + IStorage(std::unique_ptr&& backend) + : ServiceFramework("IStorage"), backend(std::move(backend)) { + static const FunctionInfo functions[] = { + {0, &IStorage::Read, "Read"}, {1, &IStorage::Write, "Write"}, + {2, &IStorage::Flush, "Flush"}, {3, &IStorage::SetSize, "SetSize"}, + {4, &IStorage::GetSize, "GetSize"}, + }; + RegisterHandlers(functions); + } + +private: + std::unique_ptr backend; + + void Read(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u64 offset = rp.Pop(); + u64 length = rp.Pop(); + + LOG_DEBUG(Service, "called, offset=0x%llx, length=0x%llx", offset, length); + + auto descriptor = ctx.BufferDescriptorB()[0]; + std::vector output(length); + + ResultVal res = backend->Read(offset, length, output.data()); + if (res.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(res.Code()); + } + + Memory::WriteBlock(descriptor.Address(), output.data(), descriptor.Size()); + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void Write(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void Flush(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void SetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } + + void GetSize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); + } +}; + +FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { + static const FunctionInfo functions[] = { + {1, &FSP_SRV::Initalize, "Initalize"}, + {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, + {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, + {1005, &FSP_SRV::GetGlobalAccessLogMode, "GetGlobalAccessLogMode"}, + }; + RegisterHandlers(functions); +} + +void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(5); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { + FileSys::Path path; + auto filesystem = OpenFileSystem(Type::RomFS, path); + if (filesystem.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(filesystem.Code()); + return; + } + + auto storage = filesystem.Unwrap()->OpenFile({}, {}); + if (storage.Failed()) { + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(storage.Code()); + return; + } + + // TODO: What if already opened? + + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(std::move(storage.Unwrap())); + LOG_WARNING(Service, "(STUBBED) called"); +} + +void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { + OpenDataStorageByCurrentProcess(ctx); +} + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h new file mode 100644 index 0000000000..b41ba6bd17 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -0,0 +1,25 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace FileSystem { + +class FSP_SRV final : public ServiceFramework { +public: + FSP_SRV(); + ~FSP_SRV() = default; + +private: + void Initalize(Kernel::HLERequestContext& ctx); + void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); + void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); + void OpenRomStorage(Kernel::HLERequestContext& ctx); +}; + +} // namespace Filesystem +} // namespace Service diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 19213a2f40..3f5ce56c60 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -19,6 +19,7 @@ #include "core/hle/service/aoc/aoc_u.h" #include "core/hle/service/apm/apm.h" #include "core/hle/service/audio/audio.h" +#include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/hid/hid.h" #include "core/hle/service/lm/lm.h" #include "core/hle/service/nvdrv/nvdrv.h" @@ -172,6 +173,7 @@ void Init() { AOC::InstallInterfaces(*SM::g_service_manager); APM::InstallInterfaces(*SM::g_service_manager); Audio::InstallInterfaces(*SM::g_service_manager); + FileSystem::InstallInterfaces(*SM::g_service_manager); HID::InstallInterfaces(*SM::g_service_manager); LM::InstallInterfaces(*SM::g_service_manager); Nvidia::InstallInterfaces(*SM::g_service_manager);