Change OTPless installation approach
This commit is contained in:
parent
d605111e28
commit
b1d596177a
23
Makefile
23
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 $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $(dir_build)/bundled.h
|
||||
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $(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)\""
|
||||
|
||||
|
@ -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=<path to>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)
|
@ -1,12 +0,0 @@
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1FFF4C80;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
@ -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)();
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
.section .text.start
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
@ Disable interrupts
|
||||
CPSID aif
|
||||
|
||||
b main
|
@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//Common data types
|
||||
typedef uint32_t u32;
|
||||
typedef volatile u32 vu32;
|
@ -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=<path to>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)
|
@ -1,11 +0,0 @@
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1FF8000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = ALIGN(4);
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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)();
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
@
|
||||
@ 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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
//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;
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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,8 +423,8 @@ u32 decryptExeFs(Cxi *cxi)
|
||||
{
|
||||
u32 exeFsSize = 0;
|
||||
|
||||
if(memcmp(cxi->ncch.magic, "NCCH", 4) == 0)
|
||||
{
|
||||
if(memcmp(cxi->ncch.magic, "NCCH", 4) != 0) return exeFsSize;
|
||||
|
||||
u8 *exeFsOffset = (u8 *)cxi + (cxi->ncch.exeFsOffset + 1) * 0x200;
|
||||
exeFsSize = (cxi->ncch.exeFsSize - 1) * 0x200;
|
||||
__attribute__((aligned(4))) u8 ncchCtr[AES_BLOCK_SIZE] = {0};
|
||||
@ -443,7 +439,6 @@ u32 decryptExeFs(Cxi *cxi)
|
||||
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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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);
|
||||
|
36
source/fs.c
36
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) return ret;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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,8 +100,8 @@ 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
|
||||
@ -127,8 +124,8 @@ u32 firmRead(void *dest)
|
||||
|
||||
f_closedir(&dir);
|
||||
|
||||
if(ret != 1 && firmVersion != 0xFFFFFFFF)
|
||||
{
|
||||
if(ret == 1 || firmVersion == 0xFFFFFFFF) goto exit;
|
||||
|
||||
//Complete the string with the .app name
|
||||
concatenateStrings(path, "/00000000.app");
|
||||
|
||||
@ -136,9 +133,8 @@ u32 firmRead(void *dest)
|
||||
hexItoa(firmVersion, path + 35, 8);
|
||||
|
||||
if(!fileRead(dest, path, 0x100000)) ret = 3;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if(firmVersion == 0xFFFFFFFF) ret = 4;
|
||||
|
||||
return ret;
|
||||
|
@ -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);
|
@ -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!");
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
void initScreens(void);
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
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) pressedKey = true;
|
||||
}
|
||||
if(i == 0x13000) break;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
void wait(u64 amount)
|
||||
{
|
||||
startChrono();
|
||||
while(chrono() < amount);
|
||||
}
|
||||
|
||||
void mcuReboot(void)
|
||||
{
|
||||
clearScreens();
|
||||
|
@ -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);
|
Loading…
x
Reference in New Issue
Block a user