Merge the chainloader into the main ARM9 folder

This commit is contained in:
TuxSH 2018-05-22 17:51:57 +02:00
parent 020236742f
commit 55bd62d7a9
8 changed files with 273 additions and 95 deletions

View File

@ -40,7 +40,6 @@ endif
dir_source := source dir_source := source
dir_patches := patches dir_patches := patches
dir_arm11 := arm11 dir_arm11 := arm11
dir_chainloader := chainloader
dir_exceptions := exceptions dir_exceptions := exceptions
dir_arm9_exceptions := $(dir_exceptions)/arm9 dir_arm9_exceptions := $(dir_exceptions)/arm9
dir_k11_extension := k11_extension dir_k11_extension := k11_extension
@ -60,7 +59,7 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
$(call rwildcard, $(dir_source), *.s *.c))) $(call rwildcard, $(dir_source), *.s *.c)))
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/arm9_exceptions.bin.o
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi
@ -80,7 +79,6 @@ firm: $(dir_out)/boot.firm
.PHONY: clean .PHONY: clean
clean: clean:
@$(MAKE) -C $(dir_arm11) clean @$(MAKE) -C $(dir_arm11) clean
@$(MAKE) -C $(dir_chainloader) clean
@$(MAKE) -C $(dir_arm9_exceptions) clean @$(MAKE) -C $(dir_arm9_exceptions) clean
@$(MAKE) -C $(dir_k11_extension) clean @$(MAKE) -C $(dir_k11_extension) clean
@$(MAKE) -C $(dir_loader) clean @$(MAKE) -C $(dir_loader) clean
@ -92,7 +90,6 @@ clean:
.PRECIOUS: $(dir_build)/%.bin .PRECIOUS: $(dir_build)/%.bin
.PHONY: $(dir_arm11) .PHONY: $(dir_arm11)
.PHONY: $(dir_chainloader)
.PHONY: $(dir_arm9_exceptions) .PHONY: $(dir_arm9_exceptions)
.PHONY: $(dir_k11_extension) .PHONY: $(dir_k11_extension)
.PHONY: $(dir_loader) .PHONY: $(dir_loader)
@ -143,10 +140,6 @@ $(dir_build)/pxi.cxi: $(dir_pxi)
$(dir_build)/%.bin.o: $(dir_build)/%.bin $(dir_build)/%.bin.o: $(dir_build)/%.bin
@$(bin2o) @$(bin2o)
$(dir_build)/chainloader.bin: $(dir_chainloader)
@mkdir -p "$(@D)"
@$(MAKE) -C $<
$(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions) $(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions)
@mkdir -p "$(@D)" @mkdir -p "$(@D)"
@$(MAKE) -C $< @$(MAKE) -C $<

View File

@ -1,44 +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)/base_tools
name := $(shell basename $(CURDIR))
dir_source := source
dir_build := build
dir_out := ../$(dir_build)
ASFLAGS := -mcpu=arm946e-s
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostartfiles -Wl,--nmagic
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
$(OBJCOPY) -S -O binary $< $@
$(dir_build)/$(name).elf: $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
$(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) $<

View File

@ -1,21 +0,0 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x01FF9000;
__start__ = ABSOLUTE(.);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
. = ALIGN(4);
__end__ = ABSOLUTE(.);
__stack_top__ = 0x01FFB800;
__stack_bottom__ = 0x01FFA800;
}

186
linker.ld
View File

