diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index ffd7dfd..cb290cc 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -8,54 +8,133 @@ /*-----------------------------------------------------------------------*/ #include "diskio.h" /* FatFs lower layer API */ +#include "aes.h" #include "platform.h" #include "sdmmc.h" -#include "nandio.h" -#define TYPE_SDCARD 0 -#define TYPE_SYSNAND 1 -#define TYPE_EMUNAND 2 +#define TYPE_SDCARD 0 +#define TYPE_SYSNAND 1 +#define TYPE_EMUNAND 2 + +#define SUBTYPE_CTRN_O 0 +#define SUBTYPE_CTRN_N 1 +#define SUBTYPE_TWLN 2 +#define SUBTYPE_TWLP 3 +#define SUBTYPE_NONE 4 typedef struct { DWORD offset; - BYTE type; - DWORD subtype; + BYTE type; + BYTE subtype; } FATpartition; -FATpartition DriveInfo[28] = { - { 0x000000, TYPE_SDCARD, 0 }, // 0 - SDCARD - { 0x000000, TYPE_SYSNAND, P_CTRNAND }, // 1 - SYSNAND CTRNAND - { 0x000000, TYPE_SYSNAND, P_TWLN }, // 2 - SYSNAND TWLN - { 0x000000, TYPE_SYSNAND, P_TWLP }, // 3 - SYSNAND TWLP - { 0x000000, TYPE_EMUNAND, P_CTRNAND }, // 4 - EMUNAND0 O3DS CTRNAND - { 0x000000, TYPE_EMUNAND, P_TWLN }, // 5 - EMUNAND0 O3DS TWLN - { 0x000000, TYPE_EMUNAND, P_TWLP }, // 6 - EMUNAND0 O3DS TWLP - { 0x200000, TYPE_EMUNAND, P_CTRNAND }, // 7 - EMUNAND1 O3DS CTRNAND - { 0x200000, TYPE_EMUNAND, P_TWLN }, // 8 - EMUNAND1 O3DS TWLN - { 0x200000, TYPE_EMUNAND, P_TWLP }, // 9 - EMUNAND1 O3DS TWLP - { 0x400000, TYPE_EMUNAND, P_CTRNAND }, // 10 - EMUNAND2 O3DS CTRNAND - { 0x400000, TYPE_EMUNAND, P_TWLN }, // 11 - EMUNAND2 O3DS TWLN - { 0x400000, TYPE_EMUNAND, P_TWLP }, // 12 - EMUNAND2 O3DS TWLP - { 0x600000, TYPE_EMUNAND, P_CTRNAND }, // 13 - EMUNAND3 O3DS CTRNAND - { 0x600000, TYPE_EMUNAND, P_TWLN }, // 14 - EMUNAND3 O3DS TWLN - { 0x600000, TYPE_EMUNAND, P_TWLP }, // 15 - EMUNAND3 O3DS TWLP - { 0x000000, TYPE_EMUNAND, P_CTRNAND }, // 16 - EMUNAND0 N3DS CTRNAND - { 0x000000, TYPE_EMUNAND, P_TWLN }, // 17 - EMUNAND0 N3DS TWLN - { 0x000000, TYPE_EMUNAND, P_TWLP }, // 18 - EMUNAND0 N3DS TWLP - { 0x400000, TYPE_EMUNAND, P_CTRNAND }, // 19 - EMUNAND1 N3DS CTRNAND - { 0x400000, TYPE_EMUNAND, P_TWLN }, // 20 - EMUNAND1 N3DS TWLN - { 0x400000, TYPE_EMUNAND, P_TWLP }, // 21 - EMUNAND1 N3DS TWLP - { 0x800000, TYPE_EMUNAND, P_CTRNAND }, // 22 - EMUNAND2 N3DS CTRNAND - { 0x800000, TYPE_EMUNAND, P_TWLN }, // 23 - EMUNAND2 N3DS TWLN - { 0x800000, TYPE_EMUNAND, P_TWLP }, // 24 - EMUNAND2 N3DS TWLP - { 0xC00000, TYPE_EMUNAND, P_CTRNAND }, // 25 - EMUNAND3 N3DS CTRNAND - { 0xC00000, TYPE_EMUNAND, P_TWLN }, // 26 - EMUNAND3 N3DS TWLN - { 0xC00000, TYPE_EMUNAND, P_TWLP } // 27 - EMUNAND3 N3DS TWLP +typedef struct { + DWORD offset; + DWORD mode; + BYTE keyslot; +} SubtypeDesc; + +FATpartition DriveInfo[31] = { + { 0x000000, TYPE_SDCARD, SUBTYPE_NONE }, // 0 - SDCARD + { 0x000000, TYPE_SYSNAND, SUBTYPE_CTRN_O }, // 1 - SYSNAND CTRNAND + { 0x000000, TYPE_SYSNAND, SUBTYPE_TWLN }, // 2 - SYSNAND TWLN + { 0x000000, TYPE_SYSNAND, SUBTYPE_TWLP }, // 3 - SYSNAND TWLP + { 0x000000, TYPE_EMUNAND, SUBTYPE_CTRN_O }, // 4 - EMUNAND0 O3DS CTRNAND + { 0x000000, TYPE_EMUNAND, SUBTYPE_TWLN }, // 5 - EMUNAND0 O3DS TWLN + { 0x000000, TYPE_EMUNAND, SUBTYPE_TWLP }, // 6 - EMUNAND0 O3DS TWLP + { 0x200000, TYPE_EMUNAND, SUBTYPE_CTRN_O }, // 7 - EMUNAND1 O3DS CTRNAND + { 0x200000, TYPE_EMUNAND, SUBTYPE_TWLN }, // 8 - EMUNAND1 O3DS TWLN + { 0x200000, TYPE_EMUNAND, SUBTYPE_TWLP }, // 9 - EMUNAND1 O3DS TWLP + { 0x400000, TYPE_EMUNAND, SUBTYPE_CTRN_O }, // 10 - EMUNAND2 O3DS CTRNAND + { 0x400000, TYPE_EMUNAND, SUBTYPE_TWLN }, // 11 - EMUNAND2 O3DS TWLN + { 0x400000, TYPE_EMUNAND, SUBTYPE_TWLP }, // 12 - EMUNAND2 O3DS TWLP + { 0x600000, TYPE_EMUNAND, SUBTYPE_CTRN_O }, // 13 - EMUNAND3 O3DS CTRNAND + { 0x600000, TYPE_EMUNAND, SUBTYPE_TWLN }, // 14 - EMUNAND3 O3DS TWLN + { 0x600000, TYPE_EMUNAND, SUBTYPE_TWLP }, // 15 - EMUNAND3 O3DS TWLPSDCARD + { 0x000000, TYPE_SYSNAND, SUBTYPE_CTRN_N }, // *1 - SYSNAND CTRNAND + { 0x000000, TYPE_SYSNAND, SUBTYPE_TWLN }, // *2 - SYSNAND TWLN + { 0x000000, TYPE_SYSNAND, SUBTYPE_TWLP }, // *3 - SYSNAND TWLP + { 0x000000, TYPE_EMUNAND, SUBTYPE_CTRN_N }, // *4 - EMUNAND0 N3DS CTRNAND + { 0x000000, TYPE_EMUNAND, SUBTYPE_TWLN }, // *5 - EMUNAND0 N3DS TWLN + { 0x000000, TYPE_EMUNAND, SUBTYPE_TWLP }, // *6 - EMUNAND0 N3DS TWLP + { 0x400000, TYPE_EMUNAND, SUBTYPE_CTRN_N }, // *7 - EMUNAND1 N3DS CTRNAND + { 0x400000, TYPE_EMUNAND, SUBTYPE_TWLN }, // *8 - EMUNAND1 N3DS TWLN + { 0x400000, TYPE_EMUNAND, SUBTYPE_TWLP }, // *9 - EMUNAND1 N3DS TWLP + { 0x800000, TYPE_EMUNAND, SUBTYPE_CTRN_N }, // *10 - EMUNAND2 N3DS CTRNAND + { 0x800000, TYPE_EMUNAND, SUBTYPE_TWLN }, // *11 - EMUNAND2 N3DS TWLN + { 0x800000, TYPE_EMUNAND, SUBTYPE_TWLP }, // *12 - EMUNAND2 N3DS TWLP + { 0xC00000, TYPE_EMUNAND, SUBTYPE_CTRN_N }, // *13 - EMUNAND3 N3DS CTRNAND + { 0xC00000, TYPE_EMUNAND, SUBTYPE_TWLN }, // *14 - EMUNAND3 N3DS TWLN + { 0xC00000, TYPE_EMUNAND, SUBTYPE_TWLP } // *15 - EMUNAND3 N3DS TWLP +}; + +SubtypeDesc SubTypes[4] = { + { 0x05CAE5, AES_CNT_CTRNAND_MODE, 0x4 }, // O3DS CTRNAND + { 0x05CAD7, AES_CNT_CTRNAND_MODE, 0x5 }, // N3DS CTRNAND + { 0x000097, AES_CNT_TWLNAND_MODE, 0x3 }, // TWLN + { 0x04808D, AES_CNT_TWLNAND_MODE, 0x3 } // TWLP }; static bool mode_n3ds = false; +/*-----------------------------------------------------------------------*/ +/* Get counter for NAND AES decryption */ +/*-----------------------------------------------------------------------*/ + +u32 GetNandCtr(u8* ctr, u32 sector) +{ + // static const char* versions[] = {"4.x", "5.x", "6.x", "7.x", "8.x", "9.x"}; + static const u8* version_ctrs[] = { + (u8*)0x080D7CAC, + (u8*)0x080D858C, + (u8*)0x080D748C, + (u8*)0x080D740C, + (u8*)0x080D74CC, + (u8*)0x080D794C + }; + static const u32 version_ctrs_len = sizeof(version_ctrs) / sizeof(u32); + static u8* ctr_start = NULL; + + if (ctr_start == NULL) { + for (u32 i = 0; i < version_ctrs_len; i++) { + if (*(u32*)version_ctrs[i] == 0x5C980) { + ctr_start = (u8*) version_ctrs[i] + 0x30; + } + } + + // If value not in previous list start memory scanning (test range) + if (ctr_start == NULL) { + for (u8* c = (u8*) 0x080D8FFF; c > (u8*) 0x08000000; c--) { + if (*(u32*)c == 0x5C980 && *(u32*)(c + 1) == 0x800005C9) { + ctr_start = c + 0x30; + break; + } + } + } + + if (ctr_start == NULL) { + return 1; + } + } + + // the ctr is stored backwards in memory + if (sector >= (0x0B100000 / 0x200)) { // CTRNAND/AGBSAVE region + for (u32 i = 0; i < 16; i++) + ctr[i] = *(ctr_start + (0xF - i)); + } else { // TWL region + for (u32 i = 0; i < 16; i++) + ctr[i] = *(ctr_start + 0x88 + (0xF - i)); + } + + // increment counter + add_ctr(ctr, sector * (0x200/0x10)); + + return 0; +} + + + /*-----------------------------------------------------------------------*/ /* Get Drive Status */ /*-----------------------------------------------------------------------*/ @@ -97,21 +176,38 @@ DRESULT disk_read ( DWORD sector, /* Sector address in LBA */ UINT count /* Number of sectors to read */ ) -{ - if ((pdrv >= 4) && mode_n3ds) - pdrv += 12; +{ + if ((pdrv > 0) && mode_n3ds) // is this really set at this point? + pdrv += 15; - if (DriveInfo[pdrv].type == TYPE_SDCARD) { + BYTE type = DriveInfo[pdrv].type; + + if (type == TYPE_SDCARD) { if (sdmmc_sdcard_readsectors(sector, count, buff)) { return RES_PARERR; } } else { - PartitionInfo* partition = GetPartitionInfo(DriveInfo[pdrv].subtype); - if (partition == NULL) return RES_PARERR; - u32 offset = (sector * 0x200) + partition->offset; - SetNand(DriveInfo[pdrv].type == TYPE_EMUNAND, DriveInfo[pdrv].offset); - if (DecryptNandToMem(buff, offset, count * 0x200, partition) != 0) + BYTE subtype = DriveInfo[pdrv].subtype; + DWORD isector = SubTypes[subtype].offset + sector; + DWORD mode = SubTypes[subtype].mode; + BYTE ctr[16] __attribute__((aligned(32))); + + if (type == TYPE_SYSNAND) { + if (sdmmc_nand_readsectors(isector, count, buff)) + return RES_PARERR; + } else if (sdmmc_sdcard_readsectors(DriveInfo[pdrv].offset + isector, count, buff)) { return RES_PARERR; + } + + GetNandCtr(ctr, isector); + use_aeskey(SubTypes[subtype].keyslot); + for (UINT s = 0; s < count; s++) { + for (UINT b = 0x0; b < 0x200; b += 0x10, buff += 0x10) { + set_ctr(ctr); + aes_decrypt((void*) buff, (void*) buff, 1, mode); + add_ctr(ctr, 0x1); + } + } } return RES_OK; @@ -132,21 +228,36 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - if ((pdrv >= 4) && mode_n3ds) - pdrv += 12; + if ((pdrv > 0) && mode_n3ds) + pdrv += 15; if (DriveInfo[pdrv].type == TYPE_SDCARD) { if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) { return RES_PARERR; } } else { - PartitionInfo* partition = GetPartitionInfo(DriveInfo[pdrv].subtype); - if (partition == NULL) return RES_PARERR; - u32 offset = (sector * 0x200) + partition->offset; - SetNand(DriveInfo[pdrv].type == TYPE_EMUNAND, DriveInfo[pdrv].offset); - // if (EncryptMemToNand(buff, offset, count * 0x200, partition) != 0) + BYTE subtype = DriveInfo[pdrv].subtype; + DWORD isector = SubTypes[subtype].offset + sector; + DWORD mode = SubTypes[subtype].mode; + BYTE ctr[16] __attribute__((aligned(32))); + + GetNandCtr(ctr, isector); + use_aeskey(SubTypes[subtype].keyslot); + for (UINT s = 0; s < count; s++) { + for (UINT b = 0x0; b < 0x200; b += 0x10, buff += 0x10) { + set_ctr(ctr); + aes_decrypt((void*) buff, (void*) buff, 1, mode); + add_ctr(ctr, 0x1); + } + } + + /*if (type == TYPE_SYSNAND) { + if (sdmmc_nand_writesectors(isector, count, buff)) + return RES_PARERR; + } else if (sdmmc_sdcard_writesectors(DriveInfo[pdrv].offset + isector, count, buff)) { return RES_PARERR; - // NO, not yet! + }*/ + // stubbed, better be safe! } return RES_OK; @@ -169,8 +280,8 @@ DRESULT disk_ioctl ( void *buff /* Buffer to send/receive control data */ ) { - if ((pdrv >= 4) && mode_n3ds) - pdrv += 12; + if ((pdrv > 0) && mode_n3ds) + pdrv += 15; switch (cmd) { case GET_SECTOR_SIZE: diff --git a/source/fatfs/nandio.c b/source/fatfs/nandio.c deleted file mode 100644 index b3bb101..0000000 --- a/source/fatfs/nandio.c +++ /dev/null @@ -1,220 +0,0 @@ -#include "platform.h" -#include "fatfs/aes.h" -#include "fatfs/nandio.h" -#include "fatfs/sdmmc.h" - -// see: http://3dbrew.org/wiki/Flash_Filesystem -static PartitionInfo partitions[] = { - { "TWLN", {0xE9, 0x00, 0x00, 0x54, 0x57, 0x4C, 0x20, 0x20}, 0x00012E00, 0x08FB5200, 0x3, AES_CNT_TWLNAND_MODE }, - { "TWLP", {0xE9, 0x00, 0x00, 0x54, 0x57, 0x4C, 0x20, 0x20}, 0x09011A00, 0x020B6600, 0x3, AES_CNT_TWLNAND_MODE }, - { "AGBSAVE", {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 0x0B100000, 0x00030000, 0x7, AES_CNT_CTRNAND_MODE }, - { "FIRM0", {0x46, 0x49, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x00}, 0x0B130000, 0x00400000, 0x6, AES_CNT_CTRNAND_MODE }, - { "FIRM1", {0x46, 0x49, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x00}, 0x0B530000, 0x00400000, 0x6, AES_CNT_CTRNAND_MODE }, - { "CTRNAND", {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20}, 0x0B95CA00, 0x2F3E3600, 0x4, AES_CNT_CTRNAND_MODE }, // O3DS - { "CTRNAND", {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20}, 0x0B95AE00, 0x41D2D200, 0x5, AES_CNT_CTRNAND_MODE } // N3DS -}; - -static u32 emunand_header = 0; -static u32 emunand_offset = 0; - - -u32 CheckEmuNand(void) -{ - u8 header[0x200]; - u32 nand_size_sectors = getMMCDevice(0)->total_size; - u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS; - u32 ret = EMUNAND_NOT_READY; - - // check the MBR for presence of a hidden partition - sdmmc_sdcard_readsectors(0, 1, header); - u32 hidden_sectors = getle32(header + 0x1BE + 0x8); - - for (u32 offset_sector = 0; offset_sector + nand_size_sectors < hidden_sectors; offset_sector += multi_sectors) { - // check for Gateway type EmuNAND - sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, header); - if (memcmp(header + 0x100, "NCSD", 4) == 0) { - ret |= EMUNAND_GATEWAY << (2 * (offset_sector / multi_sectors)); - continue; - } - // check for RedNAND type EmuNAND - sdmmc_sdcard_readsectors(offset_sector + 1, 1, header); - if (memcmp(header + 0x100, "NCSD", 4) == 0) { - ret |= EMUNAND_REDNAND << (2 * (offset_sector / multi_sectors)); - continue; - } - // EmuNAND ready but not set up - ret |= EMUNAND_READY << (2 * (offset_sector / multi_sectors)); - } - - return ret; -} - -void SetNand(bool set_emunand, u32 base_sector) -{ - // no checks here AT ALL - be careful!!! - if (set_emunand) { - emunand_header = base_sector + getMMCDevice(0)->total_size; - emunand_offset = base_sector; - } else { - emunand_header = 0; - emunand_offset = 0; - } -} - -int ReadNandSectors(u32 sector_no, u32 numsectors, u8 *out) -{ - if (emunand_header) { - if (sector_no == 0) { - int errorcode = sdmmc_sdcard_readsectors(emunand_header, 1, out); - if (errorcode) return errorcode; - sector_no = 1; - numsectors--; - out += 0x200; - } - return sdmmc_sdcard_readsectors(sector_no + emunand_offset, numsectors, out); - } else return sdmmc_nand_readsectors(sector_no, numsectors, out); -} - -int WriteNandSectors(u32 sector_no, u32 numsectors, u8 *in) -{ - if (emunand_header) { - if (sector_no == 0) { - int errorcode = sdmmc_sdcard_writesectors(emunand_header, 1, in); - if (errorcode) return errorcode; - sector_no = 1; - numsectors--; - in += 0x200; - } - return sdmmc_sdcard_writesectors(sector_no + emunand_offset, numsectors, in); - } else return sdmmc_nand_writesectors(sector_no, numsectors, in); -} - -u32 GetNandSize(void) -{ - return getMMCDevice(0)->total_size * NAND_SECTOR_SIZE; -} - -PartitionInfo* GetPartitionInfo(u32 partition_id) -{ - u32 partition_num = 0; - - if (partition_id == P_CTRNAND) { - partition_num = (GetUnitPlatform() == PLATFORM_3DS) ? 5 : 6; - } else { - for(; !(partition_id & (1<= 32) ? NULL : &(partitions[partition_num]); -} - -u32 GetNandCtr(u8* ctr, u32 offset) -{ - // static const char* versions[] = {"4.x", "5.x", "6.x", "7.x", "8.x", "9.x"}; - static const u8* version_ctrs[] = { - (u8*)0x080D7CAC, - (u8*)0x080D858C, - (u8*)0x080D748C, - (u8*)0x080D740C, - (u8*)0x080D74CC, - (u8*)0x080D794C - }; - static const u32 version_ctrs_len = sizeof(version_ctrs) / sizeof(u32); - static u8* ctr_start = NULL; - - if (ctr_start == NULL) { - for (u32 i = 0; i < version_ctrs_len; i++) { - if (*(u32*)version_ctrs[i] == 0x5C980) { - ctr_start = (u8*) version_ctrs[i] + 0x30; - } - } - - // If value not in previous list start memory scanning (test range) - if (ctr_start == NULL) { - for (u8* c = (u8*) 0x080D8FFF; c > (u8*) 0x08000000; c--) { - if (*(u32*)c == 0x5C980 && *(u32*)(c + 1) == 0x800005C9) { - ctr_start = c + 0x30; - break; - } - } - } - - if (ctr_start == NULL) { - return 1; - } - } - - // the ctr is stored backwards in memory - if (offset >= 0x0B100000) { // CTRNAND/AGBSAVE region - for (u32 i = 0; i < 16; i++) - ctr[i] = *(ctr_start + (0xF - i)); - } else { // TWL region - for (u32 i = 0; i < 16; i++) - ctr[i] = *(ctr_start + 0x88 + (0xF - i)); - } - - // increment counter - add_ctr(ctr, offset / 0x10); - - return 0; -} - -u32 CryptBuffer(CryptBufferInfo *info) -{ - u8 ctr[16] __attribute__((aligned(32))); - memcpy(ctr, info->ctr, 16); - - u8* buffer = info->buffer; - u32 size = info->size; - u32 mode = info->mode; - - if (info->setKeyY) { - u8 keyY[16] __attribute__((aligned(32))); - memcpy(keyY, info->keyY, 16); - setup_aeskeyY(info->keyslot, keyY); - info->setKeyY = 0; - } - use_aeskey(info->keyslot); - - for (u32 i = 0; i < size; i += 0x10, buffer += 0x10) { - set_ctr(ctr); - if ((mode & (0x7 << 27)) == AES_CBC_DECRYPT_MODE) - memcpy(ctr, buffer, 0x10); - aes_decrypt((void*) buffer, (void*) buffer, 1, mode); - if ((mode & (0x7 << 27)) == AES_CBC_ENCRYPT_MODE) - memcpy(ctr, buffer, 0x10); - else if ((mode & (0x7 << 27)) == AES_CTR_MODE) - add_ctr(ctr, 0x1); - } - - memcpy(info->ctr, ctr, 16); - - return 0; -} - -u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition) -{ - CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode}; - if(GetNandCtr(info.ctr, offset) != 0) - return 1; - - u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE; - u32 start_sector = offset / NAND_SECTOR_SIZE; - ReadNandSectors(start_sector, n_sectors, buffer); - CryptBuffer(&info); - - return 0; -} - -u32 EncryptMemToNand(u8* buffer, u32 offset, u32 size, PartitionInfo* partition) -{ - CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode}; - if(GetNandCtr(info.ctr, offset) != 0) - return 1; - - u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE; - u32 start_sector = offset / NAND_SECTOR_SIZE; - CryptBuffer(&info); - WriteNandSectors(start_sector, n_sectors, buffer); - - return 0; -} diff --git a/source/fatfs/nandio.h b/source/fatfs/nandio.h deleted file mode 100644 index 2a018ec..0000000 --- a/source/fatfs/nandio.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#include "common.h" - -#define BUFFER_ADDRESS ((u8*) 0x21000000) // buffer must not be used for anything else! -#define BUFFER_MAX_SIZE (1 * 1024 * 1024) // must be a multiple of 0x40 (64) - -#define NAND_SECTOR_SIZE 0x200 -#define SECTORS_PER_READ (BUFFER_MAX_SIZE / NAND_SECTOR_SIZE) - -#define P_TWLN (1<<0) -#define P_TWLP (1<<1) -#define P_AGBSAVE (1<<2) -#define P_FIRM0 (1<<3) -#define P_FIRM1 (1<<4) -#define P_CTRNAND (1<<5) - -// return values for the CheckEmuNAND() function -#define EMUNAND_NOT_READY 0 // must be zero -#define EMUNAND_READY 1 -#define EMUNAND_GATEWAY 2 -#define EMUNAND_REDNAND 3 - -// these offsets are used by Multi EmuNAND Creator -#define EMUNAND_MULTI_OFFSET_O3DS 0x00200000 -#define EMUNAND_MULTI_OFFSET_N3DS 0x00400000 - -typedef struct { - u32 keyslot; - u32 setKeyY; - u8 ctr[16]; - u8 keyY[16]; - u32 size; - u32 mode; - u8* buffer; -} __attribute__((packed)) CryptBufferInfo; - -typedef struct { - char name[16]; - u8 magic[8]; - u32 offset; - u32 size; - u32 keyslot; - u32 mode; -} __attribute__((packed)) PartitionInfo; - -PartitionInfo* GetPartitionInfo(u32 partition_id); - -u32 CheckEmuNand(void); -void SetNand(bool set_emunand, u32 base_sector); - -u32 GetNandCtr(u8* ctr, u32 offset); -u32 CryptBuffer(CryptBufferInfo *info); - -int ReadNandSectors(u32 sector_no, u32 numsectors, u8 *out); -int WriteNandSectors(u32 sector_no, u32 numsectors, u8 *in); -u32 GetNandSize(void); - -u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition); -u32 EncryptMemToNand(u8* buffer, u32 offset, u32 size, PartitionInfo* partition); diff --git a/source/fs.c b/source/fs.c index cd0b5e4..ec39cc7 100644 --- a/source/fs.c +++ b/source/fs.c @@ -1,7 +1,6 @@ #include "draw.h" #include "fs.h" #include "fatfs/ff.h" -#include "fatfs/nandio.h" // don't use this area for anything else! static FATFS* fs = (FATFS*)0x20316000; diff --git a/source/godmode.c b/source/godmode.c index c760213..44dce96 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -41,7 +41,10 @@ u32 GodMode() { u32 offset_disp = 0; ClearScreenFull(true, true, COLOR_BLACK); - if (!InitFS()) return exit_mode; + if (!InitFS()) { + InputWait(); + return exit_mode; + } contents = GetDirContents(""); while (true) { // this is the main loop