diff --git a/Source/sys-clk-OC/common/include/sysclk/client/ipc.h b/Source/sys-clk-OC/common/include/sysclk/client/ipc.h index b1d071bb..51282653 100644 --- a/Source/sys-clk-OC/common/include/sysclk/client/ipc.h +++ b/Source/sys-clk-OC/common/include/sysclk/client/ipc.h @@ -31,7 +31,7 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles); Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues); Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues); Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode); -Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table); +Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, SysClkFrequencyTable* out_table); Result sysclkIpcGetIsMariko(bool* out_is_mariko); static inline Result sysclkIpcRemoveOverride(SysClkModule module) diff --git a/Source/sys-clk-OC/common/include/sysclk/clocks.h b/Source/sys-clk-OC/common/include/sysclk/clocks.h index f5ab4bd2..c658bf18 100644 --- a/Source/sys-clk-OC/common/include/sysclk/clocks.h +++ b/Source/sys-clk-OC/common/include/sysclk/clocks.h @@ -65,10 +65,13 @@ typedef struct bool allowUnsafeFreq; bool governor; SysClkProfile realProfile; - uint32_t maxMEMFreq; - uint32_t boostCPUFreq; } SysClkOcExtra; +typedef struct +{ + uint32_t values[20]; +} SysClkFrequencyTable; + uint32_t* GetTable(SysClkModule module); typedef struct diff --git a/Source/sys-clk-OC/common/include/sysclk/ipc.h b/Source/sys-clk-OC/common/include/sysclk/ipc.h index d4a874f0..1020e7da 100644 --- a/Source/sys-clk-OC/common/include/sysclk/ipc.h +++ b/Source/sys-clk-OC/common/include/sysclk/ipc.h @@ -50,5 +50,4 @@ typedef struct { SysClkModule module; SysClkProfile profile; - size_t max_entry_num; } SysClkIpc_GetFrequencyTable_Args; diff --git a/Source/sys-clk-OC/common/src/client/ipc.c b/Source/sys-clk-OC/common/src/client/ipc.c index 3b9e1697..ce23ca2e 100644 --- a/Source/sys-clk-OC/common/src/client/ipc.c +++ b/Source/sys-clk-OC/common/src/client/ipc.c @@ -13,7 +13,6 @@ #include #include #include -#include static Service g_sysclkSrv; static atomic_size_t g_refCnt; @@ -121,30 +120,13 @@ Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode) return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode); } -Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table) +Result sysclkIpcGetFrequencyTable(SysClkModule module, SysClkProfile profile, SysClkFrequencyTable* out_table) { SysClkIpc_GetFrequencyTable_Args args = { .module = module, .profile = profile, - .max_entry_num = max_entry_num }; - size_t table_size = sizeof(uint32_t) * max_entry_num; - uint32_t* table = malloc(table_size); - memset(table, 0, table_size); - - SfDispatchParams disp; - - Result rc = serviceDispatchImpl( - &g_sysclkSrv, SysClkIpcCmd_GetFrequencyTable, - &args, sizeof(args), - table, table_size, disp); - - if (R_FAILED(rc)) - return rc; - - memcpy(out_table, table, table_size); - free(table); - return 0; + return serviceDispatchInOut(&g_sysclkSrv, SysClkIpcCmd_GetFrequencyTable, args, *out_table); } Result sysclkIpcGetIsMariko(bool* out_is_mariko) diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/base_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/base_gui.cpp index 1c26d1ad..a5a4c9ee 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/base_gui.cpp +++ b/Source/sys-clk-OC/overlay/src/ui/gui/base_gui.cpp @@ -13,13 +13,13 @@ #include "../elements/base_frame.h" // #include "logo_rgba_bin.h" -#define LOGO_LABEL_X 20 +#define LOGO_LABEL_X 40 #define LOGO_LABEL_Y 35 #define LOGO_LABEL_FONT_SIZE 20 -#define VERSION_X 246 +#define VERSION_X 266 #define VERSION_Y LOGO_LABEL_Y -#define VERSION_FONT_SIZE 15 +#define VERSION_FONT_SIZE SMALL_TEXT_SIZE void BaseGui::preDraw(tsl::gfx::Renderer* renderer) { diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/base_menu_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/base_menu_gui.cpp index 22a17154..8fbe3c84 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/base_menu_gui.cpp +++ b/Source/sys-clk-OC/overlay/src/ui/gui/base_menu_gui.cpp @@ -34,46 +34,46 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { char buf[32]; - renderer->drawString("App ID: ", false, 20, 60, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("App ID: ", false, 40, 60, SMALL_TEXT_SIZE, DESC_COLOR); snprintf(buf, sizeof(buf), "%016lX", context->applicationId); - renderer->drawString(buf, false, 81, 60, SMALL_TEXT_SIZE, VALUE_COLOR); + renderer->drawString(buf, false, 100, 60, SMALL_TEXT_SIZE, VALUE_COLOR); - renderer->drawString("Profile: ", false, 246, 60, SMALL_TEXT_SIZE, DESC_COLOR); - renderer->drawString(sysclkFormatProfile(context->profile, true), false, 302, 60, SMALL_TEXT_SIZE, VALUE_COLOR); + renderer->drawString("Profile: ", false, 266, 60, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString(sysclkFormatProfile(context->profile, true), false, 322, 60, SMALL_TEXT_SIZE, VALUE_COLOR); static struct { SysClkModule m; std::uint32_t x; } freqOffsets[SysClkModule_EnumMax] = { - { SysClkModule_CPU, 61 }, - { SysClkModule_GPU, 204 }, - { SysClkModule_MEM, 342 }, + { SysClkModule_CPU, 80 }, + { SysClkModule_GPU, 200 }, + { SysClkModule_MEM, 320 }, }; for(unsigned int i = 0; i < SysClkModule_EnumMax; i++) { std::uint32_t hz = this->context->freqs[freqOffsets[i].m]; - snprintf(buf, sizeof(buf), "%u.%u MHz", hz / 1000000, hz / 100000 - hz / 1000000 * 10); + snprintf(buf, sizeof(buf), "%u MHz", hz / 1000000); renderer->drawString(buf, false, freqOffsets[i].x, 85, SMALL_TEXT_SIZE, VALUE_COLOR); } - renderer->drawString("CPU:", false, 20, 85, SMALL_TEXT_SIZE, DESC_COLOR); - renderer->drawString("GPU:", false, 162, 85, SMALL_TEXT_SIZE, DESC_COLOR); - renderer->drawString("MEM:", false, 295, 85, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("CPU:", false, 40, 85, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("GPU:", false, 160, 85, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("MEM:", false, 270, 85, SMALL_TEXT_SIZE, DESC_COLOR); static struct { SysClkThermalSensor s; std::uint32_t x; } tempOffsets[SysClkModule_EnumMax] = { - { SysClkThermalSensor_SOC, 60 }, - { SysClkThermalSensor_PCB, 165 }, - { SysClkThermalSensor_Skin, 268 }, + { SysClkThermalSensor_SOC, 80 }, + { SysClkThermalSensor_PCB, 200 }, + { SysClkThermalSensor_Skin, 320 }, }; - renderer->drawString("SOC:", false, 20, 110, SMALL_TEXT_SIZE, DESC_COLOR); - renderer->drawString("PCB:", false, 125, 110, SMALL_TEXT_SIZE, DESC_COLOR); - renderer->drawString("Skin:", false, 230, 110, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("SOC:", false, 40, 110, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("PCB:", false, 160, 110, SMALL_TEXT_SIZE, DESC_COLOR); + renderer->drawString("Skin:", false, 270, 110, SMALL_TEXT_SIZE, DESC_COLOR); for(unsigned int i = 0; i < SysClkModule_EnumMax; i++) { std::uint32_t millis = this->context->temps[tempOffsets[i].s]; diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.cpp index 6d9100de..f6b149e3 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.cpp +++ b/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.cpp @@ -15,8 +15,8 @@ FreqChoiceGui::FreqChoiceGui(std::uint32_t selectedMHz, SysClkModule module, SysClkProfile profile, FreqChoiceListener listener) { - this->hzTable = new uint32_t[MAX_ENTRIES]; - Result rc = sysclkIpcGetFrequencyTable(module, profile, MAX_ENTRIES, hzTable); + this->hzTable = new SysClkFrequencyTable; + Result rc = sysclkIpcGetFrequencyTable(module, profile, hzTable); if (R_FAILED(rc)) { FatalGui::openWithResultCode("sysclkIpcGetFrequencyTable", rc); } @@ -26,7 +26,7 @@ FreqChoiceGui::FreqChoiceGui(std::uint32_t selectedMHz, SysClkModule module, Sys } FreqChoiceGui::~FreqChoiceGui() { - delete[] this->hzTable; + delete this->hzTable; } tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t mhz, bool selected) @@ -54,11 +54,12 @@ void FreqChoiceGui::listUI() { this->listElement->addItem(this->createFreqListItem(0, this->selectedMHz == 0)); - uint32_t* p = this->hzTable; - while(*p) + size_t idx = 0; + uint32_t freq; + while(idx < 20 && (freq = this->hzTable->values[idx])) { - uint32_t mhz = *p / 1000'000; + uint32_t mhz = freq / 1000'000; this->listElement->addItem(this->createFreqListItem(mhz, mhz == this->selectedMHz)); - p++; + idx++; } } diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.h b/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.h index 93794a7e..efadcae7 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.h +++ b/Source/sys-clk-OC/overlay/src/ui/gui/freq_choice_gui.h @@ -23,7 +23,7 @@ class FreqChoiceGui : public BaseMenuGui protected: std::uint32_t selectedMHz; static constexpr size_t MAX_ENTRIES = 20; - std::uint32_t* hzTable; + SysClkFrequencyTable* hzTable; FreqChoiceListener listener; tsl::elm::ListItem* createFreqListItem(std::uint32_t mhz, bool selected); diff --git a/Source/sys-clk-OC/sysmodule/lib/nxExt/include/nxExt/apm_ext.h b/Source/sys-clk-OC/sysmodule/lib/nxExt/include/nxExt/apm_ext.h index 98a1b520..b550fd3f 100644 --- a/Source/sys-clk-OC/sysmodule/lib/nxExt/include/nxExt/apm_ext.h +++ b/Source/sys-clk-OC/sysmodule/lib/nxExt/include/nxExt/apm_ext.h @@ -20,8 +20,11 @@ extern "C" Result apmExtInitialize(void); void apmExtExit(void); -Result apmExtGetPerformanceMode(u32 *out_mode); +// Silently fail Result apmExtSysRequestPerformanceMode(u32 mode); +Result apmExtSysSetCpuBoostMode(u32 mode); + +Result apmExtGetPerformanceMode(u32 *out_mode); Result apmExtGetCurrentPerformanceConfiguration(u32 *out_conf); inline bool apmExtIsCPUBoosted(u32 conf_id) { // CPU boosted to 1785 MHz diff --git a/Source/sys-clk-OC/sysmodule/lib/nxExt/src/apm_ext.c b/Source/sys-clk-OC/sysmodule/lib/nxExt/src/apm_ext.c index ba30d4ff..96102dd8 100644 --- a/Source/sys-clk-OC/sysmodule/lib/nxExt/src/apm_ext.c +++ b/Source/sys-clk-OC/sysmodule/lib/nxExt/src/apm_ext.c @@ -21,22 +21,15 @@ Result apmExtInitialize(void) g_refCnt++; if (serviceIsActive(&g_apmSrv)) - { return 0; - } - Result rc = 0; + Result rc = smGetService(&g_apmSrv, "apm"); - rc = smGetService(&g_apmSrv, "apm"); if(R_SUCCEEDED(rc)) - { rc = smGetService(&g_apmSysSrv, "apm:sys"); - } if (R_FAILED(rc)) - { apmExtExit(); - } return rc; } @@ -50,6 +43,11 @@ void apmExtExit(void) } } +Result apmExtSysSetCpuBoostMode(u32 mode) +{ + return serviceDispatchIn(&g_apmSysSrv, 6, mode); +} + Result apmExtGetPerformanceMode(u32 *out_mode) { return serviceDispatchOut(&g_apmSrv, 1, *out_mode); diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp index e5519a2f..3dfdc412 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp @@ -60,8 +60,6 @@ ClockManager::ClockManager() this->oc->systemCoreBoostCPU = false; this->oc->governor = false; this->oc->realProfile = SysClkProfile_Handheld; - this->oc->maxMEMFreq = 0; - this->oc->boostCPUFreq = 0; this->rnxSync = new ReverseNXSync; this->governor = new Governor; @@ -76,17 +74,6 @@ ClockManager::~ClockManager() delete this->config; } -bool ClockManager::IsBoostMode() -{ - std::uint32_t confId = this->context->perfConfId; - bool isBoostMode = apmExtIsBoostMode(confId); - if (apmExtIsCPUBoosted(confId) && !this->oc->boostCPUFreq) { - this->oc->boostCPUFreq = std::max(this->context->freqs[SysClkModule_CPU], 1785'000'000U); - this->governor->SetCPUBoostHz(this->oc->boostCPUFreq); - } - return isBoostMode; -} - void ClockManager::SetRunning(bool running) { this->running = running; @@ -127,7 +114,7 @@ uint32_t ClockManager::GetHz(SysClkModule module) case SysClkModule_MEM: hz = (mode == ReverseNX_Docked || this->oc->realProfile == SysClkProfile_Docked) ? - MAX_MEM_CLOCK : 1600'000'000; + Clocks::maxMemFreq : 1600'000'000; break; default: break; @@ -138,27 +125,13 @@ uint32_t ClockManager::GetHz(SysClkModule module) { /* Considering realProfile frequency limit */ hz = Clocks::GetNearestHz(module, this->oc->realProfile, hz); - - if (module == SysClkModule_MEM && hz == MAX_MEM_CLOCK) - { - /* Trigger Max Mem Clock and record it */ - if (!this->oc->maxMEMFreq) - { - uint32_t currentHz = Clocks::GetCurrentHz(SysClkModule_MEM); - Clocks::SetHz(SysClkModule_MEM, MAX_MEM_CLOCK); - this->oc->maxMEMFreq = Clocks::GetCurrentHz(SysClkModule_MEM); - Clocks::SetHz(SysClkModule_MEM, currentHz); - } - - return this->oc->maxMEMFreq; - } } /* Handle CPU Auto Boost, no user-defined hz required */ if (module == SysClkModule_CPU) { - if (this->oc->systemCoreBoostCPU && hz < this->oc->boostCPUFreq) - return this->oc->boostCPUFreq; + if (this->oc->systemCoreBoostCPU && hz < Clocks::boostCpuFreq) + return Clocks::boostCpuFreq; if (!hz) /* Trigger RefreshContext() and Tick(), resetting default CPU frequency */ return 1020'000'000; @@ -182,7 +155,8 @@ void ClockManager::Tick() if (hz && hz != this->context->freqs[module] && !this->oc->governor) { // Skip setting CPU or GPU clocks in CpuBoostMode if CPU <= boostCPUFreq or GPU >= 76.8MHz - bool skipBoost = IsBoostMode() && ((module == SysClkModule_CPU && hz <= this->oc->boostCPUFreq) || module == SysClkModule_GPU); + bool skipBoost = apmExtIsBoostMode(this->context->perfConfId); + skipBoost &= (module == SysClkModule_CPU && hz <= Clocks::boostCpuFreq) || module == SysClkModule_GPU; if (!skipBoost) { FileUtils::LogLine("[mgr] %s clock set : %u.%u MHz", Clocks::GetModuleName((SysClkModule)module, true), hz/1000000, hz/100000 - hz/1000000*10); Clocks::SetHz((SysClkModule)module, hz); @@ -210,7 +184,7 @@ void ClockManager::WaitForNextTick() this->GetConfig()->GetConfigValue(SysClkConfigValue_AutoCPUBoost) && this->context->enabled && this->oc->realProfile != SysClkProfile_Handheld && - this->context->freqs[SysClkModule_CPU] <= this->oc->boostCPUFreq; + this->context->freqs[SysClkModule_CPU] <= Clocks::boostCpuFreq; if (boostOK) { uint32_t core3Util = CpuCoreUtil(3, tickWaitTimeMs * 1000'000ULL).Get(); @@ -222,7 +196,7 @@ void ClockManager::WaitForNextTick() Clocks::SetHz(SysClkModule_CPU, GetHz(SysClkModule_CPU)); if (!lastBoost && this->oc->systemCoreBoostCPU) - Clocks::SetHz(SysClkModule_CPU, this->oc->boostCPUFreq); + Clocks::SetHz(SysClkModule_CPU, Clocks::boostCpuFreq); return; } @@ -313,7 +287,7 @@ bool ClockManager::RefreshContext() } // let ptm module handle boost clocks rather than resetting - if (hasChanged && !IsBoostMode()) { + if (hasChanged && !apmExtIsBoostMode(this->context->perfConfId)) { Clocks::ResetToStock(); } diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.h b/Source/sys-clk-OC/sysmodule/src/clock_manager.h index a52da841..57594788 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.h +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.h @@ -52,7 +52,5 @@ class ClockManager ReverseNXSync *rnxSync; Governor *governor; - bool IsBoostMode(); - uint32_t GetHz(SysClkModule); }; diff --git a/Source/sys-clk-OC/sysmodule/src/clocks.cpp b/Source/sys-clk-OC/sysmodule/src/clocks.cpp index 5e34690d..0d5b109d 100644 --- a/Source/sys-clk-OC/sysmodule/src/clocks.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clocks.cpp @@ -12,6 +12,7 @@ #include #include "clocks.h" #include "errors.h" +#include "file_utils.h" void Clocks::GetRange(SysClkModule module, SysClkProfile profile, uint32_t** min, uint32_t** max) { @@ -58,18 +59,18 @@ void Clocks::GetRange(SysClkModule module, SysClkProfile profile, uint32_t** min ERROR_THROW("No such PcvModule: %u", module); } -Result Clocks::GetTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table) { +Result Clocks::GetTable(SysClkModule module, SysClkProfile profile, SysClkFrequencyTable* out_table) { uint32_t* min = NULL; uint32_t* max = NULL; - memset(out_table, 0, max_entry_num * sizeof(uint32_t)); GetRange(module, profile, &min, &max); - if (!min || !max || (max - min) / sizeof(uint32_t) >= max_entry_num) + if (!min || !max || (max - min) / sizeof(uint32_t) >= sizeof(SysClkFrequencyTable) / sizeof(uint32_t)) return 1; + memset(out_table, 0, sizeof(SysClkFrequencyTable)); uint32_t* p = min; size_t idx = 0; while(p <= max) - out_table[idx++] = *p++; + out_table->values[idx++] = *p++; return 0; } @@ -78,7 +79,6 @@ void Clocks::Initialize() { Result rc = 0; - // Check if it's Mariko u64 hardware_type = 0; rc = splInitialize(); ASSERT_RESULT_OK(rc, "splInitialize"); @@ -89,11 +89,11 @@ void Clocks::Initialize() switch (hardware_type) { case 0: // Icosa case 1: // Copper - case 4: // Calcio isMariko = false; break; case 2: // Hoag case 3: // Iowa + case 4: // Calcio case 5: // Aula isMariko = true; break; @@ -127,6 +127,19 @@ void Clocks::Initialize() rc = tcInitialize(); ASSERT_RESULT_OK(rc, "tcInitialize"); } + + FileUtils::ParseLoaderKip(); + + if (!maxMemFreq) { + uint32_t curr_mem_hz = GetCurrentHz(SysClkModule_MEM); + SetHz(SysClkModule_MEM, MAX_MEM_CLOCK); + svcSleepThread(1'000'000); + if (uint32_t hz = GetCurrentHz(SysClkModule_MEM)) + maxMemFreq = hz; + else + maxMemFreq = MAX_MEM_CLOCK; + SetHz(SysClkModule_MEM, curr_mem_hz); + } } void Clocks::Exit() @@ -359,6 +372,9 @@ std::uint32_t Clocks::GetCurrentHz(SysClkModule module) std::uint32_t Clocks::GetNearestHz(SysClkModule module, SysClkProfile profile, std::uint32_t inHz) { + if (module == SysClkModule_MEM && inHz == MAX_MEM_CLOCK) + return Clocks::maxMemFreq; + uint32_t* min = NULL; uint32_t* max = NULL; GetRange(module, profile, &min, &max); diff --git a/Source/sys-clk-OC/sysmodule/src/clocks.h b/Source/sys-clk-OC/sysmodule/src/clocks.h index 5aaa86b5..b4c90158 100644 --- a/Source/sys-clk-OC/sysmodule/src/clocks.h +++ b/Source/sys-clk-OC/sysmodule/src/clocks.h @@ -18,8 +18,11 @@ class Clocks { public: + static inline uint32_t boostCpuFreq = 1785000000; + static inline uint32_t maxMemFreq = MAX_MEM_CLOCK; + static void GetRange(SysClkModule module, SysClkProfile profile, uint32_t** min, uint32_t** max); - static Result GetTable(SysClkModule module, SysClkProfile profile, size_t max_entry_num, uint32_t* out_table); + static Result GetTable(SysClkModule module, SysClkProfile profile, SysClkFrequencyTable* out_table); static void SetAllowUnsafe(bool allow) { allowUnsafe = allow; }; static bool GetIsMariko() { return isMariko; }; static void Exit(); diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp index 551d91c6..7c9eb16d 100644 --- a/Source/sys-clk-OC/sysmodule/src/file_utils.cpp +++ b/Source/sys-clk-OC/sysmodule/src/file_utils.cpp @@ -11,7 +11,6 @@ #include "file_utils.h" #include "clocks.h" #include -#include #include static LockableMutex g_log_mutex; @@ -182,3 +181,126 @@ void FileUtils::Exit() fsdevUnmountAll(); fsExit(); } + +void FileUtils::ParseLoaderKip() { + const char* dirs[] = { "/", "/atmosphere/", "/atmosphere/kips/", "/bootloader/" }; + char* full_path = new char[0x200]; + for (auto const& dir : dirs) { + struct dirent *entry = NULL; + DIR *dp = opendir(dir); + if (!dp) + continue; + + while ((entry = readdir(dp))) { + if (entry->d_type != DT_REG) + continue; + + snprintf(full_path, 0x200, "%s%s", dir, entry->d_name); + + FILE* fp = fopen(full_path, "r"); + if (!fp) + continue; + + fseek(fp, 0, SEEK_END); + long res = ftell(fp); + fclose(fp); + if (res == -1) + continue; + + size_t filesize = (size_t)res; + if (filesize < 0x1000 || filesize > 512 * 1024) + continue; + + const char kip_ext[] = {'.', 'k', 'i', 'p'}; + size_t file_name_len = strnlen(reinterpret_cast(&entry->d_name), 256); + const char* file_ext = &entry->d_name[file_name_len - sizeof(kip_ext)]; + + if (strncasecmp((const char*)kip_ext, file_ext, sizeof(kip_ext))) + continue; + + if (R_SUCCEEDED(CustParser(full_path, filesize))) { + LogLine("Parsed cust config from %s, maxMemFreq: %u MHz, boostCpuFreq: %u MHz", + full_path, + Clocks::maxMemFreq / 1'000'000, + Clocks::boostCpuFreq / 1'000'000 + ); + delete[] full_path; + return; + } + } + } + delete[] full_path; +} + +Result FileUtils::CustParser(const char* filepath, size_t filesize) { + enum ParseError { + ParseError_Success = 0, + ParseError_OpenReadFailed, + ParseError_WrongKipMagic, + ParseError_CustNotFound, + ParseError_WrongCustRev, + }; + + FILE* fp = fopen(filepath, "r"); + if (!fp) + return ParseError_OpenReadFailed; + + constexpr uint8_t KIP_MAGIC[] = {'K', 'I', 'P', '1', 'L', 'o', 'a', 'd', 'e', 'r'}; + constexpr size_t BLOCK_SIZE = 0x1000; + + char* tmp_block = new char[BLOCK_SIZE]; + fread(tmp_block, sizeof(char), BLOCK_SIZE, fp); + + if (memcmp(KIP_MAGIC, tmp_block, sizeof(KIP_MAGIC))) { + delete[] tmp_block; + return ParseError_WrongKipMagic; + } + + CustTable table {}; + + fpos_t cust_pos = 0; + long block_pos = 0; + while ((block_pos = ftell(fp)) >= 0 && (size_t)block_pos < filesize) { + for (size_t i = 0; i < BLOCK_SIZE; i += sizeof(table.cust)) { + if (memcmp(table.cust, &tmp_block[i], sizeof(table.cust))) + continue; + + fgetpos(fp, &cust_pos); + cust_pos = cust_pos + i - BLOCK_SIZE; + goto found; + } + fread(tmp_block, sizeof(char), BLOCK_SIZE, fp); + } + + found: + delete[] tmp_block; + + if (!cust_pos) { + fclose(fp); + return ParseError_CustNotFound; + } + + memset(reinterpret_cast(&table), 0, sizeof(CustTable)); + fsetpos(fp, &cust_pos); + if (!fread(reinterpret_cast(&table), 1, sizeof(CustTable), fp)) { + fclose(fp); + return ParseError_OpenReadFailed; + } + + fclose(fp); + + if (table.custRev != 2) + return ParseError_WrongCustRev; + + if (Clocks::GetIsMariko()) { + if (table.marikoCpuBoostClock) + Clocks::boostCpuFreq = table.marikoCpuBoostClock * 1000; + if (table.marikoEmcMaxClock) + Clocks::maxMemFreq = table.marikoEmcMaxClock * 1000; + } else { + if (table.eristaEmcMaxClock) + Clocks::maxMemFreq = table.eristaEmcMaxClock * 1000; + } + + return ParseError_Success; +} diff --git a/Source/sys-clk-OC/sysmodule/src/file_utils.h b/Source/sys-clk-OC/sysmodule/src/file_utils.h index 401217d0..e3b9fed2 100644 --- a/Source/sys-clk-OC/sysmodule/src/file_utils.h +++ b/Source/sys-clk-OC/sysmodule/src/file_utils.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,23 @@ class FileUtils static void InitializeAsync(); static void LogLine(const char *format, ...); static void WriteContextToCsv(const SysClkContext* context); + static void ParseLoaderKip(); protected: + typedef struct CustTable { + uint8_t cust[4] = {'C', 'U', 'S', 'T'}; + uint16_t custRev; + uint16_t mtcConf; + uint32_t marikoCpuMaxClock; + uint32_t marikoCpuBoostClock; + uint32_t marikoCpuMaxVolt; + uint32_t marikoGpuMaxClock; + uint32_t marikoEmcMaxClock; + uint32_t eristaCpuOCEnable; + uint32_t eristaCpuMaxVolt; + uint32_t eristaEmcMaxClock; + uint32_t eristaEmcVolt; + } CustTable; + static void RefreshFlags(bool force); + static Result CustParser(const char* path, size_t filesize); }; diff --git a/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp b/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp index 17a2dce7..407c44fe 100644 --- a/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp +++ b/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp @@ -164,8 +164,8 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* if(r->data.size >= sizeof(SysClkIpc_GetFrequencyTable_Args)) { SysClkIpc_GetFrequencyTable_Args* in_args = (SysClkIpc_GetFrequencyTable_Args*)r->data.ptr; - *out_dataSize = sizeof(uint32_t) * in_args->max_entry_num; - return ipcSrv->GetFrequencyTable(in_args, (uint32_t*)out_data); + *out_dataSize = sizeof(SysClkFrequencyTable); + return ipcSrv->GetFrequencyTable(in_args, (SysClkFrequencyTable*)out_data); } break; case SysClkIpcCmd_GetIsMariko: @@ -313,8 +313,8 @@ Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) { return 0; } -Result IpcService::GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, uint32_t* out_table) { - return Clocks::GetTable(args->module, args->profile, args->max_entry_num, out_table); +Result IpcService::GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, SysClkFrequencyTable* out_table) { + return Clocks::GetTable(args->module, args->profile, out_table); } Result IpcService::GetIsMariko(bool* out_is_mariko) { diff --git a/Source/sys-clk-OC/sysmodule/src/ipc_service.h b/Source/sys-clk-OC/sysmodule/src/ipc_service.h index 7cca0263..11cf3f4b 100644 --- a/Source/sys-clk-OC/sysmodule/src/ipc_service.h +++ b/Source/sys-clk-OC/sysmodule/src/ipc_service.h @@ -37,7 +37,7 @@ class IpcService Result GetConfigValues(SysClkConfigValueList* out_configValues); Result SetConfigValues(SysClkConfigValueList* configValues); Result SetReverseNXRTMode(ReverseNXMode mode); - Result GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, uint32_t* out_table); + Result GetFrequencyTable(SysClkIpc_GetFrequencyTable_Args* args, SysClkFrequencyTable* out_table); Result GetIsMariko(bool* out_is_mariko); bool running; diff --git a/Source/sys-clk-OC/sysmodule/src/main.cpp b/Source/sys-clk-OC/sysmodule/src/main.cpp index 4a0e87e8..00631d2b 100644 --- a/Source/sys-clk-OC/sysmodule/src/main.cpp +++ b/Source/sys-clk-OC/sysmodule/src/main.cpp @@ -22,7 +22,7 @@ #include "ipc_service.h" #include "oc_extra.h" -#define INNER_HEAP_SIZE 0x38000 +#define INNER_HEAP_SIZE 0x40000 extern "C" { diff --git a/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp b/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp index 3e47e834..525a377c 100644 --- a/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp +++ b/Source/sys-clk-OC/sysmodule/src/oc_extra.cpp @@ -135,10 +135,10 @@ Governor::Governor() { m_cpu_freq.module = SysClkModule_CPU; m_gpu_freq.module = SysClkModule_GPU; - m_cpu_freq.hz_list = &g_freq_table_cpu_hz[0]; - m_gpu_freq.hz_list = &g_freq_table_cpu_hz[0]; + m_cpu_freq.hz_list = GetTable(SysClkModule_CPU); + m_gpu_freq.hz_list = GetTable(SysClkModule_GPU); - m_cpu_freq.boost_hz = 1785'000'000; + m_cpu_freq.boost_hz = Clocks::boostCpuFreq; m_cpu_freq.utilref_hz = 2397'000'000; m_gpu_freq.boost_hz = 76'800'000; @@ -244,7 +244,7 @@ void Governor::s_FreqContext::SetNextFreq(uint32_t norm_util) { } else { uint32_t* p = hz_list; do { - if (*p > next_freq) { + if (*p >= next_freq) { adj_next_freq = *p; break; }