Stratosphere: Fix remaining bugs in sm, which now works as a KIP1 on hardware

This commit is contained in:
Michael Scire 2018-04-30 22:27:07 -06:00
parent 52730d2188
commit 30f975a558
6 changed files with 30 additions and 45 deletions

View file

@ -40,14 +40,8 @@ void WaitableManager::process() {
handles.resize(signalables.size()); handles.resize(signalables.size());
std::transform(signalables.begin(), signalables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); }); 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)) { if (R_SUCCEEDED(rc)) {
/* Handle a signaled waitable. */ /* Handle a signaled waitable. */
/* TODO: What timeout should be passed here? */ /* TODO: What timeout should be passed here? */
@ -82,12 +76,19 @@ void WaitableManager::process() {
delete signalables[handle_index]; 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++) { for (int i = 0; i < handle_index; i++) {
signalables[i]->update_priority(); signalables[i]->update_priority();
} }
} }
/* Do deferred callback for each waitable. */ /* 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();
}
}
} }
} }

View file

@ -48,7 +48,7 @@ void __appExit(void) {
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
consoleDebugInit(debugDevice_SVC); consoleDebugInit(debugDevice_SVC);
/* TODO: What's a good timeout value to use here? */ /* TODO: What's a good timeout value to use here? */
WaitableManager *server_manager = new WaitableManager(U64_MAX); WaitableManager *server_manager = new WaitableManager(U64_MAX);

View file

@ -4,7 +4,6 @@
Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601; Result rc = 0xF601;
switch ((ManagerServiceCmd)cmd_id) { switch ((ManagerServiceCmd)cmd_id) {
case Manager_Cmd_RegisterProcess: case Manager_Cmd_RegisterProcess:
rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);

View file

@ -6,6 +6,15 @@
static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0}; static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0};
static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {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. */ /* Utilities. */
Registration::Process *Registration::GetProcessForPid(u64 pid) { Registration::Process *Registration::GetProcessForPid(u64 pid) {
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_PROCESS; i++) { 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; return 0xC15;
} }
u64 service_name_len = 0; u64 service_name_len = GetServiceNameLength(service);
while ((service >> (8 * service_name_len)) & 0xFF) {
service_name_len++;
}
/* If the service has bytes after a null terminator, that's no good. */ /* 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; return 0xC15;
} }
@ -191,13 +197,10 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session
return 0xC15; return 0xC15;
} }
u64 service_name_len = 0; u64 service_name_len = GetServiceNameLength(service);
while ((service >> (8 * service_name_len)) & 0xFF) {
service_name_len++;
}
/* If the service has bytes after a null terminator, that's no good. */ /* 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; return 0xC15;
} }
@ -240,13 +243,10 @@ Result Registration::RegisterServiceForSelf(u64 service, u64 max_sessions, bool
return rc; return rc;
} }
u64 service_name_len = 0; u64 service_name_len = GetServiceNameLength(service);
while ((service >> (8 * service_name_len)) & 0xFF) {
service_name_len++;
}
/* If the service has bytes after a null terminator, that's no good. */ /* 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; return 0xC15;
} }
@ -276,27 +276,13 @@ Result Registration::UnregisterServiceForPid(u64 pid, u64 service) {
return 0xC15; return 0xC15;
} }
u64 service_name_len = 0; u64 service_name_len = GetServiceNameLength(service);
while ((service >> (8 * service_name_len)) & 0xFF) {
service_name_len++;
}
/* If the service has bytes after a null terminator, that's no good. */ /* 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; 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); Registration::Service *target_service = GetService(service);
if (target_service == NULL) { if (target_service == NULL) {
return 0xE15; return 0xE15;

View file

@ -4,7 +4,7 @@
#define REGISTRATION_LIST_MAX_PROCESS (0x40) #define REGISTRATION_LIST_MAX_PROCESS (0x40)
#define REGISTRATION_LIST_MAX_SERVICE (0x100) #define REGISTRATION_LIST_MAX_SERVICE (0x100)
#define REGISTRATION_MAX_SAC_SIZE (0x200) #define REGISTRATION_MAX_SAC_SIZE (0x200)
#define REGISTRATION_PID_BUILTIN_MAX 0x7 #define REGISTRATION_PID_BUILTIN_MAX 0x50
class Registration { class Registration {
public: public:

View file

@ -4,8 +4,7 @@
#include "sm_registration.hpp" #include "sm_registration.hpp"
Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { 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) { switch ((UserServiceCmd)cmd_id) {
case User_Cmd_Initialize: case User_Cmd_Initialize:
rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size); 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() { Result UserService::handle_deferred() {
/* If we're deferred, GetService failed. */ /* 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);;
} }