mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Make this A9LH compatible
This commit is contained in:
parent
ec142564c0
commit
158d10410c
@ -81,6 +81,7 @@ _enable_caches:
|
|||||||
mcr p15, 0, r5, c7, c6, 0 @ flush D-cache
|
mcr p15, 0, r5, c7, c6, 0 @ flush D-cache
|
||||||
|
|
||||||
mrc p15, 0, r4, c1, c0, 0
|
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<<12) @ instruction cache enable
|
||||||
orr r4, r4, #(1<<2) @ data cache enable
|
orr r4, r4, #(1<<2) @ data cache enable
|
||||||
orr r4, r4, #(1<<0) @ mpu enable
|
orr r4, r4, #(1<<0) @ mpu enable
|
||||||
|
@ -78,9 +78,10 @@ DSTATUS disk_initialize (
|
|||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (pdrv == 0) { // a mounted SD card is the preriquisite for everything else
|
||||||
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
|
mode_n3ds = (GetUnitPlatform() == PLATFORM_N3DS);
|
||||||
sdmmc_sdcard_init(); // multiple inits should not be required (also, below)
|
sdmmc_sdcard_init();
|
||||||
InitNandCrypto();
|
}
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
source/fs.c
72
source/fs.c
@ -2,6 +2,9 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fatfs/ff.h"
|
#include "fatfs/ff.h"
|
||||||
|
|
||||||
|
#define MAX_FS 7
|
||||||
|
|
||||||
|
|
||||||
// don't use this area for anything else!
|
// don't use this area for anything else!
|
||||||
static FATFS* fs = (FATFS*)0x20316000;
|
static FATFS* fs = (FATFS*)0x20316000;
|
||||||
|
|
||||||
@ -14,35 +17,37 @@ static size_t main_buffer_size = 1 * 1024 * 1024;
|
|||||||
static u32 write_permission_level = 1;
|
static u32 write_permission_level = 1;
|
||||||
|
|
||||||
// number of currently open file systems
|
// number of currently open file systems
|
||||||
static u32 numfs = 0;
|
static bool fs_mounted[MAX_FS] = { false };
|
||||||
|
|
||||||
bool InitFS() {
|
bool InitSDCardFS() {
|
||||||
#ifndef EXEC_GATEWAY
|
#ifndef EXEC_GATEWAY
|
||||||
// TODO: Magic?
|
// TODO: Magic?
|
||||||
*(u32*)0x10000020 = 0;
|
*(u32*)0x10000020 = 0;
|
||||||
*(u32*)0x10000020 = 0x340;
|
*(u32*)0x10000020 = 0x340;
|
||||||
#endif
|
#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];
|
char fsname[8];
|
||||||
snprintf(fsname, 7, "%lu:", numfs);
|
snprintf(fsname, 7, "%lu:", i);
|
||||||
int res = f_mount(fs + numfs, fsname, 1);
|
if (f_mount(fs + i, fsname, 1) != FR_OK) return false;
|
||||||
if (res != FR_OK) {
|
fs_mounted[i] = true;
|
||||||
if (numfs >= 1) break;
|
|
||||||
ShowPrompt(false, "Initialising failed! (%lu/%s/%i)", numfs, fsname, res);
|
|
||||||
DeinitFS();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeinitFS() {
|
void DeinitFS() {
|
||||||
for (u32 i = 0; i < numfs; i++) {
|
for (u32 i = 0; i < MAX_FS; i++) {
|
||||||
|
if (fs_mounted[i]) {
|
||||||
char fsname[8];
|
char fsname[8];
|
||||||
snprintf(fsname, 7, "%lu:", numfs);
|
snprintf(fsname, 7, "%lu:", i);
|
||||||
f_mount(NULL, fsname, 1);
|
f_mount(NULL, fsname, 1);
|
||||||
|
fs_mounted[i] = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
numfs = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckWritePermissions(const char* path) {
|
bool CheckWritePermissions(const char* path) {
|
||||||
@ -103,17 +108,29 @@ u32 GetWritePermissions() {
|
|||||||
return write_permission_level;
|
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;
|
FIL file;
|
||||||
UINT bytes_written = 0;
|
UINT bytes_written = 0;
|
||||||
if (!CheckWritePermissions(path)) return false;
|
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;
|
return false;
|
||||||
f_write(&file, data, size, &bytes_written);
|
f_write(&file, data, size, &bytes_written);
|
||||||
f_close(&file);
|
f_close(&file);
|
||||||
return (bytes_written == size);
|
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) {
|
bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
|
||||||
FILINFO fno = {.lfname = NULL};
|
FILINFO fno = {.lfname = NULL};
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
@ -292,7 +309,7 @@ void CreateScreenshot() {
|
|||||||
for (u32 x = 0; x < 320; x++)
|
for (u32 x = 0; x < 320; x++)
|
||||||
for (u32 y = 0; y < 240; y++)
|
for (u32 y = 0; y < 240; y++)
|
||||||
memcpy(buffer + (y*400 + x + 40) * 3, BOT_SCREEN0 + (x*240 + y) * 3, 3);
|
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) {
|
void DirEntryCpy(DirEntry* dest, const DirEntry* orig) {
|
||||||
@ -330,17 +347,20 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
|||||||
"SYSNAND CTRNAND", "SYSNAND TWLN", "SYSNAND TWLP",
|
"SYSNAND CTRNAND", "SYSNAND TWLN", "SYSNAND TWLP",
|
||||||
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP"
|
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP"
|
||||||
};
|
};
|
||||||
|
u32 n_entries = 0;
|
||||||
|
|
||||||
for (u32 pdrv = 0; (pdrv < numfs) && (pdrv < MAX_ENTRIES); pdrv++) {
|
for (u32 pdrv = 0; (pdrv < MAX_FS) && (pdrv < MAX_ENTRIES); pdrv++) {
|
||||||
memset(contents->entry[pdrv].path, 0x00, 16);
|
if (!fs_mounted[pdrv]) continue;
|
||||||
snprintf(contents->entry[pdrv].path + 0, 4, "%lu:", pdrv);
|
memset(contents->entry[n_entries].path, 0x00, 16);
|
||||||
snprintf(contents->entry[pdrv].path + 4, 32, "[%lu:] %s", pdrv, drvname[pdrv]);
|
snprintf(contents->entry[n_entries].path + 0, 4, "%lu:", pdrv);
|
||||||
contents->entry[pdrv].name = contents->entry[pdrv].path + 4;
|
snprintf(contents->entry[n_entries].path + 4, 32, "[%lu:] %s", pdrv, drvname[pdrv]);
|
||||||
contents->entry[pdrv].size = GetTotalSpace(contents->entry[pdrv].path);
|
contents->entry[n_entries].name = contents->entry[n_entries].path + 4;
|
||||||
contents->entry[pdrv].type = T_VRT_ROOT;
|
contents->entry[n_entries].size = GetTotalSpace(contents->entry[n_entries].path);
|
||||||
contents->entry[pdrv].marked = 0;
|
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;
|
return contents->n_entries;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,8 @@ typedef struct {
|
|||||||
DirEntry entry[MAX_ENTRIES];
|
DirEntry entry[MAX_ENTRIES];
|
||||||
} DirStruct;
|
} DirStruct;
|
||||||
|
|
||||||
bool InitFS();
|
bool InitSDCardFS();
|
||||||
|
bool InitNandFS();
|
||||||
void DeinitFS();
|
void DeinitFS();
|
||||||
|
|
||||||
/** Check if writing to this path is allowed **/
|
/** Check if writing to this path is allowed **/
|
||||||
@ -37,7 +38,10 @@ bool SetWritePermissions(u32 level);
|
|||||||
u32 GetWritePermissions();
|
u32 GetWritePermissions();
|
||||||
|
|
||||||
/** Create / overwrite file and write the provided data to it **/
|
/** 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 **/
|
/** Recursively copy a file or directory **/
|
||||||
bool PathCopy(const char* destdir, const char* orig);
|
bool PathCopy(const char* destdir, const char* orig);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
#include "fs.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_TOP_BAR ((GetWritePermissions() == 0) ? COLOR_WHITE : (GetWritePermissions() == 1) ? COLOR_BRIGHTGREEN : (GetWritePermissions() == 2) ? COLOR_BRIGHTYELLOW : COLOR_RED)
|
||||||
#define COLOR_SIDE_BAR COLOR_DARKGREY
|
#define COLOR_SIDE_BAR COLOR_DARKGREY
|
||||||
@ -138,11 +139,16 @@ u32 GodMode() {
|
|||||||
u32 cursor = 0;
|
u32 cursor = 0;
|
||||||
|
|
||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
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, "");
|
GetDirContents(current_dir, "");
|
||||||
clipboard->n_entries = 0;
|
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);
|
DrawUserInterface(current_path, &(current_dir->entry[cursor]), clipboard);
|
||||||
DrawDirContents(current_dir, cursor);
|
DrawDirContents(current_dir, cursor);
|
||||||
u32 pad_state = InputWait();
|
u32 pad_state = InputWait();
|
||||||
|
@ -5,30 +5,57 @@ void setup_aeskeyX(u8 keyslot, void* keyx)
|
|||||||
{
|
{
|
||||||
u32 * _keyx = (u32*)keyx;
|
u32 * _keyx = (u32*)keyx;
|
||||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
if (keyslot > 3) {
|
||||||
*REG_AESKEYXFIFO = _keyx[0];
|
*REG_AESKEYXFIFO = _keyx[0];
|
||||||
*REG_AESKEYXFIFO = _keyx[1];
|
*REG_AESKEYXFIFO = _keyx[1];
|
||||||
*REG_AESKEYXFIFO = _keyx[2];
|
*REG_AESKEYXFIFO = _keyx[2];
|
||||||
*REG_AESKEYXFIFO = _keyx[3];
|
*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)
|
void setup_aeskeyY(u8 keyslot, void* keyy)
|
||||||
{
|
{
|
||||||
u32 * _keyy = (u32*)keyy;
|
u32 * _keyy = (u32*)keyy;
|
||||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
if (keyslot > 3) {
|
||||||
*REG_AESKEYYFIFO = _keyy[0];
|
*REG_AESKEYYFIFO = _keyy[0];
|
||||||
*REG_AESKEYYFIFO = _keyy[1];
|
*REG_AESKEYYFIFO = _keyy[1];
|
||||||
*REG_AESKEYYFIFO = _keyy[2];
|
*REG_AESKEYYFIFO = _keyy[2];
|
||||||
*REG_AESKEYYFIFO = _keyy[3];
|
*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)
|
void setup_aeskey(u8 keyslot, void* key)
|
||||||
{
|
{
|
||||||
u32 * _key = (u32*)key;
|
u32 * _key = (u32*)key;
|
||||||
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
if (keyslot > 3) {
|
||||||
*REG_AESKEYFIFO = _key[0];
|
*REG_AESKEYFIFO = _key[0];
|
||||||
*REG_AESKEYFIFO = _key[1];
|
*REG_AESKEYFIFO = _key[1];
|
||||||
*REG_AESKEYFIFO = _key[2];
|
*REG_AESKEYFIFO = _key[2];
|
||||||
*REG_AESKEYFIFO = _key[3];
|
*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)
|
void use_aeskey(u32 keyno)
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#define REG_AESKEYFIFO ((volatile u32*)0x10009100)
|
#define REG_AESKEYFIFO ((volatile u32*)0x10009100)
|
||||||
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104)
|
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104)
|
||||||
#define REG_AESKEYYFIFO ((volatile u32*)0x10009108)
|
#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_START 0x80000000
|
||||||
#define AES_CNT_INPUT_ORDER 0x02000000
|
#define AES_CNT_INPUT_ORDER 0x02000000
|
||||||
|
@ -33,7 +33,38 @@ bool InitNandCrypto(void)
|
|||||||
for(u32 i = 0; i < 16; i++) // little endian and reversed order
|
for(u32 i = 0; i < 16; i++) // little endian and reversed order
|
||||||
TwlNandCtr[i] = shasum[15-i];
|
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;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user