]> Chaos Git - corbenik/corbenik.git/commitdiff
Working on dynamic linker thing for patches (why not?)
authorroot <chaos.kagami@gmail.com>
Sun, 15 May 2016 04:53:27 +0000 (00:53 -0400)
committerroot <chaos.kagami@gmail.com>
Sun, 15 May 2016 04:53:27 +0000 (00:53 -0400)
49 files changed:
patchbins/README.txt [new file with mode: 0644]
patchbins/firmprot/Makefile [new file with mode: 0644]
patchbins/firmprot/linker.ld [new file with mode: 0644]
patchbins/firmprot/meta/cfw_version [new file with mode: 0644]
patchbins/firmprot/meta/deps [new file with mode: 0644]
patchbins/firmprot/meta/desc [new file with mode: 0644]
patchbins/firmprot/meta/name [new file with mode: 0644]
patchbins/firmprot/meta/patch_version [new file with mode: 0644]
patchbins/firmprot/meta/title [new file with mode: 0644]
patchbins/firmprot/meta/uuid [new file with mode: 0644]
patchbins/firmprot/src/exported.h [new file with mode: 0644]
patchbins/firmprot/src/link_table.s [new file with mode: 0644]
patchbins/firmprot/src/main.c [new file with mode: 0644]
patchbins/firmprot/src/patcher.c [new file with mode: 0644]
patchbins/firmprot/src/start.s [new file with mode: 0644]
patchbins/firmprot/tool/compile_header.c [new file with mode: 0644]
patchbins/signatures/Makefile [new file with mode: 0644]
patchbins/signatures/linker.ld [new file with mode: 0644]
patchbins/signatures/meta/cfw_version [new file with mode: 0644]
patchbins/signatures/meta/deps [new file with mode: 0644]
patchbins/signatures/meta/desc [new file with mode: 0644]
patchbins/signatures/meta/name [new file with mode: 0644]
patchbins/signatures/meta/patch_version [new file with mode: 0644]
patchbins/signatures/meta/title [new file with mode: 0644]
patchbins/signatures/meta/uuid [new file with mode: 0644]
patchbins/signatures/src/exported.h [new file with mode: 0644]
patchbins/signatures/src/link_table.s [new file with mode: 0644]
patchbins/signatures/src/main.c [new file with mode: 0644]
patchbins/signatures/src/start.s [new file with mode: 0644]
patchbins/signatures/tool/compile_header.c [new file with mode: 0644]
patchbins/template/Makefile [new file with mode: 0644]
patchbins/template/linker.ld [new file with mode: 0644]
patchbins/template/meta/cfw_version [new file with mode: 0644]
patchbins/template/meta/deps [new file with mode: 0644]
patchbins/template/meta/desc [new file with mode: 0644]
patchbins/template/meta/name [new file with mode: 0644]
patchbins/template/meta/patch_version [new file with mode: 0644]
patchbins/template/meta/title [new file with mode: 0644]
patchbins/template/meta/uuid [new file with mode: 0644]
patchbins/template/src/exported.h [new file with mode: 0644]
patchbins/template/src/link_table.s [new file with mode: 0644]
patchbins/template/src/main.c [new file with mode: 0644]
patchbins/template/src/start.s [new file with mode: 0644]
patchbins/template/tool/compile_header.c [new file with mode: 0644]
source/firm/fcram.h
source/linker.c [new file with mode: 0644]
source/menu.c
source/patch_format.h
source/patcher.c

