mirror of
https://github.com/AuroraWright/SafeA9LHInstaller.git
synced 2025-06-26 13:42:45 +00:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
d55a454b15 | ||
|
2b686a4de7 | ||
|
64b1eefc5d | ||
|
c77746f383 | ||
|
5d1c717cb4 | ||
|
bccdfe4404 | ||
|
04a33143b7 | ||
|
2be5a24262 | ||
|
7067c6d0e8 | ||
|
b1d596177a | ||
|
d605111e28 | ||
|
d95851286c |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,7 +1,7 @@
|
||||
out
|
||||
build
|
||||
loader/build
|
||||
loader/arm11/build
|
||||
arm11/build
|
||||
*.bin
|
||||
*.3dsx
|
||||
*.smdh
|
||||
|
2
CakeBrah
2
CakeBrah
@ -1 +1 @@
|
||||
Subproject commit 9f7cea77d4db4d743e45b2e5193df76ffed0a571
|
||||
Subproject commit 1efda4e89476d34aeb307e0acd7a8dbcd1344601
|
2
CakeHax
2
CakeHax
@ -1 +1 @@
|
||||
Subproject commit 5245c7b9dc232956a8578a36468f9024d8cf7001
|
||||
Subproject commit 329212a8e09d4718e304cb9d94a0e10f66d9813d
|
28
Makefile
28
Makefile
@ -4,18 +4,12 @@ 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
|
||||
include $(DEVKITARM)/base_tools
|
||||
|
||||
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_cakehax := CakeHax
|
||||
dir_cakebrah := CakeBrah
|
||||
dir_build := build
|
||||
@ -30,14 +24,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
|
||||
|
||||
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
|
||||
|
||||
@ -55,7 +41,6 @@ release: $(dir_out)/$(name)$(revision).7z
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) -C $(dir_loader) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_cakehax) clean
|
||||
@$(MAKE) $(FLAGS) -C $(dir_cakebrah) clean
|
||||
@rm -rf $(dir_out) $(dir_build)
|
||||
@ -79,17 +64,11 @@ $(dir_out)/$(name)$(revision).7z: all
|
||||
@7z a -mx $@ ./$(@D)/*
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OC) -S -O binary $< $@
|
||||
$(OBJCOPY) -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)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
||||
$(dir_build)/installer.o: CFLAGS += -DTITLE="\"$(name) $(revision)\""
|
||||
|
||||
@ -100,4 +79,3 @@ $(dir_build)/%.o: $(dir_source)/%.c
|
||||
$(dir_build)/%.o: $(dir_source)/%.s
|
||||
@mkdir -p "$(@D)"
|
||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
||||
include $(call rwildcard, $(dir_build), *.d)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
**Usage / Features:**
|
||||
|
||||
*DO NOT USE THIS VERSION TO INSTALL ON NEW 3DS UNLESS YOU HAVE AN HARDMOD, CAUSES RANDOM BRICKS! UNINSTALLATION IS FINE*
|
||||
For a comprehensive guide to installing A9LH and to 3DS hacking in general, refer to [Plailect's guide](https://github.com/Plailect/Guide/wiki/Get-Started).
|
||||
For other details about the program, refer to the [GBATemp thread](http://gbatemp.net/threads/safea9lhinstaller.419577/).
|
||||
|
||||
|
14
linker.ld
14
linker.ld
@ -1,11 +1,15 @@
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x23F00000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
|
||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
||||
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
|
||||
|
||||
. = ALIGN(4);
|
||||
}
|
||||
|
@ -1,67 +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_arm11 := arm11
|
||||
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)))
|
||||
|
||||
bundled = $(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: $(dir_out)/$(name).bin
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@$(MAKE) -C $(dir_arm11) clean
|
||||
@rm -rf $(dir_build)
|
||||
|
||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
||||
$(OC) -S -O binary $< $@
|
||||
|
||||
$(dir_build)/$(name).elf: $(bundled) $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
||||
$(dir_build)/%.bin.o: $(dir_build)/%.bin
|
||||
@$(bin2o)
|
||||
|
||||
$(dir_build)/arm11.bin: $(dir_arm11)
|
||||
@mkdir -p "$(@D)"
|
||||
@$(MAKE) -C $<
|
||||
|
||||
$(dir_build)/memory.o: CFLAGS += -O3
|
||||
|
||||
$(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,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,11 +0,0 @@
|
||||
ENTRY(_start)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1FF8000;
|
||||
.text.start : { *(.text.start) }
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
.bss : { *(.bss COMMON) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = ALIGN(4);
|
||||
}
|
@ -1,52 +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 "memory.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
#define A11_PAYLOAD_LOC 0x1FFF4C80 //Keep in mind this needs to be changed in the ld script for arm11 too
|
||||
#define A11_ENTRYPOINT 0x1FFFFFF8
|
||||
|
||||
static inline void ownArm11(void)
|
||||
{
|
||||
memcpy((void *)A11_PAYLOAD_LOC, arm11_bin, arm11_bin_size);
|
||||
|
||||
*(vu32 *)A11_ENTRYPOINT = 1;
|
||||
*(vu32 *)0x1FFAED80 = 0xE51FF004;
|
||||
*(vu32 *)0x1FFAED84 = A11_PAYLOAD_LOC;
|
||||
*(vu8 *)0x1FFFFFF0 = 2;
|
||||
while(*(vu32 *)A11_ENTRYPOINT != 0);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
ownArm11();
|
||||
|
||||
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,14 +0,0 @@
|
||||
/*
|
||||
* memory.c
|
||||
*/
|
||||
|
||||
#include "memory.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size)
|
||||
{
|
||||
u8 *destc = (u8 *)dest;
|
||||
const u8 *srcc = (const u8 *)src;
|
||||
|
||||
for(u32 i = 0; i < size; i++)
|
||||
destc[i] = srcc[i];
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
/*
|
||||
* memory.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void memcpy(void *dest, const void *src, u32 size);
|
@ -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},
|
||||
@ -381,24 +381,21 @@ void generateSector(u8 *keySector, u32 mode)
|
||||
//Inject key2
|
||||
switch(mode)
|
||||
{
|
||||
case 0:
|
||||
memcpy(keySector + AES_BLOCK_SIZE, !ISDEVUNIT ? key2s[1] : devKey2s[1], AES_BLOCK_SIZE);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
memcpy(keySector + AES_BLOCK_SIZE, !ISDEVUNIT ? key2s[1] : devKey2s[1], AES_BLOCK_SIZE);
|
||||
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;
|
||||
}
|
13
source/fatfs/00history.txt
Executable file → Normal file
13
source/fatfs/00history.txt
Executable file → Normal file
@ -212,7 +212,7 @@ R0.10a (January 15, 2014)
|
||||
R0.10b (May 19, 2014)
|
||||
|
||||
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||
Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ R0.12a (July 10, 2016)
|
||||
|
||||
R0.12b (September 04, 2016)
|
||||
|
||||
Improved f_rename() to be able to rename objects with the same name but case.
|
||||
Made f_rename() be able to rename objects with the same name but case.
|
||||
Fixed an error in the case conversion teble of code page 866. (ff.c)
|
||||
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
|
||||
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
|
||||
@ -277,3 +277,12 @@ R0.12b (September 04, 2016)
|
||||
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
|
||||
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
|
||||
|
||||
|
||||
|
||||
R0.12c (March 04, 2017)
|
||||
|
||||
Improved write throughput at the fragmented file on the exFAT volume.
|
||||
Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
|
||||
Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
|
||||
Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
|
||||
|
||||
|
26
source/fatfs/00readme.txt
Executable file → Normal file
26
source/fatfs/00readme.txt
Executable file → Normal file
@ -1,21 +1,21 @@
|
||||
FatFs Module Source Files R0.12a
|
||||
FatFs Module Source Files R0.12c
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
00readme.txt This file.
|
||||
history.txt Revision history.
|
||||
ffconf.h Configuration file for FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
ff.c FatFs module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||
integer.h Integer type definitions for FatFs.
|
||||
option Optional external functions.
|
||||
00readme.txt This file.
|
||||
00history.txt Revision history.
|
||||
ff.c FatFs module.
|
||||
ffconf.h Configuration file of FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||
integer.h Integer type definitions for FatFs.
|
||||
option Optional external modules.
|
||||
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module that written
|
||||
to control the target storage device.
|
||||
module is only a generic file system layer and it does not depend on any specific
|
||||
storage device. You have to provide a low level disk I/O module written to
|
||||
control the storage device that attached to the target system.
|
||||
|
||||
|
737
source/fatfs/ff.c
Executable file → Normal file
737
source/fatfs/ff.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
25
source/fatfs/ff.h
Executable file → Normal file
25
source/fatfs/ff.h
Executable file → Normal file
@ -1,8 +1,8 @@
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT file system module R0.12b /
|
||||
/ FatFs - Generic FAT file system module R0.12c /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2016, ChaN, all right reserved.
|
||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
#ifndef _FATFS
|
||||
#define _FATFS 68020 /* Revision ID */
|
||||
#define _FATFS 68300 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -42,13 +42,6 @@ typedef struct {
|
||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||
} PARTITION;
|
||||
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
|
||||
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
|
||||
|
||||
#else /* Single partition configuration */
|
||||
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
|
||||
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -140,14 +133,15 @@ typedef struct {
|
||||
FATFS* fs; /* Pointer to the owner file system object */
|
||||
WORD id; /* Owner file system mount ID */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object start cluster (0:no cluster or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
#if _FS_EXFAT
|
||||
DWORD n_cont; /* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
|
||||
DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */
|
||||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */
|
||||
#endif
|
||||
#if _FS_LOCK != 0
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
@ -163,7 +157,7 @@ typedef struct {
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fprt is 0) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
|
||||
DWORD sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !_FS_READONLY
|
||||
DWORD dir_sect; /* Sector number containing the directory entry */
|
||||
@ -185,7 +179,7 @@ typedef struct {
|
||||
_FDID obj; /* Object identifier */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
DWORD sect; /* Current sector */
|
||||
DWORD sect; /* Current sector (0:Read operation has terminated) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
|
||||
#if _USE_LFN != 0
|
||||
@ -285,6 +279,7 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
|
||||
#define f_size(fp) ((fp)->obj.objsize)
|
||||
#define f_rewind(fp) f_lseek((fp), 0)
|
||||
#define f_rewinddir(dp) f_readdir((dp), 0)
|
||||
#define f_rmdir(path) f_unlink(path)
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
|
23
source/fatfs/ffconf.h
Executable file → Normal file
23
source/fatfs/ffconf.h
Executable file → Normal file
@ -2,7 +2,7 @@
|
||||
/ FatFs - FAT file system module configuration file
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _FFCONF 68020 /* Revision ID */
|
||||
#define _FFCONF 68300 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
@ -73,7 +73,7 @@
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect setting of the code page can cause a file open failure.
|
||||
/
|
||||
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
||||
/ 1 - ASCII (No support of extended character. Non-LFN cfg. only)
|
||||
/ 437 - U.S.
|
||||
/ 720 - Arabic
|
||||
/ 737 - Greek
|
||||
@ -148,7 +148,7 @@
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define _VOLUMES 2
|
||||
/* Number of volumes (logical drives) to be used. */
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#define _STR_VOLUME_ID 0
|
||||
@ -172,11 +172,11 @@
|
||||
#define _MIN_SS 512
|
||||
#define _MAX_SS 512
|
||||
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||
/ 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
/ to variable sector size and GET_SECTOR_SIZE command needs to be implemented to
|
||||
/ the disk_ioctl() function. */
|
||||
|
||||
|
||||
#define _USE_TRIM 0
|
||||
@ -204,7 +204,7 @@
|
||||
|
||||
#define _FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the file system object (FATFS) is used for the file data transfer. */
|
||||
|
||||
@ -212,20 +212,20 @@
|
||||
#define _FS_EXFAT 0
|
||||
/* This option switches support of exFAT file system. (0:Disable or 1:Enable)
|
||||
/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
|
||||
/ Note that enabling exFAT discards C89 compatibility. */
|
||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||
|
||||
|
||||
#define _FS_NORTC 1
|
||||
#define _NORTC_MON 1
|
||||
#define _NORTC_MDAY 1
|
||||
#define _NORTC_YEAR 2016
|
||||
#define _NORTC_YEAR 2017
|
||||
/* The option _FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
|
||||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
||||
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to get current time form real-time clock. _NORTC_MON,
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||
/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
|
||||
|
||||
|
||||
@ -258,10 +258,11 @@
|
||||
/
|
||||
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
|
||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||
/ included somewhere in the scope of ff.h. */
|
||||
|
||||
/* #include <windows.h> // O/S definitions */
|
||||
|
||||
|
||||
|
||||
/*--- End of configuration options ---*/
|
||||
|
2
source/fatfs/integer.h
Executable file → Normal file
2
source/fatfs/integer.h
Executable file → Normal file
@ -30,7 +30,7 @@ typedef unsigned short WCHAR;
|
||||
typedef long LONG;
|
||||
typedef unsigned long DWORD;
|
||||
|
||||
/* This type MUST be 64-bit (Remove this for C89 compatibility) */
|
||||
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
|
||||
typedef unsigned long long QWORD;
|
||||
|
||||
#endif
|
||||
|
0
source/fatfs/option/ccsbcs.c
Executable file → Normal file
0
source/fatfs/option/ccsbcs.c
Executable file → Normal 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;
|
||||
}
|
@ -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);
|
||||
|
100
source/fs.c
100
source/fs.c
@ -32,24 +32,17 @@ bool mountFs(bool isSd)
|
||||
return isSd ? f_mount(&fs, "0:", 1) == FR_OK : f_mount(&fs, "1:", 1) == FR_OK;
|
||||
}
|
||||
|
||||
void unmountCtrNand(void)
|
||||
{
|
||||
f_mount(NULL, "1:", 1);
|
||||
}
|
||||
|
||||
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 +50,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 +60,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 +72,25 @@ 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);
|
||||
}
|
||||
|
||||
void fileRename(const char *oldPath, const char *newPath)
|
||||
{
|
||||
f_rename(oldPath, newPath);
|
||||
}
|
||||
|
||||
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 newer than 11.3
|
||||
if(!ISDEVUNIT && tempVersion > (ISN3DS ? 0x2D : 0x5C)) ret = 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;
|
||||
|
@ -25,7 +25,8 @@
|
||||
#include "types.h"
|
||||
|
||||
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);
|
||||
void fileRename(const char *oldPath, const char *newPath);
|
||||
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,21 +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,
|
||||
0xA0, 0x10, 0xAD, 0x87, 0xF8, 0xDC, 0x55, 0x39, 0xFD, 0xDB, 0x48, 0x69, 0xAC, 0x5F, 0x3C, 0x2B
|
||||
},
|
||||
firm104N3DSHash[SHA_256_HASH_SIZE] = {
|
||||
0x2D, 0x6B, 0xCC, 0xCE, 0x3B, 0x81, 0xD7, 0xCA, 0x67, 0x17, 0x90, 0x33, 0x35, 0x4D, 0xFA, 0xA5,
|
||||
0x70, 0xF4, 0x7A, 0x99, 0xBB, 0x60, 0x0C, 0x2F, 0x34, 0x90, 0xFF, 0x10, 0xD4, 0x4C, 0x97, 0x42
|
||||
},
|
||||
sectorHashDev[SHA_256_HASH_SIZE] = {
|
||||
0xB2, 0x91, 0xD9, 0xB1, 0x33, 0x05, 0x79, 0x0D, 0x47, 0xC6, 0x06, 0x98, 0x4C, 0x67, 0xC3, 0x70,
|
||||
@ -74,11 +61,11 @@ static void drawTitle(void)
|
||||
|
||||
void main(void)
|
||||
{
|
||||
bool isOtpless = ISA9LH && magic == 0xDEADCAFE;
|
||||
bool isOtpless = ISA9LH && *(vu32 *)0x80FD0FC == 0xEAFE4AA3 && magic == 0xDEADCAFE;
|
||||
|
||||
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;
|
||||
@ -170,13 +157,11 @@ static inline void installer(bool isOtpless)
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
updateKey2 = true;
|
||||
break;
|
||||
case 4:
|
||||
updateFirm1 = true;
|
||||
updateKey2 = true;
|
||||
break;
|
||||
default:
|
||||
case 1:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -191,15 +176,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 +194,16 @@ static inline void installer(bool isOtpless)
|
||||
shutdown(1, "Error: firm1.bin is invalid or corrupted");
|
||||
}
|
||||
|
||||
if(!ISA9LH && ISN3DS && !ISDEVUNIT)
|
||||
{
|
||||
magic = 0xDEADCAFE;
|
||||
|
||||
fileRename("arm9loaderhax.bin", "arm9loaderhax.bak");
|
||||
|
||||
if(!fileWrite((void *)0x23F00000, "arm9loaderhax.bin", 0x10000))
|
||||
shutdown(1, "Error: couldn't write arm9loaderhax.bin");
|
||||
}
|
||||
|
||||
if(!isOtpless)
|
||||
{
|
||||
bool missingStage1Hash,
|
||||
@ -274,23 +260,32 @@ 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
|
||||
{
|
||||
*(vu32 *)0x80FD0FC = 0;
|
||||
|
||||
drawTitle();
|
||||
|
||||
if(sdmmc_sdcard_init(true, false) && mountFs(true))
|
||||
{
|
||||
fileDelete("arm9loaderhax.bin");
|
||||
fileRename("arm9loaderhax.bak", "arm9loaderhax.bin");
|
||||
}
|
||||
else
|
||||
{
|
||||
posY = drawString("Couldn't remove arm9loaderhax.bin!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("Do it yourself after the install ends", 10, posY, COLOR_RED);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
*(vu32 *)0x80FD0FC = 0xEAFE4AA3;
|
||||
|
||||
mcuReboot();
|
||||
}
|
||||
|
||||
writeFirm((u8 *)FIRM0_OFFSET, false, FIRM0_SIZE);
|
||||
|
||||
if(isOtpless) drawTitle();
|
||||
|
||||
shutdown(2, ISA9LH && !isOtpless ? "Update: success!" : "Full install: success!");
|
||||
}
|
||||
|
||||
@ -331,32 +326,10 @@ static inline void uninstaller(void)
|
||||
case 1:
|
||||
shutdown(1, "Error: more than one FIRM has been detected");
|
||||
break;
|
||||
case 5:
|
||||
posY = drawString("FIRM 11.0/11.1/11.2 has been detected!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("Press SELECT to load 10.4 FIRM from SD", 10, posY + SPACING_Y, COLOR_WHITE);
|
||||
posY = drawString("Press any other button to load FIRM from CTRNAND", 10, posY, COLOR_RED);
|
||||
|
||||
if(waitInput() == BUTTON_SELECT)
|
||||
{
|
||||
u32 firm104Size = ISN3DS ? 0xF2000 : 0xEA000;
|
||||
|
||||
unmountCtrNand();
|
||||
|
||||
if(!mountFs(true)) shutdown(1, "Error: failed to mount the SD card");
|
||||
|
||||
if(fileRead((void *)FIRM0_OFFSET, "a9lh/firm104.bin", firm104Size) != firm104Size)
|
||||
shutdown(1, "Error: firm104.bin doesn't exist or has a wrong size");
|
||||
|
||||
if(!verifyHash((void *)FIRM0_OFFSET, firm104Size, ISN3DS ? firm104N3DSHash : firm104O3DSHash))
|
||||
shutdown(1, "Error: firm104.bin is invalid or corrupted");
|
||||
|
||||
firmSize = firm104Size;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
if(result == 2) posY = drawString("A FIRM newer than 11.2 has been detected!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("A FIRM newer than 11.3 has been detected!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("You are about to uninstall A9LH!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("To reinstall you'll need an hardmod or a DSi dg!", 10, posY, COLOR_RED);
|
||||
posY = drawString("To reinstall you'll need hardmod + NAND backup!", 10, posY, COLOR_RED);
|
||||
break;
|
||||
case 3:
|
||||
shutdown(1, "Error: the CTRNAND FIRM is too large");
|
||||
@ -365,23 +338,16 @@ static inline void uninstaller(void)
|
||||
shutdown(1, "Error: couldn't read FIRM from CTRNAND");
|
||||
break;
|
||||
default:
|
||||
posY = drawString("You are about to uninstall A9LH!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("To reinstall you'll need 9.2 or lower!", 10, posY, COLOR_RED);
|
||||
break;
|
||||
}
|
||||
|
||||
if(firmSize != 0 || !result)
|
||||
{
|
||||
posY = drawString("You are about to uninstall A9LH!", 10, posY + SPACING_Y, COLOR_RED);
|
||||
posY = drawString("To reinstall you'll need 9.2 or lower!", 10, posY, COLOR_RED);
|
||||
}
|
||||
|
||||
inputSequence();
|
||||
|
||||
//Decrypt it and get its size
|
||||
if(!firmSize)
|
||||
{
|
||||
firmSize = decryptExeFs((Cxi *)FIRM0_OFFSET);
|
||||
if(firmSize == 0) shutdown(1, "Error: couldn't decrypt the CTRNAND FIRM");
|
||||
}
|
||||
firmSize = decryptExeFs((Cxi *)FIRM0_OFFSET);
|
||||
if(firmSize == 0) shutdown(1, "Error: couldn't decrypt the CTRNAND FIRM");
|
||||
|
||||
//writeFirm encrypts in-place, so we need two copies
|
||||
memcpy((void *)FIRM1_OFFSET, (void *)FIRM0_OFFSET, firmSize);
|
||||
|
@ -9,18 +9,17 @@
|
||||
#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];
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "screen.h"
|
||||
#include "cache.h"
|
||||
#include "utils.h"
|
||||
#include "memory.h"
|
||||
#include "i2c.h"
|
||||
|
||||
vu32 *arm11Entry = (vu32 *)BRAHMA_ARM11_ENTRY;
|
||||
@ -184,8 +185,6 @@ void initScreens(void)
|
||||
{
|
||||
invokeArm11Function(initSequence);
|
||||
|
||||
wait(3ULL);
|
||||
|
||||
//Turn on backlight
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
||||
}
|
||||
|
@ -91,4 +91,11 @@ start:
|
||||
mov r1, #0x340
|
||||
str r1, [r0]
|
||||
|
||||
@ Clear BSS
|
||||
ldr r0, =__bss_start
|
||||
mov r1, #0
|
||||
ldr r2, =__bss_end
|
||||
sub r2, r0
|
||||
bl memset32
|
||||
|
||||
b main
|
||||
|
@ -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();
|
||||
@ -65,8 +41,6 @@ void mcuReboot(void)
|
||||
//Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||
flushEntireDCache();
|
||||
|
||||
wait(3ULL);
|
||||
|
||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||
while(true);
|
||||
}
|
||||
|
@ -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