diff --git a/arm9/Makefile b/arm9/Makefile index 92657de..0c7ce9a 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -26,7 +26,7 @@ endif # Print new version if changed ifeq (,$(findstring $(GIT_VER), $(shell cat include/version.h))) -$(shell printf "\"$(GIT_VER)\"" > ../../nitrofiles/version_twlnandtool) +$(shell echo -n $(GIT_VER) > ../../nitrofiles/version_twlnandtool) $(shell printf "#ifndef VERSION_H\n#define VERSION_H\n\n#define VERSION \"$(GIT_VER)\"\n\n#endif // VERSION_H\n" > include/version.h) endif diff --git a/arm9/src/main.c b/arm9/src/main.c index 943af1d..259df88 100644 --- a/arm9/src/main.c +++ b/arm9/src/main.c @@ -79,9 +79,8 @@ PrintConsole topScreen; PrintConsole bottomScreen; typedef enum { - MENUSTATE_CHECK_NANDFIRM, MENUSTATE_FS_MENU, - MENUSTATE_CHECK_NANDINFO, + MENUSTATE_NF_MENU, MENUSTATE_TEST, MENUSTATE_EXIT } MenuState; @@ -101,9 +100,8 @@ static int _mainMenu(int cursor) setMenuHeader(m, "TwlNandTool"); char modeStr[32]; - addMenuItem(m, "Check NandFirm", NULL, 0); addMenuItem(m, "FileSystem Menu", NULL, 0); - addMenuItem(m, "CID Info", NULL, 0); + addMenuItem(m, "NandFirm menu", NULL, 0); addMenuItem(m, "Debug1", NULL, 0); addMenuItem(m, "Exit", NULL, 0); @@ -152,9 +150,9 @@ int main(int argc, char **argv) consoleSign = fifoGetValue32(FIFO_USER_01); if (consoleSign == 0x00) { - strcpy(consoleSignName, "RETAIL"); + strcpy(consoleSignName, "prod"); } else { - strcpy(consoleSignName, "PANDA"); + strcpy(consoleSignName, "dev"); } videoInit(); @@ -183,11 +181,18 @@ int main(int argc, char **argv) if(!nitroFSInit("TwlNandTool.prod.srl") || !nitroFSGood()) { if(!nitroFSInit("TwlNandTool.dev.srl") || !nitroFSGood()) { if(!nitroFSInit("ntrboot.nds") || !nitroFSGood()) { - messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[40m\nSome features will not work.\n\nTry placing the SRL for your DSion your SD card root like this:\n\nSDMC:/TwlNandTool.prod.srl\nSDMC:/TwlNandTool.dev.srl\nSDMC:/ntrboot.nds\n\n"); + while (true) + { + swiWaitForVBlank(); + scanKeys(); + + if (keysDown() & KEY_SELECT ) + break; + } + messageBox("nitroFSInit()...\x1B[31mFailed\n\x1B[40m\nSome features will not work.\n\nTry placing the SRL for your DSion your SD card root like this:\n\nSDMC:/TwlNandTool.prod.srl\nSDMC:/TwlNandTool.dev.srl\nSDMC:/ntrboot.nds\n"); } } } - //return 0; } //setup nand access @@ -204,20 +209,16 @@ int main(int argc, char **argv) switch (cursor) { - case MENUSTATE_CHECK_NANDFIRM: - nandFirmRead(); - break; - case MENUSTATE_FS_MENU: fsMain(); break; - case MENUSTATE_CHECK_NANDINFO: - nandPrintInfo(); + case MENUSTATE_NF_MENU: + nfMain(); break; case MENUSTATE_TEST: - testRoutine(); + debug1(); break; case MENUSTATE_EXIT: @@ -240,72 +241,27 @@ int main(int argc, char **argv) return 0; } -int testRoutine(void) { +int debug1(void) { clearScreen(cSUB); - iprintf("\n>> Test Area"); - iprintf("\n NAND R/W test "); + iprintf("\n>> Debug1"); + iprintf("\n NandFirm write "); iprintf("\n--------------------------------"); - int fail=0; - - int byteAddress = 0x4E400; - int inputLength = 0x401; + printf("Opening NandFirm...\n"); - int byteOffset = byteAddress % SECTOR_SIZE; - int sectorNum = byteAddress / SECTOR_SIZE; - - int byteEndOffset = (byteAddress+inputLength) % SECTOR_SIZE; - int sectorEndNum = (byteAddress+inputLength) / SECTOR_SIZE; - - iprintf("\nInput address : %02X", byteAddress); - iprintf("\nInput length : %02X", inputLength); - iprintf("\nInput sector : %02X", sectorNum); - iprintf("\nSector offset : %02X", byteOffset); - iprintf("\nEnd sector : %02X", sectorEndNum); - iprintf("\nSector offset : %02X", byteEndOffset); - iprintf("\n"); - - int i; - if (sectorNum == sectorEndNum) { - // Handle a single sector write differently since it is unpredictable - //nand_ReadSectors(sectorNum, 1, sector_buf); - //memcpy(sector_buf + inputLength, file_buf, inputLength); - //nand_WriteSectors(1, 1, sector_buf); - iprintf("\n%02X to %02X of %02X", byteOffset, byteEndOffset, sectorNum); - iprintf("\n%02X to %02X of file_buf", 0, inputLength); - } else { - for (i = sectorNum; i < sectorEndNum + 1;) { - // Back up sector - //nand_ReadSectors(i, 1, sector_buf); - if (i == sectorNum) { - // Handle the first sector differently since we'll only be writing a partial amount of data - //memcpy(sector_buf + byteOffset, file_buf, SECTOR_SIZE - byteOffset); - iprintf("\n%02X to %02X of %02X", byteOffset, (SECTOR_SIZE), i); - iprintf("\n0 to %02X of file_buf", (SECTOR_SIZE - byteOffset), i); - } else if (i == sectorEndNum) { - // Handle the last sector differently since we'll only be writing a partial amount of data - //memcpy(sector_buf, file_buf + (((i - sectorNum) * SECTOR_SIZE) - byteOffset), byteEndOffset); - iprintf("\n0 to %02X of %02X (end)", byteEndOffset, i); - iprintf("\n%02X to %02X of file_buf", ((i - sectorNum) * SECTOR_SIZE) - byteOffset, (((i - sectorNum) * SECTOR_SIZE) + byteEndOffset) - byteOffset); - } else { - // Handle the middle sectors the same because they'll always be the full sector - //memcpy(sector_buf, file_buf + (((i - sectorNum) * SECTOR_SIZE) - byteOffset), SECTOR_SIZE); - iprintf("\n0 to %02X of %02X", SECTOR_SIZE, i); - iprintf("\n%02X to %02X of file_buf", ((i - sectorNum) * SECTOR_SIZE) - byteOffset, (((i - sectorNum) * SECTOR_SIZE) - byteOffset) + SECTOR_SIZE); - } - i++; - // I need to do a cmp here - - // Write sector - //nand_WriteSectors(i, 1, sector_buf); - } - } - - iprintf("\n\n\n Please Push Select To Return "); - - // Do some check to make sure it is not outside of NAND range. + FILE *file = fopen("nitro:/import/prod/menu-launcher.nand", "r"); + if(file) { + // First 0x200 of NandFirm is reserved for MBR + fseek(file, 0, SEEK_END); + int file_length = ftell(file); + fseek(file, 0x200, SEEK_SET); + printf("Importing...\n"); + good_nandio_write_file(0x200, file_length - ftell(file), file, false); + printf("Done!\n"); + fclose(file); + } while (true) { diff --git a/arm9/src/main.h b/arm9/src/main.h index 6a0bd29..e1c4fbf 100644 --- a/arm9/src/main.h +++ b/arm9/src/main.h @@ -17,12 +17,14 @@ extern bool unlaunchPatches; extern bool charging; extern u8 batteryLevel; extern u8 region; +extern u32 consoleSign; +extern char consoleSignName[9]; void installMenu(); void titleMenu(); void backupMenu(); void testMenu(); -int testRoutine(void); +int debug1(); extern PrintConsole topScreen; extern PrintConsole bottomScreen; diff --git a/arm9/src/nand/nandfirm.c b/arm9/src/nand/nandfirm.c index 8a1e228..9893849 100644 --- a/arm9/src/nand/nandfirm.c +++ b/arm9/src/nand/nandfirm.c @@ -15,7 +15,6 @@ #include "../video.h" u32 done=0; -size_t i; void death(char *message, u8 *buffer){ iprintf("\n%s\n", message); @@ -23,6 +22,98 @@ void death(char *message, u8 *buffer){ while(1)swiWaitForVBlank(); } +static size_t i; + +enum { + MENUSTATE_CHECK_NF_VER, + MENUSTATE_IMPORT_NF, + MENUSTATE_IMPORT_NF_SDMC, + MENUSTATE_READ_CID, + BACK +}; + +static int _nfMenu(int cursor) +{ + //top screen + clearScreen(cMAIN); + + printf("\n\x1B[40mTwlNandTool Ver0.0"); + printf("\n\nNAND repair tool by RMC/RVTR"); + printf("\n\nMode: NandFirm"); + + //menu + Menu* m = newMenu(); + setMenuHeader(m, "TwlNandTool"); + + char modeStr[32]; + addMenuItem(m, "Check NandFirm", NULL, 0); + addMenuItem(m, "Import NandFirm", NULL, 0); + addMenuItem(m, "Import NandFirm (SDMC)", NULL, 0); + addMenuItem(m, "CID Info", NULL, 0); + addMenuItem(m, "Back", NULL, 0); + + m->cursor = cursor; + + //bottom screen + printMenu(m); + + while (!programEnd) + { + swiWaitForVBlank(); + scanKeys(); + + if (moveCursor(m)) + printMenu(m); + + if (keysDown() & KEY_A) + break; + } + + int result = m->cursor; + freeMenu(m); + + return result; +} + +int nfMain(void) +{ + + int cursor = 0; + + while (!programEnd) + { + cursor = _nfMenu(cursor); + + switch (cursor) + { + + case MENUSTATE_CHECK_NF_VER: + nandFirmRead(); + break; + + case MENUSTATE_IMPORT_NF: + nandFirmImport(false); + break; + + case MENUSTATE_IMPORT_NF_SDMC: + nandFirmImport(true); + break; + + case MENUSTATE_READ_CID: + nandPrintInfo(); + break; + + case BACK: + programEnd = true; + break; + } + } + + programEnd = false; + + return 0; +} + int nandFirmRead(void) { clearScreen(cSUB); @@ -62,6 +153,43 @@ int nandFirmRead(void) { } } +int nandFirmImport(bool sdmc) { + + clearScreen(cSUB); + + iprintf("\n>> Debug1"); + iprintf("\n NandFirm write "); + iprintf("\n--------------------------------"); + + printf("Opening NandFirm...\n"); + + char file_path[100]; + snprintf(file_path, 100, "nitro:/import/%s/%s-launcher.nand", consoleSignName, sdmc ? "sdmc" : "menu"); + FILE *file = fopen(file_path, "r"); + + printf("%s\n", file_path); + + if(file) { + // First 0x200 of NandFirm is reserved for MBR + fseek(file, 0, SEEK_END); + int file_length = ftell(file); + fseek(file, 0x200, SEEK_SET); + printf("Importing...\n"); + good_nandio_write_file(0x200, file_length - ftell(file), file, false); + printf("Done!\n"); + fclose(file); + } + + while (true) + { + swiWaitForVBlank(); + scanKeys(); + + if (keysDown() & KEY_SELECT ) + break; + } +} + int nandPrintInfo(void) { extern nandData nandInfo; @@ -96,21 +224,4 @@ int nandPrintInfo(void) { if (keysDown() & KEY_SELECT ) break; } -} - - -/* - - I'd actually like to make a good RAW NAND R/W routine. - nandRead(byteAddress, amount, infile) - - - I want to find the sector (626) and sector offset (80) for the hex address below: - - Offset: 320592 - Sector size: 512 - - - byteOffset = byteAddress % sectorSize and sector = byteAddress / sectorSize - -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/arm9/src/nand/nandfirm.h b/arm9/src/nand/nandfirm.h index 212bc76..192a7b1 100644 --- a/arm9/src/nand/nandfirm.h +++ b/arm9/src/nand/nandfirm.h @@ -15,5 +15,10 @@ void wait(int ticks); void death(char *message, u8 *buffer); + + +int nfMain(void); + int nandFirmRead(void); +int nandFirmImport(bool sdmc); int nandPrintInfo(void); \ No newline at end of file diff --git a/arm9/src/nand/nandio.c b/arm9/src/nand/nandio.c index c5a1da4..0aebd17 100644 --- a/arm9/src/nand/nandio.c +++ b/arm9/src/nand/nandio.c @@ -283,13 +283,61 @@ bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt //iprintf("\n0 to %02X of %02X", SECTOR_SIZE, i); //iprintf("\n%02X to %02X of buffer", ((i - sectorNum) * SECTOR_SIZE) - byteOffset, (((i - sectorNum) * SECTOR_SIZE) - byteOffset) + SECTOR_SIZE); } - // I need to do a cmp here + // I need to do a cmp here t0 save NAND writes // Write sector if (crypt == true) { dsi_nand_crypt(buffer, buffer, 0, SECTOR_SIZE / AES_BLOCK_SIZE); } nand_WriteSectors(i, 1, sector_buf); i++; + // Do some check to make sure it is not outside of NAND range. + } + } + return true; +} + +bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool crypt) { + int byteOffset = inputAddress % SECTOR_SIZE; + int sectorNum = inputAddress / SECTOR_SIZE; + int byteEndOffset = (inputAddress+inputLength) % SECTOR_SIZE; + int sectorEndNum = (inputAddress+inputLength) / SECTOR_SIZE; + int i; + u8 buffer[SECTOR_SIZE]; + if (inputLength <= 0x200) { + // Handle a single sector write differently since it is unpredictable + nand_ReadSectors(sectorNum, 1, sector_buf); + fread(buffer, 1, inputLength, fp); + memcpy(sector_buf, buffer, inputLength); + if (crypt == true) { + dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE); + } + nand_WriteSectors(sectorNum, 1, sector_buf); + } else { + for (i = sectorNum; i < sectorEndNum + 1;) { + // Back up sector + nand_ReadSectors(i, 1, sector_buf); + + if (i == sectorNum) { + // Handle the first sector differently since we'll only be writing a partial amount of data + fread(buffer, 1, SECTOR_SIZE, fp); + memcpy(sector_buf + byteOffset, buffer, SECTOR_SIZE - byteOffset); + } else if (i == sectorEndNum) { + // Handle the last sector differently since we'll only be writing a partial amount of data + fread(buffer, 1, byteEndOffset, fp); + memcpy(sector_buf, buffer - byteOffset, byteEndOffset); + } else { + // Handle the middle sectors the same because they'll always be the full sector + fread(buffer, 1, SECTOR_SIZE, fp); + memcpy(sector_buf, buffer, SECTOR_SIZE); + } + // I need to do a cmp here t0 save NAND writes + // Write sector + if (crypt == true) { + dsi_nand_crypt(buffer, buffer, 0, SECTOR_SIZE / AES_BLOCK_SIZE); + } + nand_WriteSectors(i, 1, sector_buf); + i++; + // Do some check to make sure it is not outside of NAND range. } } return true; diff --git a/arm9/src/nand/nandio.h b/arm9/src/nand/nandio.h index c14e575..74f83b7 100644 --- a/arm9/src/nand/nandio.h +++ b/arm9/src/nand/nandio.h @@ -46,6 +46,7 @@ extern u8 CID[16]; extern u8 consoleIDfixed[8]; extern bool good_nandio_write(int inputAddress, int inputLength, u8 *buffer, bool crypt); +extern bool good_nandio_write_file(int inputAddress, int inputLength, FILE *fp, bool crypt); extern bool nandio_startup(); extern bool nandio_shutdown(); diff --git a/arm9/src/nitrofs.c b/arm9/src/nitrofs.c index a1933a4..2e6d19f 100644 --- a/arm9/src/nitrofs.c +++ b/arm9/src/nitrofs.c @@ -445,9 +445,12 @@ bool nitroFSGood(void) { int length = ftell(file); fseek(file, 0, SEEK_SET); - char *version = (char *)malloc((length + 1) * sizeof(char)); - + char *version = (char *)malloc((length) * sizeof(char)); + version[length] = '\0'; + fread(version, 1, length, file); + + printf("VER |%s|%s|\n", version, VERSION); nitroFSGood = (strcmp(version, VERSION) == 0); fclose(file); } diff --git a/nitrofiles/version_twlnandtool b/nitrofiles/version_twlnandtool index 08ff0d9..1e71d83 100644 --- a/nitrofiles/version_twlnandtool +++ b/nitrofiles/version_twlnandtool @@ -1 +1 @@ -"-" \ No newline at end of file +-2787a3d \ No newline at end of file