mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
loader: update for libstratosphere refactor
This commit is contained in:
parent
8b71378920
commit
c49cfbd6af
12 changed files with 150 additions and 272 deletions
|
@ -56,6 +56,9 @@
|
|||
"svcReplyAndReceiveLight" : "0x42",
|
||||
"svcReplyAndReceive" : "0x43",
|
||||
"svcReplyAndReceiveWithUserBuffer" : "0x44",
|
||||
"svcCreateEvent": "0x45",
|
||||
"svcReadWriteRegister" : "0x4E",
|
||||
"svcQueryIoMapping": "0x55",
|
||||
"svcSetProcessMemoryPermission" : "0x73",
|
||||
"svcMapProcessMemory" : "0x74",
|
||||
"svcUnmapProcessMemory" : "0x75",
|
||||
|
|
|
@ -22,42 +22,18 @@
|
|||
#include "ldr_launch_queue.hpp"
|
||||
#include "ldr_registration.hpp"
|
||||
|
||||
Result DebugMonitorService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||
Result rc = 0xF601;
|
||||
|
||||
switch ((DebugMonitorServiceCmd)cmd_id) {
|
||||
case Dmnt_Cmd_AddTitleToLaunchQueue:
|
||||
rc = WrapIpcCommandImpl<&DebugMonitorService::add_title_to_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Dmnt_Cmd_ClearLaunchQueue:
|
||||
rc = WrapIpcCommandImpl<&DebugMonitorService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Dmnt_Cmd_GetNsoInfo:
|
||||
rc = WrapIpcCommandImpl<&DebugMonitorService::get_nso_info>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::tuple<Result> DebugMonitorService::add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args) {
|
||||
Result DebugMonitorService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) {
|
||||
fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements));
|
||||
return {LaunchQueue::add(tid, args.pointer, std::min(args_size, args.num_elements))};
|
||||
return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements));
|
||||
}
|
||||
|
||||
std::tuple<Result> DebugMonitorService::clear_launch_queue(u64 dat) {
|
||||
fprintf(stderr, "Clear launch queue: %lx\n", dat);
|
||||
LaunchQueue::clear();
|
||||
return {0};
|
||||
void DebugMonitorService::ClearLaunchQueue() {
|
||||
LaunchQueue::Clear();
|
||||
}
|
||||
|
||||
std::tuple<Result, u32> DebugMonitorService::get_nso_info(u64 pid, OutPointerWithClientSize<Registration::NsoInfo> out) {
|
||||
u32 out_num_nsos = 0;
|
||||
|
||||
Result DebugMonitorService::GetNsoInfo(Out<u32> count, OutPointerWithClientSize<Registration::NsoInfo> out, u64 pid) {
|
||||
/* Zero out the output memory. */
|
||||
std::fill(out.pointer, out.pointer + out.num_elements, (const Registration::NsoInfo){0});
|
||||
|
||||
Result rc = Registration::GetNsoInfosForProcessId(out.pointer, out.num_elements, pid, &out_num_nsos);
|
||||
|
||||
return {rc, out_num_nsos};
|
||||
/* Actually return the nso infos. */
|
||||
return Registration::GetNsoInfosForProcessId(out.pointer, out.num_elements, pid, count.GetPointer());
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include <stratosphere/iserviceobject.hpp>
|
||||
#include <stratosphere.hpp>
|
||||
#include "ldr_registration.hpp"
|
||||
|
||||
enum DebugMonitorServiceCmd {
|
||||
|
@ -26,21 +26,16 @@ enum DebugMonitorServiceCmd {
|
|||
Dmnt_Cmd_GetNsoInfo = 2
|
||||
};
|
||||
|
||||
class DebugMonitorService final : public IServiceObject {
|
||||
public:
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
|
||||
Result handle_deferred() override {
|
||||
/* This service will never defer. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DebugMonitorService *clone() override {
|
||||
return new DebugMonitorService();
|
||||
}
|
||||
|
||||
class DebugMonitorService final : public IServiceObject {
|
||||
private:
|
||||
/* 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);
|
||||
std::tuple<Result, u32> get_nso_info(u64 pid, OutPointerWithClientSize<Registration::NsoInfo> out);
|
||||
Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args);
|
||||
void ClearLaunchQueue();
|
||||
Result GetNsoInfo(Out<u32> count, OutPointerWithClientSize<Registration::NsoInfo> out, u64 pid);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_AddTitleToLaunchQueue, &DebugMonitorService::AddTitleToLaunchQueue>(),
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_ClearLaunchQueue, &DebugMonitorService::ClearLaunchQueue>(),
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_GetNsoInfo, &DebugMonitorService::GetNsoInfo>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
static std::array<LaunchQueue::LaunchItem, LAUNCH_QUEUE_SIZE> g_launch_queue = {0};
|
||||
|
||||
Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) {
|
||||
Result LaunchQueue::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);
|
||||
int idx = GetFreeIndex(tid);
|
||||
if(idx == LAUNCH_QUEUE_FULL)
|
||||
return 0x409;
|
||||
|
||||
|
@ -39,22 +39,22 @@ Result LaunchQueue::add(u64 tid, const char *args, u64 arg_size) {
|
|||
return 0x0;
|
||||
}
|
||||
|
||||
Result LaunchQueue::add_copy(u64 tid_base, u64 tid) {
|
||||
int idx = get_index(tid_base);
|
||||
Result LaunchQueue::AddCopy(u64 tid_base, u64 tid) {
|
||||
int idx = GetIndex(tid_base);
|
||||
if (idx == LAUNCH_QUEUE_FULL) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
return add(tid, g_launch_queue[idx].args, g_launch_queue[idx].arg_size);
|
||||
return Add(tid, g_launch_queue[idx].args, g_launch_queue[idx].arg_size);
|
||||
}
|
||||
|
||||
|
||||
Result LaunchQueue::add_item(const LaunchItem *item) {
|
||||
Result LaunchQueue::AddItem(const LaunchItem *item) {
|
||||
if(item->arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) {
|
||||
return 0x209;
|
||||
}
|
||||
|
||||
int idx = get_free_index(item->tid);
|
||||
int idx = GetFreeIndex(item->tid);
|
||||
if(idx == LAUNCH_QUEUE_FULL)
|
||||
return 0x409;
|
||||
|
||||
|
@ -62,7 +62,7 @@ Result LaunchQueue::add_item(const LaunchItem *item) {
|
|||
return 0x0;
|
||||
}
|
||||
|
||||
int LaunchQueue::get_index(u64 tid) {
|
||||
int LaunchQueue::GetIndex(u64 tid) {
|
||||
auto it = std::find_if(g_launch_queue.begin(), g_launch_queue.end(), member_equals_fn(&LaunchQueue::LaunchItem::tid, tid));
|
||||
if (it == g_launch_queue.end()) {
|
||||
return LAUNCH_QUEUE_FULL;
|
||||
|
@ -70,7 +70,7 @@ int LaunchQueue::get_index(u64 tid) {
|
|||
return std::distance(g_launch_queue.begin(), it);
|
||||
}
|
||||
|
||||
int LaunchQueue::get_free_index(u64 tid) {
|
||||
int LaunchQueue::GetFreeIndex(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;
|
||||
|
@ -79,19 +79,19 @@ int LaunchQueue::get_free_index(u64 tid) {
|
|||
return LAUNCH_QUEUE_FULL;
|
||||
}
|
||||
|
||||
bool LaunchQueue::contains(u64 tid) {
|
||||
return get_index(tid) != LAUNCH_QUEUE_FULL;
|
||||
bool LaunchQueue::Contains(u64 tid) {
|
||||
return GetIndex(tid) != LAUNCH_QUEUE_FULL;
|
||||
}
|
||||
|
||||
void LaunchQueue::clear() {
|
||||
void LaunchQueue::Clear() {
|
||||
for (unsigned int i = 0; i < LAUNCH_QUEUE_SIZE; i++) {
|
||||
g_launch_queue[i].tid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LaunchQueue::LaunchItem *LaunchQueue::get_item(u64 tid) {
|
||||
int idx = get_index(tid);
|
||||
LaunchQueue::LaunchItem *LaunchQueue::GetItem(u64 tid) {
|
||||
int idx = GetIndex(tid);
|
||||
if (idx == LAUNCH_QUEUE_FULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -30,13 +30,13 @@ class LaunchQueue {
|
|||
char args[LAUNCH_QUEUE_ARG_SIZE_MAX];
|
||||
};
|
||||
|
||||
static LaunchQueue::LaunchItem *get_item(u64 tid);
|
||||
static LaunchQueue::LaunchItem *GetItem(u64 tid);
|
||||
|
||||
static Result add(u64 tid, const char *args, u64 arg_size);
|
||||
static Result add_item(const LaunchItem *item);
|
||||
static Result add_copy(u64 tid_base, u64 new_tid);
|
||||
static int get_index(u64 tid);
|
||||
static int get_free_index(u64 tid);
|
||||
static bool contains(u64 tid);
|
||||
static void clear();
|
||||
static Result Add(u64 tid, const char *args, u64 arg_size);
|
||||
static Result AddItem(const LaunchItem *item);
|
||||
static Result AddCopy(u64 tid_base, u64 new_tid);
|
||||
static int GetIndex(u64 tid);
|
||||
static int GetFreeIndex(u64 tid);
|
||||
static bool Contains(u64 tid);
|
||||
static void Clear();
|
||||
};
|
|
@ -92,24 +92,31 @@ void __appExit(void) {
|
|||
smExit();
|
||||
}
|
||||
|
||||
struct LoaderServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
consoleDebugInit(debugDevice_SVC);
|
||||
|
||||
auto server_manager = new WaitableManager<LoaderServerOptions>(1);
|
||||
|
||||
/* TODO: What's a good timeout value to use here? */
|
||||
auto server_manager = std::make_unique<WaitableManager>(U64_MAX);
|
||||
|
||||
/* Add services to manager. */
|
||||
server_manager->add_waitable(new ServiceServer<ProcessManagerService>("ldr:pm", 1));
|
||||
server_manager->add_waitable(new ServiceServer<ShellService>("ldr:shel", 3));
|
||||
server_manager->add_waitable(new ServiceServer<DebugMonitorService>("ldr:dmnt", 2));
|
||||
if (!kernelAbove300()) {
|
||||
server_manager->AddWaitable(new ServiceServer<ProcessManagerService>("ldr:pm", 1));
|
||||
server_manager->AddWaitable(new ServiceServer<ShellService>("ldr:shel", 3));
|
||||
server_manager->AddWaitable(new ServiceServer<DebugMonitorService>("ldr:dmnt", 2));
|
||||
if (GetRuntimeFirmwareVersion() < FirmwareVersion_300) {
|
||||
/* On 1.0.0-2.3.0, Loader services ldr:ro instead of ro. */
|
||||
server_manager->add_waitable(new ServiceServer<RelocatableObjectsService>("ldr:ro", 0x20));
|
||||
server_manager->AddWaitable(new ServiceServer<RelocatableObjectsService>("ldr:ro", 0x20));
|
||||
}
|
||||
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
server_manager->process();
|
||||
server_manager->Process();
|
||||
|
||||
delete server_manager;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,68 +22,45 @@
|
|||
#include "ldr_content_management.hpp"
|
||||
#include "ldr_npdm.hpp"
|
||||
|
||||
Result ProcessManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||
Result rc = 0xF601;
|
||||
|
||||
switch ((ProcessManagerServiceCmd)cmd_id) {
|
||||
case Pm_Cmd_CreateProcess:
|
||||
rc = WrapIpcCommandImpl<&ProcessManagerService::create_process>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Pm_Cmd_GetProgramInfo:
|
||||
rc = WrapIpcCommandImpl<&ProcessManagerService::get_program_info>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Pm_Cmd_RegisterTitle:
|
||||
rc = WrapIpcCommandImpl<&ProcessManagerService::register_title>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Pm_Cmd_UnregisterTitle:
|
||||
rc = WrapIpcCommandImpl<&ProcessManagerService::unregister_title>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::tuple<Result, MovedHandle> ProcessManagerService::create_process(u64 flags, u64 index, CopiedHandle reslimit_h) {
|
||||
Result ProcessManagerService::CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h) {
|
||||
Result rc;
|
||||
Registration::TidSid tid_sid;
|
||||
LaunchQueue::LaunchItem *launch_item;
|
||||
char nca_path[FS_MAX_PATH] = {0};
|
||||
Handle process_h = 0;
|
||||
|
||||
fprintf(stderr, "CreateProcess(%016lx, %016lx, %08x);\n", flags, index, reslimit_h.handle);
|
||||
|
||||
rc = Registration::GetRegisteredTidSid(index, &tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc, MovedHandle{process_h}};
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (tid_sid.storage_id != FsStorageId_None) {
|
||||
rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid);
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc, MovedHandle{process_h}};
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
launch_item = LaunchQueue::get_item(tid_sid.title_id);
|
||||
launch_item = LaunchQueue::GetItem(tid_sid.title_id);
|
||||
|
||||
rc = ProcessCreation::CreateProcess(&process_h, index, nca_path, launch_item, flags, reslimit_h.handle);
|
||||
rc = ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
ContentManagement::SetCreatedTitle(tid_sid.title_id);
|
||||
}
|
||||
|
||||
return {rc, MovedHandle{process_h}};
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::tuple<Result> ProcessManagerService::get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) {
|
||||
Result ProcessManagerService::GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info) {
|
||||
Result rc;
|
||||
char nca_path[FS_MAX_PATH] = {0};
|
||||
/* Zero output. */
|
||||
std::fill(out_program_info.pointer, out_program_info.pointer + out_program_info.num_elements, (const ProcessManagerService::ProgramInfo){0});
|
||||
|
||||
rc = populate_program_info_buffer(out_program_info.pointer, &tid_sid);
|
||||
rc = PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid);
|
||||
|
||||
if (R_FAILED(rc)) {
|
||||
return {rc};
|
||||
|
@ -100,31 +77,22 @@ std::tuple<Result> ProcessManagerService::get_program_info(Registration::TidSid
|
|||
return {rc};
|
||||
}
|
||||
|
||||
rc = LaunchQueue::add_copy(tid_sid.title_id, out_program_info.pointer->title_id);
|
||||
rc = LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id);
|
||||
}
|
||||
|
||||
return {rc};
|
||||
}
|
||||
|
||||
std::tuple<Result, u64> ProcessManagerService::register_title(Registration::TidSid tid_sid) {
|
||||
u64 out_index = 0;
|
||||
if (Registration::RegisterTidSid(&tid_sid, &out_index)) {
|
||||
return {0, out_index};
|
||||
} else {
|
||||
return {0xE09, out_index};
|
||||
}
|
||||
Result ProcessManagerService::RegisterTitle(Out<u64> index, Registration::TidSid tid_sid) {
|
||||
return Registration::RegisterTidSid(&tid_sid, index.GetPointer()) ? 0 : 0xE09;
|
||||
}
|
||||
|
||||
std::tuple<Result> ProcessManagerService::unregister_title(u64 index) {
|
||||
if (Registration::UnregisterIndex(index)) {
|
||||
return {0};
|
||||
} else {
|
||||
return {0x1009};
|
||||
}
|
||||
Result ProcessManagerService::UnregisterTitle(u64 index) {
|
||||
return Registration::UnregisterIndex(index) ? 0 : 0x1009;
|
||||
}
|
||||
|
||||
|
||||
Result ProcessManagerService::populate_program_info_buffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) {
|
||||
Result ProcessManagerService::PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) {
|
||||
NpdmUtils::NpdmInfo info;
|
||||
Result rc;
|
||||
bool mounted_code = false;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere/iserviceobject.hpp>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
#include "ldr_registration.hpp"
|
||||
#include "ldr_process_creation.hpp"
|
||||
|
@ -42,26 +42,21 @@ class ProcessManagerService final : public IServiceObject {
|
|||
u8 ac_buffer[0x3E0];
|
||||
};
|
||||
|
||||
static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition.");
|
||||
|
||||
public:
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
|
||||
Result handle_deferred() override {
|
||||
/* This service will never defer. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ProcessManagerService *clone() override {
|
||||
return new ProcessManagerService();
|
||||
}
|
||||
|
||||
static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition.");
|
||||
private:
|
||||
/* Actual commands. */
|
||||
std::tuple<Result, MovedHandle> create_process(u64 flags, u64 index, CopiedHandle reslimit_h);
|
||||
std::tuple<Result> get_program_info(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info);
|
||||
std::tuple<Result, u64> register_title(Registration::TidSid tid_sid);
|
||||
std::tuple<Result> unregister_title(u64 index);
|
||||
Result CreateProcess(Out<MovedHandle> proc_h, u64 flags, u64 index, CopiedHandle reslimit_h);
|
||||
Result GetProgramInfo(Registration::TidSid tid_sid, OutPointerWithServerSize<ProcessManagerService::ProgramInfo, 0x1> out_program_info);
|
||||
Result RegisterTitle(Out<u64> index, Registration::TidSid tid_sid);
|
||||
Result UnregisterTitle(u64 index);
|
||||
|
||||
/* Utilities */
|
||||
Result populate_program_info_buffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid);
|
||||
Result PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Pm_Cmd_CreateProcess, &ProcessManagerService::CreateProcess>(),
|
||||
MakeServiceCommandMeta<Pm_Cmd_GetProgramInfo, &ProcessManagerService::GetProgramInfo>(),
|
||||
MakeServiceCommandMeta<Pm_Cmd_RegisterTitle, &ProcessManagerService::RegisterTitle>(),
|
||||
MakeServiceCommandMeta<Pm_Cmd_UnregisterTitle, &ProcessManagerService::UnregisterTitle>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -24,71 +24,34 @@
|
|||
#include "ldr_map.hpp"
|
||||
#include "ldr_nro.hpp"
|
||||
|
||||
Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||
Result rc = 0xF601;
|
||||
|
||||
switch ((RoServiceCmd)cmd_id) {
|
||||
case Ro_Cmd_LoadNro:
|
||||
rc = WrapIpcCommandImpl<&RelocatableObjectsService::load_nro>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Ro_Cmd_UnloadNro:
|
||||
rc = WrapIpcCommandImpl<&RelocatableObjectsService::unload_nro>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Ro_Cmd_LoadNrr:
|
||||
rc = WrapIpcCommandImpl<&RelocatableObjectsService::load_nrr>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Ro_Cmd_UnloadNrr:
|
||||
rc = WrapIpcCommandImpl<&RelocatableObjectsService::unload_nrr>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Ro_Cmd_Initialize:
|
||||
rc = WrapIpcCommandImpl<&RelocatableObjectsService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
std::tuple<Result, u64> RelocatableObjectsService::load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
|
||||
Result rc;
|
||||
u64 out_address = 0;
|
||||
Result RelocatableObjectsService::LoadNro(Out<u64> load_address, PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
|
||||
Registration::Process *target_proc = NULL;
|
||||
if (!this->has_initialized || this->process_id != pid_desc.pid) {
|
||||
rc = 0xAE09;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xAE09;
|
||||
}
|
||||
if (nro_address & 0xFFF) {
|
||||
rc = 0xA209;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xA209;
|
||||
}
|
||||
if (nro_address + nro_size <= nro_address || !nro_size || (nro_size & 0xFFF)) {
|
||||
rc = 0xA409;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xA409;
|
||||
}
|
||||
if (bss_size && bss_address + bss_size <= bss_address) {
|
||||
rc = 0xA409;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xA409;
|
||||
}
|
||||
/* Ensure no overflow for combined sizes. */
|
||||
if (U64_MAX - nro_size < bss_size) {
|
||||
rc = 0xA409;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xA409;
|
||||
}
|
||||
target_proc = Registration::GetProcessByProcessId(pid_desc.pid);
|
||||
if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) {
|
||||
rc = 0xAC09;
|
||||
goto LOAD_NRO_END;
|
||||
return 0xAC09;
|
||||
}
|
||||
target_proc->owner_ro_service = this;
|
||||
|
||||
rc = NroUtils::LoadNro(target_proc, this->process_handle, nro_address, nro_size, bss_address, bss_size, &out_address);
|
||||
LOAD_NRO_END:
|
||||
return {rc, out_address};
|
||||
return NroUtils::LoadNro(target_proc, this->process_handle, nro_address, nro_size, bss_address, bss_size, load_address.GetPointer());
|
||||
}
|
||||
|
||||
std::tuple<Result> RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, u64 nro_address) {
|
||||
Result RelocatableObjectsService::UnloadNro(PidDescriptor pid_desc, u64 nro_address) {
|
||||
Registration::Process *target_proc = NULL;
|
||||
if (!this->has_initialized || this->process_id != pid_desc.pid) {
|
||||
return 0xAE09;
|
||||
|
@ -106,37 +69,42 @@ std::tuple<Result> RelocatableObjectsService::unload_nro(PidDescriptor pid_desc,
|
|||
return Registration::RemoveNroInfo(target_proc->index, this->process_handle, nro_address);
|
||||
}
|
||||
|
||||
std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) {
|
||||
Result rc;
|
||||
Result RelocatableObjectsService::LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) {
|
||||
Result rc = 0;
|
||||
Registration::Process *target_proc = NULL;
|
||||
MappedCodeMemory nrr_info = {0};
|
||||
ON_SCOPE_EXIT {
|
||||
if (R_FAILED(rc) && nrr_info.IsActive()) {
|
||||
nrr_info.Close();
|
||||
}
|
||||
};
|
||||
|
||||
if (!this->has_initialized || this->process_id != pid_desc.pid) {
|
||||
rc = 0xAE09;
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
if (nrr_address & 0xFFF) {
|
||||
rc = 0xA209;
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
if (nrr_address + nrr_size <= nrr_address || !nrr_size || (nrr_size & 0xFFF)) {
|
||||
rc = 0xA409;
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
|
||||
target_proc = Registration::GetProcessByProcessId(pid_desc.pid);
|
||||
if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) {
|
||||
rc = 0xAC09;
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
target_proc->owner_ro_service = this;
|
||||
|
||||
if (R_FAILED((rc = nrr_info.Open(this->process_handle, target_proc->is_64_bit_addspace, nrr_address, nrr_size)))) {
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (R_FAILED((rc = nrr_info.Map()))) {
|
||||
goto LOAD_NRR_END;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = NroUtils::ValidateNrrHeader((NroUtils::NrrHeader *)nrr_info.mapped_address, nrr_size, target_proc->title_id);
|
||||
|
@ -144,16 +112,10 @@ std::tuple<Result> RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u
|
|||
Registration::AddNrrInfo(target_proc->index, &nrr_info);
|
||||
}
|
||||
|
||||
LOAD_NRR_END:
|
||||
if (R_FAILED(rc)) {
|
||||
if (nrr_info.IsActive()) {
|
||||
nrr_info.Close();
|
||||
}
|
||||
}
|
||||
return {rc};
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::tuple<Result> RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) {
|
||||
Result RelocatableObjectsService::UnloadNrr(PidDescriptor pid_desc, u64 nrr_address) {
|
||||
Registration::Process *target_proc = NULL;
|
||||
if (!this->has_initialized || this->process_id != pid_desc.pid) {
|
||||
return 0xAE09;
|
||||
|
@ -171,9 +133,8 @@ std::tuple<Result> RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc,
|
|||
return Registration::RemoveNrrInfo(target_proc->index, nrr_address);
|
||||
}
|
||||
|
||||
std::tuple<Result> RelocatableObjectsService::initialize(PidDescriptor pid_desc, CopiedHandle process_h) {
|
||||
Result RelocatableObjectsService::Initialize(PidDescriptor pid_desc, CopiedHandle process_h) {
|
||||
u64 handle_pid;
|
||||
Result rc = 0xAE09;
|
||||
if (R_SUCCEEDED(svcGetProcessId(&handle_pid, process_h.handle)) && handle_pid == pid_desc.pid) {
|
||||
if (this->has_initialized) {
|
||||
svcCloseHandle(this->process_handle);
|
||||
|
@ -181,7 +142,7 @@ std::tuple<Result> RelocatableObjectsService::initialize(PidDescriptor pid_desc,
|
|||
this->process_handle = process_h.handle;
|
||||
this->process_id = handle_pid;
|
||||
this->has_initialized = true;
|
||||
rc = 0;
|
||||
return 0;
|
||||
}
|
||||
return {rc};
|
||||
return 0xAE09;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include <stratosphere/iserviceobject.hpp>
|
||||
#include <stratosphere.hpp>
|
||||
#include "ldr_registration.hpp"
|
||||
|
||||
enum RoServiceCmd {
|
||||
|
@ -33,27 +33,26 @@ class RelocatableObjectsService final : public IServiceObject {
|
|||
u64 process_id = U64_MAX;
|
||||
bool has_initialized = false;
|
||||
public:
|
||||
~RelocatableObjectsService() {
|
||||
virtual ~RelocatableObjectsService() override {
|
||||
Registration::CloseRoService(this, this->process_handle);
|
||||
if (this->has_initialized) {
|
||||
svcCloseHandle(this->process_handle);
|
||||
}
|
||||
}
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
|
||||
Result handle_deferred() override {
|
||||
/* This service will never defer. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
RelocatableObjectsService *clone() override {
|
||||
return new RelocatableObjectsService(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
/* Actual commands. */
|
||||
std::tuple<Result, u64> load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
|
||||
std::tuple<Result> unload_nro(PidDescriptor pid_desc, u64 nro_address);
|
||||
std::tuple<Result> load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size);
|
||||
std::tuple<Result> unload_nrr(PidDescriptor pid_desc, u64 nrr_address);
|
||||
std::tuple<Result> initialize(PidDescriptor pid_desc, CopiedHandle process_h);
|
||||
Result LoadNro(Out<u64> load_address, PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
|
||||
Result UnloadNro(PidDescriptor pid_desc, u64 nro_address);
|
||||
Result LoadNrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size);
|
||||
Result UnloadNrr(PidDescriptor pid_desc, u64 nrr_address);
|
||||
Result Initialize(PidDescriptor pid_desc, CopiedHandle process_h);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Ro_Cmd_LoadNro, &RelocatableObjectsService::LoadNro>(),
|
||||
MakeServiceCommandMeta<Ro_Cmd_UnloadNro, &RelocatableObjectsService::UnloadNro>(),
|
||||
MakeServiceCommandMeta<Ro_Cmd_LoadNrr, &RelocatableObjectsService::LoadNrr>(),
|
||||
MakeServiceCommandMeta<Ro_Cmd_UnloadNrr, &RelocatableObjectsService::UnloadNrr>(),
|
||||
MakeServiceCommandMeta<Ro_Cmd_Initialize, &RelocatableObjectsService::Initialize>(),
|
||||
};
|
||||
};
|
||||
|
|
|
@ -20,49 +20,28 @@
|
|||
#include "ldr_launch_queue.hpp"
|
||||
#include "ldr_content_management.hpp"
|
||||
|
||||
Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
|
||||
|
||||
Result rc = 0xF601;
|
||||
|
||||
switch ((ShellServiceCmd)cmd_id) {
|
||||
case Shell_Cmd_AddTitleToLaunchQueue:
|
||||
rc = WrapIpcCommandImpl<&ShellService::add_title_to_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Shell_Cmd_ClearLaunchQueue:
|
||||
rc = WrapIpcCommandImpl<&ShellService::clear_launch_queue>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
case Shell_Cmd_AtmosphereSetExternalContentSource:
|
||||
rc = WrapIpcCommandImpl<&ShellService::set_external_content_source>(this, r, out_c, pointer_buffer, pointer_buffer_size);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
std::tuple<Result> ShellService::add_title_to_launch_queue(u64 args_size, u64 tid, InPointer<char> args) {
|
||||
Result ShellService::AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args) {
|
||||
fprintf(stderr, "Add to launch queue: %p, %zX\n", args.pointer, std::min(args_size, args.num_elements));
|
||||
return {LaunchQueue::add(tid, args.pointer, std::min(args_size, args.num_elements))};
|
||||
return LaunchQueue::Add(tid, args.pointer, std::min(args_size, args.num_elements));
|
||||
}
|
||||
|
||||
std::tuple<Result> ShellService::clear_launch_queue(u64 dat) {
|
||||
fprintf(stderr, "Clear launch queue: %lx\n", dat);
|
||||
LaunchQueue::clear();
|
||||
return {0};
|
||||
void ShellService::ClearLaunchQueue() {
|
||||
LaunchQueue::Clear();
|
||||
}
|
||||
|
||||
/* SetExternalContentSource extension */
|
||||
std::tuple<Result, MovedHandle> ShellService::set_external_content_source(u64 tid) {
|
||||
Result ShellService::SetExternalContentSource(Out<MovedHandle> out, u64 tid) {
|
||||
Handle server_h;
|
||||
Handle client_h;
|
||||
|
||||
Result rc;
|
||||
if (R_FAILED(rc = svcCreateSession(&server_h, &client_h, 0, 0))) {
|
||||
return {rc, 0};
|
||||
return rc;
|
||||
}
|
||||
|
||||
Service service;
|
||||
serviceCreate(&service, client_h);
|
||||
ContentManagement::SetExternalContentSource(tid, FsFileSystem {service});
|
||||
return {0, server_h};
|
||||
out.SetValue(server_h);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere/iserviceobject.hpp>
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
enum ShellServiceCmd {
|
||||
Shell_Cmd_AddTitleToLaunchQueue = 0,
|
||||
|
@ -26,22 +26,17 @@ enum ShellServiceCmd {
|
|||
};
|
||||
|
||||
class ShellService final : public IServiceObject {
|
||||
public:
|
||||
Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) override;
|
||||
Result handle_deferred() override {
|
||||
/* This service will never defer. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ShellService *clone() override {
|
||||
return new ShellService();
|
||||
}
|
||||
|
||||
private:
|
||||
/* 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);
|
||||
|
||||
Result AddTitleToLaunchQueue(u64 args_size, u64 tid, InPointer<char> args);
|
||||
void ClearLaunchQueue();
|
||||
|
||||
/* Atmosphere commands. */
|
||||
std::tuple<Result, MovedHandle> set_external_content_source(u64 tid);
|
||||
Result SetExternalContentSource(Out<MovedHandle> out, u64 tid);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Shell_Cmd_AddTitleToLaunchQueue, &ShellService::AddTitleToLaunchQueue>(),
|
||||
MakeServiceCommandMeta<Shell_Cmd_ClearLaunchQueue, &ShellService::ClearLaunchQueue>(),
|
||||
MakeServiceCommandMeta<Shell_Cmd_AtmosphereSetExternalContentSource, &ShellService::SetExternalContentSource>(),
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue