Compare commits

..

9 Commits
v3.7 ... v3.7.3

Author SHA1 Message Date
Aurora
4bdba9f8e9 Even moar clean-up 2016-03-06 16:31:16 +01:00
Aurora
99829b3cf7 (Hopefully last) clean-up 2016-03-06 05:04:28 +01:00
Aurora
d4a3ce2d0d Clean-up of the filesystem functions 2016-03-05 23:33:11 +01:00
Aurora
a58cb05f2c Previous release broke .dat booting from a 9.0 NAND if A9LH was installed
Also, more clean-up
2016-03-05 20:22:31 +01:00
Aurora
9ab6d107b4 Not needed 2016-03-05 18:47:47 +01:00
Aurora
42cbead456 Remove redundancies 2016-03-05 16:16:25 +01:00
Aurora
90ebe78c8e Added forcing of boot options on A9LH
Always prevents losing AGB_FIRM saves, forces the last used options on a MCU reboot (can be overridden with A)
2016-03-05 15:42:40 +01:00
Aurora
bf81ec252e Even more clean-up 2016-03-05 00:56:35 +01:00
Aurora
899ad1887a Some clean-up 2016-03-05 00:41:42 +01:00
16 changed files with 194 additions and 407 deletions

View File

@@ -1,16 +1,8 @@
// From http://github.com/b1l1s/ctr // From http://github.com/b1l1s/ctr
#include "crypto.h" #include "crypto.h"
#include <stddef.h>
#include "memory.h" #include "memory.h"
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
#include "fatfs/ff.h"
//Nand key#2 (0x12C10)
u8 key2[0x10] = {
0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0
};
/**************************************************************** /****************************************************************
* Crypto Libs * Crypto Libs
@@ -231,147 +223,24 @@ void aes(void* dst, const void* src, u32 blockCount, void* iv, u32 mode, u32 ivM
} }
} }
void sha_wait_idle()
{
while(*REG_SHA_CNT & 1);
}
void sha(void* res, const void* src, u32 size, u32 mode)
{
sha_wait_idle();
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
const u32* src32 = (const u32*)src;
int i;
while(size >= 0x40)
{
sha_wait_idle();
for(i = 0; i < 4; ++i)
{
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
*REG_SHA_INFIFO = *src32++;
}
size -= 0x40;
}
sha_wait_idle();
memcpy((void*)REG_SHA_INFIFO, src32, size);
*REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
while(*REG_SHA_CNT & SHA_FINAL_ROUND);
sha_wait_idle();
u32 hashSize = SHA_256_HASH_SIZE;
if(mode == SHA_224_MODE)
hashSize = SHA_224_HASH_SIZE;
else if(mode == SHA_1_MODE)
hashSize = SHA_1_HASH_SIZE;
memcpy(res, (void*)REG_SHA_HASH, hashSize);
}
void rsa_wait_idle()
{
while(*REG_RSA_CNT & 1);
}
void rsa_use_keyslot(u32 keyslot)
{
*REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4);
}
void rsa_setkey(u32 keyslot, const void* mod, const void* exp, u32 mode)
{
rsa_wait_idle();
*REG_RSA_CNT = (*REG_RSA_CNT & ~RSA_CNT_KEYSLOTS) | (keyslot << 4) | RSA_IO_BE | RSA_IO_NORMAL;
u32 size = mode * 4;
volatile u32* keyslotCnt = REG_RSA_SLOT0 + (keyslot << 4);
keyslotCnt[0] &= ~(RSA_SLOTCNT_KEY_SET | RSA_SLOTCNT_WPROTECT);
keyslotCnt[1] = mode;
memcpy((void*)REG_RSA_MOD_END - size, mod, size);
if(exp == NULL)
{
size -= 4;
while(size)
{
*REG_RSA_EXPFIFO = 0;
size -= 4;
}
*REG_RSA_EXPFIFO = 0x01000100; // 0x00010001 byteswapped
}
else
{
const u32* exp32 = (const u32*)exp;
while(size)
{
*REG_RSA_EXPFIFO = *exp32++;
size -= 4;
}
}
}
int rsa_iskeyset(u32 keyslot)
{
return *(REG_RSA_SLOT0 + (keyslot << 4)) & 1;
}
void rsa(void* dst, const void* src, u32 size)
{
u32 keyslot = (*REG_RSA_CNT & RSA_CNT_KEYSLOTS) >> 4;
if(rsa_iskeyset(keyslot) == 0)
return;
rsa_wait_idle();
*REG_RSA_CNT |= RSA_IO_BE | RSA_IO_NORMAL;
// Pad the message with zeroes so that it's a multiple of 8
// and write the message with the end aligned with the register
u32 padSize = ((size + 7) & ~7) - size;
memset((void*)REG_RSA_TXT_END - (size + padSize), 0, padSize);
memcpy((void*)REG_RSA_TXT_END - size, src, size);
// Start
*REG_RSA_CNT |= RSA_CNT_START;
rsa_wait_idle();
memcpy(dst, (void*)REG_RSA_TXT_END - size, size);
}
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode)
{
u8 dataHash[SHA_256_HASH_SIZE];
sha(dataHash, data, size, SHA_256_MODE);
u8 decSig[0x100]; // Way too big, need to request a work area
u32 sigSize = mode * 4;
rsa(decSig, sig, sigSize);
return memcmp(dataHash, decSig + (sigSize - SHA_256_HASH_SIZE), SHA_256_HASH_SIZE) == 0;
}
/**************************************************************** /****************************************************************
* Nand/FIRM Crypto stuff * Nand/FIRM Crypto stuff
****************************************************************/ ****************************************************************/
//Nand key#2 (0x12C10)
u8 key2[0x10] = {
0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0
};
//Get Nand CTR key //Get Nand CTR key
void getNandCTR(u8 *buf, u8 console) { void getNandCTR(u8 *buf, u8 console){
u8 *addr = console ? (u8*)0x080D8BBC : (u8*)0x080D797C; u8 *addr = (console ? (u8*)0x080D8BBC : (u8*)0x080D797C) + 0x0F;
u8 keyLen = 0x10; //CTR length for(u8 keyLen = 0x10; keyLen; keyLen--)
addr += 0x0F; *(buf++) = *(addr--);
while (keyLen --) { *(buf++) = *(addr--); }
} }
//Read firm0 from NAND and write to buffer //Read firm0 from NAND and write to buffer
void nandFirm0(u8 *outbuf, const u32 size, u8 console){ void nandFirm0(u8 *outbuf, u32 size, u8 console){
u8 CTR[0x10]; u8 CTR[0x10];
getNandCTR(CTR, console); getNandCTR(CTR, console);
aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL); aes_advctr(CTR, 0x0B130000/0x10, AES_INPUT_BE | AES_INPUT_NORMAL);
@@ -384,42 +253,48 @@ void nandFirm0(u8 *outbuf, const u32 size, u8 console){
void decArm9Bin(void *armHdr, u8 mode){ void decArm9Bin(void *armHdr, u8 mode){
//Firm keys //Firm keys
u8 keyX[0x10];
u8 keyY[0x10]; u8 keyY[0x10];
u8 CTR[0x10]; u8 CTR[0x10];
u32 slot = mode ? 0x16 : 0x15; u8 slot = mode ? 0x16 : 0x15;
//Setup keys needed for arm9bin decryption //Setup keys needed for arm9bin decryption
memcpy((u8*)keyY, (void *)(armHdr+0x10), 0x10); memcpy(keyY, armHdr+0x10, 0x10);
memcpy((u8*)CTR, (void *)(armHdr+0x20), 0x10); memcpy(CTR, armHdr+0x20, 0x10);
u32 size = atoi((void *)(armHdr+0x30)); u32 size = 0;
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
for(u8 *tmp = armHdr+0x30; *tmp; tmp++)
size = (size<<3)+(size<<1)+(*tmp)-'0';
if(mode){ if(mode){
u8 keyX[0x10];
//Set 0x11 to key2 for the arm9bin and misc keys //Set 0x11 to key2 for the arm9bin and misc keys
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11); aes_use_keyslot(0x11);
aes((u8*)keyX, (void *)(armHdr+0x60), 1, NULL, AES_ECB_DECRYPT_MODE, 0); aes(keyX, 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, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
} }
aes_setkey(slot, (u8*)keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(slot, keyY, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setiv((u8*)CTR, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setiv(CTR, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(slot); aes_use_keyslot(slot);
//Decrypt arm9bin //Decrypt arm9bin
aes((void *)(armHdr+0x800), (void *)(armHdr+0x800), size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); aes(armHdr+0x800, armHdr+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
} }
//Sets the N3DS 9.6 KeyXs //Sets the N3DS 9.6 KeyXs
void setKeyXs(void *armHdr){ void setKeyXs(void *armHdr){
void *keyData = armHdr+0x89814;
void *decKey = keyData+0x10;
//Set keys 0x19..0x1F keyXs //Set keys 0x19..0x1F keyXs
u8* decKey = (void *)(armHdr+0x89824); aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_setkey(0x11, (u8*)key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x11); aes_use_keyslot(0x11);
for(u32 slot = 0x19; slot < 0x20; slot++){ for(u8 slot = 0x19; slot < 0x20; slot++){
aes(decKey, (void *)(armHdr+0x89814), 1, NULL, AES_ECB_DECRYPT_MODE, 0); aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
aes_setkey(slot, (u8*)decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL); aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
*(u8*)(armHdr+0x89814+0xF) += 1; *(u8*)(keyData+0xF) += 1;
} }
} }

View File

@@ -1,21 +1,10 @@
// From http://github.com/b1l1s/ctr // From http://github.com/b1l1s/ctr
#ifndef __CRYPTO_H #ifndef CRYPTO_INC
#define __CRYPTO_H #define CRYPTO_INC
#include <stdint.h>
#include "types.h" #include "types.h"
#define FIRM_TYPE_ARM9 0
#define FIRM_TYPE_ARM11 1
#define MEDIA_UNITS 0x200
#define NCCH_MAGIC (0x4843434E)
#define NCSD_MAGIC (0x4453434E)
#define FIRM_MAGIC (0x4D524946)
#define ARM9BIN_MAGIC (0x47704770)
/**************************AES****************************/ /**************************AES****************************/
#define REG_AESCNT ((volatile u32*)0x10009000) #define REG_AESCNT ((volatile u32*)0x10009000)
#define REG_AESBLKCNT ((volatile u32*)0x10009004) #define REG_AESBLKCNT ((volatile u32*)0x10009004)
@@ -52,8 +41,6 @@
#define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER) #define AES_INPUT_NORMAL (AES_CNT_INPUT_ORDER)
#define AES_INPUT_REVERSED 0 #define AES_INPUT_REVERSED 0
#define AES_TEMP_KEYSLOT 0x11
#define AES_BLOCK_SIZE 0x10 #define AES_BLOCK_SIZE 0x10
#define AES_KEYCNT_WRITE (1 << 0x7) #define AES_KEYCNT_WRITE (1 << 0x7)
@@ -61,78 +48,9 @@
#define AES_KEYX 1 #define AES_KEYX 1
#define AES_KEYY 2 #define AES_KEYY 2
/**************************SHA****************************/
#define REG_SHA_CNT ((volatile u32*)0x1000A000)
#define REG_SHA_BLKCNT ((volatile u32*)0x1000A004)
#define REG_SHA_HASH ((volatile u32*)0x1000A040)
#define REG_SHA_INFIFO ((volatile u32*)0x1000A080)
#define SHA_CNT_STATE 0x00000003
#define SHA_CNT_UNK2 0x00000004
#define SHA_CNT_OUTPUT_ENDIAN 0x00000008
#define SHA_CNT_MODE 0x00000030
#define SHA_CNT_ENABLE 0x00010000
#define SHA_CNT_ACTIVE 0x00020000
#define SHA_HASH_READY 0x00000000
#define SHA_NORMAL_ROUND 0x00000001
#define SHA_FINAL_ROUND 0x00000002
#define SHA_OUTPUT_BE SHA_CNT_OUTPUT_ENDIAN
#define SHA_OUTPUT_LE 0
#define SHA_256_MODE 0
#define SHA_224_MODE 0x00000010
#define SHA_1_MODE 0x00000020
#define SHA_256_HASH_SIZE (256 / 8)
#define SHA_224_HASH_SIZE (224 / 8)
#define SHA_1_HASH_SIZE (160 / 8)
/**************************RSA****************************/
#define REG_RSA_CNT ((volatile u32*)0x1000B000)
#define REG_RSA_SLOT0 ((volatile u32*)0x1000B100)
#define REG_RSA_SLOT1 ((volatile u32*)0x1000B110)
#define REG_RSA_SLOT2 ((volatile u32*)0x1000B120)
#define REG_RSA_SLOT3 ((volatile u32*)0x1000B130)
#define REG_RSA_EXPFIFO ((volatile u32*)0x1000B200)
#define REG_RSA_MOD_END ((volatile u32*)0x1000B500)
#define REG_RSA_TXT_END ((volatile u32*)0x1000B900)
#define RSA_CNT_START 0x00000001
#define RSA_CNT_KEYSLOTS 0x000000F0
#define RSA_CNT_IO_ENDIAN 0x00000100
#define RSA_CNT_IO_ORDER 0x00000200
#define RSA_SLOTCNT_KEY_SET 0x00000001
#define RSA_SLOTCNT_WPROTECT 0x00000002 // Write protect
#define RSA_IO_BE RSA_CNT_IO_ENDIAN
#define RSA_IO_LE 0
#define RSA_IO_NORMAL RSA_CNT_IO_ORDER
#define RSA_IO_REVERSED 0
#define RSA_TEMP_KEYSLOT 0
#define RSA_1024_MODE 0x20
#define RSA_2048_MODE 0x40
//Crypto Libs
void aes_setkey(u8 keyslot, const void* key, u32 keyType, u32 mode);
void aes_use_keyslot(u8 keyslot);
void aes(void* dst, const void* src, u32 blockCount, void* iv, u32 mode, u32 ivMode);
void aes_setiv(const void* iv, u32 mode);
void aes_advctr(void* ctr, u32 val, u32 mode);
void aes_change_ctrmode(void* ctr, u32 fromMode, u32 toMode);
void aes_batch(void* dst, const void* src, u32 blockCount);
void sha(void* res, const void* src, u32 size, u32 mode);
void rsa_setkey(u32 keyslot, const void* mod, const void* exp, u32 mode);
void rsa_use_keyslot(u32 keyslot);
int rsa_verify(const void* data, u32 size, const void* sig, u32 mode);
//NAND/FIRM stuff //NAND/FIRM stuff
void nandFirm0(u8 *outbuf, const u32 size, u8 console); void nandFirm0(u8 *outbuf, u32 size, u8 console);
void decArm9Bin(void *armHdr, u8 mode); void decArm9Bin(void *armHdr, u8 mode);
void setKeyXs(void *armHdr); void setKeyXs(void *armHdr);
#endif /*__CRYPTO_H*/ #endif

View File

@@ -7,7 +7,6 @@
#include "draw.h" #include "draw.h"
#include "fs.h" #include "fs.h"
#include "memory.h" #include "memory.h"
#include "types.h"
static struct fb *fb = (struct fb *)0x23FFFE00; static struct fb *fb = (struct fb *)0x23FFFE00;
@@ -24,7 +23,7 @@ void shutdownLCD(void){
*(vu32*)0x10202014 = 0; *(vu32*)0x10202014 = 0;
//Wait for the ARM11 entrypoint to be set //Wait for the ARM11 entrypoint to be set
while (!*arm11); while(!*arm11);
//Jump to it //Jump to it
((void (*)())*arm11)(); ((void (*)())*arm11)();
} }
@@ -37,8 +36,8 @@ void clearScreen(void){
void loadSplash(void){ void loadSplash(void){
//Check if it's a no-screen-init A9LH boot via PDN_GPU_CNT //Check if it's a no-screen-init A9LH boot via PDN_GPU_CNT
if (*((u8*)0x10141200) == 0x1) return; if(*(u8*)0x10141200 == 0x1) return;
clearScreen(); clearScreen();
if(fileRead(fb->top_left, "/rei/splash.bin", 0x46500) != 0) return; if(!fileRead(fb->top_left, "/rei/splash.bin", 0x46500)) return;
u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func u64 i = 0xFFFFFF; while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func
} }

View File

@@ -4,6 +4,9 @@
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef DRAW_INC
#define DRAW_INC
#include "types.h" #include "types.h"
struct fb { struct fb {
@@ -13,4 +16,6 @@ struct fb {
}; };
void loadSplash(void); void loadSplash(void);
void shutdownLCD(void); void shutdownLCD(void);
#endif

View File

@@ -6,15 +6,14 @@
#include "emunand.h" #include "emunand.h"
#include "memory.h" #include "memory.h"
#include "fatfs/ff.h"
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
static u8 *temp = (u8*)0x24300000; static u8 *temp = (u8*)0x24300000;
void getEmunandSect(u32 *off, u32 *head){ void getEmunandSect(u32 *off, u32 *head){
u32 nandSize = getMMCDevice(0)->total_size; u32 nandSize = getMMCDevice(0)->total_size;
if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) { if(sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0){
if (*(u32*)(temp + 0x100) == NCSD_MAGIC) { if(*(u32*)(temp + 0x100) == NCSD_MAGIC){
*off = 0; *off = 0;
*head = nandSize; *head = nandSize;
} }
@@ -27,17 +26,17 @@ void getSDMMC(void *pos, u32 *off, u32 size){
*off = (u32)memsearch(pos, pattern, size, 4) - 1; *off = (u32)memsearch(pos, pattern, size, 4) - 1;
//Get DCD values //Get DCD values
unsigned char buf[4]; u8 buf[4],
int p; p;
u32 addr = 0, u32 addr = 0,
additive = 0; additive = 0;
memcpy((void*)buf, (void*)(*off+0x0A), 4); memcpy(buf, (void *)(*off+0x0A), 4);
for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p); for (p = 0; p < 4; p++) addr |= ((u32) buf[p]) << (8 * p);
memcpy((void*)buf, (void*)(*off+0x0E), 4); memcpy(buf, (void *)(*off+0x0E), 4);
for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p); for (p = 0; p < 4; p++) additive |= ((u32) buf[p]) << (8 * p);
//Return result //Return result
*off = addr + additive; *off = addr + additive;
} }
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){

View File

@@ -4,8 +4,8 @@
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef EMU_INC #ifndef EMUNAND_INC
#define EMU_INC #define EMUNAND_INC
#include "types.h" #include "types.h"

View File

@@ -26,27 +26,60 @@ char *firmPathPatched = NULL;
void setupCFW(void){ void setupCFW(void){
//Determine if booting with A9LH via PDN_SPI_CNT
u8 a9lhBoot = (*(u8*)0x101401C0 == 0x0) ? 1 : 0;
//Retrieve the last booted FIRM via CFG_BOOTENV
u8 previousFirm = *(u8*)0x10010000;
u8 overrideConfig = 0;
const char lastConfigPath[] = "rei/lastbootcfg";
//Detect the console being used //Detect the console being used
if(PDN_MPCORE_CFG == 1) console = 0; if(PDN_MPCORE_CFG == 1) console = 0;
//Get pressed buttons //Get pressed buttons
pressed = HID_PAD; pressed = HID_PAD;
//Determine if A9LH is installed via PDN_SPI_CNT and an user flag //Determine if A9LH is installed
if((*((u8*)0x101401C0) == 0x0) || fileExists("/rei/installeda9lh")){ if(a9lhBoot || fileExists("/rei/installeda9lh")){
a9lhSetup = 1; a9lhSetup = 1;
//Check flag for > 9.2 SysNAND //Check flag for > 9.2 SysNAND
if(fileExists("/rei/updatedsysnand")) updatedSys = 1; if(fileExists("/rei/updatedsysnand")) updatedSys = 1;
} }
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo //If booting with A9LH and it's a MCU reboot, try to force boot options
is not pressed, boot 9.0 FIRM */ if(a9lhBoot && previousFirm && fileExists(lastConfigPath)){
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0; u8 tempConfig;
fileRead(&tempConfig, lastConfigPath, 1);
/* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected //Always force a sysNAND boot when quitting AGB_FIRM
or R is pressed on a > 9.2 SysNAND, boot emuNAND */ if(previousFirm == 0x7) {
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) || if(!updatedSys) mode = tempConfig & 0x1;
(!updatedSys && mode && !(pressed & BUTTON_R1))) emuNAND = 1; overrideConfig = 1;
//Else, force the last used boot options unless A is pressed
} else if(!(pressed & BUTTON_A)) {
mode = tempConfig & 0x1;
emuNAND = (tempConfig >> 1) & 0x1;
overrideConfig = 1;
}
}
if(!overrideConfig){
/* If L is pressed, and on an updated SysNAND setup the SAFE MODE combo
is not pressed, boot 9.0 FIRM */
if((pressed & BUTTON_L1) && !(updatedSys && pressed == SAFEMODE)) mode = 0;
/* If L or R aren't pressed on a 9.0/9.2 SysNAND, or the 9.0 FIRM is selected
or R is pressed on a > 9.2 SysNAND, boot emuNAND */
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
(!updatedSys && mode && !(pressed & BUTTON_R1))) emuNAND = 1;
//Write the current boot options on A9LH
if(a9lhBoot){
u8 tempConfig = (mode | (emuNAND << 1)) & 0x3;
fileWrite(&tempConfig, lastConfigPath, 1);
}
}
if(mode) firmPathPatched = emuNAND ? "/rei/patched_firmware_emu.bin" : if(mode) firmPathPatched = emuNAND ? "/rei/patched_firmware_emu.bin" :
"/rei/patched_firmware_sys.bin"; "/rei/patched_firmware_sys.bin";
@@ -55,7 +88,7 @@ void setupCFW(void){
if(fileExists("/rei/usepatchedfw")){ if(fileExists("/rei/usepatchedfw")){
//Only needed with this flag //Only needed with this flag
if(!mode) firmPathPatched = "/rei/patched_firmware90.bin"; if(!mode) firmPathPatched = "/rei/patched_firmware90.bin";
if (fileExists(firmPathPatched)) usePatchedFirm = 1; if(fileExists(firmPathPatched)) usePatchedFirm = 1;
} }
} }
@@ -68,26 +101,26 @@ u8 loadFirm(void){
firmSize = console ? 0xF2000 : 0xE9000; firmSize = console ? 0xF2000 : 0xE9000;
nandFirm0((u8*)firmLocation, firmSize, console); nandFirm0((u8*)firmLocation, firmSize, console);
//Check for correct decryption //Check for correct decryption
if(memcmp((u8*)firmLocation, "FIRM", 4) != 0) return 1; if(memcmp((u8*)firmLocation, "FIRM", 4) != 0) return 0;
} }
//Load FIRM from SD //Load FIRM from SD
else{ else{
char *path = usePatchedFirm ? firmPathPatched : const char *path = usePatchedFirm ? firmPathPatched :
(mode ? "/rei/firmware.bin" : "/rei/firmware90.bin"); (mode ? "/rei/firmware.bin" : "/rei/firmware90.bin");
firmSize = fileSize(path); firmSize = fileSize(path);
if (!firmSize) return 1; if(!firmSize) return 0;
fileRead((u8*)firmLocation, path, firmSize); fileRead((u8*)firmLocation, path, firmSize);
} }
section = firmLocation->section; section = firmLocation->section;
//Check that the loaded FIRM matches the console //Check that the loaded FIRM matches the console
if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) return 1; if((((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68)) return 0;
if(console && !usePatchedFirm) if(console && !usePatchedFirm)
decArm9Bin((u8*)firmLocation + section[2].offset, mode); decArm9Bin((u8*)firmLocation + section[2].offset, mode);
return 0; return 1;
} }
//Nand redirection //Nand redirection
@@ -102,20 +135,19 @@ u8 loadEmu(void){
emuCodeOffset = 0; emuCodeOffset = 0;
//Read emunand code from SD //Read emunand code from SD
char path[] = "/rei/emunand/emunand.bin"; const char path[] = "/rei/emunand/emunand.bin";
u32 size = fileSize(path); u32 size = fileSize(path);
if (!size) return 1; if(!size) return 0;
if(!console || !mode) nandRedir[5] = 0xA4; if(!console || !mode) nandRedir[5] = 0xA4;
//Find offset for emuNAND code from the offset in nandRedir //Find offset for emuNAND code from the offset in nandRedir
u8 *emuCodeTmp = &nandRedir[4]; emuCodeOffset = *(u32 *)(nandRedir + 4) - (u32)section[2].address +
emuCodeOffset = *(u32*)emuCodeTmp - (u32)section[2].address +
section[2].offset + (u32)firmLocation; section[2].offset + (u32)firmLocation;
fileRead((u8*)emuCodeOffset, path, size); fileRead((u8*)emuCodeOffset, path, size);
//Find and patch emunand related offsets //Find and patch emunand related offsets
u32 *pos_sdmmc = memsearch((u32*)emuCodeOffset, "SDMC", size, 4); u32 *pos_sdmmc = (u32 *)memsearch((u32*)emuCodeOffset, "SDMC", size, 4);
u32 *pos_offset = memsearch((u32*)emuCodeOffset, "NAND", size, 4); u32 *pos_offset = (u32 *)memsearch((u32*)emuCodeOffset, "NAND", size, 4);
u32 *pos_header = memsearch((u32*)emuCodeOffset, "NCSD", size, 4); u32 *pos_header = (u32 *)memsearch((u32*)emuCodeOffset, "NCSD", size, 4);
getSDMMC(firmLocation, &sdmmcOffset, firmSize); getSDMMC(firmLocation, &sdmmcOffset, firmSize);
getEmunandSect(&emuOffset, &emuHeader); getEmunandSect(&emuOffset, &emuHeader);
getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite); getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite);
@@ -126,32 +158,35 @@ u8 loadEmu(void){
//Patch emuNAND code in memory for O3DS and 9.0 N3DS //Patch emuNAND code in memory for O3DS and 9.0 N3DS
if(!console || !mode){ if(!console || !mode){
u32 *pos_instr = memsearch((u32*)emuCodeOffset, "\xA6\x01\x08\x30", size, 4); void *pos_instr = memsearch((u32*)emuCodeOffset, "\xA6\x01\x08\x30", size, 4);
memcpy((u8*)pos_instr, emuInstr, sizeof(emuInstr)); memcpy(pos_instr, emuInstr, sizeof(emuInstr));
} }
//Add emunand hooks //Add emunand hooks
memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir)); memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir)); memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
//Set MPU for emu code region //Set MPU for emu code region
memcpy((u8*)mpuOffset, mpu, sizeof(mpu)); memcpy((void *)mpuOffset, mpu, sizeof(mpu));
return 0; return 1;
} }
//Patches //Patches
u8 patchFirm(void){ u8 patchFirm(void){
if(usePatchedFirm) return 0;
//Skip patching
if(usePatchedFirm) return 1;
//Apply emuNAND patches
if(emuNAND){ if(emuNAND){
if (loadEmu()) return 1; if(!loadEmu()) return 0;
} }
else if (a9lhSetup){ else if(a9lhSetup){
//Patch FIRM partitions writes on SysNAND to protect A9LH //Patch FIRM partitions writes on SysNAND to protect A9LH
u32 writeOffset = 0; u32 writeOffset = 0;
getFIRMWrite(firmLocation, firmSize, &writeOffset); getFIRMWrite(firmLocation, firmSize, &writeOffset);
memcpy((u8*)writeOffset, FIRMblock, sizeof(FIRMblock)); memcpy((void *)writeOffset, FIRMblock, sizeof(FIRMblock));
} }
//Disable signature checks //Disable signature checks
@@ -159,8 +194,8 @@ u8 patchFirm(void){
sigOffset2 = 0; sigOffset2 = 0;
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2); getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
memcpy((u8*)sigOffset, sigPat1, sizeof(sigPat1)); memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1));
memcpy((u8*)sigOffset2, sigPat2, sizeof(sigPat2)); memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2));
//Patch ARM9 entrypoint on N3DS to skip arm9loader //Patch ARM9 entrypoint on N3DS to skip arm9loader
if(console){ if(console){
@@ -168,35 +203,35 @@ u8 patchFirm(void){
*arm9 = 0x801B01C; *arm9 = 0x801B01C;
} }
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
if(mode){ if(mode){
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
u32 rebootOffset = 0, u32 rebootOffset = 0,
fOpenOffset = 0; fOpenOffset = 0;
//Read reboot code from SD //Read reboot code from SD
char *path = "/rei/reboot/reboot.bin"; const char path[] = "/rei/reboot/reboot.bin";
u32 size = fileSize(path); u32 size = fileSize(path);
if (!size) return 1; if(!size) return 0;
getReboot(firmLocation, firmSize, &rebootOffset); getReboot(firmLocation, firmSize, &rebootOffset);
fileRead((u8*)rebootOffset, path, size); fileRead((u8*)rebootOffset, path, size);
//Calculate the fOpen offset and put it in the right location //Calculate the fOpen offset and put it in the right location
u32 *pos_fopen = memsearch((u32*)rebootOffset, "OPEN", size, 4); u32 *pos_fopen = (u32 *)memsearch((u32*)rebootOffset, "OPEN", size, 4);
getfOpen(firmLocation, firmSize, &fOpenOffset); getfOpen(firmLocation, firmSize, &fOpenOffset);
*pos_fopen = fOpenOffset; *pos_fopen = fOpenOffset;
//Patch path for emuNAND-patched FIRM //Patch path for emuNAND-patched FIRM
if(emuNAND){ if(emuNAND){
u32 *pos_path = memsearch((u32*)rebootOffset, L"sys", size, 6); void *pos_path = memsearch((u32*)rebootOffset, L"sy", size, 4);
memcpy((u8*)pos_path, L"emu", 6); memcpy(pos_path, L"emu", 5);
} }
} }
//Write patched FIRM to SD if needed //Write patched FIRM to SD if needed
if(firmPathPatched) if(firmPathPatched)
if(fileWrite((u8*)firmLocation, firmPathPatched, firmSize) != 0) return 1; if(!fileWrite((u8*)firmLocation, firmPathPatched, firmSize)) return 0;
return 0; return 1;
} }
void launchFirm(void){ void launchFirm(void){

View File

@@ -3,6 +3,7 @@
* by Reisyukaku * by Reisyukaku
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef FIRM_INC #ifndef FIRM_INC
#define FIRM_INC #define FIRM_INC
@@ -12,7 +13,8 @@
#define HID_PAD ((~*(u16*)0x10146000) & 0xFFF) #define HID_PAD ((~*(u16*)0x10146000) & 0xFFF)
#define BUTTON_R1 (1 << 8) #define BUTTON_R1 (1 << 8)
#define BUTTON_L1 (1 << 9) #define BUTTON_L1 (1 << 9)
#define SAFEMODE (BUTTON_L1 | BUTTON_R1 | 1 | (1 << 6)) #define BUTTON_A 1
#define SAFEMODE (BUTTON_L1 | BUTTON_R1 | BUTTON_A | (1 << 6))
void setupCFW(void); void setupCFW(void);
u8 loadFirm(void); u8 loadFirm(void);

View File

@@ -2,96 +2,60 @@
* fs.c * fs.c
*/ */
#include <stddef.h>
#include "fs.h" #include "fs.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
static FATFS fs; static FATFS fs;
int mountSD() u8 mountSD(void){
{ if(f_mount(&fs, "0:", 1) != FR_OK) return 0;
if (f_mount(&fs, "0:", 1) != FR_OK) { return 1;
//printF("Failed to mount SD card!");
return 1;
}
//printF("Mounted SD card");
return 0;
} }
int unmountSD() u8 fileRead(u8 *dest, const char *path, u32 size){
{
if (f_mount(NULL, "0:", 1) != FR_OK) {
//printF("Failed to mount SD card!");
return 1;
}
//printF("Unmounted SD card");
return 0;
}
int fileReadOffset(u8 *dest, const char *path, u32 size, u32 offset){
FRESULT fr; FRESULT fr;
FIL fp; FIL fp;
unsigned int br = 0; unsigned int br = 0;
fr = f_open(&fp, path, FA_READ); fr = f_open(&fp, path, FA_READ);
if (fr != FR_OK)goto error; if(fr == FR_OK){
if(!size) size = f_size(&fp);
if (!size) size = f_size(&fp); fr = f_read(&fp, dest, size, &br);
if (offset) {
fr = f_lseek(&fp, offset);
if (fr != FR_OK) goto error;
} }
fr = f_read(&fp, dest, size, &br);
if (fr != FR_OK) goto error;
fr = f_close(&fp);
if (fr != FR_OK) goto error;
return 0;
error:
f_close(&fp); f_close(&fp);
return fr; return fr ? 0 : 1;
} }
int fileRead(u8 *dest, const char *path, u32 size){ u8 fileWrite(const u8 *buffer, const char *path, u32 size){
return fileReadOffset(dest, path, size, 0); FRESULT fr;
}
int fileWrite(const u8 *buffer, const char *path, u32 size){
FRESULT fr = 1;
FIL fp; FIL fp;
unsigned int br = 0; unsigned int br = 0;
f_unlink(path); fr = f_open(&fp, path, FA_WRITE | FA_OPEN_ALWAYS);
if(f_open(&fp, path, FA_WRITE | FA_OPEN_ALWAYS) == FR_OK){ if(fr == FR_OK) fr = f_write(&fp, buffer, size, &br);
fr = f_write(&fp, buffer, size, &br);
f_close(&fp); f_close(&fp);
if (fr == FR_OK && br == size) return 0; return fr ? 0 : 1;
}
return fr;
} }
int fileSize(const char* path){ u32 fileSize(const char* path){
FRESULT fr;
FIL fp; FIL fp;
int size = 0; u32 size = 0;
fr = f_open(&fp, path, FA_READ); if(f_open(&fp, path, FA_READ) == FR_OK)
if (fr != FR_OK)goto error; size = f_size(&fp);
size = f_size(&fp); f_close(&fp);
error: return size;
f_close(&fp);
return size;
} }
int fileExists(const char* path){ u8 fileExists(const char* path){
FRESULT fr;
FIL fp; FIL fp;
int exists = 1; u8 exists = 0;
fr = f_open(&fp, path, FA_READ);
if (fr != FR_OK)exists = 0; if(f_open(&fp, path, FA_READ) == FR_OK) exists = 1;
f_close(&fp); f_close(&fp);
return exists; return exists;
} }

View File

@@ -2,17 +2,15 @@
* fs.h * fs.h
*/ */
#ifndef __fs_h__ #ifndef FS_INC
#define __fs_h__ #define FS_INC
#include "types.h" #include "types.h"
int mountSD(); u8 mountSD(void);
int unmountSD(); u8 fileRead(u8 *dest, const char *path, u32 size);
int fileReadOffset(u8 *dest, const char *path, u32 size, u32 offset); u8 fileWrite(const u8 *buffer, const char *path, u32 size);
int fileRead(u8 *dest, const char *path, u32 size); u32 fileSize(const char* path);
int fileWrite(const u8 *buffer, const char *path, u32 size); u8 fileExists(const char* path);
int fileSize(const char* path);
int fileExists(const char* path);
#endif #endif

View File

@@ -14,8 +14,8 @@ u8 main(){
mountSD(); mountSD();
loadSplash(); loadSplash();
setupCFW(); setupCFW();
if (loadFirm()) return 1; if(!loadFirm()) return 0;
if (patchFirm()) return 1; if(!patchFirm()) return 0;
launchFirm(); launchFirm();
return 0; return 1;
} }

View File

@@ -3,40 +3,35 @@
* by Reisyukaku * by Reisyukaku
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#include "memory.h" #include "memory.h"
void memcpy32(u32 *dest, u32 *src, u32 size){
for (u32 i = 0; i < size; i++) dest[i] = src[i];
}
void memcpy(void *dest, const void *src, u32 size){ void memcpy(void *dest, const void *src, u32 size){
char *destc = (char *)dest; u8 *destc = (u8 *)dest;
const char *srcc = (const char *)src; const u8 *srcc = (const u8 *)src;
u32 i; for (i = 0; i < size; i++) { for(u32 i = 0; i < size; i++)
destc[i] = srcc[i]; destc[i] = srcc[i];
}
} }
void memset(void *dest, int filler, u32 size){ void memset(void *dest, int filler, u32 size){
char *destc = (char *)dest; u8 *destc = (u8 *)dest;
u32 i; for (i = 0; i < size; i++) { for(u32 i = 0; i < size; i++)
destc[i] = filler; destc[i] = (u8)filler;
}
} }
int memcmp(const void *buf1, const void *buf2, u32 size){ int memcmp(const void *buf1, const void *buf2, u32 size){
const char *buf1c = (const char *)buf1; const u8 *buf1c = (const u8 *)buf1;
const char *buf2c = (const char *)buf2; const u8 *buf2c = (const u8 *)buf2;
u32 i; for (i = 0; i < size; i++) { for(u32 i = 0; i < size; i++){
int cmp = buf1c[i] - buf2c[i]; int cmp = buf1c[i] - buf2c[i];
if (cmp) return cmp; if(cmp) return cmp;
} }
return 0; return 0;
} }
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search){ void *memsearch(void *start_pos, void *search, u32 size, u32 size_search){
for (void *pos = start_pos + size - size_search; pos >= start_pos; pos--) { for(void *pos = start_pos + size - size_search; pos >= start_pos; pos--){
if (memcmp(pos, search, size_search) == 0) return pos; if(memcmp(pos, search, size_search) == 0) return pos;
} }
return NULL; return NULL;
} }

