From cc6b8ea4d1e0a8d668aec88f8d12e6cb465fc220 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 26 Aug 2020 01:36:59 -0700 Subject: [PATCH] exo/kern: 1.0.0 requires access to bpmp smmu regs, userland (am) needs to map bpmp exception vectors --- .../source/smc/secmon_smc_register_access.cpp | 28 +++++++++++++------ ...kern_k_memory_layout.board.nintendo_nx.cpp | 6 ++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/exosphere/program/source/smc/secmon_smc_register_access.cpp b/exosphere/program/source/smc/secmon_smc_register_access.cpp index cdf834353..b07b6d13d 100644 --- a/exosphere/program/source/smc/secmon_smc_register_access.cpp +++ b/exosphere/program/source/smc/secmon_smc_register_access.cpp @@ -155,10 +155,27 @@ namespace ams::secmon::smc { /* Find the access table. */ const AccessTableEntry * const entry = GetAccessTableEntry(address); - /* If we have a table, perform the write. */ + /* Translate our entry into an address to access. */ + uintptr_t virtual_address = 0; if (entry != nullptr) { /* Get the address to read or write. */ - const uintptr_t virtual_address = entry->virtual_address + (address - entry->address); + virtual_address = entry->virtual_address + (address - entry->address); + } else { + /* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */ + /* when accessing the SMMU controls for the BPMP and for APB-DMA. */ + /* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */ + /* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */ + constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress(); + SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument); + + /* For backwards compatibility, we'll allow access to these devices on 1.0.0. */ + if (GetTargetFirmware() < TargetFirmware_2_0_0) { + virtual_address = MemoryRegionVirtualDeviceMemoryController.GetAddress() + (address - MC); + } + } + + /* Perform the read or write, if we should. */ + if (virtual_address != 0) { u32 out = 0; if (mask != ~static_cast(0)) { @@ -169,13 +186,6 @@ namespace ams::secmon::smc { } args.r[1] = out; - } else { - /* For no clearly discernable reason, SmcReadWriteRegister returns success despite not doing the read/write */ - /* when accessing the SMMU controls for the BPMP and for APB-DMA. */ - /* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */ - /* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */ - constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress(); - SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument); } return SmcResult::Success; diff --git a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp index b9b6229b6..f592f0716 100644 --- a/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp +++ b/libraries/libmesosphere/source/kern_k_memory_layout.board.nintendo_nx.cpp @@ -70,8 +70,10 @@ namespace ams::kern { MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50041000, 0x1000, KMemoryRegionType_InterruptDistributor | KMemoryRegionAttr_ShouldKernelMap)); MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50042000, 0x1000, KMemoryRegionType_InterruptCpuInterface | KMemoryRegionAttr_ShouldKernelMap)); MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x50043000, 0x1D000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); - MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); - MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); + if (GetTargetFirmware() >= TargetFirmware_2_0_0) { + MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6000F000, 0x1000, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); + MESOSPHERE_INIT_ABORT_UNLESS(KMemoryLayout::GetPhysicalMemoryRegionTree().Insert(0x6001DC00, 0x400, KMemoryRegionType_None | KMemoryRegionAttr_NoUserMap)); + } } void SetupDramPhysicalMemoryRegions() {