From a0e65c01bc2dfaaedb3f360e8f97d9603ddb5b02 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Thu, 23 Mar 2017 16:00:17 +0100 Subject: [PATCH] Improved CTRNAND transfer method --- source/common/common.h | 2 +- source/godmode.c | 29 +++++++++---- source/nand/ctrtransfer.c | 85 +++++++++++++++++++-------------------- source/nand/ctrtransfer.h | 2 +- 4 files changed, 65 insertions(+), 53 deletions(-) diff --git a/source/common/common.h b/source/common/common.h index e835b23..4fd1327 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -53,7 +53,7 @@ // GodMode9 version -#define VERSION "1.0.6" +#define VERSION "1.0.7" // Maximum payload size (arbitrary value!) #define SELF_MAX_SIZE (320 * 1024) // 320kB diff --git a/source/godmode.c b/source/godmode.c index 49ba35c..b8f8a70 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -692,10 +692,10 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur (filetype & GAME_NCCH ) ? "NCCH image options..." : (filetype & GAME_EXEFS) ? "Mount as EXEFS image" : (filetype & GAME_ROMFS) ? "Mount as ROMFS image" : - (filetype & GAME_TMD) ? "TMD file options..." : - (filetype & GAME_BOSS) ? "BOSS file options..." : + (filetype & GAME_TMD ) ? "TMD file options..." : + (filetype & GAME_BOSS ) ? "BOSS file options..." : (filetype & GAME_NUSCDN)? "Decrypt NUS/CDN file" : - (filetype & SYS_FIRM) ? "FIRM image options..." : + (filetype & SYS_FIRM ) ? "FIRM image options..." : (filetype & SYS_TICKDB) ? "Mount as ticket.db" : (filetype & BIN_NCCHNFO)? "NCCHinfo options..." : (filetype & BIN_LAUNCH) ? "Launch as arm9 payload" : "???"; @@ -794,7 +794,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur int build = (buildable) ? ++n_opt : -1; int build_legit = (buildable_legit) ? ++n_opt : -1; int verify = (verificable) ? ++n_opt : -1; - int ctradapt = (transferable) ? ++n_opt : -1; + int ctrtransfer = (transferable) ? ++n_opt : -1; int hsinject = (hsinjectable) ? ++n_opt : -1; int xorpad = (xorpadable) ? ++n_opt : -1; int xorpad_inplace = (xorpadable) ? ++n_opt : -1; @@ -807,7 +807,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur if (build > 0) optionstr[build-1] = (build_legit < 0) ? "Build CIA from file" : "Build CIA (standard)"; if (build_legit > 0) optionstr[build_legit-1] = "Build CIA (legit)"; if (verify > 0) optionstr[verify-1] = "Verify file"; - if (ctradapt > 0) optionstr[ctradapt-1] = "Adapt image to SysNAND"; + if (ctrtransfer > 0) optionstr[ctrtransfer-1] = "Transfer image to CTRNAND"; if (hsinject > 0) optionstr[hsinject-1] = "Inject to H&S"; if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)"; if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)"; @@ -1010,9 +1010,22 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur (InjectHealthAndSafety(curr_entry->path, destdrv[user_select-1]) == 0) ? "success" : "failed"); } return 0; - } else if (user_select == ctradapt) { // -> adapt CTRNAND image to SysNAND - ShowPrompt(false, "%s\n%s", pathstr, - (AdaptCtrNandImage(curr_entry->path) == 0) ? "Image adapted to SysNAND" : "Image modification failed"); + } else if (user_select == ctrtransfer) { // -> adapt CTRNAND image to SysNAND + char* destdrv[2] = { NULL }; + n_opt = 0; + if (DriveType("1:")) { + optionstr[n_opt] = "Transfer to SysNAND"; + destdrv[n_opt++] = "1:"; + } + if (DriveType("4:")) { + optionstr[n_opt] = "Transfer to EmuNAND"; + destdrv[n_opt++] = "4:"; + } + user_select = (n_opt > 1) ? (int) ShowSelectPrompt(n_opt, optionstr, pathstr) : n_opt; + if (user_select) { + ShowPrompt(false, "%s\nCTRNAND transfer %s", pathstr, + (TransferCtrNandImage(curr_entry->path, destdrv[user_select-1]) == 0) ? "success" : "failed"); + } return 0; } else if (user_select == restore) { // -> restore SysNAND (A9LH preserving) ShowPrompt(false, "%s\nNAND restore %s", pathstr, diff --git a/source/nand/ctrtransfer.c b/source/nand/ctrtransfer.c index 08ecc6a..9b4708c 100644 --- a/source/nand/ctrtransfer.c +++ b/source/nand/ctrtransfer.c @@ -4,72 +4,71 @@ #include "fsinit.h" #include "fsperm.h" #include "image.h" +#include "gameutil.h" #include "essentials.h" #include "ui.h" -u32 AdaptCtrNandImage(const char* path) { - if (!CheckWritePermissions(path)) return 1; - - // a little warning... - if (!ShowPrompt(true, "This will alter the provided image\nto make it transferable to your NAND.")) - return 1; + +u32 TransferCtrNandImage(const char* path_img, const char* drv) { + if (!CheckWritePermissions(drv)) return 1; // backup current mount path, mount new path char path_store[256] = { 0 }; char* path_bak = NULL; strncpy(path_store, GetMountPath(), 256); if (*path_store) path_bak = path_store; - if (!InitImgFS(path)) { + if (!InitImgFS(path_img)) { InitImgFS(path_bak); return 1; } - // fixing CMACs - ShowString("Fixing .db CMACs, please wait..."); - if ((FixFileCmac("7:/dbs/ticket.db") != 0) || - (FixFileCmac("7:/dbs/certs.db") != 0) || - (FixFileCmac("7:/dbs/title.db") != 0)) { - ShowPrompt(false, "Error: .db file missing."); - InitImgFS(path_bak); - return 1; - } - FixFileCmac("7:/dbs/import.db"); - FixFileCmac("7:/dbs/tmp_t.db"); - FixFileCmac("7:/dbs/tmp_i.db"); - - // cleanup this image - ShowString("Cleaning up image, please wait..."); - // special handling for out of region images + // CTRNAND preparations SecureInfo* secnfo_img = (SecureInfo*) TEMP_BUFFER; SecureInfo* secnfo_loc = (SecureInfo*) (TEMP_BUFFER + 0x200); + char* path_secnfo_a = (char*) (TEMP_BUFFER + 0x400); + char* path_secnfo_b = (char*) (TEMP_BUFFER + 0x420); + char* path_secnfo_c = (char*) (TEMP_BUFFER + 0x440); + char* path_tickdb = (char*) (TEMP_BUFFER + 0x460); + char* path_tickdb_bak = (char*) (TEMP_BUFFER + 0x480); + snprintf(path_secnfo_a, 32, "%s/rw/sys/SecureInfo_A", drv); + snprintf(path_secnfo_b, 32, "%s/rw/sys/SecureInfo_B", drv); + snprintf(path_secnfo_c, 32, "%s/rw/sys/SecureInfo_C", drv); + snprintf(path_tickdb, 32, "%s/dbs/ticket.db", drv); + snprintf(path_tickdb_bak, 32, "%s/dbs/ticket.bak", drv); + // special handling for out of region images (create SecureInfo_C) if (((FileGetData("7:/rw/sys/SecureInfo_A", (u8*) secnfo_img, sizeof(SecureInfo), 0) == sizeof(SecureInfo)) || (FileGetData("7:/rw/sys/SecureInfo_B", (u8*) secnfo_img, sizeof(SecureInfo), 0) == sizeof(SecureInfo))) && - ((FileGetData("1:/rw/sys/SecureInfo_A", (u8*) secnfo_loc, sizeof(SecureInfo), 0) == sizeof(SecureInfo)) || - (FileGetData("1:/rw/sys/SecureInfo_B", (u8*) secnfo_loc, sizeof(SecureInfo), 0) == sizeof(SecureInfo))) && + ((FileGetData(path_secnfo_a, (u8*) secnfo_loc, sizeof(SecureInfo), 0) == sizeof(SecureInfo)) || + (FileGetData(path_secnfo_b, (u8*) secnfo_loc, sizeof(SecureInfo), 0) == sizeof(SecureInfo))) && (secnfo_img->region != secnfo_loc->region)) { secnfo_loc->region = secnfo_img->region; - FileSetData("1:/rw/sys/SecureInfo_C", (u8*) secnfo_loc, sizeof(SecureInfo), 0, true); + FileSetData(path_secnfo_c, (u8*) secnfo_loc, sizeof(SecureInfo), 0, true); } - // actual cleanup - PathDelete("7:/private/movable.sed"); - PathDelete("7:/rw/sys/LocalFriendCodeSeed_B"); - PathDelete("7:/rw/sys/LocalFriendCodeSeed_A"); - PathDelete("7:/rw/sys/SecureInfo_A"); - PathDelete("7:/rw/sys/SecureInfo_B"); - PathDelete("7:/data"); + // make a backup of ticket.db + PathDelete(path_tickdb_bak); + PathRename(path_tickdb, "ticket.bak"); - // inject all required files to image + // actual transfer - db files / titles / H&S inject markfile + const char* dbnames[] = { "ticket.db", "certs.db", "title.db", "import.db", "tmp_t.db", "tmp_i.db" }; + char path_to[32]; + char path_from[32]; + char path_dbs[32]; u32 flags = OVERWRITE_ALL; - if (!PathCopy("7:/private", "1:/private/movable.sed", &flags) || - !(PathCopy("7:/rw/sys", "1:/rw/sys/LocalFriendCodeSeed_B", &flags) || - PathCopy("7:/rw/sys", "1:/rw/sys/LocalFriendCodeSeed_A", &flags)) || - !(PathCopy("7:/rw/sys", "1:/rw/sys/SecureInfo_A", &flags) || - PathCopy("7:/rw/sys", "1:/rw/sys/SecureInfo_B", &flags))) { - ShowPrompt(false, "Error: Failed transfering data."); - InitImgFS(path_bak); - return 1; + snprintf(path_dbs, 32, "%s/dbs", drv); + for (u32 i = 0; i < sizeof(dbnames) / sizeof(char*); i++) { + snprintf(path_to, 32, "%s/dbs/%s", drv, dbnames[i]); + snprintf(path_from, 32, "7:/dbs/%s", dbnames[i]); + PathDelete(path_to); + PathCopy(path_dbs, path_from, &flags); + FixFileCmac(path_to); } - PathCopy("7:", "1:/data", &flags); + snprintf(path_to, 32, "%s/" HSINJECT_MARKFILE, drv); + PathDelete(path_to); + ShowString("Cleaning up titles, please wait..."); + snprintf(path_to, 32, "%s/title", drv); + snprintf(path_from, 32, "7:/title"); + PathDelete(path_to); + PathCopy(drv, path_from, &flags); InitImgFS(path_bak); return 0; diff --git a/source/nand/ctrtransfer.h b/source/nand/ctrtransfer.h index 597f128..025dfbc 100644 --- a/source/nand/ctrtransfer.h +++ b/source/nand/ctrtransfer.h @@ -2,4 +2,4 @@ #include "common.h" -u32 AdaptCtrNandImage(const char* path); +u32 TransferCtrNandImage(const char* path_img, const char* drv);