diff --git a/config_templates/override_config.ini b/config_templates/override_config.ini index 489c9b0f1..fa86f1efc 100644 --- a/config_templates/override_config.ini +++ b/config_templates/override_config.ini @@ -1,9 +1,10 @@ [hbl_config] ; Program Specific Config ; Up to 8 program-specific configurations can be set. -; These use `program_id_#` and `override_key_#` +; These use `program_id_#`, `override_address_space_#`, and `override_key_#` ; where # is in range [0,7]. ; program_id_0=010000000000100D +; override_address_space=39_bit ; override_key_0=!R ; Any Application Config @@ -12,6 +13,7 @@ ; by a program specific config. ; override_any_app=true ; override_any_app_key=R +; override_any_app_address_space=39_bit ; path=atmosphere/hbl.nsp [default_config] diff --git a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp index b7d5847f0..ace7b0c2a 100644 --- a/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp +++ b/libraries/libstratosphere/include/stratosphere/cfg/cfg_types.hpp @@ -23,9 +23,17 @@ namespace ams::cfg { namespace impl { enum OverrideStatusFlag : u64 { - OverrideStatusFlag_Hbl = BIT(0), - OverrideStatusFlag_ProgramSpecific = BIT(1), - OverrideStatusFlag_CheatEnabled = BIT(2), + OverrideStatusFlag_Hbl = (1u << 0), + OverrideStatusFlag_ProgramSpecific = (1u << 1), + OverrideStatusFlag_CheatEnabled = (1u << 2), + + OverrideStatusFlag_AddressSpaceShift = 3, + OverrideStatusFlag_AddressSpaceMask = ((1u << 2) - 1) << OverrideStatusFlag_AddressSpaceShift, + + OverrideStatusFlag_AddressSpace32Bit = (svc::CreateProcessFlag_AddressSpace32Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64BitDeprecated = (svc::CreateProcessFlag_AddressSpace64BitDeprecated >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace32BitWithoutAlias = (svc::CreateProcessFlag_AddressSpace32BitWithoutAlias >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, + OverrideStatusFlag_AddressSpace64Bit = (svc::CreateProcessFlag_AddressSpace64Bit >> svc::CreateProcessFlag_AddressSpaceShift) << OverrideStatusFlag_AddressSpaceShift, }; } @@ -46,6 +54,9 @@ namespace ams::cfg { DEFINE_FLAG_ACCESSORS(CheatEnabled) #undef DEFINE_FLAG_ACCESSORS + + constexpr inline u64 GetOverrideAddressSpaceFlags() const { return this->flags & impl::OverrideStatusFlag_AddressSpaceMask; } + constexpr inline bool HasOverrideAddressSpace() const { return this->IsHbl() && this->GetOverrideAddressSpaceFlags() != 0; } }; static_assert(sizeof(OverrideStatus) == 0x10, "sizeof(OverrideStatus)"); diff --git a/libraries/libstratosphere/source/cfg/cfg_override.cpp b/libraries/libstratosphere/source/cfg/cfg_override.cpp index 9bd7fedb6..7391059a8 100644 --- a/libraries/libstratosphere/source/cfg/cfg_override.cpp +++ b/libraries/libstratosphere/source/cfg/cfg_override.cpp @@ -44,7 +44,9 @@ namespace ams::cfg { struct HblOverrideConfig { ProgramOverrideKey program_configs[MaxProgramOverrideKeys]; + impl::OverrideStatusFlag program_as_flags[MaxProgramOverrideKeys]; OverrideKey override_any_app_key; + impl::OverrideStatusFlag override_any_app_as_flag; bool override_any_app; }; @@ -76,10 +78,21 @@ namespace ams::cfg { InvalidProgramOverrideKey, InvalidProgramOverrideKey, }, + .program_as_flags = { + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + impl::OverrideStatusFlag_AddressSpace64Bit, + }, .override_any_app_key = { .key_combination = KEY_R, .override_by_default = false, }, + .override_any_app_as_flag = impl::OverrideStatusFlag_AddressSpace64Bit, .override_any_app = true, }; @@ -137,6 +150,29 @@ namespace ams::cfg { return cfg; } + impl::OverrideStatusFlag ParseOverrideAddressSpace(const char *value) { + if (strcasecmp(value, "39_bit") == 0 || strcasecmp(value, "39") == 0) { + return impl::OverrideStatusFlag_AddressSpace64Bit; + } else if (strcasecmp(value, "36_bit") == 0 || strcasecmp(value, "36") == 0) { + return impl::OverrideStatusFlag_AddressSpace64BitDeprecated; + } else if (strcasecmp(value, "32_bit") == 0 || strcasecmp(value, "32") == 0) { + return impl::OverrideStatusFlag_AddressSpace32Bit; + } else if (strcasecmp(value, "32_bit_without_alias") == 0 || + strcasecmp(value, "32_bit_no_alias") == 0 || + strcasecmp(value, "32_without_alias") == 0 || + strcasecmp(value, "32_no_alias") || + strcasecmp(value, "32_bit_without_map") == 0 || + strcasecmp(value, "32_bit_no_map") == 0 || + strcasecmp(value, "32_without_map") == 0 || + strcasecmp(value, "32_no_map") == 0) + { + return impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias; + } else { + /* Default to 39-bit. */ + return impl::OverrideStatusFlag_AddressSpace64Bit; + } + } + inline void SetHblSpecificProgramId(size_t i, const char *value) { g_hbl_override_config.program_configs[i].program_id = {strtoul(value, nullptr, 16)}; } @@ -145,6 +181,10 @@ namespace ams::cfg { g_hbl_override_config.program_configs[i].override_key = ParseOverrideKey(value); } + inline void SetHblSpecificAddressSpace(size_t i, const char *value) { + g_hbl_override_config.program_as_flags[i] = ParseOverrideAddressSpace(value); + } + int OverrideConfigIniHandler(void *user, const char *section, const char *name, const char *value) { /* Taken and modified, with love, from Rajkosto's implementation. */ if (strcasecmp(section, "hbl_config") == 0) { @@ -180,6 +220,22 @@ namespace ams::cfg { SetHblSpecificOverrideKey(6, value); } else if (strcasecmp(name, "override_key_7") == 0) { SetHblSpecificOverrideKey(7, value); + } else if (strcasecmp(name, "override_address_space") == 0 || strcasecmp(name, "override_address_space_0") == 0) { + SetHblSpecificAddressSpace(0, value); + } else if (strcasecmp(name, "override_address_space_1") == 0) { + SetHblSpecificAddressSpace(1, value); + } else if (strcasecmp(name, "override_address_space_2") == 0) { + SetHblSpecificAddressSpace(2, value); + } else if (strcasecmp(name, "override_address_space_3") == 0) { + SetHblSpecificAddressSpace(3, value); + } else if (strcasecmp(name, "override_address_space_4") == 0) { + SetHblSpecificAddressSpace(4, value); + } else if (strcasecmp(name, "override_address_space_5") == 0) { + SetHblSpecificAddressSpace(5, value); + } else if (strcasecmp(name, "override_address_space_6") == 0) { + SetHblSpecificAddressSpace(6, value); + } else if (strcasecmp(name, "override_address_space_7") == 0) { + SetHblSpecificAddressSpace(7, value); } else if (strcasecmp(name, "override_any_app") == 0) { if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) { g_hbl_override_config.override_any_app = true; @@ -190,6 +246,8 @@ namespace ams::cfg { } } else if (strcasecmp(name, "override_any_app_key") == 0) { g_hbl_override_config.override_any_app_key = ParseOverrideKey(value); + } else if (strcasecmp(name, "override_any_app_address_space") == 0) { + g_hbl_override_config.override_any_app_as_flag = ParseOverrideAddressSpace(value); } else if (strcasecmp(name, "path") == 0) { while (*value == '/' || *value == '\\') { value++; @@ -346,10 +404,14 @@ namespace ams::cfg { /* Detect Hbl. */ if (IsAnyApplicationHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_any_app_key)) { status.SetHbl(); + status.flags &= ~impl::OverrideStatusFlag_AddressSpaceMask; + status.flags |= g_hbl_override_config.override_any_app_as_flag; } for (size_t i = 0; i < MaxProgramOverrideKeys; i++) { if (IsSpecificHblProgramId(i, program_id) && IsOverrideMatch(status, g_hbl_override_config.program_configs[i].override_key)) { status.SetHbl(); + status.flags &= ~impl::OverrideStatusFlag_AddressSpaceMask; + status.flags |= g_hbl_override_config.program_as_flags[i]; } } diff --git a/stratosphere/loader/source/ldr_meta.cpp b/stratosphere/loader/source/ldr_meta.cpp index fb46f49d6..10d9077c9 100644 --- a/stratosphere/loader/source/ldr_meta.cpp +++ b/stratosphere/loader/source/ldr_meta.cpp @@ -215,6 +215,21 @@ namespace ams::ldr { } } + /* Perform address space override. */ + if (status.HasOverrideAddressSpace()) { + /* Clear the existing address space. */ + meta->npdm->flags &= ~Npdm::MetaFlag_AddressSpaceTypeMask; + + /* Set the new address space flag. */ + switch (status.GetOverrideAddressSpaceFlags()) { + case cfg::impl::OverrideStatusFlag_AddressSpace32Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_32Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64BitDeprecated: meta->npdm->flags |= (Npdm::AddressSpaceType_64BitDeprecated) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace32BitWithoutAlias: meta->npdm->flags |= (Npdm::AddressSpaceType_32BitWithoutAlias) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + case cfg::impl::OverrideStatusFlag_AddressSpace64Bit: meta->npdm->flags |= (Npdm::AddressSpaceType_64Bit) << Npdm::MetaFlag_AddressSpaceTypeShift; break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } + /* When hbl is applet, adjust main thread priority. */ if ((caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) { constexpr auto HblMainThreadPriorityApplication = 44; diff --git a/stratosphere/loader/source/ldr_process_creation.cpp b/stratosphere/loader/source/ldr_process_creation.cpp index fdc07c5e7..d04a68fc5 100644 --- a/stratosphere/loader/source/ldr_process_creation.cpp +++ b/stratosphere/loader/source/ldr_process_creation.cpp @@ -262,7 +262,11 @@ namespace ams::ldr { flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias; break; case Npdm::AddressSpaceType_64Bit: - flags |= svc::CreateProcessFlag_AddressSpace64Bit; + if (hos::GetVersion() >= hos::Version_2_0_0 || svc::IsKernelMesosphere()) { + flags |= svc::CreateProcessFlag_AddressSpace64Bit; + } else { + flags |= svc::CreateProcessFlag_AddressSpace64BitDeprecated; + } break; default: return ResultInvalidMeta();