From f9bf8923b1a6abfb1a19e1ed280ef0b347650b51 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Mon, 17 Jun 2019 16:29:09 -0700 Subject: [PATCH] loader: refactor for R_TRY --- .../loader/source/ldr_content_management.cpp | 85 +++---- .../loader/source/ldr_content_management.hpp | 2 +- .../loader/source/ldr_debug_monitor.cpp | 2 +- .../loader/source/ldr_debug_monitor.hpp | 4 +- stratosphere/loader/source/ldr_hid.hpp | 2 +- .../loader/source/ldr_launch_queue.cpp | 14 +- .../loader/source/ldr_launch_queue.hpp | 8 +- stratosphere/loader/source/ldr_main.cpp | 4 +- stratosphere/loader/source/ldr_map.cpp | 93 +++---- stratosphere/loader/source/ldr_map.hpp | 29 ++- stratosphere/loader/source/ldr_npdm.cpp | 229 ++++++++---------- stratosphere/loader/source/ldr_npdm.hpp | 20 +- stratosphere/loader/source/ldr_nso.cpp | 111 ++++----- stratosphere/loader/source/ldr_nso.hpp | 20 +- stratosphere/loader/source/ldr_patcher.cpp | 18 +- stratosphere/loader/source/ldr_patcher.hpp | 4 +- .../loader/source/ldr_process_creation.cpp | 152 +++++------- .../loader/source/ldr_process_creation.hpp | 2 +- .../loader/source/ldr_process_manager.cpp | 164 ++++++------- .../loader/source/ldr_process_manager.hpp | 8 +- .../loader/source/ldr_registration.cpp | 24 +- .../loader/source/ldr_registration.hpp | 10 +- stratosphere/loader/source/ldr_shell.cpp | 7 +- stratosphere/loader/source/ldr_shell.hpp | 4 +- 24 files changed, 437 insertions(+), 579 deletions(-) diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index f5f660ab2..77ac3042f 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -67,7 +67,6 @@ static std::map g_external_conten Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { char path[FS_MAX_PATH] = {0}; - Result rc; /* We defer SD card mounting, so if relevant ensure it is mounted. */ if (!g_has_initialized_fs_dev) { @@ -82,9 +81,7 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { return ResultSuccess; } - if (R_FAILED(rc = ResolveContentPath(path, tid, sid))) { - return rc; - } + R_TRY(ResolveContentPath(path, tid, sid)); /* Fix up path. */ for (unsigned int i = 0; i < FS_MAX_PATH && path[i] != '\x00'; i++) { @@ -95,20 +92,17 @@ Result ContentManagement::MountCode(u64 tid, FsStorageId sid) { /* Always re-initialize fsp-ldr, in case it's closed */ DoWithSmSession([&]() { - rc = fsldrInitialize(); + if (R_FAILED(fsldrInitialize())) { + std::abort(); + } }); - if (R_FAILED(rc)) { - return rc; - } ON_SCOPE_EXIT { fsldrExit(); }; - if (R_FAILED(rc = fsldrOpenCodeFileSystem(tid, path, &g_CodeFileSystem))) { - return rc; - } + R_TRY(fsldrOpenCodeFileSystem(tid, path, &g_CodeFileSystem)); fsdevMountDevice("code", g_CodeFileSystem); TryMountHblNspOnSd(); - return rc; + return ResultSuccess; } Result ContentManagement::UnmountCode() { @@ -139,14 +133,12 @@ void ContentManagement::TryMountHblNspOnSd() { Result ContentManagement::MountCodeNspOnSd(u64 tid) { char path[FS_MAX_PATH+1] = {0}; snprintf(path, FS_MAX_PATH, "@Sdcard:/atmosphere/titles/%016lx/exefs.nsp", tid); - Result rc = fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path); - if (R_SUCCEEDED(rc)) { - fsdevMountDevice("code", g_CodeFileSystem); - TryMountHblNspOnSd(); - } + R_TRY(fsOpenFileSystemWithId(&g_CodeFileSystem, 0, FsFileSystemType_ApplicationPackage, path)); + fsdevMountDevice("code", g_CodeFileSystem); + TryMountHblNspOnSd(); - return rc; + return ResultSuccess; } Result ContentManagement::MountCodeForTidSid(Registration::TidSid *tid_sid) { @@ -154,39 +146,29 @@ Result ContentManagement::MountCodeForTidSid(Registration::TidSid *tid_sid) { } Result ContentManagement::ResolveContentPath(char *out_path, u64 tid, FsStorageId sid) { - Result rc; - LrRegisteredLocationResolver reg; - LrLocationResolver lr; char path[FS_MAX_PATH] = {0}; /* Try to get the path from the registered resolver. */ - if (R_FAILED(rc = lrOpenRegisteredLocationResolver(®))) { - return rc; - } + LrRegisteredLocationResolver reg; + R_TRY(lrOpenRegisteredLocationResolver(®)); + ON_SCOPE_EXIT { serviceClose(®.s); }; - if (R_SUCCEEDED(rc = lrRegLrResolveProgramPath(®, tid, path))) { - strncpy(out_path, path, FS_MAX_PATH); - } else if (rc != ResultLrProgramNotFound) { - return rc; - } + R_TRY_CATCH(lrRegLrResolveProgramPath(®, tid, path)) { + R_CATCH(ResultLrProgramNotFound) { + /* Program wasn't found via registered resolver, fall back to the normal resolver. */ + LrLocationResolver lr; + R_TRY(lrOpenLocationResolver(sid, &lr)); + ON_SCOPE_EXIT { serviceClose(&lr.s); }; - serviceClose(®.s); - if (R_SUCCEEDED(rc)) { - return rc; - } + R_TRY(lrLrResolveProgramPath(&lr, tid, path)); - /* If getting the path from the registered resolver fails, fall back to the normal resolver. */ - if (R_FAILED(rc = lrOpenLocationResolver(sid, &lr))) { - return rc; - } + strncpy(out_path, path, FS_MAX_PATH); + return ResultSuccess; + } + } R_END_TRY_CATCH; - if (R_SUCCEEDED(rc = lrLrResolveProgramPath(&lr, tid, path))) { - strncpy(out_path, path, FS_MAX_PATH); - } - - serviceClose(&lr.s); - - return rc; + strncpy(out_path, path, FS_MAX_PATH); + return ResultSuccess; } Result ContentManagement::ResolveContentPathForTidSid(char *out_path, Registration::TidSid *tid_sid) { @@ -194,18 +176,11 @@ Result ContentManagement::ResolveContentPathForTidSid(char *out_path, Registrati } Result ContentManagement::RedirectContentPath(const char *path, u64 tid, FsStorageId sid) { - Result rc; LrLocationResolver lr; + R_TRY(lrOpenLocationResolver(sid, &lr)); + ON_SCOPE_EXIT { serviceClose(&lr.s); }; - if (R_FAILED(rc = lrOpenLocationResolver(sid, &lr))) { - return rc; - } - - rc = lrLrRedirectProgramPath(&lr, tid, path); - - serviceClose(&lr.s); - - return rc; + return lrLrRedirectProgramPath(&lr, tid, path); } Result ContentManagement::RedirectContentPathForTidSid(const char *path, Registration::TidSid *tid_sid) { @@ -382,7 +357,7 @@ void ContentManagement::TryMountSdCard() { can_mount = false; break; } else { - svcCloseHandle(tmp_hnd); + svcCloseHandle(tmp_hnd); } } }); diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 2dc694bd3..4fd326e0b 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include diff --git a/stratosphere/loader/source/ldr_debug_monitor.cpp b/stratosphere/loader/source/ldr_debug_monitor.cpp index cbb10faa3..f4f7babea 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.cpp +++ b/stratosphere/loader/source/ldr_debug_monitor.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include diff --git a/stratosphere/loader/source/ldr_debug_monitor.hpp b/stratosphere/loader/source/ldr_debug_monitor.hpp index 2e87c1521..3155f0b0d 100644 --- a/stratosphere/loader/source/ldr_debug_monitor.hpp +++ b/stratosphere/loader/source/ldr_debug_monitor.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include @@ -25,7 +25,7 @@ enum DebugMonitorServiceCmd { Dmnt_Cmd_GetProcessModuleInfo = 2 }; -class DebugMonitorService final : public IServiceObject { +class DebugMonitorService final : public IServiceObject { private: /* Actual commands. */ Result AddTitleToLaunchQueue(u64 tid, InPointer args, u32 args_size); diff --git a/stratosphere/loader/source/ldr_hid.hpp b/stratosphere/loader/source/ldr_hid.hpp index f62c9f7ca..af4188e9f 100644 --- a/stratosphere/loader/source/ldr_hid.hpp +++ b/stratosphere/loader/source/ldr_hid.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include diff --git a/stratosphere/loader/source/ldr_launch_queue.cpp b/stratosphere/loader/source/ldr_launch_queue.cpp index e53d85402..dad20e93b 100644 --- a/stratosphere/loader/source/ldr_launch_queue.cpp +++ b/stratosphere/loader/source/ldr_launch_queue.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -28,15 +28,15 @@ Result LaunchQueue::Add(u64 tid, const char *args, u64 arg_size) { if (arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { return ResultLoaderTooLongArgument; } - + int idx = GetFreeIndex(tid); if (idx == LAUNCH_QUEUE_FULL) { return ResultLoaderTooManyArguments; } - + g_launch_queue[idx].tid = tid; g_launch_queue[idx].arg_size = arg_size; - + std::copy(args, args + arg_size, g_launch_queue[idx].args); return ResultSuccess; } @@ -46,7 +46,7 @@ Result LaunchQueue::AddCopy(u64 tid_base, u64 tid) { if (idx == LAUNCH_QUEUE_FULL) { return ResultSuccess; } - + return Add(tid, g_launch_queue[idx].args, g_launch_queue[idx].arg_size); } @@ -55,12 +55,12 @@ Result LaunchQueue::AddItem(const LaunchItem *item) { if (item->arg_size > LAUNCH_QUEUE_ARG_SIZE_MAX) { return ResultLoaderTooLongArgument; } - + int idx = GetFreeIndex(item->tid); if (idx == LAUNCH_QUEUE_FULL) { return ResultLoaderTooManyArguments; } - + g_launch_queue[idx] = *item; return ResultSuccess; } diff --git a/stratosphere/loader/source/ldr_launch_queue.hpp b/stratosphere/loader/source/ldr_launch_queue.hpp index e560150b3..76e7ab486 100644 --- a/stratosphere/loader/source/ldr_launch_queue.hpp +++ b/stratosphere/loader/source/ldr_launch_queue.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include @@ -22,16 +22,16 @@ #define LAUNCH_QUEUE_ARG_SIZE_MAX (0x8000) -class LaunchQueue { +class LaunchQueue { public: struct LaunchItem { u64 tid; u64 arg_size; char args[LAUNCH_QUEUE_ARG_SIZE_MAX]; }; - + static LaunchQueue::LaunchItem *GetItem(u64 tid); - + static Result Add(u64 tid, const char *args, u64 arg_size); static Result AddItem(const LaunchItem *item); static Result AddCopy(u64 tid_base, u64 new_tid); diff --git a/stratosphere/loader/source/ldr_main.cpp b/stratosphere/loader/source/ldr_main.cpp index 5c7249989..ae36c0ac6 100644 --- a/stratosphere/loader/source/ldr_main.cpp +++ b/stratosphere/loader/source/ldr_main.cpp @@ -116,10 +116,10 @@ int main(int argc, char **argv) s_server_manager.AddWaitable(new ServiceServer("ldr:pm", 1)); s_server_manager.AddWaitable(new ServiceServer("ldr:shel", 3)); s_server_manager.AddWaitable(new ServiceServer("ldr:dmnt", 2)); - + /* Loop forever, servicing our services. */ s_server_manager.Process(); - + return 0; } diff --git a/stratosphere/loader/source/ldr_map.cpp b/stratosphere/loader/source/ldr_map.cpp index e2cd0a48c..f98c207a6 100644 --- a/stratosphere/loader/source/ldr_map.cpp +++ b/stratosphere/loader/source/ldr_map.cpp @@ -13,14 +13,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include "ldr_map.hpp" Result MapUtils::LocateSpaceForMap(u64 *out, u64 out_size) { - if ((GetRuntimeFirmwareVersion() >= FirmwareVersion_200)) { + if (GetRuntimeFirmwareVersion() >= FirmwareVersion_200) { return LocateSpaceForMapModern(out, out_size); } else { return LocateSpaceForMapDeprecated(out, out_size); @@ -32,31 +32,27 @@ Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) { AddressSpaceInfo address_space = {}; u32 page_info = 0; u64 cur_base = 0, cur_end = 0; - Result rc; - - if (R_FAILED((rc = GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE)))) { - return rc; - } - + + R_TRY(GetAddressSpaceInfo(&address_space, CUR_PROCESS_HANDLE)); + cur_base = address_space.addspace_base; - - rc = ResultKernelOutOfMemory; + cur_end = cur_base + out_size; if (cur_end <= cur_base) { - return rc; + return ResultKernelOutOfMemory; } - + 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; + return ResultKernelOutOfMemory; } 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; + return ResultKernelOutOfMemory; } cur_base = address_space.map_end; } else { @@ -68,77 +64,52 @@ Result MapUtils::LocateSpaceForMapModern(u64 *out, u64 out_size) { return ResultSuccess; } if (mem_info.addr + mem_info.size <= cur_base) { - return rc; + return ResultKernelOutOfMemory; } cur_base = mem_info.addr + mem_info.size; if (cur_base >= address_space.addspace_end) { - return rc; + return ResultKernelOutOfMemory; } } cur_end = cur_base + out_size; if (cur_base + out_size <= cur_base) { - return rc; + return ResultKernelOutOfMemory; } - } + } } - Result MapUtils::LocateSpaceForMapDeprecated(u64 *out, u64 out_size) { MemoryInfo mem_info = {}; u32 page_info = 0; - Result rc; - + u64 cur_base = 0x8000000ULL; - if (R_FAILED((rc = svcQueryMemory(&mem_info, &page_info, cur_base)))) { - return rc; - } - - rc = ResultKernelOutOfMemory; - while (true) { - if (mem_info.type == 0x10) { - return rc; - } + do { + R_TRY(svcQueryMemory(&mem_info, &page_info, cur_base)); + if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= out_size) { *out = cur_base; return ResultSuccess; } - u64 mem_end = mem_info.addr + mem_info.size; - if (mem_end < cur_base) { - return rc; - } - if (mem_end >> 31) { - break; + + const u64 mem_end = mem_info.addr + mem_info.size; + if (mem_info.type == 0x10 || mem_end < cur_base || (mem_end >> 31)) { + return ResultKernelOutOfMemory; } + cur_base = mem_end; - if (R_FAILED((rc = svcQueryMemory(&mem_info, &page_info, cur_base)))) { - return rc; - } - } - return rc; + } while (true); } Result MapUtils::GetAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h) { - Result rc; - if (R_FAILED((rc = svcGetInfo(&out->heap_base, 4, process_h, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&out->heap_size, 5, process_h, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&out->map_base, 2, process_h, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&out->map_size, 3, process_h, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&out->addspace_base, 12, process_h, 0)))) { - return rc; - } - if (R_FAILED((rc = svcGetInfo(&out->addspace_size, 13, process_h, 0)))) { - return rc; - } + R_TRY(svcGetInfo(&out->heap_base, 4, process_h, 0)); + R_TRY(svcGetInfo(&out->heap_size, 5, process_h, 0)); + R_TRY(svcGetInfo(&out->map_base, 2, process_h, 0)); + R_TRY(svcGetInfo(&out->map_size, 3, process_h, 0)); + R_TRY(svcGetInfo(&out->addspace_base, 12, process_h, 0)); + R_TRY(svcGetInfo(&out->addspace_size, 13, process_h, 0)); + 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 ResultSuccess; -} \ No newline at end of file +} diff --git a/stratosphere/loader/source/ldr_map.hpp b/stratosphere/loader/source/ldr_map.hpp index c4556ee9d..eca5105ab 100644 --- a/stratosphere/loader/source/ldr_map.hpp +++ b/stratosphere/loader/source/ldr_map.hpp @@ -13,12 +13,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include -class MapUtils { +class MapUtils { public: struct AddressSpaceInfo { u64 heap_base; @@ -47,29 +47,28 @@ class AutoCloseMap { ~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, address, size)))) { - return rc; - } - - this->mapped_address = (void *)try_address; + + /* Find an address to map at. */ + R_TRY(MapUtils::LocateSpaceForMap(&try_address, size)); + + /* Actually map at address. */ + void *try_map_address = reinterpret_cast(try_address); + R_TRY(svcMapProcessMemory(try_map_address, process_h, address, size)); + + this->mapped_address = try_map_address; this->process_handle = process_h; this->base_address = address; this->size = size; return ResultSuccess; } - + void Close() { if (this->mapped_address) { if (R_FAILED(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size))) { diff --git a/stratosphere/loader/source/ldr_npdm.cpp b/stratosphere/loader/source/ldr_npdm.cpp index 76634574f..d227f3679 100644 --- a/stratosphere/loader/source/ldr_npdm.cpp +++ b/stratosphere/loader/source/ldr_npdm.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -51,7 +51,7 @@ FILE *NpdmUtils::OpenNpdmFromExeFS() { return fopen(g_npdm_path, "rb"); } -FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) { +FILE *NpdmUtils::OpenNpdmFromSdCard(u64 title_id) { std::fill(g_npdm_path, g_npdm_path + FS_MAX_PATH, 0); snprintf(g_npdm_path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/exefs/main.npdm", title_id); return fopen(g_npdm_path, "rb"); @@ -63,12 +63,12 @@ FILE *NpdmUtils::OpenNpdm(u64 title_id) { if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { return OpenNpdmFromECS(ecs); } - + /* First, check HBL. */ if (ContentManagement::ShouldOverrideContentsWithHBL(title_id)) { return OpenNpdmFromHBL(); } - + /* Next, check other override. */ if (ContentManagement::ShouldOverrideContentsWithSD(title_id)) { FILE *f_out = OpenNpdmFromSdCard(title_id); @@ -76,135 +76,124 @@ FILE *NpdmUtils::OpenNpdm(u64 title_id) { return f_out; } } - + /* Last resort: real exefs. */ return OpenNpdmFromExeFS(); } Result NpdmUtils::LoadNpdmInternal(FILE *f_npdm, NpdmUtils::NpdmCache *cache) { - Result rc; - cache->info = {}; - rc = ResultFsPathNotFound; if (f_npdm == NULL) { /* For generic "Couldn't open the file" error, just say the file doesn't exist. */ - return rc; + return ResultFsPathNotFound; } - + fseek(f_npdm, 0, SEEK_END); size_t npdm_size = ftell(f_npdm); fseek(f_npdm, 0, SEEK_SET); - - rc = ResultLoaderTooLargeMeta; + if ((npdm_size > sizeof(cache->buffer)) || (fread(cache->buffer, 1, npdm_size, f_npdm) != npdm_size)) { fclose(f_npdm); - return rc; + return ResultLoaderTooLargeMeta; } - + fclose(f_npdm); - - rc = ResultLoaderInvalidMeta; + if (npdm_size < sizeof(NpdmUtils::NpdmHeader)) { - return rc; + return ResultLoaderInvalidMeta; } - + /* For ease of access... */ cache->info.header = (NpdmUtils::NpdmHeader *)(cache->buffer); NpdmInfo *info = &cache->info; - + if (info->header->magic != MAGIC_META) { - return rc; + return ResultLoaderInvalidMeta; } - + /* 7.0.0 added 0x10 as a valid bit to NPDM flags. */ if (GetRuntimeFirmwareVersion() >= FirmwareVersion_700) { if (info->header->mmu_flags > 0x1F) { - return rc; + return ResultLoaderInvalidMeta; } } else { if (info->header->mmu_flags > 0xF) { - return rc; + return ResultLoaderInvalidMeta; } } - + if (info->header->aci0_offset < sizeof(NpdmUtils::NpdmHeader) || info->header->aci0_size < sizeof(NpdmUtils::NpdmAci0) || info->header->aci0_offset + info->header->aci0_size > npdm_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->aci0 = (NpdmAci0 *)(cache->buffer + info->header->aci0_offset); - + if (info->aci0->magic != MAGIC_ACI0) { - return rc; + return ResultLoaderInvalidMeta; } - + if (info->aci0->fah_size > info->header->aci0_size || info->aci0->fah_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->fah_offset + info->aci0->fah_size > info->header->aci0_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->aci0_fah = (void *)((uintptr_t)info->aci0 + info->aci0->fah_offset); - + if (info->aci0->sac_size > info->header->aci0_size || info->aci0->sac_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->sac_offset + info->aci0->sac_size > info->header->aci0_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->aci0_sac = (void *)((uintptr_t)info->aci0 + info->aci0->sac_offset); - + if (info->aci0->kac_size > info->header->aci0_size || info->aci0->kac_offset < sizeof(NpdmUtils::NpdmAci0) || info->aci0->kac_offset + info->aci0->kac_size > info->header->aci0_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->aci0_kac = (void *)((uintptr_t)info->aci0 + info->aci0->kac_offset); - + if (info->header->acid_offset < sizeof(NpdmUtils::NpdmHeader) || info->header->acid_size < sizeof(NpdmUtils::NpdmAcid) || info->header->acid_offset + info->header->acid_size > npdm_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->acid = (NpdmAcid *)(cache->buffer + info->header->acid_offset); - + if (info->acid->magic != MAGIC_ACID) { - return rc; + return ResultLoaderInvalidMeta; } - + /* TODO: Check if retail flag is set if not development hardware. */ - + if (info->acid->fac_size > info->header->acid_size || info->acid->fac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->fac_offset + info->acid->fac_size > info->header->acid_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->acid_fac = (void *)((uintptr_t)info->acid + info->acid->fac_offset); - + if (info->acid->sac_size > info->header->acid_size || info->acid->sac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->sac_offset + info->acid->sac_size > info->header->acid_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->acid_sac = (void *)((uintptr_t)info->acid + info->acid->sac_offset); - + if (info->acid->kac_size > info->header->acid_size || info->acid->kac_offset < sizeof(NpdmUtils::NpdmAcid) || info->acid->kac_offset + info->acid->kac_size > info->header->acid_size) { - return rc; + return ResultLoaderInvalidMeta; } - + info->acid_kac = (void *)((uintptr_t)info->acid + info->acid->kac_offset); - - rc = ResultSuccess; - return rc; + + return ResultSuccess; } Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { - Result rc; - - rc = LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache); - - if (R_FAILED(rc)) { - return rc; - } - + /* Load and validate the NPDM. */ + R_TRY(LoadNpdmInternal(OpenNpdm(tid), &g_npdm_cache)); + NpdmInfo *info = &g_npdm_cache.info; /* Override the ACID/ACI0 title ID, in order to facilitate HBL takeover of any title. */ info->acid->title_id_range_min = tid; info->acid->title_id_range_max = tid; info->aci0->title_id = tid; - + if (ContentManagement::ShouldOverrideContentsWithHBL(tid) && R_SUCCEEDED(LoadNpdmInternal(OpenNpdmFromExeFS(), &g_original_npdm_cache))) { NpdmInfo *original_info = &g_original_npdm_cache.info; /* Fix pool partition. */ @@ -226,17 +215,15 @@ Result NpdmUtils::LoadNpdm(u64 tid, NpdmInfo *out) { } } } - + /* We validated! */ info->title_id = tid; *out = *info; - rc = ResultSuccess; - - return rc; + + return ResultSuccess; } -Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining) { - Result rc = ResultSuccess; +Result NpdmUtils::ValidateCapabilityAgainstRestrictions(const u32 *restrict_caps, size_t num_restrict_caps, const u32 *&cur_cap, size_t &caps_remaining) { u32 desc = *cur_cap++; caps_remaining--; unsigned int low_bits = 0; @@ -248,7 +235,6 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size u32 r_desc = 0; switch (low_bits) { case 3: /* Kernel flags. */ - rc = ResultLoaderInvalidCapabilityKernelFlags; for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0xF) == 0x7) { r_desc = restrict_caps[i] >> 4; @@ -283,18 +269,16 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size } if (highest_cpu_id > r_highest_cpu_id) { break; - } + } /* Valid! */ - rc = ResultSuccess; - break; + return ResultSuccess; } } - break; + return ResultLoaderInvalidCapabilityKernelFlags; case 4: /* Syscall mask. */ - rc = ResultLoaderInvalidCapabilitySyscallMask; for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0x1F) == 0xF) { - r_desc = restrict_caps[i] >> 5; + r_desc = restrict_caps[i] >> 5; u32 syscall_base = (desc >> 24); u32 r_syscall_base = (r_desc >> 24); if (syscall_base != r_syscall_base) { @@ -306,32 +290,31 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size break; } /* Valid! */ - rc = ResultSuccess; - break; + return ResultSuccess; } } - break; - case 6: /* Map IO/Normal. */ { - rc = ResultLoaderInvalidCapabilityMapRange; + return ResultLoaderInvalidCapabilitySyscallMask; + case 6: /* Map IO/Normal. */ + { if (caps_remaining == 0) { - break; + return ResultLoaderInvalidCapabilityMapRange; } u32 next_cap = *cur_cap++; caps_remaining--; if ((next_cap & 0x7F) != 0x3F) { - break; + return ResultLoaderInvalidCapabilityMapRange; } u32 next_desc = next_cap >> 7; u32 base_addr = desc & 0xFFFFFF; u32 base_size = next_desc & 0xFFFFFF; /* Size check the mapping. */ if (base_size >> 20) { - break; + return ResultLoaderInvalidCapabilityMapRange; } u32 base_end = base_addr + base_size; /* Validate it's possible to validate this mapping. */ if (num_restrict_caps < 2) { - break; + return ResultLoaderInvalidCapabilityMapRange; } for (size_t i = 0; i < num_restrict_caps - 1; i++) { if ((restrict_caps[i] & 0x7F) == 0x3F) { @@ -360,28 +343,24 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size continue; } /* Valid! */ - rc = ResultSuccess; - break; + return ResultSuccess; } } } - break; + return ResultLoaderInvalidCapabilityMapRange; case 7: /* Map Normal Page. */ - rc = ResultLoaderInvalidCapabilityMapPage; for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0xFF) == 0x7F) { - r_desc = restrict_caps[i] >> 8; + r_desc = restrict_caps[i] >> 8; if (r_desc != desc) { continue; } /* Valid! */ - rc = ResultSuccess; - break; + return ResultSuccess; } } - break; - case 11: /* IRQ Pair. */ - rc = ResultSuccess; + return ResultLoaderInvalidCapabilityMapPage; + case 11: /* IRQ Pair. */ for (unsigned int irq_i = 0; irq_i < 2; irq_i++) { u32 irq = desc & 0x3FF; desc >>= 10; @@ -398,18 +377,16 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size } } if (!found) { - rc = ResultLoaderInvalidCapabilityInterruptPair; - break; + return ResultLoaderInvalidCapabilityInterruptPair; } } } - break; + return ResultSuccess; case 13: /* App Type. */ - rc = ResultLoaderInvalidCapabilityApplicationType; if (num_restrict_caps) { for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0x3FFF) == 0x1FFF) { - r_desc = restrict_caps[i] >> 14; + r_desc = restrict_caps[i] >> 14; break; } } @@ -418,15 +395,14 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size } if (desc == r_desc) { /* Valid! */ - rc = ResultSuccess; + return ResultSuccess; } - break; + return ResultLoaderInvalidCapabilityApplicationType; case 14: /* Kernel Release Version. */ - rc = ResultLoaderInvalidCapabilityKernelVersion; if (num_restrict_caps) { for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0x7FFF) == 0x3FFF) { - r_desc = restrict_caps[i] >> 15; + r_desc = restrict_caps[i] >> 15; break; } } @@ -435,31 +411,28 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size } if (desc == r_desc) { /* Valid! */ - rc = ResultSuccess; + return ResultSuccess; } - break; + return ResultLoaderInvalidCapabilityKernelVersion; case 15: /* Handle Table Size. */ - rc = ResultLoaderInvalidCapabilityHandleTable; for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0xFFFF) == 0x7FFF) { - r_desc = restrict_caps[i] >> 16; + r_desc = restrict_caps[i] >> 16; desc &= 0x3FF; r_desc &= 0x3FF; if (desc > r_desc) { break; } /* Valid! */ - rc = ResultSuccess; - break; + return ResultSuccess; } } - break; + return ResultLoaderInvalidCapabilityHandleTable; case 16: /* Debug Flags. */ - rc = ResultLoaderInvalidCapabilityDebugFlags; if (num_restrict_caps) { for (size_t i = 0; i < num_restrict_caps; i++) { if ((restrict_caps[i] & 0x1FFFF) == 0xFFFF) { - r_desc = restrict_caps[i] >> 17; + r_desc = restrict_caps[i] >> 17; break; } } @@ -468,33 +441,29 @@ Result NpdmUtils::ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size } if ((desc & ~r_desc) == 0) { /* Valid! */ - rc = ResultSuccess; + return ResultSuccess; } - break; + return ResultLoaderInvalidCapabilityDebugFlags; case 32: /* Empty Descriptor. */ - rc = ResultSuccess; - break; + return ResultSuccess; default: /* Unrecognized Descriptor. */ - rc = ResultLoaderUnknownCapability; - break; + return ResultLoaderUnknownCapability; } - return rc; } -Result NpdmUtils::ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps) { - Result rc = ResultSuccess; +Result NpdmUtils::ValidateCapabilities(const u32 *acid_caps, size_t num_acid_caps, const u32 *aci0_caps, size_t num_aci0_caps) { + const u32 *cur_cap = aci0_caps; size_t remaining = num_aci0_caps; - u32 *cur_cap = aci0_caps; + while (remaining) { - if (R_FAILED((rc = ValidateCapabilityAgainstRestrictions(acid_caps, num_acid_caps, cur_cap, remaining)))) { - break; - } + /* Validate, update capabilities. cur_cap and remaining passed by reference. */ + R_TRY(ValidateCapabilityAgainstRestrictions(acid_caps, num_acid_caps, cur_cap, remaining)); } - return rc; + return ResultSuccess; } -u32 NpdmUtils::GetApplicationType(u32 *caps, size_t num_caps) { +u32 NpdmUtils::GetApplicationType(const u32 *caps, size_t num_caps) { u32 application_type = 0; for (unsigned int i = 0; i < num_caps; i++) { if ((caps[i] & 0x3FFF) == 0x1FFF) { @@ -514,7 +483,7 @@ u32 NpdmUtils::GetApplicationType(u32 *caps, size_t num_caps) { } /* Like GetApplicationType, except this returns the raw kac descriptor value. */ -u32 NpdmUtils::GetApplicationTypeRaw(u32 *caps, size_t num_caps) { +u32 NpdmUtils::GetApplicationTypeRaw(const u32 *caps, size_t num_caps) { u32 application_type = 0; for (unsigned int i = 0; i < num_caps; i++) { if ((caps[i] & 0x3FFF) == 0x1FFF) { diff --git a/stratosphere/loader/source/ldr_npdm.hpp b/stratosphere/loader/source/ldr_npdm.hpp index d4db06d1d..b0aae5731 100644 --- a/stratosphere/loader/source/ldr_npdm.hpp +++ b/stratosphere/loader/source/ldr_npdm.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include @@ -25,7 +25,7 @@ #define MAGIC_ACI0 0x30494341 #define MAGIC_ACID 0x44494341 -class NpdmUtils { +class NpdmUtils { public: struct NpdmHeader { u32 magic; @@ -91,17 +91,17 @@ class NpdmUtils { NpdmInfo info; u8 buffer[0x8000]; }; - + static_assert(sizeof(NpdmHeader) == 0x80, "Incorrectly defined NpdmHeader!"); static_assert(sizeof(NpdmAcid) == 0x240, "Incorrectly defined NpdmAcid!"); static_assert(sizeof(NpdmAci0) == 0x40, "Incorrectly defined NpdmAci0!"); - - static u32 GetApplicationType(u32 *caps, size_t num_caps); - static u32 GetApplicationTypeRaw(u32 *caps, size_t num_caps); - - static Result ValidateCapabilityAgainstRestrictions(u32 *restrict_caps, size_t num_restrict_caps, u32 *&cur_cap, size_t &caps_remaining); - static Result ValidateCapabilities(u32 *acid_caps, size_t num_acid_caps, u32 *aci0_caps, size_t num_aci0_caps); - + + static u32 GetApplicationType(const u32 *caps, size_t num_caps); + static u32 GetApplicationTypeRaw(const u32 *caps, size_t num_caps); + + static Result ValidateCapabilityAgainstRestrictions(const u32 *restrict_caps, size_t num_restrict_caps, const u32 *&cur_cap, size_t &caps_remaining); + static Result ValidateCapabilities(const u32 *acid_caps, size_t num_acid_caps, const u32 *aci0_caps, size_t num_aci0_caps); + static FILE *OpenNpdmFromECS(ContentManagement::ExternalContentSource *ecs); static FILE *OpenNpdmFromHBL(); static FILE *OpenNpdmFromExeFS(); diff --git a/stratosphere/loader/source/ldr_nso.cpp b/stratosphere/loader/source/ldr_nso.cpp index eb7ff616a..e5a7ee3b3 100644 --- a/stratosphere/loader/source/ldr_nso.cpp +++ b/stratosphere/loader/source/ldr_nso.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -47,7 +47,7 @@ FILE *NsoUtils::OpenNsoFromExeFS(unsigned int index) { return fopen(g_nso_path, "rb"); } -FILE *NsoUtils::OpenNsoFromSdCard(unsigned int index, u64 title_id) { +FILE *NsoUtils::OpenNsoFromSdCard(unsigned int index, u64 title_id) { std::fill(g_nso_path, g_nso_path + FS_MAX_PATH, 0); snprintf(g_nso_path, FS_MAX_PATH, "sdmc:/atmosphere/titles/%016lx/exefs/%s", title_id, NsoUtils::GetNsoFileName(index)); return fopen(g_nso_path, "rb"); @@ -69,7 +69,7 @@ FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { if ((ecs = ContentManagement::GetExternalContentSource(title_id)) != nullptr) { return OpenNsoFromECS(index, ecs); } - + /* First, check HBL. */ if (ContentManagement::ShouldOverrideContentsWithHBL(title_id)) { return OpenNsoFromHBL(index); @@ -84,7 +84,7 @@ FILE *NsoUtils::OpenNso(unsigned int index, u64 title_id) { return NULL; } } - + /* Finally, default to exefs. */ return OpenNsoFromExeFS(index); } @@ -103,11 +103,11 @@ unsigned char *NsoUtils::GetNsoBuildId(unsigned int index) { Result NsoUtils::LoadNsoHeaders(u64 title_id) { FILE *f_nso; - + /* Zero out the cache. */ std::fill(g_nso_present, g_nso_present + NSO_NUM_MAX, false); std::fill(g_nso_headers, g_nso_headers + NSO_NUM_MAX, NsoUtils::NsoHeader{}); - + for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { f_nso = OpenNso(i, title_id); if (f_nso != NULL) { @@ -124,7 +124,7 @@ Result NsoUtils::LoadNsoHeaders(u64 title_id) { i = 11; } } - + return ResultSuccess; } @@ -133,7 +133,7 @@ Result NsoUtils::ValidateNsoLoadSet() { if (!g_nso_present[1]) { return ResultLoaderInvalidNso; } - + /* Behavior switches depending on whether we have an rtld. */ if (g_nso_present[0]) { /* If we have an rtld, dst offset for .text must be 0 for all other NSOs. */ @@ -154,7 +154,7 @@ Result NsoUtils::ValidateNsoLoadSet() { return ResultLoaderInvalidNso; } } - + return ResultSuccess; } @@ -188,7 +188,7 @@ Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLo } } } - + /* Calculate ASLR extents for address space type. */ u64 addspace_start, addspace_size; if ((GetRuntimeFirmwareVersion() >= FirmwareVersion_200)) { @@ -221,12 +221,12 @@ Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLo if (extents->total_size > addspace_size) { return ResultKernelOutOfMemory; } - + u64 aslr_slide = 0; if (addspace_type & 0x20) { aslr_slide = StratosphereRandomUtils::GetRandomU64((addspace_size - extents->total_size) >> 21) << 21; } - + extents->base_address = addspace_start + aslr_slide; for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (g_nso_present[i]) { @@ -236,7 +236,7 @@ Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLo if (extents->args_address) { extents->args_address += extents->base_address; } - + return ResultSuccess; } @@ -253,24 +253,24 @@ Result NsoUtils::LoadNsoSegment(u64 title_id, unsigned int index, unsigned int s if ((u32)(size | out_size) >> 31) { return ResultLoaderInvalidNso; } - + u8 *dst_addr = map_base + g_nso_headers[index].segments[segment].dst_offset; u8 *load_addr = is_compressed ? map_end - size : dst_addr; - - + + fseek(f_nso, g_nso_headers[index].segments[segment].file_offset, SEEK_SET); if (fread(load_addr, 1, size, f_nso) != size) { return ResultLoaderInvalidNso; } - - + + if (is_compressed) { if (LZ4_decompress_safe((char *)load_addr, (char *)dst_addr, size, out_size) != (int)out_size) { return ResultLoaderInvalidNso; } } - + if (check_hash) { u8 hash[0x20] = {0}; sha256CalculateHash(hash, dst_addr, out_size); @@ -279,35 +279,32 @@ Result NsoUtils::LoadNsoSegment(u64 title_id, unsigned int index, unsigned int s return ResultLoaderInvalidNso; } } - + return ResultSuccess; } -Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size) { - Result rc = ResultLoaderInvalidNso; +Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, const u8 *args, u32 args_size) { for (unsigned int i = 0; i < NSO_NUM_MAX; i++) { if (g_nso_present[i]) { AutoCloseMap nso_map; - if (R_FAILED((rc = nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) { - return rc; - } - + R_TRY(nso_map.Open(process_h, extents->nso_addresses[i], extents->nso_sizes[i])); + u8 *map_base = (u8 *)nso_map.GetMappedAddress(); - - FILE *f_nso = OpenNso(i, title_id); - if (f_nso == NULL) { - /* TODO: Is there a better error to return here? */ - return ResultLoaderInvalidNso; - } - for (unsigned int seg = 0; seg < 3; seg++) { - if (R_FAILED((rc = LoadNsoSegment(title_id, i, seg, f_nso, map_base, map_base + extents->nso_sizes[i])))) { - fclose(f_nso); - return rc; + + /* Load NSO segments from file. */ + { + FILE *f_nso = OpenNso(i, title_id); + if (f_nso == NULL) { + /* TODO: Is there a better error to return here? */ + return ResultLoaderInvalidNso; + } + ON_SCOPE_EXIT { fclose(f_nso); }; + + for (unsigned int seg = 0; seg < 3; seg++) { + R_TRY(LoadNsoSegment(title_id, i, seg, f_nso, map_base, map_base + extents->nso_sizes[i])); } } - - fclose(f_nso); - f_nso = NULL; + /* Zero out memory before .text. */ u64 text_base = 0, text_start = g_nso_headers[i].segments[0].dst_offset; std::fill(map_base + text_base, map_base + text_start, 0); @@ -320,12 +317,12 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo /* Zero out .bss. */ u64 bss_base = rw_start + 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); - + /* Apply patches to loaded module. */ PatchUtils::ApplyPatches(&g_nso_headers[i], map_base, bss_base); - + nso_map.Close(); - + for (unsigned int seg = 0; seg < 3; seg++) { u64 size = g_nso_headers[i].segments[seg].decomp_size; if (seg == 2) { @@ -334,33 +331,27 @@ Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLo size += 0xFFF; size &= ~0xFFFULL; const static unsigned int segment_perms[3] = {5, 1, 3}; - if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->nso_addresses[i] + g_nso_headers[i].segments[seg].dst_offset, size, segment_perms[seg])))) { - return rc; - } + R_TRY(svcSetProcessMemoryPermission(process_h, extents->nso_addresses[i] + g_nso_headers[i].segments[seg].dst_offset, size, segment_perms[seg])); } } } - + /* Map in arguments. */ - if (args != NULL && args_size) { + if (args != nullptr && args_size) { AutoCloseMap args_map; - if (R_FAILED((rc = args_map.Open(process_h, extents->args_address, extents->args_size)))) { - return rc; - } - + R_TRY(args_map.Open(process_h, extents->args_address, extents->args_size)); + 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); - - args_map.Close(); - - if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3)))) { - return rc; - } + + args_map.Close(); + + R_TRY(svcSetProcessMemoryPermission(process_h, extents->args_address, extents->args_size, 3)); } - - return rc; + + return ResultSuccess; } diff --git a/stratosphere/loader/source/ldr_nso.hpp b/stratosphere/loader/source/ldr_nso.hpp index 558bbd728..eee9853f2 100644 --- a/stratosphere/loader/source/ldr_nso.hpp +++ b/stratosphere/loader/source/ldr_nso.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include @@ -31,7 +31,7 @@ class NsoUtils { u32 decomp_size; u32 align_or_total_size; }; - + struct NsoHeader { u32 magic; u32 _0x4; @@ -45,7 +45,7 @@ class NsoUtils { u64 dynsym_extents; u8 section_hashes[3][0x20]; }; - + struct NsoLoadExtents { u64 base_address; u64 total_size; @@ -54,17 +54,17 @@ class NsoUtils { u64 nso_addresses[NSO_NUM_MAX]; u64 nso_sizes[NSO_NUM_MAX]; }; - + struct NsoArgument { u32 allocated_space; u32 args_size; u8 _0x8[0x18]; u8 arguments[]; }; - - + + static_assert(sizeof(NsoHeader) == 0x100, "Incorrectly defined NsoHeader!"); - + static const char *GetNsoFileName(unsigned int index) { switch (index) { case 0: @@ -104,13 +104,13 @@ class NsoUtils { static FILE *OpenNsoFromSdCard(unsigned int index, u64 title_id); static bool CheckNsoStubbed(unsigned int index, u64 title_id); static FILE *OpenNso(unsigned int index, u64 title_id); - + static bool IsNsoPresent(unsigned int index); static unsigned char *GetNsoBuildId(unsigned int index); static Result LoadNsoHeaders(u64 title_id); static Result ValidateNsoLoadSet(); static Result CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLoadExtents *extents); - + static Result LoadNsoSegment(u64 title_id, unsigned int index, unsigned int segment, FILE *f_nso, u8 *map_base, u8 *map_end); - static Result LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size); + static Result LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, const u8 *args, u32 args_size); }; \ No newline at end of file diff --git a/stratosphere/loader/source/ldr_patcher.cpp b/stratosphere/loader/source/ldr_patcher.cpp index 9a81f657d..9b753072f 100644 --- a/stratosphere/loader/source/ldr_patcher.cpp +++ b/stratosphere/loader/source/ldr_patcher.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -49,14 +49,14 @@ static bool MatchesBuildId(const char *name, size_t name_len, const u8 *build_id return false; } } - + /* Read build id from name. */ u8 build_id_from_name[0x20] = {0}; for (unsigned int name_ofs = 0, id_ofs = 0; name_ofs < name_len - 4; id_ofs++) { build_id_from_name[id_ofs] |= HexNybbleToU8(name[name_ofs++]) << 4; build_id_from_name[id_ofs] |= HexNybbleToU8(name[name_ofs++]); } - + return memcmp(build_id, build_id_from_name, sizeof(build_id_from_name)) == 0; } @@ -68,7 +68,7 @@ static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FIL } else if (!is_ips32 && memcmp(buffer, IPS_TAIL, 3) == 0) { break; } - + /* Offset of patch. */ u32 patch_offset; if (is_ips32) { @@ -76,27 +76,27 @@ static void ApplyIpsPatch(u8 *mapped_nso, size_t mapped_size, bool is_ips32, FIL } else { patch_offset = (buffer[0] << 16) | (buffer[1] << 8) | (buffer[2]); } - + /* Size of patch. */ if (fread(buffer, 2, 1, f_ips) != 1) { break; } u32 patch_size = (buffer[0] << 8) | (buffer[1]); - + /* Check for RLE encoding. */ if (patch_size == 0) { /* Size of RLE. */ if (fread(buffer, 2, 1, f_ips) != 1) { break; } - + u32 rle_size = (buffer[0] << 8) | (buffer[1]); - + /* Value for RLE. */ if (fread(buffer, 1, 1, f_ips) != 1) { break; } - + if (patch_offset < sizeof(NsoUtils::NsoHeader)) { if (patch_offset + rle_size > sizeof(NsoUtils::NsoHeader)) { u32 diff = sizeof(NsoUtils::NsoHeader) - patch_offset; diff --git a/stratosphere/loader/source/ldr_patcher.hpp b/stratosphere/loader/source/ldr_patcher.hpp index aaad02c7b..eb492c726 100644 --- a/stratosphere/loader/source/ldr_patcher.hpp +++ b/stratosphere/loader/source/ldr_patcher.hpp @@ -13,14 +13,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include #include "ldr_nso.hpp" -class PatchUtils { +class PatchUtils { public: static void ApplyPatches(const NsoUtils::NsoHeader *header, u8 *mapped_nso, size_t size); }; \ 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 695e15c9b..9a1449d4e 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -28,27 +28,27 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle reslimit_h, u64 arg_flags, ProcessInfo *out_proc_info) { /* Initialize a ProcessInfo using an npdm. */ *out_proc_info = {}; - + /* Copy all but last char of name, insert NULL terminator. */ std::copy(npdm->header->title_name, npdm->header->title_name + sizeof(out_proc_info->name) - 1, out_proc_info->name); out_proc_info->name[sizeof(out_proc_info->name) - 1] = 0; - + /* Set title id. */ out_proc_info->title_id = npdm->aci0->title_id; - + /* Set process category. */ out_proc_info->process_category = npdm->header->process_category; - + /* Copy reslimit handle raw. */ out_proc_info->reslimit_h = reslimit_h; - + /* Set IsAddressSpace64Bit, AddressSpaceType. */ if (npdm->header->mmu_flags & 8) { /* Invalid Address Space Type. */ return ResultLoaderInvalidMeta; } out_proc_info->process_flags = (npdm->header->mmu_flags & 0xF); - + /* Set Bit 4 (?) and EnableAslr based on argument flags. */ out_proc_info->process_flags |= ((arg_flags & 3) << 4) ^ 0x20; /* Set UseSystemMemBlocks if application type is 1. */ @@ -62,7 +62,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle } } } - + /* 3.0.0+ System Resource Size. */ if ((GetRuntimeFirmwareVersion() >= FirmwareVersion_300)) { if (npdm->header->system_resource_size & 0x1FFFFF) { @@ -83,7 +83,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle } else { out_proc_info->system_resource_num_pages = 0; } - + /* 5.0.0+ Pool Partition. */ if ((GetRuntimeFirmwareVersion() >= FirmwareVersion_500)) { u32 pool_partition_id = (npdm->acid->flags >> 2) & 0xF; @@ -106,7 +106,7 @@ Result ProcessCreation::InitializeProcessInfo(NpdmUtils::NpdmInfo *npdm, Handle return ResultLoaderInvalidMeta; } } - + return ResultSuccess; } @@ -117,92 +117,82 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc Registration::Process *target_process; Handle process_h = 0; u64 process_id = 0; - bool mounted_code = false; - Result rc; - + /* Get the process from the registration queue. */ target_process = Registration::GetProcess(index); - if (target_process == NULL) { + if (target_process == nullptr) { return ResultLoaderProcessNotRegistered; } - + /* Mount the title's exefs. */ + bool mounted_code = false; if (target_process->tid_sid.storage_id != FsStorageId_None) { - rc = ContentManagement::MountCodeForTidSid(&target_process->tid_sid); - if (R_FAILED(rc)) { - return rc; - } + R_TRY(ContentManagement::MountCodeForTidSid(&target_process->tid_sid)); mounted_code = true; } else { if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(target_process->tid_sid.title_id))) { mounted_code = true; } } - + ON_SCOPE_EXIT { + if (mounted_code) { + if (R_FAILED(ContentManagement::UnmountCode()) && target_process->tid_sid.storage_id != FsStorageId_None) { + std::abort(); + } + } + }; + /* Load the process's NPDM. */ - rc = NpdmUtils::LoadNpdmFromCache(target_process->tid_sid.title_id, &npdm_info); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + R_TRY(NpdmUtils::LoadNpdmFromCache(target_process->tid_sid.title_id, &npdm_info)); + /* Validate the title we're loading is what we expect. */ if (npdm_info.aci0->title_id < npdm_info.acid->title_id_range_min || npdm_info.aci0->title_id > npdm_info.acid->title_id_range_max) { - rc = ResultLoaderInvalidProgramId; - goto CREATE_PROCESS_END; + return ResultLoaderInvalidProgramId; } - + /* Validate that the ACI0 Kernel Capabilities are valid and restricted by the ACID Kernel Capabilities. */ - rc = NpdmUtils::ValidateCapabilities((u32 *)npdm_info.acid_kac, npdm_info.acid->kac_size/sizeof(u32), (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32)); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + const u32 *acid_caps = reinterpret_cast(npdm_info.acid_kac); + const u32 *aci0_caps = reinterpret_cast(npdm_info.aci0_kac); + const size_t num_acid_caps = npdm_info.acid->kac_size / sizeof(*acid_caps); + const size_t num_aci0_caps = npdm_info.aci0->kac_size / sizeof(*aci0_caps); + R_TRY(NpdmUtils::ValidateCapabilities(acid_caps, num_acid_caps, aci0_caps, num_aci0_caps)); + /* Read in all NSO headers, see what NSOs are present. */ - rc = NsoUtils::LoadNsoHeaders(npdm_info.aci0->title_id); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + R_TRY(NsoUtils::LoadNsoHeaders(npdm_info.aci0->title_id)); + /* Validate that the set of NSOs to be loaded is correct. */ - rc = NsoUtils::ValidateNsoLoadSet(); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + R_TRY(NsoUtils::ValidateNsoLoadSet()); + /* Initialize the ProcessInfo. */ - rc = ProcessCreation::InitializeProcessInfo(&npdm_info, reslimit_h, arg_flags, &process_info); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + R_TRY(ProcessCreation::InitializeProcessInfo(&npdm_info, reslimit_h, arg_flags, &process_info)); + /* Figure out where NSOs will be mapped, and how much space they (and arguments) will take up. */ - rc = NsoUtils::CalculateNsoLoadExtents(process_info.process_flags, launch_item != NULL ? launch_item->arg_size : 0, &nso_extents); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + R_TRY(NsoUtils::CalculateNsoLoadExtents(process_info.process_flags, launch_item != nullptr ? launch_item->arg_size : 0, &nso_extents)); + /* Set Address Space information in ProcessInfo. */ process_info.code_addr = nso_extents.base_address; process_info.code_num_pages = nso_extents.total_size + 0xFFF; process_info.code_num_pages >>= 12; - + /* Call svcCreateProcess(). */ - rc = svcCreateProcess(&process_h, &process_info, (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32)); - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - - + R_TRY(svcCreateProcess(&process_h, &process_info, (u32 *)npdm_info.aci0_kac, npdm_info.aci0->kac_size/sizeof(u32))); + auto proc_handle_guard = SCOPE_GUARD { + svcCloseHandle(process_h); + }; + + /* Load all NSOs into Process memory, and set permissions accordingly. */ - if (launch_item != NULL) { - rc = NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, (u8 *)launch_item->args, launch_item->arg_size); - } else { - rc = NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, NULL, 0); + { + const u8 *launch_args = nullptr; + size_t launch_args_size = 0; + if (launch_item != nullptr) { + launch_args = reinterpret_cast(launch_item->args); + launch_args_size = launch_item->arg_size; + } + + R_TRY(NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, launch_args, launch_args_size)); } - if (R_FAILED(rc)) { - goto CREATE_PROCESS_END; - } - + /* Update the list of registered processes with the new process. */ svcGetProcessId(&process_id, process_h); bool is_64_bit_addspace; @@ -213,15 +203,13 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc } Registration::SetProcessIdTidAndIs64BitAddressSpace(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)) { + if (NsoUtils::IsNsoPresent(i)) { Registration::AddModuleInfo(index, nso_extents.nso_addresses[i], nso_extents.nso_sizes[i], NsoUtils::GetNsoBuildId(i)); } } - + /* Send the pid/tid pair to anyone interested in man-in-the-middle-attacking it. */ Registration::AssociatePidTidForMitM(index); - - rc = ResultSuccess; /* If HBL, override HTML document path. */ if (ContentManagement::ShouldOverrideContentsWithHBL(target_process->tid_sid.title_id)) { @@ -231,20 +219,10 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc /* ECS is a one-shot operation, but we don't clear on failure. */ ContentManagement::ClearExternalContentSource(target_process->tid_sid.title_id); + /* Cancel the process handle guard. */ + proc_handle_guard.Cancel(); -CREATE_PROCESS_END: - if (mounted_code) { - if (R_SUCCEEDED(rc) && target_process->tid_sid.storage_id != FsStorageId_None) { - rc = ContentManagement::UnmountCode(); - } else { - ContentManagement::UnmountCode(); - } - } - - if (R_SUCCEEDED(rc)) { - *out_process_h = process_h; - } else { - svcCloseHandle(process_h); - } - return rc; + /* Write process handle to output. */ + *out_process_h = process_h; + return ResultSuccess; } diff --git a/stratosphere/loader/source/ldr_process_creation.hpp b/stratosphere/loader/source/ldr_process_creation.hpp index 2f773fc78..1914122d1 100644 --- a/stratosphere/loader/source/ldr_process_creation.hpp +++ b/stratosphere/loader/source/ldr_process_creation.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include diff --git a/stratosphere/loader/source/ldr_process_manager.cpp b/stratosphere/loader/source/ldr_process_manager.cpp index c6a6d11cf..abe233422 100644 --- a/stratosphere/loader/source/ldr_process_manager.cpp +++ b/stratosphere/loader/source/ldr_process_manager.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include "ldr_process_manager.hpp" @@ -23,7 +23,6 @@ #include "ldr_npdm.hpp" Result ProcessManagerService::CreateProcess(Out proc_h, u64 index, u32 flags, CopiedHandle reslimit_h) { - Result rc; Registration::TidSid tid_sid; LaunchQueue::LaunchItem *launch_item; char nca_path[FS_MAX_PATH] = {0}; @@ -32,58 +31,35 @@ Result ProcessManagerService::CreateProcess(Out proc_h, u64 index, /* Loader doesn't persist the copied resource limit handle. */ svcCloseHandle(reslimit_h.handle); }; - - rc = Registration::GetRegisteredTidSid(index, &tid_sid); - if (R_FAILED(rc)) { - return rc; - } - + + R_TRY(Registration::GetRegisteredTidSid(index, &tid_sid)); + if (tid_sid.storage_id != FsStorageId_None) { - rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); - if (R_FAILED(rc)) { - return rc; - } + R_TRY(ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid)); } - launch_item = LaunchQueue::GetItem(tid_sid.title_id); - - rc = ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle); - - if (R_SUCCEEDED(rc)) { - ContentManagement::SetCreatedTitle(tid_sid.title_id); - } - - return rc; + R_TRY(ProcessCreation::CreateProcess(proc_h.GetHandlePointer(), index, nca_path, launch_item, flags, reslimit_h.handle)); + + ContentManagement::SetCreatedTitle(tid_sid.title_id); + return ResultSuccess; } Result ProcessManagerService::GetProgramInfo(OutPointerWithServerSize out_program_info, Registration::TidSid tid_sid) { - Result rc; char nca_path[FS_MAX_PATH] = {0}; + /* Zero output. */ std::fill(out_program_info.pointer, out_program_info.pointer + out_program_info.num_elements, ProcessManagerService::ProgramInfo{}); - - rc = PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid); - - if (R_FAILED(rc)) { - return {rc}; - } - + + R_TRY(PopulateProgramInfoBuffer(out_program_info.pointer, &tid_sid)); + if (tid_sid.storage_id != FsStorageId_None && tid_sid.title_id != out_program_info.pointer->title_id) { - rc = ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid); - if (R_FAILED(rc)) { - return {rc}; - } - - rc = ContentManagement::RedirectContentPath(nca_path, out_program_info.pointer->title_id, tid_sid.storage_id); - if (R_FAILED(rc)) { - return {rc}; - } - - rc = LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id); + R_TRY(ContentManagement::ResolveContentPathForTidSid(nca_path, &tid_sid)); + R_TRY(ContentManagement::RedirectContentPath(nca_path, out_program_info.pointer->title_id, tid_sid.storage_id)); + R_TRY(LaunchQueue::AddCopy(tid_sid.title_id, out_program_info.pointer->title_id)); } - - return {rc}; + + return ResultSuccess; } Result ProcessManagerService::RegisterTitle(Out index, Registration::TidSid tid_sid) { @@ -97,68 +73,70 @@ Result ProcessManagerService::UnregisterTitle(u64 index) { Result ProcessManagerService::PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid) { NpdmUtils::NpdmInfo info; - Result rc; - bool mounted_code = false; - - if (tid_sid->storage_id != FsStorageId_None) { - rc = ContentManagement::MountCodeForTidSid(tid_sid); - if (R_FAILED(rc)) { - return rc; + + /* Mount code, load NPDM. */ + { + bool mounted_code = false; + if (tid_sid->storage_id != FsStorageId_None) { + R_TRY(ContentManagement::MountCodeForTidSid(tid_sid)); + mounted_code = true; + } else if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(tid_sid->title_id))) { + mounted_code = true; } - mounted_code = true; - } else if (R_SUCCEEDED(ContentManagement::MountCodeNspOnSd(tid_sid->title_id))) { - mounted_code = true; - } - - rc = NpdmUtils::LoadNpdm(tid_sid->title_id, &info); - - if (mounted_code) { - ContentManagement::UnmountCode(); - } - - if (R_FAILED(rc)) { - return rc; + ON_SCOPE_EXIT { + if (mounted_code) { + ContentManagement::UnmountCode(); + } + }; + + R_TRY(NpdmUtils::LoadNpdm(tid_sid->title_id, &info)); } - out->main_thread_priority = info.header->main_thread_prio; out->default_cpu_id = info.header->default_cpuid; out->main_thread_stack_size = info.header->main_stack_size; out->title_id = info.aci0->title_id; - + out->acid_fac_size = info.acid->fac_size; out->aci0_sac_size = info.aci0->sac_size; out->aci0_fah_size = info.aci0->fah_size; - + size_t offset = 0; - rc = ResultLoaderInternalError; - if (offset + info.acid->sac_size < sizeof(out->ac_buffer)) { - out->acid_sac_size = info.acid->sac_size; - std::memcpy(out->ac_buffer + offset, info.acid_sac, out->acid_sac_size); - offset += out->acid_sac_size; - if (offset + info.aci0->sac_size < sizeof(out->ac_buffer)) { - out->aci0_sac_size = info.aci0->sac_size; - std::memcpy(out->ac_buffer + offset, info.aci0_sac, out->aci0_sac_size); - offset += out->aci0_sac_size; - if (offset + info.acid->fac_size < sizeof(out->ac_buffer)) { - out->acid_fac_size = info.acid->fac_size; - std::memcpy(out->ac_buffer + offset, info.acid_fac, out->acid_fac_size); - offset += out->acid_fac_size; - if (offset + info.aci0->fah_size < sizeof(out->ac_buffer)) { - out->aci0_fah_size = info.aci0->fah_size; - std::memcpy(out->ac_buffer + offset, info.aci0_fah, out->aci0_fah_size); - offset += out->aci0_fah_size; - rc = ResultSuccess; - } - } - } + + /* Copy ACID Service Access Control. */ + if (offset + info.acid->sac_size >= sizeof(out->ac_buffer)) { + return ResultLoaderInternalError; } - + out->acid_sac_size = info.acid->sac_size; + std::memcpy(out->ac_buffer + offset, info.acid_sac, out->acid_sac_size); + offset += out->acid_sac_size; + + /* Copy ACI0 Service Access Control. */ + if (offset + info.aci0->sac_size >= sizeof(out->ac_buffer)) { + return ResultLoaderInternalError; + } + out->aci0_sac_size = info.aci0->sac_size; + std::memcpy(out->ac_buffer + offset, info.aci0_sac, out->aci0_sac_size); + offset += out->aci0_sac_size; + + /* Copy ACID Filesystem Access Control. */ + if (offset + info.acid->fac_size >= sizeof(out->ac_buffer)) { + return ResultLoaderInternalError; + } + out->acid_fac_size = info.acid->fac_size; + std::memcpy(out->ac_buffer + offset, info.acid_fac, out->acid_fac_size); + offset += out->acid_fac_size; + + /* Copy ACI0 Filesystem Access Header. */ + if (offset + info.aci0->fah_size >= sizeof(out->ac_buffer)) { + return ResultLoaderInternalError; + } + out->aci0_fah_size = info.aci0->fah_size; + std::memcpy(out->ac_buffer + offset, info.aci0_fah, out->aci0_fah_size); + offset += out->aci0_fah_size; + /* Parse application type. */ - if (R_SUCCEEDED(rc)) { - out->application_type = NpdmUtils::GetApplicationType((u32 *)info.acid_kac, info.acid->kac_size / sizeof(u32)); - } - - - return rc; + out->application_type = NpdmUtils::GetApplicationType(reinterpret_cast(info.acid_kac), info.acid->kac_size / sizeof(u32)); + + return ResultSuccess; } diff --git a/stratosphere/loader/source/ldr_process_manager.hpp b/stratosphere/loader/source/ldr_process_manager.hpp index 06406b509..7686b7783 100644 --- a/stratosphere/loader/source/ldr_process_manager.hpp +++ b/stratosphere/loader/source/ldr_process_manager.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include @@ -41,15 +41,15 @@ class ProcessManagerService final : public IServiceObject { u32 aci0_fah_size; u8 ac_buffer[0x3E0]; }; - - static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition."); + + static_assert(sizeof(ProcessManagerService::ProgramInfo) == 0x400, "Incorrect ProgramInfo definition."); private: /* Actual commands. */ Result CreateProcess(Out proc_h, u64 index, u32 flags, CopiedHandle reslimit_h); Result GetProgramInfo(OutPointerWithServerSize out_program_info, Registration::TidSid tid_sid); Result RegisterTitle(Out index, Registration::TidSid tid_sid); Result UnregisterTitle(u64 index); - + /* Utilities */ Result PopulateProgramInfoBuffer(ProcessManagerService::ProgramInfo *out, Registration::TidSid *tid_sid); public: diff --git a/stratosphere/loader/source/ldr_registration.cpp b/stratosphere/loader/source/ldr_registration.cpp index 44c075255..d02925fed 100644 --- a/stratosphere/loader/source/ldr_registration.cpp +++ b/stratosphere/loader/source/ldr_registration.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include @@ -50,12 +50,12 @@ Registration::Process *Registration::GetProcessByProcessId(u64 pid) { return NULL; } -bool Registration::RegisterTidSid(const TidSid *tid_sid, u64 *out_index) { +bool Registration::RegisterTidSid(const TidSid *tid_sid, u64 *out_index) { Registration::Process *free_process = GetFreeProcess(); if (free_process == NULL) { return false; } - + /* Reset the process. */ *free_process = {}; free_process->tid_sid = *tid_sid; @@ -70,7 +70,7 @@ bool Registration::UnregisterIndex(u64 index) { if (target_process == NULL) { return false; } - + /* Reset the process. */ *target_process = {}; return true; @@ -82,9 +82,9 @@ Result Registration::GetRegisteredTidSid(u64 index, Registration::TidSid *out) { if (target_process == NULL) { return ResultLoaderProcessNotRegistered; } - + *out = target_process->tid_sid; - + return ResultSuccess; } @@ -93,7 +93,7 @@ void Registration::SetProcessIdTidAndIs64BitAddressSpace(u64 index, u64 process_ if (target_process == NULL) { return; } - + target_process->process_id = process_id; target_process->title_id = tid; target_process->is_64_bit_addspace = is_64_bit_addspace; @@ -120,13 +120,13 @@ Result Registration::GetProcessModuleInfo(LoaderModuleInfo *out, u32 max_out, u6 return ResultLoaderProcessNotRegistered; } u32 cur = 0; - + for (unsigned int i = 0; i < Registration::MaxModuleInfos && cur < max_out; i++) { if (target_process->module_infos[i].in_use) { out[cur++] = target_process->module_infos[i].info; } } - + *num_written = cur; return ResultSuccess; @@ -137,7 +137,7 @@ void Registration::AssociatePidTidForMitM(u64 index) { if (target_process == NULL) { return; } - + Handle sm_hnd; Result rc = svcConnectToNamedPort(&sm_hnd, "sm:"); if (R_SUCCEEDED(rc)) { @@ -182,12 +182,12 @@ void Registration::AssociatePidTidForMitM(u64 index) { u64 process_id; u64 title_id; } *raw = (decltype(raw))ipcPrepareHeader(&c, sizeof(*raw)); - + raw->magic = SFCI_MAGIC; raw->cmd_id = 65002; raw->process_id = target_process->process_id; raw->title_id = target_process->tid_sid.title_id; - + ipcDispatch(sm_hnd); } svcCloseHandle(sm_hnd); diff --git a/stratosphere/loader/source/ldr_registration.hpp b/stratosphere/loader/source/ldr_registration.hpp index 6588a8ae1..67315bc5d 100644 --- a/stratosphere/loader/source/ldr_registration.hpp +++ b/stratosphere/loader/source/ldr_registration.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include @@ -34,7 +34,7 @@ class Registration { u64 title_id; FsStorageId storage_id; }; - + struct Process { bool in_use; bool is_64_bit_addspace; @@ -44,12 +44,12 @@ class Registration { Registration::TidSid tid_sid; std::array module_infos; }; - + struct List { std::array processes; u64 num_processes; }; - + static Registration::Process *GetFreeProcess(); static Registration::Process *GetProcess(u64 index); static Registration::Process *GetProcessByProcessId(u64 pid); @@ -59,7 +59,7 @@ class Registration { static void SetProcessIdTidAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid, bool is_64_bit_addspace); static void AddModuleInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id); static Result GetProcessModuleInfo(LoaderModuleInfo *out, u32 max_out, u64 process_id, u32 *num_written); - + /* Atmosphere MitM Extension. */ static void AssociatePidTidForMitM(u64 index); }; diff --git a/stratosphere/loader/source/ldr_shell.cpp b/stratosphere/loader/source/ldr_shell.cpp index 4c3a754bc..b27d761ab 100644 --- a/stratosphere/loader/source/ldr_shell.cpp +++ b/stratosphere/loader/source/ldr_shell.cpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #include #include #include "ldr_shell.hpp" @@ -34,10 +34,7 @@ Result ShellService::SetExternalContentSource(Out out, u64 tid) { Handle server_h; Handle client_h; - Result rc; - if (R_FAILED(rc = svcCreateSession(&server_h, &client_h, 0, 0))) { - return rc; - } + R_TRY(svcCreateSession(&server_h, &client_h, 0, 0)); Service service; serviceCreate(&service, client_h); diff --git a/stratosphere/loader/source/ldr_shell.hpp b/stratosphere/loader/source/ldr_shell.hpp index 7bad59a6c..6dd7869d6 100644 --- a/stratosphere/loader/source/ldr_shell.hpp +++ b/stratosphere/loader/source/ldr_shell.hpp @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + #pragma once #include #include @@ -31,7 +31,7 @@ class ShellService final : public IServiceObject { /* Actual commands. */ Result AddTitleToLaunchQueue(u64 tid, InPointer args, u32 args_size); void ClearLaunchQueue(); - + /* Atmosphere commands. */ Result SetExternalContentSource(Out out, u64 tid); void ClearExternalContentSource(u64 tid);