diff --git a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp index d42f6583..af04fa04 100644 --- a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp +++ b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp @@ -174,12 +174,12 @@ namespace ams::secmon::smc { /* 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); + // 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) { + // /* 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. */ diff --git a/Source/hoc-clk/sysmodule/src/bpmp/bpmp.cpp b/Source/hoc-clk/sysmodule/src/bpmp/bpmp.cpp index 7c626409..4fe5003c 100644 --- a/Source/hoc-clk/sysmodule/src/bpmp/bpmp.cpp +++ b/Source/hoc-clk/sysmodule/src/bpmp/bpmp.cpp @@ -53,6 +53,32 @@ namespace bpmp { constexpr u32 ActmonGlbPeriodCtrlUsec = (1u << 8); constexpr u32 ActmonCopCtrlStockArmed = (1u << 31) | (1u << 30) | (1u << 18); + /* MC SMMU handling for the BPMP. */ + constexpr u64 McPhysBase = 0x70019000; + + constexpr u32 McSmmuTlbConfig = 0x014; + constexpr u32 McSmmuPtbAsid = 0x01C; + constexpr u32 McSmmuPtbData = 0x020; + constexpr u32 McSmmuTlbFlush = 0x030; + constexpr u32 McSmmuPtcFlush = 0x034; + constexpr u32 McSmmuAvpcAsid = 0x23C; + constexpr u32 McSmmuPpcs1Asid = 0x298; + + /* Page table is backed by the security engine's MMIO aperture. */ + constexpr u64 BpmpSmmuPdeBase = 0x70012000; + constexpr u32 BpmpSmmuAsid = 1; + + /* MC_SMMU_PTB_ASID */ + constexpr u32 SmmuPtbAsidCurrentAsid = BpmpSmmuAsid; /* [0:7] */ + + /* MC_SMMU_PTB_DATA */ + constexpr u32 SmmuPtbDataPdeMask = 0x7FFFFF; /* [0:22] */ + + /* MC_SMMU_AVPC_ASID / MC_SMMU_PPCS1_ASID */ + constexpr u32 SmmuClientSmmuEnableBit = (1u << 31); + constexpr u32 SmmuAvpcAsidValue = (SmmuClientSmmuEnableBit | BpmpSmmuAsid); + constexpr u32 SmmuPpcs1AsidValue = (SmmuClientSmmuEnableBit | BpmpSmmuAsid); + constexpr u32 EvpCopResetVector = 0x200; constexpr u32 EvpCopUndefVector = 0x204; constexpr u32 EvpCopSwiVector = 0x208; @@ -122,6 +148,43 @@ namespace bpmp { fileUtils::LogLine("[bpmp] RequestBpmpExitAndWait: BPMP timeout (cannot sleep)"); } + void EnableBpmpSmmu() { + /* Point the ASID page table at the security engine aperture. */ + const u32 pde_base = static_cast(BpmpSmmuPdeBase / 0x1000); + + /* Select the ASID and configure its page table entry. */ + SmcReadWriteRegister(McPhysBase + McSmmuPtbAsid, 0xFFFFFFFF, SmmuPtbAsidCurrentAsid); + SmcReadWriteRegister(McPhysBase + McSmmuPtbData, 0xFFFFFFFF, pde_base & SmmuPtbDataPdeMask); + + /* Route BPMP (AVPC) and PPCS1 through the SMMU. */ + SmcReadWriteRegister(McPhysBase + McSmmuAvpcAsid, 0xFFFFFFFF, SmmuAvpcAsidValue); + SmcReadWriteRegister(McPhysBase + McSmmuPpcs1Asid, 0xFFFFFFFF, SmmuPpcs1AsidValue); + + /* Flush the page table cache. */ + SmcReadWriteRegister(McPhysBase + McSmmuPtcFlush, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuTlbConfig, 0, 0); + + /* Flush the translation lookaside buffer. */ + SmcReadWriteRegister(McPhysBase + McSmmuTlbFlush, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuTlbConfig, 0, 0); + } + + void DisableBpmpSmmu() { + /* Clear the ASID page table. */ + SmcReadWriteRegister(McPhysBase + McSmmuPtbAsid, 0xFFFFFFFF, SmmuPtbAsidCurrentAsid); + SmcReadWriteRegister(McPhysBase + McSmmuPtbData, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuAvpcAsid, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuPpcs1Asid, 0xFFFFFFFF, 0); + + /* Flush the page table cache. */ + SmcReadWriteRegister(McPhysBase + McSmmuPtcFlush, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuTlbConfig, 0, 0); + + /* Flush the translation lookaside buffer. */ + SmcReadWriteRegister(McPhysBase + McSmmuTlbFlush, 0xFFFFFFFF, 0); + SmcReadWriteRegister(McPhysBase + McSmmuTlbConfig, 0, 0); + } + void RestoreStockState() { RequestBpmpExitAndWait(); @@ -140,6 +203,8 @@ namespace bpmp { Mmio(board::actmonVirtAddr, ActmonCopUpperWmark) = 0; Mmio(board::actmonVirtAddr, ActmonCopIntrStatus) = Mmio(board::actmonVirtAddr, ActmonCopIntrStatus); Mmio(board::actmonVirtAddr, ActmonCopCtrl) = ActmonCopCtrlStockArmed; + + EnableBpmpSmmu(); } void PscThreadFunc(void *) { @@ -194,6 +259,9 @@ namespace bpmp { fileUtils::LogLine("[bpmp] StartBpmfwExecution: loading %zu bytes at 0x%llx", fw_size, static_cast(FwIramPhysBase)); + /* Disable the SMMU so DRAM can be accessed */ + DisableBpmpSmmu(); + /* Set BPMP reset */ Mmio(board::clkVirtAddr, ClkRstRstDevLSet) = RstDevLCopRstBit;