From 5a5d9b206bb4d692bc35a34b519c9b4bbb544f52 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Thu, 19 Mar 2026 16:32:12 +0200 Subject: [PATCH] exosphere: automatically adjust dram id if needed Checks if programmed memory size matches the one from fused dram id. If not, adjust it properly so PCV can do proper training and not crash. --- .../program/source/smc/secmon_smc_info.cpp | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/exosphere/program/source/smc/secmon_smc_info.cpp b/exosphere/program/source/smc/secmon_smc_info.cpp index 11f4a693a..01fa3b93c 100644 --- a/exosphere/program/source/smc/secmon_smc_info.cpp +++ b/exosphere/program/source/smc/secmon_smc_info.cpp @@ -169,6 +169,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 +199,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 +492,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; + } } }