diff --git a/arm9/src/main.c b/arm9/src/main.c index 94676d4..f3f3722 100644 --- a/arm9/src/main.c +++ b/arm9/src/main.c @@ -8,6 +8,7 @@ #include "unlaunch.h" #include "nitrofs.h" #include "deviceList.h" +#include "nocashFooter.h" volatile bool programEnd = false; static volatile bool arm7Exiting = false; @@ -22,7 +23,9 @@ static const char* splashSoundBinaryPatchPath = NULL; static const char* customBgPath = NULL; volatile bool charging = false; volatile u8 batteryLevel = 0; -static bool wantsUnsafeUnlaunchUninstall = false; +static bool advancedOptionsUnlocked = false; +static bool needsNocashFooterToBeWritten = false; +static NocashFooter computedNocashFooter; PrintConsole topScreen; PrintConsole bottomScreen; @@ -35,6 +38,7 @@ enum { MAIN_MENU_SAFE_UNLAUNCH_INSTALL, MAIN_MENU_EXIT, MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP, + MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY, }; static void setupScreens() @@ -94,8 +98,11 @@ static int mainMenu(int cursor) addMenuItem(m, soundPatchesStr, NULL, foundUnlaunchInstallerVersion == v2_0 && !disableAllPatches && splashSoundBinaryPatchPath != NULL, false); addMenuItem(m, installUnlaunchStr, NULL, foundUnlaunchInstallerVersion != INVALID && !unlaunchFound, false); addMenuItem(m, "Exit", NULL, true, false); - if(wantsUnsafeUnlaunchUninstall) + if(advancedOptionsUnlocked) + { addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false); + addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false); + } m->cursor = cursor; @@ -116,7 +123,7 @@ static int mainMenu(int cursor) if (keysDown() & KEY_A) break; - if(wantsUnsafeUnlaunchUninstall) + if(advancedOptionsUnlocked) continue; int held = keysHeld(); @@ -135,8 +142,9 @@ static int mainMenu(int cursor) } if (konamiCode == 5) { - wantsUnsafeUnlaunchUninstall = true; + advancedOptionsUnlocked = true; addMenuItem(m, "Uninstall unlaunch no backup", NULL, unlaunchFound, false); + addMenuItem(m, "Write nocash footer", NULL, needsNocashFooterToBeWritten, false); } } @@ -188,7 +196,26 @@ int main(int argc, char **argv) messageBox("nand init \x1B[31mfailed\n\x1B[47m"); return 0; } - + + NocashFooter footer; + + nandio_read_nocash_footer(&footer); + nandio_construct_nocash_footer(&computedNocashFooter); + + if(!(needsNocashFooterToBeWritten = !isFooterValid(&footer))) + { + if(memcmp(&footer, &computedNocashFooter, sizeof(footer)) != 0) + { + messageBox("\x1B[31mError:\x1B[33m This console has a\n" + "nocash footer embedded in its\n" + "nand that doesn't match the one\n" + "generated.\n" + "The footer already present will\n" + "be overwritten."); + needsNocashFooterToBeWritten = true; + } + } + while (batteryLevel < 7 && !charging) { if (choiceBox("\x1B[47mBattery is too low!\nPlease plug in the console.\n\nContinue?") == NO) @@ -292,7 +319,18 @@ int main(int argc, char **argv) case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL: case MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP: if(unlaunchFound && nandio_unlock_writing()) { - bool unsafeUninstall = wantsUnsafeUnlaunchUninstall && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP; + bool unsafeUninstall = advancedOptionsUnlocked && cursor == MAIN_MENU_SAFE_UNLAUNCH_UNINSTALL_NO_BACKUP; + printf("Uninstalling"); + if(needsNocashFooterToBeWritten) + { + printf("Writing nocash footer\n"); + if(!nandio_write_nocash_footer(&computedNocashFooter)) + { + messageBox("Failed to write nocash footer"); + break; + } + needsNocashFooterToBeWritten = false; + } if(uninstallUnlaunch(retailConsole, hnaaUnlaunchFound, retailLauncherTmdPath, unsafeUninstall)) { messageBox("Uninstall successful!\n"); @@ -340,6 +378,16 @@ int main(int argc, char **argv) && nandio_unlock_writing()) { printf("Installing\n"); + if(needsNocashFooterToBeWritten) + { + printf("Writing nocash footer\n"); + if(!nandio_write_nocash_footer(&computedNocashFooter)) + { + messageBox("Failed to write nocash footer"); + break; + } + needsNocashFooterToBeWritten = false; + } if(installUnlaunch(retailConsole, retailLauncherTmdPresentAndToBePatched ? retailLauncherTmdPath : NULL, disableAllPatches, @@ -356,6 +404,18 @@ int main(int argc, char **argv) nandio_synchronize_fats(); } break; + + case MAIN_MENU_WRITE_NOCASH_FOOTER_ONLY: + if(needsNocashFooterToBeWritten) + { + if(!nandio_write_nocash_footer(&computedNocashFooter)) + { + messageBox("Failed to write nocash footer"); + break; + } + needsNocashFooterToBeWritten = false; + } + break; case MAIN_MENU_EXIT: programEnd = true; diff --git a/arm9/src/nand/nandio.c b/arm9/src/nand/nandio.c index 751cc9c..f457f1d 100644 --- a/arm9/src/nand/nandio.c +++ b/arm9/src/nand/nandio.c @@ -10,6 +10,8 @@ #include "nandio.h" #include "u128_math.h" +#define NOCASH_FOOTER_SECTOR 2044 + /************************ Function Protoypes **********************************/ static bool nandio_startup(); @@ -51,7 +53,16 @@ void nandio_set_fat_sig_fix(u32 offset) fat_sig_fix_offset = offset; } -static void getConsoleID(u8 *consoleID) +void getCID(u8 *CID) +{ + vu8* CIDbuff = (vu8*)0x2FFD7BC; + for(int i = 0; i < 16; ++i) + { + CID[i] = CIDbuff[i]; + } +} + +void getConsoleID(u8 *consoleID) { vu8 *fifo=(vu8*)0x02300000; //shared mem address that has our computed key3 stuff u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto @@ -89,6 +100,7 @@ static bool nandio_startup() u8 consoleID[8]; u8 consoleIDfixed[8]; + u8 CID[16]; // Get ConsoleID getConsoleID(consoleID); @@ -97,8 +109,10 @@ static bool nandio_startup() consoleIDfixed[i] = consoleID[7-i]; } + getCID(CID); + // iprintf("sector 0 is %s\n", is3DS ? "3DS" : "DSi"); - dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)0x2FFD7BC, is3DS); + dsi_crypt_init((const u8*)consoleIDfixed, (const u8*)CID, is3DS); dsi_nand_crypt(sector_buf, sector_buf, 0, SECTOR_SIZE / AES_BLOCK_SIZE); parse_mbr(sector_buf, is3DS); @@ -144,6 +158,49 @@ static bool read_sectors(sec_t start, sec_t len, void *buffer) } } +void nandio_construct_nocash_footer(NocashFooter* footer) +{ + u8 CID[16]; + u8 consoleID[8]; + + getCID(CID); + getConsoleID(consoleID); + + constructNocashFooter(footer, CID, consoleID); +} + +bool nandio_read_nocash_footer(NocashFooter* footer) +{ + if(!nand_ReadSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf)) + { + return false; + } + + memcpy(footer, crypt_buf, sizeof(NocashFooter)); + return true; +} + +bool nandio_write_nocash_footer(NocashFooter* footer) +{ + if (writingLocked) + return false; + + if(!nand_ReadSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf)) + { + return false; + } + + memcpy(crypt_buf, footer, sizeof(NocashFooter)); + + + if(!nand_WriteSectors(NOCASH_FOOTER_SECTOR, 1, crypt_buf)) + { + return false; + } + + return true; +} + // len is guaranteed <= CRYPT_BUF_LEN static bool write_sectors(sec_t start, sec_t len, const void *buffer) { diff --git a/arm9/src/nand/nandio.h b/arm9/src/nand/nandio.h index fba7ded..a17bfba 100644 --- a/arm9/src/nand/nandio.h +++ b/arm9/src/nand/nandio.h @@ -2,6 +2,7 @@ #include #include +#include "../nocashFooter.h" #ifdef __cplusplus extern "C" { @@ -26,6 +27,10 @@ extern bool nandio_unlock_writing(); extern bool nandio_force_fat_fix(); extern void nandio_synchronize_fats(); +extern void nandio_construct_nocash_footer(NocashFooter* footer); +extern bool nandio_read_nocash_footer(NocashFooter* footer); +extern bool nandio_write_nocash_footer(NocashFooter* footer); + #ifdef __cplusplus } #endif diff --git a/arm9/src/nocashFooter.c b/arm9/src/nocashFooter.c new file mode 100644 index 0000000..8ca3e09 --- /dev/null +++ b/arm9/src/nocashFooter.c @@ -0,0 +1,17 @@ +#include "nocashFooter.h" +#include + +static const char* nocashMagicString = "DSi eMMC CID/CPU"; + +bool isFooterValid(const NocashFooter* footer) +{ + return memcmp(nocashMagicString, footer->footerID, sizeof(footer->footerID)) == 0; +} + +void constructNocashFooter(NocashFooter* footer, const u8* CID, const u8* consoleID) +{ + memset(footer, 0, sizeof(NocashFooter)); + memcpy(footer->footerID, nocashMagicString, sizeof(footer->footerID)); + memcpy(footer->CID, CID, sizeof(footer->CID)); + memcpy(footer->consoleId, consoleID, sizeof(footer->consoleId)); +} \ No newline at end of file diff --git a/arm9/src/nocashFooter.h b/arm9/src/nocashFooter.h new file mode 100644 index 0000000..b9a19be --- /dev/null +++ b/arm9/src/nocashFooter.h @@ -0,0 +1,23 @@ +#ifndef NOCASH_FOOTER_H +#define NOCASH_FOOTER_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct NocashFooter { + char footerID[16]; //DSi eMMC CID/CPU + u8 CID[16]; + u8 consoleId[8]; + u8 pad[0x18]; +} NocashFooter; + +bool isFooterValid(const NocashFooter* footer); +void constructNocashFooter(NocashFooter* footer, const u8* CID, const u8* consoleID); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file