View File

@@ -3,13 +3,13 @@
* by Reisyukaku * by Reisyukaku
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef MEM_INC
#define MEM_INC #ifndef MEMORY_INC
#define MEMORY_INC
#include "types.h" #include "types.h"
void memcpy(void *dest, const void *src, u32 size); void memcpy(void *dest, const void *src, u32 size);
void memcpy32(u32 *dest, u32 *src, u32 size);
void memset(void *dest, int filler, u32 size); void memset(void *dest, int filler, u32 size);
int memcmp(const void *buf1, const void *buf2, u32 size); int memcmp(const void *buf1, const void *buf2, u32 size);
void *memsearch(void *start_pos, void *search, u32 size, u32 size_search); void *memsearch(void *start_pos, void *search, u32 size, u32 size_search);

View File

@@ -11,9 +11,6 @@
* Patches * Patches
**************************************************/ **************************************************/
/*
* MPU
*/
u8 mpu[0x2C] = { //MPU shit u8 mpu[0x2C] = { //MPU shit
0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00, 0x03, 0x00, 0x36, 0x00, 0x00, 0x00, 0x10, 0x10, 0x01, 0x00, 0x00, 0x01, 0x03, 0x00, 0x36, 0x00,
0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x08,
@@ -22,12 +19,11 @@ u8 mpu[0x2C] = { //MPU shit
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0xC0, 0xA5, 0x01, 0x08}; //Branch to emunand function
/*
* Sig checks
*/
u8 sigPat1[2] = {0x00, 0x20}; u8 sigPat1[2] = {0x00, 0x20};
u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47}; u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46}; u8 FIRMblock[4] = {0x00, 0x20, 0xC0, 0x46};
u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5}; u8 emuInstr[5] = {0xA5, 0x01, 0x08, 0x30, 0xA5};
/************************************************** /**************************************************
@@ -54,7 +50,6 @@ void getfOpen(void *pos, u32 size, u32 *off){
//Calculate fOpen //Calculate fOpen
u32 p9addr = *(u32*)(memsearch(pos, "ess9", size, 4) + 0xC); u32 p9addr = *(u32*)(memsearch(pos, "ess9", size, 4) + 0xC);
u32 p9off = (u32)(memsearch(pos, "code", size, 4) + 0x1FF); u32 p9off = (u32)(memsearch(pos, "code", size, 4) + 0x1FF);
unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D}; unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
*off = (u32)memsearch(pos, pattern, size, 4) - 2 - p9off + p9addr; *off = (u32)memsearch(pos, pattern, size, 4) - 2 - p9off + p9addr;

View File

@@ -3,6 +3,7 @@
* by Reisyukaku * by Reisyukaku
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef PATCHES_INC #ifndef PATCHES_INC
#define PATCHES_INC #define PATCHES_INC

View File

@@ -3,6 +3,7 @@
* by Reisyukaku * by Reisyukaku
* Copyright (c) 2015 All Rights Reserved * Copyright (c) 2015 All Rights Reserved
*/ */
#ifndef TYPES_INC #ifndef TYPES_INC
#define TYPES_INC #define TYPES_INC