From b9570b0959e77285d550555fa1f269c5278902a2 Mon Sep 17 00:00:00 2001 From: misson20000 Date: Fri, 5 Oct 2018 16:41:00 -0700 Subject: [PATCH] loader: add SetExtraMemory extension --- docs/modules/loader.md | 12 +++++++++ .../loader/source/ldr_launch_queue.cpp | 25 +++++++++++++++++++ .../loader/source/ldr_launch_queue.hpp | 6 ++++- .../loader/source/ldr_process_creation.cpp | 5 ++++ stratosphere/loader/source/ldr_shell.cpp | 9 +++++++ stratosphere/loader/source/ldr_shell.hpp | 7 +++++- 6 files changed, 62 insertions(+), 2 deletions(-) diff --git a/docs/modules/loader.md b/docs/modules/loader.md index 954873bb4..2c23a7d39 100644 --- a/docs/modules/loader.md +++ b/docs/modules/loader.md @@ -62,3 +62,15 @@ TODO ### SM MITM Integration When the Stratosphere implementation of loader creates a new process, it notifies [sm](sm.md) through the `AtmosphereAssociatePidTidForMitm` command to notify any MITM services of new processes' identities. + +### IPC: AtmosphereSetExtraMemory + +This command is added to the [`ldr:shel`](https://reswitched.github.io/SwIPC/ifaces.html#nn::ro::detail::ILdrShellInterface) interface, and allows a client to request that a title be created with a certain amount of additional CodeStatic memory the next time it is created. This is useful for advanced homebrew loaders. + +The SwIPC definition for this command follows. +``` +interface nn::ldr::detail::ILdrShellInterface is ldr:shel { + ... + [65000] AtmosphereSetExtraMemory(u64 title_id, u64 extra_memory_size); +} +``` diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index 8fda8585b..de5f4103f 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -23,6 +23,12 @@ static std::array g_launch_queue = {0}; +/* This state is maintained separately from the launch queue so that + NS can't clobber this information by clearing the launch queue + when the process using this extension doesn't expect it. */ +static u64 g_extra_memory_tid = 0; +static u64 g_extra_memory_size = 0; + Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) { if(arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { return 0x209; @@ -97,3 +103,22 @@ LaunchQueue::LaunchItem *LaunchQueue::get_item(u64 tid) { } return &g_launch_queue[idx]; } + +void LaunchQueue::set_extra_memory(u64 tid, u64 extra_size) { + g_extra_memory_tid = tid; + g_extra_memory_size = extra_size; +} + +u64 LaunchQueue::get_extra_memory(u64 tid) { + if(tid == g_extra_memory_tid) { + u64 size = g_extra_memory_size; + + // reset extra memory state + g_extra_memory_tid = 0; + g_extra_memory_size = 0; + + return size; + } else { + return 0; + } +} diff --git a/stratosphere/loader/source/ldr_launch_queue.hpp b/stratosphere/loader/source/ldr_launch_queue.hpp index 74a2a03c9..57de94ea4 100644 --- a/stratosphere/loader/source/ldr_launch_queue.hpp +++ b/stratosphere/loader/source/ldr_launch_queue.hpp @@ -39,4 +39,8 @@ class LaunchQueue { static int get_free_index(u64 tid); static bool contains(u64 tid); static void clear(); -}; \ No newline at end of file + + // extra memory extension + static void set_extra_memory(u64 tid, u64 extra_size); + static u64 get_extra_memory(u64 tid); +}; diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index 40d9d716d..8abdb997a 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -172,6 +172,11 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc if (R_FAILED(rc)) { goto CREATE_PROCESS_END; } + + nso_extents.total_size += 0xFFF; + nso_extents.total_size &= ~0xFFFULL; + + nso_extents.total_size += LaunchQueue::get_extra_memory(target_process->tid_sid.title_id); /* Set Address Space information in ProcessInfo. */ process_info.code_addr = nso_extents.base_address; diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 664388d08..bfeae6ee0 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -30,6 +30,9 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id case Shell_Cmd_ClearLaunchQueue: rc = WrapIpcCommandImpl<&ShellService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size); break; + case Shell_Cmd_AtmosphereSetExtraMemory: + rc = WrapIpcCommandImpl<&ShellService::set_extra_memory>(this, r, out_c, pointer_buffer, pointer_buffer_size); + break; default: break; } @@ -46,3 +49,9 @@ std::tuple ShellService::clear_launch_queue(u64 dat) { LaunchQueue::clear(); return {0}; } + +std::tuple ShellService::set_extra_memory(u64 tid, u64 extra_size) { + fprintf(stderr, "Set extra memory for %zX: %zX\n", tid, extra_size); + LaunchQueue::set_extra_memory(tid, extra_size); + return {0}; +} diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 7cc95f858..ef1a81178 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -20,7 +20,9 @@ enum ShellServiceCmd { Shell_Cmd_AddTitleToLaunchQueue = 0, - Shell_Cmd_ClearLaunchQueue = 1 + Shell_Cmd_ClearLaunchQueue = 1, + + Shell_Cmd_AtmosphereSetExtraMemory = 65000, }; class ShellService final : public IServiceObject { @@ -39,4 +41,7 @@ class ShellService final : public IServiceObject { /* Actual commands. */ std::tuple add_title_to_launch_queue(u64 args_size, u64 tid, InPointer args); std::tuple clear_launch_queue(u64 dat); + + /* Atmosphere commands. */ + std::tuple set_extra_memory(u64 tid, u64 extra_size); };