diff --git a/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp b/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp index 587e59cc2..0c53af706 100644 --- a/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp +++ b/libraries/libstratosphere/include/stratosphere/sf/impl/sf_impl_autogen_interface_macros.hpp @@ -122,9 +122,9 @@ namespace ams::sf::impl { template \ concept Is##CLASSNAME = CMD_MACRO(CLASSNAME, AMS_SF_IMPL_CHECK_CONCEPT_HELPER) true; - #define AMS_SF_DEFINE_INTERFACE_IMPL(BASECLASS, CLASSNAME, CMD_MACRO) \ - AMS_SF_IMPL_DEFINE_INTERFACE(::ams::sf::IServiceObject, CLASSNAME, CMD_MACRO) \ - AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \ + #define AMS_SF_DEFINE_INTERFACE_IMPL(BASECLASS, CLASSNAME, CMD_MACRO) \ + AMS_SF_IMPL_DEFINE_INTERFACE(BASECLASS, CLASSNAME, CMD_MACRO) \ + AMS_SF_IMPL_DEFINE_CONCEPT(CLASSNAME, CMD_MACRO) \ static_assert(Is##CLASSNAME); #define AMS_SF_METHOD_INFO_7(CLASSNAME, HANDLER, CMD_ID, RETURN, NAME, ARGS, ARGNAMES) \ diff --git a/stratosphere/sm/source/sm_debug_monitor_service.hpp b/stratosphere/sm/source/sm_debug_monitor_service.hpp index 9b405e769..3efff18a2 100644 --- a/stratosphere/sm/source/sm_debug_monitor_service.hpp +++ b/stratosphere/sm/source/sm_debug_monitor_service.hpp @@ -20,7 +20,7 @@ namespace ams::sm { /* Service definition. */ - class DebugMonitorService final { + class DebugMonitorService { public: Result AtmosphereGetRecord(sf::Out record, ServiceName service); void AtmosphereListRecords(const sf::OutArray &records, sf::Out out_count, u64 offset); diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 4afd2a2e1..e03ae38ee 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -25,7 +25,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x4000 + #define INNER_HEAP_SIZE 0x0 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -83,9 +83,37 @@ void __appExit(void) { namespace { - /* sm:m, sm:, sm:dmnt. */ - constexpr size_t NumServers = 3; - sf::hipc::ServerManager g_server_manager; + enum PortIndex { + PortIndex_User, + PortIndex_Manager, + PortIndex_DebugMonitor, + PortIndex_Count, + }; + + class ServerManager final : public sf::hipc::ServerManager { + private: + virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override; + }; + + using Allocator = sf::ExpHeapAllocator; + using ObjectFactory = sf::ObjectFactory; + + alignas(0x40) constinit u8 g_server_allocator_buffer[8_KB]; + Allocator g_server_allocator; + + ServerManager g_server_manager; + + ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) { + switch (port_index) { + case PortIndex_User: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(std::addressof(g_server_allocator))); + case PortIndex_Manager: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(std::addressof(g_server_allocator))); + case PortIndex_DebugMonitor: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(std::addressof(g_server_allocator))); + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } ams::Result ResumeImpl(os::WaitableHolderType *session_holder) { return g_server_manager.Process(session_holder); @@ -93,24 +121,35 @@ namespace { } +void *operator new(size_t size) { + AMS_ABORT("operator new(size_t) was called"); +} + +void operator delete(void *p) { + AMS_ABORT("operator delete(void *) was called"); +} + int main(int argc, char **argv) { /* Set thread name. */ os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(sm, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(sm, Main)); + /* Setup server allocator. */ + g_server_allocator.Attach(lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None)); + /* Create sm:, (and thus allow things to register to it). */ { Handle sm_h; R_ABORT_UNLESS(svc::ManageNamedPort(&sm_h, "sm:", 0x40)); - g_server_manager.RegisterServer(sm_h); + g_server_manager.RegisterServer(PortIndex_User, sm_h); } /* Create sm:m manually. */ { Handle smm_h; R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smm_h, sm::ServiceName::Encode("sm:m"), 1)); - g_server_manager.RegisterServer(smm_h); + g_server_manager.RegisterServer(PortIndex_Manager, smm_h); sm::impl::TestAndResume(ResumeImpl); } @@ -119,7 +158,7 @@ int main(int argc, char **argv) { Handle smdmnt_h; R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smdmnt_h, sm::ServiceName::Encode("sm:dmnt"), 1)); - g_server_manager.RegisterServer(smdmnt_h); + g_server_manager.RegisterServer(PortIndex_DebugMonitor, smdmnt_h); sm::impl::TestAndResume(ResumeImpl); } diff --git a/stratosphere/sm/source/sm_manager_service.hpp b/stratosphere/sm/source/sm_manager_service.hpp index 1906c1824..db400ddd9 100644 --- a/stratosphere/sm/source/sm_manager_service.hpp +++ b/stratosphere/sm/source/sm_manager_service.hpp @@ -19,7 +19,7 @@ namespace ams::sm { /* Service definition. */ - class ManagerService final { + class ManagerService { public: Result RegisterProcess(os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac); Result UnregisterProcess(os::ProcessId process_id); diff --git a/stratosphere/sm/source/sm_user_service.hpp b/stratosphere/sm/source/sm_user_service.hpp index 8dd22d6b8..544a7ca11 100644 --- a/stratosphere/sm/source/sm_user_service.hpp +++ b/stratosphere/sm/source/sm_user_service.hpp @@ -20,7 +20,7 @@ namespace ams::sm { /* Service definition. */ - class UserService final { + class UserService { private: os::ProcessId process_id = os::InvalidProcessId; bool has_initialized = false; diff --git a/stratosphere/spl/source/spl_deprecated_service.hpp b/stratosphere/spl/source/spl_deprecated_service.hpp index b7c03291b..96b2f5c53 100644 --- a/stratosphere/spl/source/spl_deprecated_service.hpp +++ b/stratosphere/spl/source/spl_deprecated_service.hpp @@ -18,7 +18,7 @@ namespace ams::spl { - class DeprecatedService final { + class DeprecatedService { public: virtual ~DeprecatedService(); public: diff --git a/stratosphere/spl/source/spl_main.cpp b/stratosphere/spl/source/spl_main.cpp index bcf7c7179..40275d122 100644 --- a/stratosphere/spl/source/spl_main.cpp +++ b/stratosphere/spl/source/spl_main.cpp @@ -31,7 +31,7 @@ extern "C" { u32 __nx_applet_type = AppletType_None; - #define INNER_HEAP_SIZE 0x2000 + #define INNER_HEAP_SIZE 0x0 size_t nx_inner_heap_size = INNER_HEAP_SIZE; char nx_inner_heap[INNER_HEAP_SIZE]; @@ -95,13 +95,22 @@ namespace { static constexpr size_t MaxDomainObjects = 0; }; + enum PortIndex { + PortIndex_General, + PortIndex_Random, + PortIndex_Crypto, + PortIndex_Fs, + PortIndex_Ssl, + PortIndex_Es, + PortIndex_Manu, + PortIndex_Count, + }; + constexpr sm::ServiceName RandomServiceName = sm::ServiceName::Encode("csrng"); constexpr size_t RandomMaxSessions = 3; - constexpr sm::ServiceName DeprecatedServiceName = sm::ServiceName::Encode("spl:"); - constexpr size_t DeprecatedMaxSessions = 13; - constexpr sm::ServiceName GeneralServiceName = sm::ServiceName::Encode("spl:"); + constexpr size_t DeprecatedMaxSessions = 13; constexpr size_t GeneralMaxSessions = 7; constexpr sm::ServiceName CryptoServiceName = sm::ServiceName::Encode("spl:mig"); @@ -121,11 +130,64 @@ namespace { /* csrng, spl:, spl:mig, spl:ssl, spl:es, spl:fs, spl:manu. */ /* TODO: Consider max sessions enforcement? */ - constexpr size_t NumServers = 7; constexpr size_t ModernMaxSessions = GeneralMaxSessions + CryptoMaxSessions + SslMaxSessions + EsMaxSessions + FsMaxSessions + ManuMaxSessions; constexpr size_t NumSessions = RandomMaxSessions + std::max(DeprecatedMaxSessions, ModernMaxSessions) + 1; - sf::hipc::ServerManager g_server_manager; + class ServerManager final : public sf::hipc::ServerManager { + private: + sf::ExpHeapAllocator *m_allocator; + spl::GeneralService m_general_service; + sf::UnmanagedServiceObjectByPointer m_general_service_object; + spl::RandomService m_random_service; + sf::UnmanagedServiceObjectByPointer m_random_service_object; + public: + ServerManager(sf::ExpHeapAllocator *allocator) : m_allocator(allocator), m_general_service(), m_general_service_object(std::addressof(m_general_service)), m_random_service(), m_random_service_object(std::addressof(m_random_service)) { + /* ... */ + } + private: + virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override; + }; + + using Allocator = sf::ExpHeapAllocator; + using ObjectFactory = sf::ObjectFactory; + + alignas(0x40) constinit u8 g_server_allocator_buffer[8_KB]; + Allocator g_server_allocator; + + ServerManager g_server_manager(std::addressof(g_server_allocator)); + + ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) { + switch (port_index) { + case PortIndex_General: + if (hos::GetVersion() >= hos::Version_4_0_0) { + return this->AcceptImpl(server, m_general_service_object.GetShared()); + } else { + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + } + case PortIndex_Random: + return this->AcceptImpl(server, m_random_service_object.GetShared()); + case PortIndex_Crypto: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + case PortIndex_Fs: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + case PortIndex_Ssl: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + case PortIndex_Es: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + case PortIndex_Manu: + return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced(m_allocator)); + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + +} + +void *operator new(size_t size) { + AMS_ABORT("operator new(size_t) was called"); +} + +void operator delete(void *p) { + AMS_ABORT("operator delete(void *) was called"); } int main(int argc, char **argv) @@ -134,22 +196,24 @@ int main(int argc, char **argv) os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(spl, Main)); AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(spl, Main)); + /* Setup server allocator. */ + g_server_allocator.Attach(lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None)); + /* Initialize global context. */ spl::impl::Initialize(); /* Create services. */ - R_ABORT_UNLESS((g_server_manager.RegisterServer(RandomServiceName, RandomMaxSessions))); - if (hos::GetVersion() >= hos::Version_4_0_0) { - R_ABORT_UNLESS((g_server_manager.RegisterServer(GeneralServiceName, GeneralMaxSessions))); - R_ABORT_UNLESS((g_server_manager.RegisterServer(CryptoServiceName, CryptoMaxSessions))); - R_ABORT_UNLESS((g_server_manager.RegisterServer(SslServiceName, SslMaxSessions))); - R_ABORT_UNLESS((g_server_manager.RegisterServer(EsServiceName, EsMaxSessions))); - R_ABORT_UNLESS((g_server_manager.RegisterServer(FsServiceName, FsMaxSessions))); - if (hos::GetVersion() >= hos::Version_5_0_0) { - R_ABORT_UNLESS((g_server_manager.RegisterServer(ManuServiceName, ManuMaxSessions))); + const auto fw_ver = hos::GetVersion(); + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_General, GeneralServiceName, fw_ver >= hos::Version_4_0_0 ? GeneralMaxSessions : DeprecatedMaxSessions)); + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Random, RandomServiceName, RandomMaxSessions)); + if (fw_ver >= hos::Version_4_0_0) { + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Crypto, CryptoServiceName, CryptoMaxSessions)); + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Fs, FsServiceName, FsMaxSessions)); + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Ssl, SslServiceName, SslMaxSessions)); + R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Es, EsServiceName, EsMaxSessions)); + if (fw_ver >= hos::Version_5_0_0) { + g_server_manager.RegisterServer(PortIndex_Manu, ManuServiceName, ManuMaxSessions); } - } else { - R_ABORT_UNLESS((g_server_manager.RegisterServer(DeprecatedServiceName, DeprecatedMaxSessions))); } /* Loop forever, servicing our services. */