From 50500cfd4939d7d6e367c3fddac7bc272ff26bce Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 12 Aug 2021 15:35:13 +0200 Subject: [PATCH] BAHAHAHAHAHAHAHH --- src/CMakeLists.txt | 1 + src/DSi.cpp | 68 +--------------- src/DSi_NAND.cpp | 173 ++++++++++++++++++++++++++++++++++++++++ src/DSi_NAND.h | 33 ++++++++ src/SPI.cpp | 1 - src/fatfs/diskio.c | 184 ++++++++++--------------------------------- src/fatfs/ff.h | 9 +++ src/fatfs/ffconf.h | 2 +- src/fatfs/ffsystem.c | 90 ++++++--------------- 9 files changed, 283 insertions(+), 278 deletions(-) create mode 100644 src/DSi_NAND.cpp create mode 100644 src/DSi_NAND.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a4289d0..54d08992 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,7 @@ add_library(core STATIC DSi_Camera.cpp DSi_DSP.cpp DSi_I2C.cpp + DSi_NAND.cpp DSi_NDMA.cpp DSi_NWifi.cpp DSi_SD.cpp diff --git a/src/DSi.cpp b/src/DSi.cpp index 21764a7e..47590dd5 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -36,10 +36,10 @@ #include "DSi_I2C.h" #include "DSi_SD.h" #include "DSi_AES.h" +#include "DSi_NAND.h" #include "DSi_DSP.h" #include "DSi_Camera.h" -#include "sha1/sha1.hpp" #include "tiny-AES-c/aes.hpp" @@ -530,70 +530,8 @@ bool LoadNAND() memcpy(&ARM7Init[0x0254], &ARM7iBIOS[0xC6D0], 0x1048); memcpy(&ARM7Init[0x129C], &ARM7iBIOS[0xD718], 0x1048); - // TEST ZONE - { - SHA1_CTX sha; - u8 cidhash[20]; - u8 iv[16]; - - SHA1Init(&sha); - SHA1Update(&sha, eMMC_CID, 16); - SHA1Final(cidhash, &sha); - - printf("ASS HASH: "); - for (int i = 0; i < 20; i++) printf("%02X", cidhash[i]); - printf("\n"); - - DSi_AES::Swap16(iv, cidhash); - - printf("ASS IV: "); - for (int i = 0; i < 16; i++) printf("%02X", iv[i]); - printf("\n"); - - u8 keyX[16]; - *(u32*)&keyX[0] = (u32)ConsoleID; - *(u32*)&keyX[4] = (u32)ConsoleID ^ 0x24EE6906; - *(u32*)&keyX[8] = (u32)(ConsoleID >> 32) ^ 0xE65B601D; - *(u32*)&keyX[12] = (u32)(ConsoleID >> 32); - - u8 keyY[16]; - *(u32*)&keyY[0] = 0x0AB9DC76; - *(u32*)&keyY[4] = 0xBD4DC4D3; - *(u32*)&keyY[8] = 0x202DDD1D; - *(u32*)&keyY[12] = 0xE1A00005; - - u8 shittykey[16]; - DSi_AES::DeriveNormalKey(keyX, keyY, shittykey); - - u8 normalkey[16]; - DSi_AES::Swap16(normalkey, shittykey); - - u8 dorp[0x200]; - fseek(SDMMCFile, 0, SEEK_SET); - fread(&dorp, 0x200, 1, SDMMCFile); - - AES_ctx ctx; - AES_init_ctx_iv(&ctx, normalkey, iv); - - //AES_CTR_xcrypt_buffer(&ctx, dorp, 0x200); - for (int i = 0; i < 0x200; i+=16) - { - u8 tmp[16]; - DSi_AES::Swap16(tmp, &dorp[i]); - AES_CTR_xcrypt_buffer(&ctx, tmp, 16); - DSi_AES::Swap16(&dorp[i], tmp); - } - - //printf("%08X %08X %08X %08X\n", *(u32*)&dorp[0], *(u32*)&dorp[4], *(u32*)&dorp[8], *(u32*)&dorp[12]); - for (int i = 0; i < 0x200; i+=16) - { - for (int j = 0; j < 16; j++) - { - printf("%02X ", dorp[i+j]); - } - printf("\n"); - } - } + DSi_NAND::Init(); + DSi_NAND::PatchTSC(); return true; } diff --git a/src/DSi_NAND.cpp b/src/DSi_NAND.cpp new file mode 100644 index 00000000..678dc9a9 --- /dev/null +++ b/src/DSi_NAND.cpp @@ -0,0 +1,173 @@ +/* + Copyright 2016-2021 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#include + +#include "DSi.h" +#include "DSi_AES.h" +#include "DSi_NAND.h" + +#include "sha1/sha1.hpp" +#include "tiny-AES-c/aes.hpp" + +#include "fatfs/ff.h" + + +namespace DSi_NAND +{ + +u8 FATIV[16]; +u8 FATKey[16]; + + +void Init() +{ + // init NAND crypto + + SHA1_CTX sha; + u8 tmp[20]; + + SHA1Init(&sha); + SHA1Update(&sha, DSi::eMMC_CID, 16); + SHA1Final(tmp, &sha); + + DSi_AES::Swap16(FATIV, tmp); + + u8 keyX[16]; + *(u32*)&keyX[0] = (u32)DSi::ConsoleID; + *(u32*)&keyX[4] = (u32)DSi::ConsoleID ^ 0x24EE6906; + *(u32*)&keyX[8] = (u32)(DSi::ConsoleID >> 32) ^ 0xE65B601D; + *(u32*)&keyX[12] = (u32)(DSi::ConsoleID >> 32); + + u8 keyY[16]; + *(u32*)&keyY[0] = 0x0AB9DC76; + *(u32*)&keyY[4] = 0xBD4DC4D3; + *(u32*)&keyY[8] = 0x202DDD1D; + *(u32*)&keyY[12] = 0xE1A00005; + + DSi_AES::DeriveNormalKey(keyX, keyY, tmp); + DSi_AES::Swap16(FATKey, tmp); +} + +void SetupFATCrypto(AES_ctx* ctx, u32 ctr) +{ + u8 iv[16]; + memcpy(iv, FATIV, 16); + + u32 res; + res = iv[15] + (ctr & 0xFF); + iv[15] = (res & 0xFF); + res = iv[14] + ((ctr >> 8) & 0xFF) + (res >> 8); + iv[14] = (res & 0xFF); + res = iv[13] + ((ctr >> 16) & 0xFF) + (res >> 8); + iv[13] = (res & 0xFF); + res = iv[12] + (ctr >> 24) + (res >> 8); + iv[12] = (res & 0xFF); + iv[11] += (res >> 8); + + AES_init_ctx_iv(ctx, FATKey, iv); +} + +u32 ReadFATBlock(u64 addr, u32 len, u8* buf) +{ + u32 ctr = (u32)(addr >> 4); + + AES_ctx ctx; + SetupFATCrypto(&ctx, ctr); + + fseek(DSi::SDMMCFile, addr, SEEK_SET); + u32 res = fread(buf, len, 1, DSi::SDMMCFile); + if (!res) return 0; + + for (u32 i = 0; i < len; i += 16) + { + //printf("BLOCK %d: IV=", i); + //for (int k = 0; k < 16; k++) printf("%02X:", ctx.Iv[k]); + //printf("\n"); + + u8 tmp[16]; + DSi_AES::Swap16(tmp, &buf[i]); + AES_CTR_xcrypt_buffer(&ctx, tmp, 16); + DSi_AES::Swap16(&buf[i], tmp); + } + + return len; +} + + +UINT FF_ReadNAND(BYTE* buf, LBA_t sector, UINT num) +{ + printf("READ %08X %08X\n", sector, num); + + // TODO: allow selecting other partitions? + u64 baseaddr = 0x10EE00; + + u64 blockaddr = baseaddr + (sector * 0x200ULL); + + u32 res = ReadFATBlock(blockaddr, num*0x200, buf); + return res >> 9; +} + +UINT FF_WriteNAND(BYTE* buf, LBA_t sector, UINT num) +{ + // TODO! + printf("!! WRITE %08X %08X\n", sector, num); + return 0; +} + + +void PatchTSC() +{ + // TEST ZONE + + u8 dorp[0x200]; + ReadFATBlock(0, 0x200, dorp); + + for (int i = 0; i < 0x200; i+=16) + { + for (int j = 0; j < 16; j++) + { + printf("%02X ", dorp[i+j]); + } + printf("\n"); + } + + ReadFATBlock(0x0010EE00, 0x200, dorp); + printf("FUKA\n"); + for (int i = 0; i < 0x200; i+=16) + { + for (int j = 0; j < 16; j++) + { + printf("%02X ", dorp[i+j]); + } + printf("\n"); + } + + ff_disk_open(FF_ReadNAND, FF_WriteNAND); + + FRESULT res; + FATFS fs; + res = f_mount(&fs, "0:", 0); + printf("mount=%d\n", res); + + FIL file; + res = f_open(&file, "0:/shared1/TWLCFG0.dat", FA_READ); + printf("blarg=%d\n", res); +} + +} diff --git a/src/DSi_NAND.h b/src/DSi_NAND.h new file mode 100644 index 00000000..41d40b8b --- /dev/null +++ b/src/DSi_NAND.h @@ -0,0 +1,33 @@ +/* + Copyright 2016-2021 Arisotura + + This file is part of melonDS. + + melonDS is free software: you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation, either version 3 of the License, or (at your option) + any later version. + + melonDS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with melonDS. If not, see http://www.gnu.org/licenses/. +*/ + +#ifndef DSI_NAND_H +#define DSI_NAND_H + +#include "types.h" + +namespace DSi_NAND +{ + +void Init(); + +void PatchTSC(); + +} + +#endif // DSI_NAND_H diff --git a/src/SPI.cpp b/src/SPI.cpp index 0a45c2f4..cbdbfe68 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -167,7 +167,6 @@ void Reset() UserSettings = userdata; - // TODO evetually: do this in DSi mode if (NDS::ConsoleType == 0) { // fix touchscreen coords diff --git a/src/fatfs/diskio.c b/src/fatfs/diskio.c index 179e387a..6ce9db2a 100644 --- a/src/fatfs/diskio.c +++ b/src/fatfs/diskio.c @@ -10,10 +10,32 @@ #include "ff.h" /* Obtains integer types */ #include "diskio.h" /* Declarations of disk functions */ -/* Definitions of physical drive number for each drive */ -#define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */ -#define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */ -#define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */ + +static ff_disk_read_cb ReadCb; +static ff_disk_write_cb WriteCb; +static DSTATUS Status = STA_NOINIT | STA_NODISK; + + +void ff_disk_open(ff_disk_read_cb readcb, ff_disk_write_cb writecb) +{ + if (!readcb) return; + + ReadCb = readcb; + WriteCb = writecb; + + Status &= ~STA_NODISK; + if (!writecb) Status |= STA_PROTECT; + else Status &= ~STA_PROTECT; +} + +void ff_disk_close() +{ + ReadCb = NULL; + WriteCb = NULL; + + Status &= ~STA_PROTECT; + Status |= STA_NODISK; +} /*-----------------------------------------------------------------------*/ @@ -24,32 +46,7 @@ DSTATUS disk_status ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { - DSTATUS stat; - int result; - - switch (pdrv) { - case DEV_RAM : - result = RAM_disk_status(); - - // translate the reslut code here - - return stat; - - case DEV_MMC : - result = MMC_disk_status(); - - // translate the reslut code here - - return stat; - - case DEV_USB : - result = USB_disk_status(); - - // translate the reslut code here - - return stat; - } - return STA_NOINIT; + return Status; } @@ -62,32 +59,8 @@ DSTATUS disk_initialize ( BYTE pdrv /* Physical drive nmuber to identify the drive */ ) { - DSTATUS stat; - int result; - - switch (pdrv) { - case DEV_RAM : - result = RAM_disk_initialize(); - - // translate the reslut code here - - return stat; - - case DEV_MMC : - result = MMC_disk_initialize(); - - // translate the reslut code here - - return stat; - - case DEV_USB : - result = USB_disk_initialize(); - - // translate the reslut code here - - return stat; - } - return STA_NOINIT; + Status &= ~STA_NOINIT; + return Status; } @@ -103,39 +76,12 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - DRESULT res; - int result; + if (Status & (STA_NOINIT | STA_NODISK)) return RES_NOTRDY; + if (!ReadCb) return RES_ERROR; - switch (pdrv) { - case DEV_RAM : - // translate the arguments here - - result = RAM_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - - case DEV_MMC : - // translate the arguments here - - result = MMC_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - - case DEV_USB : - // translate the arguments here - - result = USB_disk_read(buff, sector, count); - - // translate the reslut code here - - return res; - } - - return RES_PARERR; + UINT res = ReadCb(buff, sector, count); + if (res != count) return RES_ERROR; + return RES_OK; } @@ -153,39 +99,13 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - DRESULT res; - int result; + if (Status & (STA_NOINIT | STA_NODISK)) return RES_NOTRDY; + if (Status & STA_PROTECT) return RES_WRPRT; + if (!WriteCb) return RES_ERROR; - switch (pdrv) { - case DEV_RAM : - // translate the arguments here - - result = RAM_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - - case DEV_MMC : - // translate the arguments here - - result = MMC_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - - case DEV_USB : - // translate the arguments here - - result = USB_disk_write(buff, sector, count); - - // translate the reslut code here - - return res; - } - - return RES_PARERR; + UINT res = WriteCb(buff, sector, count); + if (res != count) return RES_ERROR; + return RES_OK; } #endif @@ -201,29 +121,7 @@ DRESULT disk_ioctl ( void *buff /* Buffer to send/receive control data */ ) { - DRESULT res; - int result; - - switch (pdrv) { - case DEV_RAM : - - // Process of the command for the RAM drive - - return res; - - case DEV_MMC : - - // Process of the command for the MMC/SD card - - return res; - - case DEV_USB : - - // Process of the command the USB drive - - return res; - } - + printf("disk_ioctl(%02X, %02X, %p)\n", pdrv, cmd, buff); return RES_PARERR; } diff --git a/src/fatfs/ff.h b/src/fatfs/ff.h index 48665763..6df78a8e 100644 --- a/src/fatfs/ff.h +++ b/src/fatfs/ff.h @@ -415,6 +415,15 @@ int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ #define AM_ARC 0x20 /* Archive */ +// extra additions for interfacing with melonDS + +typedef UINT (*ff_disk_read_cb)(BYTE* buff, LBA_t sector, UINT count); +typedef UINT (*ff_disk_write_cb)(BYTE* buff, LBA_t sector, UINT count); + +void ff_disk_open(ff_disk_read_cb readcb, ff_disk_write_cb writecb); +void ff_disk_close(); + + #ifdef __cplusplus } #endif diff --git a/src/fatfs/ffconf.h b/src/fatfs/ffconf.h index ca17485e..ee20d0fe 100644 --- a/src/fatfs/ffconf.h +++ b/src/fatfs/ffconf.h @@ -171,7 +171,7 @@ #define FF_STR_VOLUME_ID 0 -#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +#define FF_VOLUME_STRS "fat" /* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. / When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive / number in the path name. FF_VOLUME_STRS defines the volume ID strings for each diff --git a/src/fatfs/ffsystem.c b/src/fatfs/ffsystem.c index b88ce155..b0409efa 100644 --- a/src/fatfs/ffsystem.c +++ b/src/fatfs/ffsystem.c @@ -3,6 +3,8 @@ /* (C)ChaN, 2018 */ /*------------------------------------------------------------------------*/ +#define _POSIX_THREAD_SAFE_FUNCTIONS +#include #include "ff.h" @@ -54,27 +56,6 @@ int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object FF_SYNC_t* sobj /* Pointer to return the created sync object */ ) { - /* Win32 */ - *sobj = CreateMutex(NULL, FALSE, NULL); - return (int)(*sobj != INVALID_HANDLE_VALUE); - - /* uITRON */ -// T_CSEM csem = {TA_TPRI,1,1}; -// *sobj = acre_sem(&csem); -// return (int)(*sobj > 0); - - /* uC/OS-II */ -// OS_ERR err; -// *sobj = OSMutexCreate(0, &err); -// return (int)(err == OS_NO_ERR); - - /* FreeRTOS */ -// *sobj = xSemaphoreCreateMutex(); -// return (int)(*sobj != NULL); - - /* CMSIS-RTOS */ -// *sobj = osMutexCreate(&Mutex[vol]); -// return (int)(*sobj != NULL); } @@ -90,23 +71,6 @@ int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ ) { - /* Win32 */ - return (int)CloseHandle(sobj); - - /* uITRON */ -// return (int)(del_sem(sobj) == E_OK); - - /* uC/OS-II */ -// OS_ERR err; -// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); -// return (int)(err == OS_NO_ERR); - - /* FreeRTOS */ -// vSemaphoreDelete(sobj); -// return 1; - - /* CMSIS-RTOS */ -// return (int)(osMutexDelete(sobj) == osOK); } @@ -121,22 +85,6 @@ int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a gran FF_SYNC_t sobj /* Sync object to wait */ ) { - /* Win32 */ - return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); - - /* uITRON */ -// return (int)(wai_sem(sobj) == E_OK); - - /* uC/OS-II */ -// OS_ERR err; -// OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); -// return (int)(err == OS_NO_ERR); - - /* FreeRTOS */ -// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); - - /* CMSIS-RTOS */ -// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); } @@ -150,21 +98,27 @@ void ff_rel_grant ( FF_SYNC_t sobj /* Sync object to be signaled */ ) { - /* Win32 */ - ReleaseMutex(sobj); - - /* uITRON */ -// sig_sem(sobj); - - /* uC/OS-II */ -// OSMutexPost(sobj); - - /* FreeRTOS */ -// xSemaphoreGive(sobj); - - /* CMSIS-RTOS */ -// osMutexRelease(sobj); } #endif + +DWORD get_fattime() +{ + // TODO: return melonDS time instead of RTC?? + + time_t timestamp = time(NULL); + struct tm timedata; + localtime_r(×tamp, &timedata); + + DWORD ret; + ret = (timedata.tm_sec >> 1); + ret |= (timedata.tm_min << 5); + ret |= (timedata.tm_hour << 11); + ret |= (timedata.tm_mday << 16); + ret |= ((timedata.tm_mon + 1) << 21); + ret |= ((timedata.tm_year - 80) << 25); + + return ret; +} +