exo2: implement remainder of warmboot tz code

This commit is contained in:
Michael Scire
2020-05-13 10:56:07 -07:00
committed by SciresM
parent 97ab282351
commit ad664daea5
21 changed files with 691 additions and 17 deletions

View File

@@ -32,14 +32,14 @@ namespace ams::secmon {
void Main() {
/* Set library register addresses. */
/* actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress()); */
actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress());
clkrst::SetRegisterAddress(MemoryRegionVirtualDeviceClkRst.GetAddress());
flow::SetRegisterAddress(MemoryRegionVirtualDeviceFlowController.GetAddress());
fuse::SetRegisterAddress(MemoryRegionVirtualDeviceFuses.GetAddress());
gic::SetRegisterAddress(MemoryRegionVirtualDeviceGicDistributor.GetAddress(), MemoryRegionVirtualDeviceGicCpuInterface.GetAddress());
i2c::SetRegisterAddress(i2c::Port_1, MemoryRegionVirtualDeviceI2c1.GetAddress());
i2c::SetRegisterAddress(i2c::Port_5, MemoryRegionVirtualDeviceI2c5.GetAddress());
/* pinmux::SetRegisterAddress(); */
pinmux::SetRegisterAddress(MemoryRegionVirtualDeviceApbMisc.GetAddress(), MemoryRegionVirtualDeviceGpio.GetAddress());
pmc::SetRegisterAddress(MemoryRegionVirtualDevicePmc.GetAddress());
se::SetRegisterAddress(MemoryRegionVirtualDeviceSecurityEngine.GetAddress());
uart::SetRegisterAddress(MemoryRegionVirtualDeviceUart.GetAddress());

View File

@@ -28,6 +28,17 @@ namespace ams::secmon {
InvalidateL3Entries(l3, boot_code, boot_code_size);
}
constexpr void UnmapTzramImpl(u64 *l1, u64 *l2, u64 *l3) {
/* Unmap the L3 entries corresponding to tzram. */
InvalidateL3Entries(l3, MemoryRegionPhysicalTzram.GetAddress(), MemoryRegionPhysicalTzram.GetSize());
/* Unmap the L2 entries corresponding to those L3 entries. */
InvalidateL2Entries(l2, MemoryRegionPhysicalTzramL2.GetAddress(), MemoryRegionPhysicalTzramL2.GetSize());
/* Unmap the L1 entry corresponding to to those L2 entries. */
InvalidateL1Entries(l1, MemoryRegionPhysical.GetAddress(), MemoryRegionPhysical.GetSize());
}
}
void UnmapBootCode() {
@@ -49,4 +60,16 @@ namespace ams::secmon {
secmon::EnsureMappingConsistency();
}
void UnmapTzram() {
/* Get the tables. */
u64 * const l1 = MemoryRegionVirtualTzramL1PageTable.GetPointer<u64>();
u64 * const l2_l3 = MemoryRegionVirtualTzramL2L3PageTable.GetPointer<u64>();
/* Unmap. */
UnmapTzramImpl(l1, l2_l3, l2_l3);
/* Ensure the mappings are consistent. */
secmon::EnsureMappingConsistency();
}
}

View File

@@ -18,6 +18,6 @@
namespace ams::secmon {
/* TODO */
void UnmapTzram();
}

View File

@@ -16,9 +16,12 @@
#include <exosphere.hpp>
#include "secmon_setup.hpp"
#include "secmon_error.hpp"
#include "secmon_map.hpp"
#include "secmon_cpu_context.hpp"
#include "secmon_interrupt_handler.hpp"
#include "secmon_misc.hpp"
#include "smc/secmon_smc_power_management.hpp"
#include "smc/secmon_smc_se_lock.hpp"
namespace ams::secmon {
@@ -887,11 +890,58 @@ namespace ams::secmon {
reg::Read (MC + MC_SMMU_TLB_CONFIG);
}
void ValidateResetExpected() {
/* We're coming out of reset, so check that we expected to come out of reset. */
if (!IsResetExpected()) {
secmon::SetError(pkg1::ErrorInfo_UnexpectedReset);
AMS_ABORT("unexpected reset");
}
SetResetExpected(false);
}
void ActmonInterruptHandler() {
SetError(pkg1::ErrorInfo_ActivityMonitorInterrupt);
AMS_ABORT("actmon observed bpmp wakeup");
}
void ExitChargerHiZMode() {
/* Setup I2c-1. */
pinmux::SetupI2c1();
clkrst::EnableI2c1Clock();
/* Initialize I2c-1. */
i2c::Initialize(i2c::Port_1);
/* Exit Hi-Z mode. */
charger::ExitHiZMode();
/* Disable clock to I2c-1. */
clkrst::DisableI2c1Clock();
}
bool IsExitLp0() {
return reg::Read(MC + MC_SECURITY_CFG3) == 0;
}
void LogExitLp0() {
/* NOTE: Nintendo only does this on dev, but we will always do it. */
if (true /* !pkg1::IsProduction() */) {
log::Initialize();
log::SendText("OHAYO\n", 6);
log::Flush();
}
}
void SetupForLp0Exit() {
/* Exit HiZ mode in charger, if we need to. */
if (smc::IsChargerHiZModeEnabled()) {
ExitChargerHiZMode();
}
/* Unlock the security engine. */
secmon::smc::UnlockSecurityEngine();
}
}
void Setup1() {
@@ -908,6 +958,14 @@ namespace ams::secmon {
gic::InitializeCommon();
}
void Setup1ForWarmboot() {
/* Initialize the security engine. */
se::Initialize();
/* Initialize the gic. */
gic::InitializeCommon();
}
void SaveSecurityEngineAesKeySlotTestVector() {
GenerateSecurityEngineAesKeySlotTestVector(g_se_aes_key_slot_test_vector, sizeof(g_se_aes_key_slot_test_vector));
}
@@ -1007,7 +1065,36 @@ namespace ams::secmon {
}
void SetupSocSecurityWarmboot() {
/* ... */
/* Check that we're allowed to continue. */
ValidateResetExpected();
/* Unmap the tzram identity mapping. */
UnmapTzram();
/* If we're exiting LP0, there's a little more work for us to do. */
if (IsExitLp0()) {
/* Log that we're exiting LP0. */
LogExitLp0();
/* Perform initial setup. */
Setup1ForWarmboot();
/* Setup the Soc security. */
SetupSocSecurity();
/* Set the PMC and MC as secure-only. */
SetupPmcAndMcSecure();
/* Perform Lp0-exit specific init. */
SetupForLp0Exit();
/* Setup the Soc protections. */
SetupSocProtections();
}
/* Perform remaining CPU initialization. */
SetupCpuCoreContext();
SetupCpuSErrorDebug();
}
void SetupSocProtections() {

View File

@@ -19,6 +19,12 @@
namespace ams::secmon::smc {
namespace {
constinit bool g_charger_hi_z_mode_enabled = false;
}
SmcResult SmcPowerOffCpu(const SmcArguments &args) {
/* TODO */
return SmcResult::NotImplemented;
@@ -34,4 +40,12 @@ namespace ams::secmon::smc {
return SmcResult::NotImplemented;
}
bool IsChargerHiZModeEnabled() {
return g_charger_hi_z_mode_enabled;
}
void SetChargerHiZModeEnabled(bool en) {
g_charger_hi_z_mode_enabled = en;
}
}

View File

@@ -24,4 +24,7 @@ namespace ams::secmon::smc {
SmcResult SmcSuspendCpu(const SmcArguments &args);
bool IsChargerHiZModeEnabled();
void SetChargerHiZModeEnabled(bool en);
}

View File

@@ -0,0 +1,41 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "../secmon_error.hpp"
#include "secmon_smc_se_lock.hpp"
namespace ams::secmon::smc {
namespace {
constinit std::atomic_bool g_is_locked = false;
}
bool TryLockSecurityEngine() {
bool value = false;
return g_is_locked.compare_exchange_strong(value, true);
}
void UnlockSecurityEngine() {
g_is_locked = false;
}
bool IsSecurityEngineLocked() {
return g_is_locked;
}
}

View File

@@ -0,0 +1,26 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <exosphere.hpp>
#include "secmon_smc_common.hpp"
namespace ams::secmon::smc {
bool TryLockSecurityEngine();
void UnlockSecurityEngine();
bool IsSecurityEngineLocked();
}