From 34098f7215ff2cdb4074abe5fe4add2179d18b06 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 7 Jun 2020 19:51:49 -0700 Subject: [PATCH] exo2: add sc7fw load, skeleton rest of suspend --- exosphere2/program/Makefile | 11 ++- .../smc/secmon_smc_power_management.cpp | 80 ++++++++++++++++++- .../include/exosphere/tegra/tegra_clkrst.hpp | 7 +- 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/exosphere2/program/Makefile b/exosphere2/program/Makefile index 078b88fd9..427061ca9 100644 --- a/exosphere2/program/Makefile +++ b/exosphere2/program/Makefile @@ -21,7 +21,8 @@ export TOPDIR := $(CURDIR) export DEPSDIR := $(CURDIR)/$(BUILD) export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ + $(TOPDIR)/sc7fw CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \ $(notdir $(wildcard $(dir)/*.c)))) @@ -41,6 +42,8 @@ SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATM SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s))) SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s))) +BINFILES := sc7fw.bin + #--------------------------------------------------------------------------------- # use CXX for linking C++ projects, CC for standard C #--------------------------------------------------------------------------------- @@ -71,16 +74,20 @@ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib -L$(dir)/$(ATMOSPHERE_L #--------------------------------------------------------------------------------- all: $(BUILD) check_libexo -$(BUILD): check_libexo +$(BUILD): check_libexo check_sc7fw @[ -d $@ ] || mkdir -p $@ @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile check_libexo: @$(MAKE) --no-print-directory -C ../../libraries/libexosphere arm64 +check_sc7fw: + @$(MAKE) -C $(TOPDIR)/sc7fw all + #--------------------------------------------------------------------------------- clean: @echo clean ... + @$(MAKE) -C $(TOPDIR)/sc7fw clean @rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf *.lz4 #--------------------------------------------------------------------------------- diff --git a/exosphere2/program/source/smc/secmon_smc_power_management.cpp b/exosphere2/program/source/smc/secmon_smc_power_management.cpp index 7596903cb..4398a6961 100644 --- a/exosphere2/program/source/smc/secmon_smc_power_management.cpp +++ b/exosphere2/program/source/smc/secmon_smc_power_management.cpp @@ -20,6 +20,8 @@ #include "secmon_smc_power_management.hpp" #include "secmon_smc_se_lock.hpp" +#include "sc7fw_bin.h" + namespace ams::secmon { /* Declare assembly functionality. */ @@ -35,9 +37,12 @@ namespace ams::secmon::smc { namespace { - constexpr inline uintptr_t PMC = MemoryRegionVirtualDevicePmc.GetAddress(); - constexpr inline uintptr_t GPIO = MemoryRegionVirtualDeviceGpio.GetAddress(); - constexpr inline uintptr_t CLK_RST = MemoryRegionVirtualDeviceClkRst.GetAddress(); + constexpr inline const uintptr_t PMC = MemoryRegionVirtualDevicePmc.GetAddress(); + constexpr inline const uintptr_t APB_MISC = MemoryRegionVirtualDeviceApbMisc.GetAddress(); + constexpr inline const uintptr_t GPIO = MemoryRegionVirtualDeviceGpio.GetAddress(); + constexpr inline const uintptr_t CLK_RST = MemoryRegionVirtualDeviceClkRst.GetAddress(); + constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress(); + constexpr inline const uintptr_t FLOW_CTLR = MemoryRegionVirtualDeviceFlowController.GetAddress(); constexpr inline uintptr_t CommonSmcStackTop = MemoryRegionVirtualTzramVolatileData.GetEndAddress() - (0x80 * (NumCores - 1)); @@ -150,8 +155,75 @@ namespace ams::secmon::smc { /* TODO */ } - void SaveSecureContextAndSuspend() { + void SaveSecureContextForErista() { /* TODO */ + } + + void SaveSecureContextForMariko() { + /* TODO */ + } + + void SaveSecureContext() { + const auto soc_type = GetSocType(); + if (soc_type == fuse::SocType_Erista) { + SaveSecureContextForErista(); + } else /* if (soc_type == fuse::SocType_Mariko) */ { + SaveSecureContextForMariko(); + } + } + + void LoadAndStartSc7BpmpFirmware() { + /* Set the PMC as insecure, so that the BPMP firmware can access it. */ + reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, DISABLE)); + + /* Set the exception vectors for the bpmp. RESET should point to RESET, all others should point to generic exception/panic. */ + constexpr const u32 Sc7FirmwareResetVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x0); + constexpr const u32 Sc7FirmwarePanicVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x4); + + reg::Write(EVP + EVP_COP_RESET_VECTOR, Sc7FirmwareResetVector); + reg::Write(EVP + EVP_COP_UNDEF_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_SWI_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_PREFETCH_ABORT_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_DATA_ABORT_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_RSVD_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_IRQ_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_FIQ_VECTOR, Sc7FirmwarePanicVector); + + /* Disable activity monitor bpmp monitoring, so that we don't panic upon bpmp wake. */ + actmon::StopMonitoringBpmp(); + + /* Load the bpmp firmware. */ + void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer(); + std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size); + hw::FlushDataCache(sc7fw_load_address, sc7fw_bin_size); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Ensure that the bpmp firmware was loaded. */ + AMS_ABORT_UNLESS(crypto::IsSameBytes(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size)); + + /* Clear BPMP reset. */ + reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_COP_RST, ENABLE)); + + /* Start the bpmp. */ + reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_NONE)); + } + + void SaveSecureContextAndSuspend() { + /* Ensure there are no pending memory transactions before we continue */ + FlushEntireDataCache(); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Save all secure context (security engine state + tzram). */ + SaveSecureContext(); + + /* Load and start the sc7 firmware on the bpmp. */ + LoadAndStartSc7BpmpFirmware(); + + /* Log our suspension. */ + /* NOTE: Nintendo only does this on dev, but we will always do it. */ + if (true /* !pkg1::IsProduction() */) { + log::SendText("OYASUMI\n", 8); + } /* Finalize our powerdown and wait for an interrupt. */ FinalizePowerOff(); diff --git a/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp index 3659194aa..f6a1ae6b8 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_clkrst.hpp @@ -61,7 +61,10 @@ DEFINE_CLK_RST_REG(MISC_CLK_ENB_CFG_ALL_VISIBLE, 28, 1); #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTA (0x178) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTB (0x17C) #define CLK_RST_CONTROLLER_CLK_SOURCE_UARTC (0x1A0) -#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3e8) +#define CLK_RST_CONTROLLER_CLK_SOURCE_ACTMON (0x3E8) + +/* RST_DEV_*_CLR */ +#define CLK_RST_CONTROLLER_RST_DEV_L_CLR (0x304) /* CLK_ENB_*_INDEX */ #define CLK_RST_CONTROLLER_CLK_ENB_I2C1_INDEX (0x0C) @@ -96,3 +99,5 @@ DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTB_UARTB_CLK_SRC, 29, PLLP_OUT0, DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_UARTC_UARTC_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, RESERVED4, PLLC4_OUT1, CLK_M, PLLC4_OUT2); DEFINE_CLK_RST_REG_THREE_BIT_ENUM(CLK_SOURCE_ACTMON_ACTMON_CLK_SRC, 29, PLLP_OUT0, PLLC2_OUT0, PLLC_OUT0, PLLC4_OUT0, CLK_S, PLLC4_OUT1, CLK_M, PLLC4_OUT2); + +DEFINE_CLK_RST_REG_BIT_ENUM(RST_DEV_L_CLR_CLR_COP_RST, 1, DISABLE, ENABLE);