diff --git a/fusee_cpp/loader_stub/Makefile b/fusee_cpp/loader_stub/Makefile new file mode 100644 index 000000000..8cd08d11f --- /dev/null +++ b/fusee_cpp/loader_stub/Makefile @@ -0,0 +1,154 @@ +#--------------------------------------------------------------------------------- +# Define the atmosphere board and cpu +#--------------------------------------------------------------------------------- +export ATMOSPHERE_BOARD := nx-hac-001 +export ATMOSPHERE_CPU := arm7tdmi + +#--------------------------------------------------------------------------------- +# pull in common atmosphere configuration +#--------------------------------------------------------------------------------- +THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE))) +include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(__RECURSIVE__),1) +#--------------------------------------------------------------------------------- + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c) +CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp) +SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s) +BINFILES := + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) program.lz4.o +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES)))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I. + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR)) + +export TOPDIR := $(CURRENT_DIRECTORY) + +OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR)) + +#--------------------------------------------------------------------------------- + +ATMOSPHERE_BUILD_CONFIGS := +all: release + +define ATMOSPHERE_ADD_TARGET + +ATMOSPHERE_BUILD_CONFIGS += $(strip $1) + +$(strip $1): check_libexo_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) + @$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \ + ATMOSPHERE_BUILD_TARGET_IDENTIFIER=$(strip $1) \ + ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX=$(strip $2) \ + DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \ + LIBEXOSPHERE_NAME=exosphere$(strip $2) \ + --no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \ + -f $$(THIS_MAKEFILE) + +check_libexo_$(strip $1): + @$$(MAKE) --no-print-directory -C $$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere $$(ATMOSPHERE_ARCH_NAME)-$(strip $1) + +clean-$(strip $1): + @echo clean $(strip $1) ... + @rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf + +endef + +$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS" \ +)) + +$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_DEBUGGING" \ +)) + +$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_AUDITING" \ +)) + +$(ATMOSPHERE_BUILD_DIR)/%: + @[ -d $@ ] || mkdir -p $@ + +#--------------------------------------------------------------------------------- +clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config)) + +.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config)) + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBEXOSPHERE_NAME).a + +program.lz4.o: program_lz4.h + +program_lz4.h: $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4 + @echo $(notdir $<) + @rm -rf tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER) + @mkdir -p tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER) + @cp $(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4 tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/program.lz4 + @bin2s -a 8 -H program_lz4.h tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER)/program.lz4 | $(AS) -o program.lz4.o + @rm -rf tmp_program_$(ATMOSPHERE_BUILD_TARGET_IDENTIFIER) + +$(TOPDIR)/../program/program$(ATMOSPHERE_BUILD_TARGET_BINARY_SUFFIX).lz4: + @$(MAKE) __RECURSIVE__=0 --no-print-directory -C $(TOPDIR)/../program $(ATMOSPHERE_BUILD_TARGET_IDENTIFIER) + +%.elf: + @echo linking $(notdir $@) + $(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) program_lz4.h + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h: %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/fusee_cpp/loader_stub/loader_stub.ld b/fusee_cpp/loader_stub/loader_stub.ld new file mode 100644 index 000000000..97a1d9ae5 --- /dev/null +++ b/fusee_cpp/loader_stub/loader_stub.ld @@ -0,0 +1,125 @@ +OUTPUT_ARCH(arm) +ENTRY(_ZN3ams6nxboot6loader5StartEv) + +MEMORY +{ + NULL : ORIGIN = 0, LENGTH = 4K + data : ORIGIN = 0x40010000, LENGTH = 0x28000 + loader_stub : ORIGIN = 0x4003D000, LENGTH = 4K +} + + +SECTIONS +{ + /* =========== CODE section =========== */ + + . = ORIGIN(data); + __data_start__ = . ; + + .crt0 : + { + KEEP(*(.crt0 .crt0.*)) + . = ALIGN(8); + } >data + + /* =========== RODATA section =========== */ + . = ALIGN(8); + + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + . = ALIGN(8); + } >data + + .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >data + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >data + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >data + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >data + + .hash : { *(.hash) } >data + + /* =========== DATA section =========== */ + . = ALIGN(8); + + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >data + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >data + .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >data + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >data + + .data ALIGN(8) : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } >data + + __bss_start__ = .; + .bss (NOLOAD) : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(16); + } >data :NONE + __bss_end__ = .; + + __data_end__ = ABSOLUTE(.); + + + .loader_stub : + { + . = ALIGN(32); + PROVIDE (__loader_stub_start__ = ABSOLUTE(.)); + PROVIDE (__loader_stub_lma__ = LOADADDR(.loader_stub)); + fusee_loader_main.o(.text*) + fusee_loader_uncompress.o(.text*) + fusee_loader_error.o(.text*) + fusee_loader_main.o(.rodata*) + fusee_loader_uncompress.o(.rodata*) + fusee_loader_error.o(.rodata*) + fusee_loader_main.o(.data*) + fusee_loader_uncompress.o(.data*) + fusee_loader_error.o(.data*) + . = ALIGN(32); + PROVIDE (__loader_stub_end__ = ABSOLUTE(.)); + } >loader_stub AT>data + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note .interp) } + + /* 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) } +} \ No newline at end of file diff --git a/fusee_cpp/loader_stub/loader_stub.specs b/fusee_cpp/loader_stub/loader_stub.specs new file mode 100644 index 000000000..261cffccd --- /dev/null +++ b/fusee_cpp/loader_stub/loader_stub.specs @@ -0,0 +1,4 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /loader_stub.ld) --gc-sections --nmagic \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_error.cpp b/fusee_cpp/loader_stub/source/fusee_loader_error.cpp new file mode 100644 index 000000000..93d6b1859 --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_error.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#include "fusee_loader_error.hpp" + +namespace ams::diag { + + NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) { + AMS_UNUSED(file, line, func, expr, value, format); + ams::nxboot::loader::ErrorStop(); + } + + NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) { + AMS_UNUSED(file, line, func, expr, value); + ams::nxboot::loader::ErrorStop(); + } + + NORETURN void AbortImpl() { + ams::nxboot::loader::ErrorStop(); + } + +} + +namespace ams::nxboot::loader { + + NORETURN void ErrorStop() { + /* Halt ourselves. */ + while (true) { + reg::Write(secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress() + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP), + FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, ENABLED)); + } + } + +} \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_error.hpp b/fusee_cpp/loader_stub/source/fusee_loader_error.hpp new file mode 100644 index 000000000..83bfe6008 --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_error.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#pragma once + +namespace ams::nxboot::loader { + + NORETURN void ErrorStop(); + +} \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_main.cpp b/fusee_cpp/loader_stub/source/fusee_loader_main.cpp new file mode 100644 index 000000000..f58d5e1bd --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_main.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#include "fusee_loader_uncompress.hpp" +#include "program_lz4.h" + +namespace ams::nxboot::loader { + + namespace { + + constexpr uintptr_t ProgramImageBase = 0x40001000; + constexpr uintptr_t ProgramImageEnd = 0x4003D000; + constexpr size_t ProgramImageSizeMax = ProgramImageEnd - ProgramImageBase; + + void CopyBackwards(void *dst, const void *src, size_t size) { + /* We want to copy 32-bits at a time from destination to source. */ + const size_t words = util::DivideUp(size, sizeof(u32)); + + /* Convert to 32-bit pointers. */ + u32 *dst_32 = static_cast(dst) + words; + const u32 *src_32 = static_cast(src) + words; + + /* Copy data. */ + for (size_t i = 0; i < words; ++i) { + *(--dst_32) = *(--src_32); + } + } + + } + + NORETURN void UncompressAndExecute(const void *program, size_t program_size) { + /* Relocate the compressed binary to a place where we can safely decompress it. */ + void *relocated_program = reinterpret_cast(util::AlignDown(ProgramImageEnd - program_size, sizeof(u32))); + if (relocated_program != program) { + CopyBackwards(relocated_program, program, program_size); + } + + /* Uncompress the program image. */ + Uncompress(reinterpret_cast(ProgramImageBase), ProgramImageSizeMax, relocated_program, program_size); + + /* Jump to the boot image. */ + reinterpret_cast(ProgramImageBase)(); + + /* We will never reach this point. */ + __builtin_unreachable(); + } + +} \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_start.s b/fusee_cpp/loader_stub/source/fusee_loader_start.s new file mode 100644 index 000000000..70ced975e --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_start.s @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + + + +.section .crt0._ZN3ams6nxboot6loader5StartEv, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot6loader5StartEv +.type _ZN3ams6nxboot6loader5StartEv, %function +_ZN3ams6nxboot6loader5StartEv: + /* Switch to system mode, mask all interrupts, clear all flags */ + msr cpsr_cxsf, #0xDF + + /* Relocate loader stub. */ + ldr r0, =_ZN3ams6nxboot6loader5StartEv + adr r1, _ZN3ams6nxboot6loader5StartEv + ldr r2, =__loader_stub_lma__ + sub r2, r2, r0 + add r2, r2, r1 + + ldr r3, =__loader_stub_start__ + ldr r4, =__loader_stub_end__ + sub r4, r4, r3 + 0: + ldmia r2!, {r5-r12} + stmia r3!, {r5-r12} + subs r4, #0x20 + bne 0b + + /* Set the stack pointer */ + ldr sp, =0x40001000 + mov fp, #0 + + /* Generate arguments. */ + ldr r3, =program_lz4 + ldr r4, =program_lz4_end + sub r4, r4, r3 + sub r3, r3, r0 + add r3, r3, r1 + mov r0, r3 + mov r1, r4 + + /* Jump to the loader stub. */ + ldr r3, =_ZN3ams6nxboot6loader20UncompressAndExecuteEPKvj + bx r3 \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_uncompress.cpp b/fusee_cpp/loader_stub/source/fusee_loader_uncompress.cpp new file mode 100644 index 000000000..6926c2046 --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_uncompress.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#include "fusee_loader_uncompress.hpp" + +namespace ams::nxboot::loader { + + namespace { + + class Lz4Uncompressor { + private: + const u8 *src; + size_t src_size; + size_t src_offset; + u8 *dst; + size_t dst_size; + size_t dst_offset; + public: + Lz4Uncompressor(void *dst, size_t dst_size, const void *src, size_t src_size) : src(static_cast(src)), src_size(src_size), src_offset(0), dst(static_cast(dst)), dst_size(dst_size), dst_offset(0) { + /* ... */ + } + + void Uncompress() { + while (true) { + /* Read a control byte. */ + const u8 control = this->ReadByte(); + + /* Copy what it specifies we should copy. */ + this->Copy(this->GetCopySize(control >> 4)); + + /* If we've exceeded size, we're done. */ + if (this->src_offset >= this->src_size) { + break; + } + + /* Read the wide copy offset. */ + u16 wide_offset = this->ReadByte(); + AMS_ABORT_UNLESS(this->CanRead()); + wide_offset |= (this->ReadByte() << 8); + + /* Determine the copy size. */ + const size_t wide_copy_size = this->GetCopySize(control & 0xF); + + /* Copy bytes. */ + const size_t end_offset = this->dst_offset + wide_copy_size + 4; + for (size_t cur_offset = this->dst_offset; cur_offset < end_offset; this->dst_offset = (++cur_offset)) { + AMS_ABORT_UNLESS(wide_offset <= cur_offset); + + this->dst[cur_offset] = this->dst[cur_offset - wide_offset]; + } + } + } + private: + u8 ReadByte() { + return this->src[this->src_offset++]; + } + + bool CanRead() const { + return this->src_offset < this->src_size; + } + + size_t GetCopySize(u8 control) { + size_t size = control; + + if (control >= 0xF) { + do { + AMS_ABORT_UNLESS(this->CanRead()); + control = this->ReadByte(); + size += control; + } while (control == 0xFF); + } + + return size; + } + + void Copy(size_t size) { + __builtin_memcpy(this->dst + this->dst_offset, this->src + this->src_offset, size); + this->dst_offset += size; + this->src_offset += size; + } + }; + + } + + void Uncompress(void *dst, size_t dst_size, const void *src, size_t src_size) { + /* Create an execute a decompressor. */ + Lz4Uncompressor(dst, dst_size, src, src_size).Uncompress(); + } + +} \ No newline at end of file diff --git a/fusee_cpp/loader_stub/source/fusee_loader_uncompress.hpp b/fusee_cpp/loader_stub/source/fusee_loader_uncompress.hpp new file mode 100644 index 000000000..802e77180 --- /dev/null +++ b/fusee_cpp/loader_stub/source/fusee_loader_uncompress.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#pragma once + +namespace ams::nxboot::loader { + + void Uncompress(void *dst, size_t dst_size, const void *src, size_t src_size); + +} \ No newline at end of file diff --git a/fusee_cpp/program/Makefile b/fusee_cpp/program/Makefile new file mode 100644 index 000000000..f87cead16 --- /dev/null +++ b/fusee_cpp/program/Makefile @@ -0,0 +1,143 @@ +#--------------------------------------------------------------------------------- +# Define the atmosphere board and cpu +#--------------------------------------------------------------------------------- +export ATMOSPHERE_BOARD := nx-hac-001 +export ATMOSPHERE_CPU := arm7tdmi + +#--------------------------------------------------------------------------------- +# pull in common atmosphere configuration +#--------------------------------------------------------------------------------- +THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST))) +CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE))) +include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/exosphere.mk + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(__RECURSIVE__),1) +#--------------------------------------------------------------------------------- + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) $(CURDIR)/include \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +CFILES := $(call FIND_SOURCE_FILES,$(SOURCES),c) +CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp) +SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),s) +BINFILES := + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(subst -,_,$(BINFILES)))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I. + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/$(ATMOSPHERE_LIBRARY_DIR)) + +export TOPDIR := $(CURRENT_DIRECTORY) + +OUTPUT_BASE := $(TOPDIR)/$(notdir $(TOPDIR)) + +#--------------------------------------------------------------------------------- + +ATMOSPHERE_BUILD_CONFIGS := +all: release + +define ATMOSPHERE_ADD_TARGET + +ATMOSPHERE_BUILD_CONFIGS += $(strip $1) + +$(strip $1): check_libexo_$(strip $1) $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) + @$$(MAKE) __RECURSIVE__=1 OUTPUT=$$(OUTPUT_BASE)$(strip $2) $(3) \ + DEPSDIR=$$(CURDIR)/$$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \ + LIBEXOSPHERE_NAME=exosphere$(strip $2) \ + --no-print-directory -C $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) \ + -f $$(THIS_MAKEFILE) + +check_libexo_$(strip $1): + @$$(MAKE) --no-print-directory -C $$(ATMOSPHERE_LIBRARIES_DIR)/libexosphere $$(ATMOSPHERE_ARCH_NAME)-$(strip $1) + +clean-$(strip $1): + @echo clean $(strip $1) ... + @rm -fr $$(ATMOSPHERE_BUILD_DIR)/$(strip $1) $$(OUTPUT_BASE)$(strip $2).bin $$(OUTPUT_BASE)$(strip $2).elf + +endef + +$(eval $(call ATMOSPHERE_ADD_TARGET, release, , \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS" \ +)) + +$(eval $(call ATMOSPHERE_ADD_TARGET, debug, _debug, \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_DEBUGGING" \ +)) + +$(eval $(call ATMOSPHERE_ADD_TARGET, audit, _audit, \ + ATMOSPHERE_BUILD_SETTINGS="-DAMS_FORCE_DISABLE_DETAILED_ASSERTIONS -DAMS_BUILD_FOR_AUDITING" \ +)) + +$(ATMOSPHERE_BUILD_DIR)/%: + @[ -d $@ ] || mkdir -p $@ + +#--------------------------------------------------------------------------------- +clean: $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config)) + +.PHONY: all clean $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),$(config) clean-$(config)) + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- + +$(OUTPUT).lz4 : $(OUTPUT).bin + @python $(TOPDIR)/lz4_compress.py $(OUTPUT).bin $(OUTPUT).lz4 + @echo built ... $(notdir $@) + +$(OUTPUT).bin : $(OUTPUT).elf + $(OBJCOPY) -S -O binary --set-section-flags .bss=alloc,load,contents $< $@ + @echo built ... $(notdir $@) + +$(OUTPUT).elf : $(OFILES) + +$(OFILES) : $(ATMOSPHERE_LIBRARIES_DIR)/libexosphere/$(ATMOSPHERE_LIBRARY_DIR)/lib$(LIBEXOSPHERE_NAME).a + +%.elf: + @echo linking $(notdir $@) + $(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + @$(NM) -CSn $@ > $(notdir $*.lst) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h: %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/fusee_cpp/program/lz4_compress.py b/fusee_cpp/program/lz4_compress.py new file mode 100644 index 000000000..2bf17a64d --- /dev/null +++ b/fusee_cpp/program/lz4_compress.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +import sys, lz4 +from struct import unpack as up + +def lz4_compress(data): + try: + import lz4.block as block + except ImportError: + block = lz4.LZ4_compress + return block.compress(data, 'high_compression', store_size=False) + +def main(argc, argv): + if argc != 3: + print('Usage: %s in out' % argv[0]) + return 1 + with open(argv[1], 'rb') as f: + data = f.read() + with open(argv[2], 'wb') as f: + f.write(lz4_compress(data)) + return 0 + +if __name__ == '__main__': + sys.exit(main(len(sys.argv), sys.argv)) diff --git a/fusee_cpp/program/program.ld b/fusee_cpp/program/program.ld new file mode 100644 index 000000000..5a6ea3adf --- /dev/null +++ b/fusee_cpp/program/program.ld @@ -0,0 +1,184 @@ +OUTPUT_ARCH(arm) +ENTRY(_ZN3ams6nxboot5StartEv) + +MEMORY +{ + NULL : ORIGIN = 0, LENGTH = 4K + main : ORIGIN = 0x40001000, LENGTH = 0x2B000 + ovl : ORIGIN = 0x4002C000, LENGTH = 0x14000 +} + + +SECTIONS +{ + /* =========== CODE section =========== */ + PROVIDE(__start__ = ORIGIN(main)); + . = __start__; + __main_start__ = . ; + + .crt0 : + { + KEEP (*(.crt0 .crt0.*)) + . = ALIGN(8); + } >main + + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + . = ALIGN(8); + } >main + + .init : + { + KEEP( *(.init) ) + . = ALIGN(8); + } >main + + .plt : + { + *(.plt) + *(.iplt) + . = ALIGN(8); + } >main + + .fini : + { + KEEP( *(.fini) ) + . = ALIGN(8); + } >main + + + /* =========== RODATA section =========== */ + . = ALIGN(8); + __rodata_start = . ; + + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + . = ALIGN(8); + } >main + + .eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >main + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >main + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >main + + .hash : { *(.hash) } >main + + /* =========== DATA section =========== */ + . = ALIGN(8); + __data_start = . ; + + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >main + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >main + .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >main + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >main + + .preinit_array ALIGN(8) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } >main + + .init_array ALIGN(8) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } >main + + .fini_array ALIGN(8) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } >main + + .ctors ALIGN(8) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >main + + .dtors ALIGN(8) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >main + + __got_start__ = .; + + .got : { *(.got) *(.igot) } >main + .got.plt : { *(.got.plt) *(.igot.plt) } >main + + __got_end__ = .; + + .data ALIGN(8) : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } >main + + __bss_start__ = .; + .bss ALIGN(8) : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(16); + } >main + __bss_end__ = .; + + __main_end__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note .interp) } + + /* 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) } +} \ No newline at end of file diff --git a/fusee_cpp/program/program.specs b/fusee_cpp/program/program.specs new file mode 100644 index 000000000..7d174b721 --- /dev/null +++ b/fusee_cpp/program/program.specs @@ -0,0 +1,4 @@ +%rename link old_link + +*link: +%(old_link) -T %:getenv(TOPDIR /program.ld) --gc-sections --nmagic \ No newline at end of file diff --git a/fusee_cpp/program/source/fusee_crt0.cpp b/fusee_cpp/program/source/fusee_crt0.cpp new file mode 100644 index 000000000..791faa796 --- /dev/null +++ b/fusee_cpp/program/source/fusee_crt0.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include + +extern "C" void __libc_init_array(); + +namespace ams::nxboot::crt0 { + + void Initialize(uintptr_t bss_start, uintptr_t bss_end) { + /* TODO: Collect timing information? */ + + /* Clear bss. */ + std::memset(reinterpret_cast(bss_start), 0, bss_end - bss_start); + + /* Call init array. */ + __libc_init_array(); + } + +} diff --git a/fusee_cpp/program/source/fusee_exception_handler.cpp b/fusee_cpp/program/source/fusee_exception_handler.cpp new file mode 100644 index 000000000..d9cc0810c --- /dev/null +++ b/fusee_cpp/program/source/fusee_exception_handler.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#include "fusee_exception_handler.hpp" + +namespace ams::nxboot { + + NORETURN void ErrorStop() { + /* Halt ourselves. */ + while (true) { + reg::Write(secmon::MemoryRegionPhysicalDeviceFlowController.GetAddress() + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP), + FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, ENABLED)); + } + } + + NORETURN void ExceptionHandlerImpl(s32 which, u32 lr, u32 svc_lr) { + /* TODO */ + ErrorStop(); + } + +} + +namespace ams::diag { + + NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value, const char *format, ...) { + AMS_UNUSED(file, line, func, expr, value, format); + ams::nxboot::ErrorStop(); + } + + NORETURN void AbortImpl(const char *file, int line, const char *func, const char *expr, u64 value) { + AMS_UNUSED(file, line, func, expr, value); + ams::nxboot::ErrorStop(); + } + + NORETURN void AbortImpl() { + ams::nxboot::ErrorStop(); + } + +} \ No newline at end of file diff --git a/fusee_cpp/program/source/fusee_exception_handler.hpp b/fusee_cpp/program/source/fusee_exception_handler.hpp new file mode 100644 index 000000000..6695f1e5f --- /dev/null +++ b/fusee_cpp/program/source/fusee_exception_handler.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include +#pragma once + +namespace ams::nxboot::loader { + + NORETURN void ExceptionHandler(); + + NORETURN void ExceptionHandler0(); + NORETURN void ExceptionHandler1(); + NORETURN void ExceptionHandler2(); + NORETURN void ExceptionHandler3(); + NORETURN void ExceptionHandler4(); + NORETURN void ExceptionHandler5(); + NORETURN void ExceptionHandler6(); + NORETURN void ExceptionHandler7(); + +} \ No newline at end of file diff --git a/fusee_cpp/program/source/fusee_exception_handler_asm.s b/fusee_cpp/program/source/fusee_exception_handler_asm.s new file mode 100644 index 000000000..55836bf1d --- /dev/null +++ b/fusee_cpp/program/source/fusee_exception_handler_asm.s @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +.section .text._ZN3ams6nxboot17ExceptionHandlerNEl, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandlerNEl +.type _ZN3ams6nxboot17ExceptionHandlerNEl, %function +_ZN3ams6nxboot17ExceptionHandlerNEl: + /* Get the normal return address. */ + mov r1, lr + + /* Get the SVC return address. */ + msr cpsr_cf, #0xD3 + mov r2, lr + + /* Invoke the exception handler in abort mode. */ + msr cpsr_cf, #0xD7 + b _ZN3ams6nxboot20ExceptionHandlerImplElmm + + +.section .text._ZN3ams6nxboot16ExceptionHandlerEv, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot16ExceptionHandlerEv +.type _ZN3ams6nxboot16ExceptionHandlerEv, %function +_ZN3ams6nxboot16ExceptionHandlerEv: + mov r0, #-1 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler0Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler0Ev +.type _ZN3ams6nxboot17ExceptionHandler0Ev, %function +_ZN3ams6nxboot17ExceptionHandler0Ev: + mov r0, #0 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler1Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler1Ev +.type _ZN3ams6nxboot17ExceptionHandler1Ev, %function +_ZN3ams6nxboot17ExceptionHandler1Ev: + mov r0, #1 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler2Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler2Ev +.type _ZN3ams6nxboot17ExceptionHandler2Ev, %function +_ZN3ams6nxboot17ExceptionHandler2Ev: + mov r0, #2 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler3Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler3Ev +.type _ZN3ams6nxboot17ExceptionHandler3Ev, %function +_ZN3ams6nxboot17ExceptionHandler3Ev: + mov r0, #3 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler4Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler4Ev +.type _ZN3ams6nxboot17ExceptionHandler4Ev, %function +_ZN3ams6nxboot17ExceptionHandler4Ev: + mov r0, #4 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler5Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler5Ev +.type _ZN3ams6nxboot17ExceptionHandler5Ev, %function +_ZN3ams6nxboot17ExceptionHandler5Ev: + mov r0, #5 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler6Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler6Ev +.type _ZN3ams6nxboot17ExceptionHandler6Ev, %function +_ZN3ams6nxboot17ExceptionHandler6Ev: + mov r0, #6 + b _ZN3ams6nxboot17ExceptionHandlerNEl + +.section .text._ZN3ams6nxboot17ExceptionHandler7Ev, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot17ExceptionHandler7Ev +.type _ZN3ams6nxboot17ExceptionHandler7Ev, %function +_ZN3ams6nxboot17ExceptionHandler7Ev: + mov r0, #7 + b _ZN3ams6nxboot17ExceptionHandlerNEl diff --git a/fusee_cpp/program/source/fusee_main.cpp b/fusee_cpp/program/source/fusee_main.cpp new file mode 100644 index 000000000..f57175850 --- /dev/null +++ b/fusee_cpp/program/source/fusee_main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ +#include + +namespace ams::nxboot { + + void Main() { + /* TODO */ + AMS_INFINITE_LOOP(); + } + +} diff --git a/fusee_cpp/program/source/fusee_start.s b/fusee_cpp/program/source/fusee_start.s new file mode 100644 index 000000000..d1af31440 --- /dev/null +++ b/fusee_cpp/program/source/fusee_start.s @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope 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 . + */ + +.section .crt0._ZN3ams6nxboot5StartEv, "ax", %progbits +.arm +.align 5 +.global _ZN3ams6nxboot5StartEv +.type _ZN3ams6nxboot5StartEv, %function +_ZN3ams6nxboot5StartEv: + /* Setup all registers as = 0. */ + msr cpsr_f, #0xC0 + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0 + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + + /* Setup all modes as pointing to our exception handler. */ + msr cpsr_cf, #0xDF + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + msr cpsr_cf, #0xD2 + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + msr cpsr_cf, #0xD1 + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + msr cpsr_cf, #0xD7 + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + msr cpsr_cf, #0xDB + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + msr cpsr_cf, #0xD3 + ldr sp, =0x40001000 + ldr lr, =_ZN3ams6nxboot16ExceptionHandlerEv + + /* Perform runtime initialization. */ + ldr r0, =__bss_start__ + ldr r1, =__bss_end__ + bl _ZN3ams6nxboot4crt010InitializeEjj + + /* Perform nx boot procedure. */ + bl _ZN3ams6nxboot4MainEv diff --git a/libraries/config/templates/exosphere.mk b/libraries/config/templates/exosphere.mk index 91d3ce84d..27bd718be 100644 --- a/libraries/config/templates/exosphere.mk +++ b/libraries/config/templates/exosphere.mk @@ -17,7 +17,7 @@ CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) else ifeq ($(strip $(ATMOSPHERE_ARCH_NAME)),arm) DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE -SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Werror -fno-non-call-exceptions \ +SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -Werror -fno-non-call-exceptions \ -Wno-array-bounds \ -Wno-stringop-overflow \ -Wno-stringop-overread diff --git a/libraries/libexosphere/arm.mk b/libraries/libexosphere/arm.mk index 35592ce4b..6a42c37c6 100644 --- a/libraries/libexosphere/arm.mk +++ b/libraries/libexosphere/arm.mk @@ -16,7 +16,7 @@ include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../config/common.mk #--------------------------------------------------------------------------------- DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_EXOSPHERE -SETTINGS := $(ATMOSPHERE_SETTINGS) -Os -Wextra -Werror -flto -fno-non-call-exceptions \ +SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -Wextra -Werror -flto -fno-non-call-exceptions \ -Wno-array-bounds \ -Wno-stringop-overflow \ -Wno-stringop-overread