/* * 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 #include "fssrv_deferred_process_manager.hpp" namespace ams::fssrv { namespace { struct FileSystemProxyServerOptions { static constexpr size_t PointerBufferSize = 0x800; static constexpr size_t MaxDomains = 0x40; static constexpr size_t MaxDomainObjects = 0x4000; static constexpr bool CanDeferInvokeRequest = true; static constexpr bool CanManageMitmServers = false; }; enum PortIndex { PortIndex_FileSystemProxy, PortIndex_ProgramRegistry, PortIndex_FileSystemProxyForLoader, PortIndex_Count, }; constexpr size_t FileSystemProxyMaxSessions = 59; constexpr size_t ProgramRegistryMaxSessions = 1; constexpr size_t FileSystemProxyForLoaderMaxSessions = 1; constexpr size_t NumSessions = FileSystemProxyMaxSessions + ProgramRegistryMaxSessions + FileSystemProxyForLoaderMaxSessions; constinit os::SemaphoreType g_semaphore_for_file_system_proxy_for_loader = {}; constinit os::SemaphoreType g_semaphore_for_program_registry = {}; class FileSystemProxyServerManager final : public ams::sf::hipc::ServerManager { private: virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override { switch (port_index) { case PortIndex_FileSystemProxy: { R_RETURN(this->AcceptImpl(server, impl::GetFileSystemProxyServiceObject())); } case PortIndex_ProgramRegistry: { if (os::TryAcquireSemaphore(std::addressof(g_semaphore_for_program_registry))) { ON_RESULT_FAILURE { os::ReleaseSemaphore(std::addressof(g_semaphore_for_program_registry)); }; R_RETURN(this->AcceptImpl(server, impl::GetProgramRegistryServiceObject())); } else { R_RETURN(this->AcceptImpl(server, impl::GetInvalidProgramRegistryServiceObject())); } } case PortIndex_FileSystemProxyForLoader: { if (os::TryAcquireSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader))) { ON_RESULT_FAILURE { os::ReleaseSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader)); }; R_RETURN(this->AcceptImpl(server, impl::GetFileSystemProxyForLoaderServiceObject())); } else { R_RETURN(this->AcceptImpl(server, impl::GetInvalidFileSystemProxyForLoaderServiceObject())); } } AMS_UNREACHABLE_DEFAULT_CASE(); } } }; constinit util::TypedStorage g_server_manager_storage = {}; constinit FileSystemProxyServerManager *g_server_manager = nullptr; constinit os::BarrierType g_server_loop_barrier = {}; constinit os::EventType g_resume_wait_event = {}; constinit bool g_is_suspended = false; void TemporaryNotifyProcessDeferred(u64) { /* TODO */ } constinit DeferredProcessManager g_deferred_process_manager; } void InitializeForFileSystemProxy(const FileSystemProxyConfiguration &config) { /* TODO FS-REIMPL */ AMS_UNUSED(config); } void InitializeFileSystemProxyServer(int threads) { /* Initialize synchronization primitives. */ os::InitializeBarrier(std::addressof(g_server_loop_barrier), threads + 1); os::InitializeEvent(std::addressof(g_resume_wait_event), false, os::EventClearMode_ManualClear); g_is_suspended = false; os::InitializeSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader), 1, 1); os::InitializeSemaphore(std::addressof(g_semaphore_for_program_registry), 1, 1); /* Initialize deferred process manager. */ g_deferred_process_manager.Initialize(); /* Create the server and register our services. */ AMS_ASSERT(g_server_manager == nullptr); g_server_manager = util::ConstructAt(g_server_manager_storage); /* TODO: Manager handler. */ R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_FileSystemProxy, fs::impl::FileSystemProxyServiceName, FileSystemProxyMaxSessions)); R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_ProgramRegistry, fs::impl::ProgramRegistryServiceName, ProgramRegistryMaxSessions)); R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_FileSystemProxyForLoader, fs::impl::FileSystemProxyForLoaderServiceName, FileSystemProxyForLoaderMaxSessions)); /* Enable processing on server. */ g_server_manager->ResumeProcessing(); } }