From 0d2e59c909de1493207225c21161e1d53d708b52 Mon Sep 17 00:00:00 2001 From: Normmatt Date: Mon, 15 Jun 2015 09:19:44 +1200 Subject: [PATCH] Add support for dumping Development Carts. Fix whitespace. --- source/gamecart/command_ctr.c | 29 +++++++------ source/gamecart/protocol.c | 80 +++++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 39 deletions(-) diff --git a/source/gamecart/command_ctr.c b/source/gamecart/command_ctr.c index 9615253..bee1eb8 100644 --- a/source/gamecart/command_ctr.c +++ b/source/gamecart/command_ctr.c @@ -2,47 +2,50 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "draw.h" #include "command_ctr.h" #include "protocol_ctr.h" -void CTR_CmdReadSectorSD(u8* aBuffer, u32 aSector) +static int read_count = 0; + +void CTR_CmdC5() { - u64 adr = ((u64)0xBF << 56) | (aSector * 0x200); - const u32 readheader_cmd[4] = { - (u32)(adr >> 32), - (u32)(adr & 0xFFFFFFFF), - 0x00000000, 0x00000000 - }; - CTR_SendCommand(readheader_cmd, 0x200, 1, 0x100802C, aBuffer); + static const u32 c5_cmd[4] = { 0xC5000000, 0x00000000, 0x00000000, 0x00000000 }; + CTR_SendCommand(c5_cmd, 0, 1, 0x100002C, NULL); } void CTR_CmdReadData(u32 sector, u32 length, u32 blocks, void* buffer) { + if(read_count++ > 10000) + { + CTR_CmdC5(); + } + const u32 read_cmd[4] = { (0xBF000000 | (u32)(sector >> 23)), (u32)((sector << 9) & 0xFFFFFFFF), 0x00000000, 0x00000000 }; - CTR_SendCommand(read_cmd, length, blocks, 0x100822C, buffer); + CTR_SendCommand(read_cmd, length, blocks, 0x704822C, buffer); } void CTR_CmdReadHeader(void* buffer) { static const u32 readheader_cmd[4] = { 0x82000000, 0x00000000, 0x00000000, 0x00000000 }; - CTR_SendCommand(readheader_cmd, 0x200, 1, 0x4802C, buffer); + CTR_SendCommand(readheader_cmd, 0x200, 1, 0x704802C, buffer); } u32 CTR_CmdGetSecureId(u32 rand1, u32 rand2) { u32 id = 0; const u32 getid_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(getid_cmd, 0x4, 1, 0x100802C, &id); + CTR_SendCommand(getid_cmd, 0x4, 1, 0x701002C, &id); return id; } void CTR_CmdSeed(u32 rand1, u32 rand2) { - const u32 seed_cmd[4] = { 0x83000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(seed_cmd, 0, 1, 0x100822C, NULL); + const u32 seed_cmd[4] = { 0x83000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(seed_cmd, 0, 1, 0x700822C, NULL); } diff --git a/source/gamecart/protocol.c b/source/gamecart/protocol.c index d946cc5..86b1147 100644 --- a/source/gamecart/protocol.c +++ b/source/gamecart/protocol.c @@ -8,6 +8,7 @@ #include #include +#include "draw.h" #include "common.h" #include "aes.h" #include "protocol_ctr.h" @@ -111,29 +112,59 @@ void Cart_Init(void) } } +static void AES_SetKeyControl(u32 a) { + REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | a | 0x80; +} + //returns 1 if MAC valid otherwise 0 static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignored u8 tmp = REG_AESKEYCNT; + REG_AESCNT = 0x10C00; //flush r/w fifo macsize = 001 + + (*(vu8*)0x10000008) |= 0x0C; //??? + REG_AESCNT |= 0x2800000; - REG_AESCTR[0] = buff[14]; - REG_AESCTR[1] = buff[13]; - REG_AESCTR[2] = buff[12]; - REG_AESCNT |= 0x2800000; - REG_AESKEYCNT = (REG_AESKEYCNT & 0xC0) | 0x3B; - REG_AESKEYYFIFO = buff[0]; - REG_AESKEYYFIFO = buff[1]; - REG_AESKEYYFIFO = buff[2]; - REG_AESKEYYFIFO = buff[3]; - REG_AESKEYCNT = tmp; - REG_AESKEYSEL = 0x3B; - REG_AESCNT |= 0x4000000; + + //const u8 is_dev_unit = *(vu8*)0x10010010; + //if(is_dev_unit) //Dev unit + const u8 is_dev_cart = (A0_Response&3)==3; + if(is_dev_cart) //Dev unit + { + AES_SetKeyControl(0x11); + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYFIFO = 0; + REG_AESKEYSEL = 0x11; + } + else + { + AES_SetKeyControl(0x3B); + REG_AESKEYYFIFO = buff[0]; + REG_AESKEYYFIFO = buff[1]; + REG_AESKEYYFIFO = buff[2]; + REG_AESKEYYFIFO = buff[3]; + REG_AESKEYSEL = 0x3B; + } + + REG_AESCNT = 0x4000000; + REG_AESCNT &= 0xFFF7FFFF; REG_AESCNT |= 0x2970000; REG_AESMAC[0] = buff[11]; REG_AESMAC[1] = buff[10]; REG_AESMAC[2] = buff[9]; REG_AESMAC[3] = buff[8]; + REG_AESCNT |= 0x2800000; + REG_AESCTR[0] = buff[14]; + REG_AESCTR[1] = buff[13]; + REG_AESCTR[2] = buff[12]; REG_AESBLKCNT = 0x10000; - REG_AESCNT = 0x83D70C00; + + u32 v11 = ((REG_AESCNT | 0x80000000) & 0xC7FFFFFF); //Start and clear mode (ccm decrypt) + u32 v12 = v11 & 0xBFFFFFFF; //Disable Interrupt + REG_AESCNT = ((((v12 | 0x3000) & 0xFD7F3FFF) | (5 << 23)) & 0xFEBFFFFF) | (5 << 22); + + //REG_AESCNT = 0x83D73C00; REG_AESWRFIFO = buff[4]; REG_AESWRFIFO = buff[5]; REG_AESWRFIFO = buff[6]; @@ -146,14 +177,8 @@ static u8 card_aes(u32 *out, u32 *buff, size_t size) { // note size param ignore return ((REG_AESCNT >> 21) & 1); } -static void AES_SetKeyControl(u32 a) { - *((volatile u8*)0x10009011) = a | 0x80; -} - void Cart_Secure_Init(u32 *buf, u32 *out) { - AES_SetKeyControl(0x3B); - u8 mac_valid = card_aes(out, buf, 0x200); // if (!mac_valid) @@ -175,17 +200,20 @@ void Cart_Secure_Init(u32 *buf, u32 *out) u32 test = 0; const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); u32 test2 = 0; const u32 A3_cmd[4] = { 0xA3000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A3_cmd, 4, 1, 0x100822C, &test2); - - const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(C5_cmd, 0, 1, 0x100822C, NULL); + CTR_SendCommand(A3_cmd, 4, 1, 0x701002C, &test2); + + if(test==CartID && test2==A0_Response) + { + const u32 C5_cmd[4] = { 0xC5000000, 0x00000000, rand1, rand2 }; + CTR_SendCommand(C5_cmd, 0, 1, 0x100002C, NULL); + } for (int i = 0; i < 5; ++i) { - CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); ioDelay(0xF0000); } } @@ -194,5 +222,5 @@ void Cart_Dummy(void) { // Sends a dummy command to skip encrypted responses some problematic carts send. u32 test; const u32 A2_cmd[4] = { 0xA2000000, 0x00000000, rand1, rand2 }; - CTR_SendCommand(A2_cmd, 4, 1, 0x100822C, &test); + CTR_SendCommand(A2_cmd, 4, 1, 0x701002C, &test); }