mirror of
https://github.com/rvtr/TwlNandTool.git
synced 2025-10-31 06:01:08 -04:00
Add NandFirm import
This commit is contained in:
parent
2787a3d5cf
commit
e8e64c4c6d
@ -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
|
||||
|
||||
|
||||
106
arm9/src/main.c
106
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;
|
||||
printf("Opening NandFirm...\n");
|
||||
|
||||
int byteAddress = 0x4E400;
|
||||
int inputLength = 0x401;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
@ -97,20 +225,3 @@ int nandPrintInfo(void) {
|
||||
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
|
||||
|
||||
*/
|
||||
@ -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);
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
"-"
|
||||
-2787a3d
|
||||
Loading…
Reference in New Issue
Block a user