@ -1,15 +1,189 @@
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm) OUTPUT_ARCH(arm)
ENTRY(_start) ENTRY(_start)
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
MEMORY
{
NULL : ORIGIN = 0x00000000, LENGTH = 0x1000
main : ORIGIN = 0x08006000, LENGTH = 0x080F0000 - 0x08006000
itcm : ORIGIN = 0x01FF8000, LENGTH = 0x01FFB800 - 0x01FF8000 /* Unused ITCM slice. */
}
SECTIONS SECTIONS
{ {
. = 0x08006000; PROVIDE(__start__ = 0x08006000);
PROVIDE(__stack_top__ = 0x08100000);
PROVIDE(__stack_bottom__ = 0x080F0000);
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } . = __start__;
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } . = ALIGN(32);
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
.crt0 :
{
. = ALIGN(32);
KEEP( *(.text.start) )
KEEP( *(.init) )
. = ALIGN(4); . = ALIGN(4);
} >main
.itcm_loadable :
{
. = ALIGN(32);
PROVIDE (__itcm_start__ = .);
PROVIDE (__itcm_lma__ = LOADADDR(.itcm_loadable));
PROVIDE(__itcm_stack_top__ = 0x01FFB800);
PROVIDE(__itcm_stack_bottom__ = 0x01FFA800);
KEEP(*(.chainloader.text.start))
build/chainloader.o(.text*)
build/chainloader.o(.rodata*)
build/chainloader.o(.data*)
. = ALIGN(8);
} >itcm AT>main
.itcm_bss :
{
. = ALIGN(8);
PROVIDE (__itcm_bss_start__ = .);
build/chainloader.o(.bss* COMMON)
. = ALIGN(8);
PROVIDE (__itcm_end__ = .);
} >itcm AT>main
.text :
{
. = ALIGN(4);
/* .text */
*(.text)
*(.text.*)
*(.glue_7)
*(.glue_7t)
*(.stub)
*(.gnu.warning)
*(.gnu.linkonce.t*)
. = ALIGN(4);
/* .fini */
KEEP( *(.fini) )
. = ALIGN(4);
} >main
.rodata :
{
*(.rodata)
*(.roda)
*(.rodata.*)
*all.rodata*(*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(4);
} >main
.preinit_array ALIGN(4) :
{
PROVIDE (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
} >main
.init_array ALIGN(4) :
{
PROVIDE (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
PROVIDE (__init_array_end = .);
} >main
.fini_array ALIGN(4) :
{
PROVIDE (__fini_array_start = .);
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
PROVIDE (__fini_array_end = .);
} >main
.ctors ALIGN(4) :
{
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >main
.dtors ALIGN(4) :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >main
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >main
__exidx_start = .;
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >main
__exidx_end = .;
.data :
{
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(4);
} >main
.bss :
{
__bss_start__ = ALIGN(32);
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b*)
*(COMMON)
. = ALIGN(8);
__bss_end__ = .;
} >main
__end__ = ABSOLUTE(.) ;
/* ==================
==== Metadata ====
================== */
/* Discard sections that difficult post-processing */
/DISCARD/ : { *(.group .comment .note) }
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
} }

View File

@ -24,11 +24,37 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "memory.h" #include "chainloader.h"
#include "cache.h" #include "screen.h"
#include "firm.h"
void main(int argc, char **argv, Firm *firm) void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
#pragma GCC optimize (3)
static void *xmemcpy(void *dst, const void *src, u32 len)
{
const u8 *src8 = (const u8 *)src;
u8 *dst8 = (u8 *)dst;
for (u32 i = 0; i < len; i++) {
dst8[i] = src8[i];
}
return dst;
}
static void doLaunchFirm(Firm *firm, int argc, char **argv)
{
//Copy FIRM sections to respective memory locations
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
xmemcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
__builtin_unreachable();
}
void chainloader_main(int argc, char **argv, Firm *firm)
{ {
char *argvPassed[2], char *argvPassed[2],
absPath[24 + 255]; absPath[24 + 255];
@ -54,5 +80,5 @@ void main(int argc, char **argv, Firm *firm)
argvPassed[1] = (char *)&fbs; argvPassed[1] = (char *)&fbs;
} }
launchFirm(firm, argc, argvPassed); doLaunchFirm(firm, argc, argvPassed);
} }

View File

@ -27,5 +27,6 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include "firm.h"
void flushCaches(void); void chainload(int argc, char **argv, Firm *firm);

View File

@ -37,6 +37,7 @@
#include "crypto.h" #include "crypto.h"
#include "screen.h" #include "screen.h"
#include "fmt.h" #include "fmt.h"
#include "chainloader.h"
#include "../build/bundled.h" #include "../build/bundled.h"
static Firm *firm = (Firm *)0x20001000; static Firm *firm = (Firm *)0x20001000;
@ -528,12 +529,6 @@ u32 patch1x2xNativeAndSafeFirm(void)
void launchFirm(int argc, char **argv) void launchFirm(int argc, char **argv)
{ {
u32 *chainloaderAddress = (u32 *)0x01FF9000;
prepareArm11ForFirmlaunch(); prepareArm11ForFirmlaunch();
chainload(argc, argv, firm);
memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size);
// No need to flush caches here, the chainloader is in ITCM
((void (*)(int, char **, Firm *))chainloaderAddress)(argc, argv, firm);
} }

View File

@ -109,13 +109,67 @@ _start:
mcr p15, 0, r0, c1, c0, 0 @ write control register mcr p15, 0, r0, c1, c0, 0 @ write control register
@ Clear BSS @ Clear BSS
ldr r0, =__bss_start ldr r0, =__bss_start__
mov r1, #0 mov r1, #0
ldr r2, =__bss_end ldr r2, =__bss_end__
sub r2, r0 sub r2, r0
bl memset32 bl memset32
@ Set additional sections up
ldr r0, =__itcm_start__
ldr r1, =__itcm_lma__
ldr r2, =__itcm_bss_start__
sub r2, r0
bl memcpy
ldr r0, =__itcm_bss_start__
mov r1, #0
ldr r2, =__itcm_end__
sub r2, r0
bl memset32
@ bl __libc_init_array
mov r0, r9 mov r0, r9
mov r1, r10 mov r1, r10
mov r2, r11 mov r2, r11
b main b main
.section .chainloader.text.start, "ax", %progbits
.align 4
.global chainload
.type chainload, %function
chainload:
ldr sp, =__itcm_stack_top__
b chainloader_main
.global disableMpuAndJumpToEntrypoints
.type disableMpuAndJumpToEntrypoints, %function
disableMpuAndJumpToEntrypoints:
mov r4, r0
mov r5, r1
mov r6, r2
mov r7, r3
@ Flush caches
ldr r12, =0xFFFF0830
blx r12
ldr r12, =0xFFFF0AB4
blx r12
@ 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
@ Set the ARM11 entrypoint
mov r0, #0x20000000
str r7, [r0, #-4]
@ Jump to the ARM9 entrypoint
mov r0, r4
mov r1, r5
ldr r2, =0x3BEEF
bx r6