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:
Reisyukaku
2016-01-16 07:57:56 -05:00
parent 42df009858
commit 6a2c30503d
50 changed files with 822 additions and 4025 deletions

View File

@@ -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;
}
}

View File

@@ -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*/

View File

@@ -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
}

View File

@@ -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 */
)
{

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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)();
}

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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