loader: add SetExtraMemory extension

This commit is contained in:
misson20000 2018-10-05 16:41:00 -07:00
parent 187691f79c
commit b9570b0959
6 changed files with 62 additions and 2 deletions

View file

@ -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);
}
```

View file

@ -23,6 +23,12 @@
static std::array<LaunchQueue::LaunchItem, LAUNCH_QUEUE_SIZE> 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;
}
}

View file

@ -39,4 +39,8 @@ class LaunchQueue {
static int get_free_index(u64 tid);
static bool contains(u64 tid);
static void clear();
};
// extra memory extension
static void set_extra_memory(u64 tid, u64 extra_size);
static u64 get_extra_memory(u64 tid);
};

View file

@ -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;

View file

@ -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<Result> ShellService::clear_launch_queue(u64 dat) {
LaunchQueue::clear();
return {0};
}
std::tuple<Result> 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};
}

View file

@ -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<Result> add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args);
std::tuple<Result> clear_launch_queue(u64 dat);
/* Atmosphere commands. */
std::tuple<Result> set_extra_memory(u64 tid, u64 extra_size);
};