mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 08:22:04 +00:00
exosphere: properly implement reboot-to-payload
This commit is contained in:
parent
c9c8f64f09
commit
c6f06e2c40
8 changed files with 262 additions and 11 deletions
|
@ -76,14 +76,15 @@ export TOPDIR := $(CURDIR)
|
||||||
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \
|
||||||
$(TOPDIR)/lp0fw \
|
$(TOPDIR)/lp0fw \
|
||||||
$(TOPDIR)/sc7fw
|
$(TOPDIR)/sc7fw \
|
||||||
|
$(TOPDIR)/rebootstub
|
||||||
|
|
||||||
export DEPSDIR := $(CURDIR)/$(BUILD)
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) sc7fw.bin lp0fw.bin rebootstub.bin
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# use CXX for linking C++ projects, CC for standard C
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
@ -110,7 +111,7 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
.PHONY: $(BUILD) build_sc7fw build_lp0fw clean all
|
.PHONY: $(BUILD) build_sc7fw build_lp0fw build_rebootstub clean all
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
all: $(BUILD)
|
all: $(BUILD)
|
||||||
|
@ -121,7 +122,10 @@ check_sc7fw:
|
||||||
check_lp0fw:
|
check_lp0fw:
|
||||||
@$(MAKE) -C lp0fw all
|
@$(MAKE) -C lp0fw all
|
||||||
|
|
||||||
$(BUILD): check_sc7fw check_lp0fw
|
check_rebootstub:
|
||||||
|
@$(MAKE) -C lp0fw all
|
||||||
|
|
||||||
|
$(BUILD): check_sc7fw check_lp0fw check_rebootstub
|
||||||
@[ -d $@ ] || mkdir -p $@
|
@[ -d $@ ] || mkdir -p $@
|
||||||
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
@ -130,6 +134,7 @@ clean:
|
||||||
@echo clean ...
|
@echo clean ...
|
||||||
@$(MAKE) -C $(TOPDIR)/sc7fw clean
|
@$(MAKE) -C $(TOPDIR)/sc7fw clean
|
||||||
@$(MAKE) -C $(TOPDIR)/lp0fw clean
|
@$(MAKE) -C $(TOPDIR)/lp0fw clean
|
||||||
|
@$(MAKE) -C $(TOPDIR)/rebootstub clean
|
||||||
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
|
154
exosphere/rebootstub/Makefile
Normal file
154
exosphere/rebootstub/Makefile
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := src
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||||
|
|
||||||
|
CFLAGS := \
|
||||||
|
-g \
|
||||||
|
-O2 \
|
||||||
|
-ffunction-sections \
|
||||||
|
-fdata-sections \
|
||||||
|
-fomit-frame-pointer \
|
||||||
|
-fno-inline \
|
||||||
|
-std=gnu11 \
|
||||||
|
-Werror \
|
||||||
|
-Wall \
|
||||||
|
$(ARCH) $(DEFINES)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -D__BPMP__
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
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)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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 .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@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
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
18
exosphere/rebootstub/linker.ld
Normal file
18
exosphere/rebootstub/linker.ld
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
|
||||||
|
ENTRY(_start)
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x4003F000;
|
||||||
|
|
||||||
|
__start__ = ABSOLUTE(.);
|
||||||
|
|
||||||
|
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
||||||
|
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
||||||
|
.bss : ALIGN(8) { __bss_start__ = .; *(.bss* COMMON); . = ALIGN(8); __bss_end__ = .; }
|
||||||
|
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
__end__ = ABSOLUTE(.);
|
||||||
|
}
|
7
exosphere/rebootstub/linker.specs
Normal file
7
exosphere/rebootstub/linker.specs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
45
exosphere/rebootstub/src/start.s
Normal file
45
exosphere/rebootstub/src/start.s
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 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 .text.start
|
||||||
|
.align 4
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
b crt0
|
||||||
|
|
||||||
|
.global crt0
|
||||||
|
.type crt0, %function
|
||||||
|
crt0:
|
||||||
|
@ clear all registers
|
||||||
|
ldr r0, =0x52425430 @ RBT0
|
||||||
|
mov r1, #0x0
|
||||||
|
mov r2, #0x0
|
||||||
|
mov r3, #0x0
|
||||||
|
mov r4, #0x0
|
||||||
|
mov r5, #0x0
|
||||||
|
mov r6, #0x0
|
||||||
|
mov r7, #0x0
|
||||||
|
mov r8, #0x0
|
||||||
|
mov r9, #0x0
|
||||||
|
mov r10, #0x0
|
||||||
|
mov r11, #0x0
|
||||||
|
mov r12, #0x0
|
||||||
|
mov lr, #0x0
|
||||||
|
ldr sp, =0x40010000
|
||||||
|
ldr pc, =0x40010000
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,14 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "masterkey.h"
|
#include "masterkey.h"
|
||||||
#include "exocfg.h"
|
#include "exocfg.h"
|
||||||
|
#include "smc_ams.h"
|
||||||
|
#include "arm.h"
|
||||||
|
|
||||||
|
#define u8 uint8_t
|
||||||
|
#define u32 uint32_t
|
||||||
|
#include "rebootstub_bin.h"
|
||||||
|
#undef u8
|
||||||
|
#undef u32
|
||||||
|
|
||||||
static bool g_battery_profile = false;
|
static bool g_battery_profile = false;
|
||||||
static bool g_debugmode_override_user = false, g_debugmode_override_priv = false;
|
static bool g_debugmode_override_user = false, g_debugmode_override_priv = false;
|
||||||
|
@ -48,11 +56,22 @@ uint32_t configitem_set(bool privileged, ConfigItem item, uint64_t value) {
|
||||||
case REBOOT_KIND_TO_WB_PAYLOAD:
|
case REBOOT_KIND_TO_WB_PAYLOAD:
|
||||||
/* Set reboot kind = warmboot. */
|
/* Set reboot kind = warmboot. */
|
||||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1;
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x450ull) = 0x1;
|
||||||
/* Patch bootrom to jump to payload. */
|
/* Patch SDRAM init to perform an SVC immediately after second write */
|
||||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x630ull) = 0x0010171B; /* Return to bootrom IRAM initialization func. */
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x2E38DFFF;
|
||||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x634ull) = 0x4000FFA4; /* Overwrite bootrom return address on stack. */
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x6001DC28;
|
||||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x638ull) = 0x40010000; /* Return to start of payload. */
|
/* Set SVC handler to jump to reboot stub in IRAM. */
|
||||||
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x63Cull) = 0x4000FFB4; /* Overwrite bootrom return address on stack. */
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x520ull) = 0x4003F000;
|
||||||
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_RTC_PMC) + 0x53Cull) = 0x6000F208;
|
||||||
|
|
||||||
|
/* Copy reboot stub payload. */
|
||||||
|
ams_map_irampage(0x4003F000);
|
||||||
|
for (unsigned int i = 0; i < rebootstub_bin_size; i += 4) {
|
||||||
|
MAKE_REG32(MMIO_GET_DEVICE_ADDRESS(MMIO_DEVID_AMS_IRAM_PAGE) + i) = read32le(rebootstub_bin, i);
|
||||||
|
}
|
||||||
|
ams_unmap_irampage();
|
||||||
|
|
||||||
|
/* Ensure stub is flushed. */
|
||||||
|
flush_dcache_all();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 2;
|
return 2;
|
||||||
|
|
|
@ -72,7 +72,7 @@ static void ams_unmap_userpage(void) {
|
||||||
lock_release(&g_ams_userpage_mapped);
|
lock_release(&g_ams_userpage_mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ams_map_irampage(uintptr_t iram_address) {
|
void ams_map_irampage(uintptr_t iram_address) {
|
||||||
lock_acquire(&g_ams_iram_page_mapped);
|
lock_acquire(&g_ams_iram_page_mapped);
|
||||||
static const uint64_t irampage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE;
|
static const uint64_t irampage_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | ATTRIB_MEMTYPE_DEVICE;
|
||||||
uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
||||||
|
@ -80,7 +80,7 @@ static void ams_map_irampage(uintptr_t iram_address) {
|
||||||
tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ams_unmap_irampage(void) {
|
void ams_unmap_irampage(void) {
|
||||||
uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
uintptr_t *mmu_l3_tbl = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
||||||
mmu_unmap_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
mmu_unmap_page(mmu_l3_tbl, AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
||||||
tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
tlb_invalidate_page_inner_shareable((void *)AMS_IRAM_PAGE_SECURE_MONITOR_ADDR);
|
||||||
|
|
|
@ -21,4 +21,7 @@
|
||||||
|
|
||||||
uint32_t ams_iram_copy(smc_args_t *args);
|
uint32_t ams_iram_copy(smc_args_t *args);
|
||||||
|
|
||||||
|
void ams_map_irampage(uintptr_t iram_address);
|
||||||
|
void ams_unmap_irampage(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue