From 3df571c10521f287ff6eefa4a134be00e66a9a24 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 15 May 2016 00:53:27 -0400 Subject: [PATCH] Working on dynamic linker thing for patches (why not?) --- patchbins/README.txt | 27 ++++ patchbins/firmprot/Makefile | 60 ++++++++ patchbins/firmprot/linker.ld | 59 +++++++ patchbins/firmprot/meta/cfw_version | 1 + patchbins/firmprot/meta/deps | 1 + patchbins/firmprot/meta/desc | 1 + patchbins/firmprot/meta/name | 1 + patchbins/firmprot/meta/patch_version | 1 + patchbins/firmprot/meta/title | 1 + patchbins/firmprot/meta/uuid | 1 + patchbins/firmprot/src/exported.h | 25 +++ patchbins/firmprot/src/link_table.s | 43 ++++++ patchbins/firmprot/src/main.c | 36 +++++ patchbins/firmprot/src/patcher.c | 171 +++++++++++++++++++++ patchbins/firmprot/src/start.s | 6 + patchbins/firmprot/tool/compile_header.c | 91 +++++++++++ patchbins/signatures/Makefile | 60 ++++++++ patchbins/signatures/linker.ld | 59 +++++++ patchbins/signatures/meta/cfw_version | 1 + patchbins/signatures/meta/deps | 1 + patchbins/signatures/meta/desc | 1 + patchbins/signatures/meta/name | 1 + patchbins/signatures/meta/patch_version | 1 + patchbins/signatures/meta/title | 1 + patchbins/signatures/meta/uuid | 1 + patchbins/signatures/src/exported.h | 25 +++ patchbins/signatures/src/link_table.s | 43 ++++++ patchbins/signatures/src/main.c | 36 +++++ patchbins/signatures/src/start.s | 6 + patchbins/signatures/tool/compile_header.c | 91 +++++++++++ patchbins/template/Makefile | 60 ++++++++ patchbins/template/linker.ld | 59 +++++++ patchbins/template/meta/cfw_version | 1 + patchbins/template/meta/deps | 1 + patchbins/template/meta/desc | 1 + patchbins/template/meta/name | 1 + patchbins/template/meta/patch_version | 1 + patchbins/template/meta/title | 1 + patchbins/template/meta/uuid | 1 + patchbins/template/src/exported.h | 25 +++ patchbins/template/src/link_table.s | 53 +++++++ patchbins/template/src/main.c | 10 ++ patchbins/template/src/start.s | 8 + patchbins/template/tool/compile_header.c | 91 +++++++++++ source/firm/fcram.h | 5 +- source/linker.c | 57 +++++++ source/menu.c | 14 +- source/patch_format.h | 2 +- source/patcher.c | 7 +- 49 files changed, 1237 insertions(+), 13 deletions(-) create mode 100644 patchbins/README.txt create mode 100644 patchbins/firmprot/Makefile create mode 100644 patchbins/firmprot/linker.ld create mode 100644 patchbins/firmprot/meta/cfw_version create mode 100644 patchbins/firmprot/meta/deps create mode 100644 patchbins/firmprot/meta/desc create mode 100644 patchbins/firmprot/meta/name create mode 100644 patchbins/firmprot/meta/patch_version create mode 100644 patchbins/firmprot/meta/title create mode 100644 patchbins/firmprot/meta/uuid create mode 100644 patchbins/firmprot/src/exported.h create mode 100644 patchbins/firmprot/src/link_table.s create mode 100644 patchbins/firmprot/src/main.c create mode 100644 patchbins/firmprot/src/patcher.c create mode 100644 patchbins/firmprot/src/start.s create mode 100644 patchbins/firmprot/tool/compile_header.c create mode 100644 patchbins/signatures/Makefile create mode 100644 patchbins/signatures/linker.ld create mode 100644 patchbins/signatures/meta/cfw_version create mode 100644 patchbins/signatures/meta/deps create mode 100644 patchbins/signatures/meta/desc create mode 100644 patchbins/signatures/meta/name create mode 100644 patchbins/signatures/meta/patch_version create mode 100644 patchbins/signatures/meta/title create mode 100644 patchbins/signatures/meta/uuid create mode 100644 patchbins/signatures/src/exported.h create mode 100644 patchbins/signatures/src/link_table.s create mode 100644 patchbins/signatures/src/main.c create mode 100644 patchbins/signatures/src/start.s create mode 100644 patchbins/signatures/tool/compile_header.c create mode 100644 patchbins/template/Makefile create mode 100644 patchbins/template/linker.ld create mode 100644 patchbins/template/meta/cfw_version create mode 100644 patchbins/template/meta/deps create mode 100644 patchbins/template/meta/desc create mode 100644 patchbins/template/meta/name create mode 100644 patchbins/template/meta/patch_version create mode 100644 patchbins/template/meta/title create mode 100644 patchbins/template/meta/uuid create mode 100644 patchbins/template/src/exported.h create mode 100644 patchbins/template/src/link_table.s create mode 100644 patchbins/template/src/main.c create mode 100644 patchbins/template/src/start.s create mode 100644 patchbins/template/tool/compile_header.c create mode 100644 source/linker.c diff --git a/patchbins/README.txt b/patchbins/README.txt new file mode 100644 index 0000000..21b6567 --- /dev/null +++ b/patchbins/README.txt @@ -0,0 +1,27 @@ +You're probably wondering what the heck corbenik does differently from cakes, +considering it seems similar. + +Patches are actually code for whatever processor they're intended to run on. +They're loaded to a static offset in memory, and executed. + +Patches should have a declaration of this sort somewhere in them: + { 0xc0, 0x9b, 0xe5, 0x1c } +Followed by a table large enough to fill with all usable functions. + +See template/ for how this works. + +When the loader finds that magic value, it fills the table with +the offsets of important variables and functions for use by the patcher, much +like how an ELF loader sets up references. In other words; patches are binaries +that are relocated relative to a 'standard library'. + +There's some key differences, obviously, from running just arm9loader code. +Namely: + 1) Patches must not clobber the previous state. + 2) Patches must properly return. + 3) Patches must have a symbol table with the appropriate magic. + 4) Patches shouldn't do anything aside from change data. + 5) _start must be at offset 0x24400000. + +Basically, don't get fancy in _start. Just do a bl main; bx lr. You can implement +shit yourself, but it's an utter waste of memory. Try not to. diff --git a/patchbins/firmprot/Makefile b/patchbins/firmprot/Makefile new file mode 100644 index 0000000..e2f940b --- /dev/null +++ b/patchbins/firmprot/Makefile @@ -0,0 +1,60 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +PATH := $(PATH):$(DEVKITARM)/bin + +HOST_CC := gcc + +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +LD := arm-none-eabi-ld +OC := arm-none-eabi-objcopy + +dir_source := src +dir_build := build +dir_out := out + +ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te +CFLAGS := -MMD -MP -Wall -Wextra -Werror -O0 $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" +FLAGS := dir_out=$(abspath $(dir_out)) --no-print-directory +LDFLAGS := -nostdlib -Wl,-z,defs -lgcc + +objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ + $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ + $(call rwildcard, $(dir_source), *.s *.c))) + +.PHONY: all +all: patchbin + +.PHONY: patchbin +patchbin: tool $(dir_out)/patch.bin + ./compile_header + +.PHONY: tool +tool: + $(HOST_CC) -o compile_header tool/compile_header.c + + +.PHONY: clean +clean: + rm -rf $(dir_out) $(dir_build) compile_header + +.PHONY: $(dir_out)/patch.bin +$(dir_out)/patch.bin: $(dir_build)/main.bin + @mkdir -p "$(dir_out)" + @cp -av $< $@ + +$(dir_build)/main.bin: $(dir_build)/main.elf + $(OC) -S -O binary $< $@ + +$(dir_build)/main.elf: $(objects_cfw) + $(CC) -T linker.ld $(OUTPUT_OPTION) $^ $(LDFLAGS) + +$(dir_build)/%.o: $(dir_source)/%.c + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.s) $(OUTPUT_OPTION) $< + +include $(call rwildcard, $(dir_build), *.d) diff --git a/patchbins/firmprot/linker.ld b/patchbins/firmprot/linker.ld new file mode 100644 index 0000000..7d6129b --- /dev/null +++ b/patchbins/firmprot/linker.ld @@ -0,0 +1,59 @@ +/* This memory map is mainly to assist in doing stuff in code. +MEMORY +{ + INSTRUCTION_TCM (rw) : ORIGIN = 0x00000000, LENGTH = 0x08000000 + ARM_INTERNAL (rw) : ORIGIN = 0x08000000, LENGTH = 0x00100000 + NEW_INTERNAL (rw) : ORIGIN = 0x08100000, LENGTH = 0x00080000 + IO_MEMORY (rw) : ORIGIN = 0x10000000, LENGTH = 0x08000000 + VRAM (rw) : ORIGIN = 0x18000000, LENGTH = 0x00600000 + DSP_MEMORY (rw) : ORIGIN = 0x1FF00000, LENGTH = 0x00080000 + AXI_WRAM (rw) : ORIGIN = 0x1FF80000, LENGTH = 0x00080000 + FCRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x08000000 + NEW_FCRAM (rwx) : ORIGIN = 0x28000000, LENGTH = 0x08000000 + DATA_TCM (rw) : ORIGIN = 0xFFF00000, LENGTH = 0x00004000 + BOOTROM (rw) : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 +} */ + +ENTRY(_start) +SECTIONS +{ + . = 0x24400000; + + START_SECTION = .; + .text.start : { + *(.text.start) + } + START_SECTION_END = .; + + TABLE_SECTION = .; + .text.table : { + *(.text.table) + } + TABLE_SECTION_END = .; + + TEXT_SECTION = .; + .text : { + *(.text) + } + TEXT_SECTION_END = .; + + DATA_SECTION = .; + .data : { + *(.data) + } + DATA_SECTION_END = .; + + BSS_SECTION = .; + .bss : { + *(.bss COMMON) + } + BSS_SECTION_END = .; + + RODATA_SECTION = .; + .rodata : { + *(.rodata) + } + RODATA_SECTION_END = .; + + . = ALIGN(4); +} diff --git a/patchbins/firmprot/meta/cfw_version b/patchbins/firmprot/meta/cfw_version new file mode 100644 index 0000000..573541a --- /dev/null +++ b/patchbins/firmprot/meta/cfw_version @@ -0,0 +1 @@ +0 diff --git a/patchbins/firmprot/meta/deps b/patchbins/firmprot/meta/deps new file mode 100644 index 0000000..b0047fa --- /dev/null +++ b/patchbins/firmprot/meta/deps @@ -0,0 +1 @@ +None diff --git a/patchbins/firmprot/meta/desc b/patchbins/firmprot/meta/desc new file mode 100644 index 0000000..adf29f1 --- /dev/null +++ b/patchbins/firmprot/meta/desc @@ -0,0 +1 @@ +Prints "Hello World!" diff --git a/patchbins/firmprot/meta/name b/patchbins/firmprot/meta/name new file mode 100644 index 0000000..e3dac2c --- /dev/null +++ b/patchbins/firmprot/meta/name @@ -0,0 +1 @@ +Example Patch diff --git a/patchbins/firmprot/meta/patch_version b/patchbins/firmprot/meta/patch_version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/firmprot/meta/patch_version @@ -0,0 +1 @@ +1 diff --git a/patchbins/firmprot/meta/title b/patchbins/firmprot/meta/title new file mode 100644 index 0000000..8380236 --- /dev/null +++ b/patchbins/firmprot/meta/title @@ -0,0 +1 @@ +Native diff --git a/patchbins/firmprot/meta/uuid b/patchbins/firmprot/meta/uuid new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/firmprot/meta/uuid @@ -0,0 +1 @@ +1 diff --git a/patchbins/firmprot/src/exported.h b/patchbins/firmprot/src/exported.h new file mode 100644 index 0000000..9c102ae --- /dev/null +++ b/patchbins/firmprot/src/exported.h @@ -0,0 +1,25 @@ +#ifndef EXPORTED_H +#define EXPORTED_H + +#define stdout (void*)0 +#define stderr (void*)1 + +extern uint8_t* memory_offset; +extern uint32_t* memory_len; + +extern int strlen(const char *string); +extern int isprint(char c); +extern void memcpy(void *dest, const void *src, size_t size); +extern void memmove(void *dest, const void *src, size_t size); +extern void memset(void *dest, const int filler, size_t size); +extern int memcmp(const void *buf1, const void *buf2, const size_t size); +extern void strncpy(void *dest, const void *src, const size_t size); +extern int strncmp(const void *buf1, const void *buf2, const size_t size); +extern int atoi(const char *str); +extern uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen); + +extern void putc(void* buf, const int c); +extern void puts(void* buf, const char *string); +extern void fprintf(void* channel, const char* format, ...); + +#endif diff --git a/patchbins/firmprot/src/link_table.s b/patchbins/firmprot/src/link_table.s new file mode 100644 index 0000000..6774354 --- /dev/null +++ b/patchbins/firmprot/src/link_table.s @@ -0,0 +1,43 @@ +.section .text.table +.align 4 + +.macro stub name + .global \name + \name : + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.endm + +.global MAGIC_START +MAGIC_START: + .byte 0xc0 + .byte 0x9b + .byte 0xe5 + .byte 0x1c + +// Memory to patch as specified by the header. (uint8_t*) +stub memory_offset + +// Size of memory offset. (uint32_t*) +stub memory_len + +// Exported functions. + +// memory.c +stub strlen +stub isprint +stub memcpy +stub memmove +stub memset +stub memcmp +stub strncpy +stub strncmp +stub atoi +stub memfind + +// draw.c +stub putc +stub puts +stub fprintf diff --git a/patchbins/firmprot/src/main.c b/patchbins/firmprot/src/main.c new file mode 100644 index 0000000..93c2b77 --- /dev/null +++ b/patchbins/firmprot/src/main.c @@ -0,0 +1,36 @@ +#include +#include +#include "exported.h" + +int main() { + //Look for signature checks + uint8_t pat1[] = {0xC0, 0x1C, 0x76, 0xE7}; + uint8_t pat2[] = {0xB5, 0x22, 0x4D, 0x0C}; + + uint8_t *firm_mem = (uint8_t*)memory_offset; + uint32_t size = *(uint32_t*)memory_len; + + uint8_t *off = memfind(firm_mem, size, pat1, 4); + uint8_t *off2 = memfind(firm_mem, size, pat2, 4) - 1; + + if (off == NULL) { + fprintf(stderr, "Signature patch failed on P0.\n"); + return 1; // Failed to find sigpatch. Ugh. + } + + if (off2 == NULL) { + fprintf(stderr, "Signature patch failed on P1.\n"); + return 2; // Failed to find sigpatch. Ugh. + } + + fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off); + fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2); + + uint8_t sigpatch[] = {0x00, 0x20, 0x70, 0x47}; + + memcpy(off, sigpatch, 2); + memcpy(off2, sigpatch, 4); + fprintf(stderr, "Signature patch succeded.\n"); + + return 0; +} diff --git a/patchbins/firmprot/src/patcher.c b/patchbins/firmprot/src/patcher.c new file mode 100644 index 0000000..e5cf3c7 --- /dev/null +++ b/patchbins/firmprot/src/patcher.c @@ -0,0 +1,171 @@ +#include +#include "std/unused.h" +#include "std/memory.h" +#include "firm/firm.h" +#include "config.h" +#include "common.h" + +uint32_t wait_key(); + +// A portion of this file is inherited from Luma3DS. +/* +u16 *getFirmWrite(u8 *pos, u32 size) { + //Look for FIRM writing code + u8 *const off = memsearch(pos, "exe:", size, 4); + const u8 pattern[] = {0x00, 0x28, 0x01, 0xDA}; + + return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4); +} + +u16 *getFirmWriteSafe(u8 *pos, u32 size) { + //Look for FIRM writing code + const u8 pattern[] = {0x04, 0x1E, 0x1D, 0xDB}; + + return (u16 *)memsearch(pos, pattern, size, 4); +} + +u32 getLoader(u8 *pos, u32 *loaderSize) { + u8 *off = pos; + u32 size; + + while(1) + { + size = *(u32 *)(off + 0x104) * 0x200; + if(*(u32 *)(off + 0x200) == 0x64616F6C) break; + off += size; + } + + *loaderSize = size; + + return (u32)(off - pos); +} + + +// patch_location = (void *)((uintptr_t)firm + section->offset + (version->offset - section->address)); + +u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr) +{ + u8 *off = memsearch(pos, "ess9", size, 4); + + *process9Size = *(u32 *)(off - 0x60) * 0x200; + *process9MemAddr = *(u32 *)(off + 0xC); + + //Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size) + return off - 0x204 + (*(u32 *)(off - 0x64) * 0x200) + 0x200; +} +*/ + +int patch_signatures() { + //Look for signature checks + + uint8_t pat1[] = {0xC0, 0x1C, 0x76, 0xE7}; + uint8_t pat2[] = {0xB5, 0x22, 0x4D, 0x0C}; + + uint8_t *firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + uint32_t size = firm_p9_exefs->fileHeaders[0].size; + + uint8_t *off = memfind(firm_mem, size, pat1, 4); + uint8_t *off2 = memfind(firm_mem, size, pat2, 4) - 1; + + if (off == NULL) { + fprintf(stderr, "Signature patch failed on P0.\n"); + return 1; // Failed to find sigpatch. Ugh. + } + + if (off2 == NULL) { + fprintf(stderr, "Signature patch failed on P1.\n"); + return 2; // Failed to find sigpatch. Ugh. + } + + fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off); + fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2); + + uint8_t sigpatch[] = {0x00, 0x20, 0x70, 0x47}; + + memcpy(off, sigpatch, 2); + memcpy(off2, sigpatch, 4); + fprintf(stderr, "Signature patch succeded.\n"); + + return 0; +} + +int patch_firmprot() { + uint8_t *firm_mem = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + uint32_t size = firm_p9_exefs->fileHeaders[0].size; + + //Look for FIRM writing code + uint8_t* off = memfind(firm_mem, size, (uint8_t*)"exe:", 4); + + if(off == NULL) { + fprintf(stderr, "Couldn't find 'exe:' string.\n"); + return 1; + } + + fprintf(stderr, "Firmprot: 'exe:' string @ %x\n", (uint32_t)off); + + uint8_t pattern[] = {0x00, 0x28, 0x01, 0xDA}; + + uint8_t* firmprot = memfind(off - 0x100, 0x100, pattern, 4); + + if(firmprot == NULL) { + fprintf(stderr, "Couldn't find firmprot code.\n"); + return 2; + } + + fprintf(stderr, "Firmprot: %x\n", (uint32_t)firmprot); + + uint8_t patch[] = {0x00, 0x20, 0xC0, 0x46}; + memcpy(firmprot, patch, 4); + + fprintf(stderr, "Applied firmprot patch.\n"); + + return 0; +} + +void wait() { + if (config.options[OPTION_TRACE]) { + fprintf(stderr, "Pausing because trace is on.\n"); + wait_key(); + } +} + +int patch_firm_all() { + // Use builtin signature patcher? + + fprintf(stderr, "Sigpatch: %s\n", ((config.options[OPTION_SIGPATCH]) ? "yes" : "no" )); + fprintf(stderr, "Protect: %s\n", ((config.options[OPTION_FIRMPROT]) ? "yes" : "no" )); + + wait(); + + if (config.options[OPTION_SIGPATCH]) { + if(patch_signatures()) { + abort("Fatal. Sigpatch has failed."); + } + } + + wait(); + + if (config.options[OPTION_FIRMPROT]) { + if(patch_firmprot()) { + abort("Fatal. Firmprot has failed."); + } + } + + wait(); + + // Replace loader? + if (config.options[OPTION_LOADER]) { + // Yes. + + // This requires OPTION_SIGPATCH. + } + + // Use ARM9 hook thread? + if (config.options[OPTION_ARM9THREAD]) { + // Yes. + + // FIXME - NYI + } + + return 0; +} diff --git a/patchbins/firmprot/src/start.s b/patchbins/firmprot/src/start.s new file mode 100644 index 0000000..33e1695 --- /dev/null +++ b/patchbins/firmprot/src/start.s @@ -0,0 +1,6 @@ +.section .text.start +.align 4 +.global _start +_start: + bl main + bx lr @ return from patch. diff --git a/patchbins/firmprot/tool/compile_header.c b/patchbins/firmprot/tool/compile_header.c new file mode 100644 index 0000000..bf8b2ad --- /dev/null +++ b/patchbins/firmprot/tool/compile_header.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +#include "../../../source/patch_format.h" + +void read_file_u64(char* name, uint64_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%llu", to); + fclose(hdl); +} + + +void read_file_u32(char* name, uint32_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%u", to); + fclose(hdl); +} + +void read_str(char* name, char* to, size_t len) { + FILE* hdl = fopen(name, "rb"); + int r = fread(to, 1, len-1, hdl); + fclose(hdl); +} + +uint32_t size = 0; + +uint8_t* read_file_mem(char* name) { + FILE* hdl = fopen(name, "rb"); + + fseek(hdl, 0, SEEK_END); + size = ftell(hdl); + rewind(hdl); + + uint8_t* mem = malloc(size); + memset(mem, 0, size); + + int r = fread(mem, 1, size, hdl); + fclose(hdl); + + printf("%d\n", size); + + return mem; +} + +int main(int c, char** v) { + struct system_patch patch; + int at = 0; + + memset(&patch, 0, sizeof(patch)); + + // Set magic. + patch.magic[0] = 'A'; + patch.magic[1] = 'I'; + patch.magic[2] = 'D'; + patch.magic[3] = 'A'; + + read_file_u32("meta/patch_version", & patch.patch_ver); + read_file_u32("meta/cfw_version", & patch.load_ver); + + read_file_u64("meta/uuid", & patch.patch_id); + read_file_u64("meta/title", & patch.tid); + + read_str("meta/name", patch.name, sizeof(patch.name)); + read_str("meta/desc", patch.desc, sizeof(patch.desc)); + + uint8_t* code = read_file_mem("out/patch.bin"); + + patch.patch_size = size; + + FILE* out = fopen("out/patch.vco", "wb"); + fwrite(&patch, 1, sizeof(patch), out); + fwrite(code, 1, patch.patch_size, out); + fclose(out); + + free(code); + + printf("Ver: %u\n" + "CFW: %u\n" + "UUID: %llu\n" + "TID: %llu\n" + "Name: %s\n" + "Desc: %s\n" + "Size: %u\n", + patch.patch_ver, patch.load_ver, patch.patch_id, + patch.tid, patch.name, patch.desc, patch.patch_size); + + return 0; +} diff --git a/patchbins/signatures/Makefile b/patchbins/signatures/Makefile new file mode 100644 index 0000000..7205e8a --- /dev/null +++ b/patchbins/signatures/Makefile @@ -0,0 +1,60 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +PATH := $(PATH):$(DEVKITARM)/bin + +HOST_CC := gcc + +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +LD := arm-none-eabi-ld +OC := arm-none-eabi-objcopy + +dir_source := src +dir_build := build +dir_out := out + +ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te +CFLAGS := -MMD -MP -Wall -Wextra -Werror -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" +FLAGS := dir_out=$(abspath $(dir_out)) --no-print-directory +LDFLAGS := -nostdlib -Wl,-z,defs -lgcc + +objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ + $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ + $(call rwildcard, $(dir_source), *.s *.c))) + +.PHONY: all +all: patchbin + +.PHONY: patchbin +patchbin: tool $(dir_out)/patch.bin + ./compile_header + +.PHONY: tool +tool: + $(HOST_CC) -o compile_header tool/compile_header.c + + +.PHONY: clean +clean: + rm -rf $(dir_out) $(dir_build) compile_header + +.PHONY: $(dir_out)/patch.bin +$(dir_out)/patch.bin: $(dir_build)/main.bin + @mkdir -p "$(dir_out)" + @cp -av $< $@ + +$(dir_build)/main.bin: $(dir_build)/main.elf + $(OC) -S -O binary $< $@ + +$(dir_build)/main.elf: $(objects_cfw) + $(CC) -T linker.ld $(OUTPUT_OPTION) $^ $(LDFLAGS) + +$(dir_build)/%.o: $(dir_source)/%.c + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.s) $(OUTPUT_OPTION) $< + +include $(call rwildcard, $(dir_build), *.d) diff --git a/patchbins/signatures/linker.ld b/patchbins/signatures/linker.ld new file mode 100644 index 0000000..7d6129b --- /dev/null +++ b/patchbins/signatures/linker.ld @@ -0,0 +1,59 @@ +/* This memory map is mainly to assist in doing stuff in code. +MEMORY +{ + INSTRUCTION_TCM (rw) : ORIGIN = 0x00000000, LENGTH = 0x08000000 + ARM_INTERNAL (rw) : ORIGIN = 0x08000000, LENGTH = 0x00100000 + NEW_INTERNAL (rw) : ORIGIN = 0x08100000, LENGTH = 0x00080000 + IO_MEMORY (rw) : ORIGIN = 0x10000000, LENGTH = 0x08000000 + VRAM (rw) : ORIGIN = 0x18000000, LENGTH = 0x00600000 + DSP_MEMORY (rw) : ORIGIN = 0x1FF00000, LENGTH = 0x00080000 + AXI_WRAM (rw) : ORIGIN = 0x1FF80000, LENGTH = 0x00080000 + FCRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x08000000 + NEW_FCRAM (rwx) : ORIGIN = 0x28000000, LENGTH = 0x08000000 + DATA_TCM (rw) : ORIGIN = 0xFFF00000, LENGTH = 0x00004000 + BOOTROM (rw) : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 +} */ + +ENTRY(_start) +SECTIONS +{ + . = 0x24400000; + + START_SECTION = .; + .text.start : { + *(.text.start) + } + START_SECTION_END = .; + + TABLE_SECTION = .; + .text.table : { + *(.text.table) + } + TABLE_SECTION_END = .; + + TEXT_SECTION = .; + .text : { + *(.text) + } + TEXT_SECTION_END = .; + + DATA_SECTION = .; + .data : { + *(.data) + } + DATA_SECTION_END = .; + + BSS_SECTION = .; + .bss : { + *(.bss COMMON) + } + BSS_SECTION_END = .; + + RODATA_SECTION = .; + .rodata : { + *(.rodata) + } + RODATA_SECTION_END = .; + + . = ALIGN(4); +} diff --git a/patchbins/signatures/meta/cfw_version b/patchbins/signatures/meta/cfw_version new file mode 100644 index 0000000..573541a --- /dev/null +++ b/patchbins/signatures/meta/cfw_version @@ -0,0 +1 @@ +0 diff --git a/patchbins/signatures/meta/deps b/patchbins/signatures/meta/deps new file mode 100644 index 0000000..b0047fa --- /dev/null +++ b/patchbins/signatures/meta/deps @@ -0,0 +1 @@ +None diff --git a/patchbins/signatures/meta/desc b/patchbins/signatures/meta/desc new file mode 100644 index 0000000..8496ff8 --- /dev/null +++ b/patchbins/signatures/meta/desc @@ -0,0 +1 @@ +Patches signatures in NATIVE_FIRM. diff --git a/patchbins/signatures/meta/name b/patchbins/signatures/meta/name new file mode 100644 index 0000000..25dc00f --- /dev/null +++ b/patchbins/signatures/meta/name @@ -0,0 +1 @@ +NATIVE_FIRM Signature Patch diff --git a/patchbins/signatures/meta/patch_version b/patchbins/signatures/meta/patch_version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/signatures/meta/patch_version @@ -0,0 +1 @@ +1 diff --git a/patchbins/signatures/meta/title b/patchbins/signatures/meta/title new file mode 100644 index 0000000..8380236 --- /dev/null +++ b/patchbins/signatures/meta/title @@ -0,0 +1 @@ +Native diff --git a/patchbins/signatures/meta/uuid b/patchbins/signatures/meta/uuid new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/signatures/meta/uuid @@ -0,0 +1 @@ +1 diff --git a/patchbins/signatures/src/exported.h b/patchbins/signatures/src/exported.h new file mode 100644 index 0000000..9c102ae --- /dev/null +++ b/patchbins/signatures/src/exported.h @@ -0,0 +1,25 @@ +#ifndef EXPORTED_H +#define EXPORTED_H + +#define stdout (void*)0 +#define stderr (void*)1 + +extern uint8_t* memory_offset; +extern uint32_t* memory_len; + +extern int strlen(const char *string); +extern int isprint(char c); +extern void memcpy(void *dest, const void *src, size_t size); +extern void memmove(void *dest, const void *src, size_t size); +extern void memset(void *dest, const int filler, size_t size); +extern int memcmp(const void *buf1, const void *buf2, const size_t size); +extern void strncpy(void *dest, const void *src, const size_t size); +extern int strncmp(const void *buf1, const void *buf2, const size_t size); +extern int atoi(const char *str); +extern uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen); + +extern void putc(void* buf, const int c); +extern void puts(void* buf, const char *string); +extern void fprintf(void* channel, const char* format, ...); + +#endif diff --git a/patchbins/signatures/src/link_table.s b/patchbins/signatures/src/link_table.s new file mode 100644 index 0000000..6774354 --- /dev/null +++ b/patchbins/signatures/src/link_table.s @@ -0,0 +1,43 @@ +.section .text.table +.align 4 + +.macro stub name + .global \name + \name : + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.endm + +.global MAGIC_START +MAGIC_START: + .byte 0xc0 + .byte 0x9b + .byte 0xe5 + .byte 0x1c + +// Memory to patch as specified by the header. (uint8_t*) +stub memory_offset + +// Size of memory offset. (uint32_t*) +stub memory_len + +// Exported functions. + +// memory.c +stub strlen +stub isprint +stub memcpy +stub memmove +stub memset +stub memcmp +stub strncpy +stub strncmp +stub atoi +stub memfind + +// draw.c +stub putc +stub puts +stub fprintf diff --git a/patchbins/signatures/src/main.c b/patchbins/signatures/src/main.c new file mode 100644 index 0000000..93c2b77 --- /dev/null +++ b/patchbins/signatures/src/main.c @@ -0,0 +1,36 @@ +#include +#include +#include "exported.h" + +int main() { + //Look for signature checks + uint8_t pat1[] = {0xC0, 0x1C, 0x76, 0xE7}; + uint8_t pat2[] = {0xB5, 0x22, 0x4D, 0x0C}; + + uint8_t *firm_mem = (uint8_t*)memory_offset; + uint32_t size = *(uint32_t*)memory_len; + + uint8_t *off = memfind(firm_mem, size, pat1, 4); + uint8_t *off2 = memfind(firm_mem, size, pat2, 4) - 1; + + if (off == NULL) { + fprintf(stderr, "Signature patch failed on P0.\n"); + return 1; // Failed to find sigpatch. Ugh. + } + + if (off2 == NULL) { + fprintf(stderr, "Signature patch failed on P1.\n"); + return 2; // Failed to find sigpatch. Ugh. + } + + fprintf(stderr, "Signatures[0]: 0x%x\n", (uint32_t)off); + fprintf(stderr, "Signatures[1]: 0x%x\n", (uint32_t)off2); + + uint8_t sigpatch[] = {0x00, 0x20, 0x70, 0x47}; + + memcpy(off, sigpatch, 2); + memcpy(off2, sigpatch, 4); + fprintf(stderr, "Signature patch succeded.\n"); + + return 0; +} diff --git a/patchbins/signatures/src/start.s b/patchbins/signatures/src/start.s new file mode 100644 index 0000000..33e1695 --- /dev/null +++ b/patchbins/signatures/src/start.s @@ -0,0 +1,6 @@ +.section .text.start +.align 4 +.global _start +_start: + bl main + bx lr @ return from patch. diff --git a/patchbins/signatures/tool/compile_header.c b/patchbins/signatures/tool/compile_header.c new file mode 100644 index 0000000..bf8b2ad --- /dev/null +++ b/patchbins/signatures/tool/compile_header.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +#include "../../../source/patch_format.h" + +void read_file_u64(char* name, uint64_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%llu", to); + fclose(hdl); +} + + +void read_file_u32(char* name, uint32_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%u", to); + fclose(hdl); +} + +void read_str(char* name, char* to, size_t len) { + FILE* hdl = fopen(name, "rb"); + int r = fread(to, 1, len-1, hdl); + fclose(hdl); +} + +uint32_t size = 0; + +uint8_t* read_file_mem(char* name) { + FILE* hdl = fopen(name, "rb"); + + fseek(hdl, 0, SEEK_END); + size = ftell(hdl); + rewind(hdl); + + uint8_t* mem = malloc(size); + memset(mem, 0, size); + + int r = fread(mem, 1, size, hdl); + fclose(hdl); + + printf("%d\n", size); + + return mem; +} + +int main(int c, char** v) { + struct system_patch patch; + int at = 0; + + memset(&patch, 0, sizeof(patch)); + + // Set magic. + patch.magic[0] = 'A'; + patch.magic[1] = 'I'; + patch.magic[2] = 'D'; + patch.magic[3] = 'A'; + + read_file_u32("meta/patch_version", & patch.patch_ver); + read_file_u32("meta/cfw_version", & patch.load_ver); + + read_file_u64("meta/uuid", & patch.patch_id); + read_file_u64("meta/title", & patch.tid); + + read_str("meta/name", patch.name, sizeof(patch.name)); + read_str("meta/desc", patch.desc, sizeof(patch.desc)); + + uint8_t* code = read_file_mem("out/patch.bin"); + + patch.patch_size = size; + + FILE* out = fopen("out/patch.vco", "wb"); + fwrite(&patch, 1, sizeof(patch), out); + fwrite(code, 1, patch.patch_size, out); + fclose(out); + + free(code); + + printf("Ver: %u\n" + "CFW: %u\n" + "UUID: %llu\n" + "TID: %llu\n" + "Name: %s\n" + "Desc: %s\n" + "Size: %u\n", + patch.patch_ver, patch.load_ver, patch.patch_id, + patch.tid, patch.name, patch.desc, patch.patch_size); + + return 0; +} diff --git a/patchbins/template/Makefile b/patchbins/template/Makefile new file mode 100644 index 0000000..758faed --- /dev/null +++ b/patchbins/template/Makefile @@ -0,0 +1,60 @@ +rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) + +PATH := $(PATH):$(DEVKITARM)/bin + +HOST_CC := gcc + +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +LD := arm-none-eabi-ld +OC := arm-none-eabi-objcopy + +dir_source := src +dir_build := build +dir_out := out + +ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te +CFLAGS := -MMD -MP -Wall -Wextra -Werror -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" +FLAGS := dir_out=$(abspath $(dir_out)) --no-print-directory +LDFLAGS := -nostdlib -Wl,-z,defs + +objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ + $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ + $(call rwildcard, $(dir_source), *.s *.c))) + +.PHONY: all +all: patchbin + +.PHONY: patchbin +patchbin: tool $(dir_out)/patch.bin + ./compile_header + +.PHONY: tool +tool: + $(HOST_CC) -o compile_header tool/compile_header.c + + +.PHONY: clean +clean: + rm -rf $(dir_out) $(dir_build) compile_header + +.PHONY: $(dir_out)/patch.bin +$(dir_out)/patch.bin: $(dir_build)/main.bin + @mkdir -p "$(dir_out)" + @cp -av $< $@ + +$(dir_build)/main.bin: $(dir_build)/main.elf + $(OC) -S -O binary $< $@ + +$(dir_build)/main.elf: $(objects_cfw) + $(CC) -T linker.ld $(OUTPUT_OPTION) $^ $(LDFLAGS) + +$(dir_build)/%.o: $(dir_source)/%.c + @mkdir -p "$(@D)" + $(COMPILE.c) $(OUTPUT_OPTION) $< + +$(dir_build)/%.o: $(dir_source)/%.s + @mkdir -p "$(@D)" + $(COMPILE.s) $(OUTPUT_OPTION) $< + +include $(call rwildcard, $(dir_build), *.d) diff --git a/patchbins/template/linker.ld b/patchbins/template/linker.ld new file mode 100644 index 0000000..7d6129b --- /dev/null +++ b/patchbins/template/linker.ld @@ -0,0 +1,59 @@ +/* This memory map is mainly to assist in doing stuff in code. +MEMORY +{ + INSTRUCTION_TCM (rw) : ORIGIN = 0x00000000, LENGTH = 0x08000000 + ARM_INTERNAL (rw) : ORIGIN = 0x08000000, LENGTH = 0x00100000 + NEW_INTERNAL (rw) : ORIGIN = 0x08100000, LENGTH = 0x00080000 + IO_MEMORY (rw) : ORIGIN = 0x10000000, LENGTH = 0x08000000 + VRAM (rw) : ORIGIN = 0x18000000, LENGTH = 0x00600000 + DSP_MEMORY (rw) : ORIGIN = 0x1FF00000, LENGTH = 0x00080000 + AXI_WRAM (rw) : ORIGIN = 0x1FF80000, LENGTH = 0x00080000 + FCRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x08000000 + NEW_FCRAM (rwx) : ORIGIN = 0x28000000, LENGTH = 0x08000000 + DATA_TCM (rw) : ORIGIN = 0xFFF00000, LENGTH = 0x00004000 + BOOTROM (rw) : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000 +} */ + +ENTRY(_start) +SECTIONS +{ + . = 0x24400000; + + START_SECTION = .; + .text.start : { + *(.text.start) + } + START_SECTION_END = .; + + TABLE_SECTION = .; + .text.table : { + *(.text.table) + } + TABLE_SECTION_END = .; + + TEXT_SECTION = .; + .text : { + *(.text) + } + TEXT_SECTION_END = .; + + DATA_SECTION = .; + .data : { + *(.data) + } + DATA_SECTION_END = .; + + BSS_SECTION = .; + .bss : { + *(.bss COMMON) + } + BSS_SECTION_END = .; + + RODATA_SECTION = .; + .rodata : { + *(.rodata) + } + RODATA_SECTION_END = .; + + . = ALIGN(4); +} diff --git a/patchbins/template/meta/cfw_version b/patchbins/template/meta/cfw_version new file mode 100644 index 0000000..573541a --- /dev/null +++ b/patchbins/template/meta/cfw_version @@ -0,0 +1 @@ +0 diff --git a/patchbins/template/meta/deps b/patchbins/template/meta/deps new file mode 100644 index 0000000..b0047fa --- /dev/null +++ b/patchbins/template/meta/deps @@ -0,0 +1 @@ +None diff --git a/patchbins/template/meta/desc b/patchbins/template/meta/desc new file mode 100644 index 0000000..adf29f1 --- /dev/null +++ b/patchbins/template/meta/desc @@ -0,0 +1 @@ +Prints "Hello World!" diff --git a/patchbins/template/meta/name b/patchbins/template/meta/name new file mode 100644 index 0000000..e3dac2c --- /dev/null +++ b/patchbins/template/meta/name @@ -0,0 +1 @@ +Example Patch diff --git a/patchbins/template/meta/patch_version b/patchbins/template/meta/patch_version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/template/meta/patch_version @@ -0,0 +1 @@ +1 diff --git a/patchbins/template/meta/title b/patchbins/template/meta/title new file mode 100644 index 0000000..8380236 --- /dev/null +++ b/patchbins/template/meta/title @@ -0,0 +1 @@ +Native diff --git a/patchbins/template/meta/uuid b/patchbins/template/meta/uuid new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/patchbins/template/meta/uuid @@ -0,0 +1 @@ +1 diff --git a/patchbins/template/src/exported.h b/patchbins/template/src/exported.h new file mode 100644 index 0000000..9c102ae --- /dev/null +++ b/patchbins/template/src/exported.h @@ -0,0 +1,25 @@ +#ifndef EXPORTED_H +#define EXPORTED_H + +#define stdout (void*)0 +#define stderr (void*)1 + +extern uint8_t* memory_offset; +extern uint32_t* memory_len; + +extern int strlen(const char *string); +extern int isprint(char c); +extern void memcpy(void *dest, const void *src, size_t size); +extern void memmove(void *dest, const void *src, size_t size); +extern void memset(void *dest, const int filler, size_t size); +extern int memcmp(const void *buf1, const void *buf2, const size_t size); +extern void strncpy(void *dest, const void *src, const size_t size); +extern int strncmp(const void *buf1, const void *buf2, const size_t size); +extern int atoi(const char *str); +extern uint8_t* memfind (uint8_t *string, uint32_t stringlen, uint8_t *pat, uint32_t patlen); + +extern void putc(void* buf, const int c); +extern void puts(void* buf, const char *string); +extern void fprintf(void* channel, const char* format, ...); + +#endif diff --git a/patchbins/template/src/link_table.s b/patchbins/template/src/link_table.s new file mode 100644 index 0000000..9bdd5be --- /dev/null +++ b/patchbins/template/src/link_table.s @@ -0,0 +1,53 @@ +.section .text.table +.align 4 + +.macro stub name + .global \name + \name : + ldr pc, [pc, #-4] // Load the data after this to the PC. return will be before this call. + .byte 0 // Read; pc relative in arm mode is pc+8, so pc-4 is the correct offset + .byte 0 + .byte 0 + .byte 0 +.endm + +.macro ref name + .global \name + \name : + .byte 0 + .byte 0 + .byte 0 + .byte 0 +.endm + +.global MAGIC_START +MAGIC_START: + .byte 0xc0 + .byte 0x9b + .byte 0xe5 + .byte 0x1c + +// Memory to patch as specified by the header. (uint8_t*) +ref memory_offset + +// Size of memory offset. (uint32_t*) +ref memory_len + +// Exported functions. + +// memory.c +stub strlen +stub isprint +stub memcpy +stub memmove +stub memset +stub memcmp +stub strncpy +stub strncmp +stub atoi +stub memfind + +// draw.c +stub putc +stub puts +stub fprintf diff --git a/patchbins/template/src/main.c b/patchbins/template/src/main.c new file mode 100644 index 0000000..a790f75 --- /dev/null +++ b/patchbins/template/src/main.c @@ -0,0 +1,10 @@ +#include +#include +#include "exported.h" + +int main() { + // Your patch goes here. + fprintf(stderr, "Hi, I'm a patch!\n"); + + return 0; +} diff --git a/patchbins/template/src/start.s b/patchbins/template/src/start.s new file mode 100644 index 0000000..713b650 --- /dev/null +++ b/patchbins/template/src/start.s @@ -0,0 +1,8 @@ +.section .text.start +.align 4 +.global _start +_start: + stmdb sp!, {lr} + bl main + ldmia sp!, {lr} + bx lr // return from patch. diff --git a/patchbins/template/tool/compile_header.c b/patchbins/template/tool/compile_header.c new file mode 100644 index 0000000..bf8b2ad --- /dev/null +++ b/patchbins/template/tool/compile_header.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +#include "../../../source/patch_format.h" + +void read_file_u64(char* name, uint64_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%llu", to); + fclose(hdl); +} + + +void read_file_u32(char* name, uint32_t* to) { + FILE* hdl = fopen(name, "rb"); + fscanf(hdl, "%u", to); + fclose(hdl); +} + +void read_str(char* name, char* to, size_t len) { + FILE* hdl = fopen(name, "rb"); + int r = fread(to, 1, len-1, hdl); + fclose(hdl); +} + +uint32_t size = 0; + +uint8_t* read_file_mem(char* name) { + FILE* hdl = fopen(name, "rb"); + + fseek(hdl, 0, SEEK_END); + size = ftell(hdl); + rewind(hdl); + + uint8_t* mem = malloc(size); + memset(mem, 0, size); + + int r = fread(mem, 1, size, hdl); + fclose(hdl); + + printf("%d\n", size); + + return mem; +} + +int main(int c, char** v) { + struct system_patch patch; + int at = 0; + + memset(&patch, 0, sizeof(patch)); + + // Set magic. + patch.magic[0] = 'A'; + patch.magic[1] = 'I'; + patch.magic[2] = 'D'; + patch.magic[3] = 'A'; + + read_file_u32("meta/patch_version", & patch.patch_ver); + read_file_u32("meta/cfw_version", & patch.load_ver); + + read_file_u64("meta/uuid", & patch.patch_id); + read_file_u64("meta/title", & patch.tid); + + read_str("meta/name", patch.name, sizeof(patch.name)); + read_str("meta/desc", patch.desc, sizeof(patch.desc)); + + uint8_t* code = read_file_mem("out/patch.bin"); + + patch.patch_size = size; + + FILE* out = fopen("out/patch.vco", "wb"); + fwrite(&patch, 1, sizeof(patch), out); + fwrite(code, 1, patch.patch_size, out); + fclose(out); + + free(code); + + printf("Ver: %u\n" + "CFW: %u\n" + "UUID: %llu\n" + "TID: %llu\n" + "Name: %s\n" + "Desc: %s\n" + "Size: %u\n", + patch.patch_ver, patch.load_ver, patch.patch_id, + patch.tid, patch.name, patch.desc, patch.patch_size); + + return 0; +} diff --git a/source/firm/fcram.h b/source/firm/fcram.h index 4cf5126..e82a8ee 100644 --- a/source/firm/fcram.h +++ b/source/firm/fcram.h @@ -22,9 +22,6 @@ extern void *fcram_temp; #define FCRAM_AGB_FIRM_LOC (FCRAM_START + FCRAM_SPACING * 3) // patch.c -#define FCRAM_MEMORY_LOC (FCRAM_START + FCRAM_SPACING * 4) - -_UNUSED static uint8_t *memory_loc = (uint8_t *)FCRAM_MEMORY_LOC; -_UNUSED static void *current_memory_loc; +#define FCRAM_PATCHBIN_EXEC_LOC (FCRAM_START + FCRAM_SPACING * 4) #endif diff --git a/source/linker.c b/source/linker.c new file mode 100644 index 0000000..b727142 --- /dev/null +++ b/source/linker.c @@ -0,0 +1,57 @@ +#include "common.h" +#include "firm/fcram.h" + +int link_and_load_patchbin(char* path) { + fprintf(stderr, "Prep to relocate and execute patch.\n"); + + struct system_patch patch; + + fprintf(stderr, "Loading patch vco.\n"); + + // Load patch from path. + FILE* f = fopen(path, "r"); + fread(&patch, 1, sizeof(patch), f); + + fprintf(stderr, "Patch payload is %d bytes.\n", patch.patch_size); + + fread((uint8_t*)FCRAM_PATCHBIN_EXEC_LOC, 1, patch.patch_size, f); + + fclose(f); + + fprintf(stderr, "Finding relocation table.\n"); + // Now then...find the magical number. + uint8_t magic[] = { 0xc0, 0x9b, 0xe5, 0x1c }; + uint8_t* off = memfind((uint8_t*)FCRAM_PATCHBIN_EXEC_LOC, patch.patch_size, magic, 4); + + if (off == NULL) { + fprintf(stderr, "Relocation table missing. Abort.\n"); + return 1; + } + + fprintf(stderr, "Relocation table is at %x\n", (uint32_t)off); + + uint32_t* link_table = (uint32_t*)(off + 4); + + // memory.c + link_table[3] = (uint32_t)strlen; + link_table[5] = (uint32_t)isprint; + link_table[7] = (uint32_t)memcpy; + link_table[9] = (uint32_t)memmove; + link_table[11] = (uint32_t)memset; + link_table[13] = (uint32_t)memcmp; + link_table[15] = (uint32_t)strncpy; + link_table[17] = (uint32_t)strncmp; + link_table[19] = (uint32_t)atoi; + link_table[21] = (uint32_t)memfind; + + // draw.c + link_table[23] = (uint32_t)putc; + link_table[25] = (uint32_t)puts; + link_table[27] = (uint32_t)fprintf; + + fprintf(stderr, "Copied relocations. Running binary.\n"); + + int (*exec)() = (void*)FCRAM_PATCHBIN_EXEC_LOC ; + + return (*exec)(); +} diff --git a/source/menu.c b/source/menu.c index 1b68c47..53429f4 100644 --- a/source/menu.c +++ b/source/menu.c @@ -63,16 +63,16 @@ int menu_options() { "Inject Loader", "Enable ARM9 Thread", - "Autoboot", - "Silence debug output", - "Trace steps with (A)", + "Autoboot (NYI)", + "Silence debug output (NYI)", + "Pause for input as trace", - "Don't draw background color", - "Preserve current framebuffer", + "Don't draw background color (NYI)", + "Preserve current framebuffer (NYI)", "Hide Readme/Help from menu", - "Ignore dependencies", - "Allow enabling broken", + "Ignore dependencies (NYI)", + "Allow enabling broken (NYI)", }; const int menu_max = 11; diff --git a/source/patch_format.h b/source/patch_format.h index d5957cd..64f3a2a 100644 --- a/source/patch_format.h +++ b/source/patch_format.h @@ -67,7 +67,7 @@ struct system_patch { uint64_t depends[16]; // What patches need to be applied for this patch to be applied; as unique IDs uint32_t patch_size; // Size of the following patch data. - uint8_t patch_data[]; // The data for the patch. This is a sort of interpreted code...see below. +// uint8_t patch_data[]; // The data for the patch. This is a compiled binary for ARM9/11. } __attribute__((packed)); struct patch_opcode { diff --git a/source/patcher.c b/source/patcher.c index e5cf3c7..6bd196d 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -6,6 +6,7 @@ #include "common.h" uint32_t wait_key(); +int link_and_load_patchbin(char* path); // A portion of this file is inherited from Luma3DS. /* @@ -130,10 +131,14 @@ void wait() { } int patch_firm_all() { + link_and_load_patchbin(PATH_PATCHES "/patch.vco"); + + wait(); + // Use builtin signature patcher? fprintf(stderr, "Sigpatch: %s\n", ((config.options[OPTION_SIGPATCH]) ? "yes" : "no" )); - fprintf(stderr, "Protect: %s\n", ((config.options[OPTION_FIRMPROT]) ? "yes" : "no" )); + fprintf(stderr, "Protect: %s\n", ((config.options[OPTION_FIRMPROT]) ? "yes" : "no" )); wait(); -- 2.39.5