From e1003520ebc8b52e5bed97de0e1174bebf3d4dd1 Mon Sep 17 00:00:00 2001 From: Lightos1 <124387232+Lightos1@users.noreply.github.com> Date: Thu, 16 Apr 2026 20:49:58 +0200 Subject: [PATCH] Revert "initial mrf implementation with some bugs to fix" This reverts commit 819913ffd927c2c1d0aaa205b48683655f7279e3. --- .../loader/source/oc/customize.cpp | 2 +- .../oc/erista/calculate_timings_erista.cpp | 2 +- .../source/oc/mariko/calculate_timings.cpp | 42 +-- .../source/oc/mariko/calculate_timings.hpp | 2 +- .../loader/source/oc/mtc_timing_value.hpp | 58 ++-- .../loader/source/oc/oc_common.hpp | 1 - .../stratosphere/loader/source/oc/pcv/pcv.cpp | 2 +- .../loader/source/oc/pcv/pcv_asm.hpp | 19 +- .../loader/source/oc/pcv/pcv_erista.hpp | 33 +- .../loader/source/oc/pcv/pcv_mariko.cpp | 292 +++++------------- .../loader/source/oc/pcv/pcv_mariko.hpp | 153 +-------- 11 files changed, 112 insertions(+), 494 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 9f85de34..1be77755 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -39,7 +39,7 @@ volatile CustomizeTable C = { .eristaEmcMaxClock1 = 1600000, .eristaEmcMaxClock2 = 1600000, -.marikoEmcMaxClock = 1633000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ +.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ .marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */ .emcDvbShift = 0, diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp index ad482924..721c1a92 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/erista/calculate_timings_erista.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -#include +#include "../oc_common.hpp" #include "../mtc_timing_value.hpp" namespace ams::ldr::hoc::pcv::erista { diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp index 91a49bbb..78f8e1f3 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.cpp @@ -14,7 +14,7 @@ * along with this program. If not, see . */ -#include +#include "../oc_common.hpp" #include "../mtc_timing_value.hpp" #include "timing_tables.hpp" @@ -59,46 +59,8 @@ namespace ams::ldr::hoc::pcv::mariko { mrw2 = static_cast(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); } - void CalculateTimings(double tCK_avg) { + void CalculateTimings() { GetRext(); - - tR2P = CEIL((RL * 0.426) - 2.0); - tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; - tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg); - tRATM = CEIL((tRTM - 10.0) + (RL * 0.426)); - - rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017); - qpop = rdv - 14; - quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782); - quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg); - einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width; - einput = quse - CEIL(9.928 / tCK_avg); - u32 qrst_duration = FLOOR(8.399 - tCK_avg); - u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); - qrst = PACK_U32(qrst_duration, qrstLow); - ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); - qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); - tW2P = (CEIL(WL * 1.7303) * 2) - 5; - tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast(tW2P))) + (BL / 2)); - tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR; - tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753)); - tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0; - - wdv = WL; - wsv = WL - 2; - wev = 0xA + (WL - 14); - - u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); - u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); - obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); - - pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361))); - - tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0; - - u32 tMMRI = tRCD + (tCK_avg * 3); - pdex2mrr = tMMRI + 10; - CalculateMrw2(); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.hpp index 61b324de..dbf63bae 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mariko/calculate_timings.hpp @@ -18,7 +18,7 @@ namespace ams::ldr::hoc::pcv::mariko { - void CalculateTimings(double tCK_avg); + void CalculateTimings(); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp index 765e66c0..b6a72cc6 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -111,6 +111,8 @@ namespace ams::ldr::hoc { const std::array tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; const std::array tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 }; + const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock; + const u32 tRCD = tRCD_values[C.t1_tRCD]; const u32 tRPpb = tRP_values[C.t2_tRP]; const u32 tRAS = tRAS_values[C.t3_tRAS]; @@ -126,39 +128,43 @@ namespace ams::ldr::hoc { const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; - inline u32 tR2P; - inline u32 tR2W; - inline u32 tRTM; - inline u32 tRATM; + const u32 tR2P = CEIL((RL * 0.426) - 2.0); + const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; + const u32 tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg); + const u32 tRATM = CEIL((tRTM - 10.0) + (RL * 0.426)); inline u32 rext; - inline u32 rdv; - inline u32 qpop; - inline u32 quse_width; - inline u32 quse; - inline u32 einput_duration; - inline u32 einput; - inline u32 qrst; - inline u32 ibdly; - inline u32 qsafe; + const u32 rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017); + const u32 qpop = rdv - 14; + const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782); + const u32 quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg); + const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width; + const u32 einput = quse - CEIL(9.928 / tCK_avg); + const u32 qrst_duration = FLOOR(8.399 - tCK_avg); + const u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); + const u32 qrst = PACK_U32(qrst_duration, qrstLow); + const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); + const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); + const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5; + const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast(tW2P))) + (BL / 2)); + const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR; + const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753)); + const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0; - inline u32 tW2P; - inline u32 tWTPDEN; - inline u32 tW2R; - inline u32 tWTM; - inline u32 tWATM; + const u32 wdv = WL; + const u32 wsv = WL - 2; + const u32 wev = 0xA + (WL - 14); - inline u32 wdv; - inline u32 wsv; - inline u32 wev; + const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); + const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); + const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); - inline u32 obdly; + const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361))); - inline u32 pdex2rw; + const u32 tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0; - inline u32 tCLKSTOP; - - inline u32 pdex2mrr; + const double tMMRI = tRCD + (tCK_avg * 3); + const double pdex2mrr = tMMRI + 10; /* Do this properly? */ inline u8 mrw2; } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp index 2205c4a3..2e900f72 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp @@ -51,7 +51,6 @@ namespace ams::ldr { R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013); R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); - R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016); } namespace ams::ldr::hoc { diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index 0b9ff6c8..3b29b705 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -178,7 +178,7 @@ namespace ams::ldr::hoc::pcv { if (isMariko) { mariko::Patch(mapped_nso, nso_size); } else { - mariko::Patch(mapped_nso, nso_size); + erista::Patch(mapped_nso, nso_size); } #endif diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp index ac96bb19..bf6d0b1d 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp @@ -20,12 +20,10 @@ #pragma once -#include +#include "../oc_common.hpp" namespace ams::ldr::hoc::pcv { - constexpr u32 NopIns = 0x1f2003d5; - inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) { return ((ins1 ^ ins2) >> 5) == 0; }; @@ -46,19 +44,4 @@ namespace ams::ldr::hoc::pcv { return static_cast((ins >> 5) & 0xFFFF); }; - inline auto AsmCompareBrNoRd = [](u32 ins1, u32 ins2) { - constexpr u32 RegMask = ~(((1 << 5) - 1) << 5); - return ((ins1 & RegMask) ^ (ins2 & RegMask)) == 0; - }; - - inline auto AsmCompareAddNoImm12 = [](u32 ins1, u32 ins2) { - constexpr u32 Imm12Mask = ~(((1 << 12) - 1) << 10); - return ((ins1 & Imm12Mask) ^ (ins2 & Imm12Mask)) == 0; - }; - - inline auto AsmCompareAdrpNoImm = [](u32 ins1, u32 ins2) { - constexpr u32 ImmMask = ~((((1 << 2) - 1) << 29) | (((1 << 19) - 1) << 5)); - return ((ins1 & ImmMask) ^ (ins2 & ImmMask)) == 0; - }; - } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp index c9b180ac..35dd3326 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_erista.hpp @@ -113,38 +113,7 @@ namespace ams::ldr::hoc::pcv::erista { constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */ constexpr u32 EmcClkPllmLimit = 1866'000'000; - constexpr u32 MTC_TABLE_REV = 7; - constexpr u32 MtcTableCountDefault = 10; - - constexpr size_t MtcFullTableSize = sizeof(EristaMtcTable) * MtcTableCountDefault; - constexpr u32 MtcFullTableCount = 3; - - /* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */ - enum DramId { - ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0, - ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1, - ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC = 2, /* This doesn't have a table in pcv? Wtf? */ - ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4, - ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7, /* No table, but expected */ - }; - - enum MtcTableIndex { - T210SdevEmcDvfsTableS4gb01 = 0, /* HB-MGCH */ - T210SdevEmcDvfsTableS6gb01 = 1, /* HM-MGCH */ - T210SdevEmcDvfsTableH4gb01 = 2, /* HR-NLE */ - MtcTableIndex_Invalid = 3, - }; - - struct MtcDramIndex { - DramId dramId; - MtcTableIndex index; - }; - - constexpr MtcDramIndex mtcIndexTable[] = { - { ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, }, - { ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, }, - { ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, }, - }; + constexpr u32 MTC_TABLE_REV = 7; void Patch(uintptr_t mapped_nso, size_t nso_size); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp index c55b545a..6e9313f5 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -18,7 +18,6 @@ * along with this program. If not, see . */ -#include #include "pcv.hpp" #include "../mtc_timing_value.hpp" #include "../mariko/calculate_timings.hpp" @@ -54,7 +53,7 @@ namespace ams::ldr::hoc::pcv::mariko { R_SKIP(); } - PATCH_OFFSET(ptr, C.marikoGpuVmin); + PATCH_OFFSET(ptr + 0, C.marikoGpuVmin); PATCH_OFFSET(ptr + 3, C.marikoGpuVmin); PATCH_OFFSET(ptr + 6, C.marikoGpuVmin); PATCH_OFFSET(ptr + 9, C.marikoGpuVmin); @@ -350,8 +349,6 @@ namespace ams::ldr::hoc::pcv::mariko { TABLE->shadow_regs_ca_train.PARAM = VALUE; \ TABLE->shadow_regs_rdwr_train.PARAM = VALUE; - const double tCK_avg = 1000'000.0 / table->rate_khz; - #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) /* Ram power down */ @@ -375,7 +372,7 @@ namespace ams::ldr::hoc::pcv::mariko { const u32 dyn_self_ref_control = (static_cast(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000); - CalculateTimings(tCK_avg); + CalculateTimings(); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); @@ -402,7 +399,7 @@ namespace ams::ldr::hoc::pcv::mariko { WRITE_PARAM_ALL_REG(table, emc_twtm, tWTM); WRITE_PARAM_ALL_REG(table, emc_twatm, tWATM); WRITE_PARAM_ALL_REG(table, emc_rext, rext); - WRITE_PARAM_ALL_REG(table, emc_wext, (table->rate_khz >= 2533000) ? 0x19 : 0x16); + WRITE_PARAM_ALL_REG(table, emc_wext, (C.marikoEmcMaxClock >= 2533000) ? 0x19 : 0x16); WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw); WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4); WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw); @@ -446,7 +443,7 @@ namespace ams::ldr::hoc::pcv::mariko { constexpr double MC_ARB_DIV = 4.0; constexpr u32 MC_ARB_SFA = 2; - table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV; + table->burst_mc_regs.mc_emem_arb_cfg = C.marikoEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV; table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; @@ -488,7 +485,7 @@ namespace ams::ldr::hoc::pcv::mariko { table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x115; - if (table->rate_khz >= 2133000) { + if (C.marikoEmcMaxClock >= 2133000) { table->la_scale_regs.mc_ftop_ptsa_rate = 0x1F; } else { table->la_scale_regs.mc_ftop_ptsa_rate = 0x1B; @@ -497,14 +494,14 @@ namespace ams::ldr::hoc::pcv::mariko { table->la_scale_regs.mc_ptsa_grant_decrement = 0x17ff; constexpr u32 MaskHigh = 0xFF00FFFF; - constexpr u32 Mask2 = 0xFFFFFF00; - constexpr u32 Mask3 = 0xFF00FF00; + constexpr u32 Mask2 = 0xFFFFFF00; + constexpr u32 Mask3 = 0xFF00FF00; - const u32 allowance1 = static_cast(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF; - const u32 allowance2 = static_cast(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF; - const u32 allowance3 = static_cast(0xB540 / (table->rate_khz / 0x3E8)) & 0xFF; - const u32 allowance4 = static_cast(0x9600 / (table->rate_khz / 0x3E8)) & 0xFF; - const u32 allowance5 = static_cast(0x8980 / (table->rate_khz / 0x3E8)) & 0xFF; + const u32 allowance1 = static_cast(0x32000 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF; + const u32 allowance2 = static_cast(0x9C40 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF; + const u32 allowance3 = static_cast(0xB540 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF; + const u32 allowance4 = static_cast(0x9600 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF; + const u32 allowance5 = static_cast(0x8980 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF; table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16); table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16); @@ -528,8 +525,8 @@ namespace ams::ldr::hoc::pcv::mariko { table->dram_timings.t_rp = tRFCpb; table->dram_timings.t_rfc = tRFCab; - table->dram_timings.rl = RL; + table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); table->emc_cfg_2 = 0x11083D; } @@ -538,24 +535,24 @@ namespace ams::ldr::hoc::pcv::mariko { constexpr u32 PllOscInKHz = 38400; constexpr u32 PllOscHalfKHz = 19200; - double target_freq_d = static_cast(table->rate_khz); + double target_freq_d = static_cast(C.marikoEmcMaxClock); - s32 divm_candidate_half = static_cast(table->rate_khz / PllOscHalfKHz); + s32 divm_candidate_half = static_cast(C.marikoEmcMaxClock / PllOscHalfKHz); - bool remainder_check = (table->rate_khz - PllOscInKHz * (table->rate_khz / PllOscInKHz)) > (table->rate_khz - PllOscHalfKHz * divm_candidate_half) && static_cast(((target_freq_d / PllOscHalfKHz - divm_candidate_half - 0.5) * 8192.0)) != 0; + bool remainder_check = (C.marikoEmcMaxClock - PllOscInKHz * (C.marikoEmcMaxClock / PllOscInKHz)) > (C.marikoEmcMaxClock - PllOscHalfKHz * divm_candidate_half) && static_cast(((target_freq_d / PllOscHalfKHz - divm_candidate_half - 0.5) * 8192.0)) != 0; u32 divm_final = remainder_check + 1; table->pllmb_divm = divm_final; double div_step_d = static_cast(PllOscInKHz) / divm_final; - s32 divn_integer = static_cast(table->rate_khz / div_step_d); + s32 divn_integer = static_cast(C.marikoEmcMaxClock / div_step_d); table->pllmb_divn = divn_integer; u32 divn_fraction = static_cast((target_freq_d / div_step_d - divn_integer - 0.5) * 8192.0); u32 actual_freq_khz = static_cast((divn_integer + 0.5 + divn_fraction * 0.000122070312) * div_step_d); - if (table->rate_khz - 2366001 < 133999) { + if (C.marikoEmcMaxClock - 2366001 < 133999) { s32 divn_fraction_ssc = static_cast((actual_freq_khz * 0.997 / div_step_d - divn_integer - 0.5) * 8192.0); double delta_scaled = (0.3 / div_step_d + 0.3 / div_step_d) * (divn_fraction - divn_fraction_ssc); @@ -583,7 +580,7 @@ namespace ams::ldr::hoc::pcv::mariko { table->pllm_ss_cfg &= 0xBFFFFFFF; table->pllmb_ss_cfg &= 0xBFFFFFFF; - u64 pair = (static_cast(divn_fraction) << 32) | static_cast(table->rate_khz); + u64 pair = (static_cast(divn_fraction) << 32) | static_cast(C.marikoEmcMaxClock); u32 pll_misc = (table->pllm_ss_ctrl2 & 0xFFFF0000) | static_cast((pair - actual_freq_khz) >> 32); table->pllm_ss_ctrl2 = pll_misc; @@ -591,168 +588,52 @@ namespace ams::ldr::hoc::pcv::mariko { } } - Result VerifyMtcTable(MarikoMtcTable *tableStart, u32 expectedFreq) { - Log("Rate_khz: %u, revision: %u\n", tableStart->rate_khz, tableStart->rev); - R_UNLESS(tableStart->rate_khz == expectedFreq, ldr::ResultInvalidMtcTable()); - R_UNLESS(tableStart->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); - - R_SUCCEED(); - } - - Result MtcValidateAllTables(MarikoMtcTable *tableStart, const u32 *validationList, u32 tableCount) { - for (u32 i = 0; i < tableCount; ++i) { - R_UNLESS(R_SUCCEEDED(VerifyMtcTable(&tableStart[i], validationList[i])), ldr::ResultInvalidMtcTable()); - } - - R_SUCCEED(); - } - - DramId GetDramId() { - u64 id64; - splGetConfig(SplConfigItem_DramId, &id64); - return static_cast(id64); - } - - MtcTableIndex GetMtcDramIndex(DramId dramId) { - for (u32 i = 0; i < std::size(mtcIndexTable); ++i) { - if (mtcIndexTable[i].dramId == dramId) { - return mtcIndexTable[i].index; - } - } - - return MtcTableIndex_Invalid; - } - - NORETURN void AbortInvalidDramId() { - // Log("Invalid dram id\n"); - // ViewLog(); - panic::SmcError(panic::Emc); - CRASH("Invalid dram id\n"); - } - - u32 GetMtcOffset(MtcTableIndex index) { - if (index < T210b0SdevEmcDvfsTableS4gb03) { - return index * mariko::MtcFullTableSize; - } - - /* There are 2 erista mtc tables between T210b0SdevEmcDvfsTableS4gb01 and T210b0SdevEmcDvfsTableS4gb03, so we have to do this adjustment. */ - return mariko::MtcFullTableSize * index + (2 * erista::MtcFullTableSize); - } - - void PrepareMtcMemoryRegion(u8 *firstTable, MarikoMtcTable *usedTable) { - memmove(firstTable, usedTable, mariko::MtcFullTableSize); - - /* Clear all other tables */ - /* 1 erista table is excluded because it's always before firstTable. */ - /* We also exclude the used table obviously. */ - constexpr size_t RemainingRegionSize = (mariko::MtcFullTableSize) * 16 + (erista::MtcFullTableSize * 2); - memset(firstTable + mariko::MtcFullTableSize, 0, RemainingRegionSize); - } - - std::vector newEmcList; - void MtcGenerateFreqTables() { - constexpr u32 OverwrittenEristaTables = erista::MtcFullTableCount - 1; /* We don't overwrite the first table */ - constexpr size_t MaxFreqSize = (OverwrittenEristaTables * erista::MtcTableCountDefault) + (mariko::MtcFullTableCount * mariko::MtcTableCountDefault); - constexpr u32 StepHz = 100000; - constexpr u32 RoundHz = 1000; - - newEmcList.clear(); - newEmcList.reserve(MaxFreqSize); - newEmcList.insert(newEmcList.end(), std::begin(EmcListDefault), std::end(EmcListDefault)); - - if (C.marikoEmcMaxClock <= EmcClkOSLimit) { - return; - } - - for (u32 stepIndex = 1;; ++stepIndex) { - u32 newFreq = EmcClkOSLimit + (stepIndex * StepHz + 1) / 3; - newFreq = (newFreq / RoundHz) * RoundHz; - - if (newFreq > C.marikoEmcMaxClock) { - break; - } - - newEmcList.push_back(newFreq); - } - - newEmcList.resize(std::min(newEmcList.size(), MaxFreqSize)); - } - - void MtcExtendTables(MarikoMtcTable *table) { - for (u32 i = mariko::MtcTableCountDefault; i < newEmcList.size(); ++i) { - std::memcpy(&table[i], &table[i - 1], sizeof(MarikoMtcTable)); - table[i].rate_khz = newEmcList[i]; - } - } - - bool patchedMtc = false; Result MemFreqMtcTable(u32 *ptr) { - if (C.marikoEmcMaxClock <= EmcClkOSLimit || patchedMtc) { + u32 khz_list[] = {1600000, 1331200, 204000}; + u32 khz_list_size = sizeof(khz_list) / sizeof(u32); + + // Generate list for mtc table pointers + MarikoMtcTable *table_list[khz_list_size]; + for (u32 i = 0; i < khz_list_size; i++) { + u8 *table = reinterpret_cast(ptr) - offsetof(MarikoMtcTable, rate_khz) - i * sizeof(MarikoMtcTable); + table_list[i] = reinterpret_cast(table); + R_UNLESS(table_list[i]->rate_khz == khz_list[i], ldr::ResultInvalidMtcTable()); + R_UNLESS(table_list[i]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); + } + + if (C.marikoEmcMaxClock <= EmcClkOSLimit) R_SKIP(); - } - static const DramId dramId = [] { - DramId id = GetDramId(); - id = IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL; - //Log("Dram id: %u\n", id); - return id; - }(); + MarikoMtcTable *table_alt = table_list[1], *table_max = table_list[0]; + MarikoMtcTable *tmp = new MarikoMtcTable; - static const MtcTableIndex mtcIndex = [] { - MtcTableIndex idx = GetMtcDramIndex(dramId); - /* If for some reason this happens, there is chance of recovering this. */ - if (idx == MtcTableIndex_Invalid) { - AbortInvalidDramId(); - } - return idx; - }(); + // Copy unmodified 1600000 table to tmp + std::memcpy(reinterpret_cast(tmp), reinterpret_cast(table_max), sizeof(MarikoMtcTable)); - /* Offset to dram id specific mtc table. */ - static const u32 mtcOffset = GetMtcOffset(mtcIndex); + /* Adjust timings properly according to the new frequency. */ + MemMtcTableAutoAdjust(table_max); - /* Offset from 1600MHz pointer to 204Mhz table start. */ - constexpr u32 StartAdjustment = offsetof(MarikoMtcTable, rate_khz) + sizeof(MarikoMtcTable) * 2; - u8 *startPtr = reinterpret_cast(ptr) - StartAdjustment; - MarikoMtcTable *table = reinterpret_cast(startPtr + mtcOffset); - R_UNLESS(R_SUCCEEDED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault)), ldr::ResultInvalidMtcTable()); + MemMtcPllmbDivisor(table_max); + // Overwrite 13312000 table with unmodified 1600000 table copied back + std::memcpy(reinterpret_cast(table_alt), reinterpret_cast(tmp), sizeof(MarikoMtcTable)); - table = reinterpret_cast(startPtr); + delete tmp; - PrepareMtcMemoryRegion(startPtr, table); - if (R_FAILED(MtcValidateAllTables(table, EmcListDefault, EmcListSizeDefault))) { - panic::SmcError(panic::Emc); - } - - MtcExtendTables(table); - for (u32 i = 0; i < newEmcList.size(); ++i) { - Log("freqList[%u] = %u\n", i, newEmcList[i]); - } - - if (R_FAILED(MtcValidateAllTables(table, newEmcList.data(), newEmcList.size()))) { - panic::SmcError(panic::Emc); - } - - for (u32 i = mariko::MtcTableCountDefault; i < newEmcList.size(); ++i) { - MemMtcTableAutoAdjust(&table[i]); - MemMtcPllmbDivisor(&table[i]); - } - - patchedMtc = true; + PATCH_OFFSET(ptr, C.marikoEmcMaxClock); R_SUCCEED(); } Result MemFreqDvbTable(u32 *ptr) { emc_dvb_dvfs_table_t *default_end = reinterpret_cast(ptr); - emc_dvb_dvfs_table_t *new_start = default_end + 1; + emc_dvb_dvfs_table_t *new_start = default_end + 1; // Validate existing table void *mem_dvb_table_head = reinterpret_cast(new_start) - sizeof(EmcDvbTableDefault); - bool validated = std::memcmp(mem_dvb_table_head, EmcDvbTableDefault, sizeof(EmcDvbTableDefault)) == 0; + bool validated = std::memcmp(mem_dvb_table_head, EmcDvbTableDefault, sizeof(EmcDvbTableDefault)) == 0; R_UNLESS(validated, ldr::ResultInvalidDvbTable()); - if (C.marikoEmcMaxClock <= EmcClkOSLimit) { + if (C.marikoEmcMaxClock <= EmcClkOSLimit) R_SKIP(); - } int32_t voltAdd = 25 * C.emcDvbShift; @@ -789,9 +670,8 @@ namespace ams::ldr::hoc::pcv::mariko { } Result MemFreqMax(u32 *ptr) { - if (C.marikoEmcMaxClock <= EmcClkOSLimit) { + if (C.marikoEmcMaxClock <= EmcClkOSLimit) R_SKIP(); - } PATCH_OFFSET(ptr, C.marikoEmcMaxClock); R_SUCCEED(); @@ -805,13 +685,12 @@ namespace ams::ldr::hoc::pcv::mariko { I2cSession _session; Result res = i2cOpenSession(&_session, dev); - if (R_FAILED(res)) { + if (R_FAILED(res)) return res; - } cmd.reg = reg; cmd.val = val; - res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All); + res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All); i2csessionClose(&_session); return res; } @@ -823,24 +702,21 @@ namespace ams::ldr::hoc::pcv::mariko { constexpr u32 uv_min = 250'000; auto validator = [entry]() { - R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type == 3, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type == 3, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type_2_3.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_2_3.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_2_3.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); R_SUCCEED(); }; R_TRY(validator()); u32 emc_uv = C.marikoEmcVddqVolt; - - if (!emc_uv) { + if (!emc_uv) R_SKIP(); - } - if (emc_uv % uv_step) { + if (emc_uv % uv_step) emc_uv = (emc_uv + uv_step - 1) / uv_step * uv_step; // rounding - } PATCH_OFFSET(ptr, emc_uv); @@ -855,53 +731,28 @@ namespace ams::ldr::hoc::pcv::mariko { return resultI2C; } - Result MemMtcTableAsm(u32 *ptr) { - u32 adrp = *(ptr - 1); - R_UNLESS(AsmCompareAdrpNoImm(adrp, MtcAdrpAsm), ldr::ResultInvalidMtcTable()); - - /* We don't check for matching register because both registers must be x0 in order to pass the previous checks. */ - /* The correct instructions will always be x0 since the mtcTable pointer is returned. */ - - /* Pray this does not break. */ - u32 br = *(ptr - 12); - R_UNLESS(AsmCompareBrNoRd(br, MtcBrAsm), ldr::ResultInvalidMtcTable()); - - /* Pray this does not break either. */ - u32 mov = *(ptr - 10); - R_UNLESS(asm_compare_no_rd(mov, MtcMovAsm), ldr::ResultInvalidMtcTable()); - - u8 movRd = asm_get_rd(mov); - u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd); - - PATCH_OFFSET(ptr - 12, NopIns); - PATCH_OFFSET(ptr - 10, movCountPatch); - R_SUCCEED(); - } - void Patch(uintptr_t mapped_nso, size_t nso_size) { - MtcGenerateFreqTables(); u32 CpuCvbDefaultMaxFreq = static_cast(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq); u32 GpuCvbDefaultMaxFreq = static_cast(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq); PatcherEntry patches[] = { - { "CPU Freq Vdd", &CpuFreqVdd, 1, nullptr, CpuClkOSLimit }, - { "CPU Freq Table", CpuFreqCvbTable, 1, nullptr, CpuCvbDefaultMaxFreq }, - { "CPU Volt DVFS", &CpuVoltDVFS, 1, nullptr, CpuVminOfficial }, - { "CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial }, - { "CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, CpuTune0Low }, - { "GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial }, - { "GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial }, - { "GPU Freq Table", GpuFreqCvbTable, 1, nullptr, GpuCvbDefaultMaxFreq }, - { "GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn }, - { "GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax }, - { "GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit }, - { "MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit }, - { "MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, EmcClkOSLimit }, - { "MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit }, - { "MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit }, - { "MEM Vddq", &EmcVddqVolt, 2, nullptr, EmcVddqDefault }, - { "MEM Vdd2", &MemVoltHandler, 2, nullptr, MemVdd2Default }, - { "Mem Table Asm", &MemMtcTableAsm, 0, &MemMtcGetGetTablePatternFn }, + {"CPU Freq Vdd", &CpuFreqVdd, 1, nullptr, CpuClkOSLimit}, + {"CPU Freq Table", CpuFreqCvbTable, 1, nullptr, CpuCvbDefaultMaxFreq}, + {"CPU Volt DVFS", &CpuVoltDVFS, 1, nullptr, CpuVminOfficial}, + {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial}, + {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0x0000FFCF}, + {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial}, + {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial}, + {"GPU Freq Table", GpuFreqCvbTable, 1, nullptr, GpuCvbDefaultMaxFreq}, + {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn}, + {"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax}, + {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit}, + {"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit}, + {"MEM Freq Dvb", &MemFreqDvbTable, 1, nullptr, EmcClkOSLimit}, + {"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit}, + {"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit}, + {"MEM Vddq", &EmcVddqVolt, 2, nullptr, EmcVddqDefault}, + {"MEM Vdd2", &MemVoltHandler, 2, nullptr, MemVdd2Default}, }; for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(MarikoMtcTable); ptr += sizeof(u32)) { @@ -923,7 +774,6 @@ namespace ams::ldr::hoc::pcv::mariko { CRASH(entry.description); } } - // ViewLog(); } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp index 2d61861d..4c57bf1c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp @@ -52,8 +52,6 @@ namespace ams::ldr::hoc::pcv::mariko { constexpr u32 CpuVoltOfficial = 1120; constexpr u32 CpuVminOfficial = 620; - constexpr u32 CpuTune0Low = 0xFFCF; - static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 }; static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 }; static_assert(sizeof(cpuVoltagePatchValues) == sizeof(cpuVoltagePatchOffsets), "Invalid cpuVoltagePatch size"); @@ -119,161 +117,12 @@ namespace ams::ldr::hoc::pcv::mariko { { 1600000, { 675, 650, 637, } }, }; - constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, }; - constexpr u32 EmcListSizeDefault = std::size(EmcListDefault); - constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1; - constexpr u32 EmcRateStep = 33'000; - constexpr u32 EmcRateStepScale = 33'200; - constexpr u32 EmcClkOSAlt = 1331'200; constexpr u32 EmcClkPllmLimit = 2133'000'000; constexpr u32 EmcVddqDefault = 600'000; constexpr u32 MemVdd2Default = 1100'000; - constexpr u32 MTC_TABLE_REV = 3; - constexpr u32 MtcTableCountDefault = 3; - - constexpr size_t MtcFullTableSize = sizeof(MarikoMtcTable) * MtcTableCountDefault; - constexpr u32 MtcFullTableCount = 17; - - /* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */ - enum DramId : u64 { - HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, - AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, - IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, - - IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, - IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, - IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, - IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, - - HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, - HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, - HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, - HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, - - IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, - IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, - HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, - - IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, - HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, - AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, - - HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, - AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, - - IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, - HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, - AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, - - AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, - - IOWA_4GB_HYNIX_H54G46CYRBX267 = 29, - HOAG_4GB_HYNIX_H54G46CYRBX267 = 30, - AULA_4GB_HYNIX_H54G46CYRBX267 = 31, - - IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 32, - HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB = 33, - AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 34, - }; - - enum MtcTableIndex { - T210b0SdevEmcDvfsTableS4gb01 = 0, /* Samsung */ - T210b0SdevEmcDvfsTableS4gb03 = 1, /* Samsung AM-MGCJ 4Gb */ // guessed - T210b0SdevEmcDvfsTableS8gb03 = 2, /* Samsung AM-MGCJ 8Gb */ // Guesed - T210b0SdevEmcDvfsTableH4gb03 = 3, /* Hynix */ - T210b0SdevEmcDvfsTableM4gb03 = 4, /* Micron */ - T210b0SdevEmcDvfsTableS4gbY01 = 5, /* Samsung */ - T210b0SdevEmcDvfsTableS1y4gbY01 = 6, /* Samsung */ - T210b0SdevEmcDvfsTableS1y8gbY01 = 7, /* Samsung */ - T210b0SdevEmcDvfsTableS1y4gbX03 = 8, /* Samsung AA-MGCL 4GB */ - T210b0SdevEmcDvfsTableS1y8gbX03 = 9, /* Samsung AA-MGCL 8GB */ - T210b0SdevEmcDvfsTableS1y4gb01 = 10, /* Samsung */ - T210b0SdevEmcDvfsTableM1y4gb01 = 11, /* Micron */ - T210b0SdevEmcDvfsTableH1y4gb01 = 12, /* Hynix */ - T210b0SdevEmcDvfsTableS1y8gb04 = 13, /* Samsung */ - T210b0SdevEmcDvfsTableS1z4gb01 = 14, /* Samsung */ - T210b0SdevEmcDvfsTableH1a4gb01 = 15, /* Hynix */ - T210b0SdevEmcDvfsTableM1a4gb01 = 16, /* Micron */ - MtcTableIndex_Invalid = 17, - }; - - struct MtcDramIndex { - DramId dramId; - MtcTableIndex index; - }; - - constexpr MtcDramIndex mtcIndexTable[] = { - { HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, static_cast(0), }, - { AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, static_cast(0), }, - { IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, static_cast(0), }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, static_cast(0), }, - { IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, static_cast(0), }, - { IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME, static_cast(0), }, - { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE, static_cast(0), }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, static_cast(0), }, - { HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, static_cast(0), }, - { HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME, static_cast(0), }, - { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE, static_cast(0), }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, - { IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, static_cast(0), }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL, static_cast(0), }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, static_cast(0), }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL, static_cast(0), }, - { AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, static_cast(0), }, - { HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL, static_cast(0), }, - { AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, static_cast(0), }, - { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF, static_cast(0), }, - { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF, static_cast(0), }, - { AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF, static_cast(0), }, - { AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, static_cast(0), }, - { IOWA_4GB_HYNIX_H54G46CYRBX267, static_cast(0), }, - { HOAG_4GB_HYNIX_H54G46CYRBX267, static_cast(0), }, - { AULA_4GB_HYNIX_H54G46CYRBX267, static_cast(0), }, - { IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB, static_cast(0), }, - { HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB, static_cast(0), }, - { AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB, static_cast(0), }, - }; - - /* - 710006abfc 40 01 1f d6 br x10 - */ - - /* - 710006ac28 a0 03 00 90 adrp x0,0x71000de000 - 710006ac2c 00 80 16 91 add x0=>SdevEmcDvfsTableS4gb01,x0,#0x5a0 - */ - - /* Br */ - /* - | Z | OP | Fixed | A | M | RN | RM - 31 30 29 28 27 26 25 | 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 |11 | 10 | 9 8 7 6 5 | 4 3 2 1 0 - 1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 Rn 0 0 0 0 0 - Z op A M Rm - */ - - /* Adrp */ - /* - OP | ImmLow | ImmHigh | RD - 31 | 30 29 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0 - */ - - /* ADD (immediate) */ - /* - SF | OP | S | Fixed value | Sh | Imm12 | RN | RD - 31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - - constexpr u32 MtcBrAsm = 0xD61F0140; - constexpr u32 MtcMovAsm = 0x52800068; - constexpr u32 MtcAdrpAsm = 0x900003A0; - constexpr u32 MtcAddAsm = 0x91168000; - - ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) { - /* This builds an address that gets returned, so the register must be x0 by convention. */ - return AsmCompareAddNoImm12(*ptr, MtcAddAsm); - } + constexpr u32 MTC_TABLE_REV = 3; void Patch(uintptr_t mapped_nso, size_t nso_size);