diff --git a/config_templates/exosphere.ini b/config_templates/exosphere.ini index 8df772ccf..f815b8cc7 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 @@ -51,6 +58,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 11f4a693a..88cdeefe0 100644 --- a/exosphere/program/source/smc/secmon_smc_info.cpp +++ b/exosphere/program/source/smc/secmon_smc_info.cpp @@ -132,10 +132,13 @@ namespace ams::secmon::smc { } u32 GetMemoryMode() { - /* Unless development function is enabled, 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 (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()); } @@ -146,17 +149,19 @@ 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()); } - value.Set(memory_size); + if (bcd.IsDevelopmentFunctionEnabled() || sc.IsBootConfigMemoryModeEnabled()) { + memory_size = GetMemorySize(GetMemoryMode(bcd.GetMemoryMode())); + } - /* Exosphere extensions. */ - const auto &sc = GetSecmonConfiguration(); + value.Set(memory_size); if (!sc.DisableUserModeExceptionHandlers()) { value.Set(true); @@ -169,6 +174,27 @@ namespace ams::secmon::smc { return value.value; } + fuse::DramId GetDramIdAdjusted() { + const auto dram_id = fuse::GetDramId(); + AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count); + + const auto fuse_mem_size = DramIdToMemorySize[dram_id]; + const auto phys_mem_size = GetPhysicalMemorySize(); + + AMS_ABORT_UNLESS(fuse_mem_size <= phys_mem_size); + + if (fuse_mem_size == phys_mem_size) { + return dram_id; + } + + /* Adjust Dram ID to match density/ranks. */ + if (GetSocType() == fuse::SocType_Erista) { + return fuse::DramId_IcosaSamsung6GB; + } else { /* fuse::SocType_Mariko */ + return fuse::DramId_IowaSamsung1y8GBX; + } + } + constinit u64 g_payload_address = 0; constinit bool g_set_true_target_firmware = false; @@ -178,7 +204,7 @@ namespace ams::secmon::smc { args.r[1] = GetBootConfig().signed_data.IsProgramVerificationDisabled(); break; case ConfigItem::DramId: - args.r[1] = fuse::GetDramId(); + args.r[1] = GetDramIdAdjusted(); /* Nintendo: fuse::GetDramId() */ break; case ConfigItem::SecurityEngineInterruptNumber: args.r[1] = SecurityEngineUserInterruptId; @@ -471,9 +497,18 @@ namespace ams::secmon::smc { /* For exosphere's usage. */ pkg1::MemorySize GetPhysicalMemorySize() { - const auto dram_id = fuse::GetDramId(); - AMS_ABORT_UNLESS(dram_id < fuse::DramId_Count); - return DramIdToMemorySize[dram_id]; + const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress(); + const u32 mem_size = reg::Read(MC + MC_EMEM_CFG) & 0x3FFF; + + switch (mem_size >> 10) { + case 4: + default: + return pkg1::MemorySize_4GB; + case 6: + return pkg1::MemorySize_6GB; + case 8: + return pkg1::MemorySize_8GB; + } } } diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index 0302895e3..f5ec03ce3 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -545,6 +545,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 c37b76c82..28517ea74 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, }; @@ -103,6 +104,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(); } };