Got rid of sysnand mode, add key gen code, new splash screen, autoboot, update fatfs, removed ninjhax/mset folder for CakeBrah/CakeHax, lots of minor changes.
This commit is contained in:
119
source/crypto.c
119
source/crypto.c
@@ -357,113 +357,42 @@ int rsa_verify(const void* data, u32 size, const void* sig, u32 mode)
|
||||
* Nand/FIRM Crypto stuff
|
||||
****************************************************************/
|
||||
|
||||
//Get Nand CTR key
|
||||
void getNandCTR(u8 *buf) {
|
||||
u8 *addr = (u8*)0x080D8BBC;
|
||||
u8 keyLen = 0x10; //CTR length
|
||||
addr += 0x0F;
|
||||
while (keyLen --) { *(buf++) = *(addr--); }
|
||||
}
|
||||
|
||||
//Read firm0 from NAND and write to buffer
|
||||
void nandFirm0(u8 *outbuf, const u32 size){
|
||||
u8 CTR[0x10];
|
||||
getNandCTR(CTR);
|
||||
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
sdmmc_nand_readsectors(0x0B130000 / 0x200, size / 0x200, outbuf);
|
||||
aes_use_keyslot(0x06);
|
||||
aes(outbuf, outbuf, size / AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
}
|
||||
|
||||
//Emulates the Arm9loader process
|
||||
//9.5.0 = 0x0F
|
||||
//9.6.0 = 0x18
|
||||
void arm9loader(void *armHdr, u32 kversion){
|
||||
void arm9loader(void *armHdr){
|
||||
//Set Nand key#2 here (decrypted from 0x12C10)
|
||||
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
||||
|
||||
u8 keyX[0x10];
|
||||
u8 keyY[0x10];
|
||||
u8 CTR[0x10];
|
||||
u32 slot = (kversion >= 0x0F ? 0x16 : 0x15);
|
||||
u32 slot = 0x16;
|
||||
|
||||
//Setupkeys needed for arm9bin decryption
|
||||
memcpy(keyY, armHdr+0x10, 0x10);
|
||||
memcpy(CTR, armHdr+0x20, 0x10);
|
||||
u32 size = atoi(armHdr+0x30);
|
||||
memcpy((u8*)keyY, (void *)((uintptr_t)armHdr+0x10), 0x10);
|
||||
memcpy((u8*)CTR, (void *)((uintptr_t)armHdr+0x20), 0x10);
|
||||
u32 size = atoi((void *)((uintptr_t)armHdr+0x30));
|
||||
|
||||
if(kversion >= 0x0F){
|
||||
if(kversion >= 0x18) aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(0x11);
|
||||
aes(keyX, armHdr+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
}
|
||||
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(0x11);
|
||||
|
||||
aes_setkey(slot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setiv(CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
//Set 0x16 keyX, keyY and CTR
|
||||
aes((u8*)keyX, (void *)((uintptr_t)armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
aes_setkey(slot, (u8*)keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(slot, (u8*)keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setiv((u8*)CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(slot);
|
||||
|
||||
aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
}
|
||||
|
||||
void setKeys(kversion){
|
||||
u8 key2[0x10] = {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0};
|
||||
//Initialze keys
|
||||
if(kversion >= 0x18){
|
||||
|
||||
u8 keyX18[16] = {0x82, 0xE9, 0xC9, 0xBE, 0xBF, 0xB8, 0xBD, 0xB8, 0x75, 0xEC, 0xC0, 0xA0, 0x7D, 0x47, 0x43, 0x74};
|
||||
u8 keyX19[16] = {0xF5, 0x36, 0x7F, 0xCE, 0x73, 0x14, 0x2E, 0x66, 0xED, 0x13, 0x91, 0x79, 0x14, 0xB7, 0xF2, 0xEF};
|
||||
u8 keyX1A[16] = {0xEA, 0xBA, 0x98, 0x4C, 0x9C, 0xB7, 0x66, 0xD4, 0xA3, 0xA7, 0xE9, 0x74, 0xE2, 0xE7, 0x13, 0xA3};
|
||||
u8 keyX1B[16] = {0x45, 0xAD, 0x04, 0x95, 0x39, 0x92, 0xC7, 0xC8, 0x93, 0x72, 0x4A, 0x9A, 0x7B, 0xCE, 0x61, 0x82};
|
||||
u8 keyX1C[16] = {0xC3, 0x83, 0x0F, 0x81, 0x56, 0xE3, 0x54, 0x3B, 0x72, 0x3F, 0x0B, 0xC0, 0x46, 0x74, 0x1E, 0x8F};
|
||||
u8 keyX1D[16] = {0xD6, 0xB3, 0x8B, 0xC7, 0x59, 0x41, 0x75, 0x96, 0xD6, 0x19, 0xD6, 0x02, 0x9D, 0x13, 0xE0, 0xD8};
|
||||
u8 keyX1E[16] = {0xBB, 0x62, 0x3A, 0x97, 0xDD, 0xD7, 0x93, 0xD7, 0x57, 0xC4, 0x10, 0x4B, 0x8D, 0x9F, 0xB9, 0x69};
|
||||
u8 keyX1F[16] = {0x4C, 0x28, 0xEC, 0x6E, 0xFF, 0xA3, 0xC2, 0x36, 0x46, 0x07, 0x8B, 0xBA, 0x35, 0x0C, 0x79, 0x95};
|
||||
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x19, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1A, keyX19, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1B, keyX1B, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1C, keyX1C, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1D, keyX1D, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1E, keyX1E, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1F, keyX1F, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
/*
|
||||
//data at armHdr+0x8A804 (its not in FCRAM for whatever reason)
|
||||
u8 encryptedData1[0x10] = {
|
||||
0xA4, 0x8D, 0xE4, 0xF1, 0x0B, 0x36, 0x44, 0xAA, 0x90, 0x31, 0x28, 0xFF,
|
||||
0x4D, 0xCA, 0x76, 0xDF
|
||||
};
|
||||
//data at armHdr+0x8A814 (its not in FCRAM for whatever reason)
|
||||
u8 encryptedData2[0x10] = {
|
||||
0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D,
|
||||
0x9D, 0x2A, 0x21, 0x98
|
||||
};
|
||||
|
||||
//Set key 0x18 keyX
|
||||
u8 keyX18[0x10];
|
||||
aes(keyX18, encryptedData1, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
aes_setkey(0x18, keyX18, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
//Set key 0x11 normalkey
|
||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_use_keyslot(0x11);
|
||||
|
||||
//Set keys 0x19..0x1F keyXs
|
||||
u8 keyTemp[0x10];
|
||||
u8 keys[7][0x10];
|
||||
aes_use_keyslot(0x11);
|
||||
int i; for(i = 0; i < 7; i++) {
|
||||
aes(keyTemp, encryptedData2, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
encryptedData2[0x0F]++;
|
||||
memcpy(keys[i], keyTemp, 0x10);
|
||||
}
|
||||
aes_setkey(0x19, keys[0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1A, keys[1], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1B, keys[2], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1C, keys[3], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1D, keys[4], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1E, keys[5], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes_setkey(0x1F, keys[6], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);*/
|
||||
//Decrypt arm9bin
|
||||
aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
|
||||
//Set keys 0x19..0x1F keyXs
|
||||
u8* decKey = (void *)((uintptr_t)armHdr+0x8A824);
|
||||
aes_use_keyslot(0x11);
|
||||
for(slot = 0x19; slot < 0x20; slot++) {
|
||||
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
aes(decKey, (void *)((uintptr_t)armHdr+0x8A814), 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||
aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
*(u8 *)((void *)((uintptr_t)armHdr+0x8A814+0xF)) += 1;
|
||||
}
|
||||
}
|
||||
@@ -131,9 +131,6 @@ void rsa_use_keyslot(u32 keyslot);
|
||||
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
|
||||
|
||||
//NAND/FIRM stuff
|
||||
void getNandCTR(u8 *buf);
|
||||
void nandFirm0(u8 *outbuf, const u32 size);
|
||||
void arm9loader(void *armHdr, u32 kversion);
|
||||
void setKeys(kversion);
|
||||
void arm9loader(void *armHdr);
|
||||
|
||||
#endif /*__CRYPTO_H*/
|
||||
|
||||
@@ -17,4 +17,5 @@ void clearScreen(void){
|
||||
void loadSplash(void){
|
||||
clearScreen();
|
||||
fileRead(fb->top_left, "/rei/splash.bin", 0x46500);
|
||||
unsigned i,t; for(t=120;t>0;t--){for(i=0xFFFF;i>0;i--);}; //Ghetto sleep func
|
||||
}
|
||||
@@ -16,11 +16,11 @@
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
DSTATUS disk_status (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
__attribute__((unused))
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
return RES_OK;
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,10 @@ DSTATUS disk_status (
|
||||
|
||||
DSTATUS disk_initialize (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||
)
|
||||
{
|
||||
sdmmc_sdcard_init();
|
||||
sdmmc_sdcard_init();
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
@@ -46,15 +46,15 @@ DSTATUS disk_initialize (
|
||||
|
||||
DRESULT disk_read (
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
BYTE *buff, /* Data buffer to store read data */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to read */
|
||||
)
|
||||
{
|
||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
@@ -67,33 +67,34 @@ DRESULT disk_read (
|
||||
|
||||
#if _USE_WRITE
|
||||
DRESULT disk_write (
|
||||
__attribute__((unused))
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||
const BYTE *buff, /* Data to be written */
|
||||
DWORD sector, /* Sector address in LBA */
|
||||
UINT count /* Number of sectors to write */
|
||||
)
|
||||
{
|
||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Miscellaneous Functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
#if _USE_IOCTL
|
||||
DRESULT disk_ioctl (
|
||||
__attribute__((unused))
|
||||
__attribute__((unused))
|
||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||
__attribute__((unused))
|
||||
__attribute__((unused))
|
||||
BYTE cmd, /* Control code */
|
||||
__attribute__((unused))
|
||||
__attribute__((unused))
|
||||
void *buff /* Buffer to send/receive control data */
|
||||
)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/ and optional writing functions as well. */
|
||||
|
||||
|
||||
#define _FS_MINIMIZE 1
|
||||
#define _FS_MINIMIZE 0
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: All basic functions are enabled.
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
.arm
|
||||
.global ioDelay
|
||||
.type ioDelay STT_FUNC
|
||||
.global waitcycles
|
||||
.type waitcycles STT_FUNC
|
||||
|
||||
@ioDelay ( u32 us )
|
||||
ioDelay:
|
||||
ldr r1, =0x18000000 @ VRAM
|
||||
1:
|
||||
@ Loop doing uncached reads from VRAM to make loop timing more reliable
|
||||
ldr r2, [r1]
|
||||
subs r0, #1
|
||||
bgt 1b
|
||||
bx lr
|
||||
@waitcycles ( u32 us )
|
||||
waitcycles:
|
||||
PUSH {R0-R2,LR}
|
||||
STR R0, [SP,#4]
|
||||
waitcycles_loop:
|
||||
LDR R3, [SP,#4]
|
||||
SUBS R2, R3, #1
|
||||
STR R2, [SP,#4]
|
||||
CMP R3, #0
|
||||
BNE waitcycles_loop
|
||||
POP {R0-R2,PC}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,52 @@
|
||||
// Copyright 2014 Normmatt
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
#ifndef __SDMMC_H__
|
||||
#define __SDMMC_H__
|
||||
|
||||
#pragma once
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#include "common.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SDMMC_BASE 0x10006000u
|
||||
#define SDMMC_BASE 0x10006000
|
||||
|
||||
#define REG_SDCMD 0x00
|
||||
#define REG_SDPORTSEL 0x02
|
||||
#define REG_SDCMDARG 0x04
|
||||
#define REG_SDCMDARG0 0x04
|
||||
#define REG_SDCMDARG1 0x06
|
||||
#define REG_SDSTOP 0x08
|
||||
#define REG_SDBLKCOUNT 0x0a
|
||||
#define REG_SDCMD 0x00
|
||||
#define REG_SDPORTSEL 0x02
|
||||
#define REG_SDCMDARG 0x04
|
||||
#define REG_SDCMDARG0 0x04
|
||||
#define REG_SDCMDARG1 0x06
|
||||
#define REG_SDSTOP 0x08
|
||||
#define REG_SDBLKCOUNT 0x0a
|
||||
|
||||
#define REG_SDRESP0 0x0c
|
||||
#define REG_SDRESP1 0x0e
|
||||
#define REG_SDRESP2 0x10
|
||||
#define REG_SDRESP3 0x12
|
||||
#define REG_SDRESP4 0x14
|
||||
#define REG_SDRESP5 0x16
|
||||
#define REG_SDRESP6 0x18
|
||||
#define REG_SDRESP7 0x1a
|
||||
#define REG_SDRESP0 0x0c
|
||||
#define REG_SDRESP1 0x0e
|
||||
#define REG_SDRESP2 0x10
|
||||
#define REG_SDRESP3 0x12
|
||||
#define REG_SDRESP4 0x14
|
||||
#define REG_SDRESP5 0x16
|
||||
#define REG_SDRESP6 0x18
|
||||
#define REG_SDRESP7 0x1a
|
||||
|
||||
#define REG_SDSTATUS0 0x1c
|
||||
#define REG_SDSTATUS1 0x1e
|
||||
#define REG_SDSTATUS0 0x1c
|
||||
#define REG_SDSTATUS1 0x1e
|
||||
|
||||
#define REG_SDIRMASK0 0x20
|
||||
#define REG_SDIRMASK1 0x22
|
||||
#define REG_SDCLKCTL 0x24
|
||||
#define REG_SDIRMASK0 0x20
|
||||
#define REG_SDIRMASK1 0x22
|
||||
#define REG_SDCLKCTL 0x24
|
||||
|
||||
#define REG_SDBLKLEN 0x26
|
||||
#define REG_SDOPT 0x28
|
||||
#define REG_SDFIFO 0x30
|
||||
|
||||
#define REG_SDBLKLEN 0x26
|
||||
#define REG_SDOPT 0x28
|
||||
#define REG_SDFIFO 0x30
|
||||
#define REG_DATACTL 0xd8
|
||||
#define REG_SDRESET 0xe0
|
||||
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||
|
||||
#define REG_SDDATACTL 0xd8
|
||||
#define REG_SDRESET 0xe0
|
||||
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||
#define REG_DATACTL32 0x100
|
||||
#define REG_SDBLKLEN32 0x104
|
||||
#define REG_SDBLKCOUNT32 0x108
|
||||
#define REG_SDFIFO32 0x10C
|
||||
|
||||
#define REG_SDDATACTL32 0x100
|
||||
#define REG_SDBLKLEN32 0x104
|
||||
#define REG_SDBLKCOUNT32 0x108
|
||||
#define REG_SDFIFO32 0x10C
|
||||
|
||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||
#define REG_RESET_SDIO 0x1e0
|
||||
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||
#define REG_RESET_SDIO 0x1e0
|
||||
|
||||
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||
#define TMIO_STAT0_DATAEND 0x0004
|
||||
@@ -97,75 +97,88 @@
|
||||
#define TMIO_MASK_ALL 0x837f031d
|
||||
|
||||
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
||||
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||
|
||||
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
||||
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
||||
|
||||
typedef struct mmcdevice {
|
||||
u8* data;
|
||||
u32 size;
|
||||
u32 error;
|
||||
u16 stat0;
|
||||
u16 stat1;
|
||||
u32 ret[4];
|
||||
u32 initarg;
|
||||
u32 isSDHC;
|
||||
u32 clk;
|
||||
u32 SDOPT;
|
||||
u32 devicenumber;
|
||||
u32 total_size; //size in sectors of the device
|
||||
u32 res;
|
||||
} mmcdevice;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*int sdmmc_sdcard_init();
|
||||
void sdmmc_sdcard_readsector(uint32_t sector_no, void *out);
|
||||
void sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, void *out);
|
||||
void sdmmc_sdcard_writesector(uint32_t sector_no, void *in);
|
||||
void sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, void *in);
|
||||
void sdmmc_blktransferinit();*/
|
||||
typedef struct mmcdevice {
|
||||
uint8_t* data;
|
||||
uint32_t size;
|
||||
uint32_t error;
|
||||
uint16_t stat0;
|
||||
uint16_t stat1;
|
||||
uint32_t ret[4];
|
||||
uint32_t initarg;
|
||||
uint32_t isSDHC;
|
||||
uint32_t clk;
|
||||
uint32_t SDOPT;
|
||||
uint32_t devicenumber;
|
||||
uint32_t total_size; //size in sectors of the device
|
||||
uint32_t res;
|
||||
} mmcdevice;
|
||||
|
||||
void sdmmc_sdcard_init();
|
||||
int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
|
||||
int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||
int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
|
||||
int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||
|
||||
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||
|
||||
mmcdevice *getMMCDevice(int drive);
|
||||
|
||||
void InitSD();
|
||||
int Nand_Init();
|
||||
int SD_Init();
|
||||
|
||||
void sdmmc_sdcard_init();
|
||||
int sdmmc_sdcard_readsector(u32 sector_no, u8 *out);
|
||||
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
int sdmmc_sdcard_writesector(u32 sector_no, u8 *in);
|
||||
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
|
||||
int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, u8 *in);
|
||||
|
||||
mmcdevice *getMMCDevice(int drive);
|
||||
|
||||
void InitSDMMC();
|
||||
int Nand_Init();
|
||||
int SD_Init();
|
||||
|
||||
static inline u16 sdmmc_read16(u16 reg) {
|
||||
return *(vu16*)(SDMMC_BASE + reg);
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline uint16_t sdmmc_read16(uint16_t reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(volatile uint16_t*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write16(u16 reg, u16 val) {
|
||||
*(vu16*)(SDMMC_BASE + reg) = val;
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(volatile uint16_t*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline u32 sdmmc_read32(u16 reg) {
|
||||
return *(vu32*)(SDMMC_BASE + reg);
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline uint32_t sdmmc_read32(uint16_t reg) {
|
||||
//---------------------------------------------------------------------------------
|
||||
return *(volatile uint32_t*)(SDMMC_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void sdmmc_write32(u16 reg, u32 val) {
|
||||
*(vu32*)(SDMMC_BASE + reg) = val;
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
|
||||
//---------------------------------------------------------------------------------
|
||||
*(volatile uint32_t*)(SDMMC_BASE + reg) = val;
|
||||
}
|
||||
|
||||
static inline void sdmmc_mask16(u16 reg, const u16 clear, const u16 set) {
|
||||
u16 val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
//---------------------------------------------------------------------------------
|
||||
static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
|
||||
//---------------------------------------------------------------------------------
|
||||
uint16_t val = sdmmc_read16(reg);
|
||||
val &= ~clear;
|
||||
val |= set;
|
||||
sdmmc_write16(reg, val);
|
||||
}
|
||||
|
||||
static inline void setckl(u32 data)
|
||||
static inline void setckl(uint32_t data)
|
||||
{
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x100, 0);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF);
|
||||
sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100);
|
||||
sdmmc_mask16(REG_SDCLKCTL,0x100,0);
|
||||
sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
|
||||
sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,66 +11,52 @@
|
||||
#include "emunand.h"
|
||||
#include "crypto.h"
|
||||
|
||||
firmHeader *firmLocation = (firmHeader *)0x24000000;
|
||||
const u32 firmSize = 0xF1000;
|
||||
const firmHeader *firmLocation = (firmHeader *)0x24000000;
|
||||
const u32 firmSize = 0xF3000;
|
||||
firmSectionHeader *section;
|
||||
u32 emuOffset = 0;
|
||||
u32 emuHeader = 0;
|
||||
u32 kversion = 0;
|
||||
|
||||
//Load firm into FCRAM
|
||||
void loadFirm(int mode){
|
||||
//Sysnand mode
|
||||
if(mode == 0 || getEmunand(&emuOffset, &emuHeader) == 0){
|
||||
//Read FIRM from NAND and write to FCRAM
|
||||
nandFirm0((u8*)firmLocation, firmSize);
|
||||
section = firmLocation->section;
|
||||
kversion = 0x04; //TODO: make this not hard coded
|
||||
arm9loader((u8*)firmLocation + section[2].offset, kversion);
|
||||
}
|
||||
//Emunand mode
|
||||
else{
|
||||
//Read FIRM from SD card and write to FCRAM
|
||||
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
|
||||
section = firmLocation->section;
|
||||
kversion = 0x18; //TODO: make this not hard coded
|
||||
arm9loader((u8*)firmLocation + section[2].offset, kversion);
|
||||
loadEmu();
|
||||
}
|
||||
void loadFirm(void){
|
||||
//Read FIRM from SD card and write to FCRAM
|
||||
fileRead((u8*)firmLocation, "/rei/firmware.bin", firmSize);
|
||||
section = firmLocation->section;
|
||||
arm9loader((u8*)firmLocation + section[2].offset);
|
||||
}
|
||||
|
||||
//Nand redirection
|
||||
void loadEmu(void){
|
||||
|
||||
//Read emunand code from SD
|
||||
u32 code = emuCode(kversion);
|
||||
fileRead((u8*)code, "/rei/emunand/emunand.bin", 0);
|
||||
u32 *pos_offset = memsearch((u8*)code, "NAND", 0x218, 4);
|
||||
u32 *pos_header = memsearch((u8*)code, "NCSD", 0x218, 4);
|
||||
memcpy((void *)pos_offset, (void *)emuOffset, 4);
|
||||
memcpy((void *)pos_header, (void *)emuHeader, 4);
|
||||
|
||||
u32 code = emuCode();
|
||||
fileRead(code, "/rei/emunand/emunand.bin", 0);
|
||||
u32 *pos_offset = memsearch(code, "NAND", 0x218, 4);
|
||||
u32 *pos_header = memsearch(code, "NCSD", 0x218, 4);
|
||||
if (pos_offset && pos_header) {
|
||||
*pos_offset = emuOffset;
|
||||
*pos_header = emuHeader;
|
||||
}
|
||||
fileWrite(code, "help.bin", 0x200);
|
||||
//Add emunand hooks
|
||||
memcpy((u8*)emuHook(1, kversion), nandRedir, sizeof(nandRedir));
|
||||
memcpy((u8*)emuHook(2, kversion), nandRedir, sizeof(nandRedir));
|
||||
memcpy((u8*)emuHook(1), nandRedir, sizeof(nandRedir));
|
||||
memcpy((u8*)emuHook(2), nandRedir, sizeof(nandRedir));
|
||||
}
|
||||
|
||||
//Patches
|
||||
void patchFirm(){
|
||||
|
||||
//Part1: Set MPU for payload area
|
||||
memcpy((u8*)mpuCode(kversion), mpu, sizeof(mpu));
|
||||
memcpy((u8*)mpuCode(), mpu, sizeof(mpu));
|
||||
|
||||
//Part2: Disable signature checks
|
||||
memcpy((u8*)sigPatch(1, kversion), sigPat1, sizeof(sigPat1));
|
||||
memcpy((u8*)sigPatch(2, kversion), sigPat2, sizeof(sigPat2));
|
||||
memcpy((u8*)sigPatch(1), sigPat1, sizeof(sigPat1));
|
||||
memcpy((u8*)sigPatch(2), sigPat2, sizeof(sigPat2));
|
||||
|
||||
//Part3: Create arm9 thread
|
||||
fileRead((u8*)threadCode(kversion), "/rei/thread/arm9.bin", 0);
|
||||
if(kversion == 0x18){ //TODO: 0x18 only untill i can figure out why the hell this doesnt work on sysnand anymore.
|
||||
memcpy((u8*)threadHook(1, kversion), th1, sizeof(th1));
|
||||
memcpy((u8*)threadHook(2, kversion), th2, sizeof(th2));
|
||||
}
|
||||
fileRead((u8*)threadCode(), "/rei/thread/arm9.bin", 0);
|
||||
memcpy((u8*)threadHook(1), th1, sizeof(th1));
|
||||
memcpy((u8*)threadHook(2), th2, sizeof(th2));
|
||||
}
|
||||
|
||||
//Firmlaunchhax
|
||||
@@ -108,10 +94,7 @@ void launchFirm(void){
|
||||
memcpy(section[1].address, (u8*)firmLocation + section[1].offset, section[1].size);
|
||||
memcpy(section[2].address, (u8*)firmLocation + section[2].offset, section[2].size);
|
||||
*(u32 *)0x1FFFFFF8 = (u32)firmLocation->arm11Entry;
|
||||
|
||||
setKeys(kversion);
|
||||
|
||||
//Final jump to arm9 binary
|
||||
((void (*)())0x801B01C)();
|
||||
//((void (*)())firmLocation->arm9Entry)();
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "types.h"
|
||||
|
||||
void loadSplash(void);
|
||||
void loadFirm(int mode);
|
||||
void loadFirm(void);
|
||||
void loadEmu(void);
|
||||
void patchFirm(void);
|
||||
void launchFirm(void);
|
||||
|
||||
@@ -10,16 +10,11 @@
|
||||
#include "firm.h"
|
||||
#include "draw.h"
|
||||
|
||||
int mode = 1;
|
||||
|
||||
int main(){
|
||||
mountSD();
|
||||
loadSplash();
|
||||
while(1){
|
||||
if(((~*(unsigned *)0x10146000) & 0xFFF) == (1 << 3)) break;
|
||||
else if(((~*(unsigned *)0x10146000) & 0xFFF) == ((1 << 3) | (1 << 1))) {mode = 0; break;}
|
||||
} //Start = emu; Start+B = sys
|
||||
loadFirm(mode);
|
||||
loadFirm();
|
||||
loadEmu();
|
||||
patchFirm();
|
||||
launchFirm();
|
||||
return 0;
|
||||
|
||||
@@ -5,29 +5,38 @@
|
||||
*/
|
||||
#include "memory.h"
|
||||
|
||||
void memcpy(u8 *dest, u8 *src, u32 size){
|
||||
for (u32 i = 0; i < size; i++) dest[i] = src[i];
|
||||
}
|
||||
|
||||
void memcpy32(u32 *dest, u32 *src, u32 size){
|
||||
for (u32 i = 0; i < size; i++) dest[i] = src[i];
|
||||
}
|
||||
|
||||
void memset(u8 *dest, u32 fill, u32 size){
|
||||
for (u32 i = 0; i < size; i++) dest[i] = fill;
|
||||
void memcpy(void *dest, const void *src, u32 size){
|
||||
char *destc = (char *)dest;
|
||||
const char *srcc = (const char *)src;
|
||||
u32 i; for (i = 0; i < size; i++) {
|
||||
destc[i] = srcc[i];
|
||||
}
|
||||
}
|
||||
|
||||
int memcmp(u8 *buf1, u8 *buf2, u32 size){
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
int cmp = buf1[i] - buf2[i];
|
||||
if (cmp != 0) return cmp;
|
||||
void memset(void *dest, int filler, u32 size){
|
||||
char *destc = (char *)dest;
|
||||
u32 i; for (i = 0; i < size; i++) {
|
||||
destc[i] = filler;
|
||||
}
|
||||
}
|
||||
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size){
|
||||
const char *buf1c = (const char *)buf1;
|
||||
const char *buf2c = (const char *)buf2;
|
||||
u32 i; for (i = 0; i < size; i++) {
|
||||
int cmp = buf1c[i] - buf2c[i];
|
||||
if (cmp) return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search){
|
||||
for (u8 *pos = start_pos; pos <= start_pos + size - size_search; pos++) {
|
||||
if (memcmp(pos, search, size_search) == 0) return (u32*)pos;
|
||||
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search){
|
||||
for (void *pos = start_pos + size - size_search; pos >= start_pos; pos--) {
|
||||
if (memcmp(pos, search, size_search) == 0) return pos;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -8,10 +8,10 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void memcpy(u8 *dest, u8 *src, u32 size);
|
||||
void memcpy(void *dest, const void *src, u32 size);
|
||||
void memcpy32(u32 *dest, u32 *src, u32 size);
|
||||
void memset(u8 *dest, u32 fill, u32 size);
|
||||
int memcmp(u8 *buf1, u8 *buf2, u32 size);
|
||||
u32 *memsearch(u8 *start_pos, u8 *search, u32 size, u32 size_search);
|
||||
void memset(void *dest, int filler, u32 size);
|
||||
int memcmp(const void *buf1, const void *buf2, u32 size);
|
||||
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search);
|
||||
|
||||
#endif
|
||||
128
source/patches.c
128
source/patches.c
@@ -8,9 +8,8 @@
|
||||
|
||||
#define FIRM 0x24000000
|
||||
|
||||
#define KERNEL9 (FIRM + 0x66A00)
|
||||
#define PROC9 (FIRM + 0x7D700)
|
||||
#define v9_6_Offset 0x1600
|
||||
#define KERNEL9 (FIRM + 0x68000)
|
||||
#define PROC9 (FIRM + 0x7ED00)
|
||||
|
||||
#define K9_ADDR 0x08006000
|
||||
#define P9_ADDR 0x08028000
|
||||
@@ -49,124 +48,37 @@ u8 th2[4] = {0xE0, 0xA6, 0x01, 0x08}; //0x0801A6E0
|
||||
**************************************************/
|
||||
|
||||
//Where the emunand code is stored in firm
|
||||
u32 emuCode(u32 kver){
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
case 0x0C:
|
||||
case 0x0F:
|
||||
ret = KERNEL9 + (0x0801A4C0 - K9_ADDR);
|
||||
break;
|
||||
case 0x18:
|
||||
ret = KERNEL9 + v9_6_Offset + (0x0801A4C0 - K9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 emuCode(void){
|
||||
return KERNEL9 + (0x0801A4C0 - K9_ADDR);
|
||||
}
|
||||
|
||||
//Where thread code is stored in firm
|
||||
u32 threadCode(u32 kver){
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
case 0x0C:
|
||||
case 0x0F:
|
||||
ret = KERNEL9 + (0x0801A6E0 - K9_ADDR);
|
||||
case 0x18:
|
||||
ret = KERNEL9 + v9_6_Offset + (0x0801A6E0 - K9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 threadCode(void){
|
||||
return KERNEL9 + (0x0801A6E0 - K9_ADDR);
|
||||
}
|
||||
|
||||
//Area of MPU setting code
|
||||
u32 mpuCode(u32 kver){
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
case 0x0C:
|
||||
case 0x0F:
|
||||
ret = KERNEL9 + (0x0801B3D4 - K9_ADDR);
|
||||
break;
|
||||
case 0x18:
|
||||
ret = KERNEL9 + v9_6_Offset + (0x0801B3D4 - K9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 mpuCode(void){
|
||||
return KERNEL9 + (0x0801B3D4 - K9_ADDR);
|
||||
}
|
||||
|
||||
//Offsets to redirect to thread code
|
||||
u32 threadHook(u8 val, u32 kver){
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
ret = val == 1 ?
|
||||
PROC9 + (0x0808690C - P9_ADDR) :
|
||||
PROC9 + (0x08086940 - P9_ADDR);
|
||||
break;
|
||||
case 0x0C:
|
||||
//TODO: find
|
||||
break;
|
||||
case 0x0F:
|
||||
ret = val == 1 ?
|
||||
PROC9 + (0x080860B0 - P9_ADDR) :
|
||||
PROC9 + (0x080860E4 - P9_ADDR);
|
||||
break;
|
||||
case 0x18:
|
||||
ret = val == 1 ?
|
||||
PROC9 + v9_6_Offset + (0x08086140 - P9_ADDR) :
|
||||
PROC9 + v9_6_Offset + (0x08086174 - P9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 threadHook(u8 val){
|
||||
return val == 1 ?
|
||||
PROC9 + (0x08086140 - P9_ADDR):
|
||||
PROC9 + (0x08086174 - P9_ADDR);
|
||||
}
|
||||
|
||||
//Offsets to redirect to Emunand code
|
||||
u32 emuHook(u8 val, u32 kver){ //latest only
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
//???
|
||||
break;
|
||||
case 0x0C:
|
||||
//???
|
||||
break;
|
||||
case 0x0F:
|
||||
if(val == 1) ret = PROC9 + (0x0807882C - P9_ADDR);
|
||||
else if(val == 2) ret = PROC9 + (0x0807886C - P9_ADDR);
|
||||
break;
|
||||
case 0x18:
|
||||
if(val == 1) ret = PROC9 + v9_6_Offset + (0x0807882C - P9_ADDR);
|
||||
else if(val == 2) ret = PROC9 + v9_6_Offset + (0x0807886C - P9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 emuHook(u8 val){ //latest only
|
||||
return val == 1 ?
|
||||
PROC9 + (0x0807882C - P9_ADDR):
|
||||
PROC9 + (0x0807886C - P9_ADDR);
|
||||
}
|
||||
|
||||
//Offsets to redirect to thread code
|
||||
u32 sigPatch(u8 val, u32 kver){
|
||||
u32 ret = NULL;
|
||||
switch(kver){
|
||||
case 0x04:
|
||||
ret = val == 1 ?
|
||||
PROC9 + (0x08063C28 - P9_ADDR) :
|
||||
PROC9 + (0x0805E2D4 - P9_ADDR);
|
||||
break;
|
||||
case 0x0C:
|
||||
ret = val == 1 ?
|
||||
0 :
|
||||
0; //TODO: find
|
||||
break;
|
||||
case 0x0F:
|
||||
ret = val == 1 ?
|
||||
PROC9 + (0x08063374 - P9_ADDR) :
|
||||
PROC9 + (0x0805D498 - P9_ADDR);
|
||||
break;
|
||||
case 0x18:
|
||||
ret = val == 1 ?
|
||||
PROC9 + v9_6_Offset + (0x080632B8 - P9_ADDR) :
|
||||
PROC9 + v9_6_Offset + (0x0805D628 - P9_ADDR);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
u32 sigPatch(u8 val){
|
||||
return val == 1 ?
|
||||
PROC9 + (0x080632B8 - P9_ADDR) :
|
||||
PROC9 + (0x0805D628 - P9_ADDR);
|
||||
}
|
||||
@@ -21,11 +21,11 @@ u8 th2[4];
|
||||
/**************************************************
|
||||
* Functions
|
||||
**************************************************/
|
||||
u32 emuCode(u32 kver);
|
||||
u32 mpuCode(u32 kver);
|
||||
u32 threadCode(u32 kver);
|
||||
u32 threadHook(u8 val, u32 kver);
|
||||
u32 emuHook(u8 val, u32 kver);
|
||||
u32 sigPatch(u8 val, u32 kver);
|
||||
u32 emuCode(void);
|
||||
u32 mpuCode(void);
|
||||
u32 threadCode(void);
|
||||
u32 threadHook(u8 val);
|
||||
u32 emuHook(u8 val);
|
||||
u32 sigPatch(u8 val);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user