From 30e401d125bb8acc0369fdc1d880186d722f9207 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 18 Apr 2018 23:00:10 -0600 Subject: [PATCH] Stratosphere: Add Registration Management to Loader --- .../loader/source/ldr_debug_monitor.cpp | 10 +- .../loader/source/ldr_launch_queue.cpp | 106 +++++++++--------- .../loader/source/ldr_launch_queue.hpp | 29 ++--- .../loader/source/ldr_registration.cpp | 80 +++++++++++++ .../loader/source/ldr_registration.hpp | 43 +++++++ stratosphere/loader/source/ldr_shell.cpp | 9 +- 6 files changed, 197 insertions(+), 80 deletions(-) create mode 100644 stratosphere/loader/source/ldr_registration.cpp create mode 100644 stratosphere/loader/source/ldr_registration.hpp diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index 2bdebbb80..17ebf25cd 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -6,11 +6,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, IpcCommand *out_c, u32 *cmd_buf, u32 cmd_id, u32 *in_rawdata, u32 in_rawdata_size, u32 *out_rawdata, u32 *out_raw_data_count) { Result rc = 0xF601; - - fprintf(stderr, "TLS: %p\n", armGetTls()); - - /* TODO: Prepare SFCO. */ - + switch ((DebugMonitorServiceCmd)cmd_id) { case Dmnt_Cmd_AddTitleToLaunchQueue: /* Validate arguments. */ @@ -25,7 +21,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, IpcCommand *out_c, u32 rc = add_title_to_launch_queue(((u64 *)in_rawdata)[0], (const char *)r->Statics[0], r->StaticSizes[0]); - *out_raw_data_count = 4; + *out_raw_data_count = 0; break; case Dmnt_Cmd_ClearLaunchQueue: @@ -34,7 +30,7 @@ Result DebugMonitorService::dispatch(IpcParsedCommand *r, IpcCommand *out_c, u32 } rc = clear_launch_queue(); - *out_raw_data_count = 4; + *out_raw_data_count = 0; break; case Dmnt_Cmd_GetNsoInfo: diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index 38e51a170..7f51ad9fe 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -3,67 +3,61 @@ #include #include "ldr_launch_queue.hpp" +static LaunchQueue::LaunchItem g_launch_queue[LAUNCH_QUEUE_SIZE] = {0}; -namespace LaunchQueue { - static LaunchItem g_launch_queue[LAUNCH_QUEUE_SIZE]; - - Result add(u64 tid, const char *args, u64 arg_size) { - if(arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { - return 0x209; - } - - int idx = get_free_index(tid); - if(idx == LAUNCH_QUEUE_FULL) - return 0x409; - - g_launch_queue[idx].tid = tid; - g_launch_queue[idx].arg_size = arg_size; - - fprintf(stderr, "TID: %016llx, args: %p, size: %016llx\n", tid, args, arg_size); - fprintf(stderr, "Args: %s\n", args); - - std::copy(args, args + arg_size, g_launch_queue[idx].args); - return 0x0; +Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) { + if(arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { + return 0x209; } - Result add_item(const LaunchItem *item) { - if(item->arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { - return 0x209; - } - - int idx = get_free_index(item->tid); - if(idx == LAUNCH_QUEUE_FULL) - return 0x409; - - g_launch_queue[idx] = *item; - return 0x0; + int idx = get_free_index(tid); + if(idx == LAUNCH_QUEUE_FULL) + return 0x409; + + g_launch_queue[idx].tid = tid; + g_launch_queue[idx].arg_size = arg_size; + + std::copy(args, args + arg_size, g_launch_queue[idx].args); + return 0x0; +} + +Result LaunchQueue::add_item(const LaunchItem *item) { + if(item->arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { + return 0x209; } - int get_index(u64 tid) { - for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { - if(g_launch_queue[i].tid == tid) { - return i; - } - } - return LAUNCH_QUEUE_FULL; - } + int idx = get_free_index(item->tid); + if(idx == LAUNCH_QUEUE_FULL) + return 0x409; - int get_free_index(u64 tid) { - for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { - if(g_launch_queue[i].tid == tid || g_launch_queue[i].tid == 0x0) { - return i; - } - } - return LAUNCH_QUEUE_FULL; - } - - bool contains(u64 tid) { - return get_index(tid) != LAUNCH_QUEUE_FULL; - } - - void clear() { - for (unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { - g_launch_queue[i].tid = 0; + g_launch_queue[idx] = *item; + return 0x0; +} + +int LaunchQueue::get_index(u64 tid) { + for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { + if(g_launch_queue[i].tid == tid) { + return i; } } -} \ No newline at end of file + return LAUNCH_QUEUE_FULL; +} + +int LaunchQueue::get_free_index(u64 tid) { + for(unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { + if(g_launch_queue[i].tid == tid || g_launch_queue[i].tid == 0x0) { + return i; + } + } + return LAUNCH_QUEUE_FULL; +} + +bool LaunchQueue::contains(u64 tid) { + return get_index(tid) != LAUNCH_QUEUE_FULL; +} + +void LaunchQueue::clear() { + for (unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) { + g_launch_queue[i].tid = 0; + } +} diff --git a/stratosphere/loader/source/ldr_launch_queue.hpp b/stratosphere/loader/source/ldr_launch_queue.hpp index 720a76c25..6876e98d6 100644 --- a/stratosphere/loader/source/ldr_launch_queue.hpp +++ b/stratosphere/loader/source/ldr_launch_queue.hpp @@ -6,17 +6,18 @@ #define LAUNCH_QUEUE_ARG_SIZE_MAX (0x8000) -namespace LaunchQueue { - struct LaunchItem { - u64 tid; - u64 arg_size; - char args[LAUNCH_QUEUE_ARG_SIZE_MAX]; - }; - - Result add(u64 tid, const char *args, u64 arg_size); - Result add_item(const LaunchItem *item); - int get_index(u64 tid); - int get_free_index(u64 tid); - bool contains(u64 tid); - void clear(); -} \ No newline at end of file +class LaunchQueue { + public: + struct LaunchItem { + u64 tid; + u64 arg_size; + char args[LAUNCH_QUEUE_ARG_SIZE_MAX]; + }; + + static Result add(u64 tid, const char *args, u64 arg_size); + static Result add_item(const LaunchItem *item); + static int get_index(u64 tid); + static int get_free_index(u64 tid); + static bool contains(u64 tid); + static void clear(); +}; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp new file mode 100644 index 000000000..c860af713 --- /dev/null +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -0,0 +1,80 @@ +#include +#include +#include +#include "ldr_registration.hpp" + +static Registration::List g_registration_list = {0}; +static u64 g_num_registered = 1; + +Registration::Process *get_free_process() { + unsigned int i; + for (i = 0; i < REGISTRATION_LIST_MAX; i++) { + if (!g_registration_list.processes[i].in_use) { + return &g_registration_list.processes[i]; + } + } + return NULL; +} + +Registration::Process *get_process(u64 index) { + unsigned int i; + for (i = 0; !g_registration_list.processes[i].in_use || g_registration_list.processes[i].index != index; i++) { + if (i >= REGISTRATION_LIST_MAX) { + return NULL; + } + } + return &g_registration_list.processes[i]; +} + +bool Registration::register_tid_sid(const TidSid *tid_sid, u64 *out_index) { + Registration::Process *free_process = get_free_process(); + if (free_process == NULL) { + return false; + } + + /* Reset the process. */ + *free_process = {0}; + free_process->tid_sid = *tid_sid; + free_process->in_use = true; + free_process->index = g_num_registered++; + *out_index = free_process->index; + return true; +} + +bool Registration::unregister_index(u64 index) { + Registration::Process *target_process = get_process(index); + if (target_process == NULL) { + return false; + } + + /* Reset the process. */ + *target_process = {0}; + return true; +} + +void Registration::set_process_id_and_tid_min(u64 index, u64 process_id, u64 tid_min) { + Registration::Process *target_process = get_process(index); + if (target_process == NULL) { + return; + } + + target_process->process_id = process_id; + target_process->title_id_min = tid_min; +} + +void Registration::add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id) { + Registration::Process *target_process = get_process(index); + if (target_process == NULL) { + return; + } + + for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { + if (!target_process->nso_infos[i].in_use) { + target_process->nso_infos[i].base_address = base_address; + target_process->nso_infos[i].size = size; + std::copy(build_id, build_id + sizeof(target_process->nso_infos[i].build_id), target_process->nso_infos[i].build_id); + target_process->nso_infos[i].in_use = true; + return; + } + } +} \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp new file mode 100644 index 000000000..fc5774422 --- /dev/null +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -0,0 +1,43 @@ +#pragma once +#include + +#define REGISTRATION_LIST_MAX (0x40) + +#define NSO_INFO_MAX (0x20) + +class Registration { + public: + struct NsoInfo { + bool in_use; + u64 base_address; + u64 size; + unsigned char build_id[0x20]; + }; + + struct TidSid { + u64 title_id; + FsStorageId storage_id; + }; + + struct Process { + bool in_use; + u64 index; + u64 process_id; + u64 title_id_min; + Registration::TidSid tid_sid; + Registration::NsoInfo nso_infos[NSO_INFO_MAX]; + u64 _0x730; + }; + + struct List { + Registration::Process processes[REGISTRATION_LIST_MAX]; + u64 num_processes; + }; + + static Registration::Process *get_free_process(); + static Registration::Process *get_process(u64 index); + static bool register_tid_sid(const TidSid *tid_sid, u64 *out_index); + static bool unregister_index(u64 index); + static void set_process_id_and_tid_min(u64 index, u64 process_id, u64 tid_min); + static void add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id); +}; diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index f89977c0d..ae3116e1e 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -5,9 +5,7 @@ Result ShellService::dispatch(IpcParsedCommand *r, IpcCommand *out_c, u32 *cmd_buf, u32 cmd_id, u32 *in_rawdata, u32 in_rawdata_size, u32 *out_rawdata, u32 *out_raw_data_count) { Result rc = 0xF601; - - /* TODO: Prepare SFCO. */ - + switch ((ShellServiceCmd)cmd_id) { case Cmd_AddTitleToLaunchQueue: /* Validate arguments. */ @@ -15,6 +13,11 @@ Result ShellService::dispatch(IpcParsedCommand *r, IpcCommand *out_c, u32 *cmd_b break; } + if (r->Statics[0] == NULL) { + rc = 0xCE01; + break; + } + rc = add_title_to_launch_queue(((u64 *)in_rawdata)[0], (const char *)r->Statics[0], r->StaticSizes[0]); *out_raw_data_count = 0;