From 30f975a558d03e83b1020bca0f577fdd3d997d2a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 30 Apr 2018 22:27:07 -0600 Subject: [PATCH] Stratosphere: Fix remaining bugs in sm, which now works as a KIP1 on hardware --- .../source/waitablemanager.cpp | 17 +++---- stratosphere/sm/source/sm_main.cpp | 2 +- stratosphere/sm/source/sm_manager_service.cpp | 1 - stratosphere/sm/source/sm_registration.cpp | 48 +++++++------------ stratosphere/sm/source/sm_registration.hpp | 2 +- stratosphere/sm/source/sm_user_service.cpp | 5 +- 6 files changed, 30 insertions(+), 45 deletions(-) diff --git a/stratosphere/libstratosphere/source/waitablemanager.cpp b/stratosphere/libstratosphere/source/waitablemanager.cpp index 32db56cfc..bc80e27e4 100644 --- a/stratosphere/libstratosphere/source/waitablemanager.cpp +++ b/stratosphere/libstratosphere/source/waitablemanager.cpp @@ -40,14 +40,8 @@ void WaitableManager::process() { handles.resize(signalables.size()); std::transform(signalables.begin(), signalables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); }); - unsigned int num_not_deferred = 0; - for (auto & signalable : signalables) { - if (!signalable->get_deferred()) { - num_not_deferred++; - } - } - rc = svcWaitSynchronization(&handle_index, handles.data(), num_not_deferred, this->timeout); + rc = svcWaitSynchronization(&handle_index, handles.data(), signalables.size(), this->timeout); if (R_SUCCEEDED(rc)) { /* Handle a signaled waitable. */ /* TODO: What timeout should be passed here? */ @@ -82,12 +76,19 @@ void WaitableManager::process() { delete signalables[handle_index]; } + /* If relevant, remove from signalables. */ + signalables.erase(std::remove(signalables.begin(), signalables.end(), signalables[handle_index]), signalables.end()); + for (int i = 0; i < handle_index; i++) { signalables[i]->update_priority(); } } /* Do deferred callback for each waitable. */ - std::for_each(signalables.begin() + num_not_deferred, signalables.end(), [](IWaitable *w) { w->handle_deferred(); }); + for (auto & waitable : signalables) { + if (waitable->get_deferred()) { + waitable->handle_deferred(); + } + } } } \ No newline at end of file diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 6a20fa4f1..21c526565 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -48,7 +48,7 @@ void __appExit(void) { int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - + /* TODO: What's a good timeout value to use here? */ WaitableManager *server_manager = new WaitableManager(U64_MAX); diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index d21236040..49247ec5c 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -4,7 +4,6 @@ Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; - switch ((ManagerServiceCmd)cmd_id) { case Manager_Cmd_RegisterProcess: rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 400fffa9d..a6483cbe9 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -6,6 +6,15 @@ static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0}; static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0}; +u64 GetServiceNameLength(u64 service) { + u64 service_name_len = 0; + while (service & 0xFF) { + service_name_len++; + service >>= 8; + } + return service_name_len; +} + /* Utilities. */ Registration::Process *Registration::GetProcessForPid(u64 pid) { for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_PROCESS; i++) { @@ -162,13 +171,10 @@ Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) { return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -191,13 +197,10 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -240,13 +243,10 @@ Result Registration::RegisterServiceForSelf(u64 service, u64 max_sessions, bool return rc; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -276,27 +276,13 @@ Result Registration::UnregisterServiceForPid(u64 pid, u64 service) { return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } - if (pid >= REGISTRATION_PID_BUILTIN_MAX) { - Registration::Process *proc = GetProcessForPid(pid); - if (proc == NULL) { - return 0x415; - } - - if (!IsValidForSac(proc->sac, proc->sac_size, service, true)) { - return 0x1015; - } - } - Registration::Service *target_service = GetService(service); if (target_service == NULL) { return 0xE15; diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 2a19be857..7ac0f0f89 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -4,7 +4,7 @@ #define REGISTRATION_LIST_MAX_PROCESS (0x40) #define REGISTRATION_LIST_MAX_SERVICE (0x100) #define REGISTRATION_MAX_SAC_SIZE (0x200) -#define REGISTRATION_PID_BUILTIN_MAX 0x7 +#define REGISTRATION_PID_BUILTIN_MAX 0x50 class Registration { public: diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index f57f45858..f05070c3d 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -4,8 +4,7 @@ #include "sm_registration.hpp" Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - + Result rc = 0xF601; switch ((UserServiceCmd)cmd_id) { case User_Cmd_Initialize: rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size); @@ -27,7 +26,7 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, Result UserService::handle_deferred() { /* If we're deferred, GetService failed. */ - return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service); + return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);; }