#ifndef __INTERP_H
#define __INTERP_H
-int execb(uint64_t tid, uint16_t ver,
- uint8_t *text_mem, uint32_t text_len,
- uint8_t *data_mem, uint32_t data_size,
- uint8_t *ro_mem, uint32_t ro_size);
+int execb(uint64_t tid, uint16_t ver, uint8_t *text_mem, uint32_t text_len, uint8_t *data_mem, uint32_t data_size, uint8_t *ro_mem, uint32_t ro_size);
#endif
dump_code(progid, (u8 *)shared->text_addr, shared->total_size << 12);
// Patch segments
- patch_exe (progid, progver, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12,
- (u8 *)shared->data_addr, shared->data_size << 12, original->data_size << 12,
- (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
+ patch_exe(progid, progver, (u8 *)shared->text_addr, shared->text_size << 12, original->text_size << 12, (u8 *)shared->data_addr, shared->data_size << 12,
+ original->data_size << 12, (u8 *)shared->ro_addr, shared->ro_size << 12, original->ro_size << 12);
return 0;
}
return;
}
- else
- {
- if (R_SUCCEEDED(fileOpen(&code_f, ARCHIVE_SDMC, code_path, FS_OPEN_WRITE | FS_OPEN_CREATE)))
- {
+ else {
+ if (R_SUCCEEDED(fileOpen(&code_f, ARCHIVE_SDMC, code_path, FS_OPEN_WRITE | FS_OPEN_CREATE))) {
u32 len = 0;
FSFILE_Write(code_f, &len, 0, code_loc, code_len, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME);
logstr(" dumped code to ");
// This is only for the .code segment.
void
-patch_exe(u64 progId, u16 progver,
- u8 *text, u32 text_size, u32 orig_text,
- u8* data, u32 data_size, u32 orig_data,
- u8* ro, u32 ro_size, u32 orig_ro)
+patch_exe(u64 progId, u16 progver, u8 *text, u32 text_size, u32 orig_text, u8 *data, u32 data_size, u32 orig_data, u8 *ro, u32 ro_size, u32 orig_ro)
{
if (progId == 0x0004013000008002LL)
adjust_cpu_settings(progId, text, orig_text);
#include <3ds/types.h>
-void patch_exe(u64 progId, u16 progver,
- u8 *text, u32 text_size, u32 orig_text,
- u8* data, u32 data_size, u32 orig_data,
- u8* ro, u32 ro_size, u32 orig_ro);
+void patch_exe(u64 progId, u16 progver, u8 *text, u32 text_size, u32 orig_text, u8 *data, u32 data_size, u32 orig_data, u8 *ro, u32 ro_size, u32 orig_ro);
void dump_code(u64 progId, u8 *code_loc, u32 code_len);
fprintf(TOP_SCREEN, " ");
fprintf(TOP_SCREEN, "[%u] %s \n", toggles[options[i].index], options[i].name);
- } else if (options[i].allowed == not_option) {
+ } else if (options[i].allowed == not_option) {
fprintf(TOP_SCREEN, "%s\n", options[i].name);
}
++i;
break;
case BUTTON_A:
if (options[cursor_y].allowed == boolean_val) {
- toggles[options[cursor_y].index] = !toggles[options[cursor_y].index];
- } else if (options[cursor_y].allowed == ranged_val) {
- if (toggles[options[cursor_y].index] == options[cursor_y].b)
- toggles[options[cursor_y].index] = options[cursor_y].a;
- else
- toggles[options[cursor_y].index]++;
- }
+ toggles[options[cursor_y].index] = !toggles[options[cursor_y].index];
+ } else if (options[cursor_y].allowed == ranged_val) {
+ if (toggles[options[cursor_y].index] == options[cursor_y].b)
+ toggles[options[cursor_y].index] = options[cursor_y].a;
+ else
+ toggles[options[cursor_y].index]++;
+ }
break;
case BUTTON_X:
- if (options[cursor_y].allowed == ranged_val) {
- if (toggles[options[cursor_y].index] == options[cursor_y].a)
- toggles[options[cursor_y].index] = options[cursor_y].b;
+ if (options[cursor_y].allowed == ranged_val) {
+ if (toggles[options[cursor_y].index] == options[cursor_y].a)
+ toggles[options[cursor_y].index] = options[cursor_y].b;
else
- toggles[options[cursor_y].index]--;
- }
+ toggles[options[cursor_y].index]--;
+ }
break;
case BUTTON_B:
exit = 1;
/* Read File */
/*-----------------------------------------------------------------------*/
-
FRESULT
-f_getsector(FIL *fp, /* Pointer to the file object */
- UINT *sec /* Pointer to uint which will contain the sector */
- )
+f_getsector(FIL *fp, /* Pointer to the file object */
+ UINT *sec /* Pointer to uint which will contain the sector */
+ )
{
FRESULT res;
DWORD clst = 0, sect = 0;
LEAVE_FF(fp->fs, FR_DENIED);
if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
- csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
- if (!csect) { /* On the cluster boundary? */
- if (fp->fptr == 0) { /* On the top of the file? */
- clst = fp->sclust; /* Follow from the origin */
- } else { /* Middle or end of the file */
- clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
- }
-
- if (clst < 2)
- ABORT(fp->fs, FR_INT_ERR);
- if (clst == 0xFFFFFFFF)
- ABORT(fp->fs, FR_DISK_ERR);
- }
-
- sect = clust2sect(fp->fs, clst); /* Get current sector */
- if (!sect)
- ABORT(fp->fs, FR_INT_ERR);
- sect += csect;
- }
-
- *sec = sect;
-
- return 0;
-}
+ csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
+ if (!csect) { /* On the cluster boundary? */
+ if (fp->fptr == 0) { /* On the top of the file? */
+ clst = fp->sclust; /* Follow from the origin */
+ } else { /* Middle or end of the file */
+ clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
+ }
+ if (clst < 2)
+ ABORT(fp->fs, FR_INT_ERR);
+ if (clst == 0xFFFFFFFF)
+ ABORT(fp->fs, FR_DISK_ERR);
+ }
+
+ sect = clust2sect(fp->fs, clst); /* Get current sector */
+ if (!sect)
+ ABORT(fp->fs, FR_INT_ERR);
+ sect += csect;
+ }
+
+ *sec = sect;
+
+ return 0;
+}
/*-----------------------------------------------------------------------*/
/* Read File */
FRESULT f_mkfs(const TCHAR *path, BYTE sfd, UINT au); /* Create a file system on the volume */
FRESULT f_fdisk(BYTE pdrv, const DWORD szt[], void *work); /* Divide a physical drive into some partitions */
FRESULT f_getsector(FIL *fp, UINT *sec);
-int f_putc(TCHAR c, FIL *fp); /* Put a character to the file */
-int f_puts(const TCHAR *str, FIL *cp); /* Put a string to the file */
-int f_printf(FIL *fp, const TCHAR *str, ...); /* Put a formatted string to the file */
-TCHAR *f_gets(TCHAR *buff, int len, FIL *fp); /* Get a string from the file */
+int f_putc(TCHAR c, FIL *fp); /* Put a character to the file */
+int f_puts(const TCHAR *str, FIL *cp); /* Put a string to the file */
+int f_printf(FIL *fp, const TCHAR *str, ...); /* Put a formatted string to the file */
+TCHAR *f_gets(TCHAR *buff, int len, FIL *fp); /* Get a string from the file */
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
#define f_error(fp) ((fp)->err)
// this.
}
-int decrypt_cetk_key(void *key, const void *cetk) {
- static int common_key_y_init = 0;
- uint8_t iv[AES_BLOCK_SIZE] = {0};
- uint32_t sigtype = __builtin_bswap32(*(uint32_t *)cetk);
+int
+decrypt_cetk_key(void *key, const void *cetk)
+{
+ static int common_key_y_init = 0;
+ uint8_t iv[AES_BLOCK_SIZE] = { 0 };
+ uint32_t sigtype = __builtin_bswap32(*(uint32_t *)cetk);
- if (sigtype != SIG_TYPE_RSA2048_SHA256)
- return 1;
+ if (sigtype != SIG_TYPE_RSA2048_SHA256)
+ return 1;
- ticket_h *ticket = (ticket_h *)(cetk + sizeof(sigtype) + 0x13C);
+ ticket_h *ticket = (ticket_h *)(cetk + sizeof(sigtype) + 0x13C);
- if (ticket->ticketCommonKeyYIndex != 1)
- return 1;
+ if (ticket->ticketCommonKeyYIndex != 1)
+ return 1;
- if (!common_key_y_init) {
- uint8_t common_key_y[AES_BLOCK_SIZE] = {0};
- uint8_t *p9_base = (uint8_t *)0x08028000;
- uint8_t *i;
- for (i = p9_base + 0x70000 - AES_BLOCK_SIZE; i >= p9_base; i--) {
- if (i[0] == 0xD0 && i[4] == 0x9C && i[8] == 0x32 && i[12] == 0x23) {
- // At i, there's 7 keys with 4 bytes padding between them.
- // We only need the 2nd.
- memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y));
- fprintf(stderr, "y");
- break;
- }
- }
+ if (!common_key_y_init) {
+ uint8_t common_key_y[AES_BLOCK_SIZE] = { 0 };
+ uint8_t *p9_base = (uint8_t *)0x08028000;
+ uint8_t *i;
+ for (i = p9_base + 0x70000 - AES_BLOCK_SIZE; i >= p9_base; i--) {
+ if (i[0] == 0xD0 && i[4] == 0x9C && i[8] == 0x32 && i[12] == 0x23) {
+ // At i, there's 7 keys with 4 bytes padding between them.
+ // We only need the 2nd.
+ memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y));
+ fprintf(stderr, "y");
+ break;
+ }
+ }
- if (i < p9_base)
- return 1;
+ if (i < p9_base)
+ return 1;
- aes_setkey(0x3D, common_key_y, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
- common_key_y_init = 1;
- }
+ aes_setkey(0x3D, common_key_y, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
+ common_key_y_init = 1;
+ }
- aes_use_keyslot(0x3D);
- memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
+ aes_use_keyslot(0x3D);
+ memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
- memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
- aes(key, key, 1, iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
+ aes(key, key, 1, iv, AES_CBC_DECRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
- fprintf(stderr, "g");
+ fprintf(stderr, "g");
- return 0;
+ return 0;
}
int
-decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key) {
+decrypt_firm_title(firm_h *dest, ncch_h *ncch, uint32_t *size, void *key)
+{
uint8_t firm_iv[16] = { 0 };
uint8_t exefs_key[16] = { 0 };
uint8_t exefs_iv[16] = { 0 };
}
int
-decrypt_firm(firm_h *dest, char *path_firmkey, char* path_cetk, uint32_t *size)
+decrypt_firm(firm_h *dest, char *path_firmkey, char *path_cetk, uint32_t *size)
{
uint8_t firm_key[AES_BLOCK_SIZE];
// Firmware is likely encrypted. Decrypt.
if (!read_file(firm_key, path_firmkey, AES_BLOCK_SIZE)) {
- // Missing firmkey. Attempt to get from CETK (only works if system was booted)
- if (!read_file((void*)FCRAM_JUNK_LOC, path_cetk, FCRAM_SPACING) ||
- decrypt_cetk_key(firm_key, (void*)FCRAM_JUNK_LOC)) {
- fprintf(BOTTOM_SCREEN, "!");
- return 1;
- } else {
- fprintf(BOTTOM_SCREEN, "t");
- write_file(firm_key, path_firmkey, AES_BLOCK_SIZE);
- }
+ // Missing firmkey. Attempt to get from CETK (only works if system was booted)
+ if (!read_file((void *)FCRAM_JUNK_LOC, path_cetk, FCRAM_SPACING) || decrypt_cetk_key(firm_key, (void *)FCRAM_JUNK_LOC)) {
+ fprintf(BOTTOM_SCREEN, "!");
+ return 1;
+ } else {
+ fprintf(BOTTOM_SCREEN, "t");
+ write_file(firm_key, path_firmkey, AES_BLOCK_SIZE);
+ }
} else {
fprintf(BOTTOM_SCREEN, "k");
}
if (dest->magic != FIRM_MAGIC) {
status = decrypt_firm(dest, path_firmkey, path_cetk, size);
if (status != 0) {
- fprintf(BOTTOM_SCREEN, "!");
+ fprintf(BOTTOM_SCREEN, "!");
return 1;
- }
+ }
firmware_changed = 1; // Decryption performed.
} else {
fprintf(BOTTOM_SCREEN, "_");
wait();
clear_disp(BOTTOM_SCREEN);
- set_cursor(BOTTOM_SCREEN, 0, 0);
+ set_cursor(BOTTOM_SCREEN, 0, 0);
fumount(); // Unmount SD. No longer needed.
if (patch_firm_all() != 0)
return;
- if (config.options[OPTION_REBOOT] && config.options[OPTION_RECONFIGURED]) {
- fprintf(stderr, "Saving FIRM for reboot...\n");
- if (!write_file(firm_loc, PATH_NATIVE_P, firm_size))
- abort("Failed to save prepatched native\n");
+ if (config.options[OPTION_REBOOT] && config.options[OPTION_RECONFIGURED]) {
+ fprintf(stderr, "Saving FIRM for reboot...\n");
+ if (!write_file(firm_loc, PATH_NATIVE_P, firm_size))
+ abort("Failed to save prepatched native\n");
- if (!write_file(twl_firm_loc, PATH_TWL_P, twl_firm_size))
- abort("Failed to save prepatched twl\n");
+ if (!write_file(twl_firm_loc, PATH_TWL_P, twl_firm_size))
+ abort("Failed to save prepatched twl\n");
- if (!write_file(agb_firm_loc, PATH_AGB_P, agb_firm_size))
- abort("Failed to save prepatched agb\n");
- }
+ if (!write_file(agb_firm_loc, PATH_AGB_P, agb_firm_size))
+ abort("Failed to save prepatched agb\n");
+ }
if (config.options[OPTION_RECONFIGURED]) {
config.options[OPTION_RECONFIGURED] = 0;
save_config();
- }
+ }
boot_firm();
}
uint32_t i;
- int eq = 0, gt = 0, lt = 0; // Flags.
+ int eq = 0, gt = 0, lt = 0; // Flags.
uint8_t *code = bytecode;
uint8_t *end = code + len;
log("test\n");
code += 2;
eq = memcmp(current_mode->memory + offset, code, *(code - 1));
- if (eq < 0)
- lt = 1;
- if (eq > 0)
- gt = 1;
- eq = !eq;
+ if (eq < 0)
+ lt = 1;
+ if (eq > 0)
+ gt = 1;
+ eq = !eq;
code += *(code - 1);
break;
case OP_JMP: // Jump to offset.
if (debug)
log("jmp\n");
code++;
- code = bytecode + (code[0] + (code[1] << 8));
+ code = bytecode + (code[0] + (code[1] << 8));
break;
case OP_JMPEQ: // Jump to offset if equal
if (debug)
log("jmpeq\n");
- code++;
- if (eq)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (eq)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_JMPNE: // Jump to offset if not equal
if (debug)
log("jmpne\n");
- code++;
- if (!eq)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (!eq)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_JMPLT: // Jump to offset if less than
if (debug)
log("jmplt\n");
- code++;
- if (lt)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (lt)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_JMPGT: // Jump to offset if greater than
if (debug)
log("jmpgt\n");
- code++;
- if (gt)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (gt)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_JMPLE: // Jump to offset if less than or equal
if (debug)
log("jmple\n");
- code++;
- if (lt || eq)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (lt || eq)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_JMPGE: // Jump to offset if greater than or equal
if (debug)
log("jmpge\n");
- code++;
- if (gt || eq)
- code = bytecode + (code[0] + (code[1] << 8));
- else
- code += 2;
+ code++;
+ if (gt || eq)
+ code = bytecode + (code[0] + (code[1] << 8));
+ else
+ code += 2;
break;
case OP_CLF: // Clear flags.
if (debug)
log("clf\n");
- code++;
- gt = lt = eq = 0;
+ code++;
+ gt = lt = eq = 0;
break;
case OP_REWIND:
if (debug)
log("ver\n");
code++;
eq = memcmp(&ver, code, 2);
- if (eq < 0)
- lt = 1;
- if (eq > 0)
- gt = 1;
- eq = !eq;
+ if (eq < 0)
+ lt = 1;
+ if (eq > 0)
+ gt = 1;
+ eq = !eq;
code += 2;
break;
case OP_SEEK: // Jump to offset if greater than or equal
if (debug)
log("seek\n");
- code++;
- offset = code[0] + (code[1] << 8) + (code[2] << 16) + (code[3] << 24);
+ code++;
+ offset = code[0] + (code[1] << 8) + (code[2] << 16) + (code[3] << 24);
if (offset > current_mode->size) { // Went out of bounds. Error.
#ifndef LOADER
- fprintf(stderr, "%x", offset);
+ fprintf(stderr, "%x", offset);
#endif
abort("seeked out of bounds\n");
- }
+ }
- code += 4;
+ code += 4;
break;
case OP_NEXT:
if (debug)
#ifdef LOADER
int
-execb(uint64_t tid, uint16_t ver,
- uint8_t *text_mem, uint32_t text_len,
- uint8_t* data_mem, uint32_t data_len,
- uint8_t* ro_mem, uint32_t ro_len)
+execb(uint64_t tid, uint16_t ver, uint8_t *text_mem, uint32_t text_len, uint8_t *data_mem, uint32_t data_len, uint8_t *ro_mem, uint32_t ro_len)
{
#else
int
// Set memory.
modes[18].memory = text_mem;
- modes[18].size = text_len;
+ modes[18].size = text_len;
// Set memory.
modes[19].memory = data_mem;
- modes[19].size = data_len;
+ modes[19].size = data_len;
// Set memory.
modes[20].memory = ro_mem;
- modes[20].size = ro_len;
+ modes[20].size = ro_len;
log(" exec\n");
int
main()
{
- int c = fmount();
- screen_init();
+ int c = fmount();
+ screen_init();
if (c) {
// Failed to mount SD. Bomb out.
{ OPTION_LOADER_CPU_800MHZ, " CPU - 800Mhz (n3ds)", "Forces the system to run in 800Mhz mode. Ignored if not a N3DS.", boolean_val, 0, 0 },
{ OPTION_LOADER_LANGEMU, " Language Emulation", "Reads language emulation configuration and imitates the region/language.", boolean_val, 0, 0 },
- { OPTION_LOADER_DUMPCODE, " Dump Code Sections (dev)", "Dumps code sections for titles to SD card the first time they're loaded. This doesn't dump system titles. Slows things down considerably.", boolean_val, 0, 0 },
+ { OPTION_LOADER_DUMPCODE, " Dump Code Sections (dev)",
+ "Dumps code sections for titles to SD card the first time they're loaded. This doesn't dump system titles. Slows things down considerably.", boolean_val,
+ 0, 0 },
// space
{ 0, "", "", not_option, 0, 0 },
int
menu_main()
{
- // TODO - Stop using different menu code here.
+ // TODO - Stop using different menu code here.
set_cursor(TOP_SCREEN, 0, 0);
const char *list[] = { "Options", "Patches", "Info", "Help/Readme", "Reboot", "Power off", "Boot Firmware" };
#include "../firm/headers.h"
#include "../patch_format.h"
-uint8_t *temp = (uint8_t*)FCRAM_JUNK_LOC;
+uint8_t *temp = (uint8_t *)FCRAM_JUNK_LOC;
-void verify_loop_emunand(char* filename) {
- // FIXME - This won't work unless the NAND file is completely contiguous on disk, sadly.
- // Technically speaking if I were to defrag my SD this would work, I suspect.
+void
+verify_loop_emunand(char *filename)
+{
+ // FIXME - This won't work unless the NAND file is completely contiguous on disk, sadly.
+ // Technically speaking if I were to defrag my SD this would work, I suspect.
- uint32_t offset = get_file_sector(filename); // Get the sector of the file
+ uint32_t offset = get_file_sector(filename); // Get the sector of the file
// Check for RedNAND image on SD
- if(!sdmmc_sdcard_readsectors(offset, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
- fprintf(stderr, "emunand: found NCSD magic\n");
+ if (!sdmmc_sdcard_readsectors(offset, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+ fprintf(stderr, "emunand: found NCSD magic\n");
} else {
- abort("emunand: selected NAND image is not valid.\n");
- }
+ abort("emunand: selected NAND image is not valid.\n");
+ }
}
-void verify_emunand(uint32_t index, uint32_t* off, uint32_t* head) {
- uint32_t nandSize = getMMCDevice(0)->total_size;
+void
+verify_emunand(uint32_t index, uint32_t *off, uint32_t *head)
+{
+ uint32_t nandSize = getMMCDevice(0)->total_size;
- uint32_t offset;
- if (nandSize > 0x200000)
- offset = 0x400000 * index;
- else
- offset = 0x200000 * index;
+ uint32_t offset;
+ if (nandSize > 0x200000)
+ offset = 0x400000 * index;
+ else
+ offset = 0x200000 * index;
// Check for RedNAND/Normal physical layout on SD
- if(!sdmmc_sdcard_readsectors(offset + 1, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
- *off = offset + 1;
- *head = offset + 1;
+ if (!sdmmc_sdcard_readsectors(offset + 1, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+ *off = offset + 1;
+ *head = offset + 1;
- fprintf(stderr, "emunand: found NCSD magic for #%u\n", index);
- fprintf(stderr, "emunand: layout is normal\n");
+ fprintf(stderr, "emunand: found NCSD magic for #%u\n", index);
+ fprintf(stderr, "emunand: layout is normal\n");
}
// Check for GW EmuNAND on SD
- else if(!sdmmc_sdcard_readsectors(offset + nandSize, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
- *off = offset;
- *head = offset + nandSize;
+ else if (!sdmmc_sdcard_readsectors(offset + nandSize, 1, temp) && *(uint32_t *)(temp + 0x100) == NCSD_MAGIC) {
+ *off = offset;
+ *head = offset + nandSize;
- fprintf(stderr, "emunand: found NCSD magic for %u\n", index);
- fprintf(stderr, "emunand: layout is gateway\n");
+ fprintf(stderr, "emunand: found NCSD magic for %u\n", index);
+ fprintf(stderr, "emunand: layout is gateway\n");
} else {
- abort("emunand: selected NAND image is not valid.\n");
- }
+ abort("emunand: selected NAND image is not valid.\n");
+ }
}
-static void *getEmuCode(uint8_t *pos, uint32_t size)
+static void *
+getEmuCode(uint8_t *pos, uint32_t size)
{
- const uint8_t pattern[] = {0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
+ const uint8_t pattern[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };
- //Looking for the last free space before Process9
- void* ret = memfind(pos + 0x13500, size - 0x13500, pattern, 6) + 0x455;
+ // Looking for the last free space before Process9
+ void *ret = memfind(pos + 0x13500, size - 0x13500, pattern, 6) + 0x455;
- if (ret) {
- fprintf(stderr, "emunand: free space @ %x\n", ret);
- fprintf(stderr, "emunand: size is %u bytes\n", (uint8_t*)ret - pos);
- }
+ if (ret) {
+ fprintf(stderr, "emunand: free space @ %x\n", ret);
+ fprintf(stderr, "emunand: size is %u bytes\n", (uint8_t *)ret - pos);
+ }
- return ret;
+ return ret;
}
-static uint32_t getSDMMC(uint8_t *pos, uint32_t size)
+static uint32_t
+getSDMMC(uint8_t *pos, uint32_t size)
{
- //Look for struct code
- const uint8_t pattern[] = {0x21, 0x20, 0x18, 0x20};
+ // Look for struct code
+ const uint8_t pattern[] = { 0x21, 0x20, 0x18, 0x20 };
const uint8_t *off = memfind(pos, size, pattern, 4);
uint32_t ret = *(uint32_t *)(off + 9) + *(uint32_t *)(off + 0xD);
- fprintf(stderr, "emunand: SDMMC code @ %x\n", ret);
+ fprintf(stderr, "emunand: SDMMC code @ %x\n", ret);
- return ret;
+ return ret;
}
-static void patchNANDRW(uint8_t *pos, uint32_t size, uint32_t branchOffset)
+static void
+patchNANDRW(uint8_t *pos, uint32_t size, uint32_t branchOffset)
{
- const uint16_t nandRedir[2] = {0x4C00, 0x47A0};
+ const uint16_t nandRedir[2] = { 0x4C00, 0x47A0 };
- //Look for read/write code
- const uint8_t pattern[] = {0x1E, 0x00, 0xC8, 0x05};
+ // Look for read/write code
+ const uint8_t pattern[] = { 0x1E, 0x00, 0xC8, 0x05 };
- uint16_t *readOffset = (uint16_t *)memfind(pos, size, pattern, 4) - 3;
+ uint16_t *readOffset = (uint16_t *)memfind(pos, size, pattern, 4) - 3;
uint16_t *writeOffset = (uint16_t *)memfind((uint8_t *)(readOffset + 5), 0x100, pattern, 4) - 3;
*readOffset = nandRedir[0];
writeOffset[1] = nandRedir[1];
((uint32_t *)writeOffset)[1] = branchOffset;
- fprintf(stderr, "emunand: write @ %x\n", writeOffset);
- fprintf(stderr, "emunand: read @ %x\n", readOffset);
+ fprintf(stderr, "emunand: write @ %x\n", writeOffset);
+ fprintf(stderr, "emunand: read @ %x\n", readOffset);
}
-static void patchMPU(uint8_t *pos, uint32_t size)
+static void
+patchMPU(uint8_t *pos, uint32_t size)
{
- const uint32_t mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
+ const uint32_t mpuPatch[3] = { 0x00360003, 0x00200603, 0x001C0603 };
- //Look for MPU pattern
- const uint8_t pattern[] = {0x03, 0x00, 0x24, 0x00};
+ // Look for MPU pattern
+ const uint8_t pattern[] = { 0x03, 0x00, 0x24, 0x00 };
uint32_t *off = (uint32_t *)memfind(pos, size, pattern, 4);
off[6] = mpuPatch[1];
off[9] = mpuPatch[2];
- fprintf(stderr, "emunand: mpu @ %x\n", off);
+ fprintf(stderr, "emunand: mpu @ %x\n", off);
}
-void patch_emunand(uint32_t index) {
- //uint8_t *arm9Section, uint32_t arm9SectionSize, uint8_t *process9Offset, uint32_t process9Size, uint32_t emuOffset, uint32_t emuHeader, uint32_t branchAdditive)
+void
+patch_emunand(uint32_t index)
+{
+ // uint8_t *arm9Section, uint32_t arm9SectionSize, uint8_t *process9Offset, uint32_t process9Size, uint32_t emuOffset, uint32_t emuHeader, uint32_t
+ // branchAdditive)
// ARM9 section.
- uint8_t* arm9Section = (uint8_t*)firm_loc + firm_loc->section[2].offset;
- uint32_t arm9SectionSize = firm_loc->section[2].size;
+ uint8_t *arm9Section = (uint8_t *)firm_loc + firm_loc->section[2].offset;
+ uint32_t arm9SectionSize = firm_loc->section[2].size;
- uint8_t* process9Offset = (uint8_t *)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
- uint32_t process9Size = firm_p9_exefs->fileHeaders[0].size;
+ uint8_t *process9Offset = (uint8_t *)firm_p9_exefs + sizeof(exefs_h) + firm_p9_exefs->fileHeaders[0].offset;
+ uint32_t process9Size = firm_p9_exefs->fileHeaders[0].size;
- //Copy emuNAND code
+ // Copy emuNAND code
void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize);
- if (!emuCodeOffset)
- abort("emunand: code missing from arm9?\n");
+ if (!emuCodeOffset)
+ abort("emunand: code missing from arm9?\n");
- FILE* f = fopen(PATH_EMUNAND_CODE, "r");
- if (!f)
- abort("emunand: code not found on SD.\n");
+ FILE *f = fopen(PATH_EMUNAND_CODE, "r");
+ if (!f)
+ abort("emunand: code not found on SD.\n");
- uint32_t emunand_size = fsize(f);
- fread(emuCodeOffset, 1, emunand_size, f);
- fclose(f);
+ uint32_t emunand_size = fsize(f);
+ fread(emuCodeOffset, 1, emunand_size, f);
+ fclose(f);
uint32_t branchOffset = (uint32_t)emuCodeOffset - ((uint32_t)firm_loc + firm_loc->section[2].offset - firm_loc->section[2].address);
- fprintf(stderr, "emunand: read in emunand code - %x\n", emuCodeOffset);
+ fprintf(stderr, "emunand: read in emunand code - %x\n", emuCodeOffset);
- //Add the data of the found emuNAND
- uint32_t *pos_offset = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NAND", 4),
- *pos_head = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NCSD", 4),
- *pos_sdmmc = (uint32_t *)memfind(emuCodeOffset, emunand_size, "SDMC", 4);
+ // Add the data of the found emuNAND
+ uint32_t *pos_offset = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NAND", 4), *pos_head = (uint32_t *)memfind(emuCodeOffset, emunand_size, "NCSD", 4),
+ *pos_sdmmc = (uint32_t *)memfind(emuCodeOffset, emunand_size, "SDMC", 4);
- verify_emunand(index, pos_offset, pos_head);
+ verify_emunand(index, pos_offset, pos_head);
- fprintf(stderr, "emunand: nand is on sector %u\n", *pos_offset);
- fprintf(stderr, "emunand: head is on sector %u\n", *pos_head);
+ fprintf(stderr, "emunand: nand is on sector %u\n", *pos_offset);
+ fprintf(stderr, "emunand: head is on sector %u\n", *pos_head);
- if (!pos_offset || !pos_head || !pos_sdmmc)
- abort("emunand: couldn't find pattern in hook?\n");
+ if (!pos_offset || !pos_head || !pos_sdmmc)
+ abort("emunand: couldn't find pattern in hook?\n");
- //Add emuNAND hooks
+ // Add emuNAND hooks
patchNANDRW(process9Offset, process9Size, branchOffset);
- fprintf(stderr, "emunand: patched read/write calls\n");
+ fprintf(stderr, "emunand: patched read/write calls\n");
- //Find and add the SDMMC struct
+ // Find and add the SDMMC struct
*pos_sdmmc = getSDMMC(process9Offset, process9Size);
- //Set MPU for emu code region
+ // Set MPU for emu code region
patchMPU(arm9Section, arm9SectionSize);
- fprintf(stderr, "emunand: patched MPU settings\n");
+ fprintf(stderr, "emunand: patched MPU settings\n");
}
-
int wait();
-uint8_t *getProcess9(uint8_t *pos, uint32_t size, uint32_t *process9Size, uint32_t *process9MemAddr) {
- uint8_t *off = memfind(pos, size, "ess9", 4);
- *process9Size = *(uint32_t *)(off - 0x60) * 0x200;
- *process9MemAddr = *(uint32_t *)(off + 0xC);
- //Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
- return off - 0x204 + (*(uint32_t *)(off - 0x64) * 0x200) + 0x200;
+uint8_t *
+getProcess9(uint8_t *pos, uint32_t size, uint32_t *process9Size, uint32_t *process9MemAddr)
+{
+ uint8_t *off = memfind(pos, size, "ess9", 4);
+ *process9Size = *(uint32_t *)(off - 0x60) * 0x200;
+ *process9MemAddr = *(uint32_t *)(off + 0xC);
+ // Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
+ return off - 0x204 + (*(uint32_t *)(off - 0x64) * 0x200) + 0x200;
}
-void patch_reboot() {
- //Look for firmlaunch code
- const uint8_t pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
+void
+patch_reboot()
+{
+ // Look for firmlaunch code
+ const uint8_t pattern[] = { 0xDE, 0x1F, 0x8D, 0xE2 };
- uint32_t process9Size, process9MemAddr;
- uint8_t *process9Offset = getProcess9((uint8_t*)firm_loc + firm_loc->section[2].offset + 0x15000, firm_loc->section[2].size - 0x15000, &process9Size, &process9MemAddr);
+ uint32_t process9Size, process9MemAddr;
+ uint8_t *process9Offset =
+ getProcess9((uint8_t *)firm_loc + firm_loc->section[2].offset + 0x15000, firm_loc->section[2].size - 0x15000, &process9Size, &process9MemAddr);
- fprintf(stderr, "reboot: proc9 mem @ %x\n", process9MemAddr);
+ fprintf(stderr, "reboot: proc9 mem @ %x\n", process9MemAddr);
- wait();
+ wait();
- uint8_t *off = memfind(process9Offset, process9Size, pattern, 4) - 0x10;
+ uint8_t *off = memfind(process9Offset, process9Size, pattern, 4) - 0x10;
- fprintf(stderr, "reboot: firmlaunch @ %x\n", off);
+ fprintf(stderr, "reboot: firmlaunch @ %x\n", off);
- //Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
- uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - process9Offset + process9MemAddr);
+ // Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
+ uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - process9Offset + process9MemAddr);
- fprintf(stderr, "reboot: fopen @ %x\n", fOpenOffset);
+ fprintf(stderr, "reboot: fopen @ %x\n", fOpenOffset);
- wait();
+ wait();
- //Copy firmlaunch code
- FILE* f = fopen(PATH_BITS "/reboot_hook.bin", "r");
- if (!f)
- abort("reboot: hook not found on SD\n");
+ // Copy firmlaunch code
+ FILE *f = fopen(PATH_BITS "/reboot_hook.bin", "r");
+ if (!f)
+ abort("reboot: hook not found on SD\n");
- uint32_t size = fsize(f);
- fread(off, 1, size, f);
- fclose(f);
+ uint32_t size = fsize(f);
+ fread(off, 1, size, f);
+ fclose(f);
- //Put the fOpen offset in the right location
- uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "open", 4);
- if (!pos_fopen)
- abort("reboot: fopen location missing\n");
+ // Put the fOpen offset in the right location
+ uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "open", 4);
+ if (!pos_fopen)
+ abort("reboot: fopen location missing\n");
- *pos_fopen = fOpenOffset;
+ *pos_fopen = fOpenOffset;
- uint32_t *pos_native = (uint32_t*)memfind(off, size, "NATF", 4);
- uint32_t *pos_twl = (uint32_t*)memfind(off, size, "TWLF", 4);
- uint32_t *pos_agb = (uint32_t*)memfind(off, size, "AGBF", 4);
+ uint32_t *pos_native = (uint32_t *)memfind(off, size, "NATF", 4);
+ uint32_t *pos_twl = (uint32_t *)memfind(off, size, "TWLF", 4);
+ uint32_t *pos_agb = (uint32_t *)memfind(off, size, "AGBF", 4);
- if (!pos_native && !pos_twl && !pos_agb)
- abort("reboot: missing string placeholder?\n");
+ if (!pos_native && !pos_twl && !pos_agb)
+ abort("reboot: missing string placeholder?\n");
- fprintf(stderr, "reboot: NATF @ %x\n", pos_native);
- fprintf(stderr, "reboot: TWLF @ %x\n", pos_twl);
- fprintf(stderr, "reboot: AGBF @ %x\n", pos_agb);
+ fprintf(stderr, "reboot: NATF @ %x\n", pos_native);
+ fprintf(stderr, "reboot: TWLF @ %x\n", pos_twl);
+ fprintf(stderr, "reboot: AGBF @ %x\n", pos_agb);
- uint8_t* mem = (uint8_t*)0x01FF8000; // 0x8000 space that will be resident.
+ uint8_t *mem = (uint8_t *)0x01FF8000; // 0x8000 space that will be resident.
- *pos_native = (uint32_t)mem;
- memcpy(mem, L"sdmc:", 10);
- mem += 10;
- for(size_t i=0; i < sizeof(PATH_NATIVE_P); i++, mem += 2) {
- *mem = PATH_NATIVE_P[i];
- *(mem + 1) = 0;
- }
+ *pos_native = (uint32_t)mem;
+ memcpy(mem, L"sdmc:", 10);
+ mem += 10;
+ for (size_t i = 0; i < sizeof(PATH_NATIVE_P); i++, mem += 2) {
+ *mem = PATH_NATIVE_P[i];
+ *(mem + 1) = 0;
+ }
- *pos_twl = (uint32_t)mem;
- memcpy(mem, L"sdmc:", 10);
- mem += 10;
- for(size_t i=0; i < sizeof(PATH_TWL_P); i++, mem += 2) {
- *mem = PATH_TWL_P[i];
- *(mem + 1) = 0;
- }
+ *pos_twl = (uint32_t)mem;
+ memcpy(mem, L"sdmc:", 10);
+ mem += 10;
+ for (size_t i = 0; i < sizeof(PATH_TWL_P); i++, mem += 2) {
+ *mem = PATH_TWL_P[i];
+ *(mem + 1) = 0;
+ }
- *pos_agb = (uint32_t)mem;
- memcpy(mem, L"sdmc:", 10);
- mem += 10;
- for(size_t i=0; i < sizeof(PATH_AGB_P); i++, mem += 2) {
- *mem = PATH_AGB_P[i];
- *(mem + 1) = 0;
- }
+ *pos_agb = (uint32_t)mem;
+ memcpy(mem, L"sdmc:", 10);
+ mem += 10;
+ for (size_t i = 0; i < sizeof(PATH_AGB_P); i++, mem += 2) {
+ *mem = PATH_AGB_P[i];
+ *(mem + 1) = 0;
+ }
- uint32_t *pos_rebc = (uint32_t*)memfind(off, size, "rebc", 4);
- *pos_rebc = (uint32_t)mem;
+ uint32_t *pos_rebc = (uint32_t *)memfind(off, size, "rebc", 4);
+ *pos_rebc = (uint32_t)mem;
- fprintf(stderr, "reboot: rebc @ %x\n", pos_rebc);
+ fprintf(stderr, "reboot: rebc @ %x\n", pos_rebc);
- f = fopen(PATH_BITS "/reboot_code.bin", "r");
- if (!f)
- abort("reboot: boot not found on SD\n");
+ f = fopen(PATH_BITS "/reboot_code.bin", "r");
+ if (!f)
+ abort("reboot: boot not found on SD\n");
- fread(mem, 1, fsize(f), f);
- fclose(f);
+ fread(mem, 1, fsize(f), f);
+ fclose(f);
- write_file((void*)0x1FF8000, "/test", 0x8000);
+ write_file((void *)0x1FF8000, "/test", 0x8000);
}
uint32_t svc = (i << 4) & j; // Actual svc index.
// Refuse to replace non-NULL services unless the user has it enabled.
- // Also don't bother checking for non-null svc files (it's slow.)
+ // Also don't bother checking for non-null svc files (it's slow.)
if (svcTable[svc] && !config.options[OPTION_REPLACE_ALLOCATED_SVC])
continue;
fprintf(stderr, "Svc: %s, %d bytes\n", at, size);
if (!freeSpace)
- for (freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
+ for (freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++)
+ ;
fprintf(stderr, "Svc: Copy code to %x\n", (uint32_t)freeSpace);
#define PATH_AGB_P PATH_TEMP "/p_agb"
#define PATH_TWL_P PATH_TEMP "/p_twl"
-#define PATH_KEYS PATH_CFW "/keys" // Keyfiles will be loaded from this dir, and
- // additionally the root if not found.
-#define PATH_EXEFS PATH_CFW "/exe" // ExeFS overrides, named like '<titleid>.exefs' - NYI
+#define PATH_KEYS PATH_CFW "/keys" // Keyfiles will be loaded from this dir, and
+ // additionally the root if not found.
+#define PATH_EXEFS PATH_CFW "/exe" // ExeFS overrides, named like '<titleid>.exefs' - NYI
-#define PATH_BITS PATH_CFW "/bits" // Path to misc bits we need (emunand code, reboot code, etc)
+#define PATH_BITS PATH_CFW "/bits" // Path to misc bits we need (emunand code, reboot code, etc)
-#define PATH_EMUNAND_CODE PATH_BITS "/emunand.bin" // Emunand hook.
+#define PATH_EMUNAND_CODE PATH_BITS "/emunand.bin" // Emunand hook.
#define PATH_SCREENINIT_CODE PATH_BITS "/screeninit.bin" // Screeninit code (ARM11)
#define PATH_NATIVE_F PATH_FIRMWARES "/native"
wait();
}
-
// Use ARM9 hook thread?
if (config.options[OPTION_ARM9THREAD]) {
// Yes.
// Use EmuNAND?
if (config.options[OPTION_EMUNAND]) {
// Yes.
- patch_emunand(config.options[OPTION_EMUNAND_INDEX]);
+ patch_emunand(config.options[OPTION_EMUNAND_INDEX]);
wait();
}
static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
-void screen_init() {
- if (PDN_GPU_CNT == 1) {
- uint32_t* screenInitAddress = (uint32_t*)0x24FFFC00;
+void
+screen_init()
+{
+ if (PDN_GPU_CNT == 1) {
+ uint32_t *screenInitAddress = (uint32_t *)0x24FFFC00;
- FILE* f = fopen(PATH_SCREENINIT_CODE, "r");
- fread(screenInitAddress, 1, fsize(f), f); // Read in the screeninit payload.
- fclose(f);
+ FILE *f = fopen(PATH_SCREENINIT_CODE, "r");
+ fread(screenInitAddress, 1, fsize(f), f); // Read in the screeninit payload.
+ fclose(f);
- //Write brightness level for the stub to pick up
- screenInitAddress[2] = 0x5F;
- *a11_entry = (uint32_t)screenInitAddress;
+ // Write brightness level for the stub to pick up
+ screenInitAddress[2] = 0x5F;
+ *a11_entry = (uint32_t)screenInitAddress;
- while(*a11_entry);
+ while (*a11_entry)
+ ;
- //Turn on backlight
- i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
- }
+ // Turn on backlight
+ i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
+ }
}
fprintf(stderr, x); \
wait_key(); \
clear_disp(stderr); \
- set_cursor(stderr, 0, 0); \
+ set_cursor(stderr, 0, 0); \
menu_poweroff(); \
}
fseek(f, 0, SEEK_END);
for (int i = 0; i < TEXT_BOTTOM_HEIGHT - 1; i++) {
char *text = text_buffer_bottom + (TEXT_BOTTOM_WIDTH * i);
- for(int j = 0; j < TEXT_BOTTOM_WIDTH; j++) {
- if (text[j] == 0)
- text[j] = ' ';
- }
+ for (int j = 0; j < TEXT_BOTTOM_WIDTH; j++) {
+ if (text[j] == 0)
+ text[j] = ' ';
+ }
fwrite(text, 1, strnlen(text, TEXT_BOTTOM_WIDTH), f);
fwrite("\n", 1, 1, f);
}
// DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
// DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
-size_t get_file_sector(char* path) {
- FILE* temp = fopen(path, "r");
+size_t
+get_file_sector(char *path)
+{
+ FILE *temp = fopen(path, "r");
if (!temp || !temp->is_open)
return 0;
- UINT sector;
+ UINT sector;
- f_getsector(& temp->handle, §or);
+ f_getsector(&temp->handle, §or);
- fclose(temp);
+ fclose(temp);
- return sector;
+ return sector;
}
size_t write_file(void *data, char *path, size_t size);
size_t read_file(void *data, char *path, size_t size);
-size_t get_file_sector(char* path);
+size_t get_file_sector(char *path);
#endif