Atmosphere/libraries/libstratosphere/source/fssrv/fssrv_file_system_proxy_api.cpp

125 lines
5.8 KiB
C++

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include <stratosphere/fs/impl/fs_service_name.hpp>
#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<PortIndex_Count, FileSystemProxyServerOptions, NumSessions> {
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<FileSystemProxyServerManager> 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<FileSystemProxyServerManager, TemporaryNotifyProcessDeferred> 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();
}
}