From 7e4b4b5b1d628268f5803b62cabd1f8696888ab7 Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Mon, 27 Jul 2026 15:12:29 -0400 Subject: [PATCH] Revert "mariko 64lut cleanup" This reverts commit 88ca2e86885f993852ae166b114a933eadbd924f. --- .../loader/source/ldr_process_creation.cpp | 6 + .../stratosphere/loader/source/oc/pcv/pcv.hpp | 4 + .../loader/source/oc/pcv/pcv_common.hpp | 6 + .../loader/source/oc/pcv/pcv_hook.hpp | 4 - .../loader/source/oc/pcv/pcv_mariko.cpp | 131 ++++++++---------- .../loader/source/oc/pcv/pcv_mariko.hpp | 15 +- 6 files changed, 83 insertions(+), 83 deletions(-) diff --git a/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp index de998557..0baf0b56 100644 --- a/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp @@ -813,6 +813,12 @@ namespace ams::ldr { } Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const AutoLoadModuleContext &ctx, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { + /* Append extra .bss for 64LUT */ + /* TODO: REMOVE THIS. */ + if (g_is_pcv && ctx.main_nso_idx >= 0) { + g_nso_headers[ctx.main_nso_idx].bss_size += static_cast(hoc::pcv::HocPcvScratchSize); + } + /* Get CreateProcessParameter. */ svc::CreateProcessParameter param; R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit)); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index 2f68e285..74e540eb 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -202,6 +202,10 @@ namespace ams::ldr::hoc::pcv { Result MemFreqPllmLimit(u32 *ptr); Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 + /* Extra pcv .bss */ + constexpr size_t HocPcvScratchSize = 0x2000; + constexpr size_t HocBusFreqBufOffset = 0x1000; /* start of the SOC bus region */ + void SafetyCheck(); void Patch(uintptr_t mapped_nso, size_t nso_size, uintptr_t cave, size_t cave_size, uintptr_t nso_address, uintptr_t data_arena); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp index 76412776..1d3b9232 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp @@ -180,6 +180,12 @@ namespace ams::ldr::hoc::pcv { // The pcv SoC-voltage DVB table is a fixed 32-entry region. (it doesn't need to be larger) constexpr size_t DvbTableCapacity = 32; + // extra .bss location, 0 until Patch() runs. + inline uintptr_t g_pcv_scratch = 0; + + inline uintptr_t g_pcv_cave = 0; + inline size_t g_pcv_cave_size = 0; + template size_t GetDvfsTableEntryCount(T *table_head) { using NT = std::remove_const_t>; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp index 1a59adbe..06acacda 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp @@ -145,10 +145,6 @@ namespace ams::ldr::hoc::pcv { uintptr_t CaveVa() const { return ToVa(reinterpret_cast(m_cave)); } - uintptr_t CaveBase() const { return m_cave; } - - u32 *Reserve(size_t words) { return this->AllocCode(words); } - Result CopyPayload() { R_TRY(this->CheckEnabled()); 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 e9285fd7..111e8a55 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.cpp @@ -617,24 +617,23 @@ namespace ams::ldr::hoc::pcv::mariko { } } - /* hook payload data + buffers */ - struct HookPayloadData { - struct { - u64 orig; - u32 *buf[2]; /* VAs of the bus freq buffers */ - u32 counter; - } busFreqReloc; - }; - DEFINE_HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); - - /* The new replacement buffer */ - struct BusFreqBuf { u32 e[256]; }; - namespace { std::vector newEmcList; u32 *nsoStart; size_t g_nso_size = 0; - u32 *g_busInitSite = nullptr; /* VccSharedBusInit entry, cached by BusFreqReloc */ + uintptr_t g_cave_cursor = 0; + } + + static uintptr_t CaveReserve(size_t count) { + if (g_pcv_cave == 0 || g_cave_cursor == 0) { + return 0; + } + if (g_cave_cursor + count * sizeof(u32) > g_pcv_cave + g_pcv_cave_size) { + return 0; + } + const uintptr_t entry = g_cave_cursor; + g_cave_cursor += count * sizeof(u32); + return entry; } #if HOC_UART_LOG @@ -642,7 +641,7 @@ namespace ams::ldr::hoc::pcv::mariko { Result NvLogUartRedirect(u32 *ptr) { const uintptr_t mapped_nso = reinterpret_cast(nsoStart); const size_t nso_size = g_nso_size; - const uintptr_t textEnd = Hooks().CaveBase(); /* .text ends where the cave begins */ + const uintptr_t textEnd = g_pcv_cave; /* .text ends where the cave begins */ const uintptr_t vsnprintf_addr = reinterpret_cast(ptr); /* NvLog via the VDD_SOC log */ @@ -686,10 +685,10 @@ namespace ams::ldr::hoc::pcv::mariko { R_THROW(ldr::ResultInvalidNvLogRedirect()); } - const uintptr_t helper = reinterpret_cast(Hooks().Reserve(40)); + const uintptr_t helper = CaveReserve(40); if (helper == 0) { - LOGGING("NvLogRedirect: cave unavailable (cave=%lx free=%lx)", - static_cast(Hooks().CaveBase()), static_cast(Hooks().CaveFree())); + LOGGING("NvLogRedirect: cave unavailable (cave=%lx size=%lx)", + static_cast(g_pcv_cave), static_cast(g_pcv_cave_size)); R_THROW(ldr::ResultInvalidNvLogRedirect()); } u32 *t = reinterpret_cast(helper); @@ -727,7 +726,7 @@ namespace ams::ldr::hoc::pcv::mariko { emit(RetIns); /* Redirect the call sites as patching the actual function causes crash */ - const uintptr_t roStart = Hooks().CaveBase() + Hooks().CaveSize(); /* module .rodata start */ + const uintptr_t roStart = g_pcv_cave + g_pcv_cave_size; /* module .rodata start */ size_t patchedSites = 0; if (HOC_PCV_NVLOG_PATCH) { for (u32 *p = nsoStart; reinterpret_cast(p + 1) <= textEnd; ++p) { @@ -760,55 +759,47 @@ namespace ams::ldr::hoc::pcv::mariko { } #endif - /* Relocate C3bus/C2bus freq buffers */ + /* Relocate C2/C3Bus to avoid issues*/ Result BusFreqReloc(u32 *ptr) { - /* Entry shape: sub sp,sp,#imm ; stp x29,x30,[sp,#0x10]. */ - for (u32 i = 1; i <= 48; ++i) { - u32 *p = ptr - i; - if (p - 1 < nsoStart) { - break; - } - if (p[0] == 0xA9017BFDu /* stp x29,x30,[sp,#0x10] */ - && (p[-1] & 0xFFC003FFu) == 0xD10003FFu) { /* sub sp,sp,#imm12 */ - g_busInitSite = p - 1; - R_SUCCEED(); + const u32 busReg = AsmGetRn(ptr[0]); /* ldr Xbuf,[Xbus,#0x10] : bus struct pointer */ + const u32 bufReg = asm_get_rd(ptr[0]); /* : freq-buffer arg */ + const u32 bufOff = AsmGetLdStImm64Off(ptr[0]); /* : bus->freqBuf offset */ + const u32 cntReg = asm_get_rd(ptr[1]); /* add Xcnt,Xbus,#0x18 : arg2 (&count) */ + const u32 railReg = asm_get_rd(ptr[2]); /* str Xrail,[Xbus,#0x50]: arg0 (rail) */ + u32 *call = ptr + 3; /* the bl to relocate */ + const uintptr_t realFn = AsmBranchTarget(*call, reinterpret_cast(call)); + + /* Pick 3 scratch registers */ + u32 s[3], sc = 0; + for (u32 r = 9; r <= 15 && sc < 3; ++r) { + if (r != busReg && r != bufReg && r != cntReg && r != railReg) { + s[sc++] = r; } } - R_THROW(ldr::ResultInvalidBusFreqReloc()); - } + R_UNLESS(sc == 3, ldr::ResultInvalidBusFreqReloc()); - /* Replace VCCBusInit entry with new buffer. */ - HOOK_PAYLOAD_FN u64 VccSharedBusInitHook(u64 *bus) { - HookPayloadData *data = HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); - const u32 idx = data->busFreqReloc.counter; - if (idx < 2) { - data->busFreqReloc.counter = idx + 1; - bus[2] = reinterpret_cast(data->busFreqReloc.buf[idx]); /* bus[0x10] = big buffer */ - } - using OrigFn = u64 (*)(u64 *); - u64 result = reinterpret_cast(data->busFreqReloc.orig)(bus); - __asm__ __volatile__("" : "+r"(result)); - return result; - } + const uintptr_t tramp = CaveReserve(9); + R_UNLESS(tramp != 0, ldr::ResultInvalidBusFreqReloc()); - Result InstallHooks() { - R_TRY(Hooks().CheckEnabled()); /* CopyPayload already done at the top of Patch() */ - - auto *data = Hooks().BindData(m_HookPayloadData); - R_UNLESS(data != nullptr, ldr::ResultHookDataOutOfMemory()); - - R_UNLESS(g_busInitSite != nullptr, ldr::ResultInvalidBusFreqReloc()); - for (u32 i = 0; i < 2; ++i) { - auto *buf = Hooks().DataAlloc(); - R_UNLESS(buf != nullptr, ldr::ResultHookDataOutOfMemory()); - data->busFreqReloc.buf[i] = reinterpret_cast(Hooks().ToVa(buf)); - } - data->busFreqReloc.counter = 0; - - uintptr_t orig = 0; - R_TRY(INSTALL_IMPL_HOOK_ORIG(g_busInitSite, VccSharedBusInitHook, std::addressof(orig))); - data->busFreqReloc.orig = orig; + const uintptr_t region = g_pcv_scratch + HocBusFreqBufOffset; /* [0]=counter, +0x10 + i*0x400 = bufs */ + u32 *t = reinterpret_cast(tramp); + size_t n = 0; + auto emit = [&](u32 ins) { t[n] = ins; ++n; }; + emit(AsmMakeAdrp(tramp + n * 4, region, s[0])); /* adrp s0, */ + emit(AsmMakeAddImm64(s[0], s[0], region & 0xFFFu)); /* add s0,s0,#lo */ + emit(AsmMakeLdrImm32(s[1], s[0], 0x00)); /* s1 = counter */ + emit(AsmMakeAddImm64(s[2], s[1], 1)); /* s2 = counter+1 */ + emit(AsmMakeStrImm32(s[2], s[0], 0x00)); /* counter++ */ + emit(AsmMakeAddImm64(s[0], s[0], 0x10)); /* s0 = region+0x10 (buffers) */ + emit(AsmMakeAddShiftedReg64(bufReg, s[0], s[1], 10)); /* Xbuf = s0 + counter*0x400 */ + emit(AsmMakeStrImm64(bufReg, busReg, bufOff)); /* bus[freqBuf] = Xbuf */ + emit(AsmMakeB(tramp + n * 4, realFn)); /* tail-call the real function */ + PATCH_OFFSET(call, AsmMakeBl(reinterpret_cast(call), tramp)); + const uintptr_t base = reinterpret_cast(nsoStart); + (void) base; + LOGGING("BusFreqReloc: call@+%lx -> tramp@+%lx realfn@+%lx (bus=x%u buf=x%u off=0x%x scratch=x%u,x%u,x%u)", + reinterpret_cast(call) - base, tramp - base, realFn - base, busReg, bufReg, bufOff, s[0], s[1], s[2]); R_SUCCEED(); } @@ -1488,14 +1479,11 @@ namespace ams::ldr::hoc::pcv::mariko { } void Patch(uintptr_t mapped_nso, size_t nso_size) { - nsoStart = reinterpret_cast(mapped_nso); - g_nso_size = nso_size; + nsoStart = reinterpret_cast(mapped_nso); - /* Copy the hook payload into the cave first, patchers can allocate code past it. */ - if (R_FAILED(Hooks().CopyPayload())) { - panic::SmcError(panic::Patch); - CRASH("CopyPayload"); - } + g_pcv_scratch = mapped_nso + nso_size - HocPcvScratchSize; + g_nso_size = nso_size; + g_cave_cursor = g_pcv_cave; /* start the .text-cave bump allocator (0 if unavailable) */ MtcGenerateFreqTables(); @@ -1552,11 +1540,6 @@ namespace ams::ldr::hoc::pcv::mariko { CRASH(entry.description); } } - - if (R_FAILED(InstallHooks())) { - panic::SmcError(panic::Patch); - CRASH("InstallHooks"); - } } } 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 ee7e18b1..de72f004 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_mariko.hpp @@ -23,7 +23,6 @@ #include "../oc_common.hpp" #include "pcv_common.hpp" #include "pcv_asm.hpp" -#include "pcv_hook.hpp" namespace ams::ldr::hoc::pcv::mariko { @@ -373,6 +372,12 @@ namespace ams::ldr::hoc::pcv::mariko { } inline bool BusFreqRelocPatternFn(u32 *ptr) { + if (g_pcv_scratch == 0 || g_pcv_cave == 0) { + return false; + } + if (reinterpret_cast(ptr + 4) > g_pcv_cave) { /* the call site lives in .text */ + return false; + } if (!(AsmIsLdrImm64(ptr[0]) && AsmGetLdStImm64Off(ptr[0]) == 0x10)) return false; /* ldr Xbuf,[Xbus,#0x10] */ if (!(AsmIsAddImm64(ptr[1]) && AsmGetImm12(ptr[1]) == 0x18)) return false; /* add Xcnt,Xbus,#0x18 */ if (!(AsmIsStrImm64(ptr[2]) && AsmGetLdStImm64Off(ptr[2]) == 0x50)) return false; /* str Xrail,[Xbus,#0x50]*/ @@ -382,10 +387,10 @@ namespace ams::ldr::hoc::pcv::mariko { } inline bool ForceVerbosityPatternFn(u32 *ptr) { - if (HOC_PCV_FORCE_VERBOSITY == 0 || Hooks().CaveBase() == 0) { + if (HOC_PCV_FORCE_VERBOSITY == 0 || g_pcv_cave == 0) { return false; } - if (reinterpret_cast(ptr + 11) > Hooks().CaveBase()) { /* .text only */ + if (reinterpret_cast(ptr + 11) > g_pcv_cave) { /* .text only */ return false; } if (ptr[0] != 0xA9BE7BFDu || ptr[1] != 0xF9000BF3u || ptr[2] != 0x910003FDu) return false; /* stp/str/mov x29,sp */ @@ -404,10 +409,10 @@ namespace ams::ldr::hoc::pcv::mariko { inline constexpr u32 NvLogVsnSig[] = { 0xD10483FFu, 0xA9107BFDu, 0xF9008BFCu, 0x910403FDu, 0xF100003Fu }; inline bool NvLogVsnprintfPatternFn(u32 *ptr) { - if (HOC_UART_LOG == 0 || Hooks().CaveBase() == 0) { + if (HOC_UART_LOG == 0 || g_pcv_cave == 0) { return false; } - if (reinterpret_cast(ptr + std::size(NvLogVsnSig)) > Hooks().CaveBase()) { /* must sit in .text */ + if (reinterpret_cast(ptr + std::size(NvLogVsnSig)) > g_pcv_cave) { /* must sit in .text */ return false; } for (size_t k = 0; k < std::size(NvLogVsnSig); ++k) {