mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-03 08:08:39 -04:00
exo: implement start of mariko fatal handler
This commit is contained in:
parent
123ed80dc7
commit
7bcd5c6e3b
28 changed files with 1138 additions and 24 deletions
138
exosphere/mariko_fatal/Makefile
Normal file
138
exosphere/mariko_fatal/Makefile
Normal file
|
@ -0,0 +1,138 @@
|
|||
#---------------------------------------------------------------------------------
|
||||
# Define the atmosphere board and cpu
|
||||
#---------------------------------------------------------------------------------
|
||||
export ATMOSPHERE_BOARD := nx-hac-001
|
||||
export ATMOSPHERE_CPU := arm-cortex-a57
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# 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).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
|
||||
#---------------------------------------------------------------------------------------
|
227
exosphere/mariko_fatal/mariko_fatal.ld
Normal file
227
exosphere/mariko_fatal/mariko_fatal.ld
Normal file
|
@ -0,0 +1,227 @@
|
|||
OUTPUT_ARCH(aarch64)
|
||||
ENTRY(_start)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
NULL : ORIGIN = 0, LENGTH = 4K
|
||||
mariko_tzram : ORIGIN = 0x1F00D0000, LENGTH = 128K
|
||||
}
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* =========== CODE section =========== */
|
||||
PROVIDE(__start__ = ORIGIN(mariko_tzram));
|
||||
. = __start__;
|
||||
__code_start = . ;
|
||||
|
||||
.crt0 :
|
||||
{
|
||||
KEEP (*(.crt0 .crt0.*))
|
||||
KEEP (fatal_crt0_cpp.o(.text*))
|
||||
*(.crt0.rodata*)
|
||||
fatal_crt0_cpp.o(.rodata*)
|
||||
*(.crt0.data*)
|
||||
fatal_crt0_cpp.o(.data*)
|
||||
. = ALIGN(8);
|
||||
} >mariko_tzram
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.ctors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >mariko_tzram
|
||||
|
||||
.dtors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >mariko_tzram
|
||||
|
||||
.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);
|
||||
} >mariko_tzram
|
||||
|
||||
.init :
|
||||
{
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(8);
|
||||
} >mariko_tzram
|
||||
|
||||
.plt :
|
||||
{
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
. = ALIGN(8);
|
||||
} >mariko_tzram
|
||||
|
||||
.fini :
|
||||
{
|
||||
KEEP( *(.fini) )
|
||||
. = ALIGN(8);
|
||||
} >mariko_tzram
|
||||
|
||||
|
||||
/* =========== RODATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__rodata_start = . ;
|
||||
|
||||
.rodata :
|
||||
{
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
. = ALIGN(8);
|
||||
} >mariko_tzram
|
||||
|
||||
.eh_frame_hdr : { __eh_frame_hdr_start = .; *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) __eh_frame_hdr_end = .; } >mariko_tzram
|
||||
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } >mariko_tzram
|
||||
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } >mariko_tzram
|
||||
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } >mariko_tzram
|
||||
|
||||
.hash : { *(.hash) } >mariko_tzram
|
||||
|
||||
/* =========== DATA section =========== */
|
||||
. = ALIGN(8);
|
||||
__data_start = . ;
|
||||
|
||||
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } >mariko_tzram
|
||||
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } >mariko_tzram
|
||||
.gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } >mariko_tzram
|
||||
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } >mariko_tzram
|
||||
|
||||
.preinit_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.init_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.fini_array ALIGN(8) :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
} >mariko_tzram
|
||||
|
||||
.ctors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
} >mariko_tzram
|
||||
|
||||
.dtors ALIGN(8) :
|
||||
{
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
} >mariko_tzram
|
||||
|
||||
__got_start__ = .;
|
||||
|
||||
.got : { *(.got) *(.igot) } >mariko_tzram
|
||||
.got.plt : { *(.got.plt) *(.igot.plt) } >mariko_tzram
|
||||
|
||||
__got_end__ = .;
|
||||
|
||||
.data ALIGN(8) :
|
||||
{
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
SORT(CONSTRUCTORS)
|
||||
} >mariko_tzram
|
||||
|
||||
__bss_start__ = .;
|
||||
.bss ALIGN(8) :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(16);
|
||||
} >mariko_tzram
|
||||
__bss_end__ = .;
|
||||
|
||||
__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) }
|
||||
}
|
7
exosphere/mariko_fatal/mariko_fatal.specs
Normal file
7
exosphere/mariko_fatal/mariko_fatal.specs
Normal file
|
@ -0,0 +1,7 @@
|
|||
%rename link old_link
|
||||
|
||||
*link:
|
||||
%(old_link) -T %:getenv(TOPDIR /mariko_fatal.ld) --gc-sections --nmagic -nostdlib -nostartfiles
|
||||
|
||||
*startfile:
|
||||
crti%O%s crtbegin%O%s
|
29
exosphere/mariko_fatal/source/fatal_abort_impl.cpp
Normal file
29
exosphere/mariko_fatal/source/fatal_abort_impl.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
|
||||
namespace ams::diag {
|
||||
|
||||
void AbortImpl() {
|
||||
AMS_SECMON_LOG("AbortImpl was called\n");
|
||||
|
||||
/* TODO: Reboot */
|
||||
AMS_INFINITE_LOOP();
|
||||
}
|
||||
|
||||
#include <exosphere/diag/diag_detailed_assertion_impl.inc>
|
||||
|
||||
}
|
32
exosphere/mariko_fatal/source/fatal_crt0.s
Normal file
32
exosphere/mariko_fatal/source/fatal_crt0.s
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
.section .crt0.text.start, "ax", %progbits
|
||||
.align 6
|
||||
.global _start
|
||||
_start:
|
||||
/* Set the stack pointer to a temporary location. */
|
||||
ldr x20, =0x1F00FC000
|
||||
mov sp, x20
|
||||
|
||||
/* Initialize all memory to expected state. */
|
||||
ldr x0, =__bss_start__
|
||||
ldr x1, =__bss_end__
|
||||
bl _ZN3ams6secmon5fatal10InitializeEmm
|
||||
|
||||
/* Jump to the fatal program. */
|
||||
ldr x16, =_ZN3ams6secmon5fatal4MainEv
|
||||
br x16
|
30
exosphere/mariko_fatal/source/fatal_crt0_cpp.cpp
Normal file
30
exosphere/mariko_fatal/source/fatal_crt0_cpp.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
|
||||
extern "C" void __libc_init_array();
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
void Initialize(uintptr_t bss_start, size_t bss_end) {
|
||||
/* Clear bss. */
|
||||
std::memset(reinterpret_cast<void *>(bss_start), 0, bss_end - bss_start);
|
||||
|
||||
/* Call init array. */
|
||||
__libc_init_array();
|
||||
}
|
||||
|
||||
}
|
307
exosphere/mariko_fatal/source/fatal_device_page_table.cpp
Normal file
307
exosphere/mariko_fatal/source/fatal_device_page_table.cpp
Normal file
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Definitions. */
|
||||
constexpr size_t PageDirectorySize = mmu::PageSize;
|
||||
constexpr size_t PageTableSize = mmu::PageSize;
|
||||
static_assert(PageDirectorySize == mmu::PageSize);
|
||||
|
||||
using DeviceVirtualAddress = u64;
|
||||
|
||||
constexpr size_t AsidCount = 0x80;
|
||||
constexpr size_t PhysicalAddressBits = 34;
|
||||
constexpr size_t PhysicalAddressMask = (1ul << PhysicalAddressBits) - 1ul;
|
||||
constexpr size_t DeviceVirtualAddressBits = 34;
|
||||
constexpr size_t DeviceVirtualAddressMask = (1ul << DeviceVirtualAddressBits) - 1ul;
|
||||
|
||||
constexpr size_t DevicePageBits = 12;
|
||||
constexpr size_t DevicePageSize = (1ul << DevicePageBits);
|
||||
static_assert(DevicePageSize == mmu::PageSize);
|
||||
|
||||
constexpr size_t DeviceLargePageBits = 22;
|
||||
constexpr size_t DeviceLargePageSize = (1ul << DeviceLargePageBits);
|
||||
static_assert(DeviceLargePageSize % DevicePageSize == 0);
|
||||
|
||||
constexpr size_t DeviceRegionBits = 32;
|
||||
constexpr size_t DeviceRegionSize = (1ul << DeviceRegionBits);
|
||||
static_assert(DeviceRegionSize % DeviceLargePageSize == 0);
|
||||
|
||||
constexpr const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
|
||||
|
||||
constexpr size_t TableCount = (1ul << DeviceVirtualAddressBits) / DeviceRegionSize;
|
||||
|
||||
constexpr u8 SdmmcAsid = 1;
|
||||
|
||||
constexpr u32 SdmmcAsidRegisterValue = [] {
|
||||
u32 value = 0x80000000u;
|
||||
for (size_t t = 0; t < TableCount; t++) {
|
||||
value |= (SdmmcAsid << (BITSIZEOF(u8) * t));
|
||||
}
|
||||
return value;
|
||||
}();
|
||||
|
||||
constexpr dd::PhysicalAddress SdmmcL0PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L0DevicePageTable.GetAddress();
|
||||
constexpr dd::PhysicalAddress SdmmcL1PageTablePhysical = MemoryRegionPhysicalDramSdmmc1L1DevicePageTable.GetAddress();
|
||||
|
||||
/* Types. */
|
||||
class EntryBase {
|
||||
protected:
|
||||
enum Bit : u32 {
|
||||
Bit_Table = 28,
|
||||
Bit_NonSecure = 29,
|
||||
Bit_Writeable = 30,
|
||||
Bit_Readable = 31,
|
||||
};
|
||||
private:
|
||||
u32 value;
|
||||
protected:
|
||||
constexpr ALWAYS_INLINE u32 SelectBit(Bit n) const {
|
||||
return (this->value & (1u << n));
|
||||
}
|
||||
|
||||
constexpr ALWAYS_INLINE bool GetBit(Bit n) const {
|
||||
return this->SelectBit(n) != 0;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 EncodeBit(Bit n, bool en) {
|
||||
return en ? (1u << n) : 0;
|
||||
}
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 EncodeValue(bool r, bool w, bool ns, dd::PhysicalAddress addr, bool t) {
|
||||
return EncodeBit(Bit_Readable, r) | EncodeBit(Bit_Writeable, w) | EncodeBit(Bit_NonSecure, ns) | EncodeBit(Bit_Table, t) | static_cast<u32>(addr >> DevicePageBits);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetValue(u32 v) {
|
||||
/* Prevent re-ordering around entry modifications. */
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
this->value = v;
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
}
|
||||
public:
|
||||
static constexpr ALWAYS_INLINE u32 EncodePtbDataValue(dd::PhysicalAddress addr) {
|
||||
return EncodeValue(true, true, true, addr, false);
|
||||
}
|
||||
public:
|
||||
constexpr ALWAYS_INLINE bool IsNonSecure() const { return this->GetBit(Bit_NonSecure); }
|
||||
constexpr ALWAYS_INLINE bool IsWriteable() const { return this->GetBit(Bit_Writeable); }
|
||||
constexpr ALWAYS_INLINE bool IsReadable() const { return this->GetBit(Bit_Readable); }
|
||||
constexpr ALWAYS_INLINE bool IsValid() const { return this->IsWriteable() || this->IsReadable(); }
|
||||
|
||||
constexpr ALWAYS_INLINE u32 GetAttributes() const { return this->SelectBit(Bit_NonSecure) | this->SelectBit(Bit_Writeable) | this->SelectBit(Bit_Readable); }
|
||||
|
||||
constexpr ALWAYS_INLINE dd::PhysicalAddress GetPhysicalAddress() const { return (static_cast<u64>(this->value) << DevicePageBits) & PhysicalAddressMask; }
|
||||
|
||||
ALWAYS_INLINE void Invalidate() { this->SetValue(0); }
|
||||
};
|
||||
|
||||
class PageDirectoryEntry : public EntryBase {
|
||||
public:
|
||||
constexpr ALWAYS_INLINE bool IsTable() const { return this->GetBit(Bit_Table); }
|
||||
|
||||
ALWAYS_INLINE void SetTable(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
|
||||
AMS_ASSERT(util::IsAligned(addr, DevicePageSize));
|
||||
this->SetValue(EncodeValue(r, w, ns, addr, true));
|
||||
}
|
||||
|
||||
ALWAYS_INLINE void SetLargePage(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
|
||||
AMS_ASSERT(util::IsAligned(addr, DeviceLargePageSize));
|
||||
this->SetValue(EncodeValue(r, w, ns, addr, false));
|
||||
}
|
||||
};
|
||||
|
||||
class PageTableEntry : public EntryBase {
|
||||
public:
|
||||
ALWAYS_INLINE void SetPage(bool r, bool w, bool ns, dd::PhysicalAddress addr) {
|
||||
AMS_ASSERT(util::IsAligned(addr, DevicePageSize));
|
||||
this->SetValue(EncodeValue(r, w, ns, addr, true));
|
||||
}
|
||||
};
|
||||
|
||||
/* Memory controller access functionality. */
|
||||
void WriteMcRegister(size_t offset, u32 value) {
|
||||
reg::Write(MC + offset, value);
|
||||
}
|
||||
|
||||
u32 ReadMcRegister(size_t offset) {
|
||||
return reg::Read(MC + offset);
|
||||
}
|
||||
|
||||
/* Memory controller utilities. */
|
||||
void SmmuSynchronizationBarrier() {
|
||||
ReadMcRegister(MC_SMMU_CONFIG);
|
||||
}
|
||||
|
||||
void InvalidatePtc() {
|
||||
WriteMcRegister(MC_SMMU_PTC_FLUSH_0, 0);
|
||||
}
|
||||
|
||||
void InvalidatePtc(dd::PhysicalAddress address) {
|
||||
WriteMcRegister(MC_SMMU_PTC_FLUSH_1, (static_cast<u64>(address) >> 32));
|
||||
WriteMcRegister(MC_SMMU_PTC_FLUSH_0, (address & 0xFFFFFFF0u) | 1u);
|
||||
}
|
||||
|
||||
enum TlbFlushVaMatch : u32 {
|
||||
TlbFlushVaMatch_All = 0,
|
||||
TlbFlushVaMatch_Section = 2,
|
||||
TlbFlushVaMatch_Group = 3,
|
||||
};
|
||||
|
||||
static constexpr ALWAYS_INLINE u32 EncodeTlbFlushValue(bool match_asid, u8 asid, dd::PhysicalAddress address, TlbFlushVaMatch match) {
|
||||
return ((match_asid ? 1u : 0u) << 31) | ((asid & 0x7F) << 24) | (((address & 0xFFC00000u) >> DevicePageBits)) | (match);
|
||||
}
|
||||
|
||||
void InvalidateTlb() {
|
||||
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(false, 0, 0, TlbFlushVaMatch_All));
|
||||
}
|
||||
|
||||
void InvalidateTlb(u8 asid) {
|
||||
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(true, asid, 0, TlbFlushVaMatch_All));
|
||||
}
|
||||
|
||||
void InvalidateTlbSection(u8 asid, dd::PhysicalAddress address) {
|
||||
return WriteMcRegister(MC_SMMU_TLB_FLUSH, EncodeTlbFlushValue(true, asid, address, TlbFlushVaMatch_Section));
|
||||
}
|
||||
|
||||
void SetTable(u8 asid, dd::PhysicalAddress address) {
|
||||
/* Write the table address. */
|
||||
{
|
||||
WriteMcRegister(MC_SMMU_PTB_ASID, asid);
|
||||
WriteMcRegister(MC_SMMU_PTB_DATA, EntryBase::EncodePtbDataValue(address));
|
||||
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
|
||||
/* Ensure consistency. */
|
||||
InvalidatePtc();
|
||||
InvalidateTlb(asid);
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
|
||||
void MapImpl(dd::PhysicalAddress phys_addr, size_t size, DeviceVirtualAddress address) {
|
||||
/* Cache permissions. */
|
||||
const bool read = true;
|
||||
const bool write = true;
|
||||
|
||||
/* Walk the directory. */
|
||||
u64 remaining = size;
|
||||
while (remaining > 0) {
|
||||
const size_t l1_index = (address % DeviceRegionSize) / DeviceLargePageSize;
|
||||
const size_t l2_index = (address % DeviceLargePageSize) / DevicePageSize;
|
||||
|
||||
/* Get and validate l1. */
|
||||
PageDirectoryEntry *l1 = static_cast<PageDirectoryEntry *>(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>());
|
||||
AMS_ASSERT(l1 != nullptr);
|
||||
|
||||
/* Setup an l1 table/entry, if needed. */
|
||||
if (!l1[l1_index].IsTable()) {
|
||||
/* Check that an entry doesn't already exist. */
|
||||
AMS_ASSERT(!l1[l1_index].IsValid());
|
||||
|
||||
/* If we can make an l1 entry, do so. */
|
||||
if (l2_index == 0 && util::IsAligned(phys_addr, DeviceLargePageSize) && remaining >= DeviceLargePageSize) {
|
||||
/* Set the large page. */
|
||||
l1[l1_index].SetLargePage(read, write, true, phys_addr);
|
||||
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Advance. */
|
||||
phys_addr += DeviceLargePageSize;
|
||||
address += DeviceLargePageSize;
|
||||
remaining -= DeviceLargePageSize;
|
||||
continue;
|
||||
} else {
|
||||
/* Make an l1 table. */
|
||||
std::memset(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
|
||||
hw::FlushDataCache(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>(), mmu::PageSize);
|
||||
|
||||
/* Set the l1 table. */
|
||||
l1[l1_index].SetTable(true, true, true, SdmmcL1PageTablePhysical);
|
||||
hw::FlushDataCache(std::addressof(l1[l1_index]), sizeof(PageDirectoryEntry));
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical);
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get to this point, l1 must be a table. */
|
||||
AMS_ASSERT(l1[l1_index].IsTable());
|
||||
|
||||
/* Map l2 entries. */
|
||||
{
|
||||
PageTableEntry *l2 = static_cast<PageTableEntry *>(MemoryRegionVirtualDramSdmmc1L1DevicePageTable.GetPointer<void>());
|
||||
|
||||
const size_t remaining_in_entry = (PageTableSize / sizeof(PageTableEntry)) - l2_index;
|
||||
const size_t map_count = std::min<size_t>(remaining_in_entry, remaining / DevicePageSize);
|
||||
|
||||
/* Set the entries. */
|
||||
for (size_t i = 0; i < map_count; ++i) {
|
||||
AMS_ASSERT(!l2[l2_index + i].IsValid());
|
||||
l2[l2_index + i].SetPage(read, write, true, phys_addr + DevicePageSize * i);
|
||||
}
|
||||
hw::FlushDataCache(std::addressof(l2[l2_index]), map_count * sizeof(PageTableEntry));
|
||||
|
||||
/* Invalidate the page table cache. */
|
||||
for (size_t i = util::AlignDown(l2_index, 4); i <= util::AlignDown(l2_index + map_count - 1, 4); i += 4) {
|
||||
InvalidatePtc(SdmmcL1PageTablePhysical + i * sizeof(PageTableEntry));
|
||||
}
|
||||
|
||||
/* Synchronize. */
|
||||
InvalidateTlbSection(SdmmcAsid, address);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Advance. */
|
||||
phys_addr += map_count * DevicePageSize;
|
||||
address += map_count * DevicePageSize;
|
||||
remaining -= map_count * DevicePageSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void InitializeDevicePageTableForSdmmc1() {
|
||||
/* Configure sdmmc to use our new page table. */
|
||||
WriteMcRegister(MC_SMMU_SDMMC1A_ASID, SdmmcAsidRegisterValue);
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Ensure consistency. */
|
||||
InvalidatePtc();
|
||||
InvalidateTlb();
|
||||
SmmuSynchronizationBarrier();
|
||||
|
||||
/* Clear the L0 Page Table. */
|
||||
std::memset(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), 0, mmu::PageSize);
|
||||
hw::FlushDataCache(MemoryRegionVirtualDramSdmmc1L0DevicePageTable.GetPointer<void>(), mmu::PageSize);
|
||||
|
||||
/* Set the page table for the sdmmc asid. */
|
||||
SetTable(SdmmcAsid, SdmmcL0PageTablePhysical);
|
||||
|
||||
/* Map the appropriate region into the asid. */
|
||||
MapImpl(MemoryRegionPhysicalDramSdmmcMappedData.GetAddress(), MemoryRegionPhysicalDramSdmmcMappedData.GetSize(), MemoryRegionVirtualDramSdmmcMappedData.GetAddress());
|
||||
}
|
||||
|
||||
}
|
23
exosphere/mariko_fatal/source/fatal_device_page_table.hpp
Normal file
23
exosphere/mariko_fatal/source/fatal_device_page_table.hpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <exosphere.hpp>
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
void InitializeDevicePageTableForSdmmc1();
|
||||
|
||||
}
|
50
exosphere/mariko_fatal/source/fatal_main.cpp
Normal file
50
exosphere/mariko_fatal/source/fatal_main.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#include "fatal_sdmmc.hpp"
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
void Main() {
|
||||
/* Set library register addresses. */
|
||||
actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress());
|
||||
clkrst::SetRegisterAddress(MemoryRegionVirtualDeviceClkRst.GetAddress());
|
||||
flow::SetRegisterAddress(MemoryRegionVirtualDeviceFlowController.GetAddress());
|
||||
fuse::SetRegisterAddress(MemoryRegionVirtualDeviceFuses.GetAddress());
|
||||
gic::SetRegisterAddress(MemoryRegionVirtualDeviceGicDistributor.GetAddress(), MemoryRegionVirtualDeviceGicCpuInterface.GetAddress());
|
||||
i2c::SetRegisterAddress(i2c::Port_1, MemoryRegionVirtualDeviceI2c1.GetAddress());
|
||||
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
|
||||
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
|
||||
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
|
||||
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress(), MemoryRegionVirtualDeviceSecurityEngine2.GetAddress());
|
||||
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());
|
||||
wdt::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
||||
util::SetRegisterAddress(MemoryRegionVirtualDeviceTimer.GetAddress());
|
||||
|
||||
/* Ensure that the log library is initialized. */
|
||||
log::Initialize();
|
||||
|
||||
AMS_SECMON_LOG("%s\n", "Fatal start.");
|
||||
|
||||
/* Initialize the sdmmc driver. */
|
||||
Result result = InitializeSdCard();
|
||||
AMS_SECMON_LOG("InitializeSdCard: %08x\n", result.GetValue());
|
||||
|
||||
/* TODO */
|
||||
AMS_INFINITE_LOOP();
|
||||
}
|
||||
|
||||
}
|
50
exosphere/mariko_fatal/source/fatal_sdmmc.cpp
Normal file
50
exosphere/mariko_fatal/source/fatal_sdmmc.cpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <exosphere.hpp>
|
||||
#include "fatal_device_page_table.hpp"
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline auto Port = sdmmc::Port_SdCard0;
|
||||
|
||||
ALWAYS_INLINE u8 *GetSdCardWorkBuffer() {
|
||||
return MemoryRegionVirtualDramSdmmcMappedData.GetPointer<u8>() + MemoryRegionVirtualDramSdmmcMappedData.GetSize() - mmu::PageSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Result InitializeSdCard() {
|
||||
/* Map main memory for the sdmmc device. */
|
||||
AMS_SECMON_LOG("%s\n", "Initializing Device Page Table.");
|
||||
InitializeDevicePageTableForSdmmc1();
|
||||
AMS_SECMON_LOG("%s\n", "Initialized Device Page Table.");
|
||||
|
||||
/* Initialize sdmmc library. */
|
||||
sdmmc::Initialize(Port);
|
||||
AMS_SECMON_LOG("%s\n", "Initialized Sdmmc Port.");
|
||||
|
||||
sdmmc::SetSdCardWorkBuffer(Port, GetSdCardWorkBuffer(), sdmmc::SdCardWorkBufferSize);
|
||||
AMS_SECMON_LOG("%s\n", "Set SD Card Work Buffer.");
|
||||
|
||||
R_TRY(sdmmc::Activate(Port));
|
||||
AMS_SECMON_LOG("%s\n", "Activated.");
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
23
exosphere/mariko_fatal/source/fatal_sdmmc.hpp
Normal file
23
exosphere/mariko_fatal/source/fatal_sdmmc.hpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <exosphere.hpp>
|
||||
|
||||
namespace ams::secmon::fatal {
|
||||
|
||||
Result InitializeSdCard();
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue