int CheckInstallationData(){ File file; char str[64]; switch (getMpInfo()) { case MPINFO_CTR: getFirmPath(str, TID_CTR_NATIVE_FIRM); if(!FileOpen(&file, str, 0)) return -1; FileClose(&file); getFirmPath(str, TID_CTR_TWL_FIRM); if(!FileOpen(&file, str, 0)) return -2; FileClose(&file); getFirmPath(str, TID_CTR_AGB_FIRM); if(!FileOpen(&file, str, 0)) return -3; FileClose(&file); if(!FileOpen(&file, "rxTools/data/data.bin", 0)) return -4; FileRead(&file, str, 32, 0); FileClose(&file); if(memcmp(str, __DATE__, 11)) return -5; if(memcmp(&str[12], __TIME__, 8)) return -5; return 0; case MPINFO_KTR: getFirmPath(str, TID_KTR_NATIVE_FIRM); if(!FileOpen(&file, str, 0)) return -1; FileClose(&file); default: return 0; } }
unsigned int checkEmuNAND() { uint8_t *check = (uint8_t *)0x26000000; int isn3ds = 0; if (getMpInfo() == MPINFO_KTR)isn3ds = 1; sdmmc_sdcard_readsectors(isn3ds ? 0x4D800000 /0x200 : 0x3AF00000 / 0x200, 1, check); if (*((char *)check + 0x100) == 'N' && *((char *)check + 0x101) == 'C' && *((char *)check + 0x102) == 'S' && *((char *)check + 0x103) == 'D') { return isn3ds ? 0x4D800000 : 0x3AF00000; } else { sdmmc_sdcard_readsectors(isn3ds ? 0x76000000 /0x200 : 0x3BA00000 / 0x200, 1, check); if (*((char *)check + 0x100) == 'N' && *((char *)check + 0x101) == 'C' && *((char *)check + 0x102) == 'S' && *((char *)check + 0x103) == 'D') { return isn3ds ? 0x76000000 : 0x3BA00000; } else { return 0; } } }
void nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out, unsigned int partition) { PartitionInfo info; uint8_t myCtr[16]; if (partition == CTRNAND && getMpInfo() == MPINFO_KTR) partition = KTR_CTRNAND; //SWITCH TO KTR_CTRNAND IF ON N3DS for (int i = 0; i < 16; i++) { myCtr[i] = NANDCTR[i]; } info.ctr = myCtr; info.buffer = out; info.size = numsectors * 0x200; info.keyY = NULL; add_ctr(info.ctr, partition / 16); switch (partition) { case TWLN : info.keyslot = 0x3; break; case TWLP : info.keyslot = 0x3; break; case AGB_SAVE : info.keyslot = 0x7; break; case FIRM0 : info.keyslot = 0x6; break; case FIRM1 : info.keyslot = 0x6; break; case CTRNAND : info.keyslot = 0x4; break; case KTR_CTRNAND: info.keyslot = 0x5; break; } add_ctr(info.ctr, sector_no * 0x20); sdmmc_nand_readsectors(sector_no + partition / 0x200, numsectors, out); DecryptPartition(&info); }
//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(); }
uint8_t* decryptFirmTitleNcch(uint8_t* title, size_t *size) { const size_t sector = 512; const size_t header = 512; ctr_ncchheader NCCH; uint8_t CTR[16]; PartitionInfo INFO; NCCH = *((ctr_ncchheader*)title); if(memcmp(NCCH.magic, "NCCH", 4) != 0) return NULL; ncch_get_counter(NCCH, CTR, 2); INFO.ctr = CTR; INFO.buffer = title + getle32(NCCH.exefsoffset)*sector; INFO.keyY = NCCH.signature; INFO.size = getle32(NCCH.exefssize)*sector; INFO.keyslot = 0x2C; DecryptPartition(&INFO); if (size != NULL) *size = INFO.size - header; uint8_t* firm = (uint8_t*)(INFO.buffer + header); if (getMpInfo() == MPINFO_KTR) if (decryptFirmKtrArm9(firm)) return NULL; return firm; }
static void *findCounter(void) { uint32_t i; if (getMpInfo() == MPINFO_KTR) { if (*(uint32_t *)fsCounter9Ktr == 0x5C980) { sysver = 9; return (void *)(fsCounter9Ktr + 0x30); } } else { for (i = 0; i < sizeof(fsCountersCtr) / sizeof(uintptr_t); i++) if (*(uint32_t *)fsCountersCtr[i] == 0x5C980) { sysver = i + 3; return (void *)(fsCountersCtr[i] + 0x30); } } // If value not in previous list start memory scanning (test range) for (i = 0x080D8FFC; i > 0x08000000; i -= sizeof(uint32_t)) if (((uint32_t *)i)[0] == 0x5C980 && ((uint32_t *)i)[1] == 0x800005C9) return (void *)(i + 0x30); return NULL; }
//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);*/ uint8_t* firm = (void*)0x24000000; 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 uint8_t patch1[] = { 0x6D, 0x20, 0xCE, 0x77 }; uint8_t patch2[] = { 0x5A, 0xC5, 0x73, 0xC1 }; memcpy((uint32_t*)0x08052FD8, patch1, 4); memcpy((uint32_t*)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; }
int rxMode(int emu) { wchar_t path[64]; const char *shstrtab; const wchar_t *msg; uint8_t keyx[16]; uint32_t tid; int r, sector; Elf32_Ehdr *ehdr; Elf32_Shdr *shdr, *btm; void *keyxArg; FIL fd; UINT br, fsz; if (emu) { sector = checkEmuNAND(); if (sector == 0) { 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); swprintf(path, _MAX_LFN, L"/rxTools/Theme/%u/boot.bin", cfgs[CFG_THEME].val.i); DrawBottomSplash(path); } } else sector = 0; r = getMpInfo(); switch (r) { case MPINFO_KTR: tid = TID_KTR_NATIVE_FIRM; break; case MPINFO_CTR: tid = TID_CTR_NATIVE_FIRM; break; default: msg = L"Unknown Platform: %d"; goto fail; } setAgbBios(); if (sysver < 7 && f_open(&fd, _T("slot0x25KeyX.bin"), FA_READ) == FR_OK) { f_read(&fd, keyx, sizeof(keyx), &br); f_close(&fd); keyxArg = keyx; } else keyxArg = NULL; getFirmPath(path, tid); r = loadFirm(path, &fsz); if (r) { msg = L"Failed to load NATIVE_FIRM: %d\n" L"Reboot rxTools and try again.\n"; goto fail; } ((FirmHdr *)FIRM_ADDR)->arm9Entry = 0x0801B01C; getFirmPatchPath(path, tid); r = f_open(&fd, path, FA_READ); if (r != FR_OK) goto patchFail; r = f_read(&fd, (void *)PATCH_ADDR, PATCH_SIZE, &br); if (r != FR_OK) goto patchFail; f_close(&fd); ehdr = (void *)PATCH_ADDR; shdr = (void *)(PATCH_ADDR + ehdr->e_shoff); shstrtab = (char *)PATCH_ADDR + shdr[ehdr->e_shstrndx].sh_offset; for (btm = shdr + ehdr->e_shnum; shdr != btm; shdr++) { if (!strcmp(shstrtab + shdr->sh_name, ".patch.p9.reboot.body")) { execReboot(sector, keyxArg, ehdr->e_entry, shdr); __builtin_unreachable(); } } msg = L".patch.p9.reboot.body not found\n" L"Please 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 the patch: %d\n" L"Check your installation.\n"; goto fail; }
__attribute__((section(".text.start"), noreturn)) void _start() { static const TCHAR fontPath[] = _T("") SYS_PATH "/" FONT_NAME; void *fontBuf; UINT btr, br; int r; FIL f; // Enable TMIO IRQ *(volatile uint32_t *)0x10001000 = 0x00010000; preloadStringsA(); if (!FSInit()) { DrawString(BOT_SCREEN, strings[STR_FAILED], BOT_SCREEN_WIDTH / 2, SCREEN_HEIGHT - FONT_HEIGHT, RED, BLACK); while (1); } set_loglevel(ll_info); log(ll_info, "Initializing rxTools..."); setConsole(); fontIsLoaded = 0; r = f_open(&f, fontPath, FA_READ); if (r == FR_OK) { btr = f_size(&f); fontBuf = __builtin_alloca(btr); r = f_read(&f, fontBuf, btr, &br); if (r == FR_OK) fontIsLoaded = 1; f_close(&f); fontaddr = fontBuf; } if (fontIsLoaded) preloadStringsU(); else warn(L"Failed to load " FONT_NAME ": %d\n", r); if (getMpInfo() == MPINFO_KTR) { r = initN3DSKeys(); if (r != FR_OK) { warn(L"Failed to load keys for N3DS\n" " Code: %d\n" " RxMode will not boot. Please\n" " include key_0x16.bin and\n" " key_0x1B.bin at the root of your\n" " SD card.\n", r); InputWait(); goto postinstall; } } install(); postinstall: readCfg(); log(ll_info, "Done..."); r = loadStrings(); if (r) warn(L"Failed to load strings: %d\n", r); drawTop(); //Default boot check if (cfgs[CFG_DEFAULT].val.i && HID_STATE & BUTTON_L1) { if(cfgs[CFG_DEFAULT].val.i == 3) PastaMode(); else rxMode(cfgs[CFG_DEFAULT].val.i - 1); } if (sysver < 7) { r = initKeyX(); if (r != FR_OK) warn(L"Failed to load key X for slot 0x25\n" " Code: %d\n" " If your firmware version is less\n" " than 7.X, some titles decryption\n" " will fail, and some EmuNANDs\n" " will not boot.\n", r); } if (warned) { warn(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); WaitForButton(BUTTON_A); } OpenAnimation(); mainLoop(); }
int InstallData(char* drive){ static const FirmInfo agb_info = { 0x8B800, 0x4CE00, 0x08006800, 0xD600, 0xE200, 0x08020000}; static const FirmInfo twl_info = { 0x153600, 0x4D200, 0x08006800, 0xD600, 0xE200, 0x08020000}; FIL firmfile; unsigned int progressWidth, progressX; wchar_t progressbar[8] = {0,}; wchar_t *progress = progressbar; int i; progressWidth = getMpInfo() == MPINFO_CTR ? 7 : 3; progressX = (BOT_SCREEN_WIDTH - progressWidth * FONT_WIDTH) / 2; for (i = 0; i < progressWidth; i++) wcscat(progressbar, strings[STR_PROGRESS]); print(L"%ls", progressbar); ConsolePrevLine(); //Create the workdir sprintf(tmpstr, "%s:%s", drive, DATAFOLDER); f_mkdir(tmpstr); //Read firmware data if (f_open(&firmfile, "firmware.bin", FA_READ | FA_OPEN_EXISTING) != FR_OK) return CONF_NOFIRMBIN; wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); //Create decrypted native_firm f_read(&firmfile, WORKBUF, NAT_SIZE, &tmpu32); uint8_t* n_firm = decryptFirmTitle(WORKBUF, NAT_SIZE, 0x00000002, 1); wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); getFirmPath(tmpstr, getMpInfo() == MPINFO_KTR ? TID_KTR_NATIVE_FIRM : TID_CTR_NATIVE_FIRM); if(FileOpen(&tempfile, tmpstr, 1)){ FileWrite(&tempfile, n_firm, NAT_SIZE, 0); FileClose(&tempfile); }else { f_close(&firmfile); return CONF_ERRNFIRM; } wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); if (getMpInfo() != MPINFO_CTR) goto end; //Create AGB patched firmware f_read(&firmfile, WORKBUF, AGB_SIZE, &tmpu32); uint8_t* a_firm = decryptFirmTitle(WORKBUF, AGB_SIZE, 0x00000202, 1); if (!a_firm && checkEmuNAND()) { /* Try to get the Title Key from the EmuNAND */ a_firm = decryptFirmTitle(WORKBUF, AGB_SIZE, 0x00000202, 2); if (!a_firm) { /* If we cannot decrypt it from firmware.bin because of titlekey messed up, it probably means that AGB has been modified in some way. */ //So we read it from his installed ncch... FindApp(0x00040138, 0x00000202, 1); char* path = getContentAppPath(); if (!FileOpen(&tempfile, path, 0) && checkEmuNAND()) { /* Try with EmuNAND */ FindApp(0x00040138, 0x00000202, 2); path = getContentAppPath(); if (!FileOpen(&tempfile, path, 0)) { f_close(&firmfile); return CONF_ERRNFIRM; } } FileRead(&tempfile, WORKBUF, AGB_SIZE, 0); FileClose(&tempfile); a_firm = decryptFirmTitleNcch(WORKBUF, AGB_SIZE); } } if (a_firm) { if (applyPatch(a_firm, "/rxTools/system/patches/ctr/agb_firm.elf", &agb_info)) return CONF_ERRPATCH; getFirmPath(tmpstr, TID_CTR_TWL_FIRM); if(FileOpen(&tempfile, tmpstr, 1)){ FileWrite(&tempfile, a_firm, AGB_SIZE, 0); FileClose(&tempfile); }else { f_close(&firmfile); return CONF_ERRNFIRM; } wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); } else { wcsncpy(progress, strings[STR_PROGRESS_FAIL], wcslen(strings[STR_PROGRESS_FAIL])); progress += wcslen(strings[STR_PROGRESS_FAIL]); //If we get here, then we'll play without AGB, lol } DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); //Create TWL patched firmware f_read(&firmfile, WORKBUF, TWL_SIZE, &tmpu32); uint8_t* t_firm = decryptFirmTitle(WORKBUF, TWL_SIZE, 0x00000102, 1); if(t_firm){ if (applyPatch(t_firm, "/rxTools/system/patches/ctr/twl_firm.elf", &twl_info)) return CONF_ERRPATCH; getFirmPath(tmpstr, TID_CTR_TWL_FIRM); if(FileOpen(&tempfile, tmpstr, 1)){ FileWrite(&tempfile, t_firm, TWL_SIZE, 0); FileClose(&tempfile); //FileCopy("0004013800000102.bin", tmpstr); }else { f_close(&firmfile); return CONF_ERRNFIRM; } wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); }else{ wcsncpy(progress, strings[STR_PROGRESS_FAIL], wcslen(strings[STR_PROGRESS_FAIL])); progress += wcslen(strings[STR_PROGRESS_FAIL]); } DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); sprintf(tmpstr, "%s:%s/data.bin", drive, DATAFOLDER); if(FileOpen(&tempfile, tmpstr, 1)){ FileWrite(&tempfile, __DATE__, 12, 0); FileWrite(&tempfile, __TIME__, 9, 12); FileClose(&tempfile); }else { f_close(&firmfile); return CONF_CANTOPENFILE; } wcsncpy(progress, strings[STR_PROGRESS_OK], wcslen(strings[STR_PROGRESS_OK])); progress += wcslen(strings[STR_PROGRESS_OK]); DrawString(BOT_SCREEN, progressbar, progressX, 50, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); end: f_close(&firmfile); return 0; }
int rxMode(int emu) { const Elf32_Addr line = 32; wchar_t path[64]; const char *shstrtab; const wchar_t *msg; uint8_t keyx[16]; uint32_t tid; int r, sector; Elf32_Ehdr *ehdr; Elf32_Shdr *shdr, *btmShdr; Elf32_Addr cur, btm; void *keyxArg; FIL fd; UINT br, fsz; if (emu) { sector = checkEmuNAND(); if (sector == 0) { 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); swprintf(path, _MAX_LFN, L"/rxTools/Theme/%u/boot.bin", cfgs[CFG_THEME].val.i); DrawBottomSplash(path); } } else sector = 0; r = getMpInfo(); switch (r) { case MPINFO_KTR: tid = TID_KTR_NATIVE_FIRM; break; case MPINFO_CTR: tid = TID_CTR_NATIVE_FIRM; break; default: msg = L"Unknown Platform: %d"; goto fail; } setAgbBios(); if (sysver < 7 && f_open(&fd, _T("slot0x25KeyX.bin"), FA_READ) == FR_OK) { f_read(&fd, keyx, sizeof(keyx), &br); f_close(&fd); keyxArg = keyx; } else keyxArg = NULL; getFirmPath(path, tid); r = loadFirm(path, &fsz); if (r) { msg = L"Failed to load NATIVE_FIRM: %d\n" L"Reboot rxTools and try again.\n"; goto fail; } ((FirmHdr *)FIRM_ADDR)->arm9Entry = 0x0801B01C; getFirmPatchPath(path, tid); r = f_open(&fd, path, FA_READ); if (r != FR_OK) goto patchFail; r = f_read(&fd, (void *)PATCH_ADDR, PATCH_SIZE, &br); if (r != FR_OK) goto patchFail; f_close(&fd); ehdr = (void *)PATCH_ADDR; shdr = (void *)(PATCH_ADDR + ehdr->e_shoff); shstrtab = (char *)PATCH_ADDR + shdr[ehdr->e_shstrndx].sh_offset; for (btmShdr = shdr + ehdr->e_shnum; shdr != btmShdr; shdr++) { if (!strcmp(shstrtab + shdr->sh_name, ".patch.p9.reboot.body")) { memcpy((void *)ehdr->e_entry, (void *)(PATCH_ADDR + shdr->sh_offset), shdr->sh_size); // Drain write buffer __asm__ volatile ("mcr p15, 0, %0, c7, c10, 4" :: "r"(0)); cur = ehdr->e_entry & ~(line - 1); btm = ehdr->e_entry + shdr->sh_size; while (cur < btm) { __asm__ volatile ( // Clean Dcache "mcr p15, 0, %0, c7, c10, 1\n\t" // Flush Icache "mcr p15, 0, %0, c7, c5, 1" :: "r"(cur)); cur += line; } ((void (*)(uint32_t, void *, uintptr_t))ehdr->e_entry)( sector, keyxArg, 0x1FFFFFF8); __builtin_unreachable(); } }
static size_t getNandSize() { return getMpInfo() == MPINFO_KTR ? 0x4D800000 : 0x3AF00000; }
void DumpNandPartitions(){ ConsoleSetTitle(strings[STR_DUMP], strings[STR_NAND_PARTITIONS]); int isEmuNand = SYS_NAND; if(checkEmuNAND() && (isEmuNand = NandSwitch()) == UNK_NAND) return; isEmuNand--; ConsoleInit(); ConsoleSetTitle(strings[STR_DUMP], strings[STR_NAND_PARTITIONS]); print(strings[STR_PROCESSING], isEmuNand ? strings[STR_EMUNAND] : strings[STR_SYSNAND]); wchar_t* p_name[] = { L"twln.bin", L"twlp.bin", L"agb_save.bin", L"firm0.bin", L"firm1.bin", L"ctrnand.bin" }; wchar_t* p_descr[] = { strings[STR_TWLN], strings[STR_TWLP], strings[STR_AGB_SAVE], strings[STR_FIRM0], strings[STR_FIRM1], strings[STR_CTRNAND] }; unsigned int p_size[] = { 0x08FB5200, 0x020B6600, 0x00030000, 0x00400000, 0x00400000, getMpInfo() == MPINFO_KTR ? 0x41D2D200 : 0x2F3E3600 }; unsigned int p_addr[] = { TWLN, TWLP, AGB_SAVE, FIRM0, FIRM1, CTRNAND }; int sect_row = 0x80; wchar_t tmp[_MAX_LFN]; for(int i = 3; i < 6; i++){ //Cutting out twln, twlp and agb_save. Todo: Properly decrypt them File out; swprintf(tmp, _MAX_LFN, L"rxTools/nand/%ls%ls", isEmuNand ? L"emu_" : L"", p_name[i]); FileOpen(&out, tmp, 1); print(strings[STR_DUMPING], p_descr[i], tmp); ConsoleShow(); for(int j = 0; j*0x200 < p_size[i]; j += sect_row){ swprintf(tmp, _MAX_LFN, L"%08X / %08X", j*0x200, p_size[i]); int x, y; ConsoleGetXY(&x, &y); y += FONT_HEIGHT * 3; x += FONT_HWIDTH*2; ConsoleShow(); DrawString(BOT_SCREEN, tmp, x, y, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); if(isEmuNand) emunand_readsectors(j, sect_row, BUF1, p_addr[i]); else nand_readsectors(j, sect_row, BUF1, p_addr[i]); FileWrite(&out, BUF1, sect_row*0x200, j*0x200); } FileClose(&out); } print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); }
DrawString(BOT_SCREEN, tmp, x, y, ConsoleGetTextColor(), ConsoleGetBackgroundColor()); if(isEmuNand) emunand_readsectors(j, sect_row, BUF1, p_addr[i]); else nand_readsectors(j, sect_row, BUF1, p_addr[i]); FileWrite(&out, BUF1, sect_row*0x200, j*0x200); } FileClose(&out); } print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); } void GenerateNandXorpads(){ PadInfo myInfo = { .keyslot = getMpInfo() == MPINFO_KTR ? 0x5 : 0x4, .setKeyY = 0, .size_mb = getMpInfo() == MPINFO_KTR ? 1055 : 758, .filename = L"rxTools/nand.fat16.xorpad" }; GetNANDCTR(myInfo.CTR); add_ctr(myInfo.CTR, 0xB93000); ConsoleInit(); ConsoleSetTitle(strings[STR_GENERATE], strings[STR_NAND_XORPAD]); print(strings[STR_DUMPING], strings[STR_NAND_XORPAD], myInfo.filename); ConsoleShow(); CreatePad(&myInfo, 0); print(strings[STR_PRESS_BUTTON_ACTION], strings[STR_BUTTON_A], strings[STR_CONTINUE]); ConsoleShow(); WaitForButton(BUTTON_A); } void DumpNANDSystemTitles(){ ConsoleSetTitle(strings[STR_DUMP], strings[STR_SYSTEM_TITLES]);