diff --git a/patchbins/README.txt b/patchbins/README.txt
new file mode 100644 (file)
index 0000000..21b6567
--- /dev/null
@@ -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 (file)
index 0000000..e2f940b
--- /dev/null
@@ -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 (file)
index 0000000..7d6129b
--- /dev/null
@@ -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 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
diff --git a/patchbins/firmprot/meta/deps b/patchbins/firmprot/meta/deps
new file mode 100644 (file)
index 0000000..b0047fa
--- /dev/null
@@ -0,0 +1 @@
+None
diff --git a/patchbins/firmprot/meta/desc b/patchbins/firmprot/meta/desc
new file mode 100644 (file)
index 0000000..adf29f1
--- /dev/null
@@ -0,0 +1 @@
+Prints "Hello World!"
diff --git a/patchbins/firmprot/meta/name b/patchbins/firmprot/meta/name
new file mode 100644 (file)
index 0000000..e3dac2c
--- /dev/null
@@ -0,0 +1 @@
+Example Patch
diff --git a/patchbins/firmprot/meta/patch_version b/patchbins/firmprot/meta/patch_version
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/firmprot/meta/title b/patchbins/firmprot/meta/title
new file mode 100644 (file)
index 0000000..8380236
--- /dev/null
@@ -0,0 +1 @@
+Native
diff --git a/patchbins/firmprot/meta/uuid b/patchbins/firmprot/meta/uuid
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/firmprot/src/exported.h b/patchbins/firmprot/src/exported.h
new file mode 100644 (file)
index 0000000..9c102ae
--- /dev/null
@@ -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 (file)
index 0000000..6774354
--- /dev/null
@@ -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 (file)
index 0000000..93c2b77
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdint.h>
+#include <stddef.h>
+#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 (file)
index 0000000..e5cf3c7
--- /dev/null
@@ -0,0 +1,171 @@
+#include <stdint.h>
+#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 (file)
index 0000000..33e1695
--- /dev/null
@@ -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 (file)
index 0000000..bf8b2ad
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..7205e8a
--- /dev/null
@@ -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 (file)
index 0000000..7d6129b
--- /dev/null
@@ -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 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
diff --git a/patchbins/signatures/meta/deps b/patchbins/signatures/meta/deps
new file mode 100644 (file)
index 0000000..b0047fa
--- /dev/null
@@ -0,0 +1 @@
+None
diff --git a/patchbins/signatures/meta/desc b/patchbins/signatures/meta/desc
new file mode 100644 (file)
index 0000000..8496ff8
--- /dev/null
@@ -0,0 +1 @@
+Patches signatures in NATIVE_FIRM.
diff --git a/patchbins/signatures/meta/name b/patchbins/signatures/meta/name
new file mode 100644 (file)
index 0000000..25dc00f
--- /dev/null
@@ -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 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/signatures/meta/title b/patchbins/signatures/meta/title
new file mode 100644 (file)
index 0000000..8380236
--- /dev/null
@@ -0,0 +1 @@
+Native
diff --git a/patchbins/signatures/meta/uuid b/patchbins/signatures/meta/uuid
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/signatures/src/exported.h b/patchbins/signatures/src/exported.h
new file mode 100644 (file)
index 0000000..9c102ae
--- /dev/null
@@ -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 (file)
index 0000000..6774354
--- /dev/null
@@ -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 (file)
index 0000000..93c2b77
--- /dev/null
@@ -0,0 +1,36 @@
+#include <stdint.h>
+#include <stddef.h>
+#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 (file)
index 0000000..33e1695
--- /dev/null
@@ -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 (file)
index 0000000..bf8b2ad
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 (file)
index 0000000..758faed
--- /dev/null
@@ -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 (file)
index 0000000..7d6129b
--- /dev/null
@@ -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 (file)
index 0000000..573541a
--- /dev/null
@@ -0,0 +1 @@
+0
diff --git a/patchbins/template/meta/deps b/patchbins/template/meta/deps
new file mode 100644 (file)
index 0000000..b0047fa
--- /dev/null
@@ -0,0 +1 @@
+None
diff --git a/patchbins/template/meta/desc b/patchbins/template/meta/desc
new file mode 100644 (file)
index 0000000..adf29f1
--- /dev/null
@@ -0,0 +1 @@
+Prints "Hello World!"
diff --git a/patchbins/template/meta/name b/patchbins/template/meta/name
new file mode 100644 (file)
index 0000000..e3dac2c
--- /dev/null
@@ -0,0 +1 @@
+Example Patch
diff --git a/patchbins/template/meta/patch_version b/patchbins/template/meta/patch_version
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/template/meta/title b/patchbins/template/meta/title
new file mode 100644 (file)
index 0000000..8380236
--- /dev/null
@@ -0,0 +1 @@
+Native
diff --git a/patchbins/template/meta/uuid b/patchbins/template/meta/uuid
new file mode 100644 (file)
index 0000000..d00491f
--- /dev/null
@@ -0,0 +1 @@
+1
diff --git a/patchbins/template/src/exported.h b/patchbins/template/src/exported.h
new file mode 100644 (file)
index 0000000..9c102ae
--- /dev/null
@@ -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 (file)
index 0000000..9bdd5be
--- /dev/null
@@ -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 (file)
index 0000000..a790f75
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdint.h>
+#include <stddef.h>
+#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 (file)
index 0000000..713b650
--- /dev/null
@@ -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 (file)
index 0000000..bf8b2ad
--- /dev/null
@@ -0,0 +1,91 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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;
+}
index 4cf51269b74ac6eeaae08b443019d358e58bbfc7..e82a8ee0da150dd19674667c3326b793eb09f6ca 100644 (file)
@@ -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 (file)
index 0000000..b727142
--- /dev/null
@@ -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)();
+}
index 1b68c47b841b7b143a6a3697353bd0756a91111a..53429f4c93eee529844c2767f7565078a8585ccb 100644 (file)
@@ -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;
 
index d5957cdf8d15d9f7faabc4a577618b4d907f32ed..64f3a2aaeae3c0298ed266ac7dc2fdd815f489ed 100644 (file)
@@ -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 {
index e5cf3c73f01f2e07be52279fdd5c674005c722a3..6bd196d8dfa56c477aa567c3ae2cb7b194fbbdd1 100644 (file)
@@ -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();