diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index eaa47001a..113b3d6bb 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -8,6 +8,7 @@ #include "sm_manager_service.hpp" #include "sm_user_service.hpp" +#include "sm_registration.hpp" extern "C" { extern u32 __start__; @@ -41,8 +42,7 @@ void __appInit(void) { } void __appExit(void) { - /* Disconnect from ourselves. */ - smExit(); + /* Nothing to clean up, because we're sm. */ } int main(int argc, char **argv) @@ -55,11 +55,13 @@ int main(int argc, char **argv) /* Create sm:, (and thus allow things to register to it). */ server_manager->add_waitable(new ManagedPortServer("sm:", 0x40)); - /* Initialize, connecting to ourself. */ - smInitialize(); + /* Create sm:m manually. */ + Handle smm_h; + if (R_FAILED(Registration::RegisterServiceForSelf(smEncodeName("sm:m"), 1, false, &smm_h))) { + /* TODO: Panic. */ + } - /* Create sm:m, using libnx to talk to ourself. */ - server_manager->add_waitable(new ServiceServer("sm:m", 1)); + server_manager->add_waitable(new ExistingPortServer(smm_h, 1)); /* Loop forever, servicing our services. */ server_manager->process(); diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index b52157002..013bd4db0 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -221,6 +221,44 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session return rc; } +Result Registration::RegisterServiceForSelf(u64 service, u64 max_sessions, bool is_light, Handle *out) { + u64 pid; + Result rc = svcGetProcessId(&pid, CUR_PROCESS_HANDLE); + if (R_FAILED(rc)) { + return rc; + } + + u64 service_name_len = 0; + while ((service >> (8 * service_name_len)) & 0xFF) { + service_name_len++; + } + + /* If the service has bytes after a null terminator, that's no good. */ + if ((service >> (8 * service_name_len))) { + return 0xC15; + } + + if (HasService(service)) { + return 0x815; + } + + Registration::Service *free_service = GetFreeService(); + if (free_service == NULL) { + return 0xA15; + } + + *out = 0; + *free_service = (const Registration::Service){0}; + rc = svcCreatePort(out, &free_service->port_h, max_sessions, is_light, (char *)&free_service->service_name); + + if (R_SUCCEEDED(rc)) { + free_service->service_name = service; + free_service->owner_pid = pid; + } + + return rc; +} + Result Registration::UnregisterServiceForPid(u64 pid, u64 service) { if (!service) { return 0xC15; diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 8b15a97eb..17d984ebd 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -36,5 +36,6 @@ class Registration { static bool HasService(u64 service); static Result GetServiceForPid(u64 pid, u64 service, Handle *out); static Result RegisterServiceForPid(u64 pid, u64 service, u64 max_sessions, bool is_light, Handle *out); + static Result RegisterServiceForSelf(u64 service, u64 max_sessions, bool is_light, Handle *out); static Result UnregisterServiceForPid(u64 pid, u64 service); };