- Fixed gpu_hz_list typo in governor (#46)

- Parse loader.kip config from { "/", "/atmosphere/", "/atmosphere/kips/", "/bootloader/" } (#44)
This commit is contained in:
KazushiM
2022-10-31 00:43:40 +08:00
parent 524247955f
commit 859841ab8e
20 changed files with 232 additions and 115 deletions

View File

@@ -11,7 +11,6 @@
#include "file_utils.h"
#include "clocks.h"
#include <dirent.h>
#include <filesystem>
#include <nxExt.h>
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<const char*>(&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<void*>(&table), 0, sizeof(CustTable));
fsetpos(fp, &cust_pos);
if (!fread(reinterpret_cast<char*>(&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;
}