diff --git a/Makefile b/Makefile index 60b225a..9be1e1f 100644 --- a/Makefile +++ b/Makefile @@ -15,8 +15,6 @@ name := SafeA9LHInstaller revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i') dir_source := source -dir_loader := loader -dir_arm11 := arm11 dir_cakehax := CakeHax dir_cakebrah := CakeBrah dir_build := build @@ -31,14 +29,6 @@ objects= $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/loader.bin.o $(dir_build)/arm11.bin.o - -define bin2o - bin2s $< | $(AS) -o $(@) - echo "extern const u8" `(echo $(> $(dir_build)/bundled.h - echo "extern const u32" `(echo $(> $(dir_build)/bundled.h -endef - .PHONY: all all: launcher a9lh cakebrah @@ -56,8 +46,6 @@ release: $(dir_out)/$(name)$(revision).7z .PHONY: clean clean: - @$(MAKE) -C $(dir_loader) clean - @$(MAKE) -C $(dir_arm11) clean @$(MAKE) $(FLAGS) -C $(dir_cakehax) clean @$(MAKE) $(FLAGS) -C $(dir_cakebrah) clean @rm -rf $(dir_out) $(dir_build) @@ -83,18 +71,9 @@ $(dir_out)/$(name)$(revision).7z: all $(dir_build)/main.bin: $(dir_build)/main.elf $(OC) -S -O binary $< $@ -$(dir_build)/main.elf: $(bundled) $(objects) +$(dir_build)/main.elf: $(objects) $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ -$(dir_build)/%.bin.o: $(dir_build)/%.bin - @$(bin2o) - -$(dir_build)/loader.bin: $(dir_loader) $(dir_build) - @$(MAKE) -C $< - -$(dir_build)/arm11.bin: $(dir_arm11) $(dir_build) - @$(MAKE) -C $< - $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 $(dir_build)/installer.o: CFLAGS += -DTITLE="\"$(name) $(revision)\"" diff --git a/arm11/Makefile b/arm11/Makefile deleted file mode 100755 index 2fbc841..0000000 --- a/arm11/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/3ds_rules - -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -LD := arm-none-eabi-ld -OC := arm-none-eabi-objcopy - -name := $(shell basename $(CURDIR)) - -dir_source := source -dir_build := build -dir_out := ../$(dir_build) - -ASFLAGS := -mcpu=mpcore -mfloat-abi=hard -CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib - -objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ - $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ - $(call rwildcard, $(dir_source), *.s *.c))) - -.PHONY: all -all: $(dir_out)/$(name).bin - -.PHONY: clean -clean: - @rm -rf $(dir_build) - -$(dir_out)/$(name).bin: $(dir_build)/$(name).elf - $(OC) -S -O binary $< $@ - -$(dir_build)/$(name).elf: $(objects) - $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ - -$(dir_build)/%.o: $(dir_source)/%.c - @mkdir -p "$(@D)" - $(COMPILE.c) $(OUTPUT_OPTION) $< - -$(dir_build)/%.o: $(dir_source)/%.s - @mkdir -p "$(@D)" - $(COMPILE.s) $(OUTPUT_OPTION) $< -include $(call rwildcard, $(dir_build), *.d) diff --git a/arm11/linker.ld b/arm11/linker.ld deleted file mode 100755 index 832320b..0000000 --- a/arm11/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -ENTRY(_start) -SECTIONS -{ - . = 0x1FFF4C80; - .text.start : { *(.text.start) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - .rodata : { *(.rodata) } - . = ALIGN(4); -} - diff --git a/arm11/source/main.c b/arm11/source/main.c deleted file mode 100755 index 104b7bc..0000000 --- a/arm11/source/main.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "types.h" - -void main(void) -{ - vu32 *arm11Entry = (vu32 *)0x1FFFFFF8; - - //Clear ARM11 entrypoint - *arm11Entry = 0; - - //Wait for the entrypoint to be set - while(!*arm11Entry); - - //Jump to it - ((void (*)())*arm11Entry)(); -} \ No newline at end of file diff --git a/arm11/source/start.s b/arm11/source/start.s deleted file mode 100644 index a02aa4c..0000000 --- a/arm11/source/start.s +++ /dev/null @@ -1,8 +0,0 @@ -.section .text.start -.align 4 -.global _start -_start: - @ Disable interrupts - CPSID aif - - b main diff --git a/arm11/source/types.h b/arm11/source/types.h deleted file mode 100755 index ded9cc7..0000000 --- a/arm11/source/types.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -//Common data types -typedef uint32_t u32; -typedef volatile u32 vu32; \ No newline at end of file diff --git a/loader/Makefile b/loader/Makefile deleted file mode 100644 index 5d49685..0000000 --- a/loader/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/3ds_rules - -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -LD := arm-none-eabi-ld -OC := arm-none-eabi-objcopy - -name := $(shell basename $(CURDIR)) - -dir_source := source -dir_build := build -dir_out := ../$(dir_build) - -ASFLAGS := -mcpu=arm946e-s -CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib - -objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ - $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ - $(call rwildcard, $(dir_source), *.s *.c))) - -.PHONY: all -all: $(dir_out)/$(name).bin - -.PHONY: clean -clean: - @rm -rf $(dir_build) - -$(dir_out)/$(name).bin: $(dir_build)/$(name).elf - $(OC) -S -O binary $< $@ - -$(dir_build)/$(name).elf: $(objects) - $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ - -$(dir_build)/%.o: $(dir_source)/%.c - @mkdir -p "$(@D)" - $(COMPILE.c) $(OUTPUT_OPTION) $< - -$(dir_build)/%.o: $(dir_source)/%.s - @mkdir -p "$(@D)" - $(COMPILE.s) $(OUTPUT_OPTION) $< -include $(call rwildcard, $(dir_build), *.d) diff --git a/loader/linker.ld b/loader/linker.ld deleted file mode 100644 index 87f8b2b..0000000 --- a/loader/linker.ld +++ /dev/null @@ -1,11 +0,0 @@ -ENTRY(_start) -SECTIONS -{ - . = 0x1FF8000; - .text.start : { *(.text.start) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - .rodata : { *(.rodata) } - . = ALIGN(4); -} diff --git a/loader/source/main.c b/loader/source/main.c deleted file mode 100644 index 5023f56..0000000 --- a/loader/source/main.c +++ /dev/null @@ -1,35 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified -* reasonable legal notices or author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -*/ - -#include "types.h" - -void main(void) -{ - vu32 *payloadAddress = (vu32 *)0x23F00000; - payloadAddress[1] = 0xDEADCAFE; - - //Ensure that all memory transfers have completed and that the caches have been flushed - ((void (*)())0xFFFF0830)(); - ((void (*)())0xFFFF0AB4)(); - - ((void (*)())payloadAddress)(); -} \ No newline at end of file diff --git a/loader/source/start.s b/loader/source/start.s deleted file mode 100644 index 45f806d..0000000 --- a/loader/source/start.s +++ /dev/null @@ -1,87 +0,0 @@ -@ This file is part of Luma3DS -@ Copyright (C) 2016 Aurora Wright, TuxSH -@ -@ This program is free software: you can redistribute it and/or modify -@ it under the terms of the GNU General Public License as published by -@ the Free Software Foundation, either version 3 of the License, or -@ (at your option) any later version. -@ -@ This program is distributed in the hope that it will be useful, -@ but WITHOUT ANY WARRANTY; without even the implied warranty of -@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -@ GNU General Public License for more details. -@ -@ You should have received a copy of the GNU General Public License -@ along with this program. If not, see . -@ -@ Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified -@ reasonable legal notices or author attributions in that material or in the Appropriate Legal -@ Notices displayed by works containing it. - -@ Thanks to the numerous people who took part in writing this file - -.section .text.start -.align 4 -.global _start -_start: - @ Disable interrupts - mrs r0, cpsr - orr r0, #0x1C0 - msr cpsr_cx, r0 - - @ Change the stack pointer - mov sp, #0x27000000 - - @ Disable caches / MPU - mrc p15, 0, r0, c1, c0, 0 @ read control register - bic r0, #(1<<12) @ - instruction cache disable - bic r0, #(1<<2) @ - data cache disable - bic r0, #(1<<0) @ - mpu disable - mcr p15, 0, r0, c1, c0, 0 @ write control register - - @ Give read/write access to all the memory regions - ldr r0, =0x3333333 - mcr p15, 0, r0, c5, c0, 2 @ write data access - mcr p15, 0, r0, c5, c0, 3 @ write instruction access - - @ Set MPU permissions and cache settings - ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) - ldr r1, =0x01FF801D @ 01ff8000 32k | itcm - ldr r2, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) - ldr r3, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) - ldr r4, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) - ldr r5, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram - ldr r6, =0x1800002D @ 18000000 8M | vram (+ 2MB) - mov r7, #0 - mov r8, #0x15 - mcr p15, 0, r0, c6, c0, 0 - mcr p15, 0, r1, c6, c1, 0 - mcr p15, 0, r2, c6, c2, 0 - mcr p15, 0, r3, c6, c3, 0 - mcr p15, 0, r4, c6, c4, 0 - mcr p15, 0, r5, c6, c5, 0 - mcr p15, 0, r6, c6, c6, 0 - mcr p15, 0, r7, c6, c7, 0 - mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 4 - mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 4 - mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 4 - - @ Flush caches - ldr r0, =0xFFFF0830 - blx r0 - ldr r0, =0xFFFF0AB4 - blx r0 - - @ Enable caches / MPU - mrc p15, 0, r0, c1, c0, 0 @ read control register - orr r0, r0, #(1<<12) @ - instruction cache enable - orr r0, r0, #(1<<2) @ - data cache enable - orr r0, r0, #(1<<0) @ - mpu enable - mcr p15, 0, r0, c1, c0, 0 @ write control register - - @ Fix mounting of SDMC - ldr r0, =0x10000020 - mov r1, #0x340 - str r1, [r0] - - b main diff --git a/loader/source/types.h b/loader/source/types.h deleted file mode 100644 index 6a1677e..0000000 --- a/loader/source/types.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified -* reasonable legal notices or author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -*/ - -#pragma once - -#include - -//Common data types -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef volatile u8 vu8; -typedef volatile u16 vu16; -typedef volatile u32 vu32; -typedef volatile u64 vu64; \ No newline at end of file diff --git a/source/crypto.c b/source/crypto.c index 1d0ad88..0d9ebe5 100755 --- a/source/crypto.c +++ b/source/crypto.c @@ -277,10 +277,10 @@ static u8 nandSlot; static u32 fatStart; __attribute__((aligned(4))) const u8 key2s[5][AES_BLOCK_SIZE] = { {0x42, 0x3F, 0x81, 0x7A, 0x23, 0x52, 0x58, 0x31, 0x6E, 0x75, 0x8E, 0x3A, 0x39, 0x43, 0x2E, 0xD0}, - {0x08, 0x24, 0xD3, 0xCB, 0x4A, 0xE9, 0x4D, 0x62, 0x4D, 0xAA, 0x52, 0x60, 0x47, 0xC5, 0x93, 0x94}, + {0xA5, 0x25, 0x87, 0x11, 0x8F, 0x42, 0x9F, 0x3D, 0x65, 0x1D, 0xDD, 0x58, 0x0B, 0x6D, 0xF2, 0x17}, {0x65, 0x29, 0x3E, 0x12, 0x56, 0x0C, 0x0B, 0xD1, 0xDD, 0xB5, 0x63, 0x1C, 0xB6, 0xD9, 0x52, 0x75}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xF5, 0xF6}, - {0xA5, 0x25, 0x87, 0x11, 0x8F, 0x42, 0x9F, 0x3D, 0x65, 0x1D, 0xDD, 0x58, 0x0B, 0x6D, 0xF2, 0x17} + {0x08, 0x24, 0xD3, 0xCB, 0x4A, 0xE9, 0x4D, 0x62, 0x4D, 0xAA, 0x52, 0x60, 0x47, 0xC5, 0x93, 0x94} }, devKey2s[2][AES_BLOCK_SIZE] = { {0xFF, 0x77, 0xA0, 0x9A, 0x99, 0x81, 0xE9, 0x48, 0xEC, 0x51, 0xC9, 0x32, 0x5D, 0x14, 0xEC, 0x25}, @@ -383,7 +383,7 @@ void generateSector(u8 *keySector, u32 mode) { case 1: memcpy(keySector + AES_BLOCK_SIZE, keySector, AES_BLOCK_SIZE); - break; + return; case 2: memcpy(keySector + AES_BLOCK_SIZE, !ISDEVUNIT ? key2s[0] : devKey2s[0], AES_BLOCK_SIZE); break; @@ -392,13 +392,10 @@ void generateSector(u8 *keySector, u32 mode) break; } - if(mode != 1) - { - //Encrypt key sector - aes_use_keyslot(0x11); - for(u32 i = 0; i < 32; i++) - aes(keySector + (AES_BLOCK_SIZE * i), keySector + (AES_BLOCK_SIZE * i), 1, NULL, AES_ECB_ENCRYPT_MODE, 0); - } + //Encrypt key sector + aes_use_keyslot(0x11); + for(u32 i = 0; i < 32; i++) + aes(keySector + (AES_BLOCK_SIZE * i), keySector + (AES_BLOCK_SIZE * i), 1, NULL, AES_ECB_ENCRYPT_MODE, 0); } void getSector(u8 *keySector) @@ -406,13 +403,12 @@ void getSector(u8 *keySector) //Read keysector from NAND sdmmc_nand_readsectors(0x96, 1, keySector); - if(ISA9LH || ISDEVUNIT) - { - //Decrypt key sector - aes_use_keyslot(0x11); - for(u32 i = 0; i < 32; i++) - aes(keySector + (AES_BLOCK_SIZE * i), keySector + (AES_BLOCK_SIZE * i), 1, NULL, AES_ECB_DECRYPT_MODE, 0); - } + if(!ISA9LH && !ISDEVUNIT) return; + + //Decrypt key sector + aes_use_keyslot(0x11); + for(u32 i = 0; i < 32; i++) + aes(keySector + (AES_BLOCK_SIZE * i), keySector + (AES_BLOCK_SIZE * i), 1, NULL, AES_ECB_DECRYPT_MODE, 0); } bool verifyHash(const void *data, u32 size, const u8 *hash) @@ -427,23 +423,22 @@ u32 decryptExeFs(Cxi *cxi) { u32 exeFsSize = 0; - if(memcmp(cxi->ncch.magic, "NCCH", 4) == 0) - { - u8 *exeFsOffset = (u8 *)cxi + (cxi->ncch.exeFsOffset + 1) * 0x200; - exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200; - __attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0}; + if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return exeFsSize; - for(u32 i = 0; i < 8; i++) - ncchCtr[7 - i] = cxi->ncch.partitionId[i]; - ncchCtr[8] = 2; + u8 *exeFsOffset = (u8 *)cxi + (cxi->ncch.exeFsOffset + 1) * 0x200; + exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200; + __attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0}; - aes_setkey(0x2C, cxi, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_advctr(ncchCtr, 0x200 / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); - aes_use_keyslot(0x2C); - aes(cxi, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + for(u32 i = 0; i < 8; i++) + ncchCtr[7 - i] = cxi->ncch.partitionId[i]; + ncchCtr[8] = 2; - if(memcmp(cxi, "FIRM", 4) != 0) exeFsSize = 0; - } + aes_setkey(0x2C, cxi, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_advctr(ncchCtr, 0x200 / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); + aes_use_keyslot(0x2C); + aes(cxi, exeFsOffset, exeFsSize / AES_BLOCK_SIZE, ncchCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL); + + if(memcmp(cxi, "FIRM", 4) != 0) exeFsSize = 0; return exeFsSize; } \ No newline at end of file diff --git a/source/fatfs/sdmmc/sdmmc.c b/source/fatfs/sdmmc/sdmmc.c index 6b12a24..8c0891f 100644 --- a/source/fatfs/sdmmc/sdmmc.c +++ b/source/fatfs/sdmmc/sdmmc.c @@ -472,10 +472,11 @@ void sdmmc_get_cid(bool isNand, u32 *info) sdmmc_send_command(device, 0x10507, device->initarg << 0x10); } -bool sdmmc_sdcard_init(bool isOtpless) +bool sdmmc_sdcard_init(bool initSd, bool initNand) { InitSD(); - int nand_ret = Nand_Init(); - if(isOtpless) return true; - return (nand_ret | SD_Init()) == 0; + int ret = 0; + if(initNand) ret |= Nand_Init(); + if(initSd) ret |= SD_Init(); + return ret == 0; } \ No newline at end of file diff --git a/source/fatfs/sdmmc/sdmmc.h b/source/fatfs/sdmmc/sdmmc.h index 4bc6bd7..6eda66a 100644 --- a/source/fatfs/sdmmc/sdmmc.h +++ b/source/fatfs/sdmmc/sdmmc.h @@ -91,7 +91,7 @@ typedef struct mmcdevice { u32 res; } mmcdevice; -bool sdmmc_sdcard_init(bool isOtpless); +bool sdmmc_sdcard_init(bool initSd, bool initNand); int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); diff --git a/source/fs.c b/source/fs.c index 32db697..5ade819 100644 --- a/source/fs.c +++ b/source/fs.c @@ -40,16 +40,14 @@ void unmountCtrNand(void) u32 fileRead(void *dest, const char *path, u32 maxSize) { FIL file; - u32 ret; + u32 ret = 0; - if(f_open(&file, path, FA_READ) != FR_OK) ret = 0; - else - { - u32 size = f_size(&file); - if(size <= maxSize) - f_read(&file, dest, size, (unsigned int *)&ret); - f_close(&file); - } + if(f_open(&file, path, FA_READ) != FR_OK) return ret; + + u32 size = f_size(&file); + if(size <= maxSize) + f_read(&file, dest, size, (unsigned int *)&ret); + f_close(&file); return ret; } @@ -57,7 +55,6 @@ u32 fileRead(void *dest, const char *path, u32 maxSize) bool fileWrite(const void *buffer, const char *path, u32 size) { FIL file; - bool ret; switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS)) { @@ -68,8 +65,7 @@ bool fileWrite(const void *buffer, const char *path, u32 size) f_truncate(&file); f_close(&file); - ret = (u32)written == size; - break; + return (u32)written == size; } case FR_NO_PATH: for(u32 i = 1; path[i] != 0; i++) @@ -81,19 +77,20 @@ bool fileWrite(const void *buffer, const char *path, u32 size) f_mkdir(folder); } - ret = fileWrite(buffer, path, size); - break; + return fileWrite(buffer, path, size); default: - ret = false; - break; + return false; } +} - return ret; +void fileDelete(const char *path) +{ + f_unlink(path); } u32 firmRead(void *dest) { - const char *firmFolders[] = { "00000002", "20000002" }; + const char *firmFolders[] = {"00000002", "20000002"}; char path[48] = "1:/title/00040138/"; concatenateStrings(path, firmFolders[ISN3DS ? 1 : 0]); concatenateStrings(path, "/content"); @@ -103,42 +100,41 @@ u32 firmRead(void *dest) u32 firmVersion = 0xFFFFFFFF, ret = 0; - if(f_opendir(&dir, path) == FR_OK) + if(f_opendir(&dir, path) != FR_OK) goto exit; + + FILINFO info; + + //Parse the target directory + while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0) { - FILINFO info; + //Not a cxi + if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; - //Parse the target directory - while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0) - { - //Not a cxi - if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; + //Multiple cxis were found + if(firmVersion != 0xFFFFFFFF) ret = 1; - //Multiple cxis were found - if(firmVersion != 0xFFFFFFFF) ret = 1; + u32 tempVersion = hexAtoi(info.altname, 8); - u32 tempVersion = hexAtoi(info.altname, 8); + //FIRM is equal or newer than 11.0 + if(!ISDEVUNIT && tempVersion >= (ISN3DS ? 0x21 : 0x52)) ret = tempVersion <= (ISN3DS ? 0x28 : 0x58) ? 5 : 2; - //FIRM is equal or newer than 11.0 - if(!ISDEVUNIT && tempVersion >= (ISN3DS ? 0x21 : 0x52)) ret = tempVersion <= (ISN3DS ? 0x28 : 0x58) ? 5 : 2; - - //Found an older cxi - if(tempVersion < firmVersion) firmVersion = tempVersion; - } - - f_closedir(&dir); - - if(ret != 1 && firmVersion != 0xFFFFFFFF) - { - //Complete the string with the .app name - concatenateStrings(path, "/00000000.app"); - - //Convert back the .app name from integer to array - hexItoa(firmVersion, path + 35, 8); - - if(!fileRead(dest, path, 0x100000)) ret = 3; - } + //Found an older cxi + if(tempVersion < firmVersion) firmVersion = tempVersion; } + f_closedir(&dir); + + if(ret == 1 || firmVersion == 0xFFFFFFFF) goto exit; + + //Complete the string with the .app name + concatenateStrings(path, "/00000000.app"); + + //Convert back the .app name from integer to array + hexItoa(firmVersion, path + 35, 8); + + if(!fileRead(dest, path, 0x100000)) ret = 3; + +exit: if(firmVersion == 0xFFFFFFFF) ret = 4; return ret; diff --git a/source/fs.h b/source/fs.h index 1b4dd03..058392e 100644 --- a/source/fs.h +++ b/source/fs.h @@ -28,4 +28,5 @@ bool mountFs(bool isSd); void unmountCtrNand(void); u32 fileRead(void *dest, const char *path, u32 maxSize); bool fileWrite(const void *buffer, const char *path, u32 size); +void fileDelete(const char *path); u32 firmRead(void *dest); \ No newline at end of file diff --git a/source/installer.c b/source/installer.c index e5f3f96..271fbd9 100755 --- a/source/installer.c +++ b/source/installer.c @@ -11,7 +11,6 @@ #include "types.h" #include "installer.h" #include "fatfs/sdmmc/sdmmc.h" -#include "../build/bundled.h" static const u8 sectorHashRetail[SHA_256_HASH_SIZE] = { 0x82, 0xF2, 0x73, 0x0D, 0x2C, 0x2D, 0xA3, 0xF3, 0x01, 0x65, 0xF9, 0x87, 0xFD, 0xCC, 0xAC, 0x5C, @@ -29,13 +28,9 @@ static const u8 sectorHashRetail[SHA_256_HASH_SIZE] = { 0x68, 0x52, 0xCC, 0x21, 0x89, 0xAE, 0x28, 0x38, 0x1A, 0x75, 0x90, 0xE7, 0x38, 0x23, 0x48, 0x41, 0x8E, 0x80, 0x78, 0x75, 0x27, 0x64, 0x04, 0xD6, 0x28, 0xD6, 0xFA, 0x39, 0xA8, 0x6F, 0xB0, 0x3F }, - firm0100Hash[SHA_256_HASH_SIZE] = { + firm1HashRetail[SHA_256_HASH_SIZE] = { 0xD8, 0x2D, 0xB7, 0xB4, 0x38, 0x2B, 0x07, 0x88, 0x99, 0x77, 0x91, 0x0C, 0xC6, 0xEC, 0x6D, 0x87, 0x7D, 0x21, 0x79, 0x23, 0xD7, 0x60, 0xAF, 0x4E, 0x8B, 0x3A, 0xAB, 0xB2, 0x63, 0xE4, 0x21, 0xC6 -}, - firm1HashRetail[SHA_256_HASH_SIZE] = { - 0xD2, 0x53, 0xC1, 0xCC, 0x0A, 0x5F, 0xFA, 0xC6, 0xB3, 0x83, 0xDA, 0xC1, 0x82, 0x7C, 0xFB, 0x3B, - 0x2D, 0x3D, 0x56, 0x6C, 0x6A, 0x1A, 0x8E, 0x52, 0x54, 0xE3, 0x89, 0xC2, 0x95, 0x06, 0x23, 0xE5 }, firm104O3DSHash[SHA_256_HASH_SIZE] = { 0x5D, 0x33, 0xD9, 0xCE, 0xE3, 0x39, 0x05, 0xD5, 0xCE, 0x37, 0xFE, 0xFB, 0xB5, 0xEC, 0x73, 0x6A, @@ -62,11 +57,12 @@ static const u8 sectorHashRetail[SHA_256_HASH_SIZE] = { 0xF2, 0x38, 0x14, 0x58, 0x10, 0x83, 0x56, 0x4F, 0x0D, 0x5A, 0xDB, 0x29, 0x12, 0xD8, 0xA9, 0x84 }; +static vu32 *otplessOffset = (vu32 *)0x80FD0FC; u32 posY; -static void drawTitle(bool isOtpless) +static void drawTitle(void) { - initScreens(isOtpless); + initScreens(); posY = drawString(TITLE, 10, 10, COLOR_TITLE); posY = drawString("Thanks to delebile, #cakey and StandardBus", 10, posY + SPACING_Y, COLOR_WHITE); @@ -74,11 +70,11 @@ static void drawTitle(bool isOtpless) void main(void) { - bool isOtpless = ISA9LH && magic == 0xDEADCAFE; + bool isOtpless = ISA9LH && otplessOffset[0] == 0xEAFE4AA3 && otplessOffset[1] == 0xDEADCAFE; - if(!isOtpless) drawTitle(false); + if(!isOtpless) drawTitle(); - if(!sdmmc_sdcard_init(isOtpless)) + if(!sdmmc_sdcard_init(!isOtpless, true) && !isOtpless) shutdown(1, "Error: failed to initialize SD and NAND"); u32 pressed; @@ -191,15 +187,6 @@ static inline void installer(bool isOtpless) if(!ISA9LH || updateKey2 || isOtpless) generateSector(keySector, (!ISA9LH && ISN3DS && !ISDEVUNIT) ? 1 : 0); - if(!ISA9LH && ISN3DS && !ISDEVUNIT) - { - //Read 10.0 FIRM0 - if(fileRead((void *)FIRM0_100_OFFSET, "a9lh/firm0_100.bin", FIRM0100_SIZE) != FIRM0100_SIZE) - shutdown(1, "Error: firm0_100.bin doesn't exist or has a wrong size"); - if(!verifyHash((void *)FIRM0_100_OFFSET, FIRM0100_SIZE, firm0100Hash)) - shutdown(1, "Error: firm0_100.bin is invalid or corrupted"); - } - if(!ISA9LH || updateFirm0) { //Read FIRM0 @@ -218,6 +205,9 @@ static inline void installer(bool isOtpless) shutdown(1, "Error: firm1.bin is invalid or corrupted"); } + if(!ISA9LH && ISN3DS && !ISDEVUNIT && !fileWrite((void *)0x23F00000, "arm9loaderhax.bin", 0x10000)) + shutdown(1, "Error: couldn't write arm9loaderhax.bin"); + if(!isOtpless) { bool missingStage1Hash, @@ -274,23 +264,24 @@ static inline void installer(bool isOtpless) if(!ISA9LH || updateFirm1) writeFirm((u8 *)FIRM1_OFFSET, true, FIRM1_SIZE); if(!ISA9LH || updateKey2 || isOtpless) sdmmc_nand_writesectors(0x96, 1, keySector); + if(!isOtpless) writeFirm((u8 *)FIRM0_OFFSET, false, FIRM0_SIZE); + else + { + otplessOffset[0] = otplessOffset[1] = 0; + sdmmc_sdcard_init(true, false); + mountFs(true); + fileDelete("arm9loaderhax.bin"); + drawTitle(); + } if(!ISA9LH && ISN3DS && !ISDEVUNIT) { - const u8 ldrAndBranch[] = {0x00, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x80, 0xFF, 0x01}; - - memcpy((void *)0x80FD0FC, ldrAndBranch, sizeof(ldrAndBranch)); - memcpy((void *)0x1FF8000, loader_bin, loader_bin_size); - - writeFirm((u8 *)FIRM0_100_OFFSET, false, FIRM0100_SIZE); + otplessOffset[0] = 0xEAFE4AA3; + otplessOffset[1] = 0xDEADCAFE; mcuReboot(); } - writeFirm((u8 *)FIRM0_OFFSET, false, FIRM0_SIZE); - - if(isOtpless) drawTitle(true); - shutdown(2, ISA9LH && !isOtpless ? "Update: success!" : "Full install: success!"); } diff --git a/source/installer.h b/source/installer.h index 5a8025b..55527f5 100644 --- a/source/installer.h +++ b/source/installer.h @@ -9,18 +9,15 @@ #define OTP_FROM_MEM 0x10012000 #define FIRM0_OFFSET 0x24000000 #define SECTION2_POSITION 0x66A00 -#define FIRM0_100_OFFSET 0x24100000 -#define FIRM1_OFFSET 0x24200000 +#define FIRM1_OFFSET 0x24100000 #define FIRM0_SIZE 0xF3000 -#define FIRM0100_SIZE 0xF2000 #define FIRM1_SIZE 0xF2000 #define STAGE1_POSITION 0xF0590 #define STAGE1_OFFSET FIRM0_OFFSET + STAGE1_POSITION -#define STAGE2_OFFSET 0x24300000 +#define STAGE2_OFFSET 0x24200000 #define MAX_STAGE1_SIZE 0x1E70 #define MAX_STAGE2_SIZE 0x89A00 -extern u32 magic; extern const u8 key2s[5][AES_BLOCK_SIZE], devKey2s[2][AES_BLOCK_SIZE]; diff --git a/source/screen.c b/source/screen.c index 70b46bb..36a5ba2 100644 --- a/source/screen.c +++ b/source/screen.c @@ -39,21 +39,9 @@ #include "utils.h" #include "memory.h" #include "i2c.h" -#include "../build/bundled.h" vu32 *arm11Entry = (vu32 *)BRAHMA_ARM11_ENTRY; -static inline void ownArm11(void) -{ - memcpy((void *)A11_PAYLOAD_LOC, arm11_bin, arm11_bin_size); - - *arm11Entry = 1; - *(vu32 *)0x1FFAED80 = 0xE51FF004; - *(vu32 *)0x1FFAED84 = A11_PAYLOAD_LOC; - *(vu8 *)0x1FFFFFF0 = 2; - while(*arm11Entry != 0); -} - static void invokeArm11Function(void (*func)()) { *arm11Entry = (u32)func; @@ -87,7 +75,7 @@ void clearScreens(void) invokeArm11Function(ARM11); } -void initScreens(bool isOtpless) +void initScreens(void) { void __attribute__((naked)) initSequence(void) { @@ -195,10 +183,6 @@ void initScreens(bool isOtpless) if(!ARESCREENSINITED) { - wait(3ULL); - - if(isOtpless) ownArm11(); - invokeArm11Function(initSequence); //Turn on backlight diff --git a/source/screen.h b/source/screen.h index aee4f2e..5f273b6 100644 --- a/source/screen.h +++ b/source/screen.h @@ -33,7 +33,6 @@ #define ARESCREENSINITED (PDN_GPU_CNT != 1) #define BRAHMA_ARM11_ENTRY 0x1FFFFFF8 -#define A11_PAYLOAD_LOC 0x1FFF4C80 #define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)(); #define SCREEN_TOP_WIDTH 400 @@ -49,4 +48,4 @@ static struct fb { } *const fb = (struct fb *)0x23FFFE00; void clearScreens(void); -void initScreens(bool isOtpless); \ No newline at end of file +void initScreens(void); \ No newline at end of file diff --git a/source/start.s b/source/start.s index c108bc6..d545d4d 100644 --- a/source/start.s +++ b/source/start.s @@ -24,13 +24,6 @@ .align 4 .global _start _start: - b start - -.global magic -magic: - .word 0 - -start: @ Disable interrupts mrs r0, cpsr orr r0, #0x1C0 diff --git a/source/utils.c b/source/utils.c index 33cb4d0..b4c331e 100755 --- a/source/utils.c +++ b/source/utils.c @@ -8,56 +8,32 @@ #include "cache.h" #include "i2c.h" -static void startChrono(void) -{ - REG_TIMER_CNT(0) = 0; //67MHz - for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 4; //Count-up - - for(u32 i = 0; i < 4; i++) REG_TIMER_VAL(i) = 0; - - REG_TIMER_CNT(0) = 0x80; //67MHz; enabled - for(u32 i = 1; i < 4; i++) REG_TIMER_CNT(i) = 0x84; //Count-up; enabled -} - -static u64 chrono(void) -{ - u64 res; - for(u32 i = 0; i < 4; i++) res |= REG_TIMER_VAL(i) << (16 * i); - - res /= (TICKS_PER_SEC / 1000); - - return res; -} - u32 waitInput(void) { - bool pressedKey = false; u32 key, oldKey = HID_PAD; - while(!pressedKey) + while(true) { key = HID_PAD; - if(!key) oldKey = key; - else if(key != oldKey) + if(!key) { - //Make sure the key is pressed - u32 i; - for(i = 0; i < 0x13000 && key == HID_PAD; i++); - if(i == 0x13000) pressedKey = true; + oldKey = 0; + continue; } + + if(key == oldKey) continue; + + //Make sure the key is pressed + u32 i; + for(i = 0; i < 0x13000 && key == HID_PAD; i++); + if(i == 0x13000) break; } return key; } -void wait(u64 amount) -{ - startChrono(); - while(chrono() < amount); -} - void mcuReboot(void) { clearScreens(); diff --git a/source/utils.h b/source/utils.h index cfec731..5662236 100644 --- a/source/utils.h +++ b/source/utils.h @@ -28,7 +28,6 @@ extern u32 posY; u32 waitInput(void); -void wait(u64 amount); void mcuReboot(void); void inputSequence(void); void shutdown(u32 mode, const char *message); \ No newline at end of file