bpmpfw: disable SMMU for FW
This commit is contained in:
1 parent
cbaa61385c
commit
6980a12324
2 files changed
+72
-4
No files matched your search
@@ -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. */
|
||||
|
||||
@@ -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<u32>(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<unsigned long long>(FwIramPhysBase));
|
||||
|
||||
/* Disable the SMMU so DRAM can be accessed */
|
||||
DisableBpmpSmmu();
|
||||
|
||||
/* Set BPMP reset */
|
||||
Mmio(board::clkVirtAddr, ClkRstRstDevLSet) = RstDevLCopRstBit;
|
||||
|
||||
|
||||
Reference in new issue
Block a user