loader: update for libstratosphere refactor

This commit is contained in:
Michael Scire 2018-10-29 22:33:56 -07:00 committed by SciresM
parent 8b71378920
commit c49cfbd6af
12 changed files with 150 additions and 272 deletions

View file

@ -56,6 +56,9 @@
"svcReplyAndReceiveLight" : "0x42",
"svcReplyAndReceive" : "0x43",
"svcReplyAndReceiveWithUserBuffer" : "0x44",
"svcCreateEvent": "0x45",
"svcReadWriteRegister" : "0x4E",
"svcQueryIoMapping": "0x55",
"svcSetProcessMemoryPermission" : "0x73",
"svcMapProcessMemory" : "0x74",
"svcUnmapProcessMemory" : "0x75",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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