boot: functional exception handling/rebooting to payload

This commit is contained in:
Michael Scire 2019-05-02 17:55:50 -07:00
parent 9319463a6e
commit 505324f625
4 changed files with 123 additions and 4 deletions

View File

@ -16,6 +16,12 @@ ifneq (, $(strip $(shell git status --porcelain 2>/dev/null)))
AMSREV := $(AMSREV)-dirty
endif
define _bin2o
bin2s $< | $(AS) -o $(@)
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"_end[];" > `(echo $(<F) | tr . _ | tr - _)`.h
echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`"[];" >> `(echo $(<F) | tr . _ | tr - _)`.h
echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _ | tr - _)`_size";" >> `(echo $(<F) | tr . _ | tr - _)`.h
endef
#---------------------------------------------------------------------------------
# TARGET is the name of the output
@ -69,14 +75,14 @@ export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) $(TOPDIR)/../../fusee/fusee-primary
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) fusee-primary.bin
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
@ -116,18 +122,22 @@ else
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
endif
.PHONY: $(BUILD) clean all
.PHONY: $(BUILD) check_fusee clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
check_fusee:
@$(MAKE) -C $(TOPDIR)/../../fusee/fusee-primary all
$(BUILD): check_fusee
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@$(MAKE) -C $(TOPDIR)/../../fusee/fusee-primary clean
@rm -fr $(BUILD) $(TARGET).kip $(TARGET).elf
@ -149,6 +159,11 @@ $(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
fusee_primary.bin.o fusee_primary_bin.h: fusee-primary.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(_bin2o)
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)

View File

@ -24,6 +24,7 @@
#include <stratosphere.hpp>
#include "boot_functions.hpp"
#include "boot_reboot_manager.hpp"
extern "C" {
extern u32 __start__;
@ -50,6 +51,11 @@ void __libnx_exception_handler(ThreadExceptionDump *ctx) {
StratosphereCrashHandler(ctx);
}
void __libstratosphere_exception_handler(AtmosphereFatalErrorContext *ctx) {
/* We're boot sysmodule, so manually reboot to fatal error. */
BootRebootManager::RebootForFatalError(ctx);
}
void __libnx_initheap(void) {
void* addr = nx_inner_heap;
size_t size = nx_inner_heap_size;

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2018-2019 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 <switch.h>
#include <stratosphere.hpp>
#include <strings.h>
#include "boot_reboot_manager.hpp"
#include "fusee-primary_bin.h"
static u8 g_work_page[0x1000] __attribute__ ((aligned (0x1000)));
static void ClearIram() {
/* Make page FFs. */
memset(g_work_page, 0xFF, sizeof(g_work_page));
/* Overwrite all of IRAM with FFs. */
for (size_t ofs = 0; ofs < IRAM_SIZE; ofs += sizeof(g_work_page)) {
CopyToIram(IRAM_BASE + ofs, g_work_page, sizeof(g_work_page));
}
}
static void DoRebootToPayload() {
/* Ensure clean IRAM state. */
ClearIram();
/* Copy in payload. */
for (size_t ofs = 0; ofs < fusee_primary_bin_size; ofs += 0x1000) {
std::memcpy(g_work_page, &fusee_primary_bin[ofs], std::min(static_cast<size_t>(fusee_primary_bin_size - ofs), size_t(0x1000)));
CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, 0x1000);
}
RebootToIramPayload();
}
Result BootRebootManager::PerformReboot() {
DoRebootToPayload();
return ResultSuccess;
}
void BootRebootManager::RebootForFatalError(AtmosphereFatalErrorContext *ctx) {
/* Ensure clean IRAM state. */
ClearIram();
/* Copy in payload. */
for (size_t ofs = 0; ofs < fusee_primary_bin_size; ofs += 0x1000) {
std::memcpy(g_work_page, &fusee_primary_bin[ofs], std::min(static_cast<size_t>(fusee_primary_bin_size - ofs), size_t(0x1000)));
CopyToIram(IRAM_PAYLOAD_BASE + ofs, g_work_page, 0x1000);
}
std::memset(g_work_page, 0xCC, sizeof(g_work_page));
std::memcpy(g_work_page, ctx, sizeof(*ctx));
CopyToIram(IRAM_PAYLOAD_BASE + IRAM_PAYLOAD_MAX_SIZE, g_work_page, sizeof(g_work_page));
RebootToIramPayload();
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2019 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 <switch.h>
#include <stratosphere.hpp>
#define IRAM_BASE 0x40000000ull
#define IRAM_SIZE 0x40000
#define IRAM_PAYLOAD_MAX_SIZE 0x2E000
#define IRAM_PAYLOAD_BASE 0x40010000ull
class BootRebootManager {
public:
static Result PerformReboot();
static void RebootForFatalError(AtmosphereFatalErrorContext *ctx);
};