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:
KazushiM
2022-04-02 22:17:04 +08:00
parent ac43237b13
commit 926b9016b1
7 changed files with 112 additions and 111 deletions

View File

@@ -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`)

View File

@@ -1,4 +1,4 @@
export CC := g++-11 export CC := g++
all: test all: test

View File

@@ -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();
} }

View File

@@ -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;

View File

@@ -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"

View File

@@ -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 {