From 82d97283725e435211ecbb80ee03d662b21a00a0 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 14:51:07 -0600 Subject: [PATCH 01/21] Loader: Save process->is_64_bit as prep for ldr:ro --- stratosphere/loader/source/ldr_process_creation.cpp | 8 +++++++- stratosphere/loader/source/ldr_registration.cpp | 3 ++- stratosphere/loader/source/ldr_registration.hpp | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index a353b645d..ddac6e006 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -174,7 +174,13 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc /* Update the list of registered processes with the new process. */ svcGetProcessId(&process_id, process_h); - Registration::set_process_id_and_tid_min(index, process_id, npdm_info.aci0->title_id); + bool is_64_bit; + if (kernelAbove200()) { + is_64_bit = (((npdm_info.header->mmu_flags >> 1) & 5) | 2) == 3; + } else { + is_64_bit = (npdm_info.header->mmu_flags & 0xE) == 0x2; + } + Registration::set_process_id_tid_min_and_is_64_bit(index, process_id, npdm_info.aci0->title_id, is_64_bit); for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (NsoUtils::IsNsoPresent(i)) { Registration::add_nso_info(index, nso_extents.nso_addresses[i], nso_extents.nso_sizes[i], NsoUtils::GetNsoBuildId(i)); diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 509b85f85..706a752e2 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -75,7 +75,7 @@ Result Registration::get_registered_tid_sid(u64 index, Registration::TidSid *out return 0; } -void Registration::set_process_id_and_tid_min(u64 index, u64 process_id, u64 tid_min) { +void Registration::set_process_id_tid_min_and_is_64_bit(u64 index, u64 process_id, u64 tid_min, bool is_64_bit) { Registration::Process *target_process = get_process(index); if (target_process == NULL) { return; @@ -83,6 +83,7 @@ void Registration::set_process_id_and_tid_min(u64 index, u64 process_id, u64 tid target_process->process_id = process_id; target_process->title_id_min = tid_min; + target_process->is_64_bit = is_64_bit; } void Registration::add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index da95cde42..771c4bdb1 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -25,6 +25,7 @@ class Registration { struct Process { bool in_use; + bool is_64_bit; u64 index; u64 process_id; u64 title_id_min; @@ -44,7 +45,7 @@ class Registration { static Result get_registered_tid_sid(u64 index, Registration::TidSid *out); 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 set_process_id_tid_min_and_is_64_bit(u64 index, u64 process_id, u64 tid_min, bool is_64_bit); static void add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id); static Result get_nso_infos_for_process_id(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; From 1ec3eb1ace1b103d7df70e98a0f881156c4a1084 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 14:53:33 -0600 Subject: [PATCH 02/21] Loader: is_64_bit -> is_64_bit_addspace --- stratosphere/loader/source/ldr_process_creation.cpp | 8 ++++---- stratosphere/loader/source/ldr_registration.cpp | 4 ++-- stratosphere/loader/source/ldr_registration.hpp | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index ddac6e006..ef60ef6fe 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -174,13 +174,13 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc /* Update the list of registered processes with the new process. */ svcGetProcessId(&process_id, process_h); - bool is_64_bit; + bool is_64_bit_addspace; if (kernelAbove200()) { - is_64_bit = (((npdm_info.header->mmu_flags >> 1) & 5) | 2) == 3; + is_64_bit_addspace = (((npdm_info.header->mmu_flags >> 1) & 5) | 2) == 3; } else { - is_64_bit = (npdm_info.header->mmu_flags & 0xE) == 0x2; + is_64_bit_addspace = (npdm_info.header->mmu_flags & 0xE) == 0x2; } - Registration::set_process_id_tid_min_and_is_64_bit(index, process_id, npdm_info.aci0->title_id, is_64_bit); + Registration::set_process_id_tid_min_and_is_64_bit_addspace(index, process_id, npdm_info.aci0->title_id, is_64_bit_addspace); for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (NsoUtils::IsNsoPresent(i)) { Registration::add_nso_info(index, nso_extents.nso_addresses[i], nso_extents.nso_sizes[i], NsoUtils::GetNsoBuildId(i)); diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 706a752e2..fb959ef1a 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -75,7 +75,7 @@ Result Registration::get_registered_tid_sid(u64 index, Registration::TidSid *out return 0; } -void Registration::set_process_id_tid_min_and_is_64_bit(u64 index, u64 process_id, u64 tid_min, bool is_64_bit) { +void Registration::set_process_id_tid_min_and_is_64_bit_addspace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace) { Registration::Process *target_process = get_process(index); if (target_process == NULL) { return; @@ -83,7 +83,7 @@ void Registration::set_process_id_tid_min_and_is_64_bit(u64 index, u64 process_i target_process->process_id = process_id; target_process->title_id_min = tid_min; - target_process->is_64_bit = is_64_bit; + target_process->is_64_bit_addspace = is_64_bit_addspace; } void Registration::add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 771c4bdb1..8779bc455 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -25,7 +25,7 @@ class Registration { struct Process { bool in_use; - bool is_64_bit; + bool is_64_bit_addspace; u64 index; u64 process_id; u64 title_id_min; @@ -45,7 +45,7 @@ class Registration { static Result get_registered_tid_sid(u64 index, Registration::TidSid *out); static bool register_tid_sid(const TidSid *tid_sid, u64 *out_index); static bool unregister_index(u64 index); - static void set_process_id_tid_min_and_is_64_bit(u64 index, u64 process_id, u64 tid_min, bool is_64_bit); + static void set_process_id_tid_min_and_is_64_bit_addspace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id); static Result get_nso_infos_for_process_id(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; From 4f09c61bfa3569511aae2b86eb30379a1cd11884 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 16:45:09 -0600 Subject: [PATCH 03/21] Loader: Push ldr:ro stub. --- stratosphere/loader/source/ldr_ro_service.cpp | 57 +++++++++++++++++++ stratosphere/loader/source/ldr_ro_service.hpp | 34 +++++++++++ 2 files changed, 91 insertions(+) create mode 100644 stratosphere/loader/source/ldr_ro_service.cpp create mode 100644 stratosphere/loader/source/ldr_ro_service.hpp diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp new file mode 100644 index 000000000..f5f7f5984 --- /dev/null +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +#include "ldr_ro_service.hpp" +#include "ldr_registration.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 load_nro(PidDescriptor pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { + /* TODO */ + return std::make_tuple(0xF601, 0); +} + +std::tuple unload_nro(PidDescriptor pid, u64 nro_address) { + /* TODO */ + return std::make_tuple(0xF601); +} + +std::tuple load_nrr(PidDescriptor pid, u64 nrr_address, u64 nrr_size) { + /* TODO */ + return std::make_tuple(0xF601); +} + +std::tuple unload_nrr(PidDescriptor pid, u64 nrr_address) { + /* TODO */ + return std::make_tuple(0xF601); +} + +std::tuple initialize(PidDescriptor pid, CopiedHandle process_h) { + /* TODO */ + return std::make_tuple(0xF601); +} diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp new file mode 100644 index 000000000..29d057ba0 --- /dev/null +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -0,0 +1,34 @@ +#pragma once +#include + +#include +#include "ldr_registration.hpp" + +enum RoServiceCmd { + Ro_Cmd_LoadNro = 0, + Ro_Cmd_UnloadNro = 1, + Ro_Cmd_LoadNrr = 2, + Ro_Cmd_UnloadNrr = 3, + Ro_Cmd_Initialize = 4, +}; + +class RelocatableObjectsService : IServiceObject { + Handle process_handle; + u64 process_id; + bool has_initialized; + public: + RelocatableObjectsService() : process_handle(0), process_id(U64_MAX), has_initialized(false) { } + virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); + virtual Result handle_deferred() { + /* This service will never defer. */ + return 0; + } + + private: + /* Actual commands. */ + std::tuple load_nro(PidDescriptor pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); + std::tuple unload_nro(PidDescriptor pid, u64 nro_address); + std::tuple load_nrr(PidDescriptor pid, u64 nrr_address, u64 nrr_size); + std::tuple unload_nrr(PidDescriptor pid, u64 nrr_address); + std::tuple initialize(PidDescriptor pid, CopiedHandle process_h); +}; \ No newline at end of file From fe2f227dfc3818f17364d89876c3b434e116441b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 16:48:57 -0600 Subject: [PATCH 04/21] Loader: Implement ldr:ro->Initialize() --- stratosphere/loader/source/ldr_ro_service.cpp | 23 +++++++++++++------ stratosphere/loader/source/ldr_ro_service.hpp | 10 ++++---- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index f5f7f5984..2375a0b0b 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -31,27 +31,36 @@ Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_ } -std::tuple load_nro(PidDescriptor pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { +std::tuple RelocatableObjectsService::load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { /* TODO */ return std::make_tuple(0xF601, 0); } -std::tuple unload_nro(PidDescriptor pid, u64 nro_address) { +std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, u64 nro_address) { /* TODO */ return std::make_tuple(0xF601); } -std::tuple load_nrr(PidDescriptor pid, u64 nrr_address, u64 nrr_size) { +std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { /* TODO */ return std::make_tuple(0xF601); } -std::tuple unload_nrr(PidDescriptor pid, u64 nrr_address) { +std::tuple RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) { /* TODO */ return std::make_tuple(0xF601); } -std::tuple initialize(PidDescriptor pid, CopiedHandle process_h) { - /* TODO */ - return std::make_tuple(0xF601); +std::tuple 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); + } + this->process_handle = process_h.handle; + this->has_initialized = true; + rc = 0; + } + return std::make_tuple(rc); } diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index 29d057ba0..f2a02f252 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -26,9 +26,9 @@ class RelocatableObjectsService : IServiceObject { private: /* Actual commands. */ - std::tuple load_nro(PidDescriptor pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); - std::tuple unload_nro(PidDescriptor pid, u64 nro_address); - std::tuple load_nrr(PidDescriptor pid, u64 nrr_address, u64 nrr_size); - std::tuple unload_nrr(PidDescriptor pid, u64 nrr_address); - std::tuple initialize(PidDescriptor pid, CopiedHandle process_h); + std::tuple load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); + std::tuple unload_nro(PidDescriptor pid_desc, u64 nro_address); + std::tuple load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size); + std::tuple unload_nrr(PidDescriptor pid_desc, u64 nrr_address); + std::tuple initialize(PidDescriptor pid_desc, CopiedHandle process_h); }; \ No newline at end of file From 977a51edb0d173609845c6e89b31cac10c374d2a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 16:50:43 -0600 Subject: [PATCH 05/21] Loader: Service ldr:ro on <= 2.3.0 --- stratosphere/loader/source/ldr_main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index b82521435..f3ab9b0bc 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -9,6 +9,7 @@ #include "ldr_process_manager.hpp" #include "ldr_debug_monitor.hpp" #include "ldr_shell.hpp" +#include "ldr_ro_service.hpp" extern "C" { extern u32 __start__; @@ -83,6 +84,10 @@ int main(int argc, char **argv) server_manager->add_waitable(new ServiceServer("dbg:pm", 1)); server_manager->add_waitable(new ServiceServer("dbg:shel", 3)); server_manager->add_waitable(new ServiceServer("dbg:dmnt", 2)); + if (!kernelAbove300()) { + /* On 1.0.0-2.3.0, Loader services ldr:ro instead of ro. */ + server_manager->add_waitable(new ServiceServer("dbg:ro", 0x20)); + } /* Loop forever, servicing our services. */ server_manager->process(); From 991357f3099ef8fb9fd293d9ca55def1bef353aa Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 17:03:10 -0600 Subject: [PATCH 06/21] Loader: Add NRRInfo to RegisteredProcess, refactor Registration:: --- .../loader/source/ldr_debug_monitor.cpp | 2 +- .../loader/source/ldr_process_creation.cpp | 6 ++-- .../loader/source/ldr_process_manager.cpp | 6 ++-- .../loader/source/ldr_registration.cpp | 30 ++++++++--------- .../loader/source/ldr_registration.hpp | 32 +++++++++++++------ 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index 218e82f47..954b01168 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -41,7 +41,7 @@ std::tuple DebugMonitorService::get_nso_info(u64 pid, OutPointerWit std::fill(out.pointer, out.pointer + out.num_elements, (const Registration::NsoInfo){0}); - Result rc = Registration::get_nso_infos_for_process_id(out.pointer, out.num_elements, pid, &out_num_nsos); + Result rc = Registration::GetNsoInfosForProcessId(out.pointer, out.num_elements, pid, &out_num_nsos); return std::make_tuple(rc, out_num_nsos); } \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index ef60ef6fe..c8d0fe91c 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -96,7 +96,7 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc Result rc; /* Get the process from the registration queue. */ - target_process = Registration::get_process(index); + target_process = Registration::GetProcess(index); if (target_process == NULL) { return 0x1009; } @@ -180,10 +180,10 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc } else { is_64_bit_addspace = (npdm_info.header->mmu_flags & 0xE) == 0x2; } - Registration::set_process_id_tid_min_and_is_64_bit_addspace(index, process_id, npdm_info.aci0->title_id, is_64_bit_addspace); + Registration::SetProcessIdTidMinAndIs64BitAddressSpace(index, process_id, npdm_info.aci0->title_id, is_64_bit_addspace); for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (NsoUtils::IsNsoPresent(i)) { - Registration::add_nso_info(index, nso_extents.nso_addresses[i], nso_extents.nso_sizes[i], NsoUtils::GetNsoBuildId(i)); + Registration::AddNsoInfo(index, nso_extents.nso_addresses[i], nso_extents.nso_sizes[i], NsoUtils::GetNsoBuildId(i)); } } diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index 98ee6f0a2..8fbda0e6f 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -37,7 +37,7 @@ std::tuple ProcessManagerService::create_process(u64 flags, fprintf(stderr, "CreateProcess(%016lx, %016lx, %08x);\n", flags, index, reslimit_h.handle); - rc = Registration::get_registered_tid_sid(index, &tid_sid); + rc = Registration::GetRegisteredTidSid(index, &tid_sid); if (R_FAILED(rc)) { std::make_tuple(rc, MovedHandle{process_h}); } @@ -85,7 +85,7 @@ std::tuple ProcessManagerService::get_program_info(Registration::TidSid std::tuple ProcessManagerService::register_title(Registration::TidSid tid_sid) { u64 out_index = 0; - if (Registration::register_tid_sid(&tid_sid, &out_index)) { + if (Registration::RegisterTidSid(&tid_sid, &out_index)) { return std::make_tuple(0, out_index); } else { return std::make_tuple(0xE09, out_index); @@ -93,7 +93,7 @@ std::tuple ProcessManagerService::register_title(Registration::TidS } std::tuple ProcessManagerService::unregister_title(u64 index) { - if (Registration::unregister_index(index)) { + if (Registration::UnregisterIndex(index)) { return std::make_tuple(0); } else { return std::make_tuple(0x1009); diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index fb959ef1a..7ff8a676c 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -6,7 +6,7 @@ static Registration::List g_registration_list = {0}; static u64 g_num_registered = 1; -Registration::Process *Registration::get_free_process() { +Registration::Process *Registration::GetFreeProcess() { unsigned int i; for (i = 0; i < REGISTRATION_LIST_MAX; i++) { if (!g_registration_list.processes[i].in_use) { @@ -16,7 +16,7 @@ Registration::Process *Registration::get_free_process() { return NULL; } -Registration::Process *Registration::get_process(u64 index) { +Registration::Process *Registration::GetProcess(u64 index) { unsigned int i; for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].index != index); i++) { } @@ -26,7 +26,7 @@ Registration::Process *Registration::get_process(u64 index) { return &g_registration_list.processes[i]; } -Registration::Process *Registration::get_process_by_process_id(u64 pid) { +Registration::Process *Registration::GetProcessByProcessId(u64 pid) { unsigned int i; for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].process_id != pid); i++) { @@ -37,8 +37,8 @@ Registration::Process *Registration::get_process_by_process_id(u64 pid) { 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(); +bool Registration::RegisterTidSid(const TidSid *tid_sid, u64 *out_index) { + Registration::Process *free_process = GetFreeProcess(); if (free_process == NULL) { return false; } @@ -52,8 +52,8 @@ bool Registration::register_tid_sid(const TidSid *tid_sid, u64 *out_index) { return true; } -bool Registration::unregister_index(u64 index) { - Registration::Process *target_process = get_process(index); +bool Registration::UnregisterIndex(u64 index) { + Registration::Process *target_process = GetProcess(index); if (target_process == NULL) { return false; } @@ -64,8 +64,8 @@ bool Registration::unregister_index(u64 index) { } -Result Registration::get_registered_tid_sid(u64 index, Registration::TidSid *out) { - Registration::Process *target_process = get_process(index); +Result Registration::GetRegisteredTidSid(u64 index, Registration::TidSid *out) { + Registration::Process *target_process = GetProcess(index); if (target_process == NULL) { return 0x1009; } @@ -75,8 +75,8 @@ Result Registration::get_registered_tid_sid(u64 index, Registration::TidSid *out return 0; } -void Registration::set_process_id_tid_min_and_is_64_bit_addspace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace) { - Registration::Process *target_process = get_process(index); +void Registration::SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace) { + Registration::Process *target_process = GetProcess(index); if (target_process == NULL) { return; } @@ -86,8 +86,8 @@ void Registration::set_process_id_tid_min_and_is_64_bit_addspace(u64 index, u64 target_process->is_64_bit_addspace = is_64_bit_addspace; } -void Registration::add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id) { - Registration::Process *target_process = get_process(index); +void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id) { + Registration::Process *target_process = GetProcess(index); if (target_process == NULL) { return; } @@ -104,8 +104,8 @@ void Registration::add_nso_info(u64 index, u64 base_address, u64 size, const uns } -Result Registration::get_nso_infos_for_process_id(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { - Registration::Process *target_process = get_process_by_process_id(process_id); +Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { + Registration::Process *target_process = GetProcessByProcessId(process_id); if (target_process == NULL) { return 0x1009; } diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 8779bc455..1c1483eec 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -4,6 +4,7 @@ #define REGISTRATION_LIST_MAX (0x40) #define NSO_INFO_MAX (0x20) +#define NRR_INFO_MAX (0x40) class Registration { public: @@ -18,6 +19,18 @@ class Registration { NsoInfo info; }; + struct NrrInfo { + u64 base_address; + u64 size; + u64 code_memory_address; + u64 address_for_loader; + }; + + struct NrrInfoHolder { + bool in_use; + NrrInfo info; + }; + struct TidSid { u64 title_id; FsStorageId storage_id; @@ -31,6 +44,7 @@ class Registration { u64 title_id_min; Registration::TidSid tid_sid; Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; + Registration::NrrInfoHolder nrr_infos[NRR_INFO_MAX]; u64 _0x730; }; @@ -39,13 +53,13 @@ class Registration { u64 num_processes; }; - static Registration::Process *get_free_process(); - static Registration::Process *get_process(u64 index); - static Registration::Process *get_process_by_process_id(u64 pid); - static Result get_registered_tid_sid(u64 index, Registration::TidSid *out); - static bool register_tid_sid(const TidSid *tid_sid, u64 *out_index); - static bool unregister_index(u64 index); - static void set_process_id_tid_min_and_is_64_bit_addspace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); - static void add_nso_info(u64 index, u64 base_address, u64 size, const unsigned char *build_id); - static Result get_nso_infos_for_process_id(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); + static Registration::Process *GetFreeProcess(); + static Registration::Process *GetProcess(u64 index); + static Registration::Process *GetProcessByProcessId(u64 pid); + static Result GetRegisteredTidSid(u64 index, Registration::TidSid *out); + static bool RegisterTidSid(const TidSid *tid_sid, u64 *out_index); + static bool UnregisterIndex(u64 index); + static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); + static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); + static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; From b34b9ba0e4df1cfbf979c68cb28734a539fef9ee Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 18:04:30 -0600 Subject: [PATCH 07/21] Loader: Greatly simplify mapping logic, add CodeMemory mapper. --- stratosphere/loader/source/ldr_map.cpp | 241 ++++++++++++++----------- stratosphere/loader/source/ldr_map.hpp | 19 ++ 2 files changed, 150 insertions(+), 110 deletions(-) diff --git a/stratosphere/loader/source/ldr_map.cpp b/stratosphere/loader/source/ldr_map.cpp index 9913c39f8..7ac554e16 100644 --- a/stratosphere/loader/source/ldr_map.cpp +++ b/stratosphere/loader/source/ldr_map.cpp @@ -1,6 +1,7 @@ #include #include "ldr_map.hpp" +#include "ldr_random.hpp" Result MapUtils::LocateSpaceForMap(u64 *out, u64 out_size) { if (kernelAbove200()) { @@ -11,38 +12,26 @@ Result MapUtils::LocateSpaceForMap(u64 *out, u64 out_size) { } +Result MapUtils::MapCodeMemoryForProcess(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address) { + if (kernelAbove200()) { + return MapCodeMemoryForProcessModern(process_h, base_address, size, out_code_memory_address); + } else { + return MapCodeMemoryForProcessDeprecated(process_h, is_64_bit_address_space, base_address, size, out_code_memory_address); + } +} + Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) { MemoryInfo mem_info = {0}; + AddressSpaceInfo address_space = {0}; u32 page_info = 0; - u64 heap_base = 0, heap_size = 0, heap_end = 0; - u64 map_base = 0, map_size = 0, map_end = 0; - u64 addspace_base = 0, addspace_size = 0, addspace_end = 0; u64 cur_base = 0, cur_end = 0; Result rc; - if (R_FAILED((rc = svcGetInfo(&heap_base, 4, CUR_PROCESS_HANDLE, 0)))) { + if (R_FAILED((rc = GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE)))) { return rc; } - if (R_FAILED((rc = svcGetInfo(&heap_size, 5, CUR_PROCESS_HANDLE, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&map_base, 2, CUR_PROCESS_HANDLE, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&map_size, 3, CUR_PROCESS_HANDLE, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&addspace_base, 12, CUR_PROCESS_HANDLE, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&addspace_size, 13, CUR_PROCESS_HANDLE, 0)))) { - return rc; - } - heap_end = heap_base + heap_size; - map_end = map_base + map_size; - addspace_end = addspace_base + addspace_size; - cur_base = addspace_base; + cur_base = address_space.addspace_base; rc = 0xD001; cur_end = cur_base + out_size; @@ -50,98 +39,40 @@ Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) { return rc; } - if (heap_size) { - if (map_size) { - while (true) { - if (cur_end - 1 < heap_base || heap_end - 1 < cur_base) { - if (cur_end - 1 < map_base || map_end - 1 < cur_base) { - if (R_FAILED(svcQueryMemory(&mem_info, &page_info, cur_base))) { - /* TODO: panic. */ - } - if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) { - *out = cur_base; - return 0x0; - } - if (mem_info.addr + mem_info.size <= cur_base) { - return rc; - } - cur_base = mem_info.addr + mem_info.size; - if (cur_base >= addspace_end) { - return rc; - } - } else { - if (map_end == cur_base) { - return rc; - } - cur_base = map_end; - } - } else { - if (heap_end == cur_base) { - return rc; - } - cur_base = heap_end; - } - cur_end = cur_base + out_size; - if (cur_base + out_size <= cur_base) { - return rc; - } + while (true) { + if (address_space.heap_size && (address_space.heap_base <= cur_end - 1 && cur_base <= address_space.heap_end - 1)) { + /* If we overlap the heap region, go to the end of the heap region. */ + if (cur_base == address_space.heap_end) { + return rc; } + cur_base = address_space.heap_end; + } else if (address_space.map_size && (address_space.map_base <= cur_end - 1 && cur_base <= address_space.map_end - 1)) { + /* If we overlap the map region, go to the end of the map region. */ + if (cur_base == address_space.map_end) { + return rc; + } + cur_base = address_space.map_end; } else { - while (true) { - if (cur_end - 1 < heap_base || heap_end - 1 < cur_base) { - if (R_FAILED(svcQueryMemory(&mem_info, &page_info, cur_base))) { - /* TODO: panic. */ - } - if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) { - *out = cur_base; - return 0x0; - } - if (mem_info.addr + mem_info.size <= cur_base) { - return rc; - } - cur_base = mem_info.addr + mem_info.size; - if (cur_base >= addspace_end) { - return rc; - } - } else { - if (heap_end == cur_base) { - return rc; - } - cur_base = heap_end; - } - cur_end = cur_base + out_size; - if (cur_base + out_size <= cur_base) { - return rc; - } + if (R_FAILED(svcQueryMemory(&mem_info, &page_info, cur_base))) { + /* TODO: panic. */ + } + if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) { + *out = cur_base; + return 0x0; + } + if (mem_info.addr + mem_info.size <= cur_base) { + return rc; + } + cur_base = mem_info.addr + mem_info.size; + if (cur_base >= address_space.addspace_end) { + return rc; } } - } else { - while (cur_end > cur_base) { - if (map_size && cur_end - 1 >= map_base && map_end - 1 >= cur_base) { - if (cur_base == map_end) { - return rc; - } - cur_base = map_end; - } else { - if (R_FAILED(svcQueryMemory(&mem_info, &page_info, cur_base))) { - /* TODO: panic. */ - } - if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) { - *out = cur_base; - return 0x0; - } - if (mem_info.addr + mem_info.size <= cur_base) { - return rc; - } - cur_base = mem_info.addr + mem_info.size; - if (cur_base >= addspace_end) { - return rc; - } - } - cur_end = cur_base + out_size; + cur_end = cur_base + out_size; + if (cur_base + out_size <= cur_base) { + return rc; } - } - return rc; + } } @@ -177,4 +108,94 @@ Result MapUtils::LocateSpaceForMapDeprecated(u64 *out, u64 out_size) { } } return rc; +} + +Result MapUtils::MapCodeMemoryForProcessModern(Handle process_h, u64 base_address, u64 size, u64 *out_code_memory_address) { + AddressSpaceInfo address_space = {0}; + Result rc; + + if (R_FAILED((rc = GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE)))) { + return rc; + } + + if (size > address_space.addspace_size) { + return 0x6609; + } + + u64 try_address; + for (unsigned int i = 0; i < 0x200; i++) { + while (true) { + try_address = address_space.addspace_base + (RandomUtils::GetRandomU64((u64)(address_space.addspace_size - size) >> 12) << 12); + if (address_space.heap_size && (address_space.heap_base <= try_address + size - 1 && try_address <= address_space.heap_end - 1)) { + continue; + } + if (address_space.map_size && (address_space.map_base <= try_address + size - 1 && try_address <= address_space.map_end - 1)) { + continue; + } + break; + } + rc = svcMapProcessCodeMemory(process_h, try_address, base_address, size); + if (rc != 0xD401) { + break; + } + } + if (R_SUCCEEDED(rc)) { + *out_code_memory_address = try_address; + } + return rc; +} + +Result MapUtils::MapCodeMemoryForProcessDeprecated(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address) { + Result rc; + u64 addspace_base, addspace_size; + if (is_64_bit_address_space) { + addspace_base = 0x8000000ULL; + addspace_size = 0x78000000ULL; + } else { + addspace_base = 0x200000ULL; + addspace_size = 0x3FE0000ULL; + } + + if (size > addspace_size) { + return 0x6609; + } + + u64 try_address; + for (unsigned int i = 0; i < 0x200; i++) { + try_address = addspace_base + (RandomUtils::GetRandomU64((u64)(addspace_size - size) >> 12) << 12); + rc = svcMapProcessCodeMemory(process_h, try_address, base_address, size); + if (rc != 0xD401) { + break; + } + } + if (R_SUCCEEDED(rc)) { + *out_code_memory_address = try_address; + } + return rc; +} + +Result MapUtils::GetAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h) { + Result rc; + if (R_FAILED((rc = svcGetInfo(&out->heap_base, 4, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + if (R_FAILED((rc = svcGetInfo(&out->heap_size, 5, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + if (R_FAILED((rc = svcGetInfo(&out->map_base, 2, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + if (R_FAILED((rc = svcGetInfo(&out->map_size, 3, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + if (R_FAILED((rc = svcGetInfo(&out->addspace_base, 12, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + if (R_FAILED((rc = svcGetInfo(&out->addspace_size, 13, CUR_PROCESS_HANDLE, 0)))) { + return rc; + } + out->heap_end = out->heap_base + out->heap_size; + out->map_end = out->map_base + out->map_size; + out->addspace_end = out->addspace_base + out->addspace_size; + return 0; } \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index bca18a47d..301b8f4ac 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -1,9 +1,28 @@ #pragma once #include +#include "ldr_registration.hpp" + class MapUtils { public: + struct AddressSpaceInfo { + u64 heap_base; + u64 heap_size; + u64 heap_end; + u64 map_base; + u64 map_size; + u64 map_end; + u64 addspace_base; + u64 addspace_size; + u64 addspace_end; + }; + static Result GetAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h); static Result LocateSpaceForMapDeprecated(u64 *out, u64 out_size); static Result LocateSpaceForMapModern(u64 *out, u64 out_size); static Result LocateSpaceForMap(u64 *out, u64 out_size); + + + static Result MapCodeMemoryForProcessDeprecated(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); + static Result MapCodeMemoryForProcessModern(Handle process_h, u64 base_address, u64 size, u64 *out_code_memory_address); + static Result MapCodeMemoryForProcess(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); }; \ No newline at end of file From 1d73bd0a12687355b29fe9a852551f4bb8c16f9b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 19:13:55 -0600 Subject: [PATCH 08/21] Loader: Start work on LoadNRR, Add AutoCloseMap --- stratosphere/loader/source/ldr_map.hpp | 43 +++++++++++++++++++ stratosphere/loader/source/ldr_nso.cpp | 31 ++++--------- .../loader/source/ldr_registration.cpp | 20 +++++++++ .../loader/source/ldr_registration.hpp | 5 ++- stratosphere/loader/source/ldr_ro_service.cpp | 32 +++++++++++++- 5 files changed, 105 insertions(+), 26 deletions(-) diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index 301b8f4ac..f546bf77b 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -25,4 +25,47 @@ class MapUtils { static Result MapCodeMemoryForProcessDeprecated(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); static Result MapCodeMemoryForProcessModern(Handle process_h, u64 base_address, u64 size, u64 *out_code_memory_address); static Result MapCodeMemoryForProcess(Handle process_h, bool is_64_bit_address_space, u64 base_address, u64 size, u64 *out_code_memory_address); +}; + +class AutoCloseMap { + private: + void *mapped_address; + u64 base_address; + u64 size; + Handle process_handle; + public: + AutoCloseMap() : mapped_address(0), base_address(0), size(0), process_handle(0) { }; + ~AutoCloseMap() { + Close(); + } + + void *GetMappedAddress() { + return this->mapped_address; + } + + Result Open(Handle process_h, u64 address, u64 size) { + Result rc; + u64 try_address; + if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) { + return rc; + } + + if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, try_address, size)))) { + return rc; + } + + this->mapped_address = (void *)try_address; + this->process_handle = process_h; + this->base_address = address; + this->size = size; + return 0; + } + + void Close() { + if (this->mapped_address) { + if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { + /* TODO: panic(). */ + } + } + } }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index 9011725c7..4e70d75b9 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -224,17 +224,13 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo Result rc = 0xA09; for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (g_nso_present[i]) { - u64 map_addr = 0; - if (R_FAILED((rc = MapUtils::LocateSpaceForMap(&map_addr, extents->nso_sizes[i])))) { - return rc; - } - - u8 *map_base = (u8 *)map_addr; - - if (R_FAILED((rc = svcMapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { + AutoCloseMap nso_map; + if (R_FAILED((rc = nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { return rc; } + u8 *map_base = (u8 *)nso_map.GetMappedAddress(); + FILE *f_nso = OpenNso(i, title_id); if (f_nso == NULL) { /* Is there a better error to return here? */ @@ -243,7 +239,6 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo for (unsigned int seg = 0; seg < 3; seg++) { if (R_FAILED((rc = LoadNsoSegment(i, seg, f_nso, map_base, map_base + extents->nso_sizes[i])))) { fclose(f_nso); - svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i]); return rc; } } @@ -262,9 +257,7 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo u64 bss_base = rw_base + g_nso_headers[i].segments[2].decomp_size, bss_size = g_nso_headers[i].segments[2].align_or_total_size; std::fill(map_base + bss_base, map_base + bss_base + bss_size, 0); - if (R_FAILED((rc = svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { - return rc; - } + nso_map.Close(); for (unsigned int seg = 0; seg < 3; seg++) { u64 size = g_nso_headers[i].segments[seg].decomp_size; @@ -283,25 +276,19 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo /* Map in arguments. */ if (args != NULL && args_size) { - u64 arg_map_addr = 0; - if (R_FAILED((rc = MapUtils::LocateSpaceForMap(&arg_map_addr, extents->args_size)))) { + AutoCloseMap args_map; + if (R_FAILED((rc = args_map.Open(process_h, extents->args_address, extents->args_size)))) { return rc; } - NsoArgument *arg_map_base = (NsoArgument *)arg_map_addr; - - if (R_FAILED((rc = svcMapProcessMemory(arg_map_base, process_h, extents->args_address, extents->args_size)))) { - return rc; - } + NsoArgument *arg_map_base = (NsoArgument *)args_map.GetMappedAddress(); arg_map_base->allocated_space = extents->args_size; arg_map_base->args_size = args_size; std::fill(arg_map_base->_0x8, arg_map_base->_0x8 + sizeof(arg_map_base->_0x8), 0); std::copy(args, args + args_size, arg_map_base->arguments); - if (R_FAILED((rc = svcUnmapProcessMemory(arg_map_base, process_h, extents->args_address, extents->args_size)))) { - return rc; - } + args_map.Close(); if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3)))) { return rc; diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 7ff8a676c..0299dbc64 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -104,6 +104,26 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig } +Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* TODO: panic() */ + return 0x7009; + } + + for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { + if (!target_process->nrr_infos[i].in_use) { + target_process->nrr_infos[i].info.base_address = base_address; + target_process->nrr_infos[i].info.size = size; + target_process->nrr_infos[i].info.code_memory_address = code_memory_address; + target_process->nrr_infos[i].info.loader_address = loader_address; + return 0; + } + } + return 0x7009; +} + + Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { Registration::Process *target_process = GetProcessByProcessId(process_id); if (target_process == NULL) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 1c1483eec..53deb2aa5 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -23,7 +23,7 @@ class Registration { u64 base_address; u64 size; u64 code_memory_address; - u64 address_for_loader; + u64 loader_address; }; struct NrrInfoHolder { @@ -45,7 +45,7 @@ class Registration { Registration::TidSid tid_sid; Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; Registration::NrrInfoHolder nrr_infos[NRR_INFO_MAX]; - u64 _0x730; + void *owner_ro_service; }; struct List { @@ -61,5 +61,6 @@ class Registration { static bool UnregisterIndex(u64 index); static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); + static Result AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 2375a0b0b..ff4ad97df 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -4,6 +4,7 @@ #include "ldr_ro_service.hpp" #include "ldr_registration.hpp" +#include "ldr_map.hpp" Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; @@ -42,8 +43,34 @@ std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, } std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { - /* TODO */ - return std::make_tuple(0xF601); + Result rc; + Registration::Process *target_proc; + if (!this->has_initialized || this->process_id != pid_desc.pid) { + rc = 0xAE09; + goto LOAD_NRR_END; + } + if (nrr_address & 0xFFF) { + rc = 0xA209; + goto LOAD_NRR_END; + } + if (nrr_address + nrr_size <= nrr_address || !nrr_size || (nrr_size & 0xFFF)) { + rc = 0xA409; + goto LOAD_NRR_END; + } + + 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; + } + target_proc->owner_ro_service = this; + + + /* TODO: Implement remainder of fucntion */ + rc = 0xDED09; + +LOAD_NRR_END: + return std::make_tuple(rc); } std::tuple RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) { @@ -59,6 +86,7 @@ std::tuple RelocatableObjectsService::initialize(PidDescriptor pid_desc, svcCloseHandle(this->process_handle); } this->process_handle = process_h.handle; + this->process_id = handle_pid; this->has_initialized = true; rc = 0; } From 789afe7929043b78a972eb2fd609b231de186f42 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 19:43:26 -0600 Subject: [PATCH 09/21] Loader: fix missing reassignment in AutoCloseMap --- stratosphere/loader/source/ldr_map.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index f546bf77b..52948f371 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -66,6 +66,7 @@ class AutoCloseMap { if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { /* TODO: panic(). */ } + this->mapped_address = NULL; } } }; \ No newline at end of file From 8524f284fd38e19a4168769bccba2e4e89feac5b Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 20:27:52 -0600 Subject: [PATCH 10/21] Loader: Implement ldr:ro->LoadNRR(). NOTE: No sigchecks, at the moment. --- stratosphere/loader/source/ldr_map.hpp | 62 ++++++++++++++++++- stratosphere/loader/source/ldr_nro.cpp | 28 +++++++++ stratosphere/loader/source/ldr_nro.hpp | 33 ++++++++++ .../loader/source/ldr_registration.cpp | 9 +-- .../loader/source/ldr_registration.hpp | 18 ++---- stratosphere/loader/source/ldr_ro_service.cpp | 18 +++++- 6 files changed, 143 insertions(+), 25 deletions(-) create mode 100644 stratosphere/loader/source/ldr_nro.cpp create mode 100644 stratosphere/loader/source/ldr_nro.hpp diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index 52948f371..3a0c3885f 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -1,8 +1,6 @@ #pragma once #include -#include "ldr_registration.hpp" - class MapUtils { public: struct AddressSpaceInfo { @@ -69,4 +67,64 @@ class AutoCloseMap { this->mapped_address = NULL; } } +}; + +struct MappedCodeMemory { + Handle process_handle; + u64 base_address; + u64 size; + u64 code_memory_address; + void *mapped_address; + + bool IsActive() { + return this->mapped_address != NULL; + } + + /* Utility functions. */ + Result Open(Handle process_h, bool is_64_bit_address_space, u64 address, u64 size) { + Result rc; + u64 try_address; + if (this->IsActive()) { + return 0x19009; + } + + this->process_handle = process_h; + this->base_address = address; + this->size = size; + + if (R_FAILED((rc = MapUtils::MapCodeMemoryForProcess(process_h, is_64_bit_address_space, address, size, &this->code_memory_address)))) { + goto CODE_MEMORY_OPEN_END; + } + + if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) { + goto CODE_MEMORY_OPEN_END; + } + + if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, try_address, size)))) { + goto CODE_MEMORY_OPEN_END; + } + + this->mapped_address = (void *)try_address; + + CODE_MEMORY_OPEN_END: + if (R_FAILED(rc)) { + if (this->code_memory_address && R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) { + /* TODO: panic(). */ + } + *this = (const MappedCodeMemory){0}; + } + return rc; + } + + void Close() { + if (this->IsActive()) { + if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { + /* TODO: panic(). */ + } + if (R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) { + /* TODO: panic(). */ + } + *this = (const MappedCodeMemory){0}; + } + } }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp new file mode 100644 index 000000000..611223b16 --- /dev/null +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include "ldr_nro.hpp" +#include "ldr_map.hpp" +#include "ldr_random.hpp" + +Result NroUtils::ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min) { + if (header->magic != MAGIC_NRR0) { + return 0x6A09; + } + if (header->nrr_size != size) { + return 0xA409; + } + + /* TODO: Check NRR signature. */ + if (false) { + return 0x6C09; + } + + if (header->title_id_min != title_id_min) { + return 0x6A09; + } + + return 0x0; +} \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nro.hpp b/stratosphere/loader/source/ldr_nro.hpp new file mode 100644 index 000000000..ef39d41ae --- /dev/null +++ b/stratosphere/loader/source/ldr_nro.hpp @@ -0,0 +1,33 @@ +#pragma once +#include +#include + +#define MAGIC_NRO0 0x304F524E +#define MAGIC_NRR0 0x3052524E + +class NroUtils { + public: + struct NrrHeader { + u32 magic; + u32 _0x4; + u32 _0x8; + u32 _0xC; + u64 title_id_mask; + u64 title_id_pattern; + u64 _0x20; + u64 _0x28; + u8 modulus[0x100]; + u8 fixed_key_signature[0x100]; + u8 nrr_signature[0x100]; + u64 title_id_min; + u32 nrr_size; + u32 _0x33C; + u32 hash_offset; + u32 num_hashes; + u64 _0x348; + }; + + + static_assert(sizeof(NrrHeader) == 0x350, "Incorrectly defined NrrHeader!"); + static Result ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min); +}; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 0299dbc64..a952174c2 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -104,7 +104,7 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig } -Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address) { +Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { Registration::Process *target_process = GetProcess(index); if (target_process == NULL) { /* TODO: panic() */ @@ -112,11 +112,8 @@ Result Registration::AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_ } for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { - if (!target_process->nrr_infos[i].in_use) { - target_process->nrr_infos[i].info.base_address = base_address; - target_process->nrr_infos[i].info.size = size; - target_process->nrr_infos[i].info.code_memory_address = code_memory_address; - target_process->nrr_infos[i].info.loader_address = loader_address; + if (!target_process->nrr_infos[i].IsActive()) { + target_process->nrr_infos[i] = *nrr_info; return 0; } } diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 53deb2aa5..713d56b48 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include "ldr_map.hpp" + #define REGISTRATION_LIST_MAX (0x40) #define NSO_INFO_MAX (0x20) @@ -19,18 +21,6 @@ class Registration { NsoInfo info; }; - struct NrrInfo { - u64 base_address; - u64 size; - u64 code_memory_address; - u64 loader_address; - }; - - struct NrrInfoHolder { - bool in_use; - NrrInfo info; - }; - struct TidSid { u64 title_id; FsStorageId storage_id; @@ -44,7 +34,7 @@ class Registration { u64 title_id_min; Registration::TidSid tid_sid; Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; - Registration::NrrInfoHolder nrr_infos[NRR_INFO_MAX]; + MappedCodeMemory nrr_infos[NRR_INFO_MAX]; void *owner_ro_service; }; @@ -61,6 +51,6 @@ class Registration { static bool UnregisterIndex(u64 index); static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); - static Result AddNrrInfo(u64 index, u64 base_address, u64 size, u64 code_memory_address, u64 loader_address); + static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index ff4ad97df..2512d94d7 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -5,6 +5,7 @@ #include "ldr_ro_service.hpp" #include "ldr_registration.hpp" #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; @@ -44,7 +45,8 @@ std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { Result rc; - Registration::Process *target_proc; + Registration::Process *target_proc = NULL; + MappedCodeMemory nrr_info = {0}; if (!this->has_initialized || this->process_id != pid_desc.pid) { rc = 0xAE09; goto LOAD_NRR_END; @@ -65,11 +67,21 @@ std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u } 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; + } - /* TODO: Implement remainder of fucntion */ - rc = 0xDED09; + rc = NroUtils::ValidateNrrHeader((NroUtils::NrrHeader *)nrr_info.mapped_address, nrr_size, target_proc->title_id_min); + if (R_SUCCEEDED(rc)) { + Registration::AddNrrInfo(target_proc->index, &nrr_info); + } LOAD_NRR_END: + if (R_FAILED(rc)) { + if (nrr_info.IsActive()) { + nrr_info.Close(); + } + } return std::make_tuple(rc); } From e7aa5c246bc9d94b4dd97113449e9ed736df6f5e Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 20:37:38 -0600 Subject: [PATCH 11/21] Loader: Implement ldr:ro->UnloadNrr() --- stratosphere/loader/source/ldr_registration.cpp | 17 ++++++++++++++++- stratosphere/loader/source/ldr_registration.hpp | 1 + stratosphere/loader/source/ldr_ro_service.cpp | 17 +++++++++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index a952174c2..c7246d5cd 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -111,7 +111,7 @@ Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { return 0x7009; } - for (unsigned int i = 0; i < NSO_INFO_MAX; i++) { + for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { if (!target_process->nrr_infos[i].IsActive()) { target_process->nrr_infos[i] = *nrr_info; return 0; @@ -120,6 +120,21 @@ Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { return 0x7009; } +Result Registration::RemoveNrrInfo(u64 index, u64 base_address) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* Despite the fact that this should really be a panic condition, Nintendo returns 0x1009 in this case. */ + return 0x1009; + } + + for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { + if (target_process->nrr_infos[i].IsActive() && target_process->nrr_infos[i].base_address == base_address) { + target_process->nrr_infos[i].Close(); + return 0; + } + } + return 0xAA09; +} Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { Registration::Process *target_process = GetProcessByProcessId(process_id); diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 713d56b48..8492248f0 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -52,5 +52,6 @@ class Registration { static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info); + static Result RemoveNrrInfo(u64 index, u64 base_address); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 2512d94d7..d32c102d0 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -86,8 +86,21 @@ LOAD_NRR_END: } std::tuple RelocatableObjectsService::unload_nrr(PidDescriptor pid_desc, u64 nrr_address) { - /* TODO */ - return std::make_tuple(0xF601); + Registration::Process *target_proc = NULL; + if (!this->has_initialized || this->process_id != pid_desc.pid) { + return 0xAE09; + } + if (nrr_address & 0xFFF) { + return 0xA209; + } + + target_proc = Registration::GetProcessByProcessId(pid_desc.pid); + if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) { + return 0xAC09; + } + target_proc->owner_ro_service = this; + + return Registration::RemoveNrrInfo(target_proc->index, nrr_address); } std::tuple RelocatableObjectsService::initialize(PidDescriptor pid_desc, CopiedHandle process_h) { From 2e7b6de195419ffd4284e9357b65d246da7d09a2 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 20:50:27 -0600 Subject: [PATCH 12/21] Loader: Automatically unload NRRs on service close. --- .../loader/source/ldr_registration.cpp | 44 +++++++++++++------ .../loader/source/ldr_registration.hpp | 2 + stratosphere/loader/source/ldr_ro_service.hpp | 6 +++ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index c7246d5cd..7df25314d 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -7,8 +7,7 @@ static Registration::List g_registration_list = {0}; static u64 g_num_registered = 1; Registration::Process *Registration::GetFreeProcess() { - unsigned int i; - for (i = 0; i < REGISTRATION_LIST_MAX; i++) { + for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) { if (!g_registration_list.processes[i].in_use) { return &g_registration_list.processes[i]; } @@ -17,24 +16,30 @@ Registration::Process *Registration::GetFreeProcess() { } Registration::Process *Registration::GetProcess(u64 index) { - unsigned int i; - for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].index != index); i++) { + for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) { + if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].index == index) { + return &g_registration_list.processes[i]; + } } - if (i >= REGISTRATION_LIST_MAX) { - return NULL; - } - return &g_registration_list.processes[i]; + return NULL; } Registration::Process *Registration::GetProcessByProcessId(u64 pid) { - unsigned int i; - for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].process_id != pid); i++) { - + for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) { + if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].process_id == pid) { + return &g_registration_list.processes[i]; + } } - if (i >= REGISTRATION_LIST_MAX) { - return NULL; + return NULL; +} + +Registration::Process *Registration::GetProcessByRoService(void *service) { + for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) { + if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].owner_ro_service == service) { + return &g_registration_list.processes[i]; + } } - return &g_registration_list.processes[i]; + return NULL; } bool Registration::RegisterTidSid(const TidSid *tid_sid, u64 *out_index) { @@ -103,6 +108,17 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig } } +void Registration::CloseRoService(void *service, Handle process_h) { + Registration::Process *target_process = GetProcessByRoService(service); + if (target_process == NULL) { + return; + } + for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { + if (target_process->nrr_infos[i].IsActive() && target_process->nrr_infos[i].process_handle == process_h) { + target_process->nrr_infos[i].Close(); + } + } +} Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { Registration::Process *target_process = GetProcess(index); diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 8492248f0..f29d9e7b3 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -46,11 +46,13 @@ class Registration { static Registration::Process *GetFreeProcess(); static Registration::Process *GetProcess(u64 index); static Registration::Process *GetProcessByProcessId(u64 pid); + static Registration::Process *GetProcessByRoService(void *service); static Result GetRegisteredTidSid(u64 index, Registration::TidSid *out); static bool RegisterTidSid(const TidSid *tid_sid, u64 *out_index); static bool UnregisterIndex(u64 index); static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace); static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); + static void CloseRoService(void *service, Handle process_h); static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info); static Result RemoveNrrInfo(u64 index, u64 base_address); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); diff --git a/stratosphere/loader/source/ldr_ro_service.hpp b/stratosphere/loader/source/ldr_ro_service.hpp index f2a02f252..f47d9849b 100644 --- a/stratosphere/loader/source/ldr_ro_service.hpp +++ b/stratosphere/loader/source/ldr_ro_service.hpp @@ -18,6 +18,12 @@ class RelocatableObjectsService : IServiceObject { bool has_initialized; public: RelocatableObjectsService() : process_handle(0), process_id(U64_MAX), has_initialized(false) { } + ~RelocatableObjectsService() { + Registration::CloseRoService(this, this->process_handle); + if (this->has_initialized) { + svcCloseHandle(this->process_handle); + } + } virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size); virtual Result handle_deferred() { /* This service will never defer. */ From e43c6df98664193f3325543955fdf0354aede2c0 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 26 Apr 2018 20:51:12 -0600 Subject: [PATCH 13/21] Loader: fix missing NULL assignment --- stratosphere/loader/source/ldr_registration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 7df25314d..900499ef2 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -118,6 +118,7 @@ void Registration::CloseRoService(void *service, Handle process_h) { target_process->nrr_infos[i].Close(); } } + target_process->owner_ro_service = NULL; } Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) { From 10171313dfceb7d466db1e96cd30a4e1e0b5e67b Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 26 Apr 2018 20:45:11 -0700 Subject: [PATCH 14/21] Update README.md (#70) --- thermosphere/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/thermosphere/README.md b/thermosphere/README.md index 6b4e9df6d..cb8f6d5df 100644 --- a/thermosphere/README.md +++ b/thermosphere/README.md @@ -1,6 +1,6 @@ -Thermoshère +Thermosphère ===== ![License](https://img.shields.io/badge/License-GPLv2-blue.svg) -Thermoshère is a hypervisor for the Nintendo Switch. +Thermosphère is a hypervisor for the Nintendo Switch. From 772e41971da571bd66e756f2debebbcd3d5b099f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Apr 2018 03:17:07 -0600 Subject: [PATCH 15/21] Loader: Add ldr:ro->LoadNro() --- stratosphere/loader/source/ldr_map.hpp | 73 ++++++++++----- stratosphere/loader/source/ldr_nro.cpp | 88 +++++++++++++++++++ stratosphere/loader/source/ldr_nro.hpp | 23 +++++ .../loader/source/ldr_registration.cpp | 70 +++++++++++++++ .../loader/source/ldr_registration.hpp | 19 ++++ stratosphere/loader/source/ldr_ro_service.cpp | 40 ++++++++- 6 files changed, 288 insertions(+), 25 deletions(-) diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index 3a0c3885f..fb8fcc2fc 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -77,13 +77,16 @@ struct MappedCodeMemory { void *mapped_address; bool IsActive() { + return this->code_memory_address != 0; + } + + bool IsMapped() { return this->mapped_address != NULL; } /* Utility functions. */ Result Open(Handle process_h, bool is_64_bit_address_space, u64 address, u64 size) { Result rc; - u64 try_address; if (this->IsActive()) { return 0x19009; } @@ -91,40 +94,64 @@ struct MappedCodeMemory { this->process_handle = process_h; this->base_address = address; this->size = size; - - if (R_FAILED((rc = MapUtils::MapCodeMemoryForProcess(process_h, is_64_bit_address_space, address, size, &this->code_memory_address)))) { - goto CODE_MEMORY_OPEN_END; - } - - if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) { - goto CODE_MEMORY_OPEN_END; + + if (R_FAILED((rc = MapUtils::MapCodeMemoryForProcess(this->process_handle, is_64_bit_address_space, this->base_address, this->size, &this->code_memory_address)))) { + Close(); + } + return rc; + } + + Result OpenAtAddress(Handle process_h, u64 address, u64 size, u64 target_code_memory_address) { + Result rc; + if (this->IsActive()) { + return 0x19009; } + this->process_handle = process_h; + this->base_address = address; + this->size = size; - if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, process_h, try_address, size)))) { - goto CODE_MEMORY_OPEN_END; - } - - this->mapped_address = (void *)try_address; - - CODE_MEMORY_OPEN_END: - if (R_FAILED(rc)) { - if (this->code_memory_address && R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) { - /* TODO: panic(). */ - } - *this = (const MappedCodeMemory){0}; + if (R_SUCCEEDED((rc = svcMapProcessCodeMemory(this->process_handle, target_code_memory_address, this->base_address, this->size)))) { + this->code_memory_address = target_code_memory_address; + } else { + Close(); } return rc; } - void Close() { - if (this->IsActive()) { + Result Map() { + Result rc; + u64 try_address; + if (this->IsMapped()) { + return 0x19009; + } + if (R_FAILED(rc = MapUtils::LocateSpaceForMap(&try_address, size))) { + return rc; + } + + if (R_FAILED((rc = svcMapProcessMemory((void *)try_address, this->process_handle, try_address, size)))) { + return rc; + } + + this->mapped_address = (void *)try_address; + return rc; + } + + void Unmap() { + if (this->IsMapped()) { if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { /* TODO: panic(). */ } + } + this->mapped_address = NULL; + } + + void Close() { + Unmap(); + if (this->IsActive()) { if (R_FAILED(svcUnmapProcessCodeMemory(this->process_handle, this->code_memory_address, this->base_address, this->size))) { /* TODO: panic(). */ } - *this = (const MappedCodeMemory){0}; } + *this = (const MappedCodeMemory){0}; } }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp index 611223b16..3f95c7a50 100644 --- a/stratosphere/loader/source/ldr_nro.cpp +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -4,6 +4,7 @@ #include #include #include "ldr_nro.hpp" +#include "ldr_registration.hpp" #include "ldr_map.hpp" #include "ldr_random.hpp" @@ -24,5 +25,92 @@ Result NroUtils::ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min return 0x6A09; } + return 0x0; +} + +Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size, u64 *out_address) { + NroHeader *nro; + MappedCodeMemory mcm_nro; + MappedCodeMemory mcm_bss; + unsigned int i; + Result rc; + u8 nro_hash[0x20]; + /* Ensure there is an available NRO slot. */ + for (i = 0; i < NRO_INFO_MAX; i++) { + if (!target_proc->nro_infos[i].in_use) { + break; + } + } + if (i >= NRO_INFO_MAX) { + return 0x6E09; + } + for (i = 0; i < 0x200; i++) { + if (R_SUCCEEDED(mcm_nro.Open(process_h, target_proc->is_64_bit_addspace, nro_heap_address, nro_heap_size))) { + if (R_SUCCEEDED(mcm_bss.OpenAtAddress(process_h, bss_heap_address, bss_heap_size, nro_heap_address + nro_heap_size))) { + break; + } else { + mcm_nro.Close(); + } + } + } + if (i >= 0x200) { + return 0x6609; + } + if (R_FAILED((rc = mcm_nro.Map()))) { + goto LOAD_NRO_END; + } + + nro = (NroHeader *)mcm_nro.mapped_address; + if (nro->magic != MAGIC_NRO0) { + rc = 0x6809; + goto LOAD_NRO_END; + } + if (nro->nro_size != nro_heap_size || nro->bss_size != bss_heap_size) { + rc = 0x6809; + goto LOAD_NRO_END; + } + if ((nro->text_size & 0xFFF) || (nro->ro_size & 0xFFF) || (nro->rw_size & 0xFFF) || (nro->bss_size & 0xFFF)) { + rc = 0x6809; + goto LOAD_NRO_END; + } + if (nro->text_offset != 0 || nro->text_offset + nro->text_size != nro->ro_offset || nro->ro_offset + nro->ro_size != nro->rw_offset || nro->rw_offset + nro->rw_size != nro->nro_size) { + rc = 0x6809; + goto LOAD_NRO_END; + } + + picosha2::hash256((u8 *)nro, (u8 *)nro + nro->nro_size, nro_hash, nro_hash + sizeof(nro_hash)); + + if (!Registration::IsNroHashPresent(target_proc->index, nro_hash)) { + rc = 0x6C09; + goto LOAD_NRO_END; + } + + if (Registration::IsNroAlreadyLoaded(target_proc->index, nro_hash)) { + rc = 0x7209; + goto LOAD_NRO_END; + } + + if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address, nro->text_size, 5)))) { + goto LOAD_NRO_END; + } + + if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro->ro_offset, nro->ro_size, 1)))) { + goto LOAD_NRO_END; + } + + if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, mcm_nro.code_memory_address + nro->rw_offset, nro->rw_size + nro->bss_size, 3)))) { + goto LOAD_NRO_END; + } + + Registration::AddNroToProcess(target_proc->index, &mcm_nro, &mcm_bss, nro->text_size, nro->ro_size, nro->rw_size, nro->build_id); + mcm_nro.Unmap(); + mcm_bss.Unmap(); + rc = 0x0; + +LOAD_NRO_END: + if (R_FAILED(rc)) { + mcm_nro.Close(); + mcm_bss.Close(); + } return 0x0; } \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_nro.hpp b/stratosphere/loader/source/ldr_nro.hpp index ef39d41ae..497278fad 100644 --- a/stratosphere/loader/source/ldr_nro.hpp +++ b/stratosphere/loader/source/ldr_nro.hpp @@ -2,6 +2,7 @@ #include #include +#include "ldr_registration.hpp" #define MAGIC_NRO0 0x304F524E #define MAGIC_NRR0 0x3052524E @@ -27,7 +28,29 @@ class NroUtils { u64 _0x348; }; + struct NroHeader { + u32 entrypoint_insn; + u32 mod_offset; + u64 padding; + u32 magic; + u32 _0x14; + u32 nro_size; + u32 _0x1C; + u32 text_offset; + u32 text_size; + u32 ro_offset; + u32 ro_size; + u32 rw_offset; + u32 rw_size; + u32 bss_size; + u32 _0x3C; + unsigned char build_id[0x20]; + u8 _0x60[0x20]; + }; + static_assert(sizeof(NrrHeader) == 0x350, "Incorrectly defined NrrHeader!"); + static_assert(sizeof(NroHeader) == 0x80, "Incorrectly defined NroHeader!"); static Result ValidateNrrHeader(NrrHeader *header, u64 size, u64 title_id_min); + static Result LoadNro(Registration::Process *target_proc, Handle process_h, u64 nro_heap_address, u64 nro_heap_size, u64 bss_heap_address, u64 bss_heap_size, u64 *out_address); }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 900499ef2..2f9578fb9 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -1,7 +1,9 @@ #include #include #include +#include #include "ldr_registration.hpp" +#include "ldr_nro.hpp" static Registration::List g_registration_list = {0}; static u64 g_num_registered = 1; @@ -153,6 +155,74 @@ Result Registration::RemoveNrrInfo(u64 index, u64 base_address) { return 0xAA09; } + +bool Registration::IsNroHashPresent(u64 index, u8 *nro_hash) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* TODO: panic */ + return false; + } + + for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { + if (target_process->nrr_infos[i].IsActive()) { + NroUtils::NrrHeader *nrr = (NroUtils::NrrHeader *)target_process->nrr_infos[i].mapped_address; + /* Binary search. */ + int low = 0, high = (int)(nrr->num_hashes - 1); + while (low <= high) { + int mid = (low + high) / 2; + u8 *hash_in_nrr = (u8 *)nrr + nrr->hash_offset + 0x20 * mid; + int ret = std::memcmp(hash_in_nrr, nro_hash, 0x20); + if (ret == 0) { + return true; + } else if (ret > 0) { + high = mid - 1; + } else { + low = mid + 1; + } + } + } + } + return false; +} + +bool Registration::IsNroAlreadyLoaded(u64 index, u8 *build_id) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* TODO: panic */ + return true; + } + + for (unsigned int i = 0; i < NRO_INFO_MAX; i++) { + if (target_process->nro_infos[i].in_use && std::memcmp(target_process->nro_infos[i].build_id, build_id, 0x20) == 0) { + return true; + } + } + return false; +} + +void Registration::AddNroToProcess(u64 index, MappedCodeMemory *nro, MappedCodeMemory *bss, u32 text_size, u32 ro_size, u32 rw_size, u8 *build_id) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + /* TODO: panic */ + return; + } + + for (unsigned int i = 0; i < NRO_INFO_MAX; i++) { + if (!target_process->nro_infos[i].in_use) { + target_process->nro_infos[i].base_address = nro->code_memory_address; + target_process->nro_infos[i].nro_heap_address = nro->base_address; + target_process->nro_infos[i].nro_heap_size = nro->size; + target_process->nro_infos[i].bss_heap_address = bss->base_address; + target_process->nro_infos[i].bss_heap_size = bss->size; + target_process->nro_infos[i].text_size = text_size; + target_process->nro_infos[i].ro_size = ro_size; + target_process->nro_infos[i].rw_size = rw_size; + std::copy(build_id, build_id + sizeof(target_process->nro_infos[i].build_id), target_process->nro_infos[i].build_id); + target_process->nro_infos[i].in_use = true; + } + } +} + Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { Registration::Process *target_process = GetProcessByProcessId(process_id); if (target_process == NULL) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index f29d9e7b3..dc79995ec 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -7,6 +7,7 @@ #define NSO_INFO_MAX (0x20) #define NRR_INFO_MAX (0x40) +#define NRO_INFO_MAX (0x40) class Registration { public: @@ -21,6 +22,20 @@ class Registration { NsoInfo info; }; + struct NroInfo { + bool in_use; + u64 base_address; + u64 total_mapped_size; + u64 nro_heap_address; + u64 nro_heap_size; + u64 bss_heap_address; + u64 bss_heap_size; + u64 text_size; + u64 ro_size; + u64 rw_size; + unsigned char build_id[0x20]; + }; + struct TidSid { u64 title_id; FsStorageId storage_id; @@ -34,6 +49,7 @@ class Registration { u64 title_id_min; Registration::TidSid tid_sid; Registration::NsoInfoHolder nso_infos[NSO_INFO_MAX]; + Registration::NroInfo nro_infos[NRO_INFO_MAX]; MappedCodeMemory nrr_infos[NRR_INFO_MAX]; void *owner_ro_service; }; @@ -55,5 +71,8 @@ class Registration { static void CloseRoService(void *service, Handle process_h); static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info); static Result RemoveNrrInfo(u64 index, u64 base_address); + static bool IsNroHashPresent(u64 index, u8 *nro_hash); + static bool IsNroAlreadyLoaded(u64 index, u8 *build_id); + static void AddNroToProcess(u64 index, MappedCodeMemory *nro, MappedCodeMemory *bss, u32 text_size, u32 ro_size, u32 rw_size, u8 *build_id); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index d32c102d0..1e6b23206 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -34,8 +34,40 @@ Result RelocatableObjectsService::dispatch(IpcParsedCommand &r, IpcCommand &out_ std::tuple RelocatableObjectsService::load_nro(PidDescriptor pid_desc, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { - /* TODO */ - return std::make_tuple(0xF601, 0); + Result rc; + u64 out_address = 0; + Registration::Process *target_proc = NULL; + if (!this->has_initialized || this->process_id != pid_desc.pid) { + rc = 0xAE09; + goto LOAD_NRO_END; + } + if (nro_address & 0xFFF) { + rc = 0xA209; + goto LOAD_NRO_END; + } + if (nro_address + nro_size <= nro_address || !nro_size || (nro_size & 0xFFF)) { + rc = 0xA409; + goto LOAD_NRO_END; + } + if (bss_size && bss_address + bss_size <= bss_address) { + rc = 0xA409; + goto LOAD_NRO_END; + } + /* Ensure no overflow for combined sizes. */ + if (U64_MAX - nro_size < bss_size) { + rc = 0xA409; + goto LOAD_NRO_END; + } + 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; + } + 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 std::make_tuple(rc, out_address); } std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, u64 nro_address) { @@ -71,6 +103,10 @@ std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u goto LOAD_NRR_END; } + if (R_FAILED((rc = nrr_info.Map()))) { + goto LOAD_NRR_END; + } + rc = NroUtils::ValidateNrrHeader((NroUtils::NrrHeader *)nrr_info.mapped_address, nrr_size, target_proc->title_id_min); if (R_SUCCEEDED(rc)) { Registration::AddNrrInfo(target_proc->index, &nrr_info); From 4e1a29f618d93447d57030b85dc45f538402a57d Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Apr 2018 03:33:44 -0600 Subject: [PATCH 16/21] Loader: Finish ldr:ro --- stratosphere/loader/source/ldr_nro.cpp | 1 + .../loader/source/ldr_registration.cpp | 23 +++++++++++++++++++ .../loader/source/ldr_registration.hpp | 1 + stratosphere/loader/source/ldr_ro_service.cpp | 17 ++++++++++++-- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/stratosphere/loader/source/ldr_nro.cpp b/stratosphere/loader/source/ldr_nro.cpp index 3f95c7a50..120587fd6 100644 --- a/stratosphere/loader/source/ldr_nro.cpp +++ b/stratosphere/loader/source/ldr_nro.cpp @@ -103,6 +103,7 @@ Result NroUtils::LoadNro(Registration::Process *target_proc, Handle process_h, u } Registration::AddNroToProcess(target_proc->index, &mcm_nro, &mcm_bss, nro->text_size, nro->ro_size, nro->rw_size, nro->build_id); + *out_address = mcm_nro.code_memory_address; mcm_nro.Unmap(); mcm_bss.Unmap(); rc = 0x0; diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 2f9578fb9..ab0fce037 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -223,6 +223,29 @@ void Registration::AddNroToProcess(u64 index, MappedCodeMemory *nro, MappedCodeM } } +Result Registration::RemoveNroInfo(u64 index, Handle process_h, u64 nro_heap_address) { + Registration::Process *target_process = GetProcess(index); + if (target_process == NULL) { + return 0xA809; + } + + for (unsigned int i = 0; i < NRR_INFO_MAX; i++) { + if (target_process->nro_infos[i].in_use && target_process->nro_infos[i].nro_heap_address == nro_heap_address) { + NroInfo *info = &target_process->nro_infos[i]; + Result rc = svcUnmapProcessCodeMemory(process_h, info->base_address + info->text_size + info->ro_size + info->rw_size, info->bss_heap_address, info->bss_heap_size); + if (R_SUCCEEDED(rc)) { + rc = svcUnmapProcessCodeMemory(process_h, info->base_address + info->text_size + info->ro_size, nro_heap_address + info->text_size + info->ro_size, info->rw_size); + if (R_SUCCEEDED(rc)) { + rc = svcUnmapProcessCodeMemory(process_h, info->base_address, nro_heap_address, info->text_size + info->ro_size); + } + } + target_process->nro_infos[i] = (const NroInfo ){0}; + return rc; + } + } + return 0xA809; +} + Result Registration::GetNsoInfosForProcessId(Registration::NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written) { Registration::Process *target_process = GetProcessByProcessId(process_id); if (target_process == NULL) { diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index dc79995ec..4df3bd05d 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -74,5 +74,6 @@ class Registration { static bool IsNroHashPresent(u64 index, u8 *nro_hash); static bool IsNroAlreadyLoaded(u64 index, u8 *build_id); static void AddNroToProcess(u64 index, MappedCodeMemory *nro, MappedCodeMemory *bss, u32 text_size, u32 ro_size, u32 rw_size, u8 *build_id); + static Result RemoveNroInfo(u64 index, Handle process_h, u64 base_address); static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written); }; diff --git a/stratosphere/loader/source/ldr_ro_service.cpp b/stratosphere/loader/source/ldr_ro_service.cpp index 1e6b23206..020db98c1 100644 --- a/stratosphere/loader/source/ldr_ro_service.cpp +++ b/stratosphere/loader/source/ldr_ro_service.cpp @@ -71,8 +71,21 @@ LOAD_NRO_END: } std::tuple RelocatableObjectsService::unload_nro(PidDescriptor pid_desc, u64 nro_address) { - /* TODO */ - return std::make_tuple(0xF601); + Registration::Process *target_proc = NULL; + if (!this->has_initialized || this->process_id != pid_desc.pid) { + return 0xAE09; + } + if (nro_address & 0xFFF) { + return 0xA209; + } + + target_proc = Registration::GetProcessByProcessId(pid_desc.pid); + if (target_proc == NULL || (target_proc->owner_ro_service != NULL && (RelocatableObjectsService *)(target_proc->owner_ro_service) != this)) { + return 0xAC09; + } + target_proc->owner_ro_service = this; + + return Registration::RemoveNroInfo(target_proc->index, this->process_handle, nro_address); } std::tuple RelocatableObjectsService::load_nrr(PidDescriptor pid_desc, u64 nrr_address, u64 nrr_size) { From 0d25f342c6e6f6814ceea8fd7869ea64ec888dd4 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Apr 2018 03:56:06 -0600 Subject: [PATCH 17/21] Add banner to README --- README.md | 2 ++ img/banner.png | Bin 0 -> 13849 bytes img/banner_light.png | Bin 0 -> 14121 bytes 3 files changed, 2 insertions(+) create mode 100644 img/banner.png create mode 100644 img/banner_light.png diff --git a/README.md b/README.md index 400b84b9b..ec8e7140d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ Atmosphère-NX ===== +![Banner](img/banner.png?raw=true) + ![License](https://img.shields.io/badge/License-GPLv2-blue.svg) Atmosphère is a work-in-progress customized firmware for the Nintendo Switch. diff --git a/img/banner.png b/img/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..c056934152b84f781c2484b1bfa40d7b399180ee GIT binary patch literal 13849 zcmeHuXH-+$w=Wh=@IXum0mb;Az^$t5f^4vWUz7{5~X*0NPJLbdfdiKbI*QLZXLhlk!PH|9OP} z=hdl=8~>)_dm9qC5X-0_^lv&u4<#@BbG^VoRpN{5zRqk`r2nD=32e9c4lRA?jdc2;~-$Jys;;}V#8ka7K4?obtMDiP4nvEyd z4vUvQcOTY4l8futj;S;P&h}cff+#a9{AQ@GxLBi0N`7W5K~M0kZ%fD@10(=BJeXdO zc5XglV<<{DyXn>1LdhRWbZ#1!Dgg2Mp@s1?W2C(H*B3t{F^`@+(l~10%}*{W)O@k8 z|1fsx>J-NkEE5g935lU7cfe?sG~tY5Qqi75Czd)O{eXPSG4{X37f2vLy~f}s3rIdj zpOufVm(*k5oM@{}g<;YvDtCnS)|m-MSpp{h-n~6f0PkFZe!MQBgvUur8DCkBZA-&6 z?wz~bE#ReFthTrDUumssJ~>>aj%`tMZKiFY`c#McRa$p@vA8CM>;*sCEQ~hls)!Ki#^l@jnah&V&sw$wS4OdVe1t9ULS)$d6s<>tN zVM11JZhOP)VfEz#H_ktA3gF*#=E@^Gf78m!O7vw{zeB>kYq}$hB~8!DaeuQa4Y10L zBXT=)lrK;-+`V+8Zwl;PY}w>wif_)8kOAmEJS-yij3Wlkm#4?O@{7`nfO*(m_`|?F z9c!}pg`i$ptn4G*R;pFM=?*2{DlF{{=s~yeX zD*?o8_`OQboSSu~q*1NbZFz-}+^)OYhJRDp$MPcH+#u8BfCZt!nQg#Lpa8KfR9yBg z<-{1h9l3q$m(L+jCjO`>T?|MrNsnPR=T>>owF7d)Ei52})owzKW--ae)KA|_U@feL#WwlRtu)S51A8p!DNq2r`r=Gb4Ie*k}@!{|YyC-9w&Mjns5vNUW zW6!qh#7ypnaedCWZ>go`%F#WaHf-v(qP@?g@LL|pj&h*b9DH`%xI0kmcLiJ5ZOmDY zWG&Hn{IJe-$!0e(?)ny#8BVwIhS*ny-~~5_*=-7K+m9^s#qk0b{BdSBpr=~qZ_7J7 zKPUzpxTB>T_vgv*VPAh3`t+QL96&^BFD4#O#ECm95ymsI<{g}sYms$cnpTIb~)bUr@#uK;qwt`@PJLU9*xM(^M zbAEolpy^1^=I{hdXIsP%CryF7!T5MQB?Z(urzlNbeDG+EfINL#u+8N9VRqK-3t{3e z+6u8=f*^i{GfAqQz@m_uoK`n;4~Y~lLdSAZJ}T5f+3~Xv$MY8wk_G8`F?TRMh8$Z7 zbP9FDV=*JQztfFPo|fB=Jv!LK$f7-GE+9p#sCx}~N}y+iK>*<dS_4$z-Do;>vv{uw75bFQ$DipdF?Lmidxs z3_Uz zFnTtbxk0OUGIIou5fuzLd6WqDF?{}5=P^ETL(-!GH)J4>d3EM+1;o1Zt{=ZOh9=AL zB5j)to)at(8>sXZ$nl`;K-Gmq9^1B;wZVZ%K9GEQgQxp<+|DLhrR{)azo;2@M`Yk| zus*lS*6zKlbuu5HVDcJM!>u|Tdz$}2T#^a0iQAYF-0kuYc3` z@+-jIyRQ)Vx5pe@xn(1n<{`YrA><{l!LOHE4ASLPLqsP~IX6&-jSzxd3J;@~2Ibm) zI1xpO>6}zs{}rdQCBBf&M3jniUt*mptVgd=x^`jV(|e=|CV8abdFnRWnZoN32AvH1 z`s7^1EdX6g&Mbm6?zPj?x9(Yu_(PswU69e`%yVV~mu(O4v_b}QLSa*?9>fb(pOZ&~ zEW*j}c8lr88DZA8WHGK6zzrX8BhDcuI_1W(N8%f#s3{LbRwa~n2{|6ZoS z<`ulT5D-z)0+Bk8b%71|eDOsP-53d?p}pl61A}Lx!EPEvAUWatsuRWR;IW}3mu6UF z_ySIJ?txxkQ*Aa-J?>o;cS^%Kbq~jebXC0(OBmD;4tPU;H2(=*Pr@TA4~?ubKdFD# zOIubx6M5Ww=xNjyMqBvGU77zZl}{PreG{#x`xfsa&(aka{MdO44I%=chTLIvOboCi z$RSKKfM4pXe<jCltLxU%KzWGtd#*d+aeqhc-xNA zW92D?-0k97g*MV_>)20omKD29jUAiOy6cU&H8I0=K@;;g7kp#;Q%tH>HAZB*c2b%v zcWa+_n{*>K?-H4jM%pk5!^NsHdKyZ~TubKkM}|lAo2s+)4G(M^efO8cKB0RW{i-6d zJJo-k`Dp+N;&?*%jCIzlib0n^d5ZZTpRMvC4Mk`$*`JPMl5XeEx9>J4O7Sg~T(2`Q zMkfdz`{(%2bP0_&Vw#2@74F!O+-VSMe^qmsZps0=Lo-LrdNBm(w6TzPR-@lnYee7p*TgaBm_gOWVq znOWRbt2h3dwJ zGuB&u$@Nk?O{Kilt(@r1t5#1lWHm+qpg+EN5Z3v5<5fZDnyF}=E%O2c!^?3~D(##H zhvg+k$%geAlxEKBQ6(|?iDoWCL`J+pKJy*uT zg`DPcVslrUrv250mC}}k)qIL=U`KtX z_8oOK#_QrJ{~!Xy3i5c~^9?tWlA&;CD$#`D=y{UTc(;XS`iao#3p-AE47=RrwLw!& z?!1;v=n0pjG2NL=E($9JN^3F9w~w9O5(brS?uh2uM33=(k;~*)RuM?1oFtmyOeuv~ zc`IGG3C?MO=~#kNQS=YGNdtmVNfYD*cCvb(8gg7RY7D2olxcQ5Z+eb=O;(XaSwMZf zdU8s9CRC0q=+~;=$RO$z4P%MDu7Hm|)NkS1?PYY%%6irTR-h6k-Ea~-Q`wj1wiuEa z*r0+SVnWb{xS0Dn`SNm2?0_tF9>Z#tgB@Fw@p<<@-Dbf;q#sh@$%DK3RRk zs|zG%q5%UnNy;;2%?M`qZUm(7VSIik#oY@#jy@zPZ?W8G2AbWjeNMYI`>p{_Ry9Xo zZ9}%#ezukK(*V+p9X3KicTpQ%Hg{8`fel`v&h zL;G+$RvK4J0kaZC%`+NufIfWS;b)6l#3+IqW|6kZDO=YLNRxAqh9&2;uBa{ zc(_?ljdtfWM|TE)2+f(nUd>YmvXv<9?pd)TET3NgD&%7vtwMLvBh5&fYB7?eypA>l z9Ad@oHeX%S-F3uqP?2{=a(jF>$9Rf&EBQ9jAUg*E-S;T&Rn%sowcYW(_Yq zOihn(LJ)g0_WF9gL2VY$(ss60jG*|9{J?xMnjL3#b|B;hkUWg5MCx5~PO`{Jo>4y1#wV}@?#V`fcA zut;xaCqFDu6@&`xU)Cu%t4Sdw^|Ia!r-nT?Ki9`M z+LuYM9kV;|%^U00ugzTZkU3>tm2Q(SOyrT)jHxur*cltpuK==3x?X)5FT86*<*kZ6u}*-U4U z5s|<1nbT6pz#_=--l`jts_dx{P0i{JA@)kHK4O*1sy7g%F=w>;v3P<#kPnvWt*&e-&ip%b8l=9;>dD4J}KVVAEERm@zxC;J`NrURiLZU z3V&!dRuD2K3e~rUrWuPJS6NTEZI&%l>NN9+o8QpZKfa@lGCaGezIvBJt{TKvmJJl>QIn!1 zh}vU1MD61%G)HseFEo^z^PwNcrv&m&!sBVXbCK~~>rCRqULpVH)}7ux>@dYh2GfCgQLhQ}jr* z#E5k{e4*=r(j_~~bl)6~j0#D93hG#*-CF4n9@Df_=iA!MHpoRIKI<7-O&C+qxF*>@ z7Fcv$Iz34UH%(?P&N7jJ9m2i6w~DXK)hrklH^%av`$dxc8A`T$3Kdn~zkaU%K(46U zH|EuQ+1Q2nFcY~gF}sMG3k9Rh5@iOZSXJ)vdz!;`N6+uxeOj;yn$b0PFL7P0Ep}Z( ztB$*`Soz#U9k^R2-?CsqVahWLf}47i*fLccMv1dG)K3eNzTyii)+ud5Qk{)uShfM6 zEQtQ4XYx*C`c~0jv&mlvd)E;exSP>3nytQFGaXw3nf2DLDMeKcZ7;>OD=T(&Kh3uM z`AA22&qwE>LoL?1C@N)`Nm&nJ_V|5crZ#s&t@zfAm7~YtkCCn<5u2HulV`+dMe`}q z_SF6S(1*Fj9;e6*4f>rDVzro+c zN4EgD8hR+tbMEPXW6a+F8@lXIole#-;1T2gpVjbELIBtj$FUp${{Q3q>)`-mZG>ZA z{d+b1KZCOH(BT1;fZ*H}&X<{@$9H{`3giER)fEH)P;Hxqkl-JSLYndDj(<&T`M+T6 z7(<}s!AcPk{Bv7@MnJwja^|wa13~yY{p`Zt05~5afSBN)+ahej4*=#=5LExx{ z1b^@7Y+Ju&0A2mx1smi^vp883yS*}oIw`kD6^s=o#3D6hSMFzxElZP}kyxUahf7h2 z{UOI1PXsay$lu0lS_*jeH$b~-R3%xuyM0CgG>l7*#qHhEu>)BcsaGt{`x&RyafU|< z?U{~#)1;FLoZ!es{vdt)#Fu>bK0c;GV@N%8KbQ53E9{~yJoSeno}O)eh#wNDT}R<_ zp3CLEg9LK?dAOkBM&`Y#HhdZy8nXpF{RuGlm9%ZqGX-tjg#^;WJ>CKc3PhhAj|GrY zO`;Fq7j~)NAWl-7>X)ML&KsofoLKX zQlu#Kqpt4Qk+(?vmMEH^f|^0@dZG)A0x-< zqUUOFt!NIGqJMvMW8`_3Gw=waK>=(@1LMzdhGYC~G5*&8e^K>_tz?aACBkB{h(

zE0nmZppcN+=No^$nk)F}#D~aMT4#Pz&vB(rUu{MH1f3u|;3c11s1xN@=jHfTV-g9X(`%6gKW~8JLsmR5;ravI9p{Z&1#wxQhoNjqf zP_Lp(XsSlF)iK^dK#F3KL4(t^L!R zrL1So-D1n9%(PQ*tomzp8D?fHh0{zK7M@WwJRl%X!D%d0{*o`dLX=CYIc>yZ~VvR3{+^f(*HfGy+>rX zstG6HcWBRd@McJv0diyayM@~iXmm?0HaD2IzPlypn7b+?$3&^(Ezo%4om79?a@}ir6&id+ zrb5zlJ<@q7I<%uNg!EnH(jq72?Sw>#4SI5abIE3{t8UFtW39ol-z|Zr%}8f~eP+VG zF7Bo^=P}v_Zj7FE#Cb7_+FplgO$D6#Oz@+QBN~PV^{m_|*WHpgaU8i~qwb;yI7EXWdXzKys(*81MSd&QwQIi;_RElm&hBCr|17?tPtrY0xyoByKXXdN z=GcJHerb_jiE>3nd_#T^!kLoQz*vRe4fNfg^Y~?2<#n<ikrhld4^)&B`IJj%Ds`GH2(}K84NALWfY&CYs*G zhzl2jJpA_Q1q|;(r8er1_Od}s-AhaXE723y#GX1jI?nrM7TqU@5$l_F_HzO7dcG>m zMwI0My>dY@RZR}rZf$_k?K)hoW`m5iLk@bxqL+neTT(9hAW`bx2PU7??WHkr(QQDC z6(7?!f@%hM7mJr=yBkRi_ zK|mBuahXX_E%mVf*tumt_c;X)@X1xv9*1P~XKu~L7+?#zMMX=|a>w1Luan!K_TOvD zlQk@Rn|8lrTNdny`TZqWqCq#I4`zyB8X0F6-&@Lsd8ecVp!0V~J(7%A_#Wb_AI}vO z_Iap6E%Tw!NM^SW4>v|vMS>+(6%M}>J5tc`7Hn9~N1Dg1kosnrwaY^2^Xe zL&hX3F;6LEn}k{OuHR$8+>4rNq{K8V)<`vWpRDJ6E#FkCH2FfKK zR3n?6<^{@>1Xe-?e{O48J2*Nr0E4Uj%NSl@&_KKvX>H(hcdg;DjiJS$`pu8WjNgiR z@ZCmG+x5JY6d99vB^`WhrMXyS)TA!%;qG0v?et^BD8R_jb3-KY_^_T~?aN%Uzz>G? z#Tf&Jn~Q8IBl>zA#T5{+mmW zLxm$n=IWrL)&rY!+L&ayI|0#RF7wH({FtH7p*KCJQcL#?>%0<>?E)2sCVdSW?ifF9 zvANmI)%$+zo7oAN(uLD)B)oL|p=^~*zrDt2UGD1s%3x-p_S^V9jI_hJ+?@uPaZ!rv zv^rQmb4wrzg3y2}Ty$%P<=ow88}XA*V0ylR6?hoMv*-dAeA;J6bM{A81R) zSKO8)JU4z=JcZ&6Y%9mg7RKZZLJ#i%;$~LsbkLFav<{Ly;N@gLlqq40 z54WSsvB-e<)hf*J~YC=hPxku$0fxQg0Eb|?oYJtjG z-}~J1h04%5%?qx~Vns>m7%Y(2Qbg(%05%P9*ppcE=hZe8X_=t1;HaiLNX?Qo&l~Xr z(p)!qPttG(dc!_(e8O|AsV^S9``0us#-Z_8x=;Mj*`cnH){l4d7n#Eb`Z&dwXx*oG zP1h0XX=k=QmQyw9Kk-1QS;fZZci2}@x6fLDuHG=i;iCW+|KlBxG4EwQyQ|0RZ2jZz za)N=%F6EzPGe_}-xNt1QTF4-w8xNtWQ+%j%&(L?q?iiDJct^K02dI>fd{-V%zV4t9 zBEdwfhT$96cg)>6aqUXj9QfY<%;sA!$iO&6;#d&Awq<7@NJ*)MtKRx-eWA$midhiW zi<}FanP}3Ux=i9B-q8kBdp{W`t;WO$x)zcAr9nmZHma$+kR|$~1C3Mv2~QpWL%YbT z#+o?!kh+1=$<)4$s!0FFb_u%o1wL1u7VHmTJ_d1 z@eqmLGVdMT8t=*C(vA<6OF6I}wyy_N#t#(MibCX(2Yv|7%~%YiphdhU02_s8Kvl(+ad!0(4#aK-6b=p591(_pv|@ zl*)e(bp?&{yu4oStSY&4WPU*iPG~M8w{)3m8W`l-k|C>)BgwuW2$mS7a;elyRd;;B zJeQcAI?nDFeS@y4LY<^1s-$;JlsL$+XxA^}KcvHXXsBI{!NlvUfc<=UN z^tals-(y1~%7-i9Nh-v&J!sDP=(o>pe#3>g$aV%)`CPo-r*@6Pd9dqVXxY$9{g6d@ z1PG%9j|Wfs6s|edV!vOJN~oBR{w0qjV^P^q8FT6XjP_>d5!app?`iGJINR5k--;2B z#UF#QR00~iwxKLuU`VAGH1%r<)!sjyUn=hRIE%)$UxZDTG*?v;#!#=bR!d5CfJ;f9 zY_XYK9gnxJnu+Y24D@~&W5xBT`>^Zs?HNv3e@WwZ5cz{`CK+Wc*2+C9J~yqlyDv01 zBt=*Tfo@YQDSZVj@ncfxO|)TK_L1uyv~OXGQU?B#}sj>L&x z`6)DgS!U(4PZIGdsbko19xf_yadFlS>)Xl!gWR%Z%+XC>wIdSVSLv@du;qYF#Q9!R z*=7X&2xST27k}R7EHvh2lBHuVJYX41YCg_vmyqL#ak|`quD>J6sN1ID;(*$p`L>@a zD?!7)ED>#w@L+bk2eXW6T*yzO**l1i{|x;h8#|p(IXIN&a+dP1<{h*l|H@X!ABDSm zA;_TjP+R<18q+*Q6KyD%LI}RiSN3_|?W9sZcDK2vbGJ?AzEky$&To9Ti_GdOe{#jA zp`r)`X7wqVLG)8rB)KZbDk{uwK`^rW)l~{1noN1J0ezw_O@7AnmPk2vHZRi((Lf#P zkgXy2`bIwng1Q}B##h>y8r+7ZB%`camugjNz1Z(Pcq4JSk?M26!HtA2 z6$v{oGUhM2D-{d(2ALrst1lp+ZN@I1@$aC^AIT5M;^Zd`tw?3VIDcp|X5>pP;9K_y0QMRAE9@g+ zP4}r6?PbI2-6ww-I_~Y$V>)J3A95Wus`y!55%PSk!jaC+?6ba97*K!H=*G2oyQ0u_ z66pL51+dQ^IzxANptO*w$ZSSWh~xFiq%EoR4Pi&08~0!3B~JNP)2~>qdrdlpb}fn6 z^j^#!RCX^}4Hv~O6lue8Xl$W2d}EkR=e_WQu&kA-dU2GDW9{!48^(vyK8{{rU+g_* zeD$kU1eh#ifIj`Cv8kMj(1?7cZViV{*vmIpiwWmHsbW$VoR)2yQS_t+Wq7F!cnz0V z4Xobh5tbfrH@7^p)NowSYJv4#_)8hl@?bk!>3DGe*!9zqQ2zsILBSLc61QMin4{0H zZyeP0Ec)&8syK5rMQ>lwi8TY$T3M2w_KFgC8vs-xrr z>gT)ogTJyH6|p(_oDXb1WD$n-rMd5Z`ieFQ+C8pct&Ax64S)}3&4G>TusXSpp(~#? z>7P8eq)E-vbg+cxCA+gojv6R`%4Qjlx;OglIwA427LbnY9VlrZ69lOd!g?l@KeNf# z9@^*u88kEUpwQ#a54~`I4$tzIMMZ@kA&lQ14Saecu^Af`vbRd%zk}=E6Yoo>Lq*xcM0TDK1pU4a9GvPud{hh^fS?N!b6N25VcVbfYW>BQEw{&y zt{JQkp%=gSw4G|TVKc^V4z(wFKT}6*ryAxr+&O5#SF6d%OuvDkUzTvN-Zt}6%Tx+KvieDwTr89uX7F}1&2-y^ACvoT-S3VUeC zV&c0pI8g|8*3pjrx%w;AJ}#b5ZQ0|N8|7AyQTHU!8vPmkQ$SeQa3{Rf{59vQSkWw}sD+Km^_qm)&vPyB1R z!C;i6wS@Dm!@O{^e& zkNlA9bBdlnR^uq{`>hmoee{I%k((cD)NE=!r6y}Y*_j?CW z_ffk*Fuv6G0|>?-B9T*gsY8LT$r!zFP5s;NLdWi?~uwZpW(vIU=u z3Ga&rNx|UZ!SkgFFMo8bW__s0L()Ev0pyiHJ2l zxY8$KhC7i@5EoqVqSt53jg-_<`Q84@5R&PZR~&Ir;{!}x@hFo_uA_WwmffeL?Qrv? z*ZI3wZd|B@Gbjinl};L;8^d*zcK`r!u1^6fJX$~ejcpPeD*9y9v=pE6fiMfbLIj+# zO=))NZ?awxVFWMzHCA$3xeMdz^M$;AGWsZZ__E*Z_bCg?h7xz#NvNfJU zbQwV1>Xg4ywr4L0AP#~9N_XJkQk+lG!I)9GW&S?wx2)v8X@T#d!BKHU}PVwH)6tO0N6kHo1 zNOxO)ICC5E*P4`8oW6@P*;a?hS_{_XYXtQGc(=n2y-hHFc-R`-KT>b`5-M3x7@$93 z!_{p89P|D;IiaOt>yMcXa$h12LtX%Ka0)^L7#F^~KAyl;W z+j|?J$bNO{8ReU}PdmB8K*^0y@qb?kfjO1rrT@AIKK;M=1;1zyl)j+*dh? zGit~r5t-6TOM{u~O5EpLXoUoNt-lKF;Q$H`LgH(3FFUWziz=nm$ta)AVjhurJ`sBM z+U}n-EeNYL{(S#-oBDry{0zts|MM<{^?&4WHog2m$>D^h6~QvU?6ZXhe(Ob`Afxi6 Js~XHPa0}UmuQ%2$jHbpDZhB8MMiec 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 literal 0 HcmV?d00001 From f7434672bf56a7dbc045cd716e0b93580b562e20 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Fri, 27 Apr 2018 03:56:48 -0600 Subject: [PATCH 18/21] Update banner placement in README --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index ec8e7140d..839374deb 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ -Atmosphère-NX -===== ![Banner](img/banner.png?raw=true) +===== ![License](https://img.shields.io/badge/License-GPLv2-blue.svg) From 52730d218826f361fa1785a388943c7b2338703b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Mon, 30 Apr 2018 17:48:03 +0100 Subject: [PATCH 19/21] Adding credits section --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 839374deb..e106cd567 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,17 @@ ![License](https://img.shields.io/badge/License-GPLv2-blue.svg) Atmosphère is a work-in-progress customized firmware for the Nintendo Switch. + +Credits +===== + +Atmosphère is currently being developed and maintained by __SciresM__, __TuxSH__, __ktemkin__ and __hexkyz__.
+In no particular order, we credit the following for their invaluable contributions: + +* __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch. +* __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support. +* __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.tech/) pertaining to the Nintendo Switch. +* __naehrwert__ for the [hekate](https://github.com/nwert/hekate) project and it's hwinit code base. +* __hedgeberg__ for research and hardware testing. +* __lioncash__ for code cleanup and general improvements. +* _All those who actively contribute to the Atmosphère repository._ From 30f975a558d03e83b1020bca0f577fdd3d997d2a Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 30 Apr 2018 22:27:07 -0600 Subject: [PATCH 20/21] Stratosphere: Fix remaining bugs in sm, which now works as a KIP1 on hardware --- .../source/waitablemanager.cpp | 17 +++---- stratosphere/sm/source/sm_main.cpp | 2 +- stratosphere/sm/source/sm_manager_service.cpp | 1 - stratosphere/sm/source/sm_registration.cpp | 48 +++++++------------ stratosphere/sm/source/sm_registration.hpp | 2 +- stratosphere/sm/source/sm_user_service.cpp | 5 +- 6 files changed, 30 insertions(+), 45 deletions(-) diff --git a/stratosphere/libstratosphere/source/waitablemanager.cpp b/stratosphere/libstratosphere/source/waitablemanager.cpp index 32db56cfc..bc80e27e4 100644 --- a/stratosphere/libstratosphere/source/waitablemanager.cpp +++ b/stratosphere/libstratosphere/source/waitablemanager.cpp @@ -40,14 +40,8 @@ void WaitableManager::process() { handles.resize(signalables.size()); std::transform(signalables.begin(), signalables.end(), handles.begin(), [](IWaitable *w) { return w->get_handle(); }); - unsigned int num_not_deferred = 0; - for (auto & signalable : signalables) { - if (!signalable->get_deferred()) { - num_not_deferred++; - } - } - rc = svcWaitSynchronization(&handle_index, handles.data(), num_not_deferred, this->timeout); + rc = svcWaitSynchronization(&handle_index, handles.data(), signalables.size(), this->timeout); if (R_SUCCEEDED(rc)) { /* Handle a signaled waitable. */ /* TODO: What timeout should be passed here? */ @@ -82,12 +76,19 @@ void WaitableManager::process() { delete signalables[handle_index]; } + /* If relevant, remove from signalables. */ + signalables.erase(std::remove(signalables.begin(), signalables.end(), signalables[handle_index]), signalables.end()); + for (int i = 0; i < handle_index; i++) { signalables[i]->update_priority(); } } /* Do deferred callback for each waitable. */ - std::for_each(signalables.begin() + num_not_deferred, signalables.end(), [](IWaitable *w) { w->handle_deferred(); }); + for (auto & waitable : signalables) { + if (waitable->get_deferred()) { + waitable->handle_deferred(); + } + } } } \ No newline at end of file diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 6a20fa4f1..21c526565 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -48,7 +48,7 @@ void __appExit(void) { int main(int argc, char **argv) { consoleDebugInit(debugDevice_SVC); - + /* TODO: What's a good timeout value to use here? */ WaitableManager *server_manager = new WaitableManager(U64_MAX); diff --git a/stratosphere/sm/source/sm_manager_service.cpp b/stratosphere/sm/source/sm_manager_service.cpp index d21236040..49247ec5c 100644 --- a/stratosphere/sm/source/sm_manager_service.cpp +++ b/stratosphere/sm/source/sm_manager_service.cpp @@ -4,7 +4,6 @@ Result ManagerService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result rc = 0xF601; - switch ((ManagerServiceCmd)cmd_id) { case Manager_Cmd_RegisterProcess: rc = WrapIpcCommandImpl<&ManagerService::register_process>(this, r, out_c, pointer_buffer, pointer_buffer_size); diff --git a/stratosphere/sm/source/sm_registration.cpp b/stratosphere/sm/source/sm_registration.cpp index 400fffa9d..a6483cbe9 100644 --- a/stratosphere/sm/source/sm_registration.cpp +++ b/stratosphere/sm/source/sm_registration.cpp @@ -6,6 +6,15 @@ static Registration::Process g_process_list[REGISTRATION_LIST_MAX_PROCESS] = {0}; static Registration::Service g_service_list[REGISTRATION_LIST_MAX_SERVICE] = {0}; +u64 GetServiceNameLength(u64 service) { + u64 service_name_len = 0; + while (service & 0xFF) { + service_name_len++; + service >>= 8; + } + return service_name_len; +} + /* Utilities. */ Registration::Process *Registration::GetProcessForPid(u64 pid) { for (unsigned int i = 0; i < REGISTRATION_LIST_MAX_PROCESS; i++) { @@ -162,13 +171,10 @@ Result Registration::GetServiceForPid(u64 pid, u64 service, Handle *out) { return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -191,13 +197,10 @@ Result Registration::RegisterServiceForPid(u64 pid, u64 service, u64 max_session return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -240,13 +243,10 @@ Result Registration::RegisterServiceForSelf(u64 service, u64 max_sessions, bool return rc; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } @@ -276,27 +276,13 @@ Result Registration::UnregisterServiceForPid(u64 pid, u64 service) { return 0xC15; } - u64 service_name_len = 0; - while ((service >> (8 * service_name_len)) & 0xFF) { - service_name_len++; - } + u64 service_name_len = GetServiceNameLength(service); /* If the service has bytes after a null terminator, that's no good. */ - if ((service >> (8 * service_name_len))) { + if (service_name_len != 8 && (service >> (8 * service_name_len))) { return 0xC15; } - if (pid >= REGISTRATION_PID_BUILTIN_MAX) { - Registration::Process *proc = GetProcessForPid(pid); - if (proc == NULL) { - return 0x415; - } - - if (!IsValidForSac(proc->sac, proc->sac_size, service, true)) { - return 0x1015; - } - } - Registration::Service *target_service = GetService(service); if (target_service == NULL) { return 0xE15; diff --git a/stratosphere/sm/source/sm_registration.hpp b/stratosphere/sm/source/sm_registration.hpp index 2a19be857..7ac0f0f89 100644 --- a/stratosphere/sm/source/sm_registration.hpp +++ b/stratosphere/sm/source/sm_registration.hpp @@ -4,7 +4,7 @@ #define REGISTRATION_LIST_MAX_PROCESS (0x40) #define REGISTRATION_LIST_MAX_SERVICE (0x100) #define REGISTRATION_MAX_SAC_SIZE (0x200) -#define REGISTRATION_PID_BUILTIN_MAX 0x7 +#define REGISTRATION_PID_BUILTIN_MAX 0x50 class Registration { public: diff --git a/stratosphere/sm/source/sm_user_service.cpp b/stratosphere/sm/source/sm_user_service.cpp index f57f45858..f05070c3d 100644 --- a/stratosphere/sm/source/sm_user_service.cpp +++ b/stratosphere/sm/source/sm_user_service.cpp @@ -4,8 +4,7 @@ #include "sm_registration.hpp" Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { - Result rc = 0xF601; - + Result rc = 0xF601; switch ((UserServiceCmd)cmd_id) { case User_Cmd_Initialize: rc = WrapIpcCommandImpl<&UserService::initialize>(this, r, out_c, pointer_buffer, pointer_buffer_size); @@ -27,7 +26,7 @@ Result UserService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, Result UserService::handle_deferred() { /* If we're deferred, GetService failed. */ - return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service); + return WrapDeferredIpcCommandImpl<&UserService::deferred_get_service>(this, this->deferred_service);; } From 6a7afc5ce886e0d5b01fd0538e02ba715282af4b Mon Sep 17 00:00:00 2001 From: hexkyz Date: Tue, 1 May 2018 17:17:34 +0100 Subject: [PATCH 21/21] Fix typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e106cd567..c8564ba65 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ In no particular order, we credit the following for their invaluable contributio * __switchbrew__ for the [libnx](https://github.com/switchbrew/libnx) project and the extensive [documentation, research and tool development](http://switchbrew.org) pertaining to the Nintendo Switch. * __devkitPro__ for the [devkitA64](https://devkitpro.org/) toolchain and libnx support. * __ReSwitched Team__ for additional [documentation, research and tool development](https://reswitched.tech/) pertaining to the Nintendo Switch. -* __naehrwert__ for the [hekate](https://github.com/nwert/hekate) project and it's hwinit code base. +* __naehrwert__ for the [hekate](https://github.com/nwert/hekate) project and its hwinit code base. * __hedgeberg__ for research and hardware testing. * __lioncash__ for code cleanup and general improvements. * _All those who actively contribute to the Atmosphère repository._