From 0698338312f11c0f9616839c8698dc5982dc63f4 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 14 Jun 2020 22:06:44 -0700 Subject: [PATCH] exo2: resolve remaining erista TODOs, clean up debugging code --- .../program/source/boot/secmon_boot_setup.cpp | 7 +- exosphere/program/source/secmon_error.cpp | 58 +++++++++++----- .../program/source/smc/secmon_smc_error.cpp | 17 ++++- .../program/source/smc/secmon_smc_handler.cpp | 68 ------------------- .../smc/secmon_smc_power_management.cpp | 2 +- 5 files changed, 62 insertions(+), 90 deletions(-) diff --git a/exosphere/program/source/boot/secmon_boot_setup.cpp b/exosphere/program/source/boot/secmon_boot_setup.cpp index 1f56214b6..2f7217f25 100644 --- a/exosphere/program/source/boot/secmon_boot_setup.cpp +++ b/exosphere/program/source/boot/secmon_boot_setup.cpp @@ -60,7 +60,12 @@ namespace ams::secmon::boot { reg::ReadWrite(pmc + APBDEV_PMC_SECURE_SCRATCH21, REG_BITS_VALUE(4, 1, 1)); /* Write the warmboot key. */ - /* TODO */ + /* TODO: This is necessary for mariko. We should decide how to handle this. */ + /* In particular, mariko will need to support loading older-than-expected warmboot firmware. */ + /* We could hash the warmboot firmware and use a lookup table, or require bootloader to provide */ + /* The warmboot key as a parameter. The latter is a better solution, but it would be nice to take */ + /* care of it here. Perhaps we should read the number of anti-downgrade fuses burnt, and translate that */ + /* to the warmboot key? To be decided during the process of implementing ams-on-mariko support. */ } /* This function derives the master kek and device keys using the tsec root key. */ diff --git a/exosphere/program/source/secmon_error.cpp b/exosphere/program/source/secmon_error.cpp index c05bf4cd7..5b576294b 100644 --- a/exosphere/program/source/secmon_error.cpp +++ b/exosphere/program/source/secmon_error.cpp @@ -16,12 +16,17 @@ #include #include "secmon_error.hpp" +namespace { + + constexpr bool SaveSystemStateForDebug = false; + +} + namespace ams::diag { - void AbortImpl() { - /* TODO: This is here for debugging. Remove this when exo2 is working. */ -#if 1 - { + namespace { + + ALWAYS_INLINE void SaveSystemStateForDebugAbort() { *(volatile u32 *)(secmon::MemoryRegionVirtualDebug.GetAddress() + 0x00) = 0xDDDDDDDD; u64 temp_reg; @@ -39,7 +44,14 @@ namespace ams::diag { util::WaitMicroSeconds(1000); } -#endif + + } + + void AbortImpl() { + /* Perform any necessary (typically none) debugging. */ + if constexpr (SaveSystemStateForDebug) { + SaveSystemStateForDebugAbort(); + } secmon::SetError(pkg1::ErrorInfo_UnknownAbort); secmon::ErrorReboot(); @@ -49,18 +61,11 @@ namespace ams::diag { namespace ams::secmon { - void SetError(pkg1::ErrorInfo info) { - const uintptr_t address = secmon::MemoryRegionVirtualDevicePmc.GetAddress() + PKG1_SECURE_MONITOR_PMC_ERROR_SCRATCH; + namespace { - if (reg::Read(address) == pkg1::ErrorInfo_None) { - reg::Write(address, info); - } - } + constexpr inline uintptr_t PMC = MemoryRegionVirtualDevicePmc.GetAddress(); - NORETURN void ErrorReboot() { - /* TODO: This is here for debugging. Remove this when exo2 is working. */ -#if 1 - { + ALWAYS_INLINE void SaveSystemStateForDebugErrorReboot() { u64 temp_reg; *(volatile u32 *)(secmon::MemoryRegionVirtualDebug.GetAddress() + 0x00) = 0x5A5A5A5A; @@ -92,14 +97,31 @@ namespace ams::secmon { util::WaitMicroSeconds(1000); } -#endif + + } + + void SetError(pkg1::ErrorInfo info) { + const uintptr_t address = secmon::MemoryRegionVirtualDevicePmc.GetAddress() + PKG1_SECURE_MONITOR_PMC_ERROR_SCRATCH; + + if (reg::Read(address) == pkg1::ErrorInfo_None) { + reg::Write(address, info); + } + } + + NORETURN void ErrorReboot() { + /* Perform any necessary (typically none) debugging. */ + if constexpr (SaveSystemStateForDebug) { + SaveSystemStateForDebugErrorReboot(); + } /* Lockout the security engine. */ se::Lockout(); - /* TODO: Lockout fuses. */ + /* Lockout fuses. */ + fuse::Lockout(); - /* TODO: Disable SE Crypto Operations. */ + /* Disable crypto operations after reboot. */ + reg::Write(PMC + APBDEV_PMC_CRYPTO_OP, 0); while (true) { wdt::Reboot(); diff --git a/exosphere/program/source/smc/secmon_smc_error.cpp b/exosphere/program/source/smc/secmon_smc_error.cpp index 70ea8f1db..28f7b277b 100644 --- a/exosphere/program/source/smc/secmon_smc_error.cpp +++ b/exosphere/program/source/smc/secmon_smc_error.cpp @@ -20,8 +20,21 @@ namespace ams::secmon::smc { SmcResult SmcShowError(SmcArguments &args) { - /* TODO */ - return SmcResult::NotImplemented; + /* Decode arguments. */ + const u32 r = ((args.r[1] >> 8) & 0xF); + const u32 g = ((args.r[1] >> 4) & 0xF); + const u32 b = ((args.r[1] >> 0) & 0xF); + + const u32 rgb = (b << 8) | (g << 4) | (r << 0); + + /* Set the error info. */ + SetError(pkg1::MakeKernelPanicResetInfo(rgb)); + + /* Reboot. */ + ErrorReboot(); + + /* This point will never be reached. */ + __builtin_unreachable(); } } diff --git a/exosphere/program/source/smc/secmon_smc_handler.cpp b/exosphere/program/source/smc/secmon_smc_handler.cpp index e79d7a007..3c790e3a7 100644 --- a/exosphere/program/source/smc/secmon_smc_handler.cpp +++ b/exosphere/program/source/smc/secmon_smc_handler.cpp @@ -239,40 +239,6 @@ namespace ams::secmon::smc { return info.handler(args); } - constinit std::atomic g_logged = 0; - - constexpr int LogMin = 0x1000000; - constexpr int LogMax = 0x1000000; - - constexpr size_t LogBufSize = 0x5000; - - void DebugLog(SmcArguments &args) { - const int current = g_logged.fetch_add(1); - - if (current == 0) { - std::memset(MemoryRegionVirtualDebug.GetPointer(), 0xCC, LogBufSize); - } - - if (current < LogMin) { - return; - } - - const int ind = current - LogMin; - const int ofs = (ind * sizeof(args)) % LogBufSize; - - for (size_t i = 0; i < sizeof(args) / sizeof(u32); ++i) { - ((volatile u32 *)(MemoryRegionVirtualDebug.GetAddress() + ofs))[i] = reinterpret_cast(std::addressof(args))[i]; - } - - if (current >= LogMax) { - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x50) = 0x02; - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x00) = 0x10; - - util::WaitMicroSeconds(1000); - } - - } - } void ConfigureSmcHandlersForTargetFirmware() { @@ -288,45 +254,11 @@ namespace ams::secmon::smc { /* Get the table. */ const auto &table = GetHandlerTable(static_cast(type), args.r[0]); - if (std::addressof(table) == std::addressof(g_handler_tables[HandlerType_User])) { - DebugLog(args); - } - /* Get the handler info. */ const auto &info = GetHandlerInfo(table, args.r[0]); /* Set the invocation result. */ args.r[0] = static_cast(InvokeSmcHandler(info, args)); - - if (std::addressof(table) == std::addressof(g_handler_tables[HandlerType_User])) { - DebugLog(args); - } - -/* TODO: For debugging. Remove this when exo2 is complete. */ -#if 1 - if (args.r[0] == static_cast(SmcResult::NotImplemented)) { - *(volatile u32 *)(MemoryRegionVirtualDebug.GetAddress()) = 0xBBBBBBBB; - *(volatile u32 *)(MemoryRegionVirtualDebug.GetAddress() + 0x10) = static_cast(info.function_id); - for (size_t i = 0; i < sizeof(args) / sizeof(u32); ++i) { - ((volatile u32 *)(MemoryRegionVirtualDebug.GetAddress() + 0x20))[i] = reinterpret_cast(std::addressof(args))[i]; - } - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x50) = 0x02; - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x00) = 0x10; - - util::WaitMicroSeconds(1000); - } - if (args.r[0] != static_cast(SmcResult::Success) && info.function_id != 0xC3000007 /* generate aes key fails during SetupKekAccessKeys */) { - *(volatile u32 *)(MemoryRegionVirtualDebug.GetAddress()) = 0xCCCCCCCC; - *(volatile u32 *)(MemoryRegionVirtualDebug.GetAddress() + 0x10) = static_cast(info.function_id); - for (size_t i = 0; i < sizeof(args) / sizeof(u32); ++i) { - ((volatile u32 *)(MemoryRegionVirtualDebug.GetAddress() + 0x20))[i] = reinterpret_cast(std::addressof(args))[i]; - } - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x50) = 0x02; - *(volatile u32 *)(MemoryRegionVirtualDevicePmc.GetAddress() + 0x00) = 0x10; - - util::WaitMicroSeconds(1000); - } -#endif } } diff --git a/exosphere/program/source/smc/secmon_smc_power_management.cpp b/exosphere/program/source/smc/secmon_smc_power_management.cpp index 99008ddf6..4af64ee37 100644 --- a/exosphere/program/source/smc/secmon_smc_power_management.cpp +++ b/exosphere/program/source/smc/secmon_smc_power_management.cpp @@ -325,7 +325,7 @@ namespace ams::secmon::smc { } void SaveSecureContextForMariko() { - /* TODO */ + /* TODO: Implement this when adding ams-on-mariko support. */ } void SaveSecureContext() {