mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Provide the tools for CTR transfers (A9LH only)
This commit is contained in:
parent
55e3da2e3c
commit
e502ad1d99
@ -48,7 +48,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// GodMode9 version
|
// GodMode9 version
|
||||||
#define VERSION "1.0.3"
|
#define VERSION "1.0.4"
|
||||||
|
|
||||||
// Maximum payload size (arbitrary value!)
|
// Maximum payload size (arbitrary value!)
|
||||||
#define SELF_MAX_SIZE (320 * 1024) // 320kB
|
#define SELF_MAX_SIZE (320 * 1024) // 320kB
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "filetype.h"
|
#include "filetype.h"
|
||||||
#include "fsutil.h"
|
#include "fsutil.h"
|
||||||
#include "fatmbr.h"
|
#include "fatmbr.h"
|
||||||
|
#include "nand.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "chainload.h"
|
#include "chainload.h"
|
||||||
|
|
||||||
@ -26,8 +27,9 @@ u32 IdentifyFileType(const char* path) {
|
|||||||
} else if (ValidateMbrHeader((MbrHeader*) data) == 0) {
|
} else if (ValidateMbrHeader((MbrHeader*) data) == 0) {
|
||||||
MbrHeader* mbr = (MbrHeader*) data;
|
MbrHeader* mbr = (MbrHeader*) data;
|
||||||
MbrPartitionInfo* partition0 = mbr->partitions;
|
MbrPartitionInfo* partition0 = mbr->partitions;
|
||||||
|
bool ctr = (CheckNandMbr(data) & (NAND_TYPE_O3DS|NAND_TYPE_N3DS)); // is this a CTRNAND MBR?
|
||||||
if ((partition0->sector + partition0->count) <= (fsize / 0x200)) // size check
|
if ((partition0->sector + partition0->count) <= (fsize / 0x200)) // size check
|
||||||
return IMG_FAT; // possibly an MBR -> also treat as FAT image
|
return IMG_FAT | (ctr ? FLAG_CTR : 0); // possibly an MBR -> also treat as FAT image
|
||||||
} else if (ValidateCiaHeader((CiaHeader*) data) == 0) {
|
} else if (ValidateCiaHeader((CiaHeader*) data) == 0) {
|
||||||
// this only works because these functions ignore CIA content index
|
// this only works because these functions ignore CIA content index
|
||||||
CiaInfo info;
|
CiaInfo info;
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#define BIN_SUPPORT (1UL<<15)
|
#define BIN_SUPPORT (1UL<<15)
|
||||||
#define TYPE_BASE 0x00FFFFFF // 24 bit reserved for base types
|
#define TYPE_BASE 0x00FFFFFF // 24 bit reserved for base types
|
||||||
|
|
||||||
|
#define FLAG_CTR (1UL<<29)
|
||||||
#define FLAG_NUSCDN (1UL<<30)
|
#define FLAG_NUSCDN (1UL<<30)
|
||||||
#define FLAG_CXI (1UL<<31)
|
#define FLAG_CXI (1UL<<31)
|
||||||
|
|
||||||
@ -29,6 +30,7 @@
|
|||||||
#define FYTPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS))
|
#define FYTPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS))
|
||||||
#define FTYPE_BUILDABLE(tp) (tp&(GAME_NCSD|GAME_NCCH|GAME_TMD))
|
#define FTYPE_BUILDABLE(tp) (tp&(GAME_NCSD|GAME_NCCH|GAME_TMD))
|
||||||
#define FTYPE_BUILDABLE_L(tp) (FTYPE_BUILDABLE(tp) && (tp&(GAME_TMD)))
|
#define FTYPE_BUILDABLE_L(tp) (FTYPE_BUILDABLE(tp) && (tp&(GAME_TMD)))
|
||||||
|
#define FTYPE_TRANSFERABLE(tp) ((u32) (tp&(IMG_FAT|FLAG_CTR)) == (u32) (IMG_FAT|FLAG_CTR))
|
||||||
#define FTYPE_HSINJECTABLE(tp) ((u32) (tp&(GAME_NCCH|FLAG_CXI)) == (u32) (GAME_NCCH|FLAG_CXI))
|
#define FTYPE_HSINJECTABLE(tp) ((u32) (tp&(GAME_NCCH|FLAG_CXI)) == (u32) (GAME_NCCH|FLAG_CXI))
|
||||||
#define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND))
|
#define FTYPE_RESTORABLE(tp) (tp&(IMG_NAND))
|
||||||
#define FTYPE_EBACKUP(tp) (tp&(IMG_NAND))
|
#define FTYPE_EBACKUP(tp) (tp&(IMG_NAND))
|
||||||
|
@ -866,7 +866,7 @@ bool PathDelete(const char* path) {
|
|||||||
char fpath[256]; // 256 is the maximum length of a full path
|
char fpath[256]; // 256 is the maximum length of a full path
|
||||||
if (!CheckDirWritePermissions(path)) return false;
|
if (!CheckDirWritePermissions(path)) return false;
|
||||||
strncpy(fpath, path, 256);
|
strncpy(fpath, path, 256);
|
||||||
ShowString("Deleting files, please wait...");
|
// ShowString("Deleting files, please wait..."); // handled elsewhere
|
||||||
return PathDeleteWorker(fpath);
|
return PathDeleteWorker(fpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "vcart.h"
|
#include "vcart.h"
|
||||||
#include "nandcmac.h"
|
#include "nandcmac.h"
|
||||||
|
#include "ctrtransfer.h"
|
||||||
#include "ncchinfo.h"
|
#include "ncchinfo.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
#include "chainload.h"
|
#include "chainload.h"
|
||||||
@ -611,6 +612,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
|
|||||||
bool cryptable_inplace = ((encryptable||decryptable) && !in_output_path && (drvtype & DRV_FAT));
|
bool cryptable_inplace = ((encryptable||decryptable) && !in_output_path && (drvtype & DRV_FAT));
|
||||||
bool buildable = (FTYPE_BUILDABLE(filetype));
|
bool buildable = (FTYPE_BUILDABLE(filetype));
|
||||||
bool buildable_legit = (FTYPE_BUILDABLE_L(filetype));
|
bool buildable_legit = (FTYPE_BUILDABLE_L(filetype));
|
||||||
|
bool transferable = (FTYPE_TRANSFERABLE(filetype) && (drvtype & DRV_FAT));
|
||||||
bool hsinjectable = (FTYPE_HSINJECTABLE(filetype));
|
bool hsinjectable = (FTYPE_HSINJECTABLE(filetype));
|
||||||
bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND));
|
bool restorable = (FTYPE_RESTORABLE(filetype) && IS_A9LH && !(drvtype & DRV_SYSNAND));
|
||||||
bool ebackupable = (FTYPE_EBACKUP(filetype));
|
bool ebackupable = (FTYPE_EBACKUP(filetype));
|
||||||
@ -643,7 +645,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
|
|||||||
int searchdrv = (DriveType(current_path) & DRV_SEARCH) ? ++n_opt : -1;
|
int searchdrv = (DriveType(current_path) & DRV_SEARCH) ? ++n_opt : -1;
|
||||||
if (special > 0) optionstr[special-1] =
|
if (special > 0) optionstr[special-1] =
|
||||||
(filetype & IMG_NAND ) ? "NAND image options..." :
|
(filetype & IMG_NAND ) ? "NAND image options..." :
|
||||||
(filetype & IMG_FAT ) ? "Mount as FAT image" :
|
(filetype & IMG_FAT ) ? (transferable) ? "CTRNAND options..." : "Mount as FAT image" :
|
||||||
(filetype & GAME_CIA ) ? "CIA image options..." :
|
(filetype & GAME_CIA ) ? "CIA image options..." :
|
||||||
(filetype & GAME_NCSD ) ? "NCSD image options..." :
|
(filetype & GAME_NCSD ) ? "NCSD image options..." :
|
||||||
(filetype & GAME_NCCH ) ? "NCCH image options..." :
|
(filetype & GAME_NCCH ) ? "NCCH image options..." :
|
||||||
@ -774,6 +776,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
|
|||||||
int build = (buildable) ? ++n_opt : -1;
|
int build = (buildable) ? ++n_opt : -1;
|
||||||
int build_legit = (buildable_legit) ? ++n_opt : -1;
|
int build_legit = (buildable_legit) ? ++n_opt : -1;
|
||||||
int verify = (verificable) ? ++n_opt : -1;
|
int verify = (verificable) ? ++n_opt : -1;
|
||||||
|
int ctradapt = (transferable) ? ++n_opt : -1;
|
||||||
int hsinject = (hsinjectable) ? ++n_opt : -1;
|
int hsinject = (hsinjectable) ? ++n_opt : -1;
|
||||||
int xorpad = (xorpadable) ? ++n_opt : -1;
|
int xorpad = (xorpadable) ? ++n_opt : -1;
|
||||||
int xorpad_inplace = (xorpadable) ? ++n_opt : -1;
|
int xorpad_inplace = (xorpadable) ? ++n_opt : -1;
|
||||||
@ -786,6 +789,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 > 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 (build_legit > 0) optionstr[build_legit-1] = "Build CIA (legit)";
|
||||||
if (verify > 0) optionstr[verify-1] = "Verify file";
|
if (verify > 0) optionstr[verify-1] = "Verify file";
|
||||||
|
if (ctradapt > 0) optionstr[ctradapt-1] = "Adapt image to SysNAND";
|
||||||
if (hsinject > 0) optionstr[hsinject-1] = "Inject to H&S";
|
if (hsinject > 0) optionstr[hsinject-1] = "Inject to H&S";
|
||||||
if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)";
|
if (xorpad > 0) optionstr[xorpad-1] = "Build XORpads (SD output)";
|
||||||
if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)";
|
if (xorpad_inplace > 0) optionstr[xorpad_inplace-1] = "Build XORpads (inplace)";
|
||||||
@ -988,6 +992,10 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
|
|||||||
(InjectHealthAndSafety(curr_entry->path, destdrv[user_select-1]) == 0) ? "success" : "failed");
|
(InjectHealthAndSafety(curr_entry->path, destdrv[user_select-1]) == 0) ? "success" : "failed");
|
||||||
}
|
}
|
||||||
return 0;
|
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");
|
||||||
|
return 0;
|
||||||
} else if (user_select == restore) { // -> restore SysNAND (A9LH preserving)
|
} else if (user_select == restore) { // -> restore SysNAND (A9LH preserving)
|
||||||
ShowPrompt(false, "%s\nNAND restore %s", pathstr,
|
ShowPrompt(false, "%s\nNAND restore %s", pathstr,
|
||||||
(SafeRestoreNandDump(curr_entry->path) == 0) ? "success" : "failed");
|
(SafeRestoreNandDump(curr_entry->path) == 0) ? "success" : "failed");
|
||||||
@ -1334,6 +1342,7 @@ u32 GodMode() {
|
|||||||
if (n_marked) {
|
if (n_marked) {
|
||||||
if (ShowPrompt(true, "Delete %u path(s)?", n_marked)) {
|
if (ShowPrompt(true, "Delete %u path(s)?", n_marked)) {
|
||||||
u32 n_errors = 0;
|
u32 n_errors = 0;
|
||||||
|
ShowString("Deleting files, please wait...");
|
||||||
for (u32 c = 0; c < current_dir->n_entries; c++)
|
for (u32 c = 0; c < current_dir->n_entries; c++)
|
||||||
if (current_dir->entry[c].marked && !PathDelete(current_dir->entry[c].path))
|
if (current_dir->entry[c].marked && !PathDelete(current_dir->entry[c].path))
|
||||||
n_errors++;
|
n_errors++;
|
||||||
@ -1344,6 +1353,7 @@ u32 GodMode() {
|
|||||||
char namestr[36+1];
|
char namestr[36+1];
|
||||||
TruncateString(namestr, curr_entry->name, 28, 12);
|
TruncateString(namestr, curr_entry->name, 28, 12);
|
||||||
if (ShowPrompt(true, "Delete \"%s\"?", namestr)) {
|
if (ShowPrompt(true, "Delete \"%s\"?", namestr)) {
|
||||||
|
ShowString("Deleting files, please wait...");
|
||||||
if (!PathDelete(curr_entry->path))
|
if (!PathDelete(curr_entry->path))
|
||||||
ShowPrompt(false, "Failed deleting:\n%s", namestr);
|
ShowPrompt(false, "Failed deleting:\n%s", namestr);
|
||||||
ClearScreenF(true, false, COLOR_STD_BG);
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
|
76
source/nand/ctrtransfer.c
Normal file
76
source/nand/ctrtransfer.c
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#include "ctrtransfer.h"
|
||||||
|
#include "nandcmac.h"
|
||||||
|
#include "fsutil.h"
|
||||||
|
#include "fsinit.h"
|
||||||
|
#include "fsperm.h"
|
||||||
|
#include "image.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;
|
||||||
|
|
||||||
|
// 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)) {
|
||||||
|
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
|
||||||
|
SecureInfo* secnfo_img = (SecureInfo*) TEMP_BUFFER;
|
||||||
|
SecureInfo* secnfo_loc = (SecureInfo*) (TEMP_BUFFER + 0x200);
|
||||||
|
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))) &&
|
||||||
|
(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);
|
||||||
|
}
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
// inject all required files to image
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
PathCopy("7:", "1:/data", &flags);
|
||||||
|
|
||||||
|
InitImgFS(path_bak);
|
||||||
|
return 0;
|
||||||
|
}
|
5
source/nand/ctrtransfer.h
Normal file
5
source/nand/ctrtransfer.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
u32 AdaptCtrNandImage(const char* path);
|
@ -51,6 +51,22 @@ static const u8 twl_mbr[0x42] = { // encrypted version inside the NCSD NAND head
|
|||||||
0x55, 0xAA
|
0x55, 0xAA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const u8 ctr_mbr_o3ds[0x42] = { // found at the beginning of the CTRNAND partition (O3DS)
|
||||||
|
0x00, 0x05, 0x2B, 0x00, 0x06, 0x02, 0x42, 0x80, 0x65, 0x01, 0x00, 0x00, 0x1B, 0x9F, 0x17, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x55, 0xAA
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 ctr_mbr_n3ds[0x42] = { // found at the beginning of the CTRNAND partition (N3DS)
|
||||||
|
0x00, 0x05, 0x1D, 0x00, 0x06, 0x02, 0x82, 0x17, 0x57, 0x01, 0x00, 0x00, 0x69, 0xE9, 0x20, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x55, 0xAA
|
||||||
|
};
|
||||||
|
|
||||||
static u8 CtrNandCtr[16];
|
static u8 CtrNandCtr[16];
|
||||||
static u8 TwlNandCtr[16];
|
static u8 TwlNandCtr[16];
|
||||||
static u8 OtpSha256[32] = { 0 };
|
static u8 OtpSha256[32] = { 0 };
|
||||||
@ -352,13 +368,24 @@ int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 n
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 CheckNandMbr(u8* mbr)
|
||||||
|
{
|
||||||
|
if (memcmp(mbr + (0x200 - sizeof(twl_mbr)), twl_mbr, sizeof(twl_mbr)) == 0)
|
||||||
|
return NAND_TYPE_TWL; // TWLNAND MBR (included in NAND header)
|
||||||
|
else if (memcmp(mbr + (0x200 - sizeof(ctr_mbr_o3ds)), ctr_mbr_o3ds, sizeof(ctr_mbr_o3ds)) == 0)
|
||||||
|
return NAND_TYPE_O3DS; // CTRNAND MBR (@0x05C980)
|
||||||
|
else if (memcmp(mbr + (0x200 - sizeof(ctr_mbr_n3ds)), ctr_mbr_n3ds, sizeof(ctr_mbr_n3ds)) == 0)
|
||||||
|
return NAND_TYPE_N3DS; // CTRNAND MBR (@0x05C980)
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u32 CheckNandHeader(u8* header)
|
u32 CheckNandHeader(u8* header)
|
||||||
{
|
{
|
||||||
// TWL MBR check
|
// TWL MBR check
|
||||||
u8 header_dec[0x200];
|
u8 header_dec[0x200];
|
||||||
memcpy(header_dec, header, 0x200);
|
memcpy(header_dec, header, 0x200);
|
||||||
CryptNand(header_dec, 0, 1, 0x03);
|
CryptNand(header_dec, 0, 1, 0x03);
|
||||||
if (memcmp(header_dec + 0x1BE, twl_mbr, sizeof(twl_mbr)) != 0)
|
if (CheckNandMbr(header_dec) != NAND_TYPE_TWL)
|
||||||
return 0; // header does not belong to console
|
return 0; // header does not belong to console
|
||||||
|
|
||||||
// header type check
|
// header type check
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define NAND_TYPE_O3DS (1UL<<4)
|
#define NAND_TYPE_O3DS (1UL<<4)
|
||||||
#define NAND_TYPE_N3DS (1UL<<5)
|
#define NAND_TYPE_N3DS (1UL<<5)
|
||||||
#define NAND_TYPE_NO3DS (1UL<<6)
|
#define NAND_TYPE_NO3DS (1UL<<6)
|
||||||
|
#define NAND_TYPE_TWL (1UL<<7)
|
||||||
|
|
||||||
// minimum size of NAND memory
|
// minimum size of NAND memory
|
||||||
#define NAND_MIN_SECTORS_O3DS 0x1D7800
|
#define NAND_MIN_SECTORS_O3DS 0x1D7800
|
||||||
@ -47,6 +48,7 @@ int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 d
|
|||||||
|
|
||||||
u64 GetNandSizeSectors(u32 src);
|
u64 GetNandSizeSectors(u32 src);
|
||||||
u64 GetNandUnusedSectors(u32 src);
|
u64 GetNandUnusedSectors(u32 src);
|
||||||
|
u32 CheckNandMbr(u8* mbr);
|
||||||
u32 CheckNandHeader(u8* header);
|
u32 CheckNandHeader(u8* header);
|
||||||
u32 CheckNandType(u32 src);
|
u32 CheckNandType(u32 src);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user