/external/Makefile
/include/Makefile
/source/corbenik
+/source/corbenik.bin
/m4
/include/config.h
/include/stamp-h1
+/source/corbenik.map
*/
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
#include <stdint.h>
-void patch_emunand(firm_h* firm_loc, uint32_t size);
+int patch_emunand(firm_h* firm_loc, uint32_t size);
#endif
*
* \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.
*
*/
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
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:
#include <firm/internal.h>
firm_h*
-load_firm(const char *path)
+load_firm(const char *path, size_t *size_out)
{
int success = 0;
size_t size = fsize(firm_file);
+ if (size_out)
+ *size_out = size;
+
uint8_t* mem = malloc(size);
firm_h *firm = (firm_h*)mem;
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;
}
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;
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
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");
}
fprintf(stderr, "emunand: mpu @ %lx\n", (uint32_t)off);
}
-void
+int
patch_emunand(firm_h* firm_loc, uint32_t index)
{
#if 0
// 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);
*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);
fprintf(stderr, "emunand: patched MPU settings\n");
#endif
+ return 0;
}
}
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;
}
return off - 0x204 + (*(uint32_t *)(off - 0x64) * 0x200) + 0x200;
}
-void
+int
patch_reboot(firm_h* firm_loc)
{
// Look for firmlaunch code
// 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;
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);
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;
}
#include <common.h>
#include <stdint.h>
-// 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;
}
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;
}