From 06f68a8159bfac1d1c02461c883bf355eabca8ae Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 10 Oct 2021 21:37:29 -0700 Subject: [PATCH] loader: refactor to remove fake namespaces --- .../ldr/impl/ldr_debug_monitor_interface.hpp | 4 +- .../ldr/impl/ldr_shell_interface.hpp | 4 +- .../util/util_singleton_traits.hpp | 2 +- .../loader/source/ldr_argument_store.cpp | 62 ++++++ .../loader/source/ldr_argument_store.hpp | 52 +++++ stratosphere/loader/source/ldr_arguments.cpp | 72 ------- stratosphere/loader/source/ldr_arguments.hpp | 34 ---- .../loader/source/ldr_capabilities.cpp | 63 +++--- .../loader/source/ldr_capabilities.hpp | 12 +- .../loader/source/ldr_content_management.cpp | 45 +++-- .../loader/source/ldr_content_management.hpp | 4 +- .../loader/source/ldr_loader_service.cpp | 152 +++++++-------- .../loader/source/ldr_loader_service.hpp | 74 ++++++-- stratosphere/loader/source/ldr_meta.cpp | 12 +- .../loader/source/ldr_process_creation.cpp | 179 +++++++++--------- .../loader/source/ldr_process_creation.hpp | 6 +- 16 files changed, 407 insertions(+), 370 deletions(-) create mode 100644 stratosphere/loader/source/ldr_argument_store.cpp create mode 100644 stratosphere/loader/source/ldr_argument_store.hpp delete mode 100644 stratosphere/loader/source/ldr_arguments.cpp delete mode 100644 stratosphere/loader/source/ldr_arguments.hpp diff --git a/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_debug_monitor_interface.hpp b/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_debug_monitor_interface.hpp index 319832d32..39db27f85 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_debug_monitor_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_debug_monitor_interface.hpp @@ -20,8 +20,8 @@ #include #define AMS_LDR_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentsDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArguments, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgument, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \ AMS_SF_METHOD_INFO(C, H, 1, Result, FlushArguments, (), ()) \ AMS_SF_METHOD_INFO(C, H, 2, Result, GetProcessModuleInfo, (sf::Out count, const sf::OutPointerArray &out, os::ProcessId process_id), (count, out, process_id)) \ AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereHasLaunchedBootProgram, (sf::Out out, ncm::ProgramId program_id), (out, program_id)) diff --git a/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_shell_interface.hpp b/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_shell_interface.hpp index 2283dd63d..972d20c74 100644 --- a/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_shell_interface.hpp +++ b/libraries/libstratosphere/include/stratosphere/ldr/impl/ldr_shell_interface.hpp @@ -20,8 +20,8 @@ #include #define AMS_LDR_I_SHELL_INTERFACE_INTERFACE_INFO(C, H) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentsDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \ - AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArguments, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgumentDeprecated, (ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size), (program_id, args, args_size), hos::Version_Min, hos::Version_10_2_0) \ + AMS_SF_METHOD_INFO(C, H, 0, Result, SetProgramArgument, (ncm::ProgramId program_id, const sf::InPointerBuffer &args), (program_id, args), hos::Version_11_0_0 ) \ AMS_SF_METHOD_INFO(C, H, 1, Result, FlushArguments, (), ()) \ AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereRegisterExternalCode, (sf::OutMoveHandle out, ncm::ProgramId program_id), (out, program_id)) \ AMS_SF_METHOD_INFO(C, H, 65001, void, AtmosphereUnregisterExternalCode, (ncm::ProgramId program_id), (program_id)) diff --git a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp index 052b6077e..040dbe4a9 100644 --- a/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp +++ b/libraries/libstratosphere/include/stratosphere/util/util_singleton_traits.hpp @@ -55,4 +55,4 @@ /* Declare singleton instance variables. */ \ static constinit _CLASSNAME_ s_singleton_instance; \ return s_singleton_instance; \ - } \ No newline at end of file + } diff --git a/stratosphere/loader/source/ldr_argument_store.cpp b/stratosphere/loader/source/ldr_argument_store.cpp new file mode 100644 index 000000000..cd2a52691 --- /dev/null +++ b/stratosphere/loader/source/ldr_argument_store.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "ldr_argument_store.hpp" + +namespace ams::ldr { + + int ArgumentStore::FindIndex(Entry *map, ncm::ProgramId program_id) { + for (auto i = 0; i < ArgumentMapCount; ++i) { + if (map[i].program_id == program_id) { + return i; + } + } + + return -1; + } + + const ArgumentStore::Entry *ArgumentStore::Get(ncm::ProgramId program_id) { + /* Find the matching arguments entry. */ + Entry *argument = nullptr; + if (auto idx = FindIndex(m_argument_map, program_id); idx >= 0) { + argument = m_argument_map + idx; + } + + return argument; + } + + Result ArgumentStore::Set(ncm::ProgramId program_id, const void *argument, size_t size) { + /* Check that the argument size is within bounds. */ + R_UNLESS(size < ArgumentBufferSize, ldr::ResultArgumentOverflow()); + + /* Find either a matching arguments entry, or an empty entry. */ + auto idx = FindIndex(m_argument_map, program_id); + if (idx < 0) { + idx = FindIndex(m_argument_map, ncm::InvalidProgramId); + } + R_UNLESS(idx >= 0, ldr::ResultArgumentCountOverflow()); + + /* Set the arguments in the entry. */ + auto &entry = m_argument_map[idx]; + + entry.program_id = program_id; + entry.argument_size = size; + std::memcpy(entry.argument, argument, entry.argument_size); + + return ResultSuccess(); + } + +} diff --git a/stratosphere/loader/source/ldr_argument_store.hpp b/stratosphere/loader/source/ldr_argument_store.hpp new file mode 100644 index 000000000..4fdb61a86 --- /dev/null +++ b/stratosphere/loader/source/ldr_argument_store.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::ldr { + + class ArgumentStore { + public: + static constexpr size_t ArgumentBufferSize = 32_KB; + + struct Entry { + ncm::ProgramId program_id; + size_t argument_size; + u8 argument[ArgumentBufferSize]; + }; + private: + static constexpr int ArgumentMapCount = 10; + private: + Entry m_argument_map[ArgumentMapCount]; + public: + constexpr ArgumentStore() : m_argument_map{} { + this->Flush(); + } + public: + const Entry *Get(ncm::ProgramId program_id); + Result Set(ncm::ProgramId program_id, const void *argument, size_t size); + + constexpr Result Flush() { + for (auto &entry : m_argument_map) { + entry.program_id = ncm::InvalidProgramId; + } + return ResultSuccess(); + } + private: + static int FindIndex(Entry *map, ncm::ProgramId program_id); + }; + +} diff --git a/stratosphere/loader/source/ldr_arguments.cpp b/stratosphere/loader/source/ldr_arguments.cpp deleted file mode 100644 index 8dd046288..000000000 --- a/stratosphere/loader/source/ldr_arguments.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#include -#include "ldr_arguments.hpp" - -namespace ams::ldr::args { - - namespace { - - /* Convenience definitions. */ - constexpr size_t MaxArgumentInfos = 10; - - /* Global storage. */ - ArgumentInfo g_argument_infos[MaxArgumentInfos]; - - /* Helpers. */ - ArgumentInfo *FindArgumentInfo(ncm::ProgramId program_id) { - for (size_t i = 0; i < MaxArgumentInfos; i++) { - if (g_argument_infos[i].program_id == program_id) { - return g_argument_infos + i; - } - } - return nullptr; - } - - ArgumentInfo *FindFreeArgumentInfo() { - return FindArgumentInfo(ncm::InvalidProgramId); - } - - } - - /* API. */ - const ArgumentInfo *Get(ncm::ProgramId program_id) { - return FindArgumentInfo(program_id); - } - - Result Set(ncm::ProgramId program_id, const void *args, size_t args_size) { - R_UNLESS(args_size < ArgumentSizeMax, ldr::ResultArgumentOverflow()); - - ArgumentInfo *arg_info = FindArgumentInfo(program_id); - if (arg_info == nullptr) { - arg_info = FindFreeArgumentInfo(); - } - R_UNLESS(arg_info != nullptr, ldr::ResultArgumentCountOverflow()); - - arg_info->program_id = program_id; - arg_info->args_size = args_size; - std::memcpy(arg_info->args, args, args_size); - return ResultSuccess(); - } - - Result Flush() { - for (size_t i = 0; i < MaxArgumentInfos; i++) { - g_argument_infos[i].program_id = ncm::InvalidProgramId; - } - return ResultSuccess(); - } - -} diff --git a/stratosphere/loader/source/ldr_arguments.hpp b/stratosphere/loader/source/ldr_arguments.hpp deleted file mode 100644 index 03811fbc6..000000000 --- a/stratosphere/loader/source/ldr_arguments.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) Atmosphère-NX - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -#pragma once -#include - -namespace ams::ldr::args { - - constexpr size_t ArgumentSizeMax = 0x8000; - - struct ArgumentInfo { - ncm::ProgramId program_id; - size_t args_size; - u8 args[ArgumentSizeMax]; - }; - - /* API. */ - const ArgumentInfo *Get(ncm::ProgramId program_id); - Result Set(ncm::ProgramId program_id, const void *args, size_t args_size); - Result Flush(); - -} diff --git a/stratosphere/loader/source/ldr_capabilities.cpp b/stratosphere/loader/source/ldr_capabilities.cpp index f66db3fd8..762413798 100644 --- a/stratosphere/loader/source/ldr_capabilities.cpp +++ b/stratosphere/loader/source/ldr_capabilities.cpp @@ -16,7 +16,7 @@ #include #include "ldr_capabilities.hpp" -namespace ams::ldr::caps { +namespace ams::ldr { namespace { @@ -319,19 +319,14 @@ namespace ams::ldr::caps { } /* Capabilities API. */ - Result ValidateCapabilities(const void *acid_kac, size_t acid_kac_size, const void *aci_kac, size_t aci_kac_size) { - const util::BitPack32 *acid_caps = reinterpret_cast(acid_kac); - const util::BitPack32 *aci_caps = reinterpret_cast(aci_kac); - const size_t num_acid_caps = acid_kac_size / sizeof(*acid_caps); - const size_t num_aci_caps = aci_kac_size / sizeof(*aci_caps); - - for (size_t i = 0; i < num_aci_caps; i++) { - const auto cur_cap = aci_caps[i]; - const auto id = GetCapabilityId(cur_cap); + Result TestCapability(const util::BitPack32 *kacd, size_t kacd_count, const util::BitPack32 *kac, size_t kac_count) { + for (size_t i = 0; i < kac_count; i++) { + const auto cap = kac[i]; + const auto id = GetCapabilityId(cap); #define VALIDATE_CASE(id) \ case CapabilityId::id: \ - R_UNLESS(Capability##id::Decode(cur_cap).IsValid(acid_caps, num_acid_caps), ldr::ResultInvalidCapability##id()); \ + R_UNLESS(Capability##id::Decode(cap).IsValid(kacd, kacd_count), ldr::ResultInvalidCapability##id()); \ break switch (id) { VALIDATE_CASE(KernelFlags); @@ -347,8 +342,8 @@ namespace ams::ldr::caps { { /* Map Range needs extra logic because there it involves two sequential caps. */ i++; - R_UNLESS(i < num_aci_caps, ldr::ResultInvalidCapabilityMapRange()); - R_UNLESS(CapabilityMapRange::Decode(cur_cap).IsValid(aci_caps[i], acid_caps, num_acid_caps), ldr::ResultInvalidCapabilityMapRange()); + R_UNLESS(i < kac_count, ldr::ResultInvalidCapabilityMapRange()); + R_UNLESS(CapabilityMapRange::Decode(cap).IsValid(kac[i], kacd, kacd_count), ldr::ResultInvalidCapabilityMapRange()); } break; default: @@ -361,25 +356,23 @@ namespace ams::ldr::caps { return ResultSuccess(); } - u16 GetProgramInfoFlags(const void *kac, size_t kac_size) { - const util::BitPack32 *caps = reinterpret_cast(kac); - const size_t num_caps = kac_size / sizeof(*caps); + u16 MakeProgramInfoFlag(const util::BitPack32 *kac, size_t count) { u16 flags = 0; - for (size_t i = 0; i < num_caps; i++) { - const auto cur_cap = caps[i]; + for (size_t i = 0; i < count; ++i) { + const auto cap = kac[i]; - switch (GetCapabilityId(cur_cap)) { + switch (GetCapabilityId(cap)) { case CapabilityId::ApplicationType: { - const auto app_type = CapabilityApplicationType::Decode(cur_cap).GetApplicationType() & ProgramInfoFlag_ApplicationTypeMask; + const auto app_type = CapabilityApplicationType::Decode(cap).GetApplicationType() & ProgramInfoFlag_ApplicationTypeMask; if (app_type != ProgramInfoFlag_InvalidType) { flags |= app_type; } } break; case CapabilityId::DebugFlags: - if (CapabilityDebugFlags::Decode(cur_cap).GetAllowDebug()) { + if (CapabilityDebugFlags::Decode(cap).GetAllowDebug()) { flags |= ProgramInfoFlag_AllowDebug; } break; @@ -391,18 +384,15 @@ namespace ams::ldr::caps { return flags; } - void SetProgramInfoFlags(u16 flags, void *kac, size_t kac_size) { - util::BitPack32 *caps = reinterpret_cast(kac); - const size_t num_caps = kac_size / sizeof(*caps); - - for (size_t i = 0; i < num_caps; i++) { - const auto cur_cap = caps[i]; - switch (GetCapabilityId(cur_cap)) { + void UpdateProgramInfoFlag(u16 flags, util::BitPack32 *kac, size_t count) { + for (size_t i = 0; i < count; ++i) { + const auto cap = kac[i]; + switch (GetCapabilityId(cap)) { case CapabilityId::ApplicationType: - caps[i] = CapabilityApplicationType::Encode(flags & ProgramInfoFlag_ApplicationTypeMask); + kac[i] = CapabilityApplicationType::Encode(flags & ProgramInfoFlag_ApplicationTypeMask); break; case CapabilityId::DebugFlags: - caps[i] = CapabilityDebugFlags::Encode((flags & ProgramInfoFlag_AllowDebug) != 0, CapabilityDebugFlags::Decode(cur_cap).GetForceDebug()); + kac[i] = CapabilityDebugFlags::Encode((flags & ProgramInfoFlag_AllowDebug) != 0, CapabilityDebugFlags::Decode(cap).GetForceDebug()); break; default: break; @@ -410,19 +400,16 @@ namespace ams::ldr::caps { } } - void ProcessCapabilities(void *kac, size_t kac_size) { - util::BitPack32 *caps = reinterpret_cast(kac); - const size_t num_caps = kac_size / sizeof(*caps); - - for (size_t i = 0; i < num_caps; i++) { - const auto cur_cap = caps[i]; - switch (GetCapabilityId(cur_cap)) { + void PreProcessCapability(util::BitPack32 *kac, size_t count) { + for (size_t i = 0; i < count; ++i) { + const auto cap = kac[i]; + switch (GetCapabilityId(cap)) { case CapabilityId::MapRegion: { /* MapRegion was added in 8.0.0+, and is only allowed under kernels which have the relevant mappings. */ /* However, we allow it under all firmwares on mesosphere, to facilitate KTrace usage by hbl. */ if (!svc::IsKTraceEnabled()) { - caps[i] = EmptyCapability; + kac[i] = EmptyCapability; } } break; diff --git a/stratosphere/loader/source/ldr_capabilities.hpp b/stratosphere/loader/source/ldr_capabilities.hpp index 85f601a52..0a91b23cc 100644 --- a/stratosphere/loader/source/ldr_capabilities.hpp +++ b/stratosphere/loader/source/ldr_capabilities.hpp @@ -16,13 +16,13 @@ #pragma once #include -namespace ams::ldr::caps { +namespace ams::ldr { - /* Capabilities API. */ - Result ValidateCapabilities(const void *acid_kac, size_t acid_kac_size, const void *aci_kac, size_t aci_kac_size); - u16 GetProgramInfoFlags(const void *kac, size_t kac_size); - void SetProgramInfoFlags(u16 flags, void *kac, size_t kac_size); + Result TestCapability(const util::BitPack32 *kacd, size_t kacd_count, const util::BitPack32 *kac, size_t kac_count); - void ProcessCapabilities(void *kac, size_t kac_size); + u16 MakeProgramInfoFlag(const util::BitPack32 *kac, size_t count); + void UpdateProgramInfoFlag(u16 flags, util::BitPack32 *kac, size_t count); + + void PreProcessCapability(util::BitPack32 *kac, size_t count); } diff --git a/stratosphere/loader/source/ldr_content_management.cpp b/stratosphere/loader/source/ldr_content_management.cpp index 163970541..e1a821052 100644 --- a/stratosphere/loader/source/ldr_content_management.cpp +++ b/stratosphere/loader/source/ldr_content_management.cpp @@ -52,10 +52,8 @@ namespace ams::ldr { AMS_ABORT_UNLESS(m_has_status); /* Get the content path. */ - char content_path[fs::EntryNameLengthMax + 1] = "/"; - if (static_cast(loc.storage_id) != ncm::StorageId::None) { - R_TRY(ResolveContentPath(content_path, loc)); - } + char content_path[fs::EntryNameLengthMax + 1]; + R_TRY(GetProgramPath(content_path, sizeof(content_path), loc)); /* Mount the atmosphere code file system. */ R_TRY(fs::MountCodeForAtmosphereWithRedirection(std::addressof(m_ams_code_verification_data), AtmosphereCodeMountName, content_path, loc.program_id, m_override_status.IsHbl(), m_override_status.IsProgramSpecific())); @@ -82,7 +80,14 @@ namespace ams::ldr { } /* Redirection API. */ - Result ResolveContentPath(char *out_path, const ncm::ProgramLocation &loc) { + Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc) { + /* Check for storage id none. */ + if (static_cast(loc.storage_id) == ncm::StorageId::None) { + std::memset(out_path, 0, out_size); + std::memcpy(out_path, "/", std::min(out_size, 2)); + return ResultSuccess(); + } + lr::Path path; /* Check that path registration is allowable. */ @@ -103,23 +108,35 @@ namespace ams::ldr { } } R_END_TRY_CATCH; - std::strncpy(out_path, path.str, fs::EntryNameLengthMax); - out_path[fs::EntryNameLengthMax - 1] = '\0'; + /* Fix directory separators in path. */ + fs::Replace(path.str, sizeof(path.str), fs::StringTraits::AlternateDirectorySeparator, fs::StringTraits::DirectorySeparator); - fs::Replace(out_path, fs::EntryNameLengthMax + 1, fs::StringTraits::AlternateDirectorySeparator, fs::StringTraits::DirectorySeparator); + /* Check that the path is valid. */ + AMS_ABORT_UNLESS(path.IsValid()); + + /* Copy the output path. */ + std::memset(out_path, 0, out_size); + std::memcpy(out_path, path.str, std::min(out_size, sizeof(path))); return ResultSuccess(); } - Result RedirectContentPath(const char *path, const ncm::ProgramLocation &loc) { - /* Copy in path. */ - lr::Path lr_path; - std::strncpy(lr_path.str, path, sizeof(lr_path.str)); - lr_path.str[sizeof(lr_path.str) - 1] = '\0'; + Result RedirectProgramPath(const char *path, size_t size, const ncm::ProgramLocation &loc) { + /* Check for storage id none. */ + if (static_cast(loc.storage_id) == ncm::StorageId::None) { + return ResultSuccess(); + } - /* Redirect the path. */ + /* Open location resolver. */ lr::LocationResolver lr; R_TRY(lr::OpenLocationResolver(std::addressof(lr), static_cast(loc.storage_id))); + + /* Copy in path. */ + lr::Path lr_path; + std::memcpy(lr_path.str, path, std::min(size, sizeof(lr_path.str))); + lr_path.str[sizeof(lr_path.str) - 1] = '\x00'; + + /* Redirect the path. */ lr.RedirectProgramPath(lr_path, loc.program_id); return ResultSuccess(); diff --git a/stratosphere/loader/source/ldr_content_management.hpp b/stratosphere/loader/source/ldr_content_management.hpp index 590992ff5..f2163776f 100644 --- a/stratosphere/loader/source/ldr_content_management.hpp +++ b/stratosphere/loader/source/ldr_content_management.hpp @@ -72,8 +72,8 @@ namespace ams::ldr { #define ENCODE_CODE_PATH(relative) "code:" relative /* Redirection API. */ - Result ResolveContentPath(char *out_path, const ncm::ProgramLocation &loc); - Result RedirectContentPath(const char *path, const ncm::ProgramLocation &loc); + Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc); + Result RedirectProgramPath(const char *path, size_t size, const ncm::ProgramLocation &loc); Result RedirectHtmlDocumentPathForHbl(const ncm::ProgramLocation &loc); } diff --git a/stratosphere/loader/source/ldr_loader_service.cpp b/stratosphere/loader/source/ldr_loader_service.cpp index fddc05bef..bf39058f9 100644 --- a/stratosphere/loader/source/ldr_loader_service.cpp +++ b/stratosphere/loader/source/ldr_loader_service.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ #include -#include "ldr_arguments.hpp" +#include "ldr_argument_store.hpp" #include "ldr_content_management.hpp" #include "ldr_development_manager.hpp" #include "ldr_process_creation.hpp" @@ -25,90 +25,93 @@ namespace ams::ldr { namespace { - Result GetProgramInfoImpl(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) { - /* Zero output. */ - std::memset(out, 0, sizeof(*out)); - cfg::OverrideStatus status = {}; - - R_TRY(ldr::GetProgramInfo(out, std::addressof(status), loc)); - - if (loc.storage_id != static_cast(ncm::StorageId::None) && loc.program_id != out->program_id) { - char path[fs::EntryNameLengthMax]; - const ncm::ProgramLocation new_loc = ncm::ProgramLocation::Make(out->program_id, static_cast(loc.storage_id)); - - R_TRY(ResolveContentPath(path, loc)); - path[sizeof(path) - 1] = '\x00'; - - R_TRY(RedirectContentPath(path, new_loc)); - - const auto arg_info = args::Get(loc.program_id); - if (arg_info != nullptr) { - R_TRY(args::Set(new_loc.program_id, arg_info->args, arg_info->args_size)); - } - } - - if (out_status != nullptr) { - *out_status = status; - } - - return ResultSuccess(); - } + constinit ArgumentStore g_argument_store; } - /* Official commands. */ - Result LoaderService::CreateProcess(sf::OutMoveHandle out, PinId id, u32 flags, sf::CopyHandle &&reslimit_h) { + + Result LoaderService::CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit) { + /* Declare program path, which we'll need later. */ + + /* Get the location and override status. */ ncm::ProgramLocation loc; cfg::OverrideStatus override_status; + R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), pin_id)); + + /* Get the program path. */ char path[fs::EntryNameLengthMax]; - - /* Get location and override status. */ - R_TRY(ldr::GetProgramLocationAndOverrideStatusFromPinId(std::addressof(loc), std::addressof(override_status), id)); - - if (loc.storage_id != static_cast(ncm::StorageId::None)) { - R_TRY(ResolveContentPath(path, loc)); - path[sizeof(path) - 1] = '\x00'; - } else { - path[0] = '\x00'; - } + R_TRY(GetProgramPath(path, sizeof(path), loc)); + path[sizeof(path) - 1] = '\x00'; /* Create the process. */ - os::NativeHandle process_handle; - R_TRY(ldr::CreateProcess(std::addressof(process_handle), id, loc, override_status, path, flags, reslimit_h.GetOsHandle())); + return ldr::CreateProcess(out, pin_id, loc, override_status, path, g_argument_store.Get(loc.program_id), flags, resource_limit); + } + + Result LoaderService::GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) { + /* Zero output. */ + std::memset(out, 0, sizeof(*out)); + + /* Get the program path. */ + char path[fs::EntryNameLengthMax]; + R_TRY(GetProgramPath(path, sizeof(path), loc)); + path[sizeof(path) - 1] = '\x00'; + + /* Get the program info. */ + cfg::OverrideStatus status; + R_TRY(ldr::GetProgramInfo(out, std::addressof(status), loc, path)); + + if (loc.program_id != out->program_id) { + /* Redirect the program path. */ + const ncm::ProgramLocation new_loc = ncm::ProgramLocation::Make(out->program_id, static_cast(loc.storage_id)); + R_TRY(RedirectProgramPath(path, sizeof(path), new_loc)); + + /* Update the arguments, as needed. */ + if (const auto *entry = g_argument_store.Get(loc.program_id); entry != nullptr) { + R_TRY(this->SetProgramArgument(new_loc.program_id, entry->argument, entry->argument_size)); + } + } + + /* If we should, set the output status. */ + if (out_status != nullptr) { + *out_status = status; + } - /* Set output process handle. */ - out.SetValue(process_handle, true); return ResultSuccess(); } - Result LoaderService::GetProgramInfo(sf::Out out, const ncm::ProgramLocation &loc) { - return GetProgramInfoImpl(out.GetPointer(), nullptr, loc); - } - - Result LoaderService::PinProgram(sf::Out out_id, const ncm::ProgramLocation &loc) { - return ldr::PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{}); + Result LoaderService::PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status) { + *out = {}; + return ldr::PinProgram(out, loc, status); } Result LoaderService::UnpinProgram(PinId id) { return ldr::UnpinProgram(id); } - Result LoaderService::SetProgramArgumentsDeprecated(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size) { - return args::Set(program_id, args.GetPointer(), std::min(args.GetSize(), size_t(args_size))); - } - - Result LoaderService::SetProgramArguments(ncm::ProgramId program_id, const sf::InPointerBuffer &args) { - return args::Set(program_id, args.GetPointer(), args.GetSize()); + Result LoaderService::SetProgramArgument(ncm::ProgramId program_id, const void *argument, size_t size) { + return g_argument_store.Set(program_id, argument, size); } Result LoaderService::FlushArguments() { - return args::Flush(); + return g_argument_store.Flush(); } - Result LoaderService::GetProcessModuleInfo(sf::Out count, const sf::OutPointerArray &out, os::ProcessId process_id) { - *count = 0; - std::memset(out.GetPointer(), 0, out.GetSize() * sizeof(ldr::ModuleInfo)); - return ldr::GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id); + Result LoaderService::GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { + *out_count = 0; + std::memset(out, 0, max_out_count * sizeof(*out)); + return ldr::GetProcessModuleInfo(out_count, out, max_out_count, process_id); + } + + Result LoaderService::RegisterExternalCode(os::NativeHandle *out, ncm::ProgramId program_id) { + return fssystem::CreateExternalCode(out, program_id); + } + + void LoaderService::UnregisterExternalCode(ncm::ProgramId program_id) { + fssystem::DestroyExternalCode(program_id); + } + + void LoaderService::HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id) { + *out = ldr::HasLaunchedBootProgram(program_id); } Result LoaderService::SetEnabledProgramVerification(bool enabled) { @@ -116,29 +119,4 @@ namespace ams::ldr { return ResultSuccess(); } - /* Atmosphere commands. */ - Result LoaderService::AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id) { - os::NativeHandle handle; - R_TRY(fssystem::CreateExternalCode(std::addressof(handle), program_id)); - - out.SetValue(handle, true); - return ResultSuccess(); - } - - void LoaderService::AtmosphereUnregisterExternalCode(ncm::ProgramId program_id) { - fssystem::DestroyExternalCode(program_id); - } - - void LoaderService::AtmosphereHasLaunchedBootProgram(sf::Out out, ncm::ProgramId program_id) { - out.SetValue(ldr::HasLaunchedBootProgram(program_id)); - } - - Result LoaderService::AtmosphereGetProgramInfo(sf::Out out_program_info, sf::Out out_status, const ncm::ProgramLocation &loc) { - return GetProgramInfoImpl(out_program_info.GetPointer(), out_status.GetPointer(), loc); - } - - Result LoaderService::AtmospherePinProgram(sf::Out out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { - return ldr::PinProgram(out_id.GetPointer(), loc, override_status); - } - } diff --git a/stratosphere/loader/source/ldr_loader_service.hpp b/stratosphere/loader/source/ldr_loader_service.hpp index 56313b8e5..c7516d839 100644 --- a/stratosphere/loader/source/ldr_loader_service.hpp +++ b/stratosphere/loader/source/ldr_loader_service.hpp @@ -21,22 +21,74 @@ namespace ams::ldr { class LoaderService { public: /* Official commands. */ - Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle &&reslimit_h); - Result GetProgramInfo(sf::Out out_program_info, const ncm::ProgramLocation &loc); - Result PinProgram(sf::Out out_id, const ncm::ProgramLocation &loc); + Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle &&reslimit_h) { + os::NativeHandle handle = os::InvalidNativeHandle; + const auto result = this->CreateProcess(std::addressof(handle), id, flags, reslimit_h.GetOsHandle()); + proc_h.SetValue(handle, true); + return result; + } + + Result GetProgramInfo(sf::Out out_program_info, const ncm::ProgramLocation &loc) { + return this->GetProgramInfo(out_program_info.GetPointer(), nullptr, loc); + } + + Result PinProgram(sf::Out out_id, const ncm::ProgramLocation &loc) { + return this->PinProgram(out_id.GetPointer(), loc, cfg::OverrideStatus{}); + } + Result UnpinProgram(PinId id); - Result SetProgramArgumentsDeprecated(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size); - Result SetProgramArguments(ncm::ProgramId program_id, const sf::InPointerBuffer &args); + + Result SetProgramArgumentDeprecated(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size) { + AMS_UNUSED(args_size); + return this->SetProgramArgument(program_id, args.GetPointer(), std::min(args_size, args.GetSize())); + } + + Result SetProgramArgument(ncm::ProgramId program_id, const sf::InPointerBuffer &args) { + return this->SetProgramArgument(program_id, args.GetPointer(), args.GetSize()); + } + Result FlushArguments(); - Result GetProcessModuleInfo(sf::Out count, const sf::OutPointerArray &out, os::ProcessId process_id); + + Result GetProcessModuleInfo(sf::Out count, const sf::OutPointerArray &out, os::ProcessId process_id) { + R_UNLESS(out.GetSize() <= std::numeric_limits::max(), ldr::ResultInvalidSize()); + + return this->GetProcessModuleInfo(count.GetPointer(), out.GetPointer(), out.GetSize(), process_id); + } + Result SetEnabledProgramVerification(bool enabled); /* Atmosphere commands. */ - Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id); - void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id); - void AtmosphereHasLaunchedBootProgram(sf::Out out, ncm::ProgramId program_id); - Result AtmosphereGetProgramInfo(sf::Out out_program_info, sf::Out out_status, const ncm::ProgramLocation &loc); - Result AtmospherePinProgram(sf::Out out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status); + Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id) { + os::NativeHandle handle = os::InvalidNativeHandle; + const auto result = this->RegisterExternalCode(std::addressof(handle), program_id); + out.SetValue(handle, true); + return result; + } + + void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id) { + return this->UnregisterExternalCode(program_id); + } + + void AtmosphereHasLaunchedBootProgram(sf::Out out, ncm::ProgramId program_id) { + return this->HasLaunchedBootProgram(out.GetPointer(), program_id); + } + + Result AtmosphereGetProgramInfo(sf::Out out_program_info, sf::Out out_status, const ncm::ProgramLocation &loc) { + return this->GetProgramInfo(out_program_info.GetPointer(), out_status.GetPointer(), loc); + } + + Result AtmospherePinProgram(sf::Out out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { + return this->PinProgram(out_id.GetPointer(), loc, override_status); + } + private: + Result CreateProcess(os::NativeHandle *out, PinId pin_id, u32 flags, os::NativeHandle resource_limit); + Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc); + Result PinProgram(PinId *out, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status); + Result SetProgramArgument(ncm::ProgramId program_id, const void *argument, size_t size); + Result GetProcessModuleInfo(u32 *out_count, ModuleInfo *out, size_t max_out_count, os::ProcessId process_id); + Result RegisterExternalCode(os::NativeHandle *out, ncm::ProgramId program_id); + void UnregisterExternalCode(ncm::ProgramId program_id); + void HasLaunchedBootProgram(bool *out, ncm::ProgramId program_id); }; static_assert(ams::ldr::impl::IsIProcessManagerInterface); static_assert(ams::ldr::impl::IsIDebugMonitorInterface); diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index c70acde65..741ab3ff6 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -218,9 +218,9 @@ namespace ams::ldr { } /* Fix flags. */ - const u16 program_info_flags = caps::GetProgramInfoFlags(o_meta->aci_kac, o_meta->aci->kac_size); - caps::SetProgramInfoFlags(program_info_flags, meta->acid_kac, meta->acid->kac_size); - caps::SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size); + const u16 program_info_flags = MakeProgramInfoFlag(static_cast(o_meta->aci_kac), o_meta->aci->kac_size / sizeof(util::BitPack32)); + UpdateProgramInfoFlag(program_info_flags, static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32)); + UpdateProgramInfoFlag(program_info_flags, static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); } } @@ -240,7 +240,7 @@ namespace ams::ldr { } /* When hbl is applet, adjust main thread priority. */ - if ((caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) { + if ((MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) { constexpr auto HblMainThreadPriorityApplication = 44; constexpr auto HblMainThreadPriorityApplet = 40; if (meta->npdm->main_thread_priority == HblMainThreadPriorityApplication) { @@ -262,8 +262,8 @@ namespace ams::ldr { /* Pre-process the capabilities. */ /* This is used to e.g. avoid passing memory region descriptor to older kernels. */ - caps::ProcessCapabilities(meta->acid_kac, meta->acid->kac_size); - caps::ProcessCapabilities(meta->aci_kac, meta->aci->kac_size); + PreProcessCapability(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32)); + PreProcessCapability(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); /* Set output. */ g_cached_program_id = loc.program_id; diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index b1bb41583..69fc3c18b 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -132,10 +132,10 @@ namespace ams::ldr { /* Helpers. */ Result GetProgramInfoFromMeta(ProgramInfo *out, const Meta *meta) { /* Copy basic info. */ - out->main_thread_priority = meta->npdm->main_thread_priority; - out->default_cpu_id = meta->npdm->default_cpu_id; + out->main_thread_priority = meta->npdm->main_thread_priority; + out->default_cpu_id = meta->npdm->default_cpu_id; out->main_thread_stack_size = meta->npdm->main_thread_stack_size; - out->program_id = meta->aci->program_id; + out->program_id = meta->aci->program_id; /* Copy access controls. */ size_t offset = 0; @@ -156,16 +156,16 @@ namespace ams::ldr { #undef COPY_ACCESS_CONTROL /* Copy flags. */ - out->flags = caps::GetProgramInfoFlags(meta->acid_kac, meta->acid->kac_size); + out->flags = MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); return ResultSuccess(); } bool IsApplet(const Meta *meta) { - return (caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet; + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet; } bool IsApplication(const Meta *meta) { - return (caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application; + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application; } Npdm::AddressSpaceType GetAddressSpaceType(const Meta *meta) { @@ -226,7 +226,7 @@ namespace ams::ldr { R_UNLESS(meta->aci->program_id <= meta->acid->program_id_max, ldr::ResultInvalidProgramId()); /* Validate the kernel capabilities. */ - R_TRY(caps::ValidateCapabilities(meta->acid_kac, meta->acid->kac_size, meta->aci_kac, meta->aci->kac_size)); + R_TRY(TestCapability(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32), static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32))); /* If we have data to validate, validate it. */ if (code_verification_data.has_data && meta->check_verification_data) { @@ -335,15 +335,15 @@ namespace ams::ldr { return ResultSuccess(); } - Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, os::NativeHandle reslimit_h) { + Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, os::NativeHandle resource_limit) { /* Clear output. */ std::memset(out, 0, sizeof(*out)); /* Set name, version, program id, resource limit handle. */ std::memcpy(out->name, meta->npdm->program_name, sizeof(out->name) - 1); - out->version = meta->npdm->version; - out->program_id = static_cast(meta->aci->program_id); - out->reslimit = reslimit_h; + out->version = meta->npdm->version; + out->program_id = meta->aci->program_id.value; + out->reslimit = resource_limit; /* Set flags. */ R_TRY(GetCreateProcessFlags(std::addressof(out->flags), meta, flags)); @@ -427,7 +427,7 @@ namespace ams::ldr { } } - Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const bool *has_nso, const args::ArgumentInfo *arg_info) { + Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument) { /* Clear output. */ out->args_address = 0; out->args_size = 0; @@ -435,6 +435,7 @@ namespace ams::ldr { std::memset(out->nso_size, 0, sizeof(out->nso_size)); size_t total_size = 0; + bool argument_allocated = false; /* Calculate base offsets. */ for (size_t i = 0; i < Nso_Count; i++) { @@ -446,15 +447,15 @@ namespace ams::ldr { out->nso_size[i] = text_end; out->nso_size[i] = std::max(out->nso_size[i], ro_end); out->nso_size[i] = std::max(out->nso_size[i], rw_end); - out->nso_size[i] = (out->nso_size[i] + size_t(0xFFFul)) & ~size_t(0xFFFul); + out->nso_size[i] = util::AlignUp(out->nso_size[i], os::MemoryPageSize); total_size += out->nso_size[i]; - if (arg_info != nullptr && arg_info->args_size && !out->args_size) { + if (!argument_allocated && argument != nullptr) { out->args_address = total_size; - out->args_size = 2 * arg_info->args_size + args::ArgumentSizeMax + 2 * sizeof(u32); - out->args_size = (out->args_size + size_t(0xFFFul)) & ~size_t(0xFFFul); + out->args_size = util::AlignUp(2 * sizeof(u32) + argument->argument_size * 2 + ArgumentStore::ArgumentBufferSize, os::MemoryPageSize); total_size += out->args_size; + argument_allocated = true; } } } @@ -516,13 +517,13 @@ namespace ams::ldr { return ResultSuccess(); } - Result CreateProcessImpl(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const args::ArgumentInfo *arg_info, u32 flags, os::NativeHandle reslimit_h) { + Result CreateProcessImpl(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { /* Get CreateProcessParameter. */ svc::CreateProcessParameter param; - R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, reslimit_h)); + R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit)); /* Decide on an NSO layout. */ - R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), nso_headers, has_nso, arg_info)); + R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), nso_headers, has_nso, argument)); /* Actually create process. */ svc::Handle process_handle; @@ -567,7 +568,7 @@ namespace ams::ldr { return ResultSuccess(); } - Result LoadNsoIntoProcessMemory(os::NativeHandle process_handle, fs::FileHandle file, uintptr_t map_address, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size) { + Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, uintptr_t map_address, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size) { /* Map and read data from file. */ { AutoCloseMap map(map_address, process_handle, nso_address, nso_size); @@ -588,7 +589,7 @@ namespace ams::ldr { std::memset(reinterpret_cast(map_address), 0, nso_header->text_dst_offset); std::memset(reinterpret_cast(map_address + text_end), 0, nso_header->ro_dst_offset - text_end); std::memset(reinterpret_cast(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end); - std::memset(reinterpret_cast(map_address + rw_end), 0, nso_header->bss_size); + std::memset(reinterpret_cast(map_address + rw_end), 0, nso_header->bss_size); /* Apply embedded patches. */ ApplyEmbeddedPatchesToModule(nso_header->module_id, map_address, nso_size); @@ -598,9 +599,9 @@ namespace ams::ldr { } /* Set permissions. */ - const size_t text_size = (static_cast(nso_header->text_size) + size_t(0xFFFul)) & ~size_t(0xFFFul); - const size_t ro_size = (static_cast(nso_header->ro_size) + size_t(0xFFFul)) & ~size_t(0xFFFul); - const size_t rw_size = (static_cast(nso_header->rw_size + nso_header->bss_size) + size_t(0xFFFul)) & ~size_t(0xFFFul); + const size_t text_size = util::AlignUp(nso_header->text_size, os::MemoryPageSize); + const size_t ro_size = util::AlignUp(nso_header->ro_size, os::MemoryPageSize); + const size_t rw_size = util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize); if (text_size) { R_TRY(svc::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, svc::MemoryPermission_ReadExecute)); } @@ -614,7 +615,7 @@ namespace ams::ldr { return ResultSuccess(); } - Result LoadNsosIntoProcessMemory(const ProcessInfo *process_info, const NsoHeader *nso_headers, const bool *has_nso, const args::ArgumentInfo *arg_info) { + Result LoadAutoLoadModules(const ProcessInfo *process_info, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument) { /* Load each NSO. */ for (size_t i = 0; i < Nso_Count; i++) { if (has_nso[i]) { @@ -625,12 +626,12 @@ namespace ams::ldr { uintptr_t map_address; R_TRY(SearchFreeRegion(std::addressof(map_address), process_info->nso_size[i])); - R_TRY(LoadNsoIntoProcessMemory(process_info->process_handle, file, map_address, nso_headers + i, process_info->nso_address[i], process_info->nso_size[i])); + R_TRY(LoadAutoLoadModule(process_info->process_handle, file, map_address, nso_headers + i, process_info->nso_address[i], process_info->nso_size[i])); } } /* Load arguments, if present. */ - if (arg_info != nullptr) { + if (argument != nullptr) { /* Write argument data into memory. */ { uintptr_t map_address; @@ -642,8 +643,8 @@ namespace ams::ldr { ProgramArguments *args = reinterpret_cast(map_address); std::memset(args, 0, sizeof(*args)); args->allocated_size = process_info->args_size; - args->arguments_size = arg_info->args_size; - std::memcpy(args->arguments, arg_info->args, arg_info->args_size); + args->arguments_size = argument->argument_size; + std::memcpy(args->arguments, argument->argument, argument->argument_size); } /* Set argument region permissions. */ @@ -656,87 +657,81 @@ namespace ams::ldr { } /* Process Creation API. */ - Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h) { - /* Use global storage for NSOs. */ - NsoHeader *nso_headers = g_nso_headers; - bool *has_nso = g_has_nso; - const auto arg_info = args::Get(loc.program_id); + Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { + /* Mount code. */ + AMS_UNUSED(path); + ScopedCodeMount mount(loc, override_status); + R_TRY(mount.GetResult()); + /* Load meta, possibly from cache. */ + Meta meta; + R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status)); + + /* Validate meta. */ + R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData())); + + /* Load, validate NSOs. */ + R_TRY(LoadNsoHeaders(g_nso_headers, g_has_nso)); + R_TRY(ValidateNsoHeaders(g_nso_headers, g_has_nso)); + + /* Actually create process. */ + ProcessInfo info; + R_TRY(CreateProcessImpl(std::addressof(info), std::addressof(meta), g_nso_headers, g_has_nso, argument, flags, resource_limit)); + + /* Load NSOs into process memory. */ { - /* Mount code. */ - AMS_UNUSED(path); - ScopedCodeMount mount(loc, override_status); - R_TRY(mount.GetResult()); + /* Ensure we close the process handle, if we fail. */ + auto process_guard = SCOPE_GUARD { os::CloseNativeHandle(info.process_handle); }; - /* Load meta, possibly from cache. */ - Meta meta; - R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status)); + /* Load all NSOs. */ + R_TRY(LoadAutoLoadModules(std::addressof(info), g_nso_headers, g_has_nso, argument)); - /* Validate meta. */ - R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData())); + /* We don't need to close the process handle, since we succeeded. */ + process_guard.Cancel(); + } - /* Load, validate NSOs. */ - R_TRY(LoadNsoHeaders(nso_headers, has_nso)); - R_TRY(ValidateNsoHeaders(nso_headers, has_nso)); + /* Register NSOs with the RoManager. */ + { + /* Nintendo doesn't validate this get, but we do. */ + os::ProcessId process_id = os::GetProcessId(info.process_handle); - /* Actually create process. */ - ProcessInfo info; - R_TRY(CreateProcessImpl(std::addressof(info), std::addressof(meta), nso_headers, has_nso, arg_info, flags, reslimit_h)); + /* Register new process. */ + const auto as_type = GetAddressSpaceType(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated); - /* Load NSOs into process memory. */ - { - /* Ensure we close the process handle, if we fail. */ - auto process_guard = SCOPE_GUARD { os::CloseNativeHandle(info.process_handle); }; - - /* Load all NSOs. */ - R_TRY(LoadNsosIntoProcessMemory(std::addressof(info), nso_headers, has_nso, arg_info)); - - /* We don't need to close the process handle, since we succeeded. */ - process_guard.Cancel(); - } - - /* Register NSOs with the RoManager. */ - { - /* Nintendo doesn't validate this get, but we do. */ - os::ProcessId process_id = os::GetProcessId(info.process_handle); - - /* Register new process. */ - /* NOTE: Nintendo uses meta->aci->program_id, not loc.program_id. Should we? */ - const auto as_type = GetAddressSpaceType(std::addressof(meta)); - RoManager::GetInstance().RegisterProcess(pin_id, process_id, loc.program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated); - - /* Register all NSOs. */ - for (size_t i = 0; i < Nso_Count; i++) { - if (has_nso[i]) { - RoManager::GetInstance().AddNso(pin_id, nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]); - } + /* Register all NSOs. */ + for (size_t i = 0; i < Nso_Count; i++) { + if (g_has_nso[i]) { + RoManager::GetInstance().AddNso(pin_id, g_nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]); } } - - /* If we're overriding for HBL, perform HTML document redirection. */ - if (override_status.IsHbl()) { - /* Don't validate result, failure is okay. */ - RedirectHtmlDocumentPathForHbl(loc); - } - - /* Clear the external code for the program. */ - fssystem::DestroyExternalCode(loc.program_id); - - /* Note that we've created the program. */ - SetLaunchedBootProgram(loc.program_id); - - /* Move the process handle to output. */ - *out = info.process_handle; } + /* If we're overriding for HBL, perform HTML document redirection. */ + if (override_status.IsHbl()) { + /* Don't validate result, failure is okay. */ + RedirectHtmlDocumentPathForHbl(loc); + } + + /* Clear the external code for the program. */ + fssystem::DestroyExternalCode(loc.program_id); + + /* Note that we've created the program. */ + SetLaunchedBootProgram(loc.program_id); + + /* Move the process handle to output. */ + *out = info.process_handle; + return ResultSuccess(); } - Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc) { + Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path) { Meta meta; /* Load Meta. */ { + AMS_UNUSED(path); + ScopedCodeMount mount(loc); R_TRY(mount.GetResult()); R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus())); diff --git a/stratosphere/loader/source/ldr_process_creation.hpp b/stratosphere/loader/source/ldr_process_creation.hpp index e4924e628..f700dba15 100644 --- a/stratosphere/loader/source/ldr_process_creation.hpp +++ b/stratosphere/loader/source/ldr_process_creation.hpp @@ -14,13 +14,13 @@ * along with this program. If not, see . */ #pragma once -#include "ldr_arguments.hpp" +#include "ldr_argument_store.hpp" namespace ams::ldr { /* Process Creation API. */ - Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h); - Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc); + Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit); + Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path); Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status); Result UnpinProgram(PinId id);