From 7a058a097b0aa4cb2226dac96b5e1b0038b4a722 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Mon, 23 May 2016 13:56:57 -0400 Subject: [PATCH] Experimental shite. The kernel doesn't get passed CPU flags from the functions called here. Assuming the kernel doesn't seek backwards from the exheader pointer, the CPU state should already have been set by AM, which means loader can override what was previously set. That being the case, if I am correct, setting the CPU speed from loader should technically persist to application launch. This needs testing, obviously, but I believe granular CPU speed control is possible from here. --- external/loader/source/exheader.h | 8 ++------ external/loader/source/ksetstate.s | 5 +++++ external/loader/source/loader.c | 21 ++++++++++++++++++++- external/loader/source/patcher.c | 5 +++++ external/loader/source/patcher.h | 2 ++ host/compile_header.c | 2 +- modules/Makefile | 13 ++----------- modules/template/Makefile | 2 +- 8 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 external/loader/source/ksetstate.s diff --git a/external/loader/source/exheader.h b/external/loader/source/exheader.h index be23527..dccb083 100644 --- a/external/loader/source/exheader.h +++ b/external/loader/source/exheader.h @@ -50,6 +50,8 @@ typedef struct u8 otherattributes; } PACKED exheader_storageinfo; +// New3DS speed is flags[1]:1 + typedef struct { u64 programid; @@ -75,18 +77,12 @@ typedef struct typedef struct { - // systemcontrol info { - // coreinfo { exheader_codesetinfo codesetinfo; exheader_dependencylist deplist; - // } exheader_systeminfo systeminfo; - // } - // accesscontrolinfo { exheader_arm11systemlocalcaps arm11systemlocalcaps; exheader_arm11kernelcapabilities arm11kernelcaps; exheader_arm9accesscontrol arm9accesscontrol; - // } struct { u8 signature[0x100]; u8 ncchpubkeymodulus[0x100]; diff --git a/external/loader/source/ksetstate.s b/external/loader/source/ksetstate.s new file mode 100644 index 0000000..51f0bc4 --- /dev/null +++ b/external/loader/source/ksetstate.s @@ -0,0 +1,5 @@ +.section .text +.global KernelSetState +KernelSetState: + svc 0x7C // KernelSetState + bx lr // return; diff --git a/external/loader/source/loader.c b/external/loader/source/loader.c index c6075e6..6fc32d2 100644 --- a/external/loader/source/loader.c +++ b/external/loader/source/loader.c @@ -184,6 +184,16 @@ static Result loader_GetProgramInfo(exheader_header *exheader, u64 prog_handle) } } +extern void KernelSetState(unsigned int, unsigned int, unsigned int, unsigned int); + +static void ConfigureNew3DSCPU(u8 mode) { + // 10 -> r0 (Type) + // mode -> r1 (Mode) + // svc 0x7C + + KernelSetState(10, mode, 0, 0); // Yes, we syscall directly. Problem? +} + static Result loader_LoadProcess(Handle *process, u64 prog_handle) { Result res; @@ -229,6 +239,15 @@ static Result loader_LoadProcess(Handle *process, u64 prog_handle) load_config(); // First order of business - we need the config file. + // Check and set the CPU mode. Possible values: 0 - Keep o3ds speed, 1 - n3ds speed, -1 force o3ds + // This is A-OK because the CPU speed parameter isn't passed through to any kernel function; meaning it has already been set. + u8 n3ds_mode = g_exheader.arm11systemlocalcaps.flags[1] & 0x3; + u8 cpu_mode = get_cpumode(progid); + if (cpu_mode != 0xFF) { // Skip? + u8 mode = n3ds_mode | cpu_mode; // Keep flags set by exheader. + ConfigureNew3DSCPU(mode); // We do not use PXIPM because we are a sysmodule. It doesn't make sense. + } + // What the addressing info would be if not for expansion. This is passed to patchCode. original_vaddr.text_size = (g_exheader.codesetinfo.text.codesize + 4095) >> 12; // (Text size + one page) >> page size original_vaddr.ro_size = (g_exheader.codesetinfo.ro.codesize + 4095) >> 12; @@ -554,7 +573,7 @@ int main() g_active_handles--; reply_target = 0; } - else + else { svcBreak(USERBREAK_ASSERT); } diff --git a/external/loader/source/patcher.c b/external/loader/source/patcher.c index ef0cd65..f76cf25 100644 --- a/external/loader/source/patcher.c +++ b/external/loader/source/patcher.c @@ -458,3 +458,8 @@ u32 get_ro_extend(u64 progId, u32 size_orig) { u32 get_data_extend(u64 progId, u32 size_orig) { return 0; // Stub - nothing needs this yet } + +// Get CPU speed for progId. +u8 get_cpumode(u64 progId) { + return 0xff; // Skip. +} diff --git a/external/loader/source/patcher.h b/external/loader/source/patcher.h index ad83c8d..5b56b17 100644 --- a/external/loader/source/patcher.h +++ b/external/loader/source/patcher.h @@ -13,3 +13,5 @@ u32 get_data_extend(u64 progId, u32 size_orig); void load_config(); u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, int offset, const void *replace, u32 repSize, u32 count); + +u8 get_cpumode(u64 progId); diff --git a/host/compile_header.c b/host/compile_header.c index 049ff7d..8ec4454 100644 --- a/host/compile_header.c +++ b/host/compile_header.c @@ -4,7 +4,7 @@ #include #include -#include "../../../source/patch_format.h" +#include "../source/patch_format.h" void read_file_u64(char* name, uint64_t* to) { FILE* hdl = fopen(name, "rb"); diff --git a/modules/Makefile b/modules/Makefile index a9afaaa..4a85dfd 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -1,25 +1,16 @@ .PHONY: all copyout -all: template signatures +all: template mkdir -p ../out/corbenik/bin cp template/out/patch.vco ../out/corbenik/bin/example.vco - cp signatures/out/patch.vco ../out/corbenik/bin/signatures.vco .PHONY: clean -clean: clean_template clean_signatures +clean: clean_template rm -rf ../out/corbenik/bin .PHONY: template template: make -C template -.PHONY: signatures -signatures: - make -C signatures - .PHONY: clean_template clean_template: make -C template clean - -.PHONY: clean_signatures -clean_signatures: - make -C signatures clean diff --git a/modules/template/Makefile b/modules/template/Makefile index de1a361..972f9ee 100644 --- a/modules/template/Makefile +++ b/modules/template/Makefile @@ -31,7 +31,7 @@ patchbin: tool $(dir_out)/patch.bin .PHONY: tool tool: - $(HOST_CC) -o compile_header tool/compile_header.c + $(HOST_CC) -o compile_header ../../host/compile_header.c .PHONY: clean -- 2.39.5