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.
u8 otherattributes;
} PACKED exheader_storageinfo;
+// New3DS speed is flags[1]:1
+
typedef struct
{
u64 programid;
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];
--- /dev/null
+.section .text
+.global KernelSetState
+KernelSetState:
+ svc 0x7C // KernelSetState
+ bx lr // return;
}
}
+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;
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;
g_active_handles--;
reply_target = 0;
}
- else
+ else
{
svcBreak(USERBREAK_ASSERT);
}
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.
+}
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);
#include <stdlib.h>
#include <string.h>
-#include "../../../source/patch_format.h"
+#include "../source/patch_format.h"
void read_file_u64(char* name, uint64_t* to) {
FILE* hdl = fopen(name, "rb");
.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
.PHONY: tool
tool:
- $(HOST_CC) -o compile_header tool/compile_header.c
+ $(HOST_CC) -o compile_header ../../host/compile_header.c
.PHONY: clean