From: chaoskagami Date: Thu, 2 Jun 2016 10:38:27 +0000 (-0400) Subject: Partially implement the interpreter (works for sigs) X-Git-Tag: stable-1~16 X-Git-Url: https://chaos.moe/g/?a=commitdiff_plain;h=feab39316431f2fa7b27b338dc2717fa1e20152d;p=corbenik%2Fcorbenik.git Partially implement the interpreter (works for sigs) --- diff --git a/Makefile b/Makefile index 67a14d1..5f76877 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ dir_out := out REVISION := r$(shell git rev-list --count HEAD):$(shell git rev-parse HEAD | head -c8) ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te -CFLAGS := -MMD -MP -Wall -Wextra -Werror -fno-omit-frame-pointer -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" +CFLAGS := -MMD -MP -Wall -Wextra -Werror -fno-omit-frame-pointer -Os $(ASFLAGS) -fno-builtin -std=c11 -DVERSION=\"$(REVISION)\" -DBUFFER=1 FLAGS := dir_out=$(abspath $(dir_out)) --no-print-directory LDFLAGS := -nostdlib -Wl,-z,defs -lgcc -Wl,-Map,$(dir_build)/link.map @@ -29,7 +29,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) .PHONY: all -all: a9lh external +all: a9lh patch external .PHONY: full full: host/langemu.conf all @@ -38,6 +38,10 @@ full: host/langemu.conf all external: make -C external +.PHONY: patch +patch: + make -C patch + .PHONY: a9lh a9lh: $(dir_out)/arm9loaderhax.bin @@ -55,6 +59,7 @@ host/langemu.conf: clean: rm -f host/langemu.conf make -C external clean + make -C patch clean rm -rf $(dir_out) $(dir_build) .PHONY: $(dir_out)/arm9loaderhax.bin diff --git a/doc/bytecode.md b/doc/bytecode.md index 5bffbf4..e9747cc 100644 --- a/doc/bytecode.md +++ b/doc/bytecode.md @@ -91,11 +91,14 @@ test : 2 + size bytes : opcode 0x06 Pattern to test. jmp : 3 bytes : opcode 0x07 - Jumps to the Nth instruction within the bytecode, and + Jumps to offset instruction within the bytecode, and resumes execution from there. + Note that the assembler should be passed the number of instrcution + and will automatically calculate the offset needed. + : 2 bytes - Index to jump to. + Offset to jump to. rewind : 1 byte : opcode 0x08 Resets the location to the beginning of the space we're working off. diff --git a/doc/compiling.md b/doc/compiling.md index 0eacb7d..30aacc4 100644 --- a/doc/compiling.md +++ b/doc/compiling.md @@ -1,16 +1,17 @@ Cloning / Compilation -------------------------- -Okay, first thing's first. I can't support compiling on Windows. Use Linux. The repo abuses symbolic links, relies on certain software being present which isn't with devkitPro, and has host tools which are untested on Windows and require a native gcc (as in, mingw only.) +Okay, first thing's first. I can't support compiling on Windows. Use Linux. The repo abuses symbolic links, relies on certain software being present which isn't with devkitPro, and has host tools which are untested on Windows and require a native gcc (as in, mingw only.) Therefore, do NOT attempt to use windows to compile this. No, I will not port the build scripts to Windows. If you want to fix it without invasive changes, be my guest and make a PR. If I deem the maintenance cost too high, I'll tell you. -If you want to fix windows builds, be my guest. I'll merge it so long as it A) doesn't break my machine's builds and B) uses mingw/cygwin as the native compiler. No msvcisms will be allowed on my watch. +It may or may not compile with an OSX based cross compiler. I dunno. You'll need the following to compile: * git + * python2 * gcc (as in, host gcc) - * arm-none-eabi-gcc (as in, devkitarm OR baremetal gcc (the latter isn't well tested, but may work) - * a brain (hard requirement) + * arm-none-eabi-gcc (as in, devkitarm OR baremetal gcc (the latter isn't well tested, but may work. Compiling devkitPro using https://github.com/devkitPro/buildscripts is highly recommended.) + * bash (as /bin/bash) To clone: use `git clone --recursive`. Some parts of this CFW are submodules. diff --git a/doc/nonos.md b/doc/nonos.md index 524e584..e77b5ee 100644 --- a/doc/nonos.md +++ b/doc/nonos.md @@ -1,4 +1,4 @@ -Things I won't implement +Things I won't implement (for a number of reasons) ========================== * Memekey Support. @@ -13,18 +13,15 @@ I don't see this as a feature unless it's opt-in rather than opt-out or mandator * Gateway launcher dat -Screw off. Need I explain why? Do it yourself. No support will be offered to gateway users. You're paying for a piracy tool. Seriously, why? +Screw off. Do it yourself. No support will be offered to gateway users. You're paying for a piracy tool. Not to mention, I only integrate code I'm capable of testing safely, so this won't ever be a part of corbenik. * 3dsx -Get a9lh. Seriously. You might be able to use Brahma, but hell if I know. a9lh is the only supported method of running this, and no 3dsx launcher will be provided. +You might be able to use Brahma, but hell if I know. Either way, I'm not going to attempt to get stuff on menuhax since there's limits on version now. I recommend any menuhax users get a9lh. Not bugs ========= * CETK decryption -No, I can't fix this on a9lh. Here's how to do it; boot another CFW, go into system settings, then boot corbenik. You'll get the keys you need. This works with Cakes as well. After this, you'll never need a key again. - -Another thing to know is only NATIVE_FIRM is required to boot, so you can boot Corbenik without AGB and TWL suceeding, reboot from settings and they'll decrypt if the CETK is there. - +This has been removed from the FIRM decryptor, since it's unreliable on a9lh. I may re-add it someday. diff --git a/host/bytecode_asm.py b/host/bytecode_asm.py index 19e6116..f82e0df 100755 --- a/host/bytecode_asm.py +++ b/host/bytecode_asm.py @@ -205,10 +205,12 @@ with open(in_file, "r") as ins: data += struct.pack('I', len(title)) data += struct.pack('I', len(deps)) data += struct.pack('I', size) - for f in title: - data += bytearray.fromhex(f) - for f in deps: - data += pad_zero_r(bytearray.fromhex(f), 8) + if title: + for f in title: + data += bytearray.fromhex(f) + if deps: + for f in deps: + data += pad_zero_r(bytearray.fromhex(f), 8) data += bytecode writ.write(data) diff --git a/patch/Makefile b/patch/Makefile index 8d6fd62..b705764 100644 --- a/patch/Makefile +++ b/patch/Makefile @@ -1,5 +1,7 @@ .PHONY: all all: $(patsubst %.pco, %.vco, $(wildcard *.pco)) + mkdir -p ../out/corbenik/bin + cp *.vco ../out/corbenik/bin/ %.vco: %.pco ../host/bytecode_asm.py $< $@ diff --git a/patch/sig.pco b/patch/sig.pco index 73ea077..b952980 100644 --- a/patch/sig.pco +++ b/patch/sig.pco @@ -18,4 +18,5 @@ rewind # Pattern 2. find b5224d0c +back 01 set 00207047 diff --git a/source/firm/fcram.h b/source/firm/fcram.h index 5bd78ef..a91b608 100644 --- a/source/firm/fcram.h +++ b/source/firm/fcram.h @@ -26,7 +26,7 @@ extern void* fcram_temp; // 243 // patch.c -#define FCRAM_PATCHBIN_EXEC_LOC (FCRAM_START + FCRAM_SPACING * 4) +#define FCRAM_PATCH_LOC (FCRAM_START + FCRAM_SPACING * 4) // 244 // Throwaway temporary space. Don't expect it to stay sane. diff --git a/source/interp.c b/source/interp.c new file mode 100644 index 0000000..8031d42 --- /dev/null +++ b/source/interp.c @@ -0,0 +1,265 @@ +#include +#include "std/unused.h" +#include "std/memory.h" +#include "firm/firm.h" +#include "config.h" +#include "common.h" + +#define OP_NOP 0x00 +#define OP_REL 0x01 +#define OP_FIND 0x02 +#define OP_BACK 0x03 +#define OP_FWD 0x04 +#define OP_SET 0x05 +#define OP_TEST 0x06 +#define OP_JMP 0x07 +#define OP_REWIND 0x08 +#define OP_AND 0x09 +#define OP_TITLE 0x0A + +struct mode { + uint8_t* memory; + uint32_t size; +}; + +struct mode modes[19]; +int init_bytecode = 0; + +int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug) { + if (!init_bytecode) { + modes[0].memory = (uint8_t*)firm_loc; + modes[0].size = FCRAM_SPACING; // NATIVE_FIRM + + modes[1].memory = (uint8_t*)agb_firm_loc; + modes[1].size = FCRAM_SPACING; // AGB_FIRM + + modes[2].memory = (uint8_t*)twl_firm_loc; + modes[2].size = FCRAM_SPACING; // TWL_FIRM + + // NATIVE_FIRM Process9 (This is also the default mode.) + modes[3].memory = (uint8_t*)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + modes[3].size = firm_p9_exefs->fileHeaders[0].size; + // AGB_FIRM Process9 + modes[4].memory = (uint8_t*)agb_firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + modes[4].size = firm_p9_exefs->fileHeaders[0].size; + // TWL_FIRM Process9 + modes[5].memory = (uint8_t*)twl_firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset; + modes[5].size = firm_p9_exefs->fileHeaders[0].size; + + // NATIVE_FIRM Sect 0 + modes[6].memory = (uint8_t*)&firm_loc->section[0] + firm_loc->section[0].offset; + modes[6].size = firm_loc->section[0].size; + // NATIVE_FIRM Sect 1 + modes[7].memory = (uint8_t*)&firm_loc->section[1] + firm_loc->section[1].offset; + modes[7].size = firm_loc->section[1].size; + // NATIVE_FIRM Sect 2 + modes[8].memory = (uint8_t*)&firm_loc->section[2] + firm_loc->section[2].offset; + modes[8].size = firm_loc->section[2].size; + // NATIVE_FIRM Sect 3 + modes[9].memory = (uint8_t*)&firm_loc->section[3] + firm_loc->section[3].offset; + modes[9].size = firm_loc->section[3].size; + + // AGB_FIRM Sect 0 + modes[10].memory = (uint8_t*)&agb_firm_loc->section[0] + agb_firm_loc->section[0].offset; + modes[10].size = agb_firm_loc->section[0].size; + // AGB_FIRM Sect 1 + modes[11].memory = (uint8_t*)&agb_firm_loc->section[1] + agb_firm_loc->section[1].offset; + modes[11].size = agb_firm_loc->section[1].size; + // AGB_FIRM Sect 2 + modes[12].memory = (uint8_t*)&agb_firm_loc->section[2] + agb_firm_loc->section[2].offset; + modes[12].size = agb_firm_loc->section[2].size; + // AGB_FIRM Sect 3 + modes[13].memory = (uint8_t*)&agb_firm_loc->section[3] + agb_firm_loc->section[3].offset; + modes[13].size = agb_firm_loc->section[3].size; + + // TWL_FIRM Sect 0 + modes[14].memory = (uint8_t*)&twl_firm_loc->section[0] + twl_firm_loc->section[0].offset; + modes[14].size = twl_firm_loc->section[0].size; + // TWL_FIRM Sect 1 + modes[15].memory = (uint8_t*)&twl_firm_loc->section[1] + twl_firm_loc->section[1].offset; + modes[15].size = twl_firm_loc->section[1].size; + // TWL_FIRM Sect 2 + modes[16].memory = (uint8_t*)&twl_firm_loc->section[2] + twl_firm_loc->section[2].offset; + modes[16].size = twl_firm_loc->section[2].size; + // TWL_FIRM Sect 3 + modes[17].memory = (uint8_t*)&twl_firm_loc->section[3] + twl_firm_loc->section[3].offset; + modes[17].size = twl_firm_loc->section[3].size; + + // Loader (not valid in bootmode) + // modes[18] = { 0, 0 }; + + init_bytecode = 1; + } + + struct mode* current_mode = &modes[3]; + uint32_t offset = 0; + uint8_t test_was_false = 0; + + uint32_t set_mode = 0; + + uint32_t i; + + uint8_t* code = bytecode; + uint8_t* end = code + len; + while (code < end && code >= bytecode) { + switch(*code) { + case OP_NOP: + if (debug) + fprintf(stderr, "nop\n"); + code++; + test_was_false = 0; + break; + case OP_REL: // Change relativity. + if (debug) + fprintf(stderr, "rel\n"); + code++; + if (!test_was_false) + current_mode = &modes[*code]; + else + test_was_false = 0; + set_mode = *code; + code++; + break; + case OP_FIND: // Find pattern. + if (debug) + fprintf(stderr, "find\n"); + code += 2; + if (!test_was_false) { + offset = (uint32_t)memfind(current_mode->memory+offset, current_mode->size - offset, code, *(code-1)); + if ((uint8_t*)offset == NULL) { + // Error. Abort. + abort("Find opcode failed.\n"); + } else if (debug) { + fprintf(stderr, "Match @ %x\n", offset); + } + offset = offset - (uint32_t)current_mode->memory; + } else { + test_was_false = 0; + } + code += *(code-1); + break; + case OP_BACK: + if (debug) + fprintf(stderr, "back\n"); + code++; + if (!test_was_false) { + if (offset < *code) { + // Went out of bounds. Error. + abort("Back underflowed.\n"); + } + offset -= *code; + } else { + test_was_false = 0; + } + code++; + break; + case OP_FWD: + if (debug) + fprintf(stderr, "fwd\n"); + code++; + if (!test_was_false) { + offset += *code; + if (offset >= current_mode->size) { + // Went out of bounds. Error. + abort("Fwd overflowed.\n"); + } + } else { + test_was_false = 0; + } + code++; + break; + case OP_SET: // Set data. + if (debug) + fprintf(stderr, "set\n"); + code += 2; + if (!test_was_false) + memcpy(current_mode->memory+offset, code, *(code-1)); + else + test_was_false = 0; + offset += *(code-1); + code += *(code-1); + break; + case OP_TEST: // Test data. + if (debug) + fprintf(stderr, "test\n"); + code += 2; + if(memcmp(current_mode->memory+offset, code, *(code-1))) { + test_was_false = 1; + } + offset += *(code-1); + code += *(code-1); + break; + case OP_JMP: // Jump to offset. + if (debug) + fprintf(stderr, "jmp\n"); + code++; + if (!test_was_false) + code = bytecode + *((uint16_t*)code); + else + test_was_false = 0; + break; + case OP_REWIND: + if (debug) + fprintf(stderr, "rewind\n"); + code++; + if (!test_was_false) + offset = 0; + else + test_was_false = 0; + break; + case OP_AND: + if (debug) + fprintf(stderr, "and\n"); + code += 2; + if (!test_was_false) { + for(i=0; i < *(code-1); i++) { + *(current_mode->memory + offset) &= code[i]; + } + offset += *(code-1); + } else { + test_was_false = 0; + } + code += *(code-1); + break; + case OP_TITLE: + if (debug) + fprintf(stderr, "title\n"); + // FIXME - NYI + default: + // Panic; not proper opcode. + fprintf(stderr, "Invalid opcode. State:\n" + " Relative: %u\n" + " Actual: %x:%u\n" + " Memory: %x\n" + " Actual: %x\n" + " Code Loc: %x\n" + " Actual: %x\n" + " Opcode: %u\n", + set_mode, + current_mode->memory, current_mode->size, + offset, + current_mode->memory + offset, + code - bytecode, + code, + *code); + abort("Halting startup.\n"); + break; + } + } + + return 0; +} + +int execb(char* filename) { + FILE* f = fopen(filename, "r"); + size_t len = fsize(f); + fread((uint8_t*)FCRAM_PATCH_LOC, 1, len, f); + fclose(f); + + struct system_patch* patch = (struct system_patch*)FCRAM_PATCH_LOC; + fprintf(stderr, "Name: %s\nDesc: %s\n", patch->name, patch->desc); + uint8_t* patch_mem = (uint8_t*)patch + sizeof(struct system_patch) + (patch->depends * 8) + (patch->titles * 8); + uint32_t patch_len = patch->size; + + return exec_bytecode(patch_mem, patch_len, 1); +} diff --git a/source/interp.h b/source/interp.h new file mode 100644 index 0000000..9f33612 --- /dev/null +++ b/source/interp.h @@ -0,0 +1,7 @@ +#ifndef __INTERP_H +#define __INTERP_H + +uint8_t* execb(char* filename); +int exec_bytecode(uint8_t* bytecode, uint32_t len, int debug); + +#endif diff --git a/source/patch/patch_file.h b/source/patch/patch_file.h index 81c1fa8..5772e83 100644 --- a/source/patch/patch_file.h +++ b/source/patch/patch_file.h @@ -14,6 +14,7 @@ #include "../firm/fcram.h" #include "../config.h" #include "../common.h" +#include "../interp.h" exefs_h* get_firm_proc9_exefs(); exefs_h* get_twl_proc9_exefs(); diff --git a/source/patch/sig.c b/source/patch/sig.c index 66bbe7e..fda935c 100644 --- a/source/patch/sig.c +++ b/source/patch/sig.c @@ -15,7 +15,7 @@ extern exefs_h* firm_p9_exefs; PATCH(signatures) { - +/* // Look for signature checks uint8_t pat1[] = { 0xC0, 0x1C, 0x76, 0xE7 }; @@ -52,6 +52,8 @@ PATCH(signatures) memcpy(off2, sigpatch, 4); fprintf(stderr, "Signature patch succeded.\n"); +*/ + execb(PATH_PATCHES "/sig.vco"); return 0; } diff --git a/source/patch_format.h b/source/patch_format.h index 3f83e78..9c91864 100644 --- a/source/patch_format.h +++ b/source/patch_format.h @@ -76,25 +76,24 @@ "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up // paths. +#define PATCH_FLAG_REQUIRE (1 << 0) // Force enable patch unless 'Unsafe Options' is checked. +#define PATCH_FLAG_DEVMODE (1 << 1) // Require 'Developer Options' to be checked. +#define PATCH_FLAG_NOABORT (1 << 2) // Don't abort on error. + // Structure of a patch file. struct system_patch { char magic[4]; // "AIDA" for shits and giggles and because we like .hack. - uint32_t version; // Version of the patch itself. + uint8_t version; // Version of the patch itself. char name[64]; // User-readable name for patch in menu. char desc[256]; // User-readable description for patch in menu. uint64_t uuid; // Unique ID for patch. Each unique patch should provide // a unique ID. - uint8_t flags; // Extra flags for patch. - - #define PATCH_FLAG_REQUIRE (1 << 0) // Force enable patch unless 'Unsafe Options' is checked. - #define PATCH_FLAG_DEVMODE (1 << 1) // Require 'Developer Options' to be checked. - #define PATCH_FLAG_NOABORT (1 << 2) // Don't abort on error. + uint32_t flags; // Extra flags for patch. - uint32_t titles; // What title this patch is intended for. Certain values are - // specially handled. + uint32_t titles; // How many titles this patch should be applied to (listed later) uint32_t depends; // How many deps there are. diff --git a/source/std/abort.h b/source/std/abort.h index 8140563..6b74d4c 100644 --- a/source/std/abort.h +++ b/source/std/abort.h @@ -3,12 +3,14 @@ #include "draw.h" +int menu_poweroff(); +uint32_t wait_key(); + #define abort(x...) \ { \ - fprintf(stderr, x); \ - fumount(); \ - while (1) \ - ; \ + fprintf(stderr, x); \ + wait_key(); \ + menu_poweroff(); \ } #endif diff --git a/source/std/draw.c b/source/std/draw.c index 4828f23..14a09f6 100644 --- a/source/std/draw.c +++ b/source/std/draw.c @@ -223,6 +223,8 @@ putc(void* buf, const int c) memset(&colorbuf[(height - 1) * width], 0, width); clear_disp(buf); // Clear screen. + + cursor_y[0]--; #else clear_disp(buf); cursor_x[0] = 0; @@ -233,7 +235,6 @@ putc(void* buf, const int c) memmove(&screen[x * col + one_c], &screen[x * col + one_c], col - one_c); } */ #endif - cursor_y[0]--; } switch (c) {