From 9ddcbe9dc30552b0a1dfe47b925fccbe130f5cf0 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 12 May 2020 01:18:10 -0700 Subject: [PATCH] exo2: implement main through sync-for-pk21-load --- .../program/source/boot/secmon_boot.hpp | 1 + .../program/source/boot/secmon_boot_cache.cpp | 3 +- .../program/source/boot/secmon_boot_cache.hpp | 23 +++++++++++++ .../source/boot/secmon_boot_functions.cpp | 27 +++++++++++++++ .../source/boot/secmon_boot_functions.hpp | 2 ++ .../program/source/boot/secmon_boot_setup.cpp | 34 ++++++++++++++++++- .../program/source/boot/secmon_main.cpp | 30 ++++++++++++++++ .../source/boot/secmon_make_page_table.cpp | 2 +- exosphere2/program/source/secmon_cache.inc | 2 +- exosphere2/program/source/secmon_setup.cpp | 10 ++++++ exosphere2/program/source/secmon_setup.hpp | 2 ++ .../exosphere/secmon/secmon_memory_layout.hpp | 6 +++- .../include/exosphere/tegra/tegra_sysctr0.hpp | 2 +- 13 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 exosphere2/program/source/boot/secmon_boot_cache.hpp diff --git a/exosphere2/program/source/boot/secmon_boot.hpp b/exosphere2/program/source/boot/secmon_boot.hpp index d82c67cac..1214b8850 100644 --- a/exosphere2/program/source/boot/secmon_boot.hpp +++ b/exosphere2/program/source/boot/secmon_boot.hpp @@ -19,6 +19,7 @@ namespace ams::secmon::boot { void MakePageTable(); + void UnmapPhysicalIdentityMapping(); void InitializeColdBoot(); diff --git a/exosphere2/program/source/boot/secmon_boot_cache.cpp b/exosphere2/program/source/boot/secmon_boot_cache.cpp index ad0649c3e..f2d1f8e22 100644 --- a/exosphere2/program/source/boot/secmon_boot_cache.cpp +++ b/exosphere2/program/source/boot/secmon_boot_cache.cpp @@ -14,9 +14,10 @@ * along with this program. If not, see . */ #include +#include "secmon_boot_cache.hpp" namespace ams::secmon::boot { - /* TODO */ + #include "../secmon_cache_impl.inc" } \ No newline at end of file diff --git a/exosphere2/program/source/boot/secmon_boot_cache.hpp b/exosphere2/program/source/boot/secmon_boot_cache.hpp new file mode 100644 index 000000000..60d5b4208 --- /dev/null +++ b/exosphere2/program/source/boot/secmon_boot_cache.hpp @@ -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 . + */ +#pragma once +#include + +namespace ams::secmon::boot { + + #include "../secmon_cache.inc" + +} \ No newline at end of file diff --git a/exosphere2/program/source/boot/secmon_boot_functions.cpp b/exosphere2/program/source/boot/secmon_boot_functions.cpp index a9488e44e..537c78c5a 100644 --- a/exosphere2/program/source/boot/secmon_boot_functions.cpp +++ b/exosphere2/program/source/boot/secmon_boot_functions.cpp @@ -15,6 +15,7 @@ */ #include #include "secmon_boot.hpp" +#include "secmon_boot_cache.hpp" #include "secmon_boot_functions.hpp" namespace ams::secmon::boot { @@ -104,4 +105,30 @@ namespace ams::secmon::boot { SYSCTR0_REG_BITS_ENUM(CNTCR_EN, ENABLE)); } + void WriteGpuCarveoutMagicNumbers() { + /* Define the magic numbers. */ + constexpr u32 GpuMagicNumber = 0xC0EDBBCC; + constexpr u32 SkuInfo = 0x83; + constexpr u32 HdcpMicroCodeVersion = 0x2; + constexpr u32 ChipIdErista = 0x210; + constexpr u32 ChipIdMariko = 0x214; + + /* Get our pointers. */ + u32 *gpu_magic = MemoryRegionDramGpuCarveout.GetEndPointer() - (0x004 / sizeof(*gpu_magic)); + u32 *tsec_magic = MemoryRegionDramGpuCarveout.GetEndPointer() - (0x100 / sizeof(*tsec_magic)); + + /* Write the gpu magic number. */ + gpu_magic[0] = GpuMagicNumber; + + /* Write the tsec magic numbers. */ + tsec_magic[0] = SkuInfo; + tsec_magic[1] = HdcpMicroCodeVersion; + tsec_magic[2] = (false /* TODO: IsMariko */) ? ChipIdMariko : ChipIdErista; + + /* Flush the magic numbers. */ + hw::FlushDataCache(gpu_magic, 1 * sizeof(u32)); + hw::FlushDataCache(tsec_magic, 3 * sizeof(u32)); + hw::DataSynchronizationBarrierInnerShareable(); + } + } \ No newline at end of file diff --git a/exosphere2/program/source/boot/secmon_boot_functions.hpp b/exosphere2/program/source/boot/secmon_boot_functions.hpp index 83ac091db..97b5a105d 100644 --- a/exosphere2/program/source/boot/secmon_boot_functions.hpp +++ b/exosphere2/program/source/boot/secmon_boot_functions.hpp @@ -27,4 +27,6 @@ namespace ams::secmon::boot { void EnableTsc(u64 initial_tsc_value); + void WriteGpuCarveoutMagicNumbers(); + } \ No newline at end of file diff --git a/exosphere2/program/source/boot/secmon_boot_setup.cpp b/exosphere2/program/source/boot/secmon_boot_setup.cpp index 06b411f87..c9255a529 100644 --- a/exosphere2/program/source/boot/secmon_boot_setup.cpp +++ b/exosphere2/program/source/boot/secmon_boot_setup.cpp @@ -15,6 +15,7 @@ */ #include #include "secmon_boot.hpp" +#include "secmon_boot_cache.hpp" #include "../secmon_setup.hpp" #include "../secmon_key_storage.hpp" @@ -308,6 +309,25 @@ namespace ams::secmon::boot { } + namespace { + + using namespace ams::mmu; + + constexpr void UnmapPhysicalIdentityMappingImpl(u64 *l1, u64 *l2, u64 *l3) { + /* Invalidate the L3 entries for the tzram and iram boot code regions. */ + InvalidateL3Entries(l3, MemoryRegionPhysicalTzram.GetAddress(), MemoryRegionPhysicalTzram.GetSize()); + InvalidateL3Entries(l3, MemoryRegionPhysicalIramBootCode.GetAddress(), MemoryRegionPhysicalIramBootCode.GetSize()); + + /* Unmap the L2 entries corresponding to those L3 entries. */ + InvalidateL2Entries(l2, MemoryRegionPhysicalIramL2.GetAddress(), MemoryRegionPhysicalIramL2.GetSize()); + InvalidateL2Entries(l2, MemoryRegionPhysicalTzramL2.GetAddress(), MemoryRegionPhysicalTzramL2.GetSize()); + + /* Unmap the L1 entry corresponding to to those L2 entries. */ + InvalidateL1Entries(l1, MemoryRegionPhysical.GetAddress(), MemoryRegionPhysical.GetSize()); + } + + } + void InitializeColdBoot() { /* Ensure that the system counters are valid. */ ValidateSystemCounters(); @@ -334,4 +354,16 @@ namespace ams::secmon::boot { SaveSecurityEngineAesKeySlotTestVector(); } -} \ No newline at end of file + void UnmapPhysicalIdentityMapping() { + /* Get the tables. */ + u64 * const l1 = MemoryRegionPhysicalTzramL1PageTable.GetPointer(); + u64 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer(); + + /* Unmap. */ + UnmapPhysicalIdentityMappingImpl(l1, l2_l3, l2_l3); + + /* Ensure the mappings are consistent. */ + secmon::boot::EnsureMappingConsistency(); + } + +} diff --git a/exosphere2/program/source/boot/secmon_main.cpp b/exosphere2/program/source/boot/secmon_main.cpp index 93b9f9c93..0b09e8ecc 100644 --- a/exosphere2/program/source/boot/secmon_main.cpp +++ b/exosphere2/program/source/boot/secmon_main.cpp @@ -89,6 +89,36 @@ namespace ams::secmon { secmon::boot::EnableTsc(bc.data.GetInitialTscValue() & TscMask); } + + /* Wait for NX Bootloader to initialize DRAM. */ + secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_InitializedDram); + + /* Secure the PMC and MC. */ + secmon::SetupPmcAndMcSecure(); + + /* Copy warmboot to dram. */ + { + /* Define warmboot extents. */ + const void * const src = MemoryRegionPhysicalIramWarmbootBin.GetPointer(); + void * const dst = MemoryRegionVirtualDramSecureDataStoreWarmbootFirmware.GetPointer(); + const size_t size = MemoryRegionPhysicalIramWarmbootBin.GetSize(); + + /* Ensure we copy the correct data. */ + hw::FlushDataCache(src, size); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Copy warmboot.bin to its secure dram location. */ + std::memcpy(dst, src, size); + } + + /* Unmap the identity mapping. */ + secmon::boot::UnmapPhysicalIdentityMapping(); + + /* Setup the GPU carveout's magic numbers. */ + secmon::boot::WriteGpuCarveoutMagicNumbers(); + + /* Wait for NX bootloader to load Package2. */ + secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_LoadedPackage2); } } \ No newline at end of file diff --git a/exosphere2/program/source/boot/secmon_make_page_table.cpp b/exosphere2/program/source/boot/secmon_make_page_table.cpp index dfde30d16..876bc54c0 100644 --- a/exosphere2/program/source/boot/secmon_make_page_table.cpp +++ b/exosphere2/program/source/boot/secmon_make_page_table.cpp @@ -144,4 +144,4 @@ namespace ams::secmon::boot { MakePageTablesImpl(l1, l2_l3, l2_l3); } -} \ No newline at end of file +} diff --git a/exosphere2/program/source/secmon_cache.inc b/exosphere2/program/source/secmon_cache.inc index 1ee25f79a..ea57c0f4e 100644 --- a/exosphere2/program/source/secmon_cache.inc +++ b/exosphere2/program/source/secmon_cache.inc @@ -19,4 +19,4 @@ void InvalidateEntireDataCache(); void EnsureMappingConsistency(); void EnsureMappingConsistency(uintptr_t address); -void EnsureInstructionConsistency(); \ No newline at end of file +void EnsureInstructionConsistency(); diff --git a/exosphere2/program/source/secmon_setup.cpp b/exosphere2/program/source/secmon_setup.cpp index 7bb95aa63..296f66d68 100644 --- a/exosphere2/program/source/secmon_setup.cpp +++ b/exosphere2/program/source/secmon_setup.cpp @@ -840,6 +840,16 @@ namespace ams::secmon { } + void SetupPmcAndMcSecure() { + /* Set the PMC secure. */ + reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE)); + + /* Set the MC secure. */ + reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE)); + } + void SetupCpuCoreContext() { /* Get the tsc frequency. */ const u32 tsc_frequency = reg::Read(MemoryRegionVirtualDeviceSysCtr0.GetAddress() + SYSCTR0_CNTFID0); diff --git a/exosphere2/program/source/secmon_setup.hpp b/exosphere2/program/source/secmon_setup.hpp index 623e10e74..c3c468fee 100644 --- a/exosphere2/program/source/secmon_setup.hpp +++ b/exosphere2/program/source/secmon_setup.hpp @@ -31,6 +31,8 @@ namespace ams::secmon { void SetupSocSecurity(); void SetupSocProtections(); + void SetupPmcAndMcSecure(); + void Setup1(); void SaveSecurityEngineAesKeySlotTestVector(); diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp index 1e25108c5..d521efadc 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_memory_layout.hpp @@ -74,6 +74,9 @@ namespace ams::secmon { constexpr inline const MemoryRegion MemoryRegionPhysical = MemoryRegion(UINT64_C( 0x40000000), 1_GB); constexpr inline const MemoryRegion MemoryRegionDram = MemoryRegion(UINT64_C( 0x80000000), 2_GB); + constexpr inline const MemoryRegion MemoryRegionDramGpuCarveout = MemoryRegion(UINT64_C(0x80020000), UINT64_C(0x40000)); + static_assert(MemoryRegionDram.Contains(MemoryRegionDramGpuCarveout)); + constexpr inline const MemoryRegion MemoryRegionDramDefaultKernelCarveout = MemoryRegion(UINT64_C(0x80060000), UINT64_C(0x1FFE0000)); static_assert(MemoryRegionDram.Contains(MemoryRegionDramDefaultKernelCarveout)); @@ -274,6 +277,7 @@ namespace ams::secmon { constexpr inline const MemoryRegion MemoryRegionPhysicalTzramFullProgramImage = MemoryRegion(UINT64_C(0x7C010800), 0xD800); constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootCodeImage = MemoryRegion(UINT64_C(0x40032000), 0xC000); - constexpr inline const MemoryRegion MemoryRegionPhysicalIramBootConfig = MemoryRegion(UINT64_C(0x4003F800), 0x400); + 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/tegra/tegra_sysctr0.hpp b/libraries/libexosphere/include/exosphere/tegra/tegra_sysctr0.hpp index d7e7fd497..650067eb6 100644 --- a/libraries/libexosphere/include/exosphere/tegra/tegra_sysctr0.hpp +++ b/libraries/libexosphere/include/exosphere/tegra/tegra_sysctr0.hpp @@ -16,7 +16,7 @@ #pragma once #include -#define SYSCTR0_CNTCR (0x00C) +#define SYSCTR0_CNTCR (0x000) #define SYSCTR0_CNTCV0 (0x008) #define SYSCTR0_CNTCV1 (0x00C) #define SYSCTR0_CNTFID0 (0x020)