From 2ef41f002732793a12cb567e67a1c924d90cb7f7 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 15 Nov 2020 01:36:50 -0800 Subject: [PATCH] exo: shuffle logic around to support debug code region in iram --- exosphere/Makefile | 11 +++-- .../loader_stub/source/secmon_loader_main.cpp | 1 - exosphere/program/program.ld | 42 ++++++++++++------- .../source/boot/secmon_boot_functions.cpp | 14 ++++++- .../source/boot/secmon_boot_functions.hpp | 4 +- exosphere/program/source/boot/secmon_main.cpp | 16 +++++-- exosphere/program/split_program.py | 1 + .../exosphere/secmon/secmon_memory_layout.hpp | 10 +++-- .../secmon/secmon_volatile_context.hpp | 20 +++++---- .../source/bpc_mitm/bpc_ams_power_utils.cpp | 5 ++- stratosphere/boot/source/boot_power_utils.cpp | 5 ++- 11 files changed, 86 insertions(+), 43 deletions(-) diff --git a/exosphere/Makefile b/exosphere/Makefile index b89cd3d24..6ce912754 100644 --- a/exosphere/Makefile +++ b/exosphere/Makefile @@ -5,7 +5,7 @@ define ATMOSPHERE_ADD_TARGET ATMOSPHERE_BUILD_CONFIGS += $(strip $1) -$(strip $1): exosphere$(strip $2).bin warmboot/warmboot$(strip $2).bin +$(strip $1): exosphere$(strip $2).bin check_warmboot_$(strip $1) @cp warmboot/warmboot$(strip $2).bin warmboot$(strip $2).bin exosphere$(strip $2).bin: loader_stub/loader_stub$(strip $2).bin @@ -13,10 +13,13 @@ exosphere$(strip $2).bin: loader_stub/loader_stub$(strip $2).bin @printf LENY >> exosphere$(strip $2).bin @echo "Built exosphere$(strip $2).bin..." -warmboot/warmboot$(strip $2).bin: +check_program_$(strip $1): + @$$(MAKE) -C program $(strip $1) + +check_warmboot_$(strip $1): @$$(MAKE) -C warmboot $(strip $1) -loader_stub/loader_stub$(strip $2).bin: +loader_stub/loader_stub$(strip $2).bin: check_program_$(strip $1) @$$(MAKE) -C loader_stub $(strip $1) clean-$(strip $1): clean-program-$(strip $1) clean-loader_stub-$(strip $1) clean-warmboot-$(strip $1) @@ -49,4 +52,4 @@ clean-loader_stub: clean-warmboot: @$(MAKE) -C warmboot clean -.PHONY: all clean clean-program clean-loader_stub clean-warmboot $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),clean-$(config) clean-program-$(config) clean-loader_stub-$(config) clean-warmboot-$(config)) +.PHONY: all clean clean-program clean-loader_stub clean-warmboot $(foreach config,$(ATMOSPHERE_BUILD_CONFIGS),check_program_$(config) check_warmboot_$(strip $1) clean-$(config) clean-program-$(config) clean-loader_stub-$(config) clean-warmboot-$(config)) diff --git a/exosphere/loader_stub/source/secmon_loader_main.cpp b/exosphere/loader_stub/source/secmon_loader_main.cpp index 26b194413..40b16c3fa 100644 --- a/exosphere/loader_stub/source/secmon_loader_main.cpp +++ b/exosphere/loader_stub/source/secmon_loader_main.cpp @@ -32,7 +32,6 @@ namespace ams::secmon::loader { /* Uncompress the boot image. */ Uncompress(secmon::MemoryRegionPhysicalIramBootCodeImage.GetPointer(), secmon::MemoryRegionPhysicalIramBootCodeImage.GetSize(), relocated_boot_code, boot_code_lz4_size); - /* Jump to the boot image. */ reinterpret_cast(secmon::MemoryRegionPhysicalIramBootCodeImage.GetAddress())(); diff --git a/exosphere/program/program.ld b/exosphere/program/program.ld index 8ca399862..feb219f59 100644 --- a/exosphere/program/program.ld +++ b/exosphere/program/program.ld @@ -5,7 +5,8 @@ MEMORY { NULL : ORIGIN = 0, LENGTH = 4K unused_region : ORIGIN = 0x1000, LENGTH = 4K - iram_boot_code : ORIGIN = 0x040032000, LENGTH = 48K + iram_boot_code : ORIGIN = 0x040032000, LENGTH = 4K + iram_boot_keys : ORIGIN = 0x040033000, LENGTH = 4K tzram : ORIGIN = 0x07C010000, LENGTH = 64K /* Warmboot code follows the vectors in memory. */ @@ -13,9 +14,10 @@ MEMORY warmboot_text : ORIGIN = ORIGIN(tzram) + 10K, LENGTH = 2K main : ORIGIN = 0x1F00C0000, LENGTH = 48K - tzram_boot : ORIGIN = 0x1F01C0000, LENGTH = 8K + debug_code : ORIGIN = 0x1F0150000, LENGTH = 16K + tzram_boot : ORIGIN = 0x1F01C0800, LENGTH = 6K - glob : ORIGIN = 0x040032000, LENGTH = 64K + glob : ORIGIN = 0x040032000, LENGTH = 128K } SECTIONS @@ -85,19 +87,30 @@ SECTIONS KEEP (*(.dtors)) } >iram_boot_code AT>glob - __bootcode_end__ = ABSOLUTE(.); - - __program_start__ = ABSOLUTE(.); - - .tzram_boot_volatile_data : { - KEEP (*(.volatile_keys .volatile_keys.*)) - } >tzram_boot AT>glob - - .tzram_boot_volatile_data.fill : { + .boot_code.fill : { FILL(0x00000000); - . = ORIGIN(tzram_boot) + 0x7FF; + . = ORIGIN(iram_boot_code) + 0xFFF; BYTE(0x00); - } >tzram_boot AT>glob + } >iram_boot_code AT>glob + + .boot_code_volatile_keys : { + KEEP (*(.volatile_keys .volatile_keys.*)) + } >iram_boot_keys AT>glob + + .boot_keys.fill : { + FILL(0x00000000); + . = ORIGIN(iram_boot_keys) + 0xFFF; + BYTE(0x00); + } >iram_boot_keys AT>glob + + .debug_code : { + KEEP (*(.text._ZN3ams3log6PrintfEPKcz .text._ZN3ams3log7VPrintfEPKcSt9__va_list .text._ZN3ams3log4DumpEPKvm)) + KEEP (*(.text._ZN3ams4util10TVSNPrintfEPcmPKcSt9__va_list .text._ZN3ams4util12_GLOBAL__N_114TVSNPrintfImplEPcmPKcSt9__va_list .text._ZZN3ams4util12_GLOBAL__N_114TVSNPrintfImplEPcmPKcSt9__va_listENKUlbmE3_clEbm)) + } >debug_code AT>glob + + __bootcode_end__ = ABSOLUTE(.) - ORIGIN(debug_code) + 0x40034000; + + __program_start__ = __bootcode_end__; .tzram_boot_code : { @@ -147,7 +160,6 @@ SECTIONS . = ALIGN(0x100); } >main AT>glob - .warmboot : { KEEP (*(.warmboot.text.start)) /* Should be first */ diff --git a/exosphere/program/source/boot/secmon_boot_functions.cpp b/exosphere/program/source/boot/secmon_boot_functions.cpp index b8782605a..b64c0563e 100644 --- a/exosphere/program/source/boot/secmon_boot_functions.cpp +++ b/exosphere/program/source/boot/secmon_boot_functions.cpp @@ -49,9 +49,19 @@ namespace ams::secmon::boot { } } - void ClearIram() { + void ClearIramBootCode() { /* Clear the boot code image from where it was loaded in IRAM. */ - util::ClearMemory(MemoryRegionPhysicalIramBootCodeImage.GetPointer(), MemoryRegionPhysicalIramBootCodeImage.GetSize()); + util::ClearMemory(MemoryRegionPhysicalIramBootCodeCode.GetPointer(), MemoryRegionPhysicalIramBootCodeCode.GetSize()); + } + + void ClearIramBootKeys() { + /* Clear the boot keys from where they were loaded in IRAM. */ + util::ClearMemory(MemoryRegionPhysicalIramBootCodeKeys.GetPointer(), MemoryRegionPhysicalIramBootCodeKeys.GetSize()); + } + + void ClearIramDebugCode() { + /* Clear the boot code image from where it was loaded in IRAM. */ + util::ClearMemory(MemoryRegionPhysicalDebugCode.GetPointer(), MemoryRegionPhysicalDebugCode.GetSize()); } void WaitForNxBootloader(const pkg1::SecureMonitorParameters ¶ms, pkg1::BootloaderState state) { diff --git a/exosphere/program/source/boot/secmon_boot_functions.hpp b/exosphere/program/source/boot/secmon_boot_functions.hpp index c03a04b64..4f22c88ec 100644 --- a/exosphere/program/source/boot/secmon_boot_functions.hpp +++ b/exosphere/program/source/boot/secmon_boot_functions.hpp @@ -18,7 +18,9 @@ namespace ams::secmon::boot { - void ClearIram(); + void ClearIramBootCode(); + void ClearIramBootKeys(); + void ClearIramDebugCode(); void WaitForNxBootloader(const pkg1::SecureMonitorParameters ¶ms, pkg1::BootloaderState state); diff --git a/exosphere/program/source/boot/secmon_main.cpp b/exosphere/program/source/boot/secmon_main.cpp index 73f02e9ee..cec0a0239 100644 --- a/exosphere/program/source/boot/secmon_main.cpp +++ b/exosphere/program/source/boot/secmon_main.cpp @@ -70,7 +70,12 @@ namespace ams::secmon { secmon::SetupCpuCoreContext(); /* Clear the crt0 code that was present in iram. */ - secmon::boot::ClearIram(); + secmon::boot::ClearIramBootCode(); + + /* Clear the debug code from iram, if we're not in debug config. */ + #if !defined(AMS_BUILD_FOR_DEBUGGING) && !defined(AMS_BUILD_FOR_AUDITING) + secmon::boot::ClearIramDebugCode(); + #endif /* Alert the bootloader that we're initialized. */ secmon_params.secmon_state = pkg1::SecureMonitorState_Initialized; @@ -117,9 +122,6 @@ namespace ams::secmon { std::memcpy(dst, src, size); } - /* Unmap the identity mapping. */ - secmon::boot::UnmapPhysicalIdentityMapping(); - /* Setup the GPU carveout's magic numbers. */ secmon::boot::WriteGpuCarveoutMagicNumbers(); @@ -172,6 +174,12 @@ namespace ams::secmon { /* Set the core's entrypoint and argument. */ secmon::SetEntryContext(0, Package2LoadAddress + pkg2_meta.entrypoint, 0); + /* Clear the boot keys from iram. */ + secmon::boot::ClearIramBootKeys(); + + /* Unmap the identity mapping. */ + secmon::boot::UnmapPhysicalIdentityMapping(); + /* Unmap DRAM. */ secmon::boot::UnmapDram(); diff --git a/exosphere/program/split_program.py b/exosphere/program/split_program.py index 158aa6c69..a9c70a8d7 100644 --- a/exosphere/program/split_program.py +++ b/exosphere/program/split_program.py @@ -17,6 +17,7 @@ def split_binary(data): assert D == 0xDDDDDDDDDDDDDDDD data = data[0x40:] + #print ('%X %X %X %X' % (START, BOOT_CODE_START, BOOT_CODE_END, PROGRAM_START)) boot_code = data[BOOT_CODE_START - START:BOOT_CODE_END - BOOT_CODE_START] program = data[PROGRAM_START - START:] return [('boot_code%s.lz4', lz4_compress(boot_code)), ('program%s.lz4', lz4_compress(program))] diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp index 7cc8d2c6d..196c1f873 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp @@ -224,7 +224,7 @@ namespace ams::secmon { static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualIramSc7Firmware)); static_assert(MemoryRegionPhysicalIram.Contains(MemoryRegionPhysicalIramSc7Firmware)); - constexpr inline const MemoryRegion MemoryRegionPhysicalIramSecureMonitorDebug(UINT64_C(0x40030000), 0x8000); + constexpr inline const MemoryRegion MemoryRegionPhysicalIramSecureMonitorDebug(UINT64_C(0x40034000), 0x4000); static_assert(MemoryRegionPhysicalIram.Contains(MemoryRegionPhysicalIramSecureMonitorDebug)); constexpr inline const MemoryRegion MemoryRegionVirtualDebugCode = MemoryRegion(UINT64_C(0x1F0150000), 0x4000); @@ -289,7 +289,6 @@ namespace ams::secmon { static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramConfigurationData)); static_assert(MemoryRegionPhysicalTzramNonVolatile.Contains(MemoryRegionPhysicalTzramConfigurationData)); - constexpr inline const MemoryRegion MemoryRegionVirtualTzramL1PageTable = MemoryRegion(UINT64_C(0x1F01FCFC0), 0x40); constexpr inline const MemoryRegion MemoryRegionPhysicalTzramL1PageTable = MemoryRegion( UINT64_C(0x7C01EFC0), 0x40); static_assert(MemoryRegionPhysicalTzramConfigurationData.Contains(MemoryRegionPhysicalTzramL1PageTable)); @@ -299,8 +298,11 @@ namespace ams::secmon { static_assert(MemoryRegionVirtual.Contains(MemoryRegionVirtualTzramL2L3PageTable)); static_assert(MemoryRegionPhysicalTzramNonVolatile.Contains(MemoryRegionPhysicalTzramL2L3PageTable)); - constexpr inline const MemoryRegion MemoryRegionPhysicalTzramFullProgramImage = MemoryRegion(UINT64_C(0x7C010000), 0xE000); - constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeImage = MemoryRegion(UINT64_C(0x40032000), 0xC000); + constexpr inline const MemoryRegion MemoryRegionPhysicalTzramFullProgramImage = MemoryRegion(UINT64_C(0x7C010800), 0xD800); + constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeImage = MemoryRegion(UINT64_C(0x40032000), 0x6000); + + constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeCode = MemoryRegion(UINT64_C(0x40032000), 0x1000); + constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeKeys = MemoryRegion(UINT64_C(0x40033000), 0x1000); constexpr inline const MemoryRegion MemoryRegionPhysicalIramWarmbootBin = MemoryRegion(UINT64_C(0x4003E000), 0x17F0); constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootConfig = MemoryRegion(UINT64_C(0x4003F800), 0x400); diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_volatile_context.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_volatile_context.hpp index 332108181..d39402788 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_volatile_context.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_volatile_context.hpp @@ -30,17 +30,19 @@ namespace ams::secmon { u8 package2_dev_rsa_modulus[0x100]; u8 package2_prod_rsa_modulus[0x100]; u8 package2_aes_key[0x10]; + u8 padding[0xCF0]; }; + static_assert(util::is_pod::value); + static_assert(sizeof(VolatileKeys) == 0x1000); /* Nintendo uses the bottom 0x740 of this as a stack for warmboot setup, and another 0x740 for the core 0/1/2 SMC stacks. */ /* This is...wasteful. The warmboot stack is not deep. We will thus save 1K+ of nonvolatile storage by keeping the random cache in here. */ struct VolatileData { + u8 se_work_block[crypto::AesEncryptor128::BlockSize]; union { u8 random_cache[0x400]; - VolatileKeys keys; pkg2::Package2Meta pkg2_meta; }; - u8 se_work_block[crypto::AesEncryptor128::BlockSize]; u8 reserved_danger_zone[0x30]; /* This memory is "available", but careful consideration must be taken before declaring it used. */ u8 warmboot_stack[0x380]; u8 core012_smc_stack[0x6C0]; @@ -48,8 +50,6 @@ namespace ams::secmon { }; static_assert(util::is_pod::value); static_assert(sizeof(VolatileData) == 0x1000); - static_assert(sizeof(VolatileKeys{}.boot_config_rsa_modulus) == sizeof(pkg2::Package2Meta)); - static_assert(offsetof(VolatileData, keys.boot_config_rsa_modulus) == offsetof(VolatileData, pkg2_meta)); ALWAYS_INLINE VolatileData &GetVolatileData() { return *MemoryRegionVirtualTzramVolatileData.GetPointer(); @@ -69,17 +69,21 @@ namespace ams::secmon { namespace boot { + ALWAYS_INLINE VolatileKeys &GetVolatileKeys() { + return *MemoryRegionPhysicalIramBootCodeKeys.GetPointer(); + } + ALWAYS_INLINE const u8 *GetBootConfigRsaModulus() { - return GetVolatileData().keys.boot_config_rsa_modulus; + return GetVolatileKeys().boot_config_rsa_modulus; } ALWAYS_INLINE const u8 *GetPackage2RsaModulus(bool is_prod) { - auto &volatile_data = GetVolatileData(); - return is_prod ? volatile_data.keys.package2_prod_rsa_modulus : volatile_data.keys.package2_dev_rsa_modulus; + auto &keys = GetVolatileKeys(); + return is_prod ? keys.package2_prod_rsa_modulus : keys.package2_dev_rsa_modulus; } ALWAYS_INLINE const u8 *GetPackage2AesKey() { - return GetVolatileData().keys.package2_aes_key; + return GetVolatileKeys().package2_aes_key; } ALWAYS_INLINE pkg2::Package2Meta &GetEphemeralPackage2Meta() { diff --git a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp index 0a328aa0c..79a410283 100644 --- a/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp +++ b/stratosphere/ams_mitm/source/bpc_mitm/bpc_ams_power_utils.cpp @@ -25,7 +25,8 @@ namespace ams::mitm::bpc { constexpr uintptr_t IramBase = 0x40000000ull; constexpr uintptr_t IramPayloadBase = 0x40010000ull; constexpr size_t IramSize = 0x40000; - constexpr size_t IramPayloadMaxSize = 0x20000; + constexpr size_t IramPayloadMaxSize = 0x24000; + constexpr size_t IramFatalErrorContextOffset = 0x2E000; /* Helper enum. */ enum class RebootType : u32 { @@ -64,7 +65,7 @@ namespace ams::mitm::bpc { if (ctx != nullptr) { std::memset(g_work_page, 0xCC, sizeof(g_work_page)); std::memcpy(g_work_page, ctx, sizeof(*ctx)); - exosphere::CopyToIram(IramPayloadBase + IramPayloadMaxSize, g_work_page, sizeof(g_work_page)); + exosphere::CopyToIram(IramPayloadBase + IramFatalErrorContextOffset, g_work_page, sizeof(g_work_page)); } exosphere::ForceRebootToIramPayload(); diff --git a/stratosphere/boot/source/boot_power_utils.cpp b/stratosphere/boot/source/boot_power_utils.cpp index 59228e3c8..d0fa765af 100644 --- a/stratosphere/boot/source/boot_power_utils.cpp +++ b/stratosphere/boot/source/boot_power_utils.cpp @@ -26,7 +26,8 @@ namespace ams::boot { constexpr uintptr_t IramBase = 0x40000000ull; constexpr uintptr_t IramPayloadBase = 0x40010000ull; constexpr size_t IramSize = 0x40000; - constexpr size_t IramPayloadMaxSize = 0x20000; + constexpr size_t IramPayloadMaxSize = 0x24000; + constexpr size_t IramFatalErrorContextOffset = 0x2E000; /* Globals. */ alignas(os::MemoryPageSize) u8 g_work_page[os::MemoryPageSize]; @@ -57,7 +58,7 @@ namespace ams::boot { if (ctx != nullptr) { std::memset(g_work_page, 0xCC, sizeof(g_work_page)); std::memcpy(g_work_page, ctx, sizeof(*ctx)); - exosphere::CopyToIram(IramPayloadBase + IramPayloadMaxSize, g_work_page, sizeof(g_work_page)); + exosphere::CopyToIram(IramPayloadBase + IramFatalErrorContextOffset, g_work_page, sizeof(g_work_page)); } exosphere::ForceRebootToIramPayload();