exo2: implement remainder of warmboot tz code
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
|
||||
namespace ams::secmon {
|
||||
|
||||
/* TODO */
|
||||
void UnmapTzram();
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,4 +24,7 @@ namespace ams::secmon::smc {
|
||||
|
||||
SmcResult SmcSuspendCpu(const SmcArguments &args);
|
||||
|
||||
bool IsChargerHiZModeEnabled();
|
||||
void SetChargerHiZModeEnabled(bool en);
|
||||
|
||||
}
|
||||
|
||||
41
exosphere2/program/source/smc/secmon_smc_se_lock.cpp
Normal file
41
exosphere2/program/source/smc/secmon_smc_se_lock.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
26
exosphere2/program/source/smc/secmon_smc_se_lock.hpp
Normal file
26
exosphere2/program/source/smc/secmon_smc_se_lock.hpp
Normal 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();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user