Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
feff28a4fe | ||
|
|
b3d25ce64a | ||
|
|
0f44205959 | ||
|
|
1861d556a6 | ||
|
|
9b1df43687 | ||
|
|
56e0157d64 | ||
|
|
d23cd5acd5 | ||
|
|
39a9eb5ccb | ||
|
|
c413b6d07f | ||
|
|
85a59264c9 | ||
|
|
7f96e47b4f | ||
|
|
02b5c69802 | ||
|
|
b5eb108393 | ||
|
|
0a9cd09cc3 | ||
|
|
af451b4997 | ||
|
|
a5f8ccc3ea | ||
|
|
28cdcfed9c |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,4 @@
|
|||||||
out
|
out
|
||||||
CakeHax
|
|
||||||
CakeBrah
|
|
||||||
build
|
build
|
||||||
loader/build
|
loader/build
|
||||||
*.bin
|
*.bin
|
||||||
|
|||||||
2
CakeBrah
2
CakeBrah
Submodule CakeBrah updated: aca4aa7d3b...42ebe0d0bc
43
Makefile
43
Makefile
@@ -4,25 +4,16 @@ CC := arm-none-eabi-gcc
|
|||||||
AS := arm-none-eabi-as
|
AS := arm-none-eabi-as
|
||||||
LD := arm-none-eabi-ld
|
LD := arm-none-eabi-ld
|
||||||
OC := arm-none-eabi-objcopy
|
OC := arm-none-eabi-objcopy
|
||||||
OPENSSL := openssl
|
|
||||||
|
|
||||||
PYTHON3 := python
|
|
||||||
PYTHON_VER_MAJOR := $(word 2, $(subst ., , $(shell python --version 2>&1)))
|
|
||||||
ifneq ($(PYTHON_VER_MAJOR), 3)
|
|
||||||
PYTHON3 := py -3
|
|
||||||
endif
|
|
||||||
|
|
||||||
name := AuReiNand
|
name := AuReiNand
|
||||||
|
|
||||||
dir_source := source
|
dir_source := source
|
||||||
dir_data := data
|
dir_patches := patches
|
||||||
dir_build := build
|
|
||||||
dir_mset := CakeHax
|
|
||||||
dir_out := out
|
|
||||||
dir_emu := emunand
|
|
||||||
dir_reboot := reboot
|
|
||||||
dir_ninjhax := CakeBrah
|
|
||||||
dir_loader := loader
|
dir_loader := loader
|
||||||
|
dir_mset := CakeHax
|
||||||
|
dir_ninjhax := CakeBrah
|
||||||
|
dir_build := build
|
||||||
|
dir_out := out
|
||||||
|
|
||||||
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
ASFLAGS := -mlittle-endian -mcpu=arm946e-s -march=armv5te
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
|
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -fshort-wchar -std=c11 -Wno-main -O2 -ffast-math
|
||||||
@@ -37,7 +28,7 @@ objects_cfw = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|||||||
all: launcher a9lh ninjhax
|
all: launcher a9lh ninjhax
|
||||||
|
|
||||||
.PHONY: launcher
|
.PHONY: launcher
|
||||||
launcher: $(dir_out)/$(name).dat
|
launcher: $(dir_out)/$(name).dat
|
||||||
|
|
||||||
.PHONY: a9lh
|
.PHONY: a9lh
|
||||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||||
@@ -45,6 +36,9 @@ a9lh: $(dir_out)/arm9loaderhax.bin
|
|||||||
.PHONY: ninjhax
|
.PHONY: ninjhax
|
||||||
ninjhax: $(dir_out)/3ds/$(name)
|
ninjhax: $(dir_out)/3ds/$(name)
|
||||||
|
|
||||||
|
.PHONY: release
|
||||||
|
release: $(dir_out)/$(name).zip
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
@$(MAKE) $(FLAGS) -C $(dir_mset) clean
|
||||||
@@ -52,9 +46,12 @@ clean:
|
|||||||
@rm -rf $(dir_out) $(dir_build)
|
@rm -rf $(dir_out) $(dir_build)
|
||||||
@$(MAKE) -C $(dir_loader) clean
|
@$(MAKE) -C $(dir_loader) clean
|
||||||
|
|
||||||
|
$(dir_out):
|
||||||
|
@mkdir -p "$(dir_out)/aurei/payloads"
|
||||||
|
|
||||||
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out)
|
||||||
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
@$(MAKE) $(FLAGS) -C $(dir_mset) launcher
|
||||||
dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
@dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144
|
||||||
|
|
||||||
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out)
|
||||||
@cp -av $(dir_build)/main.bin $@
|
@cp -av $(dir_build)/main.bin $@
|
||||||
@@ -65,20 +62,20 @@ $(dir_out)/3ds/$(name): $(dir_out)
|
|||||||
@mv $(dir_out)/$(name).3dsx $@
|
@mv $(dir_out)/$(name).3dsx $@
|
||||||
@mv $(dir_out)/$(name).smdh $@
|
@mv $(dir_out)/$(name).smdh $@
|
||||||
|
|
||||||
$(dir_out):
|
$(dir_out)/$(name).zip: launcher a9lh ninjhax
|
||||||
@mkdir -p "$(dir_out)/aurei/payloads"
|
@cd $(dir_out) && zip -9 -r $(name) *
|
||||||
|
|
||||||
$(dir_build)/patches.h: $(dir_emu)/emuCode.s $(dir_reboot)/rebootCode.s
|
$(dir_build)/patches.h: $(dir_patches)/emunand.s $(dir_patches)/reboot.s
|
||||||
@mkdir -p "$(dir_build)"
|
@mkdir -p "$(dir_build)"
|
||||||
@armips $<
|
@armips $<
|
||||||
@mv emunand.bin $(dir_build)
|
|
||||||
@armips $(word 2,$^)
|
@armips $(word 2,$^)
|
||||||
@mv reboot.bin $(dir_build)
|
@mv emunand.bin reboot.bin $(dir_build)
|
||||||
@bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin
|
@bin2c -o $@ -n emunand $(dir_build)/emunand.bin -n reboot $(dir_build)/reboot.bin
|
||||||
|
|
||||||
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
$(dir_build)/loader.h: $(dir_loader)/Makefile
|
||||||
@$(MAKE) -C $(dir_loader)
|
@$(MAKE) -C $(dir_loader)
|
||||||
@bin2c -o $@ -n loader $(dir_loader)/loader.bin
|
@mv $(dir_loader)/loader.bin $(dir_build)
|
||||||
|
@bin2c -o $@ -n loader $(dir_build)/loader.bin
|
||||||
|
|
||||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||||
$(OC) -S -O binary $< $@
|
$(OC) -S -O binary $< $@
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
**Compiling:**
|
**Compiling:**
|
||||||
|
|
||||||
You'll need armips added to your Path. [HERE](https://www.dropbox.com/s/ceuv2qeqp38lpah/armips.exe?dl=0) is a pre-compiled version.
|
You'll need armips and [bin2c](https://sourceforge.net/projects/bin2c/) added to your Path. [HERE](http://www91.zippyshare.com/v/ePGpjk9r/file.html) is a pre-compiled version of armips.
|
||||||
|
|
||||||
Lastly, just run Make and everything should work!
|
Lastly, just run Make and everything should work!
|
||||||
|
|
||||||
@@ -13,12 +13,20 @@ Copy everything in 'out' folder to SD root and run!
|
|||||||
|
|
||||||
See https://github.com/Reisyukaku/ReiNand and http://gbatemp.net/threads/reinand-mod-o3ds-n3ds-sysnand.411110
|
See https://github.com/Reisyukaku/ReiNand and http://gbatemp.net/threads/reinand-mod-o3ds-n3ds-sysnand.411110
|
||||||
|
|
||||||
The FIRMs you need are here:
|
The FIRMs you need are [HERE](http://www99.zippyshare.com/v/kEIiQl0x/file.html).
|
||||||
|
|
||||||
http://www99.zippyshare.com/v/kEIiQl0x/file.html
|
|
||||||
|
|
||||||
**Credits:**
|
**Credits:**
|
||||||
|
|
||||||
Rei as this is 99% his code (this is no more than a mod)
|
Rei as this is mostly his code.
|
||||||
|
|
||||||
Everyone he credited on his GitHub :P
|
The offset to detect the console, and to calculate the O3DS NAND CTR are from Decrypt9.
|
||||||
|
|
||||||
|
tiniVi suggested me a way to detect a A9LH environment, and figured out screen deinit.
|
||||||
|
|
||||||
|
Delebile provided me with the FIRM writes blocking patch.
|
||||||
|
|
||||||
|
A skilled reverser gave me the new reboot patch.
|
||||||
|
|
||||||
|
The screen init code is from dark_samus, bil1s, Normmatt, delebile and everyone who contributed.
|
||||||
|
|
||||||
|
The code for printing to the screen is from CakesFW.
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
|
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
||||||
#define BUTTON_B (1 << 1)
|
#define BUTTON_B (1 << 1)
|
||||||
#define BUTTON_X (1 << 10)
|
#define BUTTON_X (1 << 10)
|
||||||
#define BUTTON_Y (1 << 11)
|
#define BUTTON_Y (1 << 11)
|
||||||
#define BUTTON_SELECT (1 << 2)
|
#define BUTTON_SELECT (1 << 2)
|
||||||
#define BUTTON_START (1 << 3)
|
#define BUTTON_START (1 << 3)
|
||||||
#define BUTTON_RIGHT (1 << 4)
|
#define BUTTON_RIGHT (1 << 4)
|
||||||
#define BUTTON_LEFT (1 << 5)
|
#define BUTTON_LEFT (1 << 5)
|
||||||
#define BUTTON_UP (1 << 6)
|
#define BUTTON_UP (1 << 6)
|
||||||
#define BUTTON_DOWN (1 << 7)
|
#define BUTTON_DOWN (1 << 7)
|
||||||
@@ -9,7 +9,7 @@ static u32 loadPayload(const char *path){
|
|||||||
unsigned int br;
|
unsigned int br;
|
||||||
if(f_open(&payload, path, FA_READ) == FR_OK)
|
if(f_open(&payload, path, FA_READ) == FR_OK)
|
||||||
{
|
{
|
||||||
f_read(&payload, (void*)PAYLOAD_ADDRESS, f_size(&payload), &br);
|
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
|
||||||
f_close(&payload);
|
f_close(&payload);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF)
|
#define HID_PAD (*(vu16 *)0x10146000 ^ 0xFFF)
|
||||||
#define BUTTON_R1 (1 << 8)
|
#define BUTTON_R1 (1 << 8)
|
||||||
#define BUTTON_L1 (1 << 9)
|
#define BUTTON_L1 (1 << 9)
|
||||||
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1)
|
#define BUTTON_A 1
|
||||||
#define BUTTON_A 1
|
#define BUTTON_B (1 << 1)
|
||||||
#define BUTTON_B (1 << 1)
|
#define BUTTON_UP (1 << 6)
|
||||||
#define BUTTON_UP (1 << 6)
|
#define BUTTON_DOWN (1 << 7)
|
||||||
#define BUTTON_DOWN (1 << 7)
|
#define BUTTON_START (1 << 3)
|
||||||
#define BUTTON_START (1 << 3)
|
#define BUTTON_SELECT (1 << 2)
|
||||||
#define BUTTON_SELECT (1 << 2)
|
#define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
|
||||||
#define SAFEMODE (BUTTON_L1R1 | BUTTON_A | (1 << 6))
|
#define PAYLOAD_BUTTONS ((BUTTON_L1 | BUTTON_A) ^ 0xFFF)
|
||||||
@@ -266,12 +266,12 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode){
|
|||||||
u8 slot = mode ? 0x16 : 0x15;
|
u8 slot = mode ? 0x16 : 0x15;
|
||||||
|
|
||||||
//Setup keys needed for arm9bin decryption
|
//Setup keys needed for arm9bin decryption
|
||||||
memcpy(keyY, arm9Section+0x10, 0x10);
|
memcpy(keyY, arm9Section + 0x10, 0x10);
|
||||||
memcpy(CTR, arm9Section+0x20, 0x10);
|
memcpy(CTR, arm9Section + 0x20, 0x10);
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
//http://stackoverflow.com/questions/12791077/atoi-implementation-in-c
|
||||||
for(u8 *tmp = arm9Section+0x30; *tmp; tmp++)
|
for(u8 *tmp = arm9Section + 0x30; *tmp; tmp++)
|
||||||
size = (size<<3)+(size<<1)+(*tmp)-'0';
|
size = (size << 3) + (size << 1) + (*tmp) - '0';
|
||||||
|
|
||||||
if(mode){
|
if(mode){
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
@@ -279,7 +279,7 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode){
|
|||||||
//Set 0x11 to key2 for the arm9bin and misc keys
|
//Set 0x11 to key2 for the arm9bin and misc keys
|
||||||
aes_setkey(0x11, 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(keyX, arm9Section+0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
aes(keyX, arm9Section + 0x60, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(slot, keyX, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,14 +288,14 @@ void decryptArm9Bin(u8 *arm9Section, u32 mode){
|
|||||||
aes_use_keyslot(slot);
|
aes_use_keyslot(slot);
|
||||||
|
|
||||||
//Decrypt arm9bin
|
//Decrypt arm9bin
|
||||||
aes(arm9Section+0x800, arm9Section+0x800, size/AES_BLOCK_SIZE, CTR, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(arm9Section + 0x800, arm9Section + 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(u8 *arm9Section){
|
void setKeyXs(u8 *arm9Section){
|
||||||
|
|
||||||
u8 *keyData = arm9Section+0x89814;
|
u8 *keyData = arm9Section + 0x89814;
|
||||||
u8 *decKey = keyData+0x10;
|
u8 *decKey = keyData + 0x10;
|
||||||
|
|
||||||
//Set keys 0x19..0x1F keyXs
|
//Set keys 0x19..0x1F keyXs
|
||||||
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x11, key2, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
@@ -303,6 +303,6 @@ void setKeyXs(u8 *arm9Section){
|
|||||||
for(u8 slot = 0x19; slot < 0x20; slot++){
|
for(u8 slot = 0x19; slot < 0x20; slot++){
|
||||||
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
aes(decKey, keyData, 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(slot, decKey, AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
*(keyData+0xF) += 1;
|
*(keyData + 0xF) += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ void loadSplash(void){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void drawCharacter(char character, int pos_x, int pos_y, u32 color){
|
void drawCharacter(char character, int pos_x, int pos_y, u32 color){
|
||||||
u8 *select = fb->top_left;
|
u8 *const select = fb->top_left;
|
||||||
|
|
||||||
for(int y = 0; y < 8; y++){
|
for(int y = 0; y < 8; y++){
|
||||||
unsigned char char_pos = font[character * 8 + y];
|
unsigned char char_pos = font[character * 8 + y];
|
||||||
|
|||||||
@@ -15,17 +15,21 @@ void getEmunandSect(u32 *off, u32 *head, u32 emuNAND){
|
|||||||
u32 nandOffset = emuNAND == 1 ? 0 :
|
u32 nandOffset = emuNAND == 1 ? 0 :
|
||||||
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
(nandSize > 0x200000 ? 0x400000 : 0x200000);
|
||||||
|
|
||||||
|
//Check for Gateway emuNAND
|
||||||
if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){
|
if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0){
|
||||||
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
|
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
|
||||||
*off = nandOffset;
|
*off = nandOffset;
|
||||||
*head = nandOffset + nandSize;
|
*head = nandOffset + nandSize;
|
||||||
|
}
|
||||||
|
//Check for RedNAND
|
||||||
|
else if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0){
|
||||||
|
if(*(u32 *)(temp + 0x100) == NCSD_MAGIC){
|
||||||
|
*off = nandOffset + 1;
|
||||||
|
*head = nandOffset + 1;
|
||||||
|
}
|
||||||
|
//Fallback to the first emuNAND if there's no second one
|
||||||
|
else if(emuNAND == 2) getEmunandSect(off, head, 1);
|
||||||
}
|
}
|
||||||
//Fallback to the first emuNAND if there's no second one
|
|
||||||
else if(emuNAND == 2) getEmunandSect(off, head, 1);
|
|
||||||
//Check if a RedNAND is present
|
|
||||||
else if(sdmmc_sdcard_readsectors(1, 1, temp) == 0)
|
|
||||||
if(*(u32 *)(temp + 0x100) != NCSD_MAGIC)
|
|
||||||
*head = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +38,7 @@ u32 getSDMMC(void *pos, u32 size){
|
|||||||
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
|
const unsigned char pattern[] = {0x21, 0x20, 0x18, 0x20};
|
||||||
const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
|
const u8 *off = (u8 *)memsearch(pos, pattern, size, 4) - 1;
|
||||||
|
|
||||||
return *(u32 *)(off+0x0A) + *(u32 *)(off+0x0E);
|
return *(u32 *)(off + 0x0A) + *(u32 *)(off + 0x0E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
||||||
@@ -45,16 +49,16 @@ void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff){
|
|||||||
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
*readOff = (u32)memsearch((void *)(*writeOff - 0x1000), pattern, 0x1000, 4) - 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getMPU(void *pos, u32 size){
|
u32 *getMPU(void *pos, u32 size){
|
||||||
//Look for MPU pattern
|
//Look for MPU pattern
|
||||||
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
const unsigned char pattern[] = {0x03, 0x00, 0x24, 0x00};
|
||||||
|
|
||||||
return memsearch(pos, pattern, size, 4);
|
return (u32 *)memsearch(pos, pattern, size, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset){
|
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset){
|
||||||
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
|
const unsigned char pattern[] = {0x00, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
//Looking for the last free space before Process9
|
//Looking for the last free space before Process9
|
||||||
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - (u8 *)pos)), 4) + 0xD;
|
return (u8 *)memsearch(pos, pattern, size - (size - (u32)(proc9Offset - pos)), 4) + 0xD;
|
||||||
}
|
}
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
void getEmunandSect(u32 *off, u32 *head, u32 emuNAND);
|
||||||
u32 getSDMMC(void *pos, u32 size);
|
u32 getSDMMC(void *pos, u32 size);
|
||||||
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
void getEmuRW(void *pos, u32 size, u32 *readOff, u32 *writeOff);
|
||||||
void *getMPU(void *pos, u32 size);
|
u32 *getMPU(void *pos, u32 size);
|
||||||
void *getEmuCode(void *pos, u32 size, u8 *proc9Offset);
|
void *getEmuCode(u8 *pos, u32 size, u8 *proc9Offset);
|
||||||
@@ -50,10 +50,13 @@ void setupCFW(void){
|
|||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
const char configPath[] = "aurei/config.bin";
|
const char configPath[] = "aurei/config.bin";
|
||||||
u16 config = 0;
|
u16 config = 0;
|
||||||
u32 needConfig = fileRead((u8 *)&config, configPath, 2) ? 1 : 2;
|
u32 needConfig = fileRead(&config, configPath, 2) ? 1 : 2;
|
||||||
|
|
||||||
//Determine if A9LH is installed
|
//Determine if A9LH is installed
|
||||||
if(a9lhBoot || (config >> 2) & 0x1){
|
if(a9lhBoot || (config >> 2) & 0x1){
|
||||||
|
if(pressed == SAFE_MODE)
|
||||||
|
error("Using Safe Mode would brick you, or remove A9LH!");
|
||||||
|
|
||||||
a9lhSetup = 1;
|
a9lhSetup = 1;
|
||||||
//Check setting for > 9.2 sysNAND
|
//Check setting for > 9.2 sysNAND
|
||||||
updatedSys = config & 0x1;
|
updatedSys = config & 0x1;
|
||||||
@@ -76,8 +79,10 @@ void setupCFW(void){
|
|||||||
|
|
||||||
if(needConfig){
|
if(needConfig){
|
||||||
|
|
||||||
//If L and R are pressed, chainload an external payload
|
/* If L and one of the payload buttons are pressed, and if not using A9LH
|
||||||
if((pressed & BUTTON_L1R1) == BUTTON_L1R1) loadPayload();
|
the Safe Mode combo is not pressed, chainload an external payload */
|
||||||
|
if((pressed & BUTTON_L1) && (pressed & PAYLOAD_BUTTONS) &&
|
||||||
|
pressed != SAFE_MODE) loadPayload();
|
||||||
|
|
||||||
//If no configuration file exists or SELECT is held, load configuration menu
|
//If no configuration file exists or SELECT is held, load configuration menu
|
||||||
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
if(needConfig == 2 || (pressed & BUTTON_SELECT))
|
||||||
@@ -86,13 +91,12 @@ void setupCFW(void){
|
|||||||
//If screens are inited, load splash screen
|
//If screens are inited, load splash screen
|
||||||
if(PDN_GPU_CNT != 0x1) loadSplash();
|
if(PDN_GPU_CNT != 0x1) loadSplash();
|
||||||
|
|
||||||
/* If L is pressed, and on an updated sysNAND setup the SAFE MODE combo
|
/* If L is pressed, boot 9.0 FIRM */
|
||||||
is not pressed, boot 9.0 FIRM */
|
if(pressed & BUTTON_L1) mode = 0;
|
||||||
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
|
/* 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 */
|
or R is pressed on a > 9.2 sysNAND, boot emuNAND */
|
||||||
if((updatedSys && (!mode || ((pressed & BUTTON_R1) && pressed != SAFEMODE))) ||
|
if((updatedSys && (!mode || (pressed & BUTTON_R1))) ||
|
||||||
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
(!updatedSys && mode && !(pressed & BUTTON_R1))){
|
||||||
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
//If not 9.0 FIRM and B is pressed, attempt booting the second emuNAND
|
||||||
if(mode && (pressed & BUTTON_B)) emuNAND = 2;
|
if(mode && (pressed & BUTTON_B)) emuNAND = 2;
|
||||||
@@ -112,7 +116,7 @@ void setupCFW(void){
|
|||||||
if(bootConfig != (config & 0xFF00)){
|
if(bootConfig != (config & 0xFF00)){
|
||||||
//Preserve user settings (first byte)
|
//Preserve user settings (first byte)
|
||||||
u16 tempConfig = ((config & 0xFF) | bootConfig);
|
u16 tempConfig = ((config & 0xFF) | bootConfig);
|
||||||
fileWrite((u8 *)&tempConfig, configPath, 2);
|
fileWrite(&tempConfig, configPath, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +148,7 @@ void loadFirm(void){
|
|||||||
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
|
(mode ? "/aurei/firmware.bin" : "/aurei/firmware90.bin");
|
||||||
firmSize = fileSize(path);
|
firmSize = fileSize(path);
|
||||||
if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
|
if(!firmSize) error("aurei/firmware(90).bin doesn't exist");
|
||||||
fileRead((u8 *)firmLocation, path, firmSize);
|
fileRead(firmLocation, path, firmSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
section = firmLocation->section;
|
section = firmLocation->section;
|
||||||
@@ -161,8 +165,8 @@ void loadFirm(void){
|
|||||||
//NAND redirection
|
//NAND redirection
|
||||||
static void loadEmu(u8 *proc9Offset){
|
static void loadEmu(u8 *proc9Offset){
|
||||||
|
|
||||||
u32 emuOffset = 1,
|
u32 emuOffset,
|
||||||
emuHeader = 1,
|
emuHeader = 0,
|
||||||
emuRead,
|
emuRead,
|
||||||
emuWrite;
|
emuWrite;
|
||||||
|
|
||||||
@@ -172,7 +176,7 @@ static void loadEmu(u8 *proc9Offset){
|
|||||||
//No emuNAND detected
|
//No emuNAND detected
|
||||||
if(!emuHeader) error("No emuNAND has been detected");
|
if(!emuHeader) error("No emuNAND has been detected");
|
||||||
|
|
||||||
//Copy the emuNAND patch
|
//Copy emuNAND code
|
||||||
void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset);
|
void *emuCodeOffset = getEmuCode(arm9Section, section[2].size, proc9Offset);
|
||||||
memcpy(emuCodeOffset, emunand, emunand_size);
|
memcpy(emuCodeOffset, emunand, emunand_size);
|
||||||
|
|
||||||
@@ -187,17 +191,23 @@ static void loadEmu(u8 *proc9Offset){
|
|||||||
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
*pos_sdmmc = getSDMMC(arm9Section, section[2].size);
|
||||||
|
|
||||||
//Calculate offset for the hooks
|
//Calculate offset for the hooks
|
||||||
*(u32 *)(nandRedir + 4) = (u32)emuCodeOffset - (u32)firmLocation -
|
u32 branchOffset = (u32)emuCodeOffset - (u32)firmLocation -
|
||||||
section[2].offset + (u32)section[2].address;
|
section[2].offset + (u32)section[2].address;
|
||||||
|
|
||||||
//Add emunand hooks
|
//Add emunand hooks
|
||||||
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
getEmuRW(arm9Section, section[2].size, &emuRead, &emuWrite);
|
||||||
memcpy((void *)emuRead, nandRedir, sizeof(nandRedir));
|
*(u16 *)emuRead = nandRedir[0];
|
||||||
memcpy((void *)emuWrite, nandRedir, sizeof(nandRedir));
|
*((u16 *)emuRead + 1) = nandRedir[1];
|
||||||
|
*((u32 *)emuRead + 1) = branchOffset;
|
||||||
|
*(u16 *)emuWrite = nandRedir[0];
|
||||||
|
*((u16 *)emuWrite + 1) = nandRedir[1];
|
||||||
|
*((u32 *)emuWrite + 1) = branchOffset;
|
||||||
|
|
||||||
//Set MPU for emu code region
|
//Set MPU for emu code region
|
||||||
void *mpuOffset = getMPU(arm9Section, section[2].size);
|
u32 *mpuOffset = getMPU(arm9Section, section[2].size);
|
||||||
memcpy(mpuOffset, mpu, sizeof(mpu));
|
*mpuOffset = mpuPatch[0];
|
||||||
|
*(mpuOffset + 6) = mpuPatch[1];
|
||||||
|
*(mpuOffset + 9) = mpuPatch[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Patches
|
//Patches
|
||||||
@@ -215,13 +225,17 @@ void patchFirm(void){
|
|||||||
|
|
||||||
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
|
//Patch FIRM reboots, not on 9.0 FIRM as it breaks firmlaunchhax
|
||||||
if(mode){
|
if(mode){
|
||||||
//Read reboot code from SD
|
//Calculate offset for the firmlaunch code
|
||||||
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
void *rebootOffset = getReboot(arm9Section, section[2].size);
|
||||||
|
//Calculate offset for the fOpen function
|
||||||
|
u32 fOpenOffset = getfOpen(proc9Offset, rebootOffset);
|
||||||
|
|
||||||
|
//Copy firmlaunch code
|
||||||
memcpy(rebootOffset, reboot, reboot_size);
|
memcpy(rebootOffset, reboot, reboot_size);
|
||||||
|
|
||||||
//Calculate the fOpen offset and put it in the right location
|
//Put the fOpen offset in the right location
|
||||||
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
u32 *pos_fopen = (u32 *)memsearch(rebootOffset, "OPEN", reboot_size, 4);
|
||||||
*pos_fopen = getfOpen(arm9Section, section[2].size, proc9Offset);
|
*pos_fopen = fOpenOffset;
|
||||||
|
|
||||||
//Patch path for emuNAND-patched FIRM
|
//Patch path for emuNAND-patched FIRM
|
||||||
if(emuNAND){
|
if(emuNAND){
|
||||||
@@ -233,8 +247,9 @@ void patchFirm(void){
|
|||||||
|
|
||||||
if(a9lhSetup && !emuNAND){
|
if(a9lhSetup && !emuNAND){
|
||||||
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
//Patch FIRM partitions writes on sysNAND to protect A9LH
|
||||||
void *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
u16 *writeOffset = getFirmWrite(arm9Section, section[2].size);
|
||||||
memcpy(writeOffset, writeBlock, sizeof(writeBlock));
|
*writeOffset = writeBlock[0];
|
||||||
|
*(writeOffset + 1) = writeBlock[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disable signature checks
|
//Disable signature checks
|
||||||
@@ -242,8 +257,9 @@ void patchFirm(void){
|
|||||||
sigOffset2;
|
sigOffset2;
|
||||||
|
|
||||||
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
|
getSignatures(firmLocation, firmSize, &sigOffset, &sigOffset2);
|
||||||
memcpy((void *)sigOffset, sigPat1, sizeof(sigPat1));
|
*(u16 *)sigOffset = sigPatch[0];
|
||||||
memcpy((void *)sigOffset2, sigPat2, sizeof(sigPat2));
|
*(u16 *)sigOffset2 = sigPatch[0];
|
||||||
|
*((u16 *)sigOffset2 + 1) = sigPatch[1];
|
||||||
|
|
||||||
//Patch ARM9 entrypoint on N3DS to skip arm9loader
|
//Patch ARM9 entrypoint on N3DS to skip arm9loader
|
||||||
if(console)
|
if(console)
|
||||||
@@ -251,7 +267,7 @@ void patchFirm(void){
|
|||||||
|
|
||||||
//Write patched FIRM to SD if needed
|
//Write patched FIRM to SD if needed
|
||||||
if(selectedFirm)
|
if(selectedFirm)
|
||||||
if(!fileWrite((u8 *)firmLocation, patchedFirms[selectedFirm - 1], firmSize))
|
if(!fileWrite(firmLocation, patchedFirms[selectedFirm - 1], firmSize))
|
||||||
error("Couldn't write the patched FIRM (no free space?)");
|
error("Couldn't write the patched FIRM (no free space?)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ u32 mountSD(void){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fileRead(u8 *dest, const char *path, u32 size){
|
u32 fileRead(void *dest, const char *path, u32 size){
|
||||||
FRESULT fr;
|
FRESULT fr;
|
||||||
FIL fp;
|
FIL fp;
|
||||||
unsigned int br = 0;
|
unsigned int br = 0;
|
||||||
@@ -29,7 +29,7 @@ u32 fileRead(u8 *dest, const char *path, u32 size){
|
|||||||
return fr ? 0 : 1;
|
return fr ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fileWrite(const u8 *buffer, const char *path, u32 size){
|
u32 fileWrite(const void *buffer, const char *path, u32 size){
|
||||||
FRESULT fr;
|
FRESULT fr;
|
||||||
FIL fp;
|
FIL fp;
|
||||||
unsigned int br = 0;
|
unsigned int br = 0;
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
u32 mountSD(void);
|
u32 mountSD(void);
|
||||||
u32 fileRead(u8 *dest, const char *path, u32 size);
|
u32 fileRead(void *dest, const char *path, u32 size);
|
||||||
u32 fileWrite(const u8 *buffer, const char *path, u32 size);
|
u32 fileWrite(const void *buffer, const char *path, u32 size);
|
||||||
u32 fileSize(const char *path);
|
u32 fileSize(const char *path);
|
||||||
u32 fileExists(const char *path);
|
u32 fileExists(const char *path);
|
||||||
void fileDelete(const char *path);
|
void fileDelete(const char *path);
|
||||||
@@ -36,8 +36,7 @@ int memcmp(const void *buf1, const void *buf2, u32 size){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){
|
void *memsearch(void *start_pos, const void *search, u32 size, u32 size_search){
|
||||||
for(void *pos = start_pos + size - size_search; pos >= start_pos; pos--){
|
for(u8 *pos = (u8 *)start_pos + size - size_search; pos >= (u8 *)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;
|
||||||
}
|
}
|
||||||
@@ -11,19 +11,13 @@
|
|||||||
* Patches
|
* Patches
|
||||||
**************************************************/
|
**************************************************/
|
||||||
|
|
||||||
const u8 mpu[0x2C] = {
|
const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
|
||||||
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,
|
|
||||||
0x01, 0x01, 0x01, 0x01, 0x03, 0x06, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x08
|
|
||||||
};
|
|
||||||
|
|
||||||
//Branch to emunand function. To be filled in
|
const u16 nandRedir[2] = {0x4C00, 0x47A0};
|
||||||
u8 nandRedir[0x08] = {0x00, 0x4C, 0xA0, 0x47, 0x00, 0x00, 0x00, 0x00};
|
|
||||||
|
|
||||||
const u8 sigPat1[2] = {0x00, 0x20};
|
const u16 sigPatch[2] = {0x2000, 0x4770};
|
||||||
const u8 sigPat2[4] = {0x00, 0x20, 0x70, 0x47};
|
|
||||||
|
|
||||||
const u8 writeBlock[4] = {0x00, 0x20, 0xC0, 0x46};
|
const u16 writeBlock[2] = {0x2000, 0x46C0};
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
@@ -49,22 +43,20 @@ void *getReboot(void *pos, u32 size){
|
|||||||
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
|
return (u8 *)memsearch(pos, pattern, size, 4) - 0x10;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset){
|
u32 getfOpen(u8 *proc9Offset, void *rebootOffset){
|
||||||
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
//Offset Process9 code gets loaded to in memory (defined in ExHeader)
|
||||||
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
u32 p9MemAddr = *(u32 *)(proc9Offset + 0xC);
|
||||||
//Start of Process9 .code section (start of NCCH + ExeFS offset + ExeFS header size)
|
//Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
|
||||||
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
u32 p9CodeOff = (u32)(proc9Offset - 0x204) + (*(u32 *)(proc9Offset - 0x64) * 0x200) + 0x200;
|
||||||
|
|
||||||
//Calculate fOpen
|
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||||
const unsigned char pattern[] = {0xB0, 0x04, 0x98, 0x0D};
|
return (u32)rebootOffset + 9 - (-((*(u32 *)rebootOffset & 0x00FFFFFF) << 2) & 0xFFFFF) - p9CodeOff + p9MemAddr;
|
||||||
|
|
||||||
return (u32)memsearch(pos, pattern, size, 4) - 2 - p9CodeOff + p9MemAddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getFirmWrite(void *pos, u32 size){
|
u16 *getFirmWrite(void *pos, u32 size){
|
||||||
//Look for FIRM writing code
|
//Look for FIRM writing code
|
||||||
u8 *firmwrite = (u8 *)memsearch(pos, "exe:", size, 4);
|
u8 *const off = (u8 *)memsearch(pos, "exe:", size, 4);
|
||||||
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
const unsigned char pattern[] = {0x00, 0x28, 0x01, 0xDA};
|
||||||
|
|
||||||
return memsearch(firmwrite - 0x100, pattern, 0x100, 4);
|
return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
|
||||||
}
|
}
|
||||||
@@ -11,11 +11,10 @@
|
|||||||
/**************************************************
|
/**************************************************
|
||||||
* Patches
|
* Patches
|
||||||
**************************************************/
|
**************************************************/
|
||||||
const u8 mpu[0x2C];
|
const u32 mpuPatch[3];
|
||||||
u8 nandRedir[0x08];
|
const u16 nandRedir[2];
|
||||||
const u8 sigPat1[2];
|
const u16 sigPatch[2];
|
||||||
const u8 sigPat2[4];
|
const u16 writeBlock[2];
|
||||||
const u8 writeBlock[4];
|
|
||||||
|
|
||||||
/**************************************************
|
/**************************************************
|
||||||
* Functions
|
* Functions
|
||||||
@@ -23,5 +22,5 @@ const u8 writeBlock[4];
|
|||||||
u8 *getProc9(void *pos, u32 size);
|
u8 *getProc9(void *pos, u32 size);
|
||||||
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
void getSignatures(void *pos, u32 size, u32 *off, u32 *off2);
|
||||||
void *getReboot(void *pos, u32 size);
|
void *getReboot(void *pos, u32 size);
|
||||||
u32 getfOpen(void *pos, u32 size, u8 *proc9Offset);
|
u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
|
||||||
void *getFirmWrite(void *pos, u32 size);
|
u16 *getFirmWrite(void *pos, u32 size);
|
||||||
@@ -46,8 +46,8 @@ void initScreens(void){
|
|||||||
*(vu32 *)0x10141200 = 0x1007F;
|
*(vu32 *)0x10141200 = 0x1007F;
|
||||||
*(vu32 *)0x10202014 = 0x00000001;
|
*(vu32 *)0x10202014 = 0x00000001;
|
||||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||||
*(vu32 *)0x10202240 = 0x39;
|
*(vu32 *)0x10202240 = 0x45;
|
||||||
*(vu32 *)0x10202A40 = 0x39;
|
*(vu32 *)0x10202A40 = 0x45;
|
||||||
*(vu32 *)0x10202244 = 0x1023E;
|
*(vu32 *)0x10202244 = 0x1023E;
|
||||||
*(vu32 *)0x10202A44 = 0x1023E;
|
*(vu32 *)0x10202A44 = 0x1023E;
|
||||||
|
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ static u16 waitInput(void){
|
|||||||
for(u32 i = 0x13000; i; i--){
|
for(u32 i = 0x13000; i; i--){
|
||||||
if (key != HID_PAD)
|
if (key != HID_PAD)
|
||||||
break;
|
break;
|
||||||
if(i==1) pressedkey = 1;
|
if(i == 1) pressedkey = 1;
|
||||||
}
|
}
|
||||||
} while (!pressedkey);
|
} while(!pressedkey);
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ void configureCFW(const char *configPath){
|
|||||||
|
|
||||||
//Read and parse the existing configuration
|
//Read and parse the existing configuration
|
||||||
u16 tempConfig = 0;
|
u16 tempConfig = 0;
|
||||||
fileRead((u8 *)&tempConfig, configPath, 2);
|
fileRead(&tempConfig, configPath, 2);
|
||||||
for(u32 i = 0; i < OPTIONS; i++)
|
for(u32 i = 0; i < OPTIONS; i++)
|
||||||
options.enabled[i] = (tempConfig >> i) & 0x1;
|
options.enabled[i] = (tempConfig >> i) & 0x1;
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ void configureCFW(const char *configPath){
|
|||||||
//Parse and write the selected options
|
//Parse and write the selected options
|
||||||
for(u32 i = 0; i < OPTIONS; i++)
|
for(u32 i = 0; i < OPTIONS; i++)
|
||||||
tempConfig |= options.enabled[i] << i;
|
tempConfig |= options.enabled[i] << i;
|
||||||
fileWrite((u8 *)&tempConfig, configPath, 2);
|
fileWrite(&tempConfig, configPath, 2);
|
||||||
|
|
||||||
//Reboot
|
//Reboot
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||||
|
|||||||
Reference in New Issue
Block a user