Make this A9LH compatible

This commit is contained in:
d0k3 2016-03-11 01:29:14 +01:00
parent ec142564c0
commit 158d10410c
8 changed files with 140 additions and 48 deletions

View File

@ -81,6 +81,7 @@ _enable_caches:
mcr p15, 0, r5, c7, c6, 0 @ flush D-cache
mrc p15, 0, r4, c1, c0, 0
orr r4, r4, #(1<<18) @ itcm enable
orr r4, r4, #(1<<12) @ instruction cache enable
orr r4, r4, #(1<<2) @ data cache enable
orr r4, r4, #(1<<0) @ mpu enable

View File

@ -78,9 +78,10 @@ DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
sdmmc_sdcard_init(); // multiple inits should not be required (also, below)
InitNandCrypto();
if (pdrv == 0) { // a mounted SD card is the preriquisite for everything else
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
sdmmc_sdcard_init();
}
return RES_OK;
}

View File

@ -2,6 +2,9 @@
#include "fs.h"
#include "fatfs/ff.h"
#define MAX_FS 7
// don't use this area for anything else!
static FATFS* fs = (FATFS*)0x20316000;
@ -14,35 +17,37 @@ static size_t main_buffer_size = 1 * 1024 * 1024;
static u32 write_permission_level = 1;
// number of currently open file systems
static u32 numfs = 0;
static bool fs_mounted[MAX_FS] = { false };
bool InitFS() {
bool InitSDCardFS() {
#ifndef EXEC_GATEWAY
// TODO: Magic?
*(u32*)0x10000020 = 0;
*(u32*)0x10000020 = 0x340;
#endif
for (numfs = 0; numfs < 7; numfs++) {
fs_mounted[0] = (f_mount(fs, "0:", 1) == FR_OK);
return fs_mounted[0];
}
bool InitNandFS() {
for (u32 i = 1; i < MAX_FS; i++) {
char fsname[8];
snprintf(fsname, 7, "%lu:", numfs);
int res = f_mount(fs + numfs, fsname, 1);
if (res != FR_OK) {
if (numfs >= 1) break;
ShowPrompt(false, "Initialising failed! (%lu/%s/%i)", numfs, fsname, res);
DeinitFS();
return false;
}
snprintf(fsname, 7, "%lu:", i);
if (f_mount(fs + i, fsname, 1) != FR_OK) return false;
fs_mounted[i] = true;
}
return true;
}
void DeinitFS() {
for (u32 i = 0; i < numfs; i++) {
char fsname[8];
snprintf(fsname, 7, "%lu:", numfs);
f_mount(NULL, fsname, 1);
for (u32 i = 0; i < MAX_FS; i++) {
if (fs_mounted[i]) {
char fsname[8];
snprintf(fsname, 7, "%lu:", i);
f_mount(NULL, fsname, 1);
fs_mounted[i] = false;
}
}
numfs = 0;
}
bool CheckWritePermissions(const char* path) {
@ -103,17 +108,29 @@ u32 GetWritePermissions() {
return write_permission_level;
}
bool FileCreate(const char* path, u8* data, u32 size) {
bool FileCreateData(const char* path, u8* data, size_t size) {
FIL file;
UINT bytes_written = 0;
if (!CheckWritePermissions(path)) return false;
if (f_open(&file, path, FA_READ | FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
if (f_open(&file, path, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
return false;
f_write(&file, data, size, &bytes_written);
f_close(&file);
return (bytes_written == size);
}
bool FileGetData(const char* path, u8* data, size_t size, size_t foffset)
{
FIL file;
UINT bytes_read = 0;
if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK)
return false;
f_lseek(&file, foffset);
f_read(&file, data, size, &bytes_read);
f_close(&file);
return (bytes_read == size);
}
bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
FILINFO fno = {.lfname = NULL};
bool ret = false;
@ -292,7 +309,7 @@ void CreateScreenshot() {
for (u32 x = 0; x < 320; x++)
for (u32 y = 0; y < 240; y++)
memcpy(buffer + (y*400 + x + 40) * 3, BOT_SCREEN0 + (x*240 + y) * 3, 3);
FileCreate(filename, main_buffer, 54 + (400 * 240 * 3 * 2));
FileCreateData(filename, main_buffer, 54 + (400 * 240 * 3 * 2));
}
void DirEntryCpy(DirEntry* dest, const DirEntry* orig) {
@ -330,17 +347,20 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
"SYSNAND CTRNAND", "SYSNAND TWLN", "SYSNAND TWLP",
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP"
};
u32 n_entries = 0;
for (u32 pdrv = 0; (pdrv < numfs) && (pdrv < MAX_ENTRIES); pdrv++) {
memset(contents->entry[pdrv].path, 0x00, 16);
snprintf(contents->entry[pdrv].path + 0, 4, "%lu:", pdrv);
snprintf(contents->entry[pdrv].path + 4, 32, "[%lu:] %s", pdrv, drvname[pdrv]);
contents->entry[pdrv].name = contents->entry[pdrv].path + 4;
contents->entry[pdrv].size = GetTotalSpace(contents->entry[pdrv].path);
contents->entry[pdrv].type = T_VRT_ROOT;
contents->entry[pdrv].marked = 0;
for (u32 pdrv = 0; (pdrv < MAX_FS) && (pdrv < MAX_ENTRIES); pdrv++) {
if (!fs_mounted[pdrv]) continue;
memset(contents->entry[n_entries].path, 0x00, 16);
snprintf(contents->entry[n_entries].path + 0, 4, "%lu:", pdrv);
snprintf(contents->entry[n_entries].path + 4, 32, "[%lu:] %s", pdrv, drvname[pdrv]);
contents->entry[n_entries].name = contents->entry[n_entries].path + 4;
contents->entry[n_entries].size = GetTotalSpace(contents->entry[n_entries].path);
contents->entry[n_entries].type = T_VRT_ROOT;
contents->entry[n_entries].marked = 0;
n_entries++;
}
contents->n_entries = numfs;
contents->n_entries = n_entries;
return contents->n_entries;
}

View File

@ -24,7 +24,8 @@ typedef struct {
DirEntry entry[MAX_ENTRIES];
} DirStruct;
bool InitFS();
bool InitSDCardFS();
bool InitNandFS();
void DeinitFS();
/** Check if writing to this path is allowed **/
@ -37,7 +38,10 @@ bool SetWritePermissions(u32 level);
u32 GetWritePermissions();
/** Create / overwrite file and write the provided data to it **/
bool FileCreate(const char* path, u8* data, u32 size);
bool FileCreateData(const char* path, u8* data, size_t size);
/** Read data from file@offset **/
bool FileGetData(const char* path, u8* data, size_t size, size_t foffset);
/** Recursively copy a file or directory **/
bool PathCopy(const char* destdir, const char* orig);

View File

@ -2,6 +2,7 @@
#include "draw.h"
#include "hid.h"
#include "fs.h"
#include "nand.h"
#define COLOR_TOP_BAR ((GetWritePermissions() == 0) ? COLOR_WHITE : (GetWritePermissions() == 1) ? COLOR_BRIGHTGREEN : (GetWritePermissions() == 2) ? COLOR_BRIGHTYELLOW : COLOR_RED)
#define COLOR_SIDE_BAR COLOR_DARKGREY
@ -138,11 +139,16 @@ u32 GodMode() {
u32 cursor = 0;
ClearScreenF(true, true, COLOR_STD_BG);
if (!InitFS()) return exit_mode;
if (!InitSDCardFS()) {
ShowPrompt(false, "Initialising SD card failed!");
return exit_mode;
}
InitNandCrypto();
InitNandFS();
GetDirContents(current_dir, "");
clipboard->n_entries = 0;
while (true) { // this is the main loop !!! EMPTY DIRS
while (true) { // this is the main loop
DrawUserInterface(current_path, &(current_dir->entry[cursor]), clipboard);
DrawDirContents(current_dir, cursor);
u32 pad_state = InputWait();

View File

@ -5,30 +5,57 @@ void setup_aeskeyX(u8 keyslot, void* keyx)
{
u32 * _keyx = (u32*)keyx;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
*REG_AESKEYXFIFO = _keyx[0];
*REG_AESKEYXFIFO = _keyx[1];
*REG_AESKEYXFIFO = _keyx[2];
*REG_AESKEYXFIFO = _keyx[3];
if (keyslot > 3) {
*REG_AESKEYXFIFO = _keyx[0];
*REG_AESKEYXFIFO = _keyx[1];
*REG_AESKEYXFIFO = _keyx[2];
*REG_AESKEYXFIFO = _keyx[3];
} else {
u32 old_aescnt = *REG_AESCNT;
vu32* reg_aeskeyx = REG_AESKEY0123 + (((0x30*keyslot) + 0x10)/4);
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
for (u32 i = 0; i < 4; i++)
reg_aeskeyx[i] = _keyx[i];
*REG_AESCNT = old_aescnt;
}
}
void setup_aeskeyY(u8 keyslot, void* keyy)
{
u32 * _keyy = (u32*)keyy;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
*REG_AESKEYYFIFO = _keyy[0];
*REG_AESKEYYFIFO = _keyy[1];
*REG_AESKEYYFIFO = _keyy[2];
*REG_AESKEYYFIFO = _keyy[3];
if (keyslot > 3) {
*REG_AESKEYYFIFO = _keyy[0];
*REG_AESKEYYFIFO = _keyy[1];
*REG_AESKEYYFIFO = _keyy[2];
*REG_AESKEYYFIFO = _keyy[3];
} else {
u32 old_aescnt = *REG_AESCNT;
vu32* reg_aeskeyy = REG_AESKEY0123 + (((0x30*keyslot) + 0x20)/4);
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
for (u32 i = 0; i < 4; i++)
reg_aeskeyy[i] = _keyy[i];
*REG_AESCNT = old_aescnt;
}
}
void setup_aeskey(u8 keyslot, void* key)
{
u32 * _key = (u32*)key;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
*REG_AESKEYFIFO = _key[0];
*REG_AESKEYFIFO = _key[1];
*REG_AESKEYFIFO = _key[2];
*REG_AESKEYFIFO = _key[3];
if (keyslot > 3) {
*REG_AESKEYFIFO = _key[0];
*REG_AESKEYFIFO = _key[1];
*REG_AESKEYFIFO = _key[2];
*REG_AESKEYFIFO = _key[3];
} else {
u32 old_aescnt = *REG_AESCNT;
vu32* reg_aeskey = REG_AESKEY0123 + ((0x30*keyslot)/4);
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER));
for (u32 i = 0; i < 4; i++)
reg_aeskey[i] = _key[i];
*REG_AESCNT = old_aescnt;
}
}
void use_aeskey(u32 keyno)

View File

@ -22,6 +22,8 @@
#define REG_AESKEYFIFO ((volatile u32*)0x10009100)
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104)
#define REG_AESKEYYFIFO ((volatile u32*)0x10009108)
// see https://www.3dbrew.org/wiki/AES_Registers#AES_KEY0.2F1.2F2.2F3
#define REG_AESKEY0123 ((volatile u32*)0x10009040)
#define AES_CNT_START 0x80000000
#define AES_CNT_INPUT_ORDER 0x02000000

View File

@ -33,9 +33,40 @@ bool InitNandCrypto(void)
for(u32 i = 0; i < 16; i++) // little endian and reversed order
TwlNandCtr[i] = shasum[15-i];
// STEP #2: Calculate slot 0x3 key, set it up to slot 0x11
// part #2: TWL KEY
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
u32* TwlCustId = (u32*) (0x01FFB808);
u8 TwlKeyX[16];
u8 TwlKeyY[16];
// thanks b1l1s & Normmatt
// see source from https://gbatemp.net/threads/release-twltool-dsi-downgrading-save-injection-etc-multitool.393488/
const char* nintendo = "NINTENDO";
u32* TwlKeyXW = (u32*) TwlKeyX;
TwlKeyXW[0] = (TwlCustId[0] ^ 0xB358A6AF) | 0x80000000;
TwlKeyXW[3] = TwlCustId[1] ^ 0x08C267B7;
memcpy(TwlKeyX + 4, nintendo, 8);
// see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM
u32 TwlKeyYW3 = 0xE1A00005;
memcpy(TwlKeyY, (u8*) 0x01FFD3C8, 12);
memcpy(TwlKeyY + 12, &TwlKeyYW3, 4);
setup_aeskeyX(0x03, TwlKeyX);
setup_aeskeyY(0x03, TwlKeyY);
use_aeskey(0x03);
// part #3: CTRNAND N3DS KEY
if (GetUnitPlatform() == PLATFORM_N3DS) {
u8 CtrNandKeyY[16];
if (FileGetData("0:/slot0x05KeyY.bin", CtrNandKeyY, 16, 0)) {
setup_aeskeyY(0x05, CtrNandKeyY);
use_aeskey(0x05);
}
}
return true;
}