diff --git a/libraries/libstratosphere/include/stratosphere/fssrv.hpp b/libraries/libstratosphere/include/stratosphere/fssrv.hpp index 56183d68a..79fcd2bff 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv.hpp @@ -31,4 +31,5 @@ #include #include #include +#include #include diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp index 3b4c0e2e2..58b1b0e79 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_file_system_proxy_impl.hpp @@ -27,12 +27,16 @@ namespace ams::fssrv { } + class NcaFileSystemService; + class SaveDataFileSystemService; + class FileSystemProxyImpl { NON_COPYABLE(FileSystemProxyImpl); NON_MOVEABLE(FileSystemProxyImpl); private: impl::FileSystemProxyCoreImpl *m_impl; - /* TODO: service pointers. */ + std::shared_ptr m_nca_service; + std::shared_ptr m_save_data_service; u64 m_process_id; public: FileSystemProxyImpl(); diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_impl.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_impl.hpp index 5a5b0ba07..7d79a1322 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_impl.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_impl.hpp @@ -19,6 +19,8 @@ namespace ams::fssrv { + class ProgramRegistryServiceImpl; + namespace impl { class ProgramInfo; @@ -33,6 +35,8 @@ namespace ams::fssrv { public: ProgramRegistryImpl(); ~ProgramRegistryImpl(); + public: + static void Initialize(ProgramRegistryServiceImpl *service); public: Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const ams::sf::InBuffer &data, s64 data_size, const ams::sf::InBuffer &desc, s64 desc_size); Result UnregisterProgram(u64 process_id); diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_service.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_service.hpp new file mode 100644 index 000000000..284b264e8 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_program_registry_service.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include + +namespace ams::fssrv { + + namespace impl { + + class ProgramInfo; + class ProgramRegistryManager; + class ProgramIndexMapInfoManager; + + } + + class ProgramRegistryServiceImpl { + public: + struct Configuration { + /* ... */ + }; + private: + Configuration m_config; + fssystem::Pimpl m_registry_manager; + fssystem::Pimpl m_index_map_info_manager; + public: + ProgramRegistryServiceImpl(const Configuration &cfg) : m_config(cfg) { /* ... */ } + + Result RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size); + Result UnregisterProgramInfo(u64 process_id); + }; + +} diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp index 34b2c3fff..3973cb23e 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv/impl/fssrv_impl_program_index_map_info_manager.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace ams::fssrv::impl { @@ -156,3 +157,5 @@ namespace ams::fssrv::impl { } + +AMS_FSSYSTEM_ENABLE_PIMPL(::ams::fssrv::impl::ProgramIndexMapInfoManager) diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_pimpl.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_pimpl.hpp new file mode 100644 index 000000000..c007a94f1 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_pimpl.hpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::fssystem { + + namespace impl { + + template + struct PimplHelper { + static void Construct(void *); + static void Destroy(void *); + }; + + } + + template + class Pimpl { + private: + alignas(0x10) u8 m_storage[Size]; + public: + ALWAYS_INLINE Pimpl() { impl::PimplHelper::Construct(m_storage); } + ALWAYS_INLINE ~Pimpl() { impl::PimplHelper::Destroy(m_storage); } + + ALWAYS_INLINE T *Get() { return reinterpret_cast(m_storage + 0); } + ALWAYS_INLINE T *operator->() { return reinterpret_cast(m_storage + 0); } + }; + + #define AMS_FSSYSTEM_ENABLE_PIMPL(_CLASSNAME_) \ + namespace ams::fssystem::impl { \ + \ + template \ + struct PimplHelper<_CLASSNAME_, Size> { \ + static ALWAYS_INLINE void Construct(void *p) { \ + static_assert(sizeof(_CLASSNAME_) <= Size); \ + static_assert(alignof(_CLASSNAME_) <= 0x10); \ + \ + std::construct_at(static_cast<_CLASSNAME_ *>(p)); \ + } \ + \ + static ALWAYS_INLINE void Destroy(void *p) { \ + std::destroy_at(static_cast<_CLASSNAME_ *>(p)); \ + } \ + }; \ + \ + } + +} diff --git a/libraries/libstratosphere/source/fssrv/fssrv_file_system_proxy_impl.cpp b/libraries/libstratosphere/source/fssrv/fssrv_file_system_proxy_impl.cpp new file mode 100644 index 000000000..90e3b0abb --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/fssrv_file_system_proxy_impl.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "impl/fssrv_program_info.hpp" + +namespace ams::fssrv { + + FileSystemProxyImpl::FileSystemProxyImpl() { + /* TODO: Set core impl. */ + m_process_id = os::InvalidProcessId.value; + } + + FileSystemProxyImpl::~FileSystemProxyImpl() { + /* ... */ + } + + Result FileSystemProxyImpl::OpenCodeFileSystemDeprecated(ams::sf::Out> out_fs, const fssrv::sf::Path &path, ncm::ProgramId program_id) { + AMS_ABORT("TODO"); + AMS_UNUSED(out_fs, path, program_id); + } + + Result FileSystemProxyImpl::OpenCodeFileSystem(ams::sf::Out> out_fs, ams::sf::Out out_verif, const fssrv::sf::Path &path, ncm::ProgramId program_id) { + AMS_ABORT("TODO"); + AMS_UNUSED(out_fs, out_verif, path, program_id); + } + + Result FileSystemProxyImpl::IsArchivedProgram(ams::sf::Out out, u64 process_id) { + AMS_ABORT("TODO"); + AMS_UNUSED(out, process_id); + } + + Result FileSystemProxyImpl::SetCurrentProcess(const ams::sf::ClientProcessId &client_pid) { + /* Set current process. */ + m_process_id = client_pid.GetValue().value; + + /* TODO: Allocate NcaFileSystemService. */ + AMS_ABORT("TODO"); + } + +} diff --git a/libraries/libstratosphere/source/fssrv/fssrv_program_registry_impl.cpp b/libraries/libstratosphere/source/fssrv/fssrv_program_registry_impl.cpp new file mode 100644 index 000000000..aeb96cd00 --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/fssrv_program_registry_impl.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "impl/fssrv_program_info.hpp" + +namespace ams::fssrv { + + namespace { + + constinit ProgramRegistryServiceImpl *g_impl = nullptr; + + } + + ProgramRegistryImpl::ProgramRegistryImpl() : m_process_id(os::InvalidProcessId.value) { + /* ... */ + } + + ProgramRegistryImpl::~ProgramRegistryImpl() { + /* ... */ + } + + void ProgramRegistryImpl::Initialize(ProgramRegistryServiceImpl *service) { + /* Check pre-conditions. */ + AMS_ASSERT(g_impl != nullptr); + AMS_ASSERT(g_impl == nullptr); + + /* Set the global service. */ + g_impl = service; + } + + Result ProgramRegistryImpl::RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const ams::sf::InBuffer &data, s64 data_size, const ams::sf::InBuffer &desc, s64 desc_size) { + /* Check pre-conditions. */ + AMS_ASSERT(g_impl != nullptr); + + /* Check that we're allowed to register. */ + R_UNLESS(fssrv::impl::IsInitialProgram(m_process_id), fs::ResultPermissionDenied()); + + /* Check buffer sizes. */ + R_UNLESS(data.GetSize() >= static_cast(data_size), fs::ResultInvalidSize()); + R_UNLESS(desc.GetSize() >= static_cast(desc_size), fs::ResultInvalidSize()); + + /* Register the program. */ + return g_impl->RegisterProgramInfo(process_id, program_id, storage_id, data.GetPointer(), data_size, desc.GetPointer(), desc_size); + } + + Result ProgramRegistryImpl::UnregisterProgram(u64 process_id) { + /* Check pre-conditions. */ + AMS_ASSERT(g_impl != nullptr); + + /* Check that we're allowed to register. */ + R_UNLESS(fssrv::impl::IsInitialProgram(m_process_id), fs::ResultPermissionDenied()); + + /* Unregister the program. */ + return g_impl->UnregisterProgramInfo(process_id); + } + + Result ProgramRegistryImpl::SetCurrentProcess(const ams::sf::ClientProcessId &client_pid) { + /* Set our process id. */ + m_process_id = client_pid.GetValue().value; + + return ResultSuccess(); + } + + Result ProgramRegistryImpl::SetEnabledProgramVerification(bool en) { + /* TODO: How to deal with this backwards compat? */ + AMS_ABORT("TODO: SetEnabledProgramVerification"); + AMS_UNUSED(en); + } + +} diff --git a/libraries/libstratosphere/source/fssrv/fssrv_program_registry_service.cpp b/libraries/libstratosphere/source/fssrv/fssrv_program_registry_service.cpp new file mode 100644 index 000000000..6694c61c0 --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/fssrv_program_registry_service.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "impl/fssrv_program_info.hpp" + +namespace ams::fssrv { + + Result ProgramRegistryServiceImpl::RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) { + AMS_ABORT("TODO"); + AMS_UNUSED(process_id, program_id, storage_id, data, data_size, desc, desc_size); + } + + Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) { + AMS_ABORT("TODO"); + AMS_UNUSED(process_id); + } + +} diff --git a/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.cpp b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.cpp new file mode 100644 index 000000000..f3ae2889f --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "fssrv_program_info.hpp" + +namespace ams::fssrv::impl { + + namespace { + + constinit os::SdkMutex g_mutex; + constinit bool g_initialized = false; + + constinit u64 g_initial_process_id_min = 0; + constinit u64 g_initial_process_id_max = 0; + + constinit u64 g_current_process_id = 0; + + ALWAYS_INLINE void InitializeInitialAndCurrentProcessId() { + if (AMS_UNLIKELY(!g_initialized)) { + std::scoped_lock lk(g_mutex); + if (AMS_LIKELY(!g_initialized)) { + /* Get initial process id range. */ + R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_min), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Minimum)); + R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_max), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Maximum)); + + AMS_ABORT_UNLESS(0 < g_initial_process_id_min); + AMS_ABORT_UNLESS(g_initial_process_id_min <= g_initial_process_id_max); + + /* Get current procss id. */ + R_ABORT_UNLESS(svc::GetProcessId(std::addressof(g_current_process_id), svc::PseudoHandle::CurrentProcess)); + + /* Set initialized. */ + g_initialized = true; + } + } + } + + } + + bool IsInitialProgram(u64 process_id) { + /* Initialize/sanity check. */ + InitializeInitialAndCurrentProcessId(); + AMS_ABORT_UNLESS(g_initial_process_id_min > 0); + + /* Check process id in range. */ + return g_initial_process_id_min <= process_id && process_id <= g_initial_process_id_max; + } + + bool IsCurrentProcess(u64 process_id) { + /* Initialize. */ + InitializeInitialAndCurrentProcessId(); + + return process_id == g_current_process_id; + } + +} diff --git a/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.hpp b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.hpp new file mode 100644 index 000000000..fe445b96d --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_info.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::fssrv::impl { + + class ProgramInfo : public ::ams::fs::impl::Newable { + private: + u64 m_process_id; + ncm::ProgramId m_program_id; + ncm::StorageId m_storage_id; + /* TODO: AccessControl m_access_control; */ + public: + ProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) : m_process_id(process_id) /* TODO: m_access_control */ { + m_program_id.value = program_id; + m_storage_id = static_cast(storage_id); + + /* TODO */ + AMS_UNUSED(data, data_size, desc, desc_size); + } + }; + + struct ProgramInfoNode : public util::IntrusiveListBaseNode, public ::ams::fs::impl::Newable { + std::shared_ptr program_info; + }; + + bool IsInitialProgram(u64 process_id); + bool IsCurrentProcess(u64 process_id); + +} diff --git a/libraries/libstratosphere/source/fssrv/impl/fssrv_program_registry_manager.hpp b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_registry_manager.hpp new file mode 100644 index 000000000..0f2f7f3de --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/impl/fssrv_program_registry_manager.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include "fssrv_program_info.hpp" + +namespace ams::fssrv::impl { + + class ProgramRegistryManager { + NON_COPYABLE(ProgramRegistryManager); + NON_MOVEABLE(ProgramRegistryManager); + private: + using ProgramInfoList = util::IntrusiveListBaseTraits::ListType; + private: + ProgramInfoList m_program_info_list{}; + os::SdkMutex m_mutex{}; + public: + constexpr ProgramRegistryManager() = default; + + Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size); + Result UnregisterProgram(u64 process_id); + + Result GetProgramInfo(std::shared_ptr *out, u64 process_id); + Result GetProgramInfoByProgramId(std::shared_ptr *out, u64 program_id); + }; + +} + +AMS_FSSYSTEM_ENABLE_PIMPL(::ams::fssrv::impl::ProgramRegistryManager); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp b/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp index f93d1e6b6..3aafb281d 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp @@ -14,6 +14,7 @@ * along with this program. If not, see . */ #include +#include "../fssrv/impl/fssrv_program_registry_manager.hpp" namespace ams::fssystem { @@ -22,7 +23,7 @@ namespace ams::fssystem { namespace { - constexpr inline auto FileSystemProxyServerThreadCount = 5; + constexpr inline auto FileSystemProxyServerThreadCount = fssrv::FileSystemProxyServerActiveSessionCount; /* TODO: Heap sizes need to match FS, when this is FS in master rather than ams.mitm. */ @@ -152,6 +153,8 @@ namespace ams::fssystem { }; /* TODO FS-REIMPL: Revise above for latest firmware, all the new Services creation. */ + fssrv::ProgramRegistryServiceImpl program_registry_service(fssrv::ProgramRegistryServiceImpl::Configuration{}); + fssrv::ProgramRegistryImpl::Initialize(std::addressof(program_registry_service)); /* TODO FS-REIMPL: Memory Report Creators, fssrv::SetMemoryReportCreator */ @@ -166,7 +169,7 @@ namespace ams::fssystem { fs::SetEnabledAutoAbort(false); /* Initialize fsp server. */ - fssrv::InitializeFileSystemProxyServer(fssrv::FileSystemProxyServerActiveSessionCount); + fssrv::InitializeFileSystemProxyServer(FileSystemProxyServerThreadCount); /* TODO FS-REIMPL: Cleanup calls. */