ldr/hbl: support address space width overrides

This commit is contained in:
Michael Scire 2020-11-20 16:57:07 -08:00
parent a9062994d2
commit e133d475ee
2 changed files with 76 additions and 3 deletions

View File

@ -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)");

View File

@ -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];
} }
} }