ldr_oc_suite: adopt ams style return code; test is now clang compatible; loader.kip will not crash if pcv/ptm sysmodules is manually patched.
This commit is contained in:
@@ -146,9 +146,9 @@ This project will not be actively maintained or regularly updated along with Atm
|
|||||||
|
|
||||||
### Patching sysmodules manually
|
### Patching sysmodules manually
|
||||||
|
|
||||||
This method is only served as reference.
|
This method is only served as reference as it could damage your MMC file system if not handled properly.
|
||||||
|
|
||||||
Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (usually in `x.0.0`).
|
Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (normally in `x.0.0`).
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ Patched sysmodules would be persistent until pcv or ptm was updated in new HOS (
|
|||||||
|
|
||||||
1. Dump `prod.keys` with Lockpick_RCM
|
1. Dump `prod.keys` with Lockpick_RCM
|
||||||
2. Dump HOS firmware with TegraExplorer
|
2. Dump HOS firmware with TegraExplorer
|
||||||
3. Configure and run `test.sh` in `/Source/Atmosphere/stratosphere/loader/source/oc/` to generate patched pcv & ptm
|
3. Configure and run `test_patch.sh` to generate patched pcv & ptm sysmodules in nca
|
||||||
4. Replace nca in `SYSTEM:/Contents/registered/` with TegraExplorer
|
4. Replace nca in `SYSTEM:/Contents/registered/` with TegraExplorer
|
||||||
5. `ValidateAcidSignature()` should be stubbed to allow unsigned sysmodules to load (a.k.a. `loader_patch`)
|
5. `ValidateAcidSignature()` should be stubbed to allow unsigned sysmodules to load (a.k.a. `loader_patch`)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export CC := g++-11
|
export CC := g++
|
||||||
|
|
||||||
all: test
|
all: test
|
||||||
|
|
||||||
|
|||||||
@@ -28,33 +28,33 @@ namespace ams::ldr::oc {
|
|||||||
namespace pcv {
|
namespace pcv {
|
||||||
Result MemPllmLimitHandler(u32* ptr) {
|
Result MemPllmLimitHandler(u32* ptr) {
|
||||||
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||||
if (entry->max_0 != entry->max_1)
|
R_UNLESS(entry->max_0 == entry->max_1, ldr::ResultInvalidMemPllmEntry());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
// Double the max clk simply
|
// Double the max clk simply
|
||||||
u32 max_clk = entry->max_0 * 2;
|
u32 max_clk = entry->max_0 * 2;
|
||||||
entry->max_0 = max_clk;
|
entry->max_0 = max_clk;
|
||||||
entry->max_1 = max_clk;
|
entry->max_1 = max_clk;
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename M>
|
template<typename M>
|
||||||
Result MtcOverwrite(M* des, M* src) {
|
Result MtcOverwrite(M* des, M* src) {
|
||||||
constexpr u32 mtc_magic = 0x5F43544D;
|
constexpr u32 mtc_magic = 0x5F43544D;
|
||||||
if (src->rev != mtc_magic)
|
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
// Ignore params from dvfs_ver to clock_src;
|
// Ignore params from dvfs_ver to clock_src;
|
||||||
for (size_t offset = offsetof(M, clk_src_emc); offset < sizeof(M); offset += sizeof(u32)) {
|
for (size_t offset = offsetof(M, clk_src_emc); offset < sizeof(M); offset += sizeof(u32)) {
|
||||||
u32* src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
|
u32* src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
|
||||||
u32* des_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(des) + offset);
|
u32* des_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(des) + offset);
|
||||||
u32 src_val = *src_ent;
|
u32 src_val = *src_ent;
|
||||||
if (src_val != UINT32_MAX) {
|
|
||||||
|
constexpr u32 ignore_val = UINT32_MAX;
|
||||||
|
if (src_val != ignore_val) {
|
||||||
PatchOffset(des_ent, src_val);
|
PatchOffset(des_ent, src_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ namespace ams::ldr::oc {
|
|||||||
constexpr u32 CpuClkOSLimit = 1785'000;
|
constexpr u32 CpuClkOSLimit = 1785'000;
|
||||||
constexpr u32 CpuClkOfficial = 1963'500;
|
constexpr u32 CpuClkOfficial = 1963'500;
|
||||||
constexpr u32 CpuVoltOfficial = 1120;
|
constexpr u32 CpuVoltOfficial = 1120;
|
||||||
constexpr u32 GpuClkOSLimit = 921'600;
|
// constexpr u32 GpuClkOSLimit = 921'600;
|
||||||
constexpr u32 GpuClkOfficial = 1267'200;
|
constexpr u32 GpuClkOfficial = 1267'200;
|
||||||
constexpr u32 MemClkOSLimit = 1600'000;
|
constexpr u32 MemClkOSLimit = 1600'000;
|
||||||
constexpr u32 MemClkOSAlt = 1331'200;
|
constexpr u32 MemClkOSAlt = 1331'200;
|
||||||
@@ -677,16 +677,13 @@ namespace ams::ldr::oc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result CpuClockVddHandler(u32* ptr) {
|
Result CpuClockVddHandler(u32* ptr) {
|
||||||
u32 value_1 = *(ptr + 2);
|
R_UNLESS(*(ptr + 2) == 0, ldr::ResultInvalidCpuClockVddEntry());
|
||||||
u32 value_2 = *(ptr + 12);
|
R_UNLESS(*(ptr + 12) == 1525000, ldr::ResultInvalidCpuClockVddEntry());
|
||||||
constexpr u32 pattern_1 = 0;
|
|
||||||
constexpr u32 pattern_2 = 1525000;
|
|
||||||
if (value_1 != pattern_1 || value_2 != pattern_2)
|
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
if (C.marikoCpuMaxClock)
|
if (C.marikoCpuMaxClock)
|
||||||
PatchOffset(ptr, C.marikoCpuMaxClock);
|
PatchOffset(ptr, C.marikoCpuMaxClock);
|
||||||
return ResultSuccess();
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
Result CpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
||||||
@@ -696,21 +693,17 @@ namespace ams::ldr::oc {
|
|||||||
cpu_freq_cvb_table_t* entry_1020 = entry_204 + 8;
|
cpu_freq_cvb_table_t* entry_1020 = entry_204 + 8;
|
||||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
||||||
|
|
||||||
if ( entry_end_offset >= nso_end_offset
|
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_204)) != 204'000
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_204)) == 204'000, ldr::ResultInvalidCpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||||
{
|
|
||||||
return ResultFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.marikoCpuMaxClock > CpuClkOfficial)
|
if (C.marikoCpuMaxClock > CpuClkOfficial)
|
||||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
||||||
|
|
||||||
// Patch CPU max volt in CPU dvfs table
|
// Patch CPU max volt in CPU dvfs table
|
||||||
cpu_freq_cvb_table_t* entry_current = entry_1020;
|
cpu_freq_cvb_table_t* entry_current = entry_1020;
|
||||||
if (entry_current->cvb_pll_param.c0 != CpuVoltOfficial * 1000)
|
R_UNLESS(entry_current->cvb_pll_param.c0 == CpuVoltOfficial * 1000, ldr::ResultInvalidCpuDvfs());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
if (C.marikoCpuMaxVolt) {
|
if (C.marikoCpuMaxVolt) {
|
||||||
while (entry_current->cvb_pll_param.c0 == CpuVoltOfficial * 1000) {
|
while (entry_current->cvb_pll_param.c0 == CpuVoltOfficial * 1000) {
|
||||||
@@ -719,7 +712,7 @@ namespace ams::ldr::oc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
Result GpuDvfsHandler(u32* ptr, uintptr_t nso_end_offset) {
|
||||||
@@ -728,17 +721,15 @@ namespace ams::ldr::oc {
|
|||||||
gpu_cvb_pll_table_t* entry_76_8 = entry_free - 17;
|
gpu_cvb_pll_table_t* entry_76_8 = entry_free - 17;
|
||||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewGpuTables) - sizeof(u32);
|
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewGpuTables) - sizeof(u32);
|
||||||
|
|
||||||
if ( entry_end_offset >= nso_end_offset
|
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidGpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_76_8)) != 76'800
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_76_8)) == 76'800, ldr::ResultInvalidGpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidGpuDvfs());
|
||||||
{
|
|
||||||
return ResultFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.marikoGpuMaxClock > GpuClkOfficial)
|
if (C.marikoGpuMaxClock > GpuClkOfficial)
|
||||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewGpuTables, sizeof(NewGpuTables));
|
std::memcpy(reinterpret_cast<void *>(entry_free), NewGpuTables, sizeof(NewGpuTables));
|
||||||
return ResultSuccess();
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CpuVoltRangeHandler(u32* ptr) {
|
Result CpuVoltRangeHandler(u32* ptr) {
|
||||||
@@ -750,9 +741,9 @@ namespace ams::ldr::oc {
|
|||||||
case 610:
|
case 610:
|
||||||
if (C.marikoCpuMaxVolt)
|
if (C.marikoCpuMaxVolt)
|
||||||
PatchOffset(ptr, C.marikoCpuMaxVolt);
|
PatchOffset(ptr, C.marikoCpuMaxVolt);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
default:
|
default:
|
||||||
return ResultFailure();
|
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,20 +762,19 @@ namespace ams::ldr::oc {
|
|||||||
PatchOffset(ptr_next, gpuMaxClockMarikoPattern[1] | reg_id);
|
PatchOffset(ptr_next, gpuMaxClockMarikoPattern[1] | reg_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ResultFailure();
|
R_THROW(ldr::ResultInvalidGpuMaxClkPattern());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MtcTableHandler(u32* ptr) {
|
Result MtcTableHandler(u32* ptr) {
|
||||||
MarikoMtcTable* const mtc_table_max = reinterpret_cast<MarikoMtcTable *>(ptr - offsetof(MarikoMtcTable, rate_khz) / sizeof(u32));
|
MarikoMtcTable* const mtc_table_max = reinterpret_cast<MarikoMtcTable *>(ptr - offsetof(MarikoMtcTable, rate_khz) / sizeof(u32));
|
||||||
MarikoMtcTable* const mtc_table_alt = mtc_table_max - 1;
|
MarikoMtcTable* const mtc_table_alt = mtc_table_max - 1;
|
||||||
constexpr u32 mtc_mariko_rev = 3;
|
constexpr u32 mtc_mariko_rev = 3;
|
||||||
if ( mtc_table_max->rev != mtc_mariko_rev
|
R_UNLESS(mtc_table_max->rev == mtc_mariko_rev, ldr::ResultInvalidMtcTable());
|
||||||
|| mtc_table_alt->rev != mtc_mariko_rev
|
R_UNLESS(mtc_table_alt->rev == mtc_mariko_rev, ldr::ResultInvalidMtcTable());
|
||||||
|| mtc_table_alt->rate_khz != MemClkOSAlt )
|
R_UNLESS(mtc_table_alt->rate_khz == MemClkOSAlt, ldr::ResultInvalidMtcTable());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
MarikoMtcTable* const table = const_cast<MarikoMtcTable *>(C.marikoMtc);
|
MarikoMtcTable* const table = const_cast<MarikoMtcTable *>(C.marikoMtc);
|
||||||
bool replace_entire_table = (C.mtcConf == ENTIRE_TABLE_MARIKO);
|
bool replace_entire_table = (C.mtcConf == ENTIRE_TABLE_MARIKO);
|
||||||
@@ -797,7 +787,7 @@ namespace ams::ldr::oc {
|
|||||||
MtcTableAutoAdjust(mtc_table_max, mtc_table_alt);
|
MtcTableAutoAdjust(mtc_table_max, mtc_table_alt);
|
||||||
MtcPllmbDivHandler(mtc_table_max);
|
MtcPllmbDivHandler(mtc_table_max);
|
||||||
std::memcpy(reinterpret_cast<void *>(mtc_table_alt), reinterpret_cast<void *>(table), sizeof(MarikoMtcTable));
|
std::memcpy(reinterpret_cast<void *>(mtc_table_alt), reinterpret_cast<void *>(table), sizeof(MarikoMtcTable));
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DvbTableHandler(u32* ptr) {
|
Result DvbTableHandler(u32* ptr) {
|
||||||
@@ -805,11 +795,10 @@ namespace ams::ldr::oc {
|
|||||||
emc_dvb_dvfs_table_t* dvb_1331_entry = dvb_max_entry - 1;
|
emc_dvb_dvfs_table_t* dvb_1331_entry = dvb_max_entry - 1;
|
||||||
|
|
||||||
u32* dvb_1331_offset = reinterpret_cast<u32 *>(dvb_1331_entry);
|
u32* dvb_1331_offset = reinterpret_cast<u32 *>(dvb_1331_entry);
|
||||||
if (*(dvb_1331_offset) != MemClkOSAlt)
|
R_UNLESS(*(dvb_1331_offset) == MemClkOSAlt, ldr::ResultInvalidDvbTable());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
PatchOffset(dvb_1331_offset, MemClkOSLimit);
|
PatchOffset(dvb_1331_offset, MemClkOSLimit);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MemMaxClockHandler(u32* ptr) {
|
Result MemMaxClockHandler(u32* ptr) {
|
||||||
@@ -821,26 +810,24 @@ namespace ams::ldr::oc {
|
|||||||
constexpr u32 mtc_min_volt = 1100;
|
constexpr u32 mtc_min_volt = 1100;
|
||||||
constexpr u32 dvb_entry_volt = 675;
|
constexpr u32 dvb_entry_volt = 675;
|
||||||
|
|
||||||
Result rc = ResultSuccess();
|
|
||||||
|
|
||||||
if (value_next == mtc_min_volt) {
|
if (value_next == mtc_min_volt) {
|
||||||
rc = MtcTableHandler(ptr);
|
R_TRY(MtcTableHandler(ptr));
|
||||||
} else if (value_next2 == dvb_entry_volt) {
|
} else if (value_next2 == dvb_entry_volt) {
|
||||||
rc = DvbTableHandler(ptr);
|
R_TRY(DvbTableHandler(ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
PatchOffset(ptr, C.marikoEmcMaxClock);
|
PatchOffset(ptr, C.marikoEmcMaxClock);
|
||||||
return rc;
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GpuPllLimitHandler(u32* ptr) {
|
Result GpuPllLimitHandler(u32* ptr) {
|
||||||
u32 value_next = *(ptr + 1);
|
u32 value_next = *(ptr + 1);
|
||||||
if (value_next != 0)
|
R_UNLESS(value_next == 0, ldr::ResultInvalidGpuPllEntry());
|
||||||
return ResultFailure();
|
|
||||||
|
|
||||||
|
// Double the max clk simply
|
||||||
u32 max_clk = *(ptr) * 2;
|
u32 max_clk = *(ptr) * 2;
|
||||||
PatchOffset(ptr, max_clk);
|
PatchOffset(ptr, max_clk);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||||
@@ -922,14 +909,13 @@ namespace ams::ldr::oc {
|
|||||||
cnt[MEM_PLL_CLK],
|
cnt[MEM_PLL_CLK],
|
||||||
cnt[GPU_MAX_CLOCK]);
|
cnt[GPU_MAX_CLOCK]);
|
||||||
|
|
||||||
if ( cnt[CPU_CLOCK_VDD] != 1
|
if (cnt[CPU_CLOCK_VDD] > 1 ||
|
||||||
|| cnt[CPU_TABLE] != 1
|
cnt[CPU_TABLE] > 1 ||
|
||||||
|| cnt[GPU_TABLE] != 1
|
cnt[GPU_TABLE] > 1 ||
|
||||||
|| cnt[CPU_MAX_VOLT] > 13 || !cnt[CPU_MAX_VOLT]
|
cnt[CPU_MAX_VOLT] > 13 ||
|
||||||
|| cnt[MEM_CLOCK] == 0
|
cnt[GPU_PLL_CLK] > 1 ||
|
||||||
|| cnt[GPU_PLL_CLK] != 1
|
cnt[MEM_PLL_CLK] > 2 ||
|
||||||
|| cnt[MEM_PLL_CLK] != 2
|
cnt[GPU_MAX_CLOCK] > 2)
|
||||||
|| cnt[GPU_MAX_CLOCK] != 2)
|
|
||||||
{
|
{
|
||||||
CRASH();
|
CRASH();
|
||||||
}
|
}
|
||||||
@@ -974,18 +960,15 @@ namespace ams::ldr::oc {
|
|||||||
cpu_freq_cvb_table_t* entry_204 = entry_free - 16;
|
cpu_freq_cvb_table_t* entry_204 = entry_free - 16;
|
||||||
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
uintptr_t entry_end_offset = reinterpret_cast<uintptr_t>(entry_free) + sizeof(NewCpuTables) - sizeof(u32);
|
||||||
|
|
||||||
if ( entry_end_offset >= nso_end_offset
|
R_UNLESS(entry_end_offset < nso_end_offset, ldr::ResultOutOfRange());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_free)) != 0
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_free)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_204)) != 204'000
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_204)) == 204'000, ldr::ResultInvalidCpuDvfs());
|
||||||
|| *(reinterpret_cast<u32 *>(entry_end_offset)) != 0 )
|
R_UNLESS(*(reinterpret_cast<u32 *>(entry_end_offset)) == 0, ldr::ResultInvalidCpuDvfs());
|
||||||
{
|
|
||||||
return ResultFailure();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.eristaCpuOCEnable)
|
if (C.eristaCpuOCEnable)
|
||||||
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
std::memcpy(reinterpret_cast<void *>(entry_free), NewCpuTables, sizeof(NewCpuTables));
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CpuVoltRangeHandler(u32* ptr) {
|
Result CpuVoltRangeHandler(u32* ptr) {
|
||||||
@@ -997,10 +980,10 @@ namespace ams::ldr::oc {
|
|||||||
case 810:
|
case 810:
|
||||||
if (C.eristaCpuMaxVolt)
|
if (C.eristaCpuMaxVolt)
|
||||||
PatchOffset(ptr, C.eristaCpuMaxVolt);
|
PatchOffset(ptr, C.eristaCpuMaxVolt);
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
default:
|
default:
|
||||||
LOGGING("Invalid min voltage: %u @%p!", *(ptr-1), ptr-1);
|
LOGGING("Invalid min voltage: %u @%p!", *(ptr-1), ptr-1);
|
||||||
return ResultFailure();
|
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1012,21 +995,20 @@ namespace ams::ldr::oc {
|
|||||||
return MtcOverwrite(mtc_table_max, table);
|
return MtcOverwrite(mtc_table_max, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MemMaxClockHandler(u32* ptr) {
|
Result MemMaxClockHandler(u32* ptr) {
|
||||||
u32 value_next = *(ptr + 1);
|
u32 value_next = *(ptr + 1);
|
||||||
constexpr u32 mtc_min_volt = 887;
|
constexpr u32 mtc_min_volt = 887;
|
||||||
|
|
||||||
Result rc = ResultSuccess();
|
if (value_next == mtc_min_volt)
|
||||||
if (value_next == mtc_min_volt) {
|
R_TRY(MtcTableHandler(ptr));
|
||||||
rc = MtcTableHandler(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.eristaEmcMaxClock > MemClkOSLimit)
|
if (C.eristaEmcMaxClock > MemClkOSLimit)
|
||||||
PatchOffset(ptr, C.eristaEmcMaxClock);
|
PatchOffset(ptr, C.eristaEmcMaxClock);
|
||||||
return rc;
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MemVoltHandler(u32* ptr) {
|
Result MemVoltHandler(u32* ptr) {
|
||||||
@@ -1035,10 +1017,11 @@ namespace ams::ldr::oc {
|
|||||||
constexpr u32 uv_step = 12'500;
|
constexpr u32 uv_step = 12'500;
|
||||||
if (emc_uv % uv_step)
|
if (emc_uv % uv_step)
|
||||||
emc_uv = emc_uv / uv_step * uv_step;
|
emc_uv = emc_uv / uv_step * uv_step;
|
||||||
|
|
||||||
PatchOffset(ptr, emc_uv);
|
PatchOffset(ptr, emc_uv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||||
@@ -1099,11 +1082,9 @@ namespace ams::ldr::oc {
|
|||||||
cnt[MEM_VOLT],
|
cnt[MEM_VOLT],
|
||||||
cnt[MEM_PLL_CLK]);
|
cnt[MEM_PLL_CLK]);
|
||||||
|
|
||||||
if ( cnt[CPU_CLOCK] != 1
|
if (cnt[CPU_CLOCK] > 1 ||
|
||||||
|| cnt[CPU_MAX_VOLT] < 2
|
cnt[MEM_VOLT] > 2 ||
|
||||||
|| cnt[MEM_CLOCK] == 0
|
cnt[MEM_PLL_CLK] > 2)
|
||||||
|| cnt[MEM_VOLT] != 2
|
|
||||||
|| cnt[MEM_PLL_CLK] != 2)
|
|
||||||
{
|
{
|
||||||
CRASH();
|
CRASH();
|
||||||
}
|
}
|
||||||
@@ -1112,10 +1093,11 @@ namespace ams::ldr::oc {
|
|||||||
|
|
||||||
namespace pcv {
|
namespace pcv {
|
||||||
void SafetyCheck() {
|
void SafetyCheck() {
|
||||||
if ( C.custRev != CUST_REV
|
if (C.custRev != CUST_REV ||
|
||||||
|| C.marikoCpuMaxVolt >= 1300
|
C.marikoCpuMaxVolt >= 1300 ||
|
||||||
|| C.eristaCpuMaxVolt >= 1400
|
C.eristaCpuMaxVolt >= 1400 ||
|
||||||
|| (C.eristaEmcVolt && (C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)))
|
(C.eristaEmcVolt &&
|
||||||
|
(C.eristaEmcVolt < 600'000 || C.eristaEmcVolt > 1250'000)))
|
||||||
{
|
{
|
||||||
CRASH();
|
CRASH();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,30 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "mtc_timing_table.hpp"
|
||||||
|
|
||||||
#define CUST_REV 2
|
#define CUST_REV 2
|
||||||
#include "mtc_timing_table.hpp"
|
|
||||||
|
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||||
|
#include <vapours/results/results_common.hpp>
|
||||||
|
#define LOGGING(fmt, ...) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CRASH() { AMS_ABORT(); __builtin_unreachable(); }
|
||||||
|
|
||||||
|
namespace ams::ldr {
|
||||||
|
R_DEFINE_ERROR_RESULT(OutOfRange, 1000);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidMemPllmEntry, 1001);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidMtcMagic, 1002);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidMtcTable, 1003);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidDvbTable, 1004);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidCpuClockVddEntry, 1005);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidCpuDvfs, 1006);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidCpuMinVolt, 1007);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1008);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidGpuMaxClkPattern, 1009);
|
||||||
|
R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1010);
|
||||||
|
}
|
||||||
|
|
||||||
namespace ams::ldr::oc {
|
namespace ams::ldr::oc {
|
||||||
enum MtcConfig {
|
enum MtcConfig {
|
||||||
@@ -26,7 +47,7 @@ namespace ams::ldr::oc {
|
|||||||
ENTIRE_TABLE_MARIKO = 3,
|
ENTIRE_TABLE_MARIKO = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct CustomizeTable {
|
||||||
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
u8 cust[4] = {'C', 'U', 'S', 'T'};
|
||||||
u16 custRev = CUST_REV;
|
u16 custRev = CUST_REV;
|
||||||
u16 mtcConf = AUTO_ADJ_MARIKO_SAFE;
|
u16 mtcConf = AUTO_ADJ_MARIKO_SAFE;
|
||||||
@@ -47,16 +68,8 @@ namespace ams::ldr::oc {
|
|||||||
|
|
||||||
inline void PatchOffset(u32* offset, u32 value) { *(offset) = value; }
|
inline void PatchOffset(u32* offset, u32 value) { *(offset) = value; }
|
||||||
|
|
||||||
inline Result ResultFailure() { return -1; }
|
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
|
||||||
#define LOGGING(fmt, ...) ((void)0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CRASH() { AMS_ABORT(); __builtin_unreachable(); }
|
|
||||||
|
|
||||||
namespace pcv {
|
namespace pcv {
|
||||||
typedef struct {
|
typedef struct cvb_coefficients {
|
||||||
s32 c0 = 0;
|
s32 c0 = 0;
|
||||||
s32 c1 = 0;
|
s32 c1 = 0;
|
||||||
s32 c2 = 0;
|
s32 c2 = 0;
|
||||||
@@ -65,24 +78,24 @@ namespace ams::ldr::oc {
|
|||||||
s32 c5 = 0;
|
s32 c5 = 0;
|
||||||
} cvb_coefficients;
|
} cvb_coefficients;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct cpu_freq_cvb_table_t {
|
||||||
u64 freq;
|
u64 freq;
|
||||||
cvb_coefficients cvb_dfll_param;
|
cvb_coefficients cvb_dfll_param;
|
||||||
cvb_coefficients cvb_pll_param; // only c0 is reserved
|
cvb_coefficients cvb_pll_param; // only c0 is reserved
|
||||||
} cpu_freq_cvb_table_t;
|
} cpu_freq_cvb_table_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct gpu_cvb_pll_table_t {
|
||||||
u64 freq;
|
u64 freq;
|
||||||
cvb_coefficients cvb_dfll_param; // empty, dfll clock source not selected
|
cvb_coefficients cvb_dfll_param; // empty, dfll clock source not selected
|
||||||
cvb_coefficients cvb_pll_param;
|
cvb_coefficients cvb_pll_param;
|
||||||
} gpu_cvb_pll_table_t;
|
} gpu_cvb_pll_table_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct emc_dvb_dvfs_table_t {
|
||||||
u64 freq;
|
u64 freq;
|
||||||
s32 volt[4] = {0};
|
s32 volt[4] = {0};
|
||||||
} emc_dvb_dvfs_table_t;
|
} emc_dvb_dvfs_table_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct clk_pll_param {
|
||||||
u32 max_0;
|
u32 max_0;
|
||||||
u32 unk[5];
|
u32 unk[5];
|
||||||
u32 max_1;
|
u32 max_1;
|
||||||
|
|||||||
@@ -11,12 +11,17 @@ typedef int32_t s32;
|
|||||||
typedef uint64_t u64;
|
typedef uint64_t u64;
|
||||||
typedef int Result;
|
typedef int Result;
|
||||||
|
|
||||||
#define R_SUCCEEDED(arg) (arg == ResultSuccess())
|
#define R_SUCCEEDED(arg) (arg == 0)
|
||||||
#define R_FAILED(arg) (!R_SUCCEEDED(arg))
|
#define R_FAILED(arg) (arg != 0)
|
||||||
#define LOGGING(fmt, ...) { printf(fmt "\n\tin %s\n", ##__VA_ARGS__, __PRETTY_FUNCTION__); }
|
#define LOGGING(fmt, ...) { printf(fmt "\n\tin %s\n", ##__VA_ARGS__, __PRETTY_FUNCTION__); }
|
||||||
#define AMS_ABORT() { fprintf(stderr, "Failed in %s!\n", __PRETTY_FUNCTION__); exit(-1); }
|
#define AMS_ABORT() { fprintf(stderr, "Failed in %s!\n", __PRETTY_FUNCTION__); exit(-1); }
|
||||||
|
#define R_SUCCEED() { return 0; }
|
||||||
|
#define R_THROW(err) { return err; }
|
||||||
|
#define R_TRY(expr) { Result _rc = (expr); if (R_FAILED(_rc)) { return _rc; } }
|
||||||
|
#define R_UNLESS(expr, rc) { if (!(expr)) { return rc; } }
|
||||||
|
|
||||||
inline Result ResultSuccess() { return 0; }
|
#define R_DEFINE_ERROR_RESULT(name, rc) \
|
||||||
|
inline Result Result##name() { return rc; }
|
||||||
|
|
||||||
#include "ldr_oc_suite.hpp"
|
#include "ldr_oc_suite.hpp"
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace ams::ldr::oc {
|
namespace ams::ldr::oc {
|
||||||
namespace pcv {
|
namespace pcv {
|
||||||
|
|||||||
Reference in New Issue
Block a user