From 0a31b2e7e0e45cfa486b771adaefcadd96cea334 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Thu, 19 Mar 2026 16:35:36 +0200 Subject: [PATCH] exosphere: allow memory mode to be used on retail --- config_templates/exosphere.ini | 8 +++++++ .../program/source/smc/secmon_smc_info.cpp | 23 ++++++++----------- fusee/program/source/fusee_setup_horizon.cpp | 6 +++++ .../secmon/secmon_monitor_context.hpp | 2 ++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/config_templates/exosphere.ini b/config_templates/exosphere.ini index 4a2d5efeb..ddc761b09 100644 --- a/config_templates/exosphere.ini +++ b/config_templates/exosphere.ini @@ -15,6 +15,13 @@ # Desc: Controls whether userland has access to the PMU registers. # NOTE: It is unknown what effects this has on official code. +# Key: enable_mem_mode, default: 0. +# Desc: Controls whether boot config memory mode is taken into account +# for retail units. This does not affect development units. +# NOTE: On retail units max ram size is capped to 4GB. +# Enabling this will use the boot config memory mode parameter, +# which by default is auto and size gets set based on physical size. + # Key: blank_prodinfo_sysmmc, default: 0. # Desc: Controls whether PRODINFO should be blanked in sysmmc. # This will cause the system to see dummied out keys and @@ -55,6 +62,7 @@ debugmode=1 debugmode_user=0 disable_user_exception_handlers=0 enable_user_pmu_access=0 +enable_mem_mode=0 blank_prodinfo_sysmmc=0 blank_prodinfo_emummc=0 allow_writing_to_cal_sysmmc=0 diff --git a/exosphere/program/source/smc/secmon_smc_info.cpp b/exosphere/program/source/smc/secmon_smc_info.cpp index a08543287..0e11c529e 100644 --- a/exosphere/program/source/smc/secmon_smc_info.cpp +++ b/exosphere/program/source/smc/secmon_smc_info.cpp @@ -132,13 +132,13 @@ namespace ams::secmon::smc { } u32 GetMemoryMode() { - /* Unless development function is enabled or memory_mode_auto is set, we're 4 GB. */ + /* Unless development function or forced boot config memory size is enabled, we're 4 GB. */ u32 memory_mode = pkg1::MemoryMode_4GB; - if (GetSecmonConfiguration().IsMemoryModeAuto()) { - /* If memory_mode_auto is set, determine memory mode from physical memory */ - memory_mode = GetMemoryMode(pkg1::MemoryMode_Auto); - } else if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { + const auto &bcd = GetBootConfig().data; + const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */ + + if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) { memory_mode = GetMemoryMode(bcd.GetMemoryMode()); } return memory_mode; @@ -148,23 +148,20 @@ namespace ams::secmon::smc { pkg1::MemorySize memory_size = pkg1::MemorySize_4GB; util::BitPack32 value = {}; - if (const auto &bcd = GetBootConfig().data; bcd.IsDevelopmentFunctionEnabled()) { - memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode())); + const auto &bcd = GetBootConfig().data; + const auto &sc = GetSecmonConfiguration(); /* Exosphere extensions */ + if (bcd.IsDevelopmentFunctionEnabled()) { value.Set(bcd.GetKernelFlags1()); value.Set(bcd.GetKernelFlags0()); } - if (GetSecmonConfiguration().IsMemoryModeAuto()) { - memory_size = pkg1::GetMemorySize(GetMemoryMode(pkg1::MemoryMode_Auto)); + if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) { + memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode())); } - value.Set(memory_size); - /* Exosphere extensions. */ - const auto &sc = GetSecmonConfiguration(); - if (!sc.DisableUserModeExceptionHandlers()) { value.Set(true); } diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index 6693ced18..94a9347c5 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -435,6 +435,12 @@ namespace ams::nxboot { } else { storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_EnableUserModePerformanceCounterAccess; } + } else if (std::strcmp(entry.key, "enable_mem_mode") == 0) { + if (entry.value[0] == '1') { + storage_ctx.flags[0] |= secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled; + } else { + storage_ctx.flags[0] &= ~secmon::SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled; + } } else if (std::strcmp(entry.key, "blank_prodinfo_sysmmc") == 0) { if (!emummc_enabled) { if (entry.value[0] == '1') { diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp index 3ea1fd016..79282ee5b 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp @@ -30,6 +30,7 @@ namespace ams::secmon { SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary = (1u << 5), SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc = (1u << 6), SecureMonitorConfigurationFlag_ForceEnableUsb30 = (1u << 7), + SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled = (1u << 8), SecureMonitorConfigurationFlag_Default = SecureMonitorConfigurationFlag_IsDevelopmentFunctionEnabledForKernel, }; @@ -106,6 +107,7 @@ namespace ams::secmon { constexpr bool ShouldUseBlankCalibrationBinary() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ShouldUseBlankCalibrationBinary) != 0; } constexpr bool AllowWritingToCalibrationBinarySysmmc() const { return (this->flags[0] & SecureMonitorConfigurationFlag_AllowWritingToCalibrationBinarySysmmc) != 0; } constexpr bool IsUsb30ForceEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_ForceEnableUsb30) != 0; } + constexpr bool IsBootConfigMemoryModeEnabled() const { return (this->flags[0] & SecureMonitorConfigurationFlag_BootConfigMemoryModeEnabled) != 0; } constexpr bool IsDevelopmentFunctionEnabled(bool for_kern) const { return for_kern ? this->IsDevelopmentFunctionEnabledForKernel() : this->IsDevelopmentFunctionEnabledForUser(); } };