From 78111b5dc7b8dc814ce80b349339391daa2c041a Mon Sep 17 00:00:00 2001 From: Aurora Date: Thu, 24 Mar 2016 00:14:29 +0100 Subject: [PATCH] Cleaned Makefile, added confirmation prompt on stage2 install, SD unmounting/remounting wheh coming back to menu after stage2 install --- .gitignore | 2 -- Makefile | 26 +++++++------- source/crypto.c | 8 ++--- source/crypto.h | 2 +- source/fs.c | 5 +++ source/fs.h | 1 + source/installer.c | 86 ++++++++++++++++++++++++++------------------- source/installer.h | 18 +++++----- source/main.c | 6 +--- source/screeninit.c | 12 ++++--- source/screeninit.h | 4 ++- source/utils.c | 9 ++--- source/utils.h | 5 +++ 13 files changed, 105 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index 65bdbc0..a05904a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ out -CakeHax -CakeBrah build *.bin *.3dsx diff --git a/Makefile b/Makefile index cbc8a97..3ee2c53 100644 --- a/Makefile +++ b/Makefile @@ -4,21 +4,14 @@ CC := arm-none-eabi-gcc AS := arm-none-eabi-as LD := arm-none-eabi-ld 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 := SafeA9LHInstaller dir_source := source -dir_build := build dir_mset := CakeHax -dir_out := out dir_ninjhax := CakeBrah +dir_build := build +dir_out := out 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 @@ -41,26 +34,35 @@ a9lh: $(dir_out)/arm9loaderhax.bin .PHONY: ninjhax ninjhax: $(dir_out)/3ds/$(name) +.PHONY: release +release: $(dir_out)/$(name).zip + .PHONY: clean clean: @$(MAKE) $(FLAGS) -C $(dir_mset) clean @$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean @rm -rf $(dir_out) $(dir_build) -$(dir_out)/$(name).dat: $(dir_build)/main.bin +$(dir_out): + @mkdir -p "$(dir_out)" + +$(dir_out)/$(name).dat: $(dir_build)/main.bin $(dir_out) @mkdir -p $(dir_out) @$(MAKE) $(FLAGS) -C $(dir_mset) launcher dd if=$(dir_build)/main.bin of=$@ bs=512 seek=144 -$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin +$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin $(dir_out) @cp -av $(dir_build)/main.bin $@ -$(dir_out)/3ds/$(name): +$(dir_out)/3ds/$(name): $(dir_out) @mkdir -p $(dir_out)/3ds/$(name) @$(MAKE) $(FLAGS) -C $(dir_ninjhax) @mv $(dir_out)/$(name).3dsx $@ @mv $(dir_out)/$(name).smdh $@ +$(dir_out)/$(name).zip: launcher a9lh ninjhax + @cd $(dir_out) && zip -9 -r $(name) * + $(dir_build)/main.bin: $(dir_build)/main.elf $(OC) -S -O binary $< $@ diff --git a/source/crypto.c b/source/crypto.c index 346f78f..c3a0ad3 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -349,16 +349,16 @@ void generateSector(u8 *keySector){ } //Test the OTP to be correct by verifying key2 -u32 testOtp(u32 a9lhBoot){ +u32 testOtp(u32 a9lhBoot, void *tempOffset){ //Read keysector from NAND - sdmmc_nand_readsectors(0x96, 0x1, (vu8 *)0x24500000); + sdmmc_nand_readsectors(0x96, 0x1, (vu8 *)tempOffset); //Decrypt key2 aes_use_keyslot(0x11); - aes((void *)0x24500000 + 0x10, (void *)0x24500000 + 0x10, 1, NULL, AES_ECB_DECRYPT_MODE, 0); + aes((void *)tempOffset + 0x10, (void *)tempOffset + 0x10, 1, NULL, AES_ECB_DECRYPT_MODE, 0); //Test key2 - if(memcmp((void *)0x24500000 + 0x10, a9lhBoot ? a9lhKey2 : key2, 0x10) != 0) return 0; + if(memcmp((void *)tempOffset + 0x10, a9lhBoot ? a9lhKey2 : key2, 0x10) != 0) return 0; return 1; } diff --git a/source/crypto.h b/source/crypto.h index 9b81594..da86adb 100755 --- a/source/crypto.h +++ b/source/crypto.h @@ -81,5 +81,5 @@ void readFirm0(u8 *outbuf, u32 size); void writeFirm(u8 *inbuf, u32 offset, u32 size); void setupKeyslot0x11(u32 a9lhBoot, const u8 *otp); void generateSector(u8 *keySector); -u32 testOtp(u32 a9lhBoot); +u32 testOtp(u32 a9lhBoot, void *tempOffset); u32 verifyHash(const void *data, u32 size, const u8 *hash); \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index 766ad52..57b9442 100644 --- a/source/fs.c +++ b/source/fs.c @@ -12,6 +12,11 @@ u32 mountSD(void){ return 1; } +u32 unmountSD(void){ + if(f_mount(NULL, "0:", 1) != FR_OK) return 0; + return 1; +} + u32 fileRead(u8 *dest, const char *path, u32 size){ FRESULT fr; FIL fp; diff --git a/source/fs.h b/source/fs.h index 1e5ede8..2de6ebc 100644 --- a/source/fs.h +++ b/source/fs.h @@ -7,5 +7,6 @@ #include "types.h" u32 mountSD(void); +u32 unmountSD(void); u32 fileRead(u8 *dest, const char *path, u32 size); u32 fileSize(const char *path); \ No newline at end of file diff --git a/source/installer.c b/source/installer.c index fa63575..03932f1 100755 --- a/source/installer.c +++ b/source/installer.c @@ -21,20 +21,23 @@ static const u8 firm1Hash[0x20] = { 0x2D, 0x3D, 0x56, 0x6C, 0x6A, 0x1A, 0x8E, 0x52, 0x54, 0xE3, 0x89, 0xC2, 0x95, 0x06, 0x23, 0xE5 }; -static const char *path; -static u32 size; int pos_y; static void installStage2(u32 mode){ //Read stage2 - path = "a9lh/payload_stage2.bin"; - size = fileSize(path); - if(!size || size > MAXSTAGE2SIZE) + const char path[] = "a9lh/payload_stage2.bin"; + u32 size = fileSize(path); + if(!size || size > MAX_STAGE2_SIZE) shutdown(1, "Error: stage2.bin doesn't exist or exceeds\nmax size"); - memset((u8 *)STAGE2OFFSET, 0, MAXSTAGE2SIZE); - fileRead((u8 *)STAGE2OFFSET, path, size); + memset((u8 *)STAGE2_OFFSET, 0, MAX_STAGE2_SIZE); + fileRead((u8 *)STAGE2_OFFSET, path, size); + if(mode) return; - sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2OFFSET); + + sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2_OFFSET); + + //Unmount the SD card + unmountSD(); shutdown(2, "Stage2 update: success!"); } @@ -46,63 +49,74 @@ void installer(void){ while(1){ clearScreens(); - drawString("Safe A9LH Installer v1.3", 10, 10, 0xff9900); - pos_y = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, 0xFFFFFF); - pos_y = drawString("Press SELECT for a full install", 10, pos_y + SPACING_VERT, 0xFFFFFF); - if(a9lhBoot){ pos_y = drawString("Press START to only update stage2", 10, pos_y, 0xFFFFFF); - pos_y = drawString("(Only do stage2 updates from the fork you use!)", 10, pos_y, 0x0000FF); } - pos_y = drawString("Press any other button to shutdown", 10, pos_y, 0xFFFFFF); + drawString("Safe A9LH Installer v1.3.1", 10, 10, COLOR_TITLE); + pos_y = drawString("Thanks to delebile, #cakey and StandardBus", 10, 40, COLOR_WHITE); + pos_y = drawString("Press SELECT for a full install", 10, pos_y + SPACING_VERT, COLOR_WHITE); + if(a9lhBoot){ pos_y = drawString("Press START to only update stage2", 10, pos_y, COLOR_WHITE); + pos_y = drawString("(Only do stage2 updates from the fork you use!)", 10, pos_y, COLOR_RED); } + pos_y = drawString("Press any other button to shutdown", 10, pos_y, COLOR_WHITE); u16 pressed = waitInput(); - if(a9lhBoot && pressed == BUTTON_START) installStage2(0); + if(a9lhBoot && pressed == BUTTON_START){ + pos_y = drawString("Stage2 update: are you sure? Press A to confirm", 10, pos_y + SPACING_VERT, COLOR_RED); + if(waitInput() == BUTTON_A){ + mountSD(); + installStage2(0); + } + } else if(pressed == BUTTON_SELECT) break; else shutdown(0, NULL); } + //Mount the SD card + mountSD(); + + const char *path; + //If making a first install, we need the OTP if(!a9lhBoot){ //Read OTP path = "a9lh/otp.bin"; if(fileSize(path) != 256) shutdown(1, "Error: otp.bin doesn't exist or has a wrong size"); - fileRead((u8 *)OTPOFFSET, path, 256); + fileRead((u8 *)OTP_OFFSET, path, 256); } //Setup the key sector de/encryption with the SHA register or otp.bin - setupKeyslot0x11(a9lhBoot, (u8 *)OTPOFFSET); + setupKeyslot0x11(a9lhBoot, (u8 *)OTP_OFFSET); - if(a9lhBoot && !testOtp(a9lhBoot)) + if(a9lhBoot && !testOtp(a9lhBoot, (void *)TEMP_OFFSET)) shutdown(1, "Error: the OTP hash is invalid"); - if(!a9lhBoot && console && !testOtp(a9lhBoot)) + if(!a9lhBoot && console && !testOtp(a9lhBoot, (void *)TEMP_OFFSET)) shutdown(1, "Error: otp.bin is invalid or corrupted"); //Calculate the CTR for the 3DS partitions getNandCTR(); //Test that the CTR is correct - readFirm0((u8 *)TEMPOFFSET, 0x200); - if(memcmp((void *)TEMPOFFSET, "FIRM", 4) != 0) + readFirm0((u8 *)TEMP_OFFSET, 0x200); + if(memcmp((void *)TEMP_OFFSET, "FIRM", 4) != 0) shutdown(1, "Error: failed to setup FIRM encryption"); //Read decrypted key sector path = "a9lh/secret_sector.bin"; if(fileSize(path) != 0x200) shutdown(1, "Error: secret_sector.bin doesn't exist or has\na wrong size"); - fileRead((u8 *)SECTOROFFSET, path, 0x200); - if(!verifyHash((u8 *)SECTOROFFSET, 0x200, sectorHash)) + fileRead((u8 *)SECTOR_OFFSET, path, 0x200); + if(!verifyHash((u8 *)SECTOR_OFFSET, 0x200, sectorHash)) shutdown(1, "Error: secret_sector.bin is invalid or corrupted"); //Generate and encrypt a per-console A9LH key sector - generateSector((void *)SECTOROFFSET); + generateSector((void *)SECTOR_OFFSET); //Read FIRM0 path = "a9lh/firm0.bin"; u32 firm0Size = fileSize(path); if(!firm0Size) shutdown(1, "Error: firm0.bin doesn't exist"); - fileRead((u8 *)FIRM0OFFSET, path, firm0Size); - if(!verifyHash((u8 *)FIRM0OFFSET, firm0Size, firm0Hash)) + fileRead((u8 *)FIRM0_OFFSET, path, firm0Size); + if(!verifyHash((u8 *)FIRM0_OFFSET, firm0Size, firm0Hash)) shutdown(1, "Error: firm0.bin is invalid or corrupted"); //Read FIRM1 @@ -110,26 +124,26 @@ void installer(void){ u32 firm1Size = fileSize(path); if(!firm1Size) shutdown(1, "Error: firm1.bin doesn't exist"); - fileRead((u8 *)FIRM1OFFSET, path, firm1Size); - if(!verifyHash((u8 *)FIRM1OFFSET, firm1Size, firm1Hash)) + fileRead((u8 *)FIRM1_OFFSET, path, firm1Size); + if(!verifyHash((u8 *)FIRM1_OFFSET, firm1Size, firm1Hash)) shutdown(1, "Error: firm1.bin is invalid or corrupted"); //Inject stage1 path = "a9lh/payload_stage1.bin"; - size = fileSize(path); - if(!size || size > MAXSTAGE1SIZE) + u32 size = fileSize(path); + if(!size || size > MAX_STAGE1_SIZE) shutdown(1, "Error: stage1.bin doesn't exist or exceeds\nmax size"); - fileRead((u8 *)STAGE1OFFSET, path, size); + fileRead((u8 *)STAGE1_OFFSET, path, size); installStage2(1); - pos_y = drawString("All checks passed, installing...", 10, pos_y + SPACING_VERT, 0xFFFFFF); + pos_y = drawString("All checks passed, installing...", 10, pos_y + SPACING_VERT, COLOR_WHITE); //Point of no return, install stuff in the safest order - sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2OFFSET); - writeFirm((u8 *)FIRM1OFFSET, 1, firm1Size); - writeFirm((u8 *)FIRM0OFFSET, 0, firm0Size); - sdmmc_nand_writesectors(0x96, 0x1, (vu8 *)SECTOROFFSET); + sdmmc_nand_writesectors(0x5C000, 0x20, (vu8 *)STAGE2_OFFSET); + writeFirm((u8 *)FIRM1_OFFSET, 1, firm1Size); + writeFirm((u8 *)FIRM0_OFFSET, 0, firm0Size); + sdmmc_nand_writesectors(0x96, 0x1, (vu8 *)SECTOR_OFFSET); shutdown(1, "Full install: success!"); } \ No newline at end of file diff --git a/source/installer.h b/source/installer.h index 74a837b..4106716 100644 --- a/source/installer.h +++ b/source/installer.h @@ -5,14 +5,14 @@ #define PDN_MPCORE_CFG (*(vu8 *)0x10140FFC) #define PDN_SPI_CNT (*(vu8 *)0x101401C0) -#define OTPOFFSET 0x24000000 -#define SECTOROFFSET 0x24100000 -#define FIRM0OFFSET 0x24200000 -#define FIRM1OFFSET 0x24300000 -#define STAGE1OFFSET FIRM0OFFSET + 0xF0400 -#define STAGE2OFFSET 0x24400000 -#define MAXSTAGE1SIZE 0x1C00 -#define MAXSTAGE2SIZE 0x2800 -#define TEMPOFFSET 0x24500000 +#define OTP_OFFSET 0x24000000 +#define SECTOR_OFFSET 0x24100000 +#define FIRM0_OFFSET 0x24200000 +#define FIRM1_OFFSET 0x24300000 +#define STAGE1_OFFSET FIRM0_OFFSET + 0xF0400 +#define STAGE2_OFFSET 0x24400000 +#define MAX_STAGE1_SIZE 0x1C00 +#define MAX_STAGE2_SIZE 0x2800 +#define TEMP_OFFSET 0x24500000 void installer(void); \ No newline at end of file diff --git a/source/main.c b/source/main.c index 7fa16e6..72e65a0 100644 --- a/source/main.c +++ b/source/main.c @@ -6,15 +6,11 @@ * Minimalist CFW for N3DS */ -#include "fs.h" #include "installer.h" #include "screeninit.h" #include "types.h" -#define PDN_GPU_CNT (*(vu8 *)0x10141200) - void main(void){ - mountSD(); - if(PDN_GPU_CNT == 0x1) initLCD(); + initScreens(); installer(); } \ No newline at end of file diff --git a/source/screeninit.c b/source/screeninit.c index 81600da..99d3e7f 100644 --- a/source/screeninit.c +++ b/source/screeninit.c @@ -1,7 +1,7 @@ #include "screeninit.h" #include "i2c.h" -void initLCD(void){ +void initScreens(void){ vu32 *const arm11 = (vu32 *)0x1FFFFFF8; void __attribute__((naked)) ARM11(void){ @@ -9,8 +9,8 @@ void initLCD(void){ *(vu32 *)0x10141200 = 0x1007F; *(vu32 *)0x10202014 = 0x00000001; *(vu32 *)0x1020200C &= 0xFFFEFFFE; - *(vu32 *)0x10202240 = 0x39; - *(vu32 *)0x10202A40 = 0x39; + *(vu32 *)0x10202240 = 0x45; + *(vu32 *)0x10202A40 = 0x45; *(vu32 *)0x10202244 = 0x1023E; *(vu32 *)0x10202A44 = 0x1023E; @@ -103,6 +103,8 @@ void initLCD(void){ while(1); } - *arm11 = (u32)ARM11; - while(*arm11); + if(PDN_GPU_CNT == 0x1){ + *arm11 = (u32)ARM11; + while(*arm11); + } } \ No newline at end of file diff --git a/source/screeninit.h b/source/screeninit.h index 15f9cec..6e3e6f7 100644 --- a/source/screeninit.h +++ b/source/screeninit.h @@ -2,4 +2,6 @@ #include "types.h" -void initLCD(void); \ No newline at end of file +#define PDN_GPU_CNT (*(vu8 *)0x10141200) + +void initScreens(void); \ No newline at end of file diff --git a/source/utils.c b/source/utils.c index 8e710dc..de2c171 100755 --- a/source/utils.c +++ b/source/utils.c @@ -27,11 +27,12 @@ u16 waitInput(void){ void shutdown(u32 mode, char *message){ if(mode){ - pos_y = drawString(message, 10, pos_y + SPACING_VERT, 0xFFFFFF); - if(mode == 1) drawString("Press any button to shutdown", 10, pos_y, 0xFFFFFF); + pos_y = drawString(message, 10, pos_y + SPACING_VERT, COLOR_WHITE); + if(mode == 1) drawString("Press any button to shutdown", 10, pos_y, COLOR_WHITE); else { - pos_y = drawString("Press START or SELECT to return to menu", 10, pos_y, 0x0000FF); - pos_y = drawString("Press any other button to shutdown", 10, pos_y, 0xFFFFFF); + pos_y = drawString("Press START or SELECT to return to menu", 10, pos_y, COLOR_RED); + pos_y = drawString("(SD will be unmounted until the next install)", 10, pos_y, COLOR_RED); + pos_y = drawString("Press any other button to shutdown", 10, pos_y, COLOR_WHITE); } u16 pressed = waitInput(); if(mode == 2 && (pressed & (BUTTON_START | BUTTON_SELECT))) return; diff --git a/source/utils.h b/source/utils.h index 0515171..d94981f 100644 --- a/source/utils.h +++ b/source/utils.h @@ -5,6 +5,11 @@ #define HID_PAD ((~*(vu16 *)0x10146000) & 0xFFF) #define BUTTON_START (1 << 3) #define BUTTON_SELECT (1 << 2) +#define BUTTON_A 1 + +#define COLOR_TITLE 0xFF9900 +#define COLOR_WHITE 0xFFFFFF +#define COLOR_RED 0x0000FF extern int pos_y;