mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
ldr/hbl: support address space width overrides
This commit is contained in:
parent
835aa6b9db
commit
dd56f8449f
5 changed files with 99 additions and 5 deletions
|
@ -1,9 +1,10 @@
|
||||||
[hbl_config]
|
[hbl_config]
|
||||||
; Program Specific Config
|
; Program Specific Config
|
||||||
; Up to 8 program-specific configurations can be set.
|
; 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].
|
; where # is in range [0,7].
|
||||||
; program_id_0=010000000000100D
|
; program_id_0=010000000000100D
|
||||||
|
; override_address_space=39_bit
|
||||||
; override_key_0=!R
|
; override_key_0=!R
|
||||||
|
|
||||||
; Any Application Config
|
; Any Application Config
|
||||||
|
@ -12,6 +13,7 @@
|
||||||
; by a program specific config.
|
; by a program specific config.
|
||||||
; override_any_app=true
|
; override_any_app=true
|
||||||
; override_any_app_key=R
|
; override_any_app_key=R
|
||||||
|
; override_any_app_address_space=39_bit
|
||||||
; path=atmosphere/hbl.nsp
|
; path=atmosphere/hbl.nsp
|
||||||
|
|
||||||
[default_config]
|
[default_config]
|
||||||
|
|
|
@ -23,9 +23,17 @@ namespace ams::cfg {
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
enum OverrideStatusFlag : u64 {
|
enum OverrideStatusFlag : u64 {
|
||||||
OverrideStatusFlag_Hbl = BIT(0),
|
OverrideStatusFlag_Hbl = (1u << 0),
|
||||||
OverrideStatusFlag_ProgramSpecific = BIT(1),
|
OverrideStatusFlag_ProgramSpecific = (1u << 1),
|
||||||
OverrideStatusFlag_CheatEnabled = BIT(2),
|
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)
|
DEFINE_FLAG_ACCESSORS(CheatEnabled)
|
||||||
|
|
||||||
#undef DEFINE_FLAG_ACCESSORS
|
#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)");
|
static_assert(sizeof(OverrideStatus) == 0x10, "sizeof(OverrideStatus)");
|
||||||
|
|
|
@ -44,7 +44,9 @@ namespace ams::cfg {
|
||||||
|
|
||||||
struct HblOverrideConfig {
|
struct HblOverrideConfig {
|
||||||
ProgramOverrideKey program_configs[MaxProgramOverrideKeys];
|
ProgramOverrideKey program_configs[MaxProgramOverrideKeys];
|
||||||
|
impl::OverrideStatusFlag program_as_flags[MaxProgramOverrideKeys];
|
||||||
OverrideKey override_any_app_key;
|
OverrideKey override_any_app_key;
|
||||||
|
impl::OverrideStatusFlag override_any_app_as_flag;
|
||||||
bool override_any_app;
|
bool override_any_app;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,10 +78,21 @@ namespace ams::cfg {
|
||||||
InvalidProgramOverrideKey,
|
InvalidProgramOverrideKey,
|
||||||
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 = {
|
.override_any_app_key = {
|
||||||
.key_combination = KEY_R,
|
.key_combination = KEY_R,
|
||||||
.override_by_default = false,
|
.override_by_default = false,
|
||||||
},
|
},
|
||||||
|
.override_any_app_as_flag = impl::OverrideStatusFlag_AddressSpace64Bit,
|
||||||
.override_any_app = true,
|
.override_any_app = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +150,29 @@ namespace ams::cfg {
|
||||||
return 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) {
|
inline void SetHblSpecificProgramId(size_t i, const char *value) {
|
||||||
g_hbl_override_config.program_configs[i].program_id = {strtoul(value, nullptr, 16)};
|
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);
|
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) {
|
int OverrideConfigIniHandler(void *user, const char *section, const char *name, const char *value) {
|
||||||
/* Taken and modified, with love, from Rajkosto's implementation. */
|
/* Taken and modified, with love, from Rajkosto's implementation. */
|
||||||
if (strcasecmp(section, "hbl_config") == 0) {
|
if (strcasecmp(section, "hbl_config") == 0) {
|
||||||
|
@ -180,6 +220,22 @@ namespace ams::cfg {
|
||||||
SetHblSpecificOverrideKey(6, value);
|
SetHblSpecificOverrideKey(6, value);
|
||||||
} else if (strcasecmp(name, "override_key_7") == 0) {
|
} else if (strcasecmp(name, "override_key_7") == 0) {
|
||||||
SetHblSpecificOverrideKey(7, value);
|
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) {
|
} else if (strcasecmp(name, "override_any_app") == 0) {
|
||||||
if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
|
if (strcasecmp(value, "true") == 0 || strcasecmp(value, "1") == 0) {
|
||||||
g_hbl_override_config.override_any_app = true;
|
g_hbl_override_config.override_any_app = true;
|
||||||
|
@ -190,6 +246,8 @@ namespace ams::cfg {
|
||||||
}
|
}
|
||||||
} else if (strcasecmp(name, "override_any_app_key") == 0) {
|
} else if (strcasecmp(name, "override_any_app_key") == 0) {
|
||||||
g_hbl_override_config.override_any_app_key = ParseOverrideKey(value);
|
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) {
|
} else if (strcasecmp(name, "path") == 0) {
|
||||||
while (*value == '/' || *value == '\\') {
|
while (*value == '/' || *value == '\\') {
|
||||||
value++;
|
value++;
|
||||||
|
@ -346,10 +404,14 @@ namespace ams::cfg {
|
||||||
/* Detect Hbl. */
|
/* Detect Hbl. */
|
||||||
if (IsAnyApplicationHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_any_app_key)) {
|
if (IsAnyApplicationHblProgramId(program_id) && IsOverrideMatch(status, g_hbl_override_config.override_any_app_key)) {
|
||||||
status.SetHbl();
|
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++) {
|
for (size_t i = 0; i < MaxProgramOverrideKeys; i++) {
|
||||||
if (IsSpecificHblProgramId(i, program_id) && IsOverrideMatch(status, g_hbl_override_config.program_configs[i].override_key)) {
|
if (IsSpecificHblProgramId(i, program_id) && IsOverrideMatch(status, g_hbl_override_config.program_configs[i].override_key)) {
|
||||||
status.SetHbl();
|
status.SetHbl();
|
||||||
|
status.flags &= ~impl::OverrideStatusFlag_AddressSpaceMask;
|
||||||
|
status.flags |= g_hbl_override_config.program_as_flags[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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. */
|
/* When hbl is applet, adjust main thread priority. */
|
||||||
if ((caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) {
|
if ((caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet) {
|
||||||
constexpr auto HblMainThreadPriorityApplication = 44;
|
constexpr auto HblMainThreadPriorityApplication = 44;
|
||||||
|
|
|
@ -262,7 +262,11 @@ namespace ams::ldr {
|
||||||
flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias;
|
flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias;
|
||||||
break;
|
break;
|
||||||
case Npdm::AddressSpaceType_64Bit:
|
case Npdm::AddressSpaceType_64Bit:
|
||||||
|
if (hos::GetVersion() >= hos::Version_2_0_0 || svc::IsKernelMesosphere()) {
|
||||||
flags |= svc::CreateProcessFlag_AddressSpace64Bit;
|
flags |= svc::CreateProcessFlag_AddressSpace64Bit;
|
||||||
|
} else {
|
||||||
|
flags |= svc::CreateProcessFlag_AddressSpace64BitDeprecated;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return ResultInvalidMeta();
|
return ResultInvalidMeta();
|
||||||
|
|
Loading…
Reference in a new issue