void FirmLoader(){ char firm_path[256]; if (!FileExplorerMain(firm_path, sizeof(firm_path))) { UINT fsz; if (loadFirm(firm_path, &fsz)) { ConsoleInit(); ConsoleSetTitle(strings[STR_LOAD], strings[STR_FIRMWARE_FILE]); print(strings[STR_WRONG], "", strings[STR_FIRMWARE_FILE]); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); return; } if (loadExecReboot()) { ConsoleInit(); ConsoleSetTitle(strings[STR_LOAD], strings[STR_FIRMWARE_FILE]); print(strings[STR_ERROR_LAUNCHING], strings[STR_FIRMWARE_FILE]); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); return; } } }
//Just patches signatures check, loads in sysnand int PastaMode(){ /*PastaMode is ready for n3ds BUT there's an unresolved bug which affects nand reading functions, like nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM0);*/ uint8_t* firm = (void*)FIRM_ADDR; nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM0); if (strncmp((char*)firm, "FIRM", 4)) nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM1); if(getMpInfo() == MPINFO_CTR) { //o3ds patches unsigned char sign1[] = { 0xC1, 0x17, 0x49, 0x1C, 0x31, 0xD0, 0x68, 0x46, 0x01, 0x78, 0x40, 0x1C, 0x00, 0x29, 0x10, 0xD1 }; unsigned char sign2[] = { 0xC0, 0x1C, 0x76, 0xE7, 0x20, 0x00, 0x74, 0xE7, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; unsigned char patch1[] = { 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }; unsigned char patch2[] = { 0x00, 0x20 }; for (int i = 0; i < 0xF0000; i++){ if (!memcmp(firm + i, sign1, 16)){ memcpy(firm + i, patch1, 6); } if (!memcmp(firm + i, sign2, 16)){ memcpy(firm + i, patch2, 2); } } } else { //new 3ds patches decryptFirmKtrArm9((void *)FIRM_ADDR); uint8_t patch0[] = { 0x00, 0x20, 0x3B, 0xE0 }; uint8_t patch1[] = { 0x00, 0x20, 0x08, 0xE0 }; memcpy((uint32_t*)(FIRM_ADDR + 0xB39D8), patch0, 4); memcpy((uint32_t*)(FIRM_ADDR + 0xB9204), patch1, 4); } return loadExecReboot(); }
void FirmLoader(TCHAR firm_path[]){ UINT fsz; if (loadFirm(firm_path, &fsz)) { ConsoleInit(); ConsoleSetTitle(strings[STR_LOAD], strings[STR_FIRMWARE_FILE]); print(strings[STR_WRONG], L"", strings[STR_FIRMWARE_FILE]); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); return; } if (loadExecReboot()) { ConsoleInit(); ConsoleSetTitle(strings[STR_LOAD], strings[STR_FIRMWARE_FILE]); print(strings[STR_ERROR_LAUNCHING], strings[STR_FIRMWARE_FILE]); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); return; } }
//Just patches signatures check, loads in sysnand int DevMode(){ /*DevMode is ready for n3ds BUT there's an unresolved bug which affects nand reading functions, like nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM0);*/ u8* firm = (void*)0x24000000; nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM0); if (strncmp((char*)firm, "FIRM", 4)) nand_readsectors(0, 0xF0000 / 0x200, firm, FIRM1); if(Platform_CheckUnit() == PLATFORM_3DS) { //o3ds patches unsigned char sign1[] = { 0xC1, 0x17, 0x49, 0x1C, 0x31, 0xD0, 0x68, 0x46, 0x01, 0x78, 0x40, 0x1C, 0x00, 0x29, 0x10, 0xD1 }; unsigned char sign2[] = { 0xC0, 0x1C, 0x76, 0xE7, 0x20, 0x00, 0x74, 0xE7, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F }; unsigned char patch1[] = { 0x00, 0x20, 0x4E, 0xB0, 0x70, 0xBD }; unsigned char patch2[] = { 0x00, 0x20 }; for (int i = 0; i < 0xF0000; i++){ if (!memcmp(firm + i, sign1, 16)){ memcpy(firm + i, patch1, 6); } if (!memcmp(firm + i, sign2, 16)){ memcpy(firm + i, patch2, 2); } } } else { //new 3ds patches u8 patch1[] = { 0x6D, 0x20, 0xCE, 0x77 }; u8 patch2[] = { 0x5A, 0xC5, 0x73, 0xC1 }; memcpy((u32*)0x08052FD8, patch1, 4); memcpy((u32*)0x08058804, patch2, 4); } return loadExecReboot(); }
int rxMode(int emu) { if (!checkEmuNAND() && emu) { ConsoleInit(); ConsoleSetTitle(L"EMUNAND NOT FOUND!"); print(L"The emunand was not found on\n"); print(L"your SDCard. \n"); print(L"\n"); print(L"Press A to boot SYSNAND\n"); ConsoleShow(); WaitForButton(BUTTON_A); emu = 0; char s[32]; sprintf(s, "/rxTools/Theme/%u/boot.bin", cfgs[CFG_THEME].val.i); DrawBottomSplash(s); } static const char patchNandPrefix[] = ".patch.p9.nand"; unsigned int cur, offset, shstrSize; char path[64], shstrtab[512], *sh_name; const char *platformDir; const wchar_t *msg; int r, sector; void *p; Elf32_Ehdr ehdr; Elf32_Shdr shdr; FIL fd, keyxFd; UINT br, fsz; setAgbBios(); getFirmPath(path, getMpInfo() == MPINFO_KTR ? TID_KTR_NATIVE_FIRM : TID_CTR_NATIVE_FIRM); strcpy(path + strlen(path) - 4, "orig.bin"); r = loadFirm(path, &fsz); if (r) { msg = L"Failed to load NATIVE_FIRM: %d\n" L"Reboot rxTools and try again.\n"; goto fail; } r = getMpInfo(); switch (r) { case MPINFO_KTR: platformDir = "ktr"; break; case MPINFO_CTR: platformDir = "ctr"; break; default: msg = L"Unknown Platform: %d"; goto fail; } sprintf(path, SYS_PATH "/patches/%s/native_firm.elf", platformDir); r = f_open(&fd, path, FA_READ); if (r != FR_OK) goto patchFail; r = f_read(&fd, &ehdr, sizeof(ehdr), &br); if (r != FR_OK) goto patchFail; r = f_lseek(&fd, ehdr.e_shoff + ehdr.e_shstrndx * sizeof(Elf32_Shdr)); if (r != FR_OK) goto patchFail; r = f_read(&fd, &shdr, sizeof(shdr), &br); if (r != FR_OK) goto patchFail; r = f_lseek(&fd, shdr.sh_offset); if (r != FR_OK) goto patchFail; r = f_read(&fd, shstrtab, shdr.sh_size > sizeof(shstrtab) ? sizeof(shstrtab) : shdr.sh_size, &shstrSize); if (r != FR_OK) goto patchFail; if (emu) { sector = checkEmuNAND(); if (sector == 0) { msg = L"Failed to find EmuNAND.\n" L"Check your EmuNAND.\n"; goto fail; } } else sector = 0; cur = ehdr.e_shoff; for (; ehdr.e_shnum; ehdr.e_shnum--, cur += sizeof(shdr)) { if (f_lseek(&fd, cur) != FR_OK) continue; if (f_read(&fd, &shdr, sizeof(shdr), &br) != FR_OK) continue; if (!(shdr.sh_flags & SHF_ALLOC) || shdr.sh_name >= shstrSize) continue; offset = locateSecInFirm(&shdr, (FirmHdr *)FIRM_ADDR); if (offset == 0) continue; p = (void *)(FIRM_ADDR + offset); sh_name = shstrtab + shdr.sh_name; if (!strcmp(sh_name, ".rodata.keyx")) { if (sysver >= 7) continue; if (f_open(&keyxFd, "slot0x25KeyX.bin", FA_READ) != FR_OK) continue; f_read(&keyxFd, p, shdr.sh_size, &br); f_close(&keyxFd); } else if (!strcmp(sh_name, ".rodata.nand.sector")) { if (sector) *(uint32_t *)p = (sector / 0x200) - 1; } else if (!strcmp(sh_name, ".rodata.label")) { *(uint32_t *)p = sector ? 'E-XR' : 'S-XR'; } else if (shdr.sh_type == SHT_PROGBITS && (sector || memcmp(sh_name, patchNandPrefix, sizeof(patchNandPrefix) - 1)) && (sysver < 7 || strcmp(sh_name, ".patch.p9.keyx"))) { if (f_lseek(&fd, shdr.sh_offset) != FR_OK) continue; f_read(&fd, p, shdr.sh_size, &br); } } getFirmPath(path, getMpInfo() == MPINFO_KTR ? TID_KTR_NATIVE_FIRM : TID_CTR_NATIVE_FIRM); f_open(&fd, path, FA_WRITE | FA_CREATE_ALWAYS); f_write(&fd, (void *)FIRM_ADDR, fsz, &br); f_close(&fd); r = loadExecReboot(); // This won't return if it succeeds. msg = L"Failed to load reboot.bin: %d\n" L"Check your installation.\n"; fail: ConsoleInit(); ConsoleSetTitle(L"rxMode"); print(msg, r); print(L"\n"); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); return r; patchFail: msg = L"Failed to load native_firm.elf: %d\n" L"Check your installation.\n"; goto fail; }
static int firmlaunch(u8* firm){ memcpy(FIRM_ADDR, firm, 0x200000); //Fixed size, no FIRM right now is that big return loadExecReboot(); }