From 90a4b3402f3fc61a0b3cb62d576d943a09296525 Mon Sep 17 00:00:00 2001 From: chaoskagami Date: Wed, 7 Sep 2016 14:13:57 -0400 Subject: [PATCH] Reboot is now functional again, w00t --- .gitignore | 2 ++ include/firm/firm.h | 8 +++-- include/patch/emunand.h | 2 +- include/patcher.h | 6 +++- source/Makefile.am | 2 +- source/firm/firm.c | 54 +++++++++++++++++++++++++++++--- source/main.c | 12 +++++++- source/patch/emunand.c | 9 +++--- source/patch/module.c | 4 +-- source/patch/reboot.c | 10 +++--- source/patcher.c | 68 +++++++++++++++++++---------------------- 11 files changed, 119 insertions(+), 58 deletions(-) diff --git a/.gitignore b/.gitignore index 9a12a1a..3bf7965 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ depcomp /external/Makefile /include/Makefile /source/corbenik +/source/corbenik.bin /m4 /include/config.h /include/stamp-h1 +/source/corbenik.map diff --git a/include/firm/firm.h b/include/firm/firm.h index 93023f3..453bd60 100644 --- a/include/firm/firm.h +++ b/include/firm/firm.h @@ -31,12 +31,16 @@ struct firm_signature */ struct firm_signature *get_firm_info(firm_h *firm); +/* Loads a firmware off disk, returning it. The memory should be free()'d when done, unless you plan to boot. + */ +int prepatch_firm(const char *path, const char *prepatch_path, const char* module_path); + /* Boots the CFW, generating caches and applying patches as-needed to the specified FIRM */ -int boot_cfw(char *firm_path); +int boot_firm(const char *firm_path, const char *prepatch_path, const char* module_path); /* Loads a firmware off disk, returning it. The memory should be free()'d when done, unless you plan to boot. */ -firm_h* load_firm(const char *path); +firm_h* load_firm(const char *path, size_t *size_out); #endif diff --git a/include/patch/emunand.h b/include/patch/emunand.h index 1c26bcd..4f29402 100644 --- a/include/patch/emunand.h +++ b/include/patch/emunand.h @@ -3,6 +3,6 @@ #include -void patch_emunand(firm_h* firm_loc, uint32_t size); +int patch_emunand(firm_h* firm_loc, uint32_t size); #endif diff --git a/include/patcher.h b/include/patcher.h index 40e09d8..17ae138 100644 --- a/include/patcher.h +++ b/include/patcher.h @@ -5,7 +5,7 @@ * * \return zero on success */ -int patch_firm_all(uint64_t tid, firm_h* firm); +int patch_firm_all(uint64_t tid, firm_h* firm, const char* module_path); /* Generates patch cache for boot/loader for the current configuration. * @@ -13,4 +13,8 @@ int patch_firm_all(uint64_t tid, firm_h* firm); */ int generate_patch_cache(); +int patch_svc_calls(firm_h* firm_loc); +int patch_reboot(firm_h* firm_loc); +int patch_modules(firm_h* firm_loc, const char* module_path); + #endif diff --git a/source/Makefile.am b/source/Makefile.am index f62fb99..69045da 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -2,7 +2,7 @@ include $(top_srcdir)/common.mk noinst_PROGRAMS = corbenik corbenik_CFLAGS=$(AM_CFLAGS) -T$(srcdir)/linker.ld -nostartfiles -corbenik_LDFLAGS=$(AM_LDFLAGS) -lctr9 +corbenik_LDFLAGS=$(AM_LDFLAGS) -lctr9 -Wl,-Map,corbenik.map EXTRA_DIST = linker.ld install: diff --git a/source/firm/firm.c b/source/firm/firm.c index 376d3b1..9d15e62 100644 --- a/source/firm/firm.c +++ b/source/firm/firm.c @@ -10,7 +10,7 @@ #include firm_h* -load_firm(const char *path) +load_firm(const char *path, size_t *size_out) { int success = 0; @@ -21,6 +21,9 @@ load_firm(const char *path) size_t size = fsize(firm_file); + if (size_out) + *size_out = size; + uint8_t* mem = malloc(size); firm_h *firm = (firm_h*)mem; @@ -69,7 +72,7 @@ load_firm(const char *path) patch_entry(firm, sig->type); - if (patch_section_keys(firm, sig->k9l)) { + if (sig->type == type_native && patch_section_keys(firm, sig->k9l)) { free(firm); free(mem); return NULL; @@ -86,9 +89,44 @@ load_firm(const char *path) } int -boot_cfw(char* firm_path) +prepatch_firm(const char* firm_path, const char* prepatch_path, const char* module_path) { - firm_h* firm = load_firm(firm_path); + size_t size = 0; + firm_h* firm = load_firm(firm_path, &size); + + if (firm == NULL) + return 1; + + struct firm_signature *sig = get_firm_info(firm); + + uint64_t tid = 0x0004013800000002LLu; + + if (sig->console == console_n3ds) + tid |= 0x20000000LLu; + + tid |= sig->type * 0x100LLu; + + free(sig); + + if (patch_firm_all(tid, firm, module_path)) { + free(firm); + return 1; + } + + FILE* f = fopen(prepatch_path, "w"); + fwrite(firm, 1, size, f); + fclose(f); + + free(firm); + + return 0; +} + +int +boot_firm(const char* firm_path, const char* prepatch_path, const char* module_path) +{ + size_t size = 0; + firm_h* firm = load_firm(firm_path, &size); if (firm == NULL) return 1; @@ -104,8 +142,14 @@ boot_cfw(char* firm_path) free(sig); - if (patch_firm_all(tid, firm) != 0) + if (patch_firm_all(tid, firm, module_path)) { + free(firm); return 1; + } + + FILE* f = fopen(prepatch_path, "w"); + fwrite(firm, 1, size, f); + fclose(f); firmlaunch(firm); // <- should NOT return if all is well diff --git a/source/main.c b/source/main.c index 7da5e77..cb3135a 100644 --- a/source/main.c +++ b/source/main.c @@ -63,7 +63,17 @@ main(int argc, char** argv) generate_patch_cache(); } - boot_cfw(config->firm[0]); + if (prepatch_firm(config->firm[1], PATH_TWL_P, PATH_MODULE_TWL)) { + fprintf(stderr, "WARNING: Failed to load/patch TWL.\n"); + wait(); + } + + if(prepatch_firm(config->firm[2], PATH_AGB_P, PATH_MODULE_AGB)) { + fprintf(stderr, "WARNING: Failed to load/patch AGB.\n"); + wait(); + } + + boot_firm(config->firm[0], PATH_NATIVE_P, PATH_MODULE_NATIVE); panic("Firmlaunch failed!\n"); } diff --git a/source/patch/emunand.c b/source/patch/emunand.c index 8c18055..69a6e09 100644 --- a/source/patch/emunand.c +++ b/source/patch/emunand.c @@ -113,7 +113,7 @@ patchMPU(uint8_t *pos, uint32_t size) fprintf(stderr, "emunand: mpu @ %lx\n", (uint32_t)off); } -void +int patch_emunand(firm_h* firm_loc, uint32_t index) { #if 0 @@ -127,11 +127,11 @@ patch_emunand(firm_h* firm_loc, uint32_t index) // Copy emuNAND code void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize); if (!emuCodeOffset) - panic("emunand: code missing from arm9?\n"); + return 1; FILE *f = fopen(PATH_EMUNAND_CODE, "r"); if (!f) - panic("emunand: code not found on SD.\n"); + return 1; uint32_t emunand_size = fsize(f); fread(emuCodeOffset, 1, emunand_size, f); @@ -147,7 +147,7 @@ patch_emunand(firm_h* firm_loc, uint32_t index) *pos_sdmmc = (uint32_t *)memfind(emuCodeOffset, emunand_size, "SDMC", 4); if (!pos_offset || !pos_head || !pos_sdmmc) - panic("emunand: couldn't find pattern in hook?\n"); + return 1; verify_emunand(index, pos_offset, pos_head); @@ -168,4 +168,5 @@ patch_emunand(firm_h* firm_loc, uint32_t index) fprintf(stderr, "emunand: patched MPU settings\n"); #endif + return 0; } diff --git a/source/patch/module.c b/source/patch/module.c index 82a76f6..d148e51 100644 --- a/source/patch/module.c +++ b/source/patch/module.c @@ -87,10 +87,10 @@ end_inj: } int -patch_modules(firm_h* firm_loc) +patch_modules(firm_h* firm_loc, const char* module_path) { firm_modules = firm_loc; - recurse_call(PATH_MODULE_NATIVE, inject_module); + recurse_call(module_path, inject_module); return 0; } diff --git a/source/patch/reboot.c b/source/patch/reboot.c index 332d9bf..80c557b 100644 --- a/source/patch/reboot.c +++ b/source/patch/reboot.c @@ -14,7 +14,7 @@ getProcess9(uint8_t *pos, uint32_t size, uint32_t *process9Size, uint32_t *proce return off - 0x204 + (*(uint32_t *)(off - 0x64) * 0x200) + 0x200; } -void +int patch_reboot(firm_h* firm_loc) { // Look for firmlaunch code @@ -51,7 +51,7 @@ patch_reboot(firm_h* firm_loc) // Put the fOpen offset in the right location uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "open", 4); if (!pos_fopen) - panic("reboot: fopen location missing\n"); + return 1; *pos_fopen = fOpenOffset; @@ -60,7 +60,7 @@ patch_reboot(firm_h* firm_loc) uint32_t *pos_agb = (uint32_t *)memfind(off, size, "AGBF", 4); if (!pos_native && !pos_twl && !pos_agb) - panic("reboot: missing string placeholder?\n"); + return 1; fprintf(stderr, "reboot: NATF @ %lx\n", (uint32_t)pos_native); fprintf(stderr, "reboot: TWLF @ %lx\n", (uint32_t)pos_twl); @@ -104,8 +104,10 @@ patch_reboot(firm_h* firm_loc) f = fopen(PATH_REBOOT_CODE, "r"); if (!f) - panic("reboot: boot not found on SD\n"); + return 1; fread(mem, 1, fsize(f), f); fclose(f); + + return 0; } diff --git a/source/patcher.c b/source/patcher.c index 61293ef..5393f47 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -1,12 +1,6 @@ #include #include -// TODO - Basically all this needs to move to patcher programs. - -extern int patch_svc_calls(firm_h*); -extern int patch_modules(firm_h*); -extern int patch_reboot(firm_h*); - extern int doing_autoboot; extern uint8_t *enable_list; @@ -51,43 +45,43 @@ generate_patch_cache() } int -patch_firm_all(uint64_t tid, firm_h* firm) +patch_firm_all(uint64_t tid, firm_h* firm, const char* module_path) { - execb(tid, firm); - - fprintf(stderr, "VM exited without issue\n"); - - // Hook firmlaunch? - if (get_opt_u32(OPTION_REBOOT)) { - patch_reboot(firm); - - wait(); - } + int exit = 0; - // Use EmuNAND? - if (get_opt_u32(OPTION_EMUNAND)) { - // Yes. - patch_emunand(firm, get_opt_u32(OPTION_EMUNAND_INDEX)); - - wait(); - } + execb(tid, firm); - // Inject services? - if (get_opt_u32(OPTION_SVCS)) { - if (patch_svc_calls(firm)) { - panic("Fatal. Svc inject has failed."); - } - wait(); + switch (tid) { + case 0x0004013800000002LLu: // NFIRM + case 0x0004013820000002LLu: + // Hook firmlaunch? + if (get_opt_u32(OPTION_REBOOT)) + patch_reboot(firm); + + // Use EmuNAND? + if (get_opt_u32(OPTION_EMUNAND)) + patch_emunand(firm, get_opt_u32(OPTION_EMUNAND_INDEX)); + + // Inject services? + if (get_opt_u32(OPTION_SVCS)) + if (patch_svc_calls(firm)) + exit |= 2; + break; + case 0x0004013800000102LLu: + case 0x0004013820000102LLu: + break; + case 0x0004013800000202LLu: + case 0x0004013820000202LLu: + break; + default: + exit |= 4; + break; } // Replace loader? - if (get_opt_u32(OPTION_LOADER)) { - if (patch_modules(firm)) { - panic("Fatal. Loader inject has failed."); - } - // This requires OPTION_SIGPATCH. - wait(); - } + if (get_opt_u32(OPTION_LOADER)) + if (patch_modules(firm, module_path)) + exit |= 1; return 0; } -- 2.39.5