Change OTPless installation approach

This commit is contained in:
Aurora 2016-11-22 22:45:14 +01:00
parent d605111e28
commit b1d596177a
23 changed files with 113 additions and 508 deletions

View File

@ -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)\""

View File

@ -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)

View File

@ -1,12 +0,0 @@
ENTRY(_start)
SECTIONS
{
. = 0x1FFF4C80;
.text.start : { *(.text.start) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
.rodata : { *(.rodata) }
. = ALIGN(4);
}

View File

@ -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)();
}

View File

@ -1,8 +0,0 @@
.section .text.start
.align 4
.global _start
_start:
@ Disable interrupts
CPSID aif
b main

View File

@ -1,7 +0,0 @@
#pragma once
#include <stdint.h>
//Common data types
typedef uint32_t u32;
typedef volatile u32 vu32;

View File

@ -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)

View File

@ -1,11 +0,0 @@
ENTRY(_start)
SECTIONS
{
. = 0x1FF8000;
.text.start : { *(.text.start) }
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss COMMON) }
.rodata : { *(.rodata) }
. = ALIGN(4);
}

View File

@ -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)();
}

View File

@ -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

View File

@ -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;

View File

@ -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,28 +392,24 @@ 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)
{
//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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,14 +77,15 @@ 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)
@ -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;

View File

@ -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);

View File

@ -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!");
}

View File

@ -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];

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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();

View File

@ -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);