Merge branch 'main' of https://github.com/horizon-OC/horizon-OC
This commit is contained in:
@@ -813,12 +813,6 @@ 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<u32>(hoc::pcv::HocPcvScratchSize);
|
||||
}
|
||||
|
||||
/* Get CreateProcessParameter. */
|
||||
svc::CreateProcessParameter param;
|
||||
R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit));
|
||||
|
||||
@@ -202,10 +202,6 @@ 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);
|
||||
|
||||
|
||||
@@ -180,12 +180,6 @@ 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<typename T>
|
||||
size_t GetDvfsTableEntryCount(T *table_head) {
|
||||
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
||||
|
||||
@@ -145,6 +145,10 @@ namespace ams::ldr::hoc::pcv {
|
||||
|
||||
uintptr_t CaveVa() const { return ToVa(reinterpret_cast<const void *>(m_cave)); }
|
||||
|
||||
uintptr_t CaveBase() const { return m_cave; }
|
||||
|
||||
u32 *Reserve(size_t words) { return this->AllocCode(words); }
|
||||
|
||||
Result CopyPayload() {
|
||||
R_TRY(this->CheckEnabled());
|
||||
|
||||
|
||||
@@ -617,23 +617,24 @@ 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<u32> newEmcList;
|
||||
u32 *nsoStart;
|
||||
size_t g_nso_size = 0;
|
||||
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;
|
||||
u32 *g_busInitSite = nullptr; /* VccSharedBusInit entry, cached by BusFreqReloc */
|
||||
}
|
||||
|
||||
#if HOC_UART_LOG
|
||||
@@ -641,7 +642,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
Result NvLogUartRedirect(u32 *ptr) {
|
||||
const uintptr_t mapped_nso = reinterpret_cast<uintptr_t>(nsoStart);
|
||||
const size_t nso_size = g_nso_size;
|
||||
const uintptr_t textEnd = g_pcv_cave; /* .text ends where the cave begins */
|
||||
const uintptr_t textEnd = Hooks().CaveBase(); /* .text ends where the cave begins */
|
||||
const uintptr_t vsnprintf_addr = reinterpret_cast<uintptr_t>(ptr);
|
||||
|
||||
/* NvLog via the VDD_SOC log */
|
||||
@@ -685,10 +686,10 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
R_THROW(ldr::ResultInvalidNvLogRedirect());
|
||||
}
|
||||
|
||||
const uintptr_t helper = CaveReserve(40);
|
||||
const uintptr_t helper = reinterpret_cast<uintptr_t>(Hooks().Reserve(40));
|
||||
if (helper == 0) {
|
||||
LOGGING("NvLogRedirect: cave unavailable (cave=%lx size=%lx)",
|
||||
static_cast<unsigned long>(g_pcv_cave), static_cast<unsigned long>(g_pcv_cave_size));
|
||||
LOGGING("NvLogRedirect: cave unavailable (cave=%lx free=%lx)",
|
||||
static_cast<unsigned long>(Hooks().CaveBase()), static_cast<unsigned long>(Hooks().CaveFree()));
|
||||
R_THROW(ldr::ResultInvalidNvLogRedirect());
|
||||
}
|
||||
u32 *t = reinterpret_cast<u32 *>(helper);
|
||||
@@ -726,7 +727,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
emit(RetIns);
|
||||
|
||||
/* Redirect the call sites as patching the actual function causes crash */
|
||||
const uintptr_t roStart = g_pcv_cave + g_pcv_cave_size; /* module .rodata start */
|
||||
const uintptr_t roStart = Hooks().CaveBase() + Hooks().CaveSize(); /* module .rodata start */
|
||||
size_t patchedSites = 0;
|
||||
if (HOC_PCV_NVLOG_PATCH) {
|
||||
for (u32 *p = nsoStart; reinterpret_cast<uintptr_t>(p + 1) <= textEnd; ++p) {
|
||||
@@ -759,47 +760,55 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Relocate C2/C3Bus to avoid issues*/
|
||||
/* Relocate C3bus/C2bus freq buffers */
|
||||
Result BusFreqReloc(u32 *ptr) {
|
||||
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<uintptr_t>(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;
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
R_UNLESS(sc == 3, ldr::ResultInvalidBusFreqReloc());
|
||||
R_THROW(ldr::ResultInvalidBusFreqReloc());
|
||||
}
|
||||
|
||||
const uintptr_t tramp = CaveReserve(9);
|
||||
R_UNLESS(tramp != 0, 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<u64>(data->busFreqReloc.buf[idx]); /* bus[0x10] = big buffer */
|
||||
}
|
||||
using OrigFn = u64 (*)(u64 *);
|
||||
u64 result = reinterpret_cast<OrigFn>(data->busFreqReloc.orig)(bus);
|
||||
__asm__ __volatile__("" : "+r"(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
const uintptr_t region = g_pcv_scratch + HocBusFreqBufOffset; /* [0]=counter, +0x10 + i*0x400 = bufs */
|
||||
u32 *t = reinterpret_cast<u32 *>(tramp);
|
||||
size_t n = 0;
|
||||
auto emit = [&](u32 ins) { t[n] = ins; ++n; };
|
||||
emit(AsmMakeAdrp(tramp + n * 4, region, s[0])); /* adrp s0,<region> */
|
||||
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 */
|
||||
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<BusFreqBuf>();
|
||||
R_UNLESS(buf != nullptr, ldr::ResultHookDataOutOfMemory());
|
||||
data->busFreqReloc.buf[i] = reinterpret_cast<u32 *>(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;
|
||||
|
||||
PATCH_OFFSET(call, AsmMakeBl(reinterpret_cast<uintptr_t>(call), tramp));
|
||||
const uintptr_t base = reinterpret_cast<uintptr_t>(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<uintptr_t>(call) - base, tramp - base, realFn - base, busReg, bufReg, bufOff, s[0], s[1], s[2]);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
@@ -1479,11 +1488,14 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
}
|
||||
|
||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||
nsoStart = reinterpret_cast<u32 *>(mapped_nso);
|
||||
nsoStart = reinterpret_cast<u32 *>(mapped_nso);
|
||||
g_nso_size = nso_size;
|
||||
|
||||
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) */
|
||||
/* 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");
|
||||
}
|
||||
|
||||
MtcGenerateFreqTables();
|
||||
|
||||
@@ -1540,6 +1552,11 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
CRASH(entry.description);
|
||||
}
|
||||
}
|
||||
|
||||
if (R_FAILED(InstallHooks())) {
|
||||
panic::SmcError(panic::Patch);
|
||||
CRASH("InstallHooks");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../oc_common.hpp"
|
||||
#include "pcv_common.hpp"
|
||||
#include "pcv_asm.hpp"
|
||||
#include "pcv_hook.hpp"
|
||||
|
||||
namespace ams::ldr::hoc::pcv::mariko {
|
||||
|
||||
@@ -372,12 +373,6 @@ 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<uintptr_t>(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]*/
|
||||
@@ -387,10 +382,10 @@ namespace ams::ldr::hoc::pcv::mariko {
|
||||
}
|
||||
|
||||
inline bool ForceVerbosityPatternFn(u32 *ptr) {
|
||||
if (HOC_PCV_FORCE_VERBOSITY == 0 || g_pcv_cave == 0) {
|
||||
if (HOC_PCV_FORCE_VERBOSITY == 0 || Hooks().CaveBase() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (reinterpret_cast<uintptr_t>(ptr + 11) > g_pcv_cave) { /* .text only */
|
||||
if (reinterpret_cast<uintptr_t>(ptr + 11) > Hooks().CaveBase()) { /* .text only */
|
||||
return false;
|
||||
}
|
||||
if (ptr[0] != 0xA9BE7BFDu || ptr[1] != 0xF9000BF3u || ptr[2] != 0x910003FDu) return false; /* stp/str/mov x29,sp */
|
||||
@@ -409,10 +404,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 || g_pcv_cave == 0) {
|
||||
if (HOC_UART_LOG == 0 || Hooks().CaveBase() == 0) {
|
||||
return false;
|
||||
}
|
||||
if (reinterpret_cast<uintptr_t>(ptr + std::size(NvLogVsnSig)) > g_pcv_cave) { /* must sit in .text */
|
||||
if (reinterpret_cast<uintptr_t>(ptr + std::size(NvLogVsnSig)) > Hooks().CaveBase()) { /* must sit in .text */
|
||||
return false;
|
||||
}
|
||||
for (size_t k = 0; k < std::size(NvLogVsnSig); ++k) {
|
||||
|
||||
@@ -229,7 +229,7 @@ std::vector<std::string> ConfigInfoStrings(HocClkConfigValue val, bool isMariko,
|
||||
return {
|
||||
"The step that RAM clocks take.",
|
||||
"Options:",
|
||||
" - 33MHz - 3 MHz step (ex. 1600, 1633, 1666, 1700, etc.)",
|
||||
" - 33MHz - 33 MHz step (ex. 1600, 1633, 1666, 1700, etc.)",
|
||||
" - 66MHz - 66 MHz step (ex. 1600, 1666, 1733, etc.)",
|
||||
" - 100MHz - 100 MHz step (ex. 1600, 1700, 1800, etc.)",
|
||||
" - 133MHz - 133 MHz step (ex. 1600, 1733, 1866, etc.)",
|
||||
|
||||
Reference in New Issue
Block a user