diff --git a/Source/Atmosphere-Patches/diff/README.MD b/Source/Atmosphere-Patches/diff/README.MD
new file mode 100644
index 00000000..b96a27bc
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/README.MD
@@ -0,0 +1 @@
+This contains a diff all modifications done to exosphere
diff --git a/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff
new file mode 100644
index 00000000..1cb6ab99
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff
@@ -0,0 +1,57 @@
+131,156c131,159
+< #define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
+< HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+< HANDLER(Uart, GicCpuInterface, UINT64_C(0x70006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
+< HANDLER(ClkRst, Uart, UINT64_C(0x60006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
+< HANDLER(RtcPmc, ClkRst, UINT64_C(0x7000E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(Timer, RtcPmc, UINT64_C(0x60005000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(System, Timer, UINT64_C(0x6000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(SecurityEngine, System, UINT64_C(0x70012000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+< HANDLER(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+< HANDLER(SysCtr0, SecurityEngine2, UINT64_C(0x700F0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(MemoryController, SysCtr0, UINT64_C(0x70019000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(FuseKFuse, MemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(ApbMisc, FuseKFuse, UINT64_C(0x70000000), UINT64_C(0x4000), true, ## __VA_ARGS__) \
+< HANDLER(FlowController, ApbMisc, UINT64_C(0x60007000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(BootloaderParams, FlowController, UINT64_C(0x40000000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(I2c5, BootloaderParams, UINT64_C(0x7000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(Gpio, I2c5, UINT64_C(0x6000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(I2c1, Gpio, UINT64_C(0x7000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
+< HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+< HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__)
+---
+> #define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
+> HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+> HANDLER(Uart, GicCpuInterface, UINT64_C(0x70006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
+> HANDLER(ClkRst, Uart, UINT64_C(0x60006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
+> HANDLER(RtcPmc, ClkRst, UINT64_C(0x7000E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(Timer, RtcPmc, UINT64_C(0x60005000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(System, Timer, UINT64_C(0x6000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(SecurityEngine, System, UINT64_C(0x70012000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+> HANDLER(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
+> HANDLER(SysCtr0, SecurityEngine2, UINT64_C(0x700F0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(MemoryController, SysCtr0, UINT64_C(0x70019000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExternalMemoryController, MemoryController, UINT64_C(0x7001b000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(FuseKFuse, ExternalMemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ApbMisc, FuseKFuse, UINT64_C(0x70000000), UINT64_C(0x4000), true, ## __VA_ARGS__) \
+> HANDLER(FlowController, ApbMisc, UINT64_C(0x60007000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(BootloaderParams, FlowController, UINT64_C(0x40000000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(I2c5, BootloaderParams, UINT64_C(0x7000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(Gpio, I2c5, UINT64_C(0x6000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(I2c1, Gpio, UINT64_C(0x7000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
+> HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+> HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
diff --git a/Source/Atmosphere-Patches/diff/secmon_setup.diff b/Source/Atmosphere-Patches/diff/secmon_setup.diff
new file mode 100644
index 00000000..5b796e03
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/secmon_setup.diff
@@ -0,0 +1,29 @@
+1221c1221
+< const auto target_fw = GetTargetFirmware();
+---
+> // const auto target_fw = GetTargetFirmware();
+1223,1226c1223,1226
+< if (target_fw >= TargetFirmware_2_0_0) {
+< /* Set the PMC secure. */
+< reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE));
+< }
+---
+> // if (target_fw >= TargetFirmware_2_0_0) {
+> // /* Set the PMC secure. */ I REFUSE
+> // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE));
+> // }
+1228,1233c1228,1234
+< if (target_fw >= TargetFirmware_4_0_0) {
+< /* Set the MC secure. */
+< reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE),
+< SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE),
+< SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE));
+< }
+---
+> // if (target_fw >= TargetFirmware_4_0_0) {
+> // /* Set the MC secure. */ I REFUSE
+> // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE),
+> // SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE),
+> // SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE));
+> // }
+> return;
diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff b/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff
new file mode 100644
index 00000000..ee25f585
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff
@@ -0,0 +1,2 @@
+154a155
+> { 0xF0000005, Restriction_None, SmcShowError },
diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_power_management.diff b/Source/Atmosphere-Patches/diff/secmon_smc_power_management.diff
new file mode 100644
index 00000000..78251361
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/secmon_smc_power_management.diff
@@ -0,0 +1,9 @@
+160c160
+< /* Validate that the bpmp is appropriately halted. */
+---
+> /* Horizon-OC: Halt BPMP here as hoc-clk may be running it, and if it's running there will be a panic. */
+161a162,165
+> reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
+> FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, jtag, ENABLED, DISABLED));
+>
+> /* Validate that the bpmp is appropriately halted. */
diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff
new file mode 100644
index 00000000..e4c4375a
--- /dev/null
+++ b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff
@@ -0,0 +1,22 @@
+100a101,105
+> #include "secmon_define_emc_access_table.inc"
+> #include "secmon_define_emc01_access_table.inc"
+> #include "secmon_define_flow_controller_access_table.inc"
+> #include "secmon_define_exception_vectors_access_table.inc"
+> #include "secmon_define_rtc_pmc_access_table.inc"
+104,107c109,118
+< { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
+< { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
+< { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
+< { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
+---
+> { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
+> { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
+> { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
+> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, },
+> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, },
+> { FlowControllerAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceFlowController.GetAddress(), FlowControllerAccessTable::Address, FlowControllerAccessTable::Size, },
+> { ExceptionVectorsAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExceptionVectors.GetAddress(), ExceptionVectorsAccessTable::Address, ExceptionVectorsAccessTable::Size, },
+> { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
+> { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
+> { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
diff --git a/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc b/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc
new file mode 100644
index 00000000..3a34e1dc
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+#define __ACCESS_TABLE_NAME__ Emc01AccessTable
+#define __ACCESS_TABLE_ADDRESS__ 0
+#define __ACCESS_TABLE_INC__ "secmon_emc01_access_table_data.inc"
+
+#include "secmon_define_access_table.inc"
+
+#undef __ACCESS_TABLE_INC__
+#undef __ACCESS_TABLE_ADDRESS__
+#undef __ACCESS_TABLE_NAME__
diff --git a/Source/Atmosphere-Patches/secmon_define_exception_vectors_access_table.inc b/Source/Atmosphere-Patches/secmon_define_exception_vectors_access_table.inc
new file mode 100644
index 00000000..2c06ea01
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_define_exception_vectors_access_table.inc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+#define __ACCESS_TABLE_NAME__ ExceptionVectorsAccessTable
+#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExceptionVectors.GetAddress()
+#define __ACCESS_TABLE_INC__ "secmon_exception_vectors_access_table_data.inc"
+
+#include "secmon_define_access_table.inc"
+
+#undef __ACCESS_TABLE_INC__
+#undef __ACCESS_TABLE_ADDRESS__
+#undef __ACCESS_TABLE_NAME__
diff --git a/Source/Atmosphere-Patches/secmon_define_flow_controller_access_table.inc b/Source/Atmosphere-Patches/secmon_define_flow_controller_access_table.inc
new file mode 100644
index 00000000..99589e76
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_define_flow_controller_access_table.inc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+#define __ACCESS_TABLE_NAME__ FlowControllerAccessTable
+#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceFlowController.GetAddress()
+#define __ACCESS_TABLE_INC__ "secmon_flow_controller_access_table_data.inc"
+
+#include "secmon_define_access_table.inc"
+
+#undef __ACCESS_TABLE_INC__
+#undef __ACCESS_TABLE_ADDRESS__
+#undef __ACCESS_TABLE_NAME__
diff --git a/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc
new file mode 100644
index 00000000..a3718c5e
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+SetRegisterAllowed(0x0);
+SetRegisterAllowed(0x4);
+SetRegisterAllowed(0x8);
+SetRegisterAllowed(0xC);
+SetRegisterAllowed(0x10);
+SetRegisterAllowed(0x14);
+SetRegisterAllowed(0x18);
+SetRegisterAllowed(0x1C);
+SetRegisterAllowed(0x20);
+SetRegisterAllowed(0x24);
+SetRegisterAllowed(0x28);
+SetRegisterAllowed(0x2C);
+SetRegisterAllowed(0x30);
+SetRegisterAllowed(0x34);
+SetRegisterAllowed(0x38);
+SetRegisterAllowed(0x3C);
+SetRegisterAllowed(0x40);
+SetRegisterAllowed(0x44);
+SetRegisterAllowed(0x48);
+SetRegisterAllowed(0x4C);
+SetRegisterAllowed(0x50);
+SetRegisterAllowed(0x54);
+SetRegisterAllowed(0x58);
+SetRegisterAllowed(0x5C);
+SetRegisterAllowed(0x60);
+SetRegisterAllowed(0x64);
+SetRegisterAllowed(0x68);
+SetRegisterAllowed(0x6C);
+SetRegisterAllowed(0x70);
+SetRegisterAllowed(0x74);
+SetRegisterAllowed(0x78);
+SetRegisterAllowed(0x7C);
+SetRegisterAllowed(0x80);
+SetRegisterAllowed(0x84);
+SetRegisterAllowed(0x88);
+SetRegisterAllowed(0x8C);
+SetRegisterAllowed(0x90);
+SetRegisterAllowed(0x94);
+SetRegisterAllowed(0x98);
+SetRegisterAllowed(0x9C);
+SetRegisterAllowed(0xA0);
+SetRegisterAllowed(0xA4);
+SetRegisterAllowed(0xA8);
+SetRegisterAllowed(0xAC);
+SetRegisterAllowed(0xB0);
+SetRegisterAllowed(0xB4);
+SetRegisterAllowed(0xB8);
+SetRegisterAllowed(0xBC);
+SetRegisterAllowed(0xC0);
+SetRegisterAllowed(0xC4);
+SetRegisterAllowed(0xC8);
+SetRegisterAllowed(0xCC);
+SetRegisterAllowed(0xD0);
+SetRegisterAllowed(0xD4);
+SetRegisterAllowed(0xD8);
+SetRegisterAllowed(0xDC);
+SetRegisterAllowed(0xE0);
+SetRegisterAllowed(0xE4);
+SetRegisterAllowed(0xE8);
+SetRegisterAllowed(0xEC);
+SetRegisterAllowed(0xF0);
+SetRegisterAllowed(0xF4);
+SetRegisterAllowed(0xF8);
+SetRegisterAllowed(0xFC);
+SetRegisterAllowed(0x100);
+SetRegisterAllowed(0x104);
+SetRegisterAllowed(0x108);
+SetRegisterAllowed(0x10C);
+SetRegisterAllowed(0x110);
+SetRegisterAllowed(0x114);
+SetRegisterAllowed(0x118);
+SetRegisterAllowed(0x11C);
+SetRegisterAllowed(0x120);
+SetRegisterAllowed(0x124);
+SetRegisterAllowed(0x128);
+SetRegisterAllowed(0x12C);
+SetRegisterAllowed(0x130);
+SetRegisterAllowed(0x134);
+SetRegisterAllowed(0x138);
+SetRegisterAllowed(0x13C);
+SetRegisterAllowed(0x140);
+SetRegisterAllowed(0x144);
+SetRegisterAllowed(0x148);
+SetRegisterAllowed(0x14C);
+SetRegisterAllowed(0x150);
+SetRegisterAllowed(0x154);
+SetRegisterAllowed(0x158);
+SetRegisterAllowed(0x15C);
+SetRegisterAllowed(0x160);
+SetRegisterAllowed(0x164);
+SetRegisterAllowed(0x168);
+SetRegisterAllowed(0x16C);
+SetRegisterAllowed(0x170);
+SetRegisterAllowed(0x174);
+SetRegisterAllowed(0x178);
+SetRegisterAllowed(0x17C);
+SetRegisterAllowed(0x180);
+SetRegisterAllowed(0x184);
+SetRegisterAllowed(0x188);
+SetRegisterAllowed(0x18C);
+SetRegisterAllowed(0x190);
+SetRegisterAllowed(0x194);
+SetRegisterAllowed(0x198);
+SetRegisterAllowed(0x19C);
+SetRegisterAllowed(0x1A0);
+SetRegisterAllowed(0x1A4);
+SetRegisterAllowed(0x1A8);
+SetRegisterAllowed(0x1AC);
+SetRegisterAllowed(0x1B0);
+SetRegisterAllowed(0x1B4);
+SetRegisterAllowed(0x1B8);
+SetRegisterAllowed(0x1BC);
+SetRegisterAllowed(0x1C0);
+SetRegisterAllowed(0x1C4);
+SetRegisterAllowed(0x1C8);
+SetRegisterAllowed(0x1CC);
+SetRegisterAllowed(0x1D0);
+SetRegisterAllowed(0x1D4);
+SetRegisterAllowed(0x1D8);
+SetRegisterAllowed(0x1DC);
+SetRegisterAllowed(0x1E0);
+SetRegisterAllowed(0x1E4);
+SetRegisterAllowed(0x1E8);
+SetRegisterAllowed(0x1EC);
+SetRegisterAllowed(0x1F0);
+SetRegisterAllowed(0x1F4);
+SetRegisterAllowed(0x1F8);
+SetRegisterAllowed(0x1FC);
+SetRegisterAllowed(0x200);
+SetRegisterAllowed(0x204);
+SetRegisterAllowed(0x208);
+SetRegisterAllowed(0x20C);
+SetRegisterAllowed(0x210);
+SetRegisterAllowed(0x214);
+SetRegisterAllowed(0x218);
+SetRegisterAllowed(0x21C);
+SetRegisterAllowed(0x220);
+SetRegisterAllowed(0x224);
+SetRegisterAllowed(0x228);
+SetRegisterAllowed(0x22C);
+SetRegisterAllowed(0x230);
+SetRegisterAllowed(0x234);
+SetRegisterAllowed(0x238);
+SetRegisterAllowed(0x23C);
+SetRegisterAllowed(0x240);
+SetRegisterAllowed(0x244);
+SetRegisterAllowed(0x248);
+SetRegisterAllowed(0x24C);
+SetRegisterAllowed(0x250);
+SetRegisterAllowed(0x254);
+SetRegisterAllowed(0x258);
+SetRegisterAllowed(0x25C);
+SetRegisterAllowed(0x260);
+SetRegisterAllowed(0x264);
+SetRegisterAllowed(0x268);
+SetRegisterAllowed(0x26C);
+SetRegisterAllowed(0x270);
+SetRegisterAllowed(0x274);
+SetRegisterAllowed(0x278);
+SetRegisterAllowed(0x27C);
+SetRegisterAllowed(0x280);
+SetRegisterAllowed(0x284);
+SetRegisterAllowed(0x288);
+SetRegisterAllowed(0x28C);
+SetRegisterAllowed(0x290);
+SetRegisterAllowed(0x294);
+SetRegisterAllowed(0x298);
+SetRegisterAllowed(0x29C);
+SetRegisterAllowed(0x2A0);
+SetRegisterAllowed(0x2A4);
+SetRegisterAllowed(0x2A8);
+SetRegisterAllowed(0x2AC);
+SetRegisterAllowed(0x2B0);
+SetRegisterAllowed(0x2B4);
+SetRegisterAllowed(0x2B8);
+SetRegisterAllowed(0x2BC);
+SetRegisterAllowed(0x2C0);
+SetRegisterAllowed(0x2C4);
+SetRegisterAllowed(0x2C8);
+SetRegisterAllowed(0x2CC);
+SetRegisterAllowed(0x2D0);
+SetRegisterAllowed(0x2D4);
+SetRegisterAllowed(0x2D8);
+SetRegisterAllowed(0x2DC);
+SetRegisterAllowed(0x2E0);
+SetRegisterAllowed(0x2E4);
+SetRegisterAllowed(0x2E8);
+SetRegisterAllowed(0x2EC);
+SetRegisterAllowed(0x2F0);
+SetRegisterAllowed(0x2F4);
+SetRegisterAllowed(0x2F8);
+SetRegisterAllowed(0x2FC);
+SetRegisterAllowed(0x300);
+SetRegisterAllowed(0x304);
+SetRegisterAllowed(0x308);
+SetRegisterAllowed(0x30C);
+SetRegisterAllowed(0x310);
+SetRegisterAllowed(0x314);
+SetRegisterAllowed(0x318);
+SetRegisterAllowed(0x31C);
+SetRegisterAllowed(0x320);
+SetRegisterAllowed(0x324);
+SetRegisterAllowed(0x328);
+SetRegisterAllowed(0x32C);
+SetRegisterAllowed(0x330);
+SetRegisterAllowed(0x334);
+SetRegisterAllowed(0x338);
+SetRegisterAllowed(0x33C);
+SetRegisterAllowed(0x340);
+SetRegisterAllowed(0x344);
+SetRegisterAllowed(0x348);
+SetRegisterAllowed(0x34C);
+SetRegisterAllowed(0x350);
+SetRegisterAllowed(0x354);
+SetRegisterAllowed(0x358);
+SetRegisterAllowed(0x35C);
+SetRegisterAllowed(0x360);
+SetRegisterAllowed(0x364);
+SetRegisterAllowed(0x368);
+SetRegisterAllowed(0x36C);
+SetRegisterAllowed(0x370);
+SetRegisterAllowed(0x374);
+SetRegisterAllowed(0x378);
+SetRegisterAllowed(0x37C);
+SetRegisterAllowed(0x380);
+SetRegisterAllowed(0x384);
+SetRegisterAllowed(0x388);
+SetRegisterAllowed(0x38C);
+SetRegisterAllowed(0x390);
+SetRegisterAllowed(0x394);
+SetRegisterAllowed(0x398);
+SetRegisterAllowed(0x39C);
+SetRegisterAllowed(0x3A0);
+SetRegisterAllowed(0x3A4);
+SetRegisterAllowed(0x3A8);
+SetRegisterAllowed(0x3AC);
+SetRegisterAllowed(0x3B0);
+SetRegisterAllowed(0x3B4);
+SetRegisterAllowed(0x3B8);
+SetRegisterAllowed(0x3BC);
+SetRegisterAllowed(0x3C0);
+SetRegisterAllowed(0x3C4);
+SetRegisterAllowed(0x3C8);
+SetRegisterAllowed(0x3CC);
+SetRegisterAllowed(0x3D0);
+SetRegisterAllowed(0x3D4);
+SetRegisterAllowed(0x3D8);
+SetRegisterAllowed(0x3DC);
+SetRegisterAllowed(0x3E0);
+SetRegisterAllowed(0x3E4);
+SetRegisterAllowed(0x3E8);
+SetRegisterAllowed(0x3EC);
+SetRegisterAllowed(0x3F0);
+SetRegisterAllowed(0x3F4);
+SetRegisterAllowed(0x3F8);
+SetRegisterAllowed(0x3FC);
+SetRegisterAllowed(0x400);
+SetRegisterAllowed(0x404);
+SetRegisterAllowed(0x408);
+SetRegisterAllowed(0x40C);
+SetRegisterAllowed(0x410);
+SetRegisterAllowed(0x414);
+SetRegisterAllowed(0x418);
+SetRegisterAllowed(0x41C);
+SetRegisterAllowed(0x420);
+SetRegisterAllowed(0x424);
+SetRegisterAllowed(0x428);
+SetRegisterAllowed(0x42C);
+SetRegisterAllowed(0x430);
+SetRegisterAllowed(0x434);
+SetRegisterAllowed(0x438);
+SetRegisterAllowed(0x43C);
+SetRegisterAllowed(0x440);
+SetRegisterAllowed(0x444);
+SetRegisterAllowed(0x448);
+SetRegisterAllowed(0x44C);
+SetRegisterAllowed(0x450);
+SetRegisterAllowed(0x454);
+SetRegisterAllowed(0x458);
+SetRegisterAllowed(0x45C);
+SetRegisterAllowed(0x460);
+SetRegisterAllowed(0x464);
+SetRegisterAllowed(0x468);
+SetRegisterAllowed(0x46C);
+SetRegisterAllowed(0x470);
+SetRegisterAllowed(0x474);
+SetRegisterAllowed(0x478);
+SetRegisterAllowed(0x47C);
+SetRegisterAllowed(0x480);
+SetRegisterAllowed(0x484);
+SetRegisterAllowed(0x488);
+SetRegisterAllowed(0x48C);
+SetRegisterAllowed(0x490);
+SetRegisterAllowed(0x494);
+SetRegisterAllowed(0x498);
+SetRegisterAllowed(0x49C);
+SetRegisterAllowed(0x4A0);
+SetRegisterAllowed(0x4A4);
+SetRegisterAllowed(0x4A8);
+SetRegisterAllowed(0x4AC);
+SetRegisterAllowed(0x4B0);
+SetRegisterAllowed(0x4B4);
+SetRegisterAllowed(0x4B8);
+SetRegisterAllowed(0x4BC);
+SetRegisterAllowed(0x4C0);
+SetRegisterAllowed(0x4C4);
+SetRegisterAllowed(0x4C8);
+SetRegisterAllowed(0x4CC);
+SetRegisterAllowed(0x4D0);
+SetRegisterAllowed(0x4D4);
+SetRegisterAllowed(0x4D8);
+SetRegisterAllowed(0x4DC);
+SetRegisterAllowed(0x4E0);
+SetRegisterAllowed(0x4E4);
+SetRegisterAllowed(0x4E8);
+SetRegisterAllowed(0x4EC);
+SetRegisterAllowed(0x4F0);
+SetRegisterAllowed(0x4F4);
+SetRegisterAllowed(0x4F8);
+SetRegisterAllowed(0x4FC);
+SetRegisterAllowed(0x500);
+SetRegisterAllowed(0x504);
+SetRegisterAllowed(0x508);
+SetRegisterAllowed(0x50C);
+SetRegisterAllowed(0x510);
+SetRegisterAllowed(0x514);
+SetRegisterAllowed(0x518);
+SetRegisterAllowed(0x51C);
+SetRegisterAllowed(0x520);
+SetRegisterAllowed(0x524);
+SetRegisterAllowed(0x528);
+SetRegisterAllowed(0x52C);
+SetRegisterAllowed(0x530);
+SetRegisterAllowed(0x534);
+SetRegisterAllowed(0x538);
+SetRegisterAllowed(0x53C);
+SetRegisterAllowed(0x540);
+SetRegisterAllowed(0x544);
+SetRegisterAllowed(0x548);
+SetRegisterAllowed(0x54C);
+SetRegisterAllowed(0x550);
+SetRegisterAllowed(0x554);
+SetRegisterAllowed(0x558);
+SetRegisterAllowed(0x55C);
+SetRegisterAllowed(0x560);
+SetRegisterAllowed(0x564);
+SetRegisterAllowed(0x568);
+SetRegisterAllowed(0x56C);
+SetRegisterAllowed(0x570);
+SetRegisterAllowed(0x574);
+SetRegisterAllowed(0x578);
+SetRegisterAllowed(0x57C);
+SetRegisterAllowed(0x580);
+SetRegisterAllowed(0x584);
+SetRegisterAllowed(0x588);
+SetRegisterAllowed(0x58C);
+SetRegisterAllowed(0x590);
+SetRegisterAllowed(0x594);
+SetRegisterAllowed(0x598);
+SetRegisterAllowed(0x59C);
+SetRegisterAllowed(0x5A0);
+SetRegisterAllowed(0x5A4);
+SetRegisterAllowed(0x5A8);
+SetRegisterAllowed(0x5AC);
+SetRegisterAllowed(0x5B0);
+SetRegisterAllowed(0x5B4);
+SetRegisterAllowed(0x5B8);
+SetRegisterAllowed(0x5BC);
+SetRegisterAllowed(0x5C0);
+SetRegisterAllowed(0x5C4);
+SetRegisterAllowed(0x5C8);
+SetRegisterAllowed(0x5CC);
+SetRegisterAllowed(0x5D0);
+SetRegisterAllowed(0x5D4);
+SetRegisterAllowed(0x5D8);
+SetRegisterAllowed(0x5DC);
+SetRegisterAllowed(0x5E0);
+SetRegisterAllowed(0x5E4);
+SetRegisterAllowed(0x5E8);
+SetRegisterAllowed(0x5EC);
+SetRegisterAllowed(0x5F0);
+SetRegisterAllowed(0x5F4);
+SetRegisterAllowed(0x5F8);
+SetRegisterAllowed(0x5FC);
+SetRegisterAllowed(0x600);
+SetRegisterAllowed(0x604);
+SetRegisterAllowed(0x608);
+SetRegisterAllowed(0x60C);
+SetRegisterAllowed(0x610);
+SetRegisterAllowed(0x614);
+SetRegisterAllowed(0x618);
+SetRegisterAllowed(0x61C);
+SetRegisterAllowed(0x620);
+SetRegisterAllowed(0x624);
+SetRegisterAllowed(0x628);
+SetRegisterAllowed(0x62C);
+SetRegisterAllowed(0x630);
+SetRegisterAllowed(0x634);
+SetRegisterAllowed(0x638);
+SetRegisterAllowed(0x63C);
+SetRegisterAllowed(0x640);
+SetRegisterAllowed(0x644);
+SetRegisterAllowed(0x648);
+SetRegisterAllowed(0x64C);
+SetRegisterAllowed(0x650);
+SetRegisterAllowed(0x654);
+SetRegisterAllowed(0x658);
+SetRegisterAllowed(0x65C);
+SetRegisterAllowed(0x660);
+SetRegisterAllowed(0x664);
+SetRegisterAllowed(0x668);
+SetRegisterAllowed(0x66C);
+SetRegisterAllowed(0x670);
+SetRegisterAllowed(0x674);
+SetRegisterAllowed(0x678);
+SetRegisterAllowed(0x67C);
+SetRegisterAllowed(0x680);
+SetRegisterAllowed(0x684);
+SetRegisterAllowed(0x688);
+SetRegisterAllowed(0x68C);
+SetRegisterAllowed(0x690);
+SetRegisterAllowed(0x694);
+SetRegisterAllowed(0x698);
+SetRegisterAllowed(0x69C);
+SetRegisterAllowed(0x6A0);
+SetRegisterAllowed(0x6A4);
+SetRegisterAllowed(0x6A8);
+SetRegisterAllowed(0x6AC);
+SetRegisterAllowed(0x6B0);
+SetRegisterAllowed(0x6B4);
+SetRegisterAllowed(0x6B8);
+SetRegisterAllowed(0x6BC);
+SetRegisterAllowed(0x6C0);
+SetRegisterAllowed(0x6C4);
+SetRegisterAllowed(0x6C8);
+SetRegisterAllowed(0x6CC);
+SetRegisterAllowed(0x6D0);
+SetRegisterAllowed(0x6D4);
+SetRegisterAllowed(0x6D8);
+SetRegisterAllowed(0x6DC);
+SetRegisterAllowed(0x6E0);
+SetRegisterAllowed(0x6E4);
+SetRegisterAllowed(0x6E8);
+SetRegisterAllowed(0x6EC);
+SetRegisterAllowed(0x6F0);
+SetRegisterAllowed(0x6F4);
+SetRegisterAllowed(0x6F8);
+SetRegisterAllowed(0x6FC);
+SetRegisterAllowed(0x700);
+SetRegisterAllowed(0x704);
+SetRegisterAllowed(0x708);
+SetRegisterAllowed(0x70C);
+SetRegisterAllowed(0x710);
+SetRegisterAllowed(0x714);
+SetRegisterAllowed(0x718);
+SetRegisterAllowed(0x71C);
+SetRegisterAllowed(0x720);
+SetRegisterAllowed(0x724);
+SetRegisterAllowed(0x728);
+SetRegisterAllowed(0x72C);
+SetRegisterAllowed(0x730);
+SetRegisterAllowed(0x734);
+SetRegisterAllowed(0x738);
+SetRegisterAllowed(0x73C);
+SetRegisterAllowed(0x740);
+SetRegisterAllowed(0x744);
+SetRegisterAllowed(0x748);
+SetRegisterAllowed(0x74C);
+SetRegisterAllowed(0x750);
+SetRegisterAllowed(0x754);
+SetRegisterAllowed(0x758);
+SetRegisterAllowed(0x75C);
+SetRegisterAllowed(0x760);
+SetRegisterAllowed(0x764);
+SetRegisterAllowed(0x768);
+SetRegisterAllowed(0x76C);
+SetRegisterAllowed(0x770);
+SetRegisterAllowed(0x774);
+SetRegisterAllowed(0x778);
+SetRegisterAllowed(0x77C);
+SetRegisterAllowed(0x780);
+SetRegisterAllowed(0x784);
+SetRegisterAllowed(0x788);
+SetRegisterAllowed(0x78C);
+SetRegisterAllowed(0x790);
+SetRegisterAllowed(0x794);
+SetRegisterAllowed(0x798);
+SetRegisterAllowed(0x79C);
+SetRegisterAllowed(0x7A0);
+SetRegisterAllowed(0x7A4);
+SetRegisterAllowed(0x7A8);
+SetRegisterAllowed(0x7AC);
+SetRegisterAllowed(0x7B0);
+SetRegisterAllowed(0x7B4);
+SetRegisterAllowed(0x7B8);
+SetRegisterAllowed(0x7BC);
+SetRegisterAllowed(0x7C0);
+SetRegisterAllowed(0x7C4);
+SetRegisterAllowed(0x7C8);
+SetRegisterAllowed(0x7CC);
+SetRegisterAllowed(0x7D0);
+SetRegisterAllowed(0x7D4);
+SetRegisterAllowed(0x7D8);
+SetRegisterAllowed(0x7DC);
+SetRegisterAllowed(0x7E0);
+SetRegisterAllowed(0x7E4);
+SetRegisterAllowed(0x7E8);
+SetRegisterAllowed(0x7EC);
+SetRegisterAllowed(0x7F0);
+SetRegisterAllowed(0x7F4);
+SetRegisterAllowed(0x7F8);
+SetRegisterAllowed(0x7FC);
+SetRegisterAllowed(0x800);
+SetRegisterAllowed(0x804);
+SetRegisterAllowed(0x808);
+SetRegisterAllowed(0x80C);
+SetRegisterAllowed(0x810);
+SetRegisterAllowed(0x814);
+SetRegisterAllowed(0x818);
+SetRegisterAllowed(0x81C);
+SetRegisterAllowed(0x820);
+SetRegisterAllowed(0x824);
+SetRegisterAllowed(0x828);
+SetRegisterAllowed(0x82C);
+SetRegisterAllowed(0x830);
+SetRegisterAllowed(0x834);
+SetRegisterAllowed(0x838);
+SetRegisterAllowed(0x83C);
+SetRegisterAllowed(0x840);
+SetRegisterAllowed(0x844);
+SetRegisterAllowed(0x848);
+SetRegisterAllowed(0x84C);
+SetRegisterAllowed(0x850);
+SetRegisterAllowed(0x854);
+SetRegisterAllowed(0x858);
+SetRegisterAllowed(0x85C);
+SetRegisterAllowed(0x860);
+SetRegisterAllowed(0x864);
+SetRegisterAllowed(0x868);
+SetRegisterAllowed(0x86C);
+SetRegisterAllowed(0x870);
+SetRegisterAllowed(0x874);
+SetRegisterAllowed(0x878);
+SetRegisterAllowed(0x87C);
+SetRegisterAllowed(0x880);
+SetRegisterAllowed(0x884);
+SetRegisterAllowed(0x888);
+SetRegisterAllowed(0x88C);
+SetRegisterAllowed(0x890);
+SetRegisterAllowed(0x894);
+SetRegisterAllowed(0x898);
+SetRegisterAllowed(0x89C);
+SetRegisterAllowed(0x8A0);
+SetRegisterAllowed(0x8A4);
+SetRegisterAllowed(0x8A8);
+SetRegisterAllowed(0x8AC);
+SetRegisterAllowed(0x8B0);
+SetRegisterAllowed(0x8B4);
+SetRegisterAllowed(0x8B8);
+SetRegisterAllowed(0x8BC);
+SetRegisterAllowed(0x8C0);
+SetRegisterAllowed(0x8C4);
+SetRegisterAllowed(0x8C8);
+SetRegisterAllowed(0x8CC);
+SetRegisterAllowed(0x8D0);
+SetRegisterAllowed(0x8D4);
+SetRegisterAllowed(0x8D8);
+SetRegisterAllowed(0x8DC);
+SetRegisterAllowed(0x8E0);
+SetRegisterAllowed(0x8E4);
+SetRegisterAllowed(0x8E8);
+SetRegisterAllowed(0x8EC);
+SetRegisterAllowed(0x8F0);
+SetRegisterAllowed(0x8F4);
+SetRegisterAllowed(0x8F8);
+SetRegisterAllowed(0x8FC);
+SetRegisterAllowed(0x900);
+SetRegisterAllowed(0x904);
+SetRegisterAllowed(0x908);
+SetRegisterAllowed(0x90C);
+SetRegisterAllowed(0x910);
+SetRegisterAllowed(0x914);
+SetRegisterAllowed(0x918);
+SetRegisterAllowed(0x91C);
+SetRegisterAllowed(0x920);
+SetRegisterAllowed(0x924);
+SetRegisterAllowed(0x928);
+SetRegisterAllowed(0x92C);
+SetRegisterAllowed(0x930);
+SetRegisterAllowed(0x934);
+SetRegisterAllowed(0x938);
+SetRegisterAllowed(0x93C);
+SetRegisterAllowed(0x940);
+SetRegisterAllowed(0x944);
+SetRegisterAllowed(0x948);
+SetRegisterAllowed(0x94C);
+SetRegisterAllowed(0x950);
+SetRegisterAllowed(0x954);
+SetRegisterAllowed(0x958);
+SetRegisterAllowed(0x95C);
+SetRegisterAllowed(0x960);
+SetRegisterAllowed(0x964);
+SetRegisterAllowed(0x968);
+SetRegisterAllowed(0x96C);
+SetRegisterAllowed(0x970);
+SetRegisterAllowed(0x974);
+SetRegisterAllowed(0x978);
+SetRegisterAllowed(0x97C);
+SetRegisterAllowed(0x980);
+SetRegisterAllowed(0x984);
+SetRegisterAllowed(0x988);
+SetRegisterAllowed(0x98C);
+SetRegisterAllowed(0x990);
+SetRegisterAllowed(0x994);
+SetRegisterAllowed(0x998);
+SetRegisterAllowed(0x99C);
+SetRegisterAllowed(0x9A0);
+SetRegisterAllowed(0x9A4);
+SetRegisterAllowed(0x9A8);
+SetRegisterAllowed(0x9AC);
+SetRegisterAllowed(0x9B0);
+SetRegisterAllowed(0x9B4);
+SetRegisterAllowed(0x9B8);
+SetRegisterAllowed(0x9BC);
+SetRegisterAllowed(0x9C0);
+SetRegisterAllowed(0x9C4);
+SetRegisterAllowed(0x9C8);
+SetRegisterAllowed(0x9CC);
+SetRegisterAllowed(0x9D0);
+SetRegisterAllowed(0x9D4);
+SetRegisterAllowed(0x9D8);
+SetRegisterAllowed(0x9DC);
+SetRegisterAllowed(0x9E0);
+SetRegisterAllowed(0x9E4);
+SetRegisterAllowed(0x9E8);
+SetRegisterAllowed(0x9EC);
+SetRegisterAllowed(0x9F0);
+SetRegisterAllowed(0x9F4);
+SetRegisterAllowed(0x9F8);
+SetRegisterAllowed(0x9FC);
+SetRegisterAllowed(0xA00);
+SetRegisterAllowed(0xA04);
+SetRegisterAllowed(0xA08);
+SetRegisterAllowed(0xA0C);
+SetRegisterAllowed(0xA10);
+SetRegisterAllowed(0xA14);
+SetRegisterAllowed(0xA18);
+SetRegisterAllowed(0xA1C);
+SetRegisterAllowed(0xA20);
+SetRegisterAllowed(0xA24);
+SetRegisterAllowed(0xA28);
+SetRegisterAllowed(0xA2C);
+SetRegisterAllowed(0xA30);
+SetRegisterAllowed(0xA34);
+SetRegisterAllowed(0xA38);
+SetRegisterAllowed(0xA3C);
+SetRegisterAllowed(0xA40);
+SetRegisterAllowed(0xA44);
+SetRegisterAllowed(0xA48);
+SetRegisterAllowed(0xA4C);
+SetRegisterAllowed(0xA50);
+SetRegisterAllowed(0xA54);
+SetRegisterAllowed(0xA58);
+SetRegisterAllowed(0xA5C);
+SetRegisterAllowed(0xA60);
+SetRegisterAllowed(0xA64);
+SetRegisterAllowed(0xA68);
+SetRegisterAllowed(0xA6C);
+SetRegisterAllowed(0xA70);
+SetRegisterAllowed(0xA74);
+SetRegisterAllowed(0xA78);
+SetRegisterAllowed(0xA7C);
+SetRegisterAllowed(0xA80);
+SetRegisterAllowed(0xA84);
+SetRegisterAllowed(0xA88);
+SetRegisterAllowed(0xA8C);
+SetRegisterAllowed(0xA90);
+SetRegisterAllowed(0xA94);
+SetRegisterAllowed(0xA98);
+SetRegisterAllowed(0xA9C);
+SetRegisterAllowed(0xAA0);
+SetRegisterAllowed(0xAA4);
+SetRegisterAllowed(0xAA8);
+SetRegisterAllowed(0xAAC);
+SetRegisterAllowed(0xAB0);
+SetRegisterAllowed(0xAB4);
+SetRegisterAllowed(0xAB8);
+SetRegisterAllowed(0xABC);
+SetRegisterAllowed(0xAC0);
+SetRegisterAllowed(0xAC4);
+SetRegisterAllowed(0xAC8);
+SetRegisterAllowed(0xACC);
+SetRegisterAllowed(0xAD0);
+SetRegisterAllowed(0xAD4);
+SetRegisterAllowed(0xAD8);
+SetRegisterAllowed(0xADC);
+SetRegisterAllowed(0xAE0);
+SetRegisterAllowed(0xAE4);
+SetRegisterAllowed(0xAE8);
+SetRegisterAllowed(0xAEC);
+SetRegisterAllowed(0xAF0);
+SetRegisterAllowed(0xAF4);
+SetRegisterAllowed(0xAF8);
+SetRegisterAllowed(0xAFC);
+SetRegisterAllowed(0xB00);
+SetRegisterAllowed(0xB04);
+SetRegisterAllowed(0xB08);
+SetRegisterAllowed(0xB0C);
+SetRegisterAllowed(0xB10);
+SetRegisterAllowed(0xB14);
+SetRegisterAllowed(0xB18);
+SetRegisterAllowed(0xB1C);
+SetRegisterAllowed(0xB20);
+SetRegisterAllowed(0xB24);
+SetRegisterAllowed(0xB28);
+SetRegisterAllowed(0xB2C);
+SetRegisterAllowed(0xB30);
+SetRegisterAllowed(0xB34);
+SetRegisterAllowed(0xB38);
+SetRegisterAllowed(0xB3C);
+SetRegisterAllowed(0xB40);
+SetRegisterAllowed(0xB44);
+SetRegisterAllowed(0xB48);
+SetRegisterAllowed(0xB4C);
+SetRegisterAllowed(0xB50);
+SetRegisterAllowed(0xB54);
+SetRegisterAllowed(0xB58);
+SetRegisterAllowed(0xB5C);
+SetRegisterAllowed(0xB60);
+SetRegisterAllowed(0xB64);
+SetRegisterAllowed(0xB68);
+SetRegisterAllowed(0xB6C);
+SetRegisterAllowed(0xB70);
+SetRegisterAllowed(0xB74);
+SetRegisterAllowed(0xB78);
+SetRegisterAllowed(0xB7C);
+SetRegisterAllowed(0xB80);
+SetRegisterAllowed(0xB84);
+SetRegisterAllowed(0xB88);
+SetRegisterAllowed(0xB8C);
+SetRegisterAllowed(0xB90);
+SetRegisterAllowed(0xB94);
+SetRegisterAllowed(0xB98);
+SetRegisterAllowed(0xB9C);
+SetRegisterAllowed(0xBA0);
+SetRegisterAllowed(0xBA4);
+SetRegisterAllowed(0xBA8);
+SetRegisterAllowed(0xBAC);
+SetRegisterAllowed(0xBB0);
+SetRegisterAllowed(0xBB4);
+SetRegisterAllowed(0xBB8);
+SetRegisterAllowed(0xBBC);
+SetRegisterAllowed(0xBC0);
+SetRegisterAllowed(0xBC4);
+SetRegisterAllowed(0xBC8);
+SetRegisterAllowed(0xBCC);
+SetRegisterAllowed(0xBD0);
+SetRegisterAllowed(0xBD4);
+SetRegisterAllowed(0xBD8);
+SetRegisterAllowed(0xBDC);
+SetRegisterAllowed(0xBE0);
+SetRegisterAllowed(0xBE4);
+SetRegisterAllowed(0xBE8);
+SetRegisterAllowed(0xBEC);
+SetRegisterAllowed(0xBF0);
+SetRegisterAllowed(0xBF4);
+SetRegisterAllowed(0xBF8);
+SetRegisterAllowed(0xBFC);
+SetRegisterAllowed(0xC00);
+SetRegisterAllowed(0xC04);
+SetRegisterAllowed(0xC08);
+SetRegisterAllowed(0xC0C);
+SetRegisterAllowed(0xC10);
+SetRegisterAllowed(0xC14);
+SetRegisterAllowed(0xC18);
+SetRegisterAllowed(0xC1C);
+SetRegisterAllowed(0xC20);
+SetRegisterAllowed(0xC24);
+SetRegisterAllowed(0xC28);
+SetRegisterAllowed(0xC2C);
+SetRegisterAllowed(0xC30);
+SetRegisterAllowed(0xC34);
+SetRegisterAllowed(0xC38);
+SetRegisterAllowed(0xC3C);
+SetRegisterAllowed(0xC40);
+SetRegisterAllowed(0xC44);
+SetRegisterAllowed(0xC48);
+SetRegisterAllowed(0xC4C);
+SetRegisterAllowed(0xC50);
+SetRegisterAllowed(0xC54);
+SetRegisterAllowed(0xC58);
+SetRegisterAllowed(0xC5C);
+SetRegisterAllowed(0xC60);
+SetRegisterAllowed(0xC64);
+SetRegisterAllowed(0xC68);
+SetRegisterAllowed(0xC6C);
+SetRegisterAllowed(0xC70);
+SetRegisterAllowed(0xC74);
+SetRegisterAllowed(0xC78);
+SetRegisterAllowed(0xC7C);
+SetRegisterAllowed(0xC80);
+SetRegisterAllowed(0xC84);
+SetRegisterAllowed(0xC88);
+SetRegisterAllowed(0xC8C);
+SetRegisterAllowed(0xC90);
+SetRegisterAllowed(0xC94);
+SetRegisterAllowed(0xC98);
+SetRegisterAllowed(0xC9C);
+SetRegisterAllowed(0xCA0);
+SetRegisterAllowed(0xCA4);
+SetRegisterAllowed(0xCA8);
+SetRegisterAllowed(0xCAC);
+SetRegisterAllowed(0xCB0);
+SetRegisterAllowed(0xCB4);
+SetRegisterAllowed(0xCB8);
+SetRegisterAllowed(0xCBC);
+SetRegisterAllowed(0xCC0);
+SetRegisterAllowed(0xCC4);
+SetRegisterAllowed(0xCC8);
+SetRegisterAllowed(0xCCC);
+SetRegisterAllowed(0xCD0);
+SetRegisterAllowed(0xCD4);
+SetRegisterAllowed(0xCD8);
+SetRegisterAllowed(0xCDC);
+SetRegisterAllowed(0xCE0);
+SetRegisterAllowed(0xCE4);
+SetRegisterAllowed(0xCE8);
+SetRegisterAllowed(0xCEC);
+SetRegisterAllowed(0xCF0);
+SetRegisterAllowed(0xCF4);
+SetRegisterAllowed(0xCF8);
+SetRegisterAllowed(0xCFC);
+SetRegisterAllowed(0xD00);
+SetRegisterAllowed(0xD04);
+SetRegisterAllowed(0xD08);
+SetRegisterAllowed(0xD0C);
+SetRegisterAllowed(0xD10);
+SetRegisterAllowed(0xD14);
+SetRegisterAllowed(0xD18);
+SetRegisterAllowed(0xD1C);
+SetRegisterAllowed(0xD20);
+SetRegisterAllowed(0xD24);
+SetRegisterAllowed(0xD28);
+SetRegisterAllowed(0xD2C);
+SetRegisterAllowed(0xD30);
+SetRegisterAllowed(0xD34);
+SetRegisterAllowed(0xD38);
+SetRegisterAllowed(0xD3C);
+SetRegisterAllowed(0xD40);
+SetRegisterAllowed(0xD44);
+SetRegisterAllowed(0xD48);
+SetRegisterAllowed(0xD4C);
+SetRegisterAllowed(0xD50);
+SetRegisterAllowed(0xD54);
+SetRegisterAllowed(0xD58);
+SetRegisterAllowed(0xD5C);
+SetRegisterAllowed(0xD60);
+SetRegisterAllowed(0xD64);
+SetRegisterAllowed(0xD68);
+SetRegisterAllowed(0xD6C);
+SetRegisterAllowed(0xD70);
+SetRegisterAllowed(0xD74);
+SetRegisterAllowed(0xD78);
+SetRegisterAllowed(0xD7C);
+SetRegisterAllowed(0xD80);
+SetRegisterAllowed(0xD84);
+SetRegisterAllowed(0xD88);
+SetRegisterAllowed(0xD8C);
+SetRegisterAllowed(0xD90);
+SetRegisterAllowed(0xD94);
+SetRegisterAllowed(0xD98);
+SetRegisterAllowed(0xD9C);
+SetRegisterAllowed(0xDA0);
+SetRegisterAllowed(0xDA4);
+SetRegisterAllowed(0xDA8);
+SetRegisterAllowed(0xDAC);
+SetRegisterAllowed(0xDB0);
+SetRegisterAllowed(0xDB4);
+SetRegisterAllowed(0xDB8);
+SetRegisterAllowed(0xDBC);
+SetRegisterAllowed(0xDC0);
+SetRegisterAllowed(0xDC4);
+SetRegisterAllowed(0xDC8);
+SetRegisterAllowed(0xDCC);
+SetRegisterAllowed(0xDD0);
+SetRegisterAllowed(0xDD4);
+SetRegisterAllowed(0xDD8);
+SetRegisterAllowed(0xDDC);
+SetRegisterAllowed(0xDE0);
+SetRegisterAllowed(0xDE4);
+SetRegisterAllowed(0xDE8);
+SetRegisterAllowed(0xDEC);
+SetRegisterAllowed(0xDF0);
+SetRegisterAllowed(0xDF4);
+SetRegisterAllowed(0xDF8);
+SetRegisterAllowed(0xDFC);
+SetRegisterAllowed(0xE00);
+SetRegisterAllowed(0xE04);
+SetRegisterAllowed(0xE08);
+SetRegisterAllowed(0xE0C);
+SetRegisterAllowed(0xE10);
+SetRegisterAllowed(0xE14);
+SetRegisterAllowed(0xE18);
+SetRegisterAllowed(0xE1C);
+SetRegisterAllowed(0xE20);
+SetRegisterAllowed(0xE24);
+SetRegisterAllowed(0xE28);
+SetRegisterAllowed(0xE2C);
+SetRegisterAllowed(0xE30);
+SetRegisterAllowed(0xE34);
+SetRegisterAllowed(0xE38);
+SetRegisterAllowed(0xE3C);
+SetRegisterAllowed(0xE40);
+SetRegisterAllowed(0xE44);
+SetRegisterAllowed(0xE48);
+SetRegisterAllowed(0xE4C);
+SetRegisterAllowed(0xE50);
+SetRegisterAllowed(0xE54);
+SetRegisterAllowed(0xE58);
+SetRegisterAllowed(0xE5C);
+SetRegisterAllowed(0xE60);
+SetRegisterAllowed(0xE64);
+SetRegisterAllowed(0xE68);
+SetRegisterAllowed(0xE6C);
+SetRegisterAllowed(0xE70);
+SetRegisterAllowed(0xE74);
+SetRegisterAllowed(0xE78);
+SetRegisterAllowed(0xE7C);
+SetRegisterAllowed(0xE80);
+SetRegisterAllowed(0xE84);
+SetRegisterAllowed(0xE88);
+SetRegisterAllowed(0xE8C);
+SetRegisterAllowed(0xE90);
+SetRegisterAllowed(0xE94);
+SetRegisterAllowed(0xE98);
+SetRegisterAllowed(0xE9C);
+SetRegisterAllowed(0xEA0);
+SetRegisterAllowed(0xEA4);
+SetRegisterAllowed(0xEA8);
+SetRegisterAllowed(0xEAC);
+SetRegisterAllowed(0xEB0);
+SetRegisterAllowed(0xEB4);
+SetRegisterAllowed(0xEB8);
+SetRegisterAllowed(0xEBC);
+SetRegisterAllowed(0xEC0);
+SetRegisterAllowed(0xEC4);
+SetRegisterAllowed(0xEC8);
+SetRegisterAllowed(0xECC);
+SetRegisterAllowed(0xED0);
+SetRegisterAllowed(0xED4);
+SetRegisterAllowed(0xED8);
+SetRegisterAllowed(0xEDC);
+SetRegisterAllowed(0xEE0);
+SetRegisterAllowed(0xEE4);
+SetRegisterAllowed(0xEE8);
+SetRegisterAllowed(0xEEC);
+SetRegisterAllowed(0xEF0);
+SetRegisterAllowed(0xEF4);
+SetRegisterAllowed(0xEF8);
+SetRegisterAllowed(0xEFC);
+SetRegisterAllowed(0xF00);
+SetRegisterAllowed(0xF04);
+SetRegisterAllowed(0xF08);
+SetRegisterAllowed(0xF0C);
+SetRegisterAllowed(0xF10);
+SetRegisterAllowed(0xF14);
+SetRegisterAllowed(0xF18);
+SetRegisterAllowed(0xF1C);
+SetRegisterAllowed(0xF20);
+SetRegisterAllowed(0xF24);
+SetRegisterAllowed(0xF28);
+SetRegisterAllowed(0xF2C);
+SetRegisterAllowed(0xF30);
+SetRegisterAllowed(0xF34);
+SetRegisterAllowed(0xF38);
+SetRegisterAllowed(0xF3C);
+SetRegisterAllowed(0xF40);
+SetRegisterAllowed(0xF44);
+SetRegisterAllowed(0xF48);
+SetRegisterAllowed(0xF4C);
+SetRegisterAllowed(0xF50);
+SetRegisterAllowed(0xF54);
+SetRegisterAllowed(0xF58);
+SetRegisterAllowed(0xF5C);
+SetRegisterAllowed(0xF60);
+SetRegisterAllowed(0xF64);
+SetRegisterAllowed(0xF68);
+SetRegisterAllowed(0xF6C);
+SetRegisterAllowed(0xF70);
+SetRegisterAllowed(0xF74);
+SetRegisterAllowed(0xF78);
+SetRegisterAllowed(0xF7C);
+SetRegisterAllowed(0xF80);
+SetRegisterAllowed(0xF84);
+SetRegisterAllowed(0xF88);
+SetRegisterAllowed(0xF8C);
+SetRegisterAllowed(0xF90);
+SetRegisterAllowed(0xF94);
+SetRegisterAllowed(0xF98);
+SetRegisterAllowed(0xF9C);
+SetRegisterAllowed(0xFA0);
+SetRegisterAllowed(0xFA4);
+SetRegisterAllowed(0xFA8);
+SetRegisterAllowed(0xFAC);
+SetRegisterAllowed(0xFB0);
+SetRegisterAllowed(0xFB4);
+SetRegisterAllowed(0xFB8);
+SetRegisterAllowed(0xFBC);
+SetRegisterAllowed(0xFC0);
+SetRegisterAllowed(0xFC4);
+SetRegisterAllowed(0xFC8);
+SetRegisterAllowed(0xFCC);
+SetRegisterAllowed(0xFD0);
+SetRegisterAllowed(0xFD4);
+SetRegisterAllowed(0xFD8);
+SetRegisterAllowed(0xFDC);
+SetRegisterAllowed(0xFE0);
+SetRegisterAllowed(0xFE4);
+SetRegisterAllowed(0xFE8);
+SetRegisterAllowed(0xFEC);
+SetRegisterAllowed(0xFF0);
+SetRegisterAllowed(0xFF4);
+SetRegisterAllowed(0xFF8);
+SetRegisterAllowed(0xFFC);
diff --git a/Source/Atmosphere-Patches/secmon_exception_vectors_access_table_data.inc b/Source/Atmosphere-Patches/secmon_exception_vectors_access_table_data.inc
new file mode 100644
index 00000000..a3718c5e
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_exception_vectors_access_table_data.inc
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+SetRegisterAllowed(0x0);
+SetRegisterAllowed(0x4);
+SetRegisterAllowed(0x8);
+SetRegisterAllowed(0xC);
+SetRegisterAllowed(0x10);
+SetRegisterAllowed(0x14);
+SetRegisterAllowed(0x18);
+SetRegisterAllowed(0x1C);
+SetRegisterAllowed(0x20);
+SetRegisterAllowed(0x24);
+SetRegisterAllowed(0x28);
+SetRegisterAllowed(0x2C);
+SetRegisterAllowed(0x30);
+SetRegisterAllowed(0x34);
+SetRegisterAllowed(0x38);
+SetRegisterAllowed(0x3C);
+SetRegisterAllowed(0x40);
+SetRegisterAllowed(0x44);
+SetRegisterAllowed(0x48);
+SetRegisterAllowed(0x4C);
+SetRegisterAllowed(0x50);
+SetRegisterAllowed(0x54);
+SetRegisterAllowed(0x58);
+SetRegisterAllowed(0x5C);
+SetRegisterAllowed(0x60);
+SetRegisterAllowed(0x64);
+SetRegisterAllowed(0x68);
+SetRegisterAllowed(0x6C);
+SetRegisterAllowed(0x70);
+SetRegisterAllowed(0x74);
+SetRegisterAllowed(0x78);
+SetRegisterAllowed(0x7C);
+SetRegisterAllowed(0x80);
+SetRegisterAllowed(0x84);
+SetRegisterAllowed(0x88);
+SetRegisterAllowed(0x8C);
+SetRegisterAllowed(0x90);
+SetRegisterAllowed(0x94);
+SetRegisterAllowed(0x98);
+SetRegisterAllowed(0x9C);
+SetRegisterAllowed(0xA0);
+SetRegisterAllowed(0xA4);
+SetRegisterAllowed(0xA8);
+SetRegisterAllowed(0xAC);
+SetRegisterAllowed(0xB0);
+SetRegisterAllowed(0xB4);
+SetRegisterAllowed(0xB8);
+SetRegisterAllowed(0xBC);
+SetRegisterAllowed(0xC0);
+SetRegisterAllowed(0xC4);
+SetRegisterAllowed(0xC8);
+SetRegisterAllowed(0xCC);
+SetRegisterAllowed(0xD0);
+SetRegisterAllowed(0xD4);
+SetRegisterAllowed(0xD8);
+SetRegisterAllowed(0xDC);
+SetRegisterAllowed(0xE0);
+SetRegisterAllowed(0xE4);
+SetRegisterAllowed(0xE8);
+SetRegisterAllowed(0xEC);
+SetRegisterAllowed(0xF0);
+SetRegisterAllowed(0xF4);
+SetRegisterAllowed(0xF8);
+SetRegisterAllowed(0xFC);
+SetRegisterAllowed(0x100);
+SetRegisterAllowed(0x104);
+SetRegisterAllowed(0x108);
+SetRegisterAllowed(0x10C);
+SetRegisterAllowed(0x110);
+SetRegisterAllowed(0x114);
+SetRegisterAllowed(0x118);
+SetRegisterAllowed(0x11C);
+SetRegisterAllowed(0x120);
+SetRegisterAllowed(0x124);
+SetRegisterAllowed(0x128);
+SetRegisterAllowed(0x12C);
+SetRegisterAllowed(0x130);
+SetRegisterAllowed(0x134);
+SetRegisterAllowed(0x138);
+SetRegisterAllowed(0x13C);
+SetRegisterAllowed(0x140);
+SetRegisterAllowed(0x144);
+SetRegisterAllowed(0x148);
+SetRegisterAllowed(0x14C);
+SetRegisterAllowed(0x150);
+SetRegisterAllowed(0x154);
+SetRegisterAllowed(0x158);
+SetRegisterAllowed(0x15C);
+SetRegisterAllowed(0x160);
+SetRegisterAllowed(0x164);
+SetRegisterAllowed(0x168);
+SetRegisterAllowed(0x16C);
+SetRegisterAllowed(0x170);
+SetRegisterAllowed(0x174);
+SetRegisterAllowed(0x178);
+SetRegisterAllowed(0x17C);
+SetRegisterAllowed(0x180);
+SetRegisterAllowed(0x184);
+SetRegisterAllowed(0x188);
+SetRegisterAllowed(0x18C);
+SetRegisterAllowed(0x190);
+SetRegisterAllowed(0x194);
+SetRegisterAllowed(0x198);
+SetRegisterAllowed(0x19C);
+SetRegisterAllowed(0x1A0);
+SetRegisterAllowed(0x1A4);
+SetRegisterAllowed(0x1A8);
+SetRegisterAllowed(0x1AC);
+SetRegisterAllowed(0x1B0);
+SetRegisterAllowed(0x1B4);
+SetRegisterAllowed(0x1B8);
+SetRegisterAllowed(0x1BC);
+SetRegisterAllowed(0x1C0);
+SetRegisterAllowed(0x1C4);
+SetRegisterAllowed(0x1C8);
+SetRegisterAllowed(0x1CC);
+SetRegisterAllowed(0x1D0);
+SetRegisterAllowed(0x1D4);
+SetRegisterAllowed(0x1D8);
+SetRegisterAllowed(0x1DC);
+SetRegisterAllowed(0x1E0);
+SetRegisterAllowed(0x1E4);
+SetRegisterAllowed(0x1E8);
+SetRegisterAllowed(0x1EC);
+SetRegisterAllowed(0x1F0);
+SetRegisterAllowed(0x1F4);
+SetRegisterAllowed(0x1F8);
+SetRegisterAllowed(0x1FC);
+SetRegisterAllowed(0x200);
+SetRegisterAllowed(0x204);
+SetRegisterAllowed(0x208);
+SetRegisterAllowed(0x20C);
+SetRegisterAllowed(0x210);
+SetRegisterAllowed(0x214);
+SetRegisterAllowed(0x218);
+SetRegisterAllowed(0x21C);
+SetRegisterAllowed(0x220);
+SetRegisterAllowed(0x224);
+SetRegisterAllowed(0x228);
+SetRegisterAllowed(0x22C);
+SetRegisterAllowed(0x230);
+SetRegisterAllowed(0x234);
+SetRegisterAllowed(0x238);
+SetRegisterAllowed(0x23C);
+SetRegisterAllowed(0x240);
+SetRegisterAllowed(0x244);
+SetRegisterAllowed(0x248);
+SetRegisterAllowed(0x24C);
+SetRegisterAllowed(0x250);
+SetRegisterAllowed(0x254);
+SetRegisterAllowed(0x258);
+SetRegisterAllowed(0x25C);
+SetRegisterAllowed(0x260);
+SetRegisterAllowed(0x264);
+SetRegisterAllowed(0x268);
+SetRegisterAllowed(0x26C);
+SetRegisterAllowed(0x270);
+SetRegisterAllowed(0x274);
+SetRegisterAllowed(0x278);
+SetRegisterAllowed(0x27C);
+SetRegisterAllowed(0x280);
+SetRegisterAllowed(0x284);
+SetRegisterAllowed(0x288);
+SetRegisterAllowed(0x28C);
+SetRegisterAllowed(0x290);
+SetRegisterAllowed(0x294);
+SetRegisterAllowed(0x298);
+SetRegisterAllowed(0x29C);
+SetRegisterAllowed(0x2A0);
+SetRegisterAllowed(0x2A4);
+SetRegisterAllowed(0x2A8);
+SetRegisterAllowed(0x2AC);
+SetRegisterAllowed(0x2B0);
+SetRegisterAllowed(0x2B4);
+SetRegisterAllowed(0x2B8);
+SetRegisterAllowed(0x2BC);
+SetRegisterAllowed(0x2C0);
+SetRegisterAllowed(0x2C4);
+SetRegisterAllowed(0x2C8);
+SetRegisterAllowed(0x2CC);
+SetRegisterAllowed(0x2D0);
+SetRegisterAllowed(0x2D4);
+SetRegisterAllowed(0x2D8);
+SetRegisterAllowed(0x2DC);
+SetRegisterAllowed(0x2E0);
+SetRegisterAllowed(0x2E4);
+SetRegisterAllowed(0x2E8);
+SetRegisterAllowed(0x2EC);
+SetRegisterAllowed(0x2F0);
+SetRegisterAllowed(0x2F4);
+SetRegisterAllowed(0x2F8);
+SetRegisterAllowed(0x2FC);
+SetRegisterAllowed(0x300);
+SetRegisterAllowed(0x304);
+SetRegisterAllowed(0x308);
+SetRegisterAllowed(0x30C);
+SetRegisterAllowed(0x310);
+SetRegisterAllowed(0x314);
+SetRegisterAllowed(0x318);
+SetRegisterAllowed(0x31C);
+SetRegisterAllowed(0x320);
+SetRegisterAllowed(0x324);
+SetRegisterAllowed(0x328);
+SetRegisterAllowed(0x32C);
+SetRegisterAllowed(0x330);
+SetRegisterAllowed(0x334);
+SetRegisterAllowed(0x338);
+SetRegisterAllowed(0x33C);
+SetRegisterAllowed(0x340);
+SetRegisterAllowed(0x344);
+SetRegisterAllowed(0x348);
+SetRegisterAllowed(0x34C);
+SetRegisterAllowed(0x350);
+SetRegisterAllowed(0x354);
+SetRegisterAllowed(0x358);
+SetRegisterAllowed(0x35C);
+SetRegisterAllowed(0x360);
+SetRegisterAllowed(0x364);
+SetRegisterAllowed(0x368);
+SetRegisterAllowed(0x36C);
+SetRegisterAllowed(0x370);
+SetRegisterAllowed(0x374);
+SetRegisterAllowed(0x378);
+SetRegisterAllowed(0x37C);
+SetRegisterAllowed(0x380);
+SetRegisterAllowed(0x384);
+SetRegisterAllowed(0x388);
+SetRegisterAllowed(0x38C);
+SetRegisterAllowed(0x390);
+SetRegisterAllowed(0x394);
+SetRegisterAllowed(0x398);
+SetRegisterAllowed(0x39C);
+SetRegisterAllowed(0x3A0);
+SetRegisterAllowed(0x3A4);
+SetRegisterAllowed(0x3A8);
+SetRegisterAllowed(0x3AC);
+SetRegisterAllowed(0x3B0);
+SetRegisterAllowed(0x3B4);
+SetRegisterAllowed(0x3B8);
+SetRegisterAllowed(0x3BC);
+SetRegisterAllowed(0x3C0);
+SetRegisterAllowed(0x3C4);
+SetRegisterAllowed(0x3C8);
+SetRegisterAllowed(0x3CC);
+SetRegisterAllowed(0x3D0);
+SetRegisterAllowed(0x3D4);
+SetRegisterAllowed(0x3D8);
+SetRegisterAllowed(0x3DC);
+SetRegisterAllowed(0x3E0);
+SetRegisterAllowed(0x3E4);
+SetRegisterAllowed(0x3E8);
+SetRegisterAllowed(0x3EC);
+SetRegisterAllowed(0x3F0);
+SetRegisterAllowed(0x3F4);
+SetRegisterAllowed(0x3F8);
+SetRegisterAllowed(0x3FC);
+SetRegisterAllowed(0x400);
+SetRegisterAllowed(0x404);
+SetRegisterAllowed(0x408);
+SetRegisterAllowed(0x40C);
+SetRegisterAllowed(0x410);
+SetRegisterAllowed(0x414);
+SetRegisterAllowed(0x418);
+SetRegisterAllowed(0x41C);
+SetRegisterAllowed(0x420);
+SetRegisterAllowed(0x424);
+SetRegisterAllowed(0x428);
+SetRegisterAllowed(0x42C);
+SetRegisterAllowed(0x430);
+SetRegisterAllowed(0x434);
+SetRegisterAllowed(0x438);
+SetRegisterAllowed(0x43C);
+SetRegisterAllowed(0x440);
+SetRegisterAllowed(0x444);
+SetRegisterAllowed(0x448);
+SetRegisterAllowed(0x44C);
+SetRegisterAllowed(0x450);
+SetRegisterAllowed(0x454);
+SetRegisterAllowed(0x458);
+SetRegisterAllowed(0x45C);
+SetRegisterAllowed(0x460);
+SetRegisterAllowed(0x464);
+SetRegisterAllowed(0x468);
+SetRegisterAllowed(0x46C);
+SetRegisterAllowed(0x470);
+SetRegisterAllowed(0x474);
+SetRegisterAllowed(0x478);
+SetRegisterAllowed(0x47C);
+SetRegisterAllowed(0x480);
+SetRegisterAllowed(0x484);
+SetRegisterAllowed(0x488);
+SetRegisterAllowed(0x48C);
+SetRegisterAllowed(0x490);
+SetRegisterAllowed(0x494);
+SetRegisterAllowed(0x498);
+SetRegisterAllowed(0x49C);
+SetRegisterAllowed(0x4A0);
+SetRegisterAllowed(0x4A4);
+SetRegisterAllowed(0x4A8);
+SetRegisterAllowed(0x4AC);
+SetRegisterAllowed(0x4B0);
+SetRegisterAllowed(0x4B4);
+SetRegisterAllowed(0x4B8);
+SetRegisterAllowed(0x4BC);
+SetRegisterAllowed(0x4C0);
+SetRegisterAllowed(0x4C4);
+SetRegisterAllowed(0x4C8);
+SetRegisterAllowed(0x4CC);
+SetRegisterAllowed(0x4D0);
+SetRegisterAllowed(0x4D4);
+SetRegisterAllowed(0x4D8);
+SetRegisterAllowed(0x4DC);
+SetRegisterAllowed(0x4E0);
+SetRegisterAllowed(0x4E4);
+SetRegisterAllowed(0x4E8);
+SetRegisterAllowed(0x4EC);
+SetRegisterAllowed(0x4F0);
+SetRegisterAllowed(0x4F4);
+SetRegisterAllowed(0x4F8);
+SetRegisterAllowed(0x4FC);
+SetRegisterAllowed(0x500);
+SetRegisterAllowed(0x504);
+SetRegisterAllowed(0x508);
+SetRegisterAllowed(0x50C);
+SetRegisterAllowed(0x510);
+SetRegisterAllowed(0x514);
+SetRegisterAllowed(0x518);
+SetRegisterAllowed(0x51C);
+SetRegisterAllowed(0x520);
+SetRegisterAllowed(0x524);
+SetRegisterAllowed(0x528);
+SetRegisterAllowed(0x52C);
+SetRegisterAllowed(0x530);
+SetRegisterAllowed(0x534);
+SetRegisterAllowed(0x538);
+SetRegisterAllowed(0x53C);
+SetRegisterAllowed(0x540);
+SetRegisterAllowed(0x544);
+SetRegisterAllowed(0x548);
+SetRegisterAllowed(0x54C);
+SetRegisterAllowed(0x550);
+SetRegisterAllowed(0x554);
+SetRegisterAllowed(0x558);
+SetRegisterAllowed(0x55C);
+SetRegisterAllowed(0x560);
+SetRegisterAllowed(0x564);
+SetRegisterAllowed(0x568);
+SetRegisterAllowed(0x56C);
+SetRegisterAllowed(0x570);
+SetRegisterAllowed(0x574);
+SetRegisterAllowed(0x578);
+SetRegisterAllowed(0x57C);
+SetRegisterAllowed(0x580);
+SetRegisterAllowed(0x584);
+SetRegisterAllowed(0x588);
+SetRegisterAllowed(0x58C);
+SetRegisterAllowed(0x590);
+SetRegisterAllowed(0x594);
+SetRegisterAllowed(0x598);
+SetRegisterAllowed(0x59C);
+SetRegisterAllowed(0x5A0);
+SetRegisterAllowed(0x5A4);
+SetRegisterAllowed(0x5A8);
+SetRegisterAllowed(0x5AC);
+SetRegisterAllowed(0x5B0);
+SetRegisterAllowed(0x5B4);
+SetRegisterAllowed(0x5B8);
+SetRegisterAllowed(0x5BC);
+SetRegisterAllowed(0x5C0);
+SetRegisterAllowed(0x5C4);
+SetRegisterAllowed(0x5C8);
+SetRegisterAllowed(0x5CC);
+SetRegisterAllowed(0x5D0);
+SetRegisterAllowed(0x5D4);
+SetRegisterAllowed(0x5D8);
+SetRegisterAllowed(0x5DC);
+SetRegisterAllowed(0x5E0);
+SetRegisterAllowed(0x5E4);
+SetRegisterAllowed(0x5E8);
+SetRegisterAllowed(0x5EC);
+SetRegisterAllowed(0x5F0);
+SetRegisterAllowed(0x5F4);
+SetRegisterAllowed(0x5F8);
+SetRegisterAllowed(0x5FC);
+SetRegisterAllowed(0x600);
+SetRegisterAllowed(0x604);
+SetRegisterAllowed(0x608);
+SetRegisterAllowed(0x60C);
+SetRegisterAllowed(0x610);
+SetRegisterAllowed(0x614);
+SetRegisterAllowed(0x618);
+SetRegisterAllowed(0x61C);
+SetRegisterAllowed(0x620);
+SetRegisterAllowed(0x624);
+SetRegisterAllowed(0x628);
+SetRegisterAllowed(0x62C);
+SetRegisterAllowed(0x630);
+SetRegisterAllowed(0x634);
+SetRegisterAllowed(0x638);
+SetRegisterAllowed(0x63C);
+SetRegisterAllowed(0x640);
+SetRegisterAllowed(0x644);
+SetRegisterAllowed(0x648);
+SetRegisterAllowed(0x64C);
+SetRegisterAllowed(0x650);
+SetRegisterAllowed(0x654);
+SetRegisterAllowed(0x658);
+SetRegisterAllowed(0x65C);
+SetRegisterAllowed(0x660);
+SetRegisterAllowed(0x664);
+SetRegisterAllowed(0x668);
+SetRegisterAllowed(0x66C);
+SetRegisterAllowed(0x670);
+SetRegisterAllowed(0x674);
+SetRegisterAllowed(0x678);
+SetRegisterAllowed(0x67C);
+SetRegisterAllowed(0x680);
+SetRegisterAllowed(0x684);
+SetRegisterAllowed(0x688);
+SetRegisterAllowed(0x68C);
+SetRegisterAllowed(0x690);
+SetRegisterAllowed(0x694);
+SetRegisterAllowed(0x698);
+SetRegisterAllowed(0x69C);
+SetRegisterAllowed(0x6A0);
+SetRegisterAllowed(0x6A4);
+SetRegisterAllowed(0x6A8);
+SetRegisterAllowed(0x6AC);
+SetRegisterAllowed(0x6B0);
+SetRegisterAllowed(0x6B4);
+SetRegisterAllowed(0x6B8);
+SetRegisterAllowed(0x6BC);
+SetRegisterAllowed(0x6C0);
+SetRegisterAllowed(0x6C4);
+SetRegisterAllowed(0x6C8);
+SetRegisterAllowed(0x6CC);
+SetRegisterAllowed(0x6D0);
+SetRegisterAllowed(0x6D4);
+SetRegisterAllowed(0x6D8);
+SetRegisterAllowed(0x6DC);
+SetRegisterAllowed(0x6E0);
+SetRegisterAllowed(0x6E4);
+SetRegisterAllowed(0x6E8);
+SetRegisterAllowed(0x6EC);
+SetRegisterAllowed(0x6F0);
+SetRegisterAllowed(0x6F4);
+SetRegisterAllowed(0x6F8);
+SetRegisterAllowed(0x6FC);
+SetRegisterAllowed(0x700);
+SetRegisterAllowed(0x704);
+SetRegisterAllowed(0x708);
+SetRegisterAllowed(0x70C);
+SetRegisterAllowed(0x710);
+SetRegisterAllowed(0x714);
+SetRegisterAllowed(0x718);
+SetRegisterAllowed(0x71C);
+SetRegisterAllowed(0x720);
+SetRegisterAllowed(0x724);
+SetRegisterAllowed(0x728);
+SetRegisterAllowed(0x72C);
+SetRegisterAllowed(0x730);
+SetRegisterAllowed(0x734);
+SetRegisterAllowed(0x738);
+SetRegisterAllowed(0x73C);
+SetRegisterAllowed(0x740);
+SetRegisterAllowed(0x744);
+SetRegisterAllowed(0x748);
+SetRegisterAllowed(0x74C);
+SetRegisterAllowed(0x750);
+SetRegisterAllowed(0x754);
+SetRegisterAllowed(0x758);
+SetRegisterAllowed(0x75C);
+SetRegisterAllowed(0x760);
+SetRegisterAllowed(0x764);
+SetRegisterAllowed(0x768);
+SetRegisterAllowed(0x76C);
+SetRegisterAllowed(0x770);
+SetRegisterAllowed(0x774);
+SetRegisterAllowed(0x778);
+SetRegisterAllowed(0x77C);
+SetRegisterAllowed(0x780);
+SetRegisterAllowed(0x784);
+SetRegisterAllowed(0x788);
+SetRegisterAllowed(0x78C);
+SetRegisterAllowed(0x790);
+SetRegisterAllowed(0x794);
+SetRegisterAllowed(0x798);
+SetRegisterAllowed(0x79C);
+SetRegisterAllowed(0x7A0);
+SetRegisterAllowed(0x7A4);
+SetRegisterAllowed(0x7A8);
+SetRegisterAllowed(0x7AC);
+SetRegisterAllowed(0x7B0);
+SetRegisterAllowed(0x7B4);
+SetRegisterAllowed(0x7B8);
+SetRegisterAllowed(0x7BC);
+SetRegisterAllowed(0x7C0);
+SetRegisterAllowed(0x7C4);
+SetRegisterAllowed(0x7C8);
+SetRegisterAllowed(0x7CC);
+SetRegisterAllowed(0x7D0);
+SetRegisterAllowed(0x7D4);
+SetRegisterAllowed(0x7D8);
+SetRegisterAllowed(0x7DC);
+SetRegisterAllowed(0x7E0);
+SetRegisterAllowed(0x7E4);
+SetRegisterAllowed(0x7E8);
+SetRegisterAllowed(0x7EC);
+SetRegisterAllowed(0x7F0);
+SetRegisterAllowed(0x7F4);
+SetRegisterAllowed(0x7F8);
+SetRegisterAllowed(0x7FC);
+SetRegisterAllowed(0x800);
+SetRegisterAllowed(0x804);
+SetRegisterAllowed(0x808);
+SetRegisterAllowed(0x80C);
+SetRegisterAllowed(0x810);
+SetRegisterAllowed(0x814);
+SetRegisterAllowed(0x818);
+SetRegisterAllowed(0x81C);
+SetRegisterAllowed(0x820);
+SetRegisterAllowed(0x824);
+SetRegisterAllowed(0x828);
+SetRegisterAllowed(0x82C);
+SetRegisterAllowed(0x830);
+SetRegisterAllowed(0x834);
+SetRegisterAllowed(0x838);
+SetRegisterAllowed(0x83C);
+SetRegisterAllowed(0x840);
+SetRegisterAllowed(0x844);
+SetRegisterAllowed(0x848);
+SetRegisterAllowed(0x84C);
+SetRegisterAllowed(0x850);
+SetRegisterAllowed(0x854);
+SetRegisterAllowed(0x858);
+SetRegisterAllowed(0x85C);
+SetRegisterAllowed(0x860);
+SetRegisterAllowed(0x864);
+SetRegisterAllowed(0x868);
+SetRegisterAllowed(0x86C);
+SetRegisterAllowed(0x870);
+SetRegisterAllowed(0x874);
+SetRegisterAllowed(0x878);
+SetRegisterAllowed(0x87C);
+SetRegisterAllowed(0x880);
+SetRegisterAllowed(0x884);
+SetRegisterAllowed(0x888);
+SetRegisterAllowed(0x88C);
+SetRegisterAllowed(0x890);
+SetRegisterAllowed(0x894);
+SetRegisterAllowed(0x898);
+SetRegisterAllowed(0x89C);
+SetRegisterAllowed(0x8A0);
+SetRegisterAllowed(0x8A4);
+SetRegisterAllowed(0x8A8);
+SetRegisterAllowed(0x8AC);
+SetRegisterAllowed(0x8B0);
+SetRegisterAllowed(0x8B4);
+SetRegisterAllowed(0x8B8);
+SetRegisterAllowed(0x8BC);
+SetRegisterAllowed(0x8C0);
+SetRegisterAllowed(0x8C4);
+SetRegisterAllowed(0x8C8);
+SetRegisterAllowed(0x8CC);
+SetRegisterAllowed(0x8D0);
+SetRegisterAllowed(0x8D4);
+SetRegisterAllowed(0x8D8);
+SetRegisterAllowed(0x8DC);
+SetRegisterAllowed(0x8E0);
+SetRegisterAllowed(0x8E4);
+SetRegisterAllowed(0x8E8);
+SetRegisterAllowed(0x8EC);
+SetRegisterAllowed(0x8F0);
+SetRegisterAllowed(0x8F4);
+SetRegisterAllowed(0x8F8);
+SetRegisterAllowed(0x8FC);
+SetRegisterAllowed(0x900);
+SetRegisterAllowed(0x904);
+SetRegisterAllowed(0x908);
+SetRegisterAllowed(0x90C);
+SetRegisterAllowed(0x910);
+SetRegisterAllowed(0x914);
+SetRegisterAllowed(0x918);
+SetRegisterAllowed(0x91C);
+SetRegisterAllowed(0x920);
+SetRegisterAllowed(0x924);
+SetRegisterAllowed(0x928);
+SetRegisterAllowed(0x92C);
+SetRegisterAllowed(0x930);
+SetRegisterAllowed(0x934);
+SetRegisterAllowed(0x938);
+SetRegisterAllowed(0x93C);
+SetRegisterAllowed(0x940);
+SetRegisterAllowed(0x944);
+SetRegisterAllowed(0x948);
+SetRegisterAllowed(0x94C);
+SetRegisterAllowed(0x950);
+SetRegisterAllowed(0x954);
+SetRegisterAllowed(0x958);
+SetRegisterAllowed(0x95C);
+SetRegisterAllowed(0x960);
+SetRegisterAllowed(0x964);
+SetRegisterAllowed(0x968);
+SetRegisterAllowed(0x96C);
+SetRegisterAllowed(0x970);
+SetRegisterAllowed(0x974);
+SetRegisterAllowed(0x978);
+SetRegisterAllowed(0x97C);
+SetRegisterAllowed(0x980);
+SetRegisterAllowed(0x984);
+SetRegisterAllowed(0x988);
+SetRegisterAllowed(0x98C);
+SetRegisterAllowed(0x990);
+SetRegisterAllowed(0x994);
+SetRegisterAllowed(0x998);
+SetRegisterAllowed(0x99C);
+SetRegisterAllowed(0x9A0);
+SetRegisterAllowed(0x9A4);
+SetRegisterAllowed(0x9A8);
+SetRegisterAllowed(0x9AC);
+SetRegisterAllowed(0x9B0);
+SetRegisterAllowed(0x9B4);
+SetRegisterAllowed(0x9B8);
+SetRegisterAllowed(0x9BC);
+SetRegisterAllowed(0x9C0);
+SetRegisterAllowed(0x9C4);
+SetRegisterAllowed(0x9C8);
+SetRegisterAllowed(0x9CC);
+SetRegisterAllowed(0x9D0);
+SetRegisterAllowed(0x9D4);
+SetRegisterAllowed(0x9D8);
+SetRegisterAllowed(0x9DC);
+SetRegisterAllowed(0x9E0);
+SetRegisterAllowed(0x9E4);
+SetRegisterAllowed(0x9E8);
+SetRegisterAllowed(0x9EC);
+SetRegisterAllowed(0x9F0);
+SetRegisterAllowed(0x9F4);
+SetRegisterAllowed(0x9F8);
+SetRegisterAllowed(0x9FC);
+SetRegisterAllowed(0xA00);
+SetRegisterAllowed(0xA04);
+SetRegisterAllowed(0xA08);
+SetRegisterAllowed(0xA0C);
+SetRegisterAllowed(0xA10);
+SetRegisterAllowed(0xA14);
+SetRegisterAllowed(0xA18);
+SetRegisterAllowed(0xA1C);
+SetRegisterAllowed(0xA20);
+SetRegisterAllowed(0xA24);
+SetRegisterAllowed(0xA28);
+SetRegisterAllowed(0xA2C);
+SetRegisterAllowed(0xA30);
+SetRegisterAllowed(0xA34);
+SetRegisterAllowed(0xA38);
+SetRegisterAllowed(0xA3C);
+SetRegisterAllowed(0xA40);
+SetRegisterAllowed(0xA44);
+SetRegisterAllowed(0xA48);
+SetRegisterAllowed(0xA4C);
+SetRegisterAllowed(0xA50);
+SetRegisterAllowed(0xA54);
+SetRegisterAllowed(0xA58);
+SetRegisterAllowed(0xA5C);
+SetRegisterAllowed(0xA60);
+SetRegisterAllowed(0xA64);
+SetRegisterAllowed(0xA68);
+SetRegisterAllowed(0xA6C);
+SetRegisterAllowed(0xA70);
+SetRegisterAllowed(0xA74);
+SetRegisterAllowed(0xA78);
+SetRegisterAllowed(0xA7C);
+SetRegisterAllowed(0xA80);
+SetRegisterAllowed(0xA84);
+SetRegisterAllowed(0xA88);
+SetRegisterAllowed(0xA8C);
+SetRegisterAllowed(0xA90);
+SetRegisterAllowed(0xA94);
+SetRegisterAllowed(0xA98);
+SetRegisterAllowed(0xA9C);
+SetRegisterAllowed(0xAA0);
+SetRegisterAllowed(0xAA4);
+SetRegisterAllowed(0xAA8);
+SetRegisterAllowed(0xAAC);
+SetRegisterAllowed(0xAB0);
+SetRegisterAllowed(0xAB4);
+SetRegisterAllowed(0xAB8);
+SetRegisterAllowed(0xABC);
+SetRegisterAllowed(0xAC0);
+SetRegisterAllowed(0xAC4);
+SetRegisterAllowed(0xAC8);
+SetRegisterAllowed(0xACC);
+SetRegisterAllowed(0xAD0);
+SetRegisterAllowed(0xAD4);
+SetRegisterAllowed(0xAD8);
+SetRegisterAllowed(0xADC);
+SetRegisterAllowed(0xAE0);
+SetRegisterAllowed(0xAE4);
+SetRegisterAllowed(0xAE8);
+SetRegisterAllowed(0xAEC);
+SetRegisterAllowed(0xAF0);
+SetRegisterAllowed(0xAF4);
+SetRegisterAllowed(0xAF8);
+SetRegisterAllowed(0xAFC);
+SetRegisterAllowed(0xB00);
+SetRegisterAllowed(0xB04);
+SetRegisterAllowed(0xB08);
+SetRegisterAllowed(0xB0C);
+SetRegisterAllowed(0xB10);
+SetRegisterAllowed(0xB14);
+SetRegisterAllowed(0xB18);
+SetRegisterAllowed(0xB1C);
+SetRegisterAllowed(0xB20);
+SetRegisterAllowed(0xB24);
+SetRegisterAllowed(0xB28);
+SetRegisterAllowed(0xB2C);
+SetRegisterAllowed(0xB30);
+SetRegisterAllowed(0xB34);
+SetRegisterAllowed(0xB38);
+SetRegisterAllowed(0xB3C);
+SetRegisterAllowed(0xB40);
+SetRegisterAllowed(0xB44);
+SetRegisterAllowed(0xB48);
+SetRegisterAllowed(0xB4C);
+SetRegisterAllowed(0xB50);
+SetRegisterAllowed(0xB54);
+SetRegisterAllowed(0xB58);
+SetRegisterAllowed(0xB5C);
+SetRegisterAllowed(0xB60);
+SetRegisterAllowed(0xB64);
+SetRegisterAllowed(0xB68);
+SetRegisterAllowed(0xB6C);
+SetRegisterAllowed(0xB70);
+SetRegisterAllowed(0xB74);
+SetRegisterAllowed(0xB78);
+SetRegisterAllowed(0xB7C);
+SetRegisterAllowed(0xB80);
+SetRegisterAllowed(0xB84);
+SetRegisterAllowed(0xB88);
+SetRegisterAllowed(0xB8C);
+SetRegisterAllowed(0xB90);
+SetRegisterAllowed(0xB94);
+SetRegisterAllowed(0xB98);
+SetRegisterAllowed(0xB9C);
+SetRegisterAllowed(0xBA0);
+SetRegisterAllowed(0xBA4);
+SetRegisterAllowed(0xBA8);
+SetRegisterAllowed(0xBAC);
+SetRegisterAllowed(0xBB0);
+SetRegisterAllowed(0xBB4);
+SetRegisterAllowed(0xBB8);
+SetRegisterAllowed(0xBBC);
+SetRegisterAllowed(0xBC0);
+SetRegisterAllowed(0xBC4);
+SetRegisterAllowed(0xBC8);
+SetRegisterAllowed(0xBCC);
+SetRegisterAllowed(0xBD0);
+SetRegisterAllowed(0xBD4);
+SetRegisterAllowed(0xBD8);
+SetRegisterAllowed(0xBDC);
+SetRegisterAllowed(0xBE0);
+SetRegisterAllowed(0xBE4);
+SetRegisterAllowed(0xBE8);
+SetRegisterAllowed(0xBEC);
+SetRegisterAllowed(0xBF0);
+SetRegisterAllowed(0xBF4);
+SetRegisterAllowed(0xBF8);
+SetRegisterAllowed(0xBFC);
+SetRegisterAllowed(0xC00);
+SetRegisterAllowed(0xC04);
+SetRegisterAllowed(0xC08);
+SetRegisterAllowed(0xC0C);
+SetRegisterAllowed(0xC10);
+SetRegisterAllowed(0xC14);
+SetRegisterAllowed(0xC18);
+SetRegisterAllowed(0xC1C);
+SetRegisterAllowed(0xC20);
+SetRegisterAllowed(0xC24);
+SetRegisterAllowed(0xC28);
+SetRegisterAllowed(0xC2C);
+SetRegisterAllowed(0xC30);
+SetRegisterAllowed(0xC34);
+SetRegisterAllowed(0xC38);
+SetRegisterAllowed(0xC3C);
+SetRegisterAllowed(0xC40);
+SetRegisterAllowed(0xC44);
+SetRegisterAllowed(0xC48);
+SetRegisterAllowed(0xC4C);
+SetRegisterAllowed(0xC50);
+SetRegisterAllowed(0xC54);
+SetRegisterAllowed(0xC58);
+SetRegisterAllowed(0xC5C);
+SetRegisterAllowed(0xC60);
+SetRegisterAllowed(0xC64);
+SetRegisterAllowed(0xC68);
+SetRegisterAllowed(0xC6C);
+SetRegisterAllowed(0xC70);
+SetRegisterAllowed(0xC74);
+SetRegisterAllowed(0xC78);
+SetRegisterAllowed(0xC7C);
+SetRegisterAllowed(0xC80);
+SetRegisterAllowed(0xC84);
+SetRegisterAllowed(0xC88);
+SetRegisterAllowed(0xC8C);
+SetRegisterAllowed(0xC90);
+SetRegisterAllowed(0xC94);
+SetRegisterAllowed(0xC98);
+SetRegisterAllowed(0xC9C);
+SetRegisterAllowed(0xCA0);
+SetRegisterAllowed(0xCA4);
+SetRegisterAllowed(0xCA8);
+SetRegisterAllowed(0xCAC);
+SetRegisterAllowed(0xCB0);
+SetRegisterAllowed(0xCB4);
+SetRegisterAllowed(0xCB8);
+SetRegisterAllowed(0xCBC);
+SetRegisterAllowed(0xCC0);
+SetRegisterAllowed(0xCC4);
+SetRegisterAllowed(0xCC8);
+SetRegisterAllowed(0xCCC);
+SetRegisterAllowed(0xCD0);
+SetRegisterAllowed(0xCD4);
+SetRegisterAllowed(0xCD8);
+SetRegisterAllowed(0xCDC);
+SetRegisterAllowed(0xCE0);
+SetRegisterAllowed(0xCE4);
+SetRegisterAllowed(0xCE8);
+SetRegisterAllowed(0xCEC);
+SetRegisterAllowed(0xCF0);
+SetRegisterAllowed(0xCF4);
+SetRegisterAllowed(0xCF8);
+SetRegisterAllowed(0xCFC);
+SetRegisterAllowed(0xD00);
+SetRegisterAllowed(0xD04);
+SetRegisterAllowed(0xD08);
+SetRegisterAllowed(0xD0C);
+SetRegisterAllowed(0xD10);
+SetRegisterAllowed(0xD14);
+SetRegisterAllowed(0xD18);
+SetRegisterAllowed(0xD1C);
+SetRegisterAllowed(0xD20);
+SetRegisterAllowed(0xD24);
+SetRegisterAllowed(0xD28);
+SetRegisterAllowed(0xD2C);
+SetRegisterAllowed(0xD30);
+SetRegisterAllowed(0xD34);
+SetRegisterAllowed(0xD38);
+SetRegisterAllowed(0xD3C);
+SetRegisterAllowed(0xD40);
+SetRegisterAllowed(0xD44);
+SetRegisterAllowed(0xD48);
+SetRegisterAllowed(0xD4C);
+SetRegisterAllowed(0xD50);
+SetRegisterAllowed(0xD54);
+SetRegisterAllowed(0xD58);
+SetRegisterAllowed(0xD5C);
+SetRegisterAllowed(0xD60);
+SetRegisterAllowed(0xD64);
+SetRegisterAllowed(0xD68);
+SetRegisterAllowed(0xD6C);
+SetRegisterAllowed(0xD70);
+SetRegisterAllowed(0xD74);
+SetRegisterAllowed(0xD78);
+SetRegisterAllowed(0xD7C);
+SetRegisterAllowed(0xD80);
+SetRegisterAllowed(0xD84);
+SetRegisterAllowed(0xD88);
+SetRegisterAllowed(0xD8C);
+SetRegisterAllowed(0xD90);
+SetRegisterAllowed(0xD94);
+SetRegisterAllowed(0xD98);
+SetRegisterAllowed(0xD9C);
+SetRegisterAllowed(0xDA0);
+SetRegisterAllowed(0xDA4);
+SetRegisterAllowed(0xDA8);
+SetRegisterAllowed(0xDAC);
+SetRegisterAllowed(0xDB0);
+SetRegisterAllowed(0xDB4);
+SetRegisterAllowed(0xDB8);
+SetRegisterAllowed(0xDBC);
+SetRegisterAllowed(0xDC0);
+SetRegisterAllowed(0xDC4);
+SetRegisterAllowed(0xDC8);
+SetRegisterAllowed(0xDCC);
+SetRegisterAllowed(0xDD0);
+SetRegisterAllowed(0xDD4);
+SetRegisterAllowed(0xDD8);
+SetRegisterAllowed(0xDDC);
+SetRegisterAllowed(0xDE0);
+SetRegisterAllowed(0xDE4);
+SetRegisterAllowed(0xDE8);
+SetRegisterAllowed(0xDEC);
+SetRegisterAllowed(0xDF0);
+SetRegisterAllowed(0xDF4);
+SetRegisterAllowed(0xDF8);
+SetRegisterAllowed(0xDFC);
+SetRegisterAllowed(0xE00);
+SetRegisterAllowed(0xE04);
+SetRegisterAllowed(0xE08);
+SetRegisterAllowed(0xE0C);
+SetRegisterAllowed(0xE10);
+SetRegisterAllowed(0xE14);
+SetRegisterAllowed(0xE18);
+SetRegisterAllowed(0xE1C);
+SetRegisterAllowed(0xE20);
+SetRegisterAllowed(0xE24);
+SetRegisterAllowed(0xE28);
+SetRegisterAllowed(0xE2C);
+SetRegisterAllowed(0xE30);
+SetRegisterAllowed(0xE34);
+SetRegisterAllowed(0xE38);
+SetRegisterAllowed(0xE3C);
+SetRegisterAllowed(0xE40);
+SetRegisterAllowed(0xE44);
+SetRegisterAllowed(0xE48);
+SetRegisterAllowed(0xE4C);
+SetRegisterAllowed(0xE50);
+SetRegisterAllowed(0xE54);
+SetRegisterAllowed(0xE58);
+SetRegisterAllowed(0xE5C);
+SetRegisterAllowed(0xE60);
+SetRegisterAllowed(0xE64);
+SetRegisterAllowed(0xE68);
+SetRegisterAllowed(0xE6C);
+SetRegisterAllowed(0xE70);
+SetRegisterAllowed(0xE74);
+SetRegisterAllowed(0xE78);
+SetRegisterAllowed(0xE7C);
+SetRegisterAllowed(0xE80);
+SetRegisterAllowed(0xE84);
+SetRegisterAllowed(0xE88);
+SetRegisterAllowed(0xE8C);
+SetRegisterAllowed(0xE90);
+SetRegisterAllowed(0xE94);
+SetRegisterAllowed(0xE98);
+SetRegisterAllowed(0xE9C);
+SetRegisterAllowed(0xEA0);
+SetRegisterAllowed(0xEA4);
+SetRegisterAllowed(0xEA8);
+SetRegisterAllowed(0xEAC);
+SetRegisterAllowed(0xEB0);
+SetRegisterAllowed(0xEB4);
+SetRegisterAllowed(0xEB8);
+SetRegisterAllowed(0xEBC);
+SetRegisterAllowed(0xEC0);
+SetRegisterAllowed(0xEC4);
+SetRegisterAllowed(0xEC8);
+SetRegisterAllowed(0xECC);
+SetRegisterAllowed(0xED0);
+SetRegisterAllowed(0xED4);
+SetRegisterAllowed(0xED8);
+SetRegisterAllowed(0xEDC);
+SetRegisterAllowed(0xEE0);
+SetRegisterAllowed(0xEE4);
+SetRegisterAllowed(0xEE8);
+SetRegisterAllowed(0xEEC);
+SetRegisterAllowed(0xEF0);
+SetRegisterAllowed(0xEF4);
+SetRegisterAllowed(0xEF8);
+SetRegisterAllowed(0xEFC);
+SetRegisterAllowed(0xF00);
+SetRegisterAllowed(0xF04);
+SetRegisterAllowed(0xF08);
+SetRegisterAllowed(0xF0C);
+SetRegisterAllowed(0xF10);
+SetRegisterAllowed(0xF14);
+SetRegisterAllowed(0xF18);
+SetRegisterAllowed(0xF1C);
+SetRegisterAllowed(0xF20);
+SetRegisterAllowed(0xF24);
+SetRegisterAllowed(0xF28);
+SetRegisterAllowed(0xF2C);
+SetRegisterAllowed(0xF30);
+SetRegisterAllowed(0xF34);
+SetRegisterAllowed(0xF38);
+SetRegisterAllowed(0xF3C);
+SetRegisterAllowed(0xF40);
+SetRegisterAllowed(0xF44);
+SetRegisterAllowed(0xF48);
+SetRegisterAllowed(0xF4C);
+SetRegisterAllowed(0xF50);
+SetRegisterAllowed(0xF54);
+SetRegisterAllowed(0xF58);
+SetRegisterAllowed(0xF5C);
+SetRegisterAllowed(0xF60);
+SetRegisterAllowed(0xF64);
+SetRegisterAllowed(0xF68);
+SetRegisterAllowed(0xF6C);
+SetRegisterAllowed(0xF70);
+SetRegisterAllowed(0xF74);
+SetRegisterAllowed(0xF78);
+SetRegisterAllowed(0xF7C);
+SetRegisterAllowed(0xF80);
+SetRegisterAllowed(0xF84);
+SetRegisterAllowed(0xF88);
+SetRegisterAllowed(0xF8C);
+SetRegisterAllowed(0xF90);
+SetRegisterAllowed(0xF94);
+SetRegisterAllowed(0xF98);
+SetRegisterAllowed(0xF9C);
+SetRegisterAllowed(0xFA0);
+SetRegisterAllowed(0xFA4);
+SetRegisterAllowed(0xFA8);
+SetRegisterAllowed(0xFAC);
+SetRegisterAllowed(0xFB0);
+SetRegisterAllowed(0xFB4);
+SetRegisterAllowed(0xFB8);
+SetRegisterAllowed(0xFBC);
+SetRegisterAllowed(0xFC0);
+SetRegisterAllowed(0xFC4);
+SetRegisterAllowed(0xFC8);
+SetRegisterAllowed(0xFCC);
+SetRegisterAllowed(0xFD0);
+SetRegisterAllowed(0xFD4);
+SetRegisterAllowed(0xFD8);
+SetRegisterAllowed(0xFDC);
+SetRegisterAllowed(0xFE0);
+SetRegisterAllowed(0xFE4);
+SetRegisterAllowed(0xFE8);
+SetRegisterAllowed(0xFEC);
+SetRegisterAllowed(0xFF0);
+SetRegisterAllowed(0xFF4);
+SetRegisterAllowed(0xFF8);
+SetRegisterAllowed(0xFFC);
diff --git a/Source/Atmosphere-Patches/secmon_flow_controller_access_table_data.inc b/Source/Atmosphere-Patches/secmon_flow_controller_access_table_data.inc
new file mode 100644
index 00000000..a3718c5e
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_flow_controller_access_table_data.inc
@@ -0,0 +1,1040 @@
+/*
+ * Copyright (c) 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 .
+ */
+
+SetRegisterAllowed(0x0);
+SetRegisterAllowed(0x4);
+SetRegisterAllowed(0x8);
+SetRegisterAllowed(0xC);
+SetRegisterAllowed(0x10);
+SetRegisterAllowed(0x14);
+SetRegisterAllowed(0x18);
+SetRegisterAllowed(0x1C);
+SetRegisterAllowed(0x20);
+SetRegisterAllowed(0x24);
+SetRegisterAllowed(0x28);
+SetRegisterAllowed(0x2C);
+SetRegisterAllowed(0x30);
+SetRegisterAllowed(0x34);
+SetRegisterAllowed(0x38);
+SetRegisterAllowed(0x3C);
+SetRegisterAllowed(0x40);
+SetRegisterAllowed(0x44);
+SetRegisterAllowed(0x48);
+SetRegisterAllowed(0x4C);
+SetRegisterAllowed(0x50);
+SetRegisterAllowed(0x54);
+SetRegisterAllowed(0x58);
+SetRegisterAllowed(0x5C);
+SetRegisterAllowed(0x60);
+SetRegisterAllowed(0x64);
+SetRegisterAllowed(0x68);
+SetRegisterAllowed(0x6C);
+SetRegisterAllowed(0x70);
+SetRegisterAllowed(0x74);
+SetRegisterAllowed(0x78);
+SetRegisterAllowed(0x7C);
+SetRegisterAllowed(0x80);
+SetRegisterAllowed(0x84);
+SetRegisterAllowed(0x88);
+SetRegisterAllowed(0x8C);
+SetRegisterAllowed(0x90);
+SetRegisterAllowed(0x94);
+SetRegisterAllowed(0x98);
+SetRegisterAllowed(0x9C);
+SetRegisterAllowed(0xA0);
+SetRegisterAllowed(0xA4);
+SetRegisterAllowed(0xA8);
+SetRegisterAllowed(0xAC);
+SetRegisterAllowed(0xB0);
+SetRegisterAllowed(0xB4);
+SetRegisterAllowed(0xB8);
+SetRegisterAllowed(0xBC);
+SetRegisterAllowed(0xC0);
+SetRegisterAllowed(0xC4);
+SetRegisterAllowed(0xC8);
+SetRegisterAllowed(0xCC);
+SetRegisterAllowed(0xD0);
+SetRegisterAllowed(0xD4);
+SetRegisterAllowed(0xD8);
+SetRegisterAllowed(0xDC);
+SetRegisterAllowed(0xE0);
+SetRegisterAllowed(0xE4);
+SetRegisterAllowed(0xE8);
+SetRegisterAllowed(0xEC);
+SetRegisterAllowed(0xF0);
+SetRegisterAllowed(0xF4);
+SetRegisterAllowed(0xF8);
+SetRegisterAllowed(0xFC);
+SetRegisterAllowed(0x100);
+SetRegisterAllowed(0x104);
+SetRegisterAllowed(0x108);
+SetRegisterAllowed(0x10C);
+SetRegisterAllowed(0x110);
+SetRegisterAllowed(0x114);
+SetRegisterAllowed(0x118);
+SetRegisterAllowed(0x11C);
+SetRegisterAllowed(0x120);
+SetRegisterAllowed(0x124);
+SetRegisterAllowed(0x128);
+SetRegisterAllowed(0x12C);
+SetRegisterAllowed(0x130);
+SetRegisterAllowed(0x134);
+SetRegisterAllowed(0x138);
+SetRegisterAllowed(0x13C);
+SetRegisterAllowed(0x140);
+SetRegisterAllowed(0x144);
+SetRegisterAllowed(0x148);
+SetRegisterAllowed(0x14C);
+SetRegisterAllowed(0x150);
+SetRegisterAllowed(0x154);
+SetRegisterAllowed(0x158);
+SetRegisterAllowed(0x15C);
+SetRegisterAllowed(0x160);
+SetRegisterAllowed(0x164);
+SetRegisterAllowed(0x168);
+SetRegisterAllowed(0x16C);
+SetRegisterAllowed(0x170);
+SetRegisterAllowed(0x174);
+SetRegisterAllowed(0x178);
+SetRegisterAllowed(0x17C);
+SetRegisterAllowed(0x180);
+SetRegisterAllowed(0x184);
+SetRegisterAllowed(0x188);
+SetRegisterAllowed(0x18C);
+SetRegisterAllowed(0x190);
+SetRegisterAllowed(0x194);
+SetRegisterAllowed(0x198);
+SetRegisterAllowed(0x19C);
+SetRegisterAllowed(0x1A0);
+SetRegisterAllowed(0x1A4);
+SetRegisterAllowed(0x1A8);
+SetRegisterAllowed(0x1AC);
+SetRegisterAllowed(0x1B0);
+SetRegisterAllowed(0x1B4);
+SetRegisterAllowed(0x1B8);
+SetRegisterAllowed(0x1BC);
+SetRegisterAllowed(0x1C0);
+SetRegisterAllowed(0x1C4);
+SetRegisterAllowed(0x1C8);
+SetRegisterAllowed(0x1CC);
+SetRegisterAllowed(0x1D0);
+SetRegisterAllowed(0x1D4);
+SetRegisterAllowed(0x1D8);
+SetRegisterAllowed(0x1DC);
+SetRegisterAllowed(0x1E0);
+SetRegisterAllowed(0x1E4);
+SetRegisterAllowed(0x1E8);
+SetRegisterAllowed(0x1EC);
+SetRegisterAllowed(0x1F0);
+SetRegisterAllowed(0x1F4);
+SetRegisterAllowed(0x1F8);
+SetRegisterAllowed(0x1FC);
+SetRegisterAllowed(0x200);
+SetRegisterAllowed(0x204);
+SetRegisterAllowed(0x208);
+SetRegisterAllowed(0x20C);
+SetRegisterAllowed(0x210);
+SetRegisterAllowed(0x214);
+SetRegisterAllowed(0x218);
+SetRegisterAllowed(0x21C);
+SetRegisterAllowed(0x220);
+SetRegisterAllowed(0x224);
+SetRegisterAllowed(0x228);
+SetRegisterAllowed(0x22C);
+SetRegisterAllowed(0x230);
+SetRegisterAllowed(0x234);
+SetRegisterAllowed(0x238);
+SetRegisterAllowed(0x23C);
+SetRegisterAllowed(0x240);
+SetRegisterAllowed(0x244);
+SetRegisterAllowed(0x248);
+SetRegisterAllowed(0x24C);
+SetRegisterAllowed(0x250);
+SetRegisterAllowed(0x254);
+SetRegisterAllowed(0x258);
+SetRegisterAllowed(0x25C);
+SetRegisterAllowed(0x260);
+SetRegisterAllowed(0x264);
+SetRegisterAllowed(0x268);
+SetRegisterAllowed(0x26C);
+SetRegisterAllowed(0x270);
+SetRegisterAllowed(0x274);
+SetRegisterAllowed(0x278);
+SetRegisterAllowed(0x27C);
+SetRegisterAllowed(0x280);
+SetRegisterAllowed(0x284);
+SetRegisterAllowed(0x288);
+SetRegisterAllowed(0x28C);
+SetRegisterAllowed(0x290);
+SetRegisterAllowed(0x294);
+SetRegisterAllowed(0x298);
+SetRegisterAllowed(0x29C);
+SetRegisterAllowed(0x2A0);
+SetRegisterAllowed(0x2A4);
+SetRegisterAllowed(0x2A8);
+SetRegisterAllowed(0x2AC);
+SetRegisterAllowed(0x2B0);
+SetRegisterAllowed(0x2B4);
+SetRegisterAllowed(0x2B8);
+SetRegisterAllowed(0x2BC);
+SetRegisterAllowed(0x2C0);
+SetRegisterAllowed(0x2C4);
+SetRegisterAllowed(0x2C8);
+SetRegisterAllowed(0x2CC);
+SetRegisterAllowed(0x2D0);
+SetRegisterAllowed(0x2D4);
+SetRegisterAllowed(0x2D8);
+SetRegisterAllowed(0x2DC);
+SetRegisterAllowed(0x2E0);
+SetRegisterAllowed(0x2E4);
+SetRegisterAllowed(0x2E8);
+SetRegisterAllowed(0x2EC);
+SetRegisterAllowed(0x2F0);
+SetRegisterAllowed(0x2F4);
+SetRegisterAllowed(0x2F8);
+SetRegisterAllowed(0x2FC);
+SetRegisterAllowed(0x300);
+SetRegisterAllowed(0x304);
+SetRegisterAllowed(0x308);
+SetRegisterAllowed(0x30C);
+SetRegisterAllowed(0x310);
+SetRegisterAllowed(0x314);
+SetRegisterAllowed(0x318);
+SetRegisterAllowed(0x31C);
+SetRegisterAllowed(0x320);
+SetRegisterAllowed(0x324);
+SetRegisterAllowed(0x328);
+SetRegisterAllowed(0x32C);
+SetRegisterAllowed(0x330);
+SetRegisterAllowed(0x334);
+SetRegisterAllowed(0x338);
+SetRegisterAllowed(0x33C);
+SetRegisterAllowed(0x340);
+SetRegisterAllowed(0x344);
+SetRegisterAllowed(0x348);
+SetRegisterAllowed(0x34C);
+SetRegisterAllowed(0x350);
+SetRegisterAllowed(0x354);
+SetRegisterAllowed(0x358);
+SetRegisterAllowed(0x35C);
+SetRegisterAllowed(0x360);
+SetRegisterAllowed(0x364);
+SetRegisterAllowed(0x368);
+SetRegisterAllowed(0x36C);
+SetRegisterAllowed(0x370);
+SetRegisterAllowed(0x374);
+SetRegisterAllowed(0x378);
+SetRegisterAllowed(0x37C);
+SetRegisterAllowed(0x380);
+SetRegisterAllowed(0x384);
+SetRegisterAllowed(0x388);
+SetRegisterAllowed(0x38C);
+SetRegisterAllowed(0x390);
+SetRegisterAllowed(0x394);
+SetRegisterAllowed(0x398);
+SetRegisterAllowed(0x39C);
+SetRegisterAllowed(0x3A0);
+SetRegisterAllowed(0x3A4);
+SetRegisterAllowed(0x3A8);
+SetRegisterAllowed(0x3AC);
+SetRegisterAllowed(0x3B0);
+SetRegisterAllowed(0x3B4);
+SetRegisterAllowed(0x3B8);
+SetRegisterAllowed(0x3BC);
+SetRegisterAllowed(0x3C0);
+SetRegisterAllowed(0x3C4);
+SetRegisterAllowed(0x3C8);
+SetRegisterAllowed(0x3CC);
+SetRegisterAllowed(0x3D0);
+SetRegisterAllowed(0x3D4);
+SetRegisterAllowed(0x3D8);
+SetRegisterAllowed(0x3DC);
+SetRegisterAllowed(0x3E0);
+SetRegisterAllowed(0x3E4);
+SetRegisterAllowed(0x3E8);
+SetRegisterAllowed(0x3EC);
+SetRegisterAllowed(0x3F0);
+SetRegisterAllowed(0x3F4);
+SetRegisterAllowed(0x3F8);
+SetRegisterAllowed(0x3FC);
+SetRegisterAllowed(0x400);
+SetRegisterAllowed(0x404);
+SetRegisterAllowed(0x408);
+SetRegisterAllowed(0x40C);
+SetRegisterAllowed(0x410);
+SetRegisterAllowed(0x414);
+SetRegisterAllowed(0x418);
+SetRegisterAllowed(0x41C);
+SetRegisterAllowed(0x420);
+SetRegisterAllowed(0x424);
+SetRegisterAllowed(0x428);
+SetRegisterAllowed(0x42C);
+SetRegisterAllowed(0x430);
+SetRegisterAllowed(0x434);
+SetRegisterAllowed(0x438);
+SetRegisterAllowed(0x43C);
+SetRegisterAllowed(0x440);
+SetRegisterAllowed(0x444);
+SetRegisterAllowed(0x448);
+SetRegisterAllowed(0x44C);
+SetRegisterAllowed(0x450);
+SetRegisterAllowed(0x454);
+SetRegisterAllowed(0x458);
+SetRegisterAllowed(0x45C);
+SetRegisterAllowed(0x460);
+SetRegisterAllowed(0x464);
+SetRegisterAllowed(0x468);
+SetRegisterAllowed(0x46C);
+SetRegisterAllowed(0x470);
+SetRegisterAllowed(0x474);
+SetRegisterAllowed(0x478);
+SetRegisterAllowed(0x47C);
+SetRegisterAllowed(0x480);
+SetRegisterAllowed(0x484);
+SetRegisterAllowed(0x488);
+SetRegisterAllowed(0x48C);
+SetRegisterAllowed(0x490);
+SetRegisterAllowed(0x494);
+SetRegisterAllowed(0x498);
+SetRegisterAllowed(0x49C);
+SetRegisterAllowed(0x4A0);
+SetRegisterAllowed(0x4A4);
+SetRegisterAllowed(0x4A8);
+SetRegisterAllowed(0x4AC);
+SetRegisterAllowed(0x4B0);
+SetRegisterAllowed(0x4B4);
+SetRegisterAllowed(0x4B8);
+SetRegisterAllowed(0x4BC);
+SetRegisterAllowed(0x4C0);
+SetRegisterAllowed(0x4C4);
+SetRegisterAllowed(0x4C8);
+SetRegisterAllowed(0x4CC);
+SetRegisterAllowed(0x4D0);
+SetRegisterAllowed(0x4D4);
+SetRegisterAllowed(0x4D8);
+SetRegisterAllowed(0x4DC);
+SetRegisterAllowed(0x4E0);
+SetRegisterAllowed(0x4E4);
+SetRegisterAllowed(0x4E8);
+SetRegisterAllowed(0x4EC);
+SetRegisterAllowed(0x4F0);
+SetRegisterAllowed(0x4F4);
+SetRegisterAllowed(0x4F8);
+SetRegisterAllowed(0x4FC);
+SetRegisterAllowed(0x500);
+SetRegisterAllowed(0x504);
+SetRegisterAllowed(0x508);
+SetRegisterAllowed(0x50C);
+SetRegisterAllowed(0x510);
+SetRegisterAllowed(0x514);
+SetRegisterAllowed(0x518);
+SetRegisterAllowed(0x51C);
+SetRegisterAllowed(0x520);
+SetRegisterAllowed(0x524);
+SetRegisterAllowed(0x528);
+SetRegisterAllowed(0x52C);
+SetRegisterAllowed(0x530);
+SetRegisterAllowed(0x534);
+SetRegisterAllowed(0x538);
+SetRegisterAllowed(0x53C);
+SetRegisterAllowed(0x540);
+SetRegisterAllowed(0x544);
+SetRegisterAllowed(0x548);
+SetRegisterAllowed(0x54C);
+SetRegisterAllowed(0x550);
+SetRegisterAllowed(0x554);
+SetRegisterAllowed(0x558);
+SetRegisterAllowed(0x55C);
+SetRegisterAllowed(0x560);
+SetRegisterAllowed(0x564);
+SetRegisterAllowed(0x568);
+SetRegisterAllowed(0x56C);
+SetRegisterAllowed(0x570);
+SetRegisterAllowed(0x574);
+SetRegisterAllowed(0x578);
+SetRegisterAllowed(0x57C);
+SetRegisterAllowed(0x580);
+SetRegisterAllowed(0x584);
+SetRegisterAllowed(0x588);
+SetRegisterAllowed(0x58C);
+SetRegisterAllowed(0x590);
+SetRegisterAllowed(0x594);
+SetRegisterAllowed(0x598);
+SetRegisterAllowed(0x59C);
+SetRegisterAllowed(0x5A0);
+SetRegisterAllowed(0x5A4);
+SetRegisterAllowed(0x5A8);
+SetRegisterAllowed(0x5AC);
+SetRegisterAllowed(0x5B0);
+SetRegisterAllowed(0x5B4);
+SetRegisterAllowed(0x5B8);
+SetRegisterAllowed(0x5BC);
+SetRegisterAllowed(0x5C0);
+SetRegisterAllowed(0x5C4);
+SetRegisterAllowed(0x5C8);
+SetRegisterAllowed(0x5CC);
+SetRegisterAllowed(0x5D0);
+SetRegisterAllowed(0x5D4);
+SetRegisterAllowed(0x5D8);
+SetRegisterAllowed(0x5DC);
+SetRegisterAllowed(0x5E0);
+SetRegisterAllowed(0x5E4);
+SetRegisterAllowed(0x5E8);
+SetRegisterAllowed(0x5EC);
+SetRegisterAllowed(0x5F0);
+SetRegisterAllowed(0x5F4);
+SetRegisterAllowed(0x5F8);
+SetRegisterAllowed(0x5FC);
+SetRegisterAllowed(0x600);
+SetRegisterAllowed(0x604);
+SetRegisterAllowed(0x608);
+SetRegisterAllowed(0x60C);
+SetRegisterAllowed(0x610);
+SetRegisterAllowed(0x614);
+SetRegisterAllowed(0x618);
+SetRegisterAllowed(0x61C);
+SetRegisterAllowed(0x620);
+SetRegisterAllowed(0x624);
+SetRegisterAllowed(0x628);
+SetRegisterAllowed(0x62C);
+SetRegisterAllowed(0x630);
+SetRegisterAllowed(0x634);
+SetRegisterAllowed(0x638);
+SetRegisterAllowed(0x63C);
+SetRegisterAllowed(0x640);
+SetRegisterAllowed(0x644);
+SetRegisterAllowed(0x648);
+SetRegisterAllowed(0x64C);
+SetRegisterAllowed(0x650);
+SetRegisterAllowed(0x654);
+SetRegisterAllowed(0x658);
+SetRegisterAllowed(0x65C);
+SetRegisterAllowed(0x660);
+SetRegisterAllowed(0x664);
+SetRegisterAllowed(0x668);
+SetRegisterAllowed(0x66C);
+SetRegisterAllowed(0x670);
+SetRegisterAllowed(0x674);
+SetRegisterAllowed(0x678);
+SetRegisterAllowed(0x67C);
+SetRegisterAllowed(0x680);
+SetRegisterAllowed(0x684);
+SetRegisterAllowed(0x688);
+SetRegisterAllowed(0x68C);
+SetRegisterAllowed(0x690);
+SetRegisterAllowed(0x694);
+SetRegisterAllowed(0x698);
+SetRegisterAllowed(0x69C);
+SetRegisterAllowed(0x6A0);
+SetRegisterAllowed(0x6A4);
+SetRegisterAllowed(0x6A8);
+SetRegisterAllowed(0x6AC);
+SetRegisterAllowed(0x6B0);
+SetRegisterAllowed(0x6B4);
+SetRegisterAllowed(0x6B8);
+SetRegisterAllowed(0x6BC);
+SetRegisterAllowed(0x6C0);
+SetRegisterAllowed(0x6C4);
+SetRegisterAllowed(0x6C8);
+SetRegisterAllowed(0x6CC);
+SetRegisterAllowed(0x6D0);
+SetRegisterAllowed(0x6D4);
+SetRegisterAllowed(0x6D8);
+SetRegisterAllowed(0x6DC);
+SetRegisterAllowed(0x6E0);
+SetRegisterAllowed(0x6E4);
+SetRegisterAllowed(0x6E8);
+SetRegisterAllowed(0x6EC);
+SetRegisterAllowed(0x6F0);
+SetRegisterAllowed(0x6F4);
+SetRegisterAllowed(0x6F8);
+SetRegisterAllowed(0x6FC);
+SetRegisterAllowed(0x700);
+SetRegisterAllowed(0x704);
+SetRegisterAllowed(0x708);
+SetRegisterAllowed(0x70C);
+SetRegisterAllowed(0x710);
+SetRegisterAllowed(0x714);
+SetRegisterAllowed(0x718);
+SetRegisterAllowed(0x71C);
+SetRegisterAllowed(0x720);
+SetRegisterAllowed(0x724);
+SetRegisterAllowed(0x728);
+SetRegisterAllowed(0x72C);
+SetRegisterAllowed(0x730);
+SetRegisterAllowed(0x734);
+SetRegisterAllowed(0x738);
+SetRegisterAllowed(0x73C);
+SetRegisterAllowed(0x740);
+SetRegisterAllowed(0x744);
+SetRegisterAllowed(0x748);
+SetRegisterAllowed(0x74C);
+SetRegisterAllowed(0x750);
+SetRegisterAllowed(0x754);
+SetRegisterAllowed(0x758);
+SetRegisterAllowed(0x75C);
+SetRegisterAllowed(0x760);
+SetRegisterAllowed(0x764);
+SetRegisterAllowed(0x768);
+SetRegisterAllowed(0x76C);
+SetRegisterAllowed(0x770);
+SetRegisterAllowed(0x774);
+SetRegisterAllowed(0x778);
+SetRegisterAllowed(0x77C);
+SetRegisterAllowed(0x780);
+SetRegisterAllowed(0x784);
+SetRegisterAllowed(0x788);
+SetRegisterAllowed(0x78C);
+SetRegisterAllowed(0x790);
+SetRegisterAllowed(0x794);
+SetRegisterAllowed(0x798);
+SetRegisterAllowed(0x79C);
+SetRegisterAllowed(0x7A0);
+SetRegisterAllowed(0x7A4);
+SetRegisterAllowed(0x7A8);
+SetRegisterAllowed(0x7AC);
+SetRegisterAllowed(0x7B0);
+SetRegisterAllowed(0x7B4);
+SetRegisterAllowed(0x7B8);
+SetRegisterAllowed(0x7BC);
+SetRegisterAllowed(0x7C0);
+SetRegisterAllowed(0x7C4);
+SetRegisterAllowed(0x7C8);
+SetRegisterAllowed(0x7CC);
+SetRegisterAllowed(0x7D0);
+SetRegisterAllowed(0x7D4);
+SetRegisterAllowed(0x7D8);
+SetRegisterAllowed(0x7DC);
+SetRegisterAllowed(0x7E0);
+SetRegisterAllowed(0x7E4);
+SetRegisterAllowed(0x7E8);
+SetRegisterAllowed(0x7EC);
+SetRegisterAllowed(0x7F0);
+SetRegisterAllowed(0x7F4);
+SetRegisterAllowed(0x7F8);
+SetRegisterAllowed(0x7FC);
+SetRegisterAllowed(0x800);
+SetRegisterAllowed(0x804);
+SetRegisterAllowed(0x808);
+SetRegisterAllowed(0x80C);
+SetRegisterAllowed(0x810);
+SetRegisterAllowed(0x814);
+SetRegisterAllowed(0x818);
+SetRegisterAllowed(0x81C);
+SetRegisterAllowed(0x820);
+SetRegisterAllowed(0x824);
+SetRegisterAllowed(0x828);
+SetRegisterAllowed(0x82C);
+SetRegisterAllowed(0x830);
+SetRegisterAllowed(0x834);
+SetRegisterAllowed(0x838);
+SetRegisterAllowed(0x83C);
+SetRegisterAllowed(0x840);
+SetRegisterAllowed(0x844);
+SetRegisterAllowed(0x848);
+SetRegisterAllowed(0x84C);
+SetRegisterAllowed(0x850);
+SetRegisterAllowed(0x854);
+SetRegisterAllowed(0x858);
+SetRegisterAllowed(0x85C);
+SetRegisterAllowed(0x860);
+SetRegisterAllowed(0x864);
+SetRegisterAllowed(0x868);
+SetRegisterAllowed(0x86C);
+SetRegisterAllowed(0x870);
+SetRegisterAllowed(0x874);
+SetRegisterAllowed(0x878);
+SetRegisterAllowed(0x87C);
+SetRegisterAllowed(0x880);
+SetRegisterAllowed(0x884);
+SetRegisterAllowed(0x888);
+SetRegisterAllowed(0x88C);
+SetRegisterAllowed(0x890);
+SetRegisterAllowed(0x894);
+SetRegisterAllowed(0x898);
+SetRegisterAllowed(0x89C);
+SetRegisterAllowed(0x8A0);
+SetRegisterAllowed(0x8A4);
+SetRegisterAllowed(0x8A8);
+SetRegisterAllowed(0x8AC);
+SetRegisterAllowed(0x8B0);
+SetRegisterAllowed(0x8B4);
+SetRegisterAllowed(0x8B8);
+SetRegisterAllowed(0x8BC);
+SetRegisterAllowed(0x8C0);
+SetRegisterAllowed(0x8C4);
+SetRegisterAllowed(0x8C8);
+SetRegisterAllowed(0x8CC);
+SetRegisterAllowed(0x8D0);
+SetRegisterAllowed(0x8D4);
+SetRegisterAllowed(0x8D8);
+SetRegisterAllowed(0x8DC);
+SetRegisterAllowed(0x8E0);
+SetRegisterAllowed(0x8E4);
+SetRegisterAllowed(0x8E8);
+SetRegisterAllowed(0x8EC);
+SetRegisterAllowed(0x8F0);
+SetRegisterAllowed(0x8F4);
+SetRegisterAllowed(0x8F8);
+SetRegisterAllowed(0x8FC);
+SetRegisterAllowed(0x900);
+SetRegisterAllowed(0x904);
+SetRegisterAllowed(0x908);
+SetRegisterAllowed(0x90C);
+SetRegisterAllowed(0x910);
+SetRegisterAllowed(0x914);
+SetRegisterAllowed(0x918);
+SetRegisterAllowed(0x91C);
+SetRegisterAllowed(0x920);
+SetRegisterAllowed(0x924);
+SetRegisterAllowed(0x928);
+SetRegisterAllowed(0x92C);
+SetRegisterAllowed(0x930);
+SetRegisterAllowed(0x934);
+SetRegisterAllowed(0x938);
+SetRegisterAllowed(0x93C);
+SetRegisterAllowed(0x940);
+SetRegisterAllowed(0x944);
+SetRegisterAllowed(0x948);
+SetRegisterAllowed(0x94C);
+SetRegisterAllowed(0x950);
+SetRegisterAllowed(0x954);
+SetRegisterAllowed(0x958);
+SetRegisterAllowed(0x95C);
+SetRegisterAllowed(0x960);
+SetRegisterAllowed(0x964);
+SetRegisterAllowed(0x968);
+SetRegisterAllowed(0x96C);
+SetRegisterAllowed(0x970);
+SetRegisterAllowed(0x974);
+SetRegisterAllowed(0x978);
+SetRegisterAllowed(0x97C);
+SetRegisterAllowed(0x980);
+SetRegisterAllowed(0x984);
+SetRegisterAllowed(0x988);
+SetRegisterAllowed(0x98C);
+SetRegisterAllowed(0x990);
+SetRegisterAllowed(0x994);
+SetRegisterAllowed(0x998);
+SetRegisterAllowed(0x99C);
+SetRegisterAllowed(0x9A0);
+SetRegisterAllowed(0x9A4);
+SetRegisterAllowed(0x9A8);
+SetRegisterAllowed(0x9AC);
+SetRegisterAllowed(0x9B0);
+SetRegisterAllowed(0x9B4);
+SetRegisterAllowed(0x9B8);
+SetRegisterAllowed(0x9BC);
+SetRegisterAllowed(0x9C0);
+SetRegisterAllowed(0x9C4);
+SetRegisterAllowed(0x9C8);
+SetRegisterAllowed(0x9CC);
+SetRegisterAllowed(0x9D0);
+SetRegisterAllowed(0x9D4);
+SetRegisterAllowed(0x9D8);
+SetRegisterAllowed(0x9DC);
+SetRegisterAllowed(0x9E0);
+SetRegisterAllowed(0x9E4);
+SetRegisterAllowed(0x9E8);
+SetRegisterAllowed(0x9EC);
+SetRegisterAllowed(0x9F0);
+SetRegisterAllowed(0x9F4);
+SetRegisterAllowed(0x9F8);
+SetRegisterAllowed(0x9FC);
+SetRegisterAllowed(0xA00);
+SetRegisterAllowed(0xA04);
+SetRegisterAllowed(0xA08);
+SetRegisterAllowed(0xA0C);
+SetRegisterAllowed(0xA10);
+SetRegisterAllowed(0xA14);
+SetRegisterAllowed(0xA18);
+SetRegisterAllowed(0xA1C);
+SetRegisterAllowed(0xA20);
+SetRegisterAllowed(0xA24);
+SetRegisterAllowed(0xA28);
+SetRegisterAllowed(0xA2C);
+SetRegisterAllowed(0xA30);
+SetRegisterAllowed(0xA34);
+SetRegisterAllowed(0xA38);
+SetRegisterAllowed(0xA3C);
+SetRegisterAllowed(0xA40);
+SetRegisterAllowed(0xA44);
+SetRegisterAllowed(0xA48);
+SetRegisterAllowed(0xA4C);
+SetRegisterAllowed(0xA50);
+SetRegisterAllowed(0xA54);
+SetRegisterAllowed(0xA58);
+SetRegisterAllowed(0xA5C);
+SetRegisterAllowed(0xA60);
+SetRegisterAllowed(0xA64);
+SetRegisterAllowed(0xA68);
+SetRegisterAllowed(0xA6C);
+SetRegisterAllowed(0xA70);
+SetRegisterAllowed(0xA74);
+SetRegisterAllowed(0xA78);
+SetRegisterAllowed(0xA7C);
+SetRegisterAllowed(0xA80);
+SetRegisterAllowed(0xA84);
+SetRegisterAllowed(0xA88);
+SetRegisterAllowed(0xA8C);
+SetRegisterAllowed(0xA90);
+SetRegisterAllowed(0xA94);
+SetRegisterAllowed(0xA98);
+SetRegisterAllowed(0xA9C);
+SetRegisterAllowed(0xAA0);
+SetRegisterAllowed(0xAA4);
+SetRegisterAllowed(0xAA8);
+SetRegisterAllowed(0xAAC);
+SetRegisterAllowed(0xAB0);
+SetRegisterAllowed(0xAB4);
+SetRegisterAllowed(0xAB8);
+SetRegisterAllowed(0xABC);
+SetRegisterAllowed(0xAC0);
+SetRegisterAllowed(0xAC4);
+SetRegisterAllowed(0xAC8);
+SetRegisterAllowed(0xACC);
+SetRegisterAllowed(0xAD0);
+SetRegisterAllowed(0xAD4);
+SetRegisterAllowed(0xAD8);
+SetRegisterAllowed(0xADC);
+SetRegisterAllowed(0xAE0);
+SetRegisterAllowed(0xAE4);
+SetRegisterAllowed(0xAE8);
+SetRegisterAllowed(0xAEC);
+SetRegisterAllowed(0xAF0);
+SetRegisterAllowed(0xAF4);
+SetRegisterAllowed(0xAF8);
+SetRegisterAllowed(0xAFC);
+SetRegisterAllowed(0xB00);
+SetRegisterAllowed(0xB04);
+SetRegisterAllowed(0xB08);
+SetRegisterAllowed(0xB0C);
+SetRegisterAllowed(0xB10);
+SetRegisterAllowed(0xB14);
+SetRegisterAllowed(0xB18);
+SetRegisterAllowed(0xB1C);
+SetRegisterAllowed(0xB20);
+SetRegisterAllowed(0xB24);
+SetRegisterAllowed(0xB28);
+SetRegisterAllowed(0xB2C);
+SetRegisterAllowed(0xB30);
+SetRegisterAllowed(0xB34);
+SetRegisterAllowed(0xB38);
+SetRegisterAllowed(0xB3C);
+SetRegisterAllowed(0xB40);
+SetRegisterAllowed(0xB44);
+SetRegisterAllowed(0xB48);
+SetRegisterAllowed(0xB4C);
+SetRegisterAllowed(0xB50);
+SetRegisterAllowed(0xB54);
+SetRegisterAllowed(0xB58);
+SetRegisterAllowed(0xB5C);
+SetRegisterAllowed(0xB60);
+SetRegisterAllowed(0xB64);
+SetRegisterAllowed(0xB68);
+SetRegisterAllowed(0xB6C);
+SetRegisterAllowed(0xB70);
+SetRegisterAllowed(0xB74);
+SetRegisterAllowed(0xB78);
+SetRegisterAllowed(0xB7C);
+SetRegisterAllowed(0xB80);
+SetRegisterAllowed(0xB84);
+SetRegisterAllowed(0xB88);
+SetRegisterAllowed(0xB8C);
+SetRegisterAllowed(0xB90);
+SetRegisterAllowed(0xB94);
+SetRegisterAllowed(0xB98);
+SetRegisterAllowed(0xB9C);
+SetRegisterAllowed(0xBA0);
+SetRegisterAllowed(0xBA4);
+SetRegisterAllowed(0xBA8);
+SetRegisterAllowed(0xBAC);
+SetRegisterAllowed(0xBB0);
+SetRegisterAllowed(0xBB4);
+SetRegisterAllowed(0xBB8);
+SetRegisterAllowed(0xBBC);
+SetRegisterAllowed(0xBC0);
+SetRegisterAllowed(0xBC4);
+SetRegisterAllowed(0xBC8);
+SetRegisterAllowed(0xBCC);
+SetRegisterAllowed(0xBD0);
+SetRegisterAllowed(0xBD4);
+SetRegisterAllowed(0xBD8);
+SetRegisterAllowed(0xBDC);
+SetRegisterAllowed(0xBE0);
+SetRegisterAllowed(0xBE4);
+SetRegisterAllowed(0xBE8);
+SetRegisterAllowed(0xBEC);
+SetRegisterAllowed(0xBF0);
+SetRegisterAllowed(0xBF4);
+SetRegisterAllowed(0xBF8);
+SetRegisterAllowed(0xBFC);
+SetRegisterAllowed(0xC00);
+SetRegisterAllowed(0xC04);
+SetRegisterAllowed(0xC08);
+SetRegisterAllowed(0xC0C);
+SetRegisterAllowed(0xC10);
+SetRegisterAllowed(0xC14);
+SetRegisterAllowed(0xC18);
+SetRegisterAllowed(0xC1C);
+SetRegisterAllowed(0xC20);
+SetRegisterAllowed(0xC24);
+SetRegisterAllowed(0xC28);
+SetRegisterAllowed(0xC2C);
+SetRegisterAllowed(0xC30);
+SetRegisterAllowed(0xC34);
+SetRegisterAllowed(0xC38);
+SetRegisterAllowed(0xC3C);
+SetRegisterAllowed(0xC40);
+SetRegisterAllowed(0xC44);
+SetRegisterAllowed(0xC48);
+SetRegisterAllowed(0xC4C);
+SetRegisterAllowed(0xC50);
+SetRegisterAllowed(0xC54);
+SetRegisterAllowed(0xC58);
+SetRegisterAllowed(0xC5C);
+SetRegisterAllowed(0xC60);
+SetRegisterAllowed(0xC64);
+SetRegisterAllowed(0xC68);
+SetRegisterAllowed(0xC6C);
+SetRegisterAllowed(0xC70);
+SetRegisterAllowed(0xC74);
+SetRegisterAllowed(0xC78);
+SetRegisterAllowed(0xC7C);
+SetRegisterAllowed(0xC80);
+SetRegisterAllowed(0xC84);
+SetRegisterAllowed(0xC88);
+SetRegisterAllowed(0xC8C);
+SetRegisterAllowed(0xC90);
+SetRegisterAllowed(0xC94);
+SetRegisterAllowed(0xC98);
+SetRegisterAllowed(0xC9C);
+SetRegisterAllowed(0xCA0);
+SetRegisterAllowed(0xCA4);
+SetRegisterAllowed(0xCA8);
+SetRegisterAllowed(0xCAC);
+SetRegisterAllowed(0xCB0);
+SetRegisterAllowed(0xCB4);
+SetRegisterAllowed(0xCB8);
+SetRegisterAllowed(0xCBC);
+SetRegisterAllowed(0xCC0);
+SetRegisterAllowed(0xCC4);
+SetRegisterAllowed(0xCC8);
+SetRegisterAllowed(0xCCC);
+SetRegisterAllowed(0xCD0);
+SetRegisterAllowed(0xCD4);
+SetRegisterAllowed(0xCD8);
+SetRegisterAllowed(0xCDC);
+SetRegisterAllowed(0xCE0);
+SetRegisterAllowed(0xCE4);
+SetRegisterAllowed(0xCE8);
+SetRegisterAllowed(0xCEC);
+SetRegisterAllowed(0xCF0);
+SetRegisterAllowed(0xCF4);
+SetRegisterAllowed(0xCF8);
+SetRegisterAllowed(0xCFC);
+SetRegisterAllowed(0xD00);
+SetRegisterAllowed(0xD04);
+SetRegisterAllowed(0xD08);
+SetRegisterAllowed(0xD0C);
+SetRegisterAllowed(0xD10);
+SetRegisterAllowed(0xD14);
+SetRegisterAllowed(0xD18);
+SetRegisterAllowed(0xD1C);
+SetRegisterAllowed(0xD20);
+SetRegisterAllowed(0xD24);
+SetRegisterAllowed(0xD28);
+SetRegisterAllowed(0xD2C);
+SetRegisterAllowed(0xD30);
+SetRegisterAllowed(0xD34);
+SetRegisterAllowed(0xD38);
+SetRegisterAllowed(0xD3C);
+SetRegisterAllowed(0xD40);
+SetRegisterAllowed(0xD44);
+SetRegisterAllowed(0xD48);
+SetRegisterAllowed(0xD4C);
+SetRegisterAllowed(0xD50);
+SetRegisterAllowed(0xD54);
+SetRegisterAllowed(0xD58);
+SetRegisterAllowed(0xD5C);
+SetRegisterAllowed(0xD60);
+SetRegisterAllowed(0xD64);
+SetRegisterAllowed(0xD68);
+SetRegisterAllowed(0xD6C);
+SetRegisterAllowed(0xD70);
+SetRegisterAllowed(0xD74);
+SetRegisterAllowed(0xD78);
+SetRegisterAllowed(0xD7C);
+SetRegisterAllowed(0xD80);
+SetRegisterAllowed(0xD84);
+SetRegisterAllowed(0xD88);
+SetRegisterAllowed(0xD8C);
+SetRegisterAllowed(0xD90);
+SetRegisterAllowed(0xD94);
+SetRegisterAllowed(0xD98);
+SetRegisterAllowed(0xD9C);
+SetRegisterAllowed(0xDA0);
+SetRegisterAllowed(0xDA4);
+SetRegisterAllowed(0xDA8);
+SetRegisterAllowed(0xDAC);
+SetRegisterAllowed(0xDB0);
+SetRegisterAllowed(0xDB4);
+SetRegisterAllowed(0xDB8);
+SetRegisterAllowed(0xDBC);
+SetRegisterAllowed(0xDC0);
+SetRegisterAllowed(0xDC4);
+SetRegisterAllowed(0xDC8);
+SetRegisterAllowed(0xDCC);
+SetRegisterAllowed(0xDD0);
+SetRegisterAllowed(0xDD4);
+SetRegisterAllowed(0xDD8);
+SetRegisterAllowed(0xDDC);
+SetRegisterAllowed(0xDE0);
+SetRegisterAllowed(0xDE4);
+SetRegisterAllowed(0xDE8);
+SetRegisterAllowed(0xDEC);
+SetRegisterAllowed(0xDF0);
+SetRegisterAllowed(0xDF4);
+SetRegisterAllowed(0xDF8);
+SetRegisterAllowed(0xDFC);
+SetRegisterAllowed(0xE00);
+SetRegisterAllowed(0xE04);
+SetRegisterAllowed(0xE08);
+SetRegisterAllowed(0xE0C);
+SetRegisterAllowed(0xE10);
+SetRegisterAllowed(0xE14);
+SetRegisterAllowed(0xE18);
+SetRegisterAllowed(0xE1C);
+SetRegisterAllowed(0xE20);
+SetRegisterAllowed(0xE24);
+SetRegisterAllowed(0xE28);
+SetRegisterAllowed(0xE2C);
+SetRegisterAllowed(0xE30);
+SetRegisterAllowed(0xE34);
+SetRegisterAllowed(0xE38);
+SetRegisterAllowed(0xE3C);
+SetRegisterAllowed(0xE40);
+SetRegisterAllowed(0xE44);
+SetRegisterAllowed(0xE48);
+SetRegisterAllowed(0xE4C);
+SetRegisterAllowed(0xE50);
+SetRegisterAllowed(0xE54);
+SetRegisterAllowed(0xE58);
+SetRegisterAllowed(0xE5C);
+SetRegisterAllowed(0xE60);
+SetRegisterAllowed(0xE64);
+SetRegisterAllowed(0xE68);
+SetRegisterAllowed(0xE6C);
+SetRegisterAllowed(0xE70);
+SetRegisterAllowed(0xE74);
+SetRegisterAllowed(0xE78);
+SetRegisterAllowed(0xE7C);
+SetRegisterAllowed(0xE80);
+SetRegisterAllowed(0xE84);
+SetRegisterAllowed(0xE88);
+SetRegisterAllowed(0xE8C);
+SetRegisterAllowed(0xE90);
+SetRegisterAllowed(0xE94);
+SetRegisterAllowed(0xE98);
+SetRegisterAllowed(0xE9C);
+SetRegisterAllowed(0xEA0);
+SetRegisterAllowed(0xEA4);
+SetRegisterAllowed(0xEA8);
+SetRegisterAllowed(0xEAC);
+SetRegisterAllowed(0xEB0);
+SetRegisterAllowed(0xEB4);
+SetRegisterAllowed(0xEB8);
+SetRegisterAllowed(0xEBC);
+SetRegisterAllowed(0xEC0);
+SetRegisterAllowed(0xEC4);
+SetRegisterAllowed(0xEC8);
+SetRegisterAllowed(0xECC);
+SetRegisterAllowed(0xED0);
+SetRegisterAllowed(0xED4);
+SetRegisterAllowed(0xED8);
+SetRegisterAllowed(0xEDC);
+SetRegisterAllowed(0xEE0);
+SetRegisterAllowed(0xEE4);
+SetRegisterAllowed(0xEE8);
+SetRegisterAllowed(0xEEC);
+SetRegisterAllowed(0xEF0);
+SetRegisterAllowed(0xEF4);
+SetRegisterAllowed(0xEF8);
+SetRegisterAllowed(0xEFC);
+SetRegisterAllowed(0xF00);
+SetRegisterAllowed(0xF04);
+SetRegisterAllowed(0xF08);
+SetRegisterAllowed(0xF0C);
+SetRegisterAllowed(0xF10);
+SetRegisterAllowed(0xF14);
+SetRegisterAllowed(0xF18);
+SetRegisterAllowed(0xF1C);
+SetRegisterAllowed(0xF20);
+SetRegisterAllowed(0xF24);
+SetRegisterAllowed(0xF28);
+SetRegisterAllowed(0xF2C);
+SetRegisterAllowed(0xF30);
+SetRegisterAllowed(0xF34);
+SetRegisterAllowed(0xF38);
+SetRegisterAllowed(0xF3C);
+SetRegisterAllowed(0xF40);
+SetRegisterAllowed(0xF44);
+SetRegisterAllowed(0xF48);
+SetRegisterAllowed(0xF4C);
+SetRegisterAllowed(0xF50);
+SetRegisterAllowed(0xF54);
+SetRegisterAllowed(0xF58);
+SetRegisterAllowed(0xF5C);
+SetRegisterAllowed(0xF60);
+SetRegisterAllowed(0xF64);
+SetRegisterAllowed(0xF68);
+SetRegisterAllowed(0xF6C);
+SetRegisterAllowed(0xF70);
+SetRegisterAllowed(0xF74);
+SetRegisterAllowed(0xF78);
+SetRegisterAllowed(0xF7C);
+SetRegisterAllowed(0xF80);
+SetRegisterAllowed(0xF84);
+SetRegisterAllowed(0xF88);
+SetRegisterAllowed(0xF8C);
+SetRegisterAllowed(0xF90);
+SetRegisterAllowed(0xF94);
+SetRegisterAllowed(0xF98);
+SetRegisterAllowed(0xF9C);
+SetRegisterAllowed(0xFA0);
+SetRegisterAllowed(0xFA4);
+SetRegisterAllowed(0xFA8);
+SetRegisterAllowed(0xFAC);
+SetRegisterAllowed(0xFB0);
+SetRegisterAllowed(0xFB4);
+SetRegisterAllowed(0xFB8);
+SetRegisterAllowed(0xFBC);
+SetRegisterAllowed(0xFC0);
+SetRegisterAllowed(0xFC4);
+SetRegisterAllowed(0xFC8);
+SetRegisterAllowed(0xFCC);
+SetRegisterAllowed(0xFD0);
+SetRegisterAllowed(0xFD4);
+SetRegisterAllowed(0xFD8);
+SetRegisterAllowed(0xFDC);
+SetRegisterAllowed(0xFE0);
+SetRegisterAllowed(0xFE4);
+SetRegisterAllowed(0xFE8);
+SetRegisterAllowed(0xFEC);
+SetRegisterAllowed(0xFF0);
+SetRegisterAllowed(0xFF4);
+SetRegisterAllowed(0xFF8);
+SetRegisterAllowed(0xFFC);
diff --git a/Source/Atmosphere-Patches/secmon_memory_layout.hpp b/Source/Atmosphere-Patches/secmon_memory_layout.hpp
index 7c0e499a..ba3e3ab8 100644
--- a/Source/Atmosphere-Patches/secmon_memory_layout.hpp
+++ b/Source/Atmosphere-Patches/secmon_memory_layout.hpp
@@ -151,7 +151,9 @@ namespace ams::secmon {
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
- HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
+ HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
diff --git a/Source/Atmosphere-Patches/secmon_setup.cpp b/Source/Atmosphere-Patches/secmon_setup.cpp
new file mode 100644
index 00000000..af6c3ed8
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_setup.cpp
@@ -0,0 +1,1290 @@
+/*
+ * Copyright (c) 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 .
+ */
+#include
+#include "secmon_setup.hpp"
+#include "secmon_error.hpp"
+#include "secmon_map.hpp"
+#include "secmon_cpu_context.hpp"
+#include "secmon_mariko_fatal_error.hpp"
+#include "secmon_interrupt_handler.hpp"
+#include "secmon_misc.hpp"
+#include "smc/secmon_random_cache.hpp"
+#include "smc/secmon_smc_power_management.hpp"
+#include "smc/secmon_smc_se_lock.hpp"
+
+namespace ams::secmon {
+
+ namespace {
+
+ constexpr inline const uintptr_t TIMER = secmon::MemoryRegionVirtualDeviceTimer.GetAddress();
+ constexpr inline const uintptr_t SYSTEM = secmon::MemoryRegionVirtualDeviceSystem.GetAddress();
+ constexpr inline const uintptr_t APB_MISC = secmon::MemoryRegionVirtualDeviceApbMisc.GetAddress();
+ constexpr inline const uintptr_t FLOW_CTLR = secmon::MemoryRegionVirtualDeviceFlowController.GetAddress();
+ constexpr inline const uintptr_t PMC = secmon::MemoryRegionVirtualDevicePmc.GetAddress();
+ constexpr inline const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress();
+ constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress();
+ constexpr inline const uintptr_t CLK_RST = secmon::MemoryRegionVirtualDeviceClkRst.GetAddress();
+
+ alignas(8) constinit u8 g_se_aes_key_slot_test_vector[se::AesBlockSize] = {};
+
+ struct Carveout {
+ uintptr_t address;
+ size_t size;
+ };
+
+ constinit Carveout g_kernel_carveouts[KernelCarveoutCount] = {
+ { secmon::MemoryRegionDramDefaultKernelCarveout.GetAddress(), secmon::MemoryRegionDramDefaultKernelCarveout.GetSize(), },
+ { 0, 0, },
+ };
+
+ constinit bool g_is_cold_boot = true;
+
+ constinit se::StickyBits ExpectedSeStickyBits = {
+ .se_security = (1 << 0), /* SE_HARD_SETTING */
+ .tzram_security = 0,
+ .crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1,
+ .crypto_keytable_access = {
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
+ (0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (0 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEY. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */
+ },
+ .rsa_security_perkey = 0,
+ .rsa_keytable_access = {
+ (0 << 2) | (1 << 1) | (0 << 0), /* KEYUSE/KEYREAD disabled, KEYUPDATE enabled. */
+ (0 << 2) | (1 << 1) | (0 << 0), /* KEYUSE/KEYREAD disabled, KEYUPDATE enabled. */
+ },
+ };
+
+ void InitializeConfigurationContext() {
+ /* Get the global context. */
+ auto &ctx = ::ams::secmon::impl::GetConfigurationContext();
+
+ /* Clear the context to zero. */
+ std::memset(std::addressof(ctx), 0, sizeof(ctx));
+
+ /* If the storage context is valid, we want to copy it to the global context. */
+ if (const auto &storage_ctx = *MemoryRegionPhysicalDramMonitorConfiguration.GetPointer(); storage_ctx.IsValid()) {
+ ctx.secmon_cfg.CopyFrom(storage_ctx);
+ ctx.emummc_cfg = storage_ctx.emummc_cfg;
+ } else {
+ /* If we don't have a valid storage context, we can just use the default one. */
+ ctx.secmon_cfg = DefaultSecureMonitorConfiguration;
+ }
+
+ /* Cache the fuse info for quick access. */
+ ctx.secmon_cfg.SetFuseInfo();
+ }
+
+ void GenerateSecurityEngineAesKeySlotTestVector(void *dst, size_t size) {
+ /* Clear the output. */
+ AMS_ABORT_UNLESS(size == se::AesBlockSize);
+ std::memset(dst, 0, se::AesBlockSize);
+
+ /* Ensure output is seen as cleared by the se. */
+ hw::FlushDataCache(dst, se::AesBlockSize);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Declare a block. */
+ alignas(8) u8 empty_block[se::AesBlockSize];
+
+ /* Iteratively transform an empty block. */
+ #define TRANSFORM_WITH_KEY(key) \
+ __builtin_memset(empty_block, 0, sizeof(empty_block)); \
+ se::SetEncryptedAesKey256(pkg1::AesKeySlot_Temporary, key, empty_block, sizeof(empty_block)); \
+ se::DecryptAes128(dst, se::AesBlockSize, pkg1::AesKeySlot_Temporary, dst, se::AesBlockSize)
+
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForUserWrap);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForKeyStorageWrap);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Master);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_DeviceMaster);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Device);
+
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForUserWrap);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForKeyStorageWrap);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Master);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_DeviceMaster);
+ TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Device);
+
+ /* Ensure output is seen correctly by the cpu. */
+ hw::FlushDataCache(dst, se::AesBlockSize);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Clear the temporary key slot. */
+ se::ClearAesKeySlot(pkg1::AesKeySlot_Temporary);
+ }
+
+ void VerifySecurityEngineStickyBits() {
+ /* On mariko, an extra sticky bit is set. */
+ if (GetSocType() == fuse::SocType_Mariko) {
+ ExpectedSeStickyBits.se_security |= (1 << 5);
+ } else /* if (GetSocType() == fuse::SocType_Erista) */ {
+ /* Erista does not support DST_KEYTABLE_ONLY, and so all keys will have the bit clear. */
+ for (size_t i = 0; i < util::size(ExpectedSeStickyBits.crypto_keytable_access); ++i) {
+ ExpectedSeStickyBits.crypto_keytable_access[i] &= ~(1 << 7);
+ }
+ }
+
+ if (!se::ValidateStickyBits(ExpectedSeStickyBits)) {
+ SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits);
+ AMS_ABORT("Invalid sticky bits");
+ }
+ }
+
+ void VerifySecurityEngineAesKeySlotTestVector() {
+ alignas(8) u8 test_vector[se::AesBlockSize];
+ GenerateSecurityEngineAesKeySlotTestVector(test_vector, sizeof(test_vector));
+
+ AMS_ABORT_UNLESS(crypto::IsSameBytes(g_se_aes_key_slot_test_vector, test_vector, se::AesBlockSize));
+ }
+
+ void ClearAesKeySlots() {
+ /* Clear all non-secure monitor keys. */
+ for (int i = 0; i < pkg1::AesKeySlot_SecmonStart; ++i) {
+ se::ClearAesKeySlot(i);
+ }
+
+ /* Clear the secure-monitor temporary keys. */
+ se::ClearAesKeySlot(pkg1::AesKeySlot_Temporary);
+ se::ClearAesKeySlot(pkg1::AesKeySlot_Smc);
+ }
+
+ void ClearRsaKeySlots() {
+ /* Clear all rsa keyslots. */
+ for (int i = 0; i < se::RsaKeySlotCount; ++i) {
+ se::ClearRsaKeySlot(i);
+ }
+ }
+
+ void SetupKernelCarveouts() {
+ #define MC_ENABLE_CLIENT_ACCESS(INDEX, WHICH) MC_REG_BITS_ENUM(CLIENT_ACCESS##INDEX##_##WHICH, ENABLE)
+
+ constexpr u32 ClientAccess0 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(0, PTCR),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0A),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0AB),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0B),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0BB),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0C),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0CB),
+ MC_ENABLE_CLIENT_ACCESS(0, AFIR),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAYHC),
+ MC_ENABLE_CLIENT_ACCESS(0, DISPLAYHCB),
+ MC_ENABLE_CLIENT_ACCESS(0, HDAR),
+ MC_ENABLE_CLIENT_ACCESS(0, HOST1XDMAR),
+ MC_ENABLE_CLIENT_ACCESS(0, HOST1XR),
+ MC_ENABLE_CLIENT_ACCESS(0, NVENCSRD),
+ MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBDMAR),
+ MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBSLVR));
+
+ constexpr u32 ClientAccess1 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(1, MPCORER),
+ MC_ENABLE_CLIENT_ACCESS(1, NVENCSWR),
+ MC_ENABLE_CLIENT_ACCESS(1, AFIW),
+ MC_ENABLE_CLIENT_ACCESS(1, HDAW),
+ MC_ENABLE_CLIENT_ACCESS(1, HOST1XW),
+ MC_ENABLE_CLIENT_ACCESS(1, MPCOREW),
+ MC_ENABLE_CLIENT_ACCESS(1, PPCSAHBDMAW),
+ MC_ENABLE_CLIENT_ACCESS(1, PPCSAHBSLVW));
+
+ constexpr u32 ClientAccess2 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTR),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTW),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVR),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVW));
+
+ constexpr u32 ClientAccess2_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTR),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTW),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVR),
+ MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVW),
+ MC_ENABLE_CLIENT_ACCESS(2, TSECSRD),
+ MC_ENABLE_CLIENT_ACCESS(2, TSECSWR));
+
+ constexpr u32 ClientAccess3 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(3, SDMMCRA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAB),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAB),
+ MC_ENABLE_CLIENT_ACCESS(3, VICSRD),
+ MC_ENABLE_CLIENT_ACCESS(3, VICSWR),
+ MC_ENABLE_CLIENT_ACCESS(3, DISPLAYD),
+ MC_ENABLE_CLIENT_ACCESS(3, APER),
+ MC_ENABLE_CLIENT_ACCESS(3, APEW),
+ MC_ENABLE_CLIENT_ACCESS(3, NVJPGSRD),
+ MC_ENABLE_CLIENT_ACCESS(3, NVJPGSWR));
+
+ constexpr u32 ClientAccess3_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(3, SDMMCRA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAB),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAA),
+ MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAB),
+ MC_ENABLE_CLIENT_ACCESS(3, VICSRD),
+ MC_ENABLE_CLIENT_ACCESS(3, VICSWR),
+ MC_ENABLE_CLIENT_ACCESS(3, DISPLAYD),
+ MC_ENABLE_CLIENT_ACCESS(3, NVDECSRD),
+ MC_ENABLE_CLIENT_ACCESS(3, NVDECSWR),
+ MC_ENABLE_CLIENT_ACCESS(3, APER),
+ MC_ENABLE_CLIENT_ACCESS(3, APEW),
+ MC_ENABLE_CLIENT_ACCESS(3, NVJPGSRD),
+ MC_ENABLE_CLIENT_ACCESS(3, NVJPGSWR));
+
+ constexpr u32 ClientAccess4 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD),
+ MC_ENABLE_CLIENT_ACCESS(4, SESWR));
+
+ constexpr u32 ClientAccess4_800 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD),
+ MC_ENABLE_CLIENT_ACCESS(4, SESWR),
+ MC_ENABLE_CLIENT_ACCESS(4, TSECRDB),
+ MC_ENABLE_CLIENT_ACCESS(4, TSECWRB));
+
+
+ constexpr u32 ClientAccess4_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD),
+ MC_ENABLE_CLIENT_ACCESS(4, SESWR));
+
+ #undef MC_ENABLE_CLIENT_ACCESS
+
+ constexpr u32 ForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE));
+ constexpr u32 ForceInternalAccess0_100 = 0;
+
+ constexpr u32 ForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE));
+ constexpr u32 ForceInternalAccess1_100 = 0;
+
+ constexpr u32 CarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, TZ_SECURE));
+
+ constexpr u32 CarveoutConfig_100 = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, TZ_SECURE));
+
+ const u32 target_fw = GetTargetFirmware();
+ u32 client_access_2;
+ u32 client_access_3;
+ u32 client_access_4;
+ u32 carveout_config;
+ if (target_fw >= TargetFirmware_8_1_0) {
+ client_access_2 = ClientAccess2;
+ client_access_3 = ClientAccess3;
+ client_access_4 = ClientAccess4;
+ carveout_config = CarveoutConfig;
+ } else if (target_fw >= TargetFirmware_8_0_0) {
+ client_access_2 = ClientAccess2;
+ client_access_3 = ClientAccess3;
+ client_access_4 = ClientAccess4_800;
+ carveout_config = CarveoutConfig;
+ } else {
+ client_access_2 = ClientAccess2_100;
+ client_access_3 = ClientAccess3_100;
+ client_access_4 = ClientAccess4_100;
+ carveout_config = CarveoutConfig_100;
+ }
+
+ /* Configure carveout 4. */
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM, g_kernel_carveouts[0].address >> 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM_HI, g_kernel_carveouts[0].address >> 32);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_SIZE_128KB, g_kernel_carveouts[0].size / 128_KB);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0, ClientAccess0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1, ClientAccess1);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2, client_access_2);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3, client_access_3);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4, client_access_4);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0, (target_fw >= TargetFirmware_4_0_0) ? ForceInternalAccess0 : ForceInternalAccess0_100);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1, (target_fw >= TargetFirmware_4_0_0) ? ForceInternalAccess1 : ForceInternalAccess1_100);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT4_CFG0, carveout_config);
+
+ /* Configure carveout 5. */
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_BOM, g_kernel_carveouts[1].address >> 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_BOM_HI, g_kernel_carveouts[1].address >> 32);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_SIZE_128KB, g_kernel_carveouts[1].size / 128_KB);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0, ClientAccess0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1, ClientAccess1);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2, client_access_2);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3, client_access_3);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4, client_access_4);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT5_CFG0, carveout_config);
+ }
+
+ void ConfigureSlaveSecurity() {
+ u32 reg0, reg1, reg2;
+ if (GetTargetFirmware() > TargetFirmware_1_0_0) {
+ reg0 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, SATA_AUX, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, DTV, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, QSPI, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, SE, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, SATA, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, LA, ENABLE));
+
+ reg1 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, SPI1, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI2, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI3, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI5, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI6, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, I2C6, ENABLE));
+
+ reg2 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SDMMC3, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(2, DDS, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(2, DP2, ENABLE));
+
+ const auto hw_type = GetHardwareType();
+
+ /* Switch Lite can't use HDMI, so set CEC to secure on hoag. */
+ if (hw_type == fuse::HardwareType_Hoag) {
+ reg0 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, CEC, ENABLE));
+ }
+
+ /* Icosa, Iowa, and Aula all set I2C4 to be secure. */
+ if (hw_type == fuse::HardwareType_Icosa && hw_type == fuse::HardwareType_Iowa && hw_type == fuse::HardwareType_Aula) {
+ reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, I2C4, ENABLE));
+
+ }
+
+ /* Hoag additionally sets UART_B to secure. */
+ if (hw_type == fuse::HardwareType_Hoag) {
+ reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, UART_B, ENABLE));
+ }
+
+ /* Copper and Calcio lack a lot of hardware, so set the corresponding registers to secure for them. */
+ if (hw_type == fuse::HardwareType_Calcio || hw_type == fuse::HardwareType_Copper) {
+ reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, UART_B, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, UART_C, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI4, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, I2C2, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, I2C3, ENABLE));
+
+ /* Copper/Calcio have no gamecard reader, and thus set SDMMC2 as secure. */
+ reg2 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SDMMC2, ENABLE));
+ }
+
+ /* Mariko hardware types (not Icosa or Copper) additionally set mariko-only mmio (SE2, PKA1, FEK) as secure. */
+ if (hw_type != fuse::HardwareType_Icosa && hw_type != fuse::HardwareType_Copper) {
+ reg2 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SE2, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(2, PKA1, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(2, FEK, ENABLE));
+ }
+ } else {
+ reg0 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, SATA_AUX, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, DTV, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, QSPI, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, SATA, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(0, LA, ENABLE));
+
+ reg1 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, SPI1, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI2, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI3, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI5, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, SPI6, ENABLE),
+ SLAVE_SECURITY_REG_BITS_ENUM(1, I2C6, ENABLE));
+
+ reg2 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, DDS, ENABLE),
+ REG_BITS_VALUE(5, 1, 1), /* Note: Bit 5 is not documented in TRM. */
+ REG_BITS_VALUE(4, 1, 1)); /* Note: Bit 4 is not documented in TRM. */
+ }
+
+ reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, reg0);
+ reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, reg1);
+ reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0, reg2);
+ }
+
+ void SetupSecureRegisters() {
+ /* Configure timers 5-8 and watchdog timers 0-3 as secure. */
+ reg::Write(TIMER + TIMER_SHARED_TIMER_SECURE_CFG, TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR5, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR6, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR7, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR8, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT0, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT1, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT2, ENABLE),
+ TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT3, ENABLE));
+
+ /* Lock cluster switching, to prevent usage of the A53 cores. */
+ reg::Write(FLOW_CTLR + FLOW_CTLR_BPMP_CLUSTER_CONTROL, FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER_LOCK, ENABLE),
+ FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_CLUSTER_SWITCH_ENABLE, DISABLE),
+ FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, FAST));
+
+ /* Enable flow controller debug qualifier for legacy FIQs. */
+ reg::Write(FLOW_CTLR + FLOW_CTLR_FLOW_DBG_QUAL, FLOW_REG_BITS_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, ENABLE));
+
+ /* Configure the PMC to disable deep power-down. */
+ reg::Write(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_TSC_MULT_EN, DISABLE),
+ PMC_REG_BITS_ENUM(DPD_ENABLE_ON, DISABLE));
+
+ /* Configure the video protect region. */
+ reg::Write(MC + MC_VIDEO_PROTECT_GPU_OVERRIDE_0, 1);
+ reg::Write(MC + MC_VIDEO_PROTECT_GPU_OVERRIDE_1, 0);
+ reg::Write(MC + MC_VIDEO_PROTECT_BOM, 0);
+ reg::Write(MC + MC_VIDEO_PROTECT_SIZE_MB, 0);
+ reg::Write(MC + MC_VIDEO_PROTECT_REG_CTRL, MC_REG_BITS_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_ALLOW_TZ_WRITE, DISABLED),
+ MC_REG_BITS_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_WRITE_ACCESS, DISABLED));
+
+ /* Configure the SEC carveout. */
+ reg::Write(MC + MC_SEC_CARVEOUT_BOM, 0);
+ reg::Write(MC + MC_SEC_CARVEOUT_SIZE_MB, 0);
+ reg::Write(MC + MC_SEC_CARVEOUT_REG_CTRL, MC_REG_BITS_ENUM(SEC_CARVEOUT_REG_CTRL_SEC_CARVEOUT_WRITE_ACCESS, DISABLED));
+
+ /* Configure the MTS carveout. */
+ reg::Write(MC + MC_MTS_CARVEOUT_BOM, 0);
+ reg::Write(MC + MC_MTS_CARVEOUT_SIZE_MB, 0);
+ reg::Write(MC + MC_MTS_CARVEOUT_ADR_HI, 0);
+ reg::Write(MC + MC_MTS_CARVEOUT_REG_CTRL, MC_REG_BITS_ENUM(MTS_CARVEOUT_REG_CTRL_MTS_CARVEOUT_WRITE_ACCESS, DISABLED));
+
+ /* Configure the security carveout. */
+ reg::Write(MC + MC_SECURITY_CFG0, MC_REG_BITS_VALUE(SECURITY_CFG0_SECURITY_BOM, 0));
+ reg::Write(MC + MC_SECURITY_CFG1, MC_REG_BITS_VALUE(SECURITY_CFG1_SECURITY_SIZE, 0));
+ reg::Write(MC + MC_SECURITY_CFG3, MC_REG_BITS_VALUE(SECURITY_CFG3_SECURITY_BOM_HI, 3));
+
+ /* Configure security carveout 1. */
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_BOM, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_BOM_HI, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_SIZE_128KB, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT1_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
+
+ /* Security carveout 2 will be configured later by SetupGpuCarveout, after magic values are written to configure gpu/tsec. */
+
+ /* Configure carveout 3. */
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_BOM, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_BOM_HI, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_SIZE_128KB, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2, MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSRD, ENABLE),
+ MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSWR, ENABLE));
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4, MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSRD2, ENABLE),
+ MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSWR2, ENABLE));
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT3_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 3),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
+
+ /* If we're cold-booting and on 1.0.0, alter the default carveout size. */
+ if (g_is_cold_boot && GetTargetFirmware() <= TargetFirmware_1_0_0) {
+ g_kernel_carveouts[0].size = 200 * 128_KB;
+ }
+
+ /* NOTE: Here Nintendo configures the two kernel carveouts; we will do this later, to allow fusee to continue using AVP_CACHE. */
+ /* SetupKernelCarveouts(); */
+
+ /* Configure slave register security. */
+ ConfigureSlaveSecurity();
+ }
+
+ void SetupSmmu() {
+ /* Turn on SMMU translation for all devices. */
+ reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_0, ~0u);
+ reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_1, ~0u);
+ reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_2, ~0u);
+ reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_3, ~0u);
+ reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_4, ~0u);
+
+ /* On modern firmware, configure ASIDs 1-3 as secure, and all others as non-secure. */
+ if (GetTargetFirmware() >= TargetFirmware_4_0_0) {
+ reg::Write(MC + MC_SMMU_ASID_SECURITY, MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, SECURE),
+ MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, SECURE),
+ MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, SECURE));
+ } else {
+ /* Legacy firmware accesses the MC directly, though, and so correspondingly we must allow ASIDs to be edited by non-secure world. */
+ reg::Write(MC + MC_SMMU_ASID_SECURITY, 0);
+ }
+
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_1, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_2, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_3, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_4, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_5, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_6, 0);
+ reg::Write(MC + MC_SMMU_ASID_SECURITY_7, 0);
+
+ /* Initialize the PTB registers to zero .*/
+ reg::Write(MC + MC_SMMU_PTB_ASID, 0);
+ reg::Write(MC + MC_SMMU_PTB_DATA, 0);
+
+ /* Configure the TLB and PTC, then read TLB_CONFIG to ensure configuration takes. */
+ reg::Write(MC + MC_SMMU_TLB_CONFIG, MC_REG_BITS_ENUM (SMMU_TLB_CONFIG_TLB_HIT_UNDER_MISS, ENABLE),
+ MC_REG_BITS_ENUM (SMMU_TLB_CONFIG_TLB_ROUND_ROBIN_ARBITRATION, ENABLE),
+ MC_REG_BITS_VALUE(SMMU_TLB_CONFIG_TLB_ACTIVE_LINES, 0x30));
+
+ reg::Write(MC + MC_SMMU_PTC_CONFIG, MC_REG_BITS_ENUM (SMMU_PTC_CONFIG_PTC_CACHE_ENABLE, ENABLE),
+ MC_REG_BITS_VALUE(SMMU_PTC_CONFIG_PTC_REQ_LIMIT, 8),
+ MC_REG_BITS_VALUE(SMMU_PTC_CONFIG_PTC_INDEX_MAP, 0x3F));
+
+ reg::Read (MC + MC_SMMU_TLB_CONFIG);
+
+ /* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
+ reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
+ reg::Read (MC + MC_SMMU_TLB_CONFIG);
+
+ /* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
+ reg::Write(MC + MC_SMMU_TLB_FLUSH, 0);
+ reg::Read (MC + MC_SMMU_TLB_CONFIG);
+
+ /* Enable the SMMU, and read TLB_CONFIG to ensure the enable takes. */
+ reg::Write(MC + MC_SMMU_CONFIG, MC_REG_BITS_ENUM (SMMU_CONFIG_SMMU_ENABLE, ENABLE));
+ reg::Read (MC + MC_SMMU_TLB_CONFIG);
+ }
+
+ void SetupSecureEl2AndEl1SystemRegisters() {
+ /* Setup actlr_el2 and actlr_el3. */
+ {
+ util::BitPack32 actlr = {};
+
+ actlr.Set(1); /* Enable access to cpuactlr from lower EL. */
+ actlr.Set(1); /* Enable access to cpuectlr from lower EL. */
+ actlr.Set(1); /* Enable access to l2ctlr from lower EL. */
+ actlr.Set(1); /* Enable access to l2actlr from lower EL. */
+ actlr.Set(1); /* Enable access to l2ectlr from lower EL. */
+
+ HW_CPU_SET_ACTLR_EL3(actlr);
+ HW_CPU_SET_ACTLR_EL2(actlr);
+ }
+
+ /* Setup hcr_el2. */
+ {
+ util::BitPack64 hcr = {};
+
+ hcr.Set(1); /* EL1 is aarch64 mode. */
+
+ HW_CPU_SET_HCR_EL2(hcr);
+ }
+
+ /* Configure all domain access permissions as manager. */
+ HW_CPU_SET_DACR32_EL2(~0u);
+
+ /* Setup sctlr_el1. */
+ {
+ util::BitPack64 sctlr = { hw::SctlrEl1::Res1 };
+
+ sctlr.Set(0); /* Globally disable the MMU. */
+ sctlr.Set(0); /* Disable alignment fault checking. */
+ sctlr.Set(0); /* Globally disable the data and unified caches. */
+ sctlr.Set(1); /* Enable stack alignment checking. */
+ sctlr.Set(1); /* Enable el0 stack alignment checking. */
+ sctlr.Set(1); /* Enable cp15 barrier operations. */
+ sctlr.Set(0); /* Disable ThumbEE. */
+ sctlr.Set(0); /* Enable itd instructions. */
+ sctlr.Set(0); /* Enable setend instruction. */
+ sctlr.Set(0); /* Disable el0 interrupt mask access. */
+ sctlr.Set(0); /* Globally disable the instruction cache. */
+ sctlr.Set(0); /* Disable el0 access to dc zva instruction. */
+ sctlr.Set(1); /* wfi instructions in el0 trap. */
+ sctlr.Set(1); /* wfe instructions in el0 trap. */
+ sctlr.Set(0); /* Do not force writable pages to be ExecuteNever. */
+ sctlr.Set(0); /* Data accesses in el0 are little endian. */
+ sctlr.Set(0); /* Exceptions should be little endian. */
+ sctlr.Set(0); /* Disable el0 access to dc cvau, dc civac, dc cvac, ic ivau. */
+
+ HW_CPU_SET_SCTLR_EL1(sctlr);
+ }
+
+ /* Setup sctlr_el2. */
+ {
+ util::BitPack64 sctlr = { hw::SctlrEl2::Res1 };
+
+ sctlr.Set(0); /* Globally disable the MMU. */
+ sctlr.Set(0); /* Disable alignment fault checking. */
+ sctlr.Set(0); /* Globally disable the data and unified caches. */
+ sctlr.Set(1); /* Enable stack alignment checking. */
+ sctlr.Set(0); /* Globally disable the instruction cache. */
+ sctlr.Set(0); /* Do not force writable pages to be ExecuteNever. */
+ sctlr.Set(0); /* Exceptions should be little endian. */
+
+ HW_CPU_SET_SCTLR_EL2(sctlr);
+ }
+
+ /* Ensure instruction consistency. */
+ hw::InstructionSynchronizationBarrier();
+ }
+
+ void SetupNonSecureSystemRegisters(u32 tsc_frequency) {
+ /* Set cntfrq_el0. */
+ HW_CPU_SET_CNTFRQ_EL0(tsc_frequency);
+
+ /* Set cnthctl_el2. */
+ {
+ util::BitPack32 cnthctl = {};
+
+ cnthctl.Set(1); /* Do not trap accesses to cntpct_el0. */
+ cnthctl.Set(1); /* Do not trap accesses to cntp_ctl_el0, cntp_cval_el0, and cntp_tval_el0. */
+ cnthctl.Set(0); /* Disable the event stream. */
+ cnthctl.Set(0); /* Trigger events on 0 -> 1 transition. */
+ cnthctl.Set(0); /* Select bit0 of cntpct_el0 as the event stream trigger. */
+
+ HW_CPU_SET_CNTHCTL_EL2(cnthctl);
+ }
+
+ /* Ensure instruction consistency. */
+ hw::InstructionSynchronizationBarrier();
+ }
+
+ void SetupGpuCarveout() {
+ /* Configure carveout 2. */
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM, static_cast(MemoryRegionDramGpuCarveout.GetAddress() >> 0));
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM_HI, static_cast(MemoryRegionDramGpuCarveout.GetAddress() >> BITSIZEOF(u32)));
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_SIZE_128KB, MemoryRegionDramGpuCarveout.GetSize() / 128_KB);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2, MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSRD, ENABLE),
+ MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSWR, ENABLE),
+ MC_REG_BITS_ENUM (CLIENT_ACCESS2_TSECSRD, ENABLE));
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4, MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSRD2, ENABLE),
+ MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSWR2, ENABLE));
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4, 0);
+ reg::Write(MC + MC_SECURITY_CARVEOUT2_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 2),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
+ }
+
+ void DisableArc() {
+ /* Configure IRAM top/bottom to point to memory ends (disabling redirection). */
+ reg::Write(MC + MC_IRAM_BOM, MC_REG_BITS_VALUE(IRAM_BOM_IRAM_BOM, (~0u)));
+ reg::Write(MC + MC_IRAM_TOM, MC_REG_BITS_VALUE(IRAM_TOM_IRAM_TOM, ( 0u)));
+
+ /* Lock the IRAM aperture. */
+ reg::ReadWrite(MC + MC_IRAM_REG_CTRL, MC_REG_BITS_ENUM(IRAM_REG_CTRL_IRAM_CFG_WRITE_ACCESS, DISABLED));
+
+ /* Disable the ARC clock gate override. */
+ reg::ReadWrite(CLK_RST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD, CLK_RST_REG_BITS_ENUM(LVL2_CLK_GATE_OVRD_ARC_CLK_OVR_ON, OFF));
+
+ /* Read IRAM REG CTRL to make sure our writes take. */
+ reg::Read(MC + MC_IRAM_REG_CTRL);
+ }
+
+ void DisableUntranslatedDeviceMemoryAccess() {
+ /* If we can (mariko only), disable GMMU accesses that bypass the SMMU. */
+ /* Additionally, force all untranslated acccesses to hit one of the carveouts. */
+ if (GetSocType() == fuse::SocType_Mariko) {
+ reg::Write(MC + MC_UNTRANSLATED_REGION_CHECK, MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_UNTRANSLATED_REGION_CHECK_ACCESS, DISABLED),
+ MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_REQUIRE_UNTRANSLATED_CLIENTS_HIT_CARVEOUT, ENABLED),
+ MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_REQUIRE_UNTRANSLATED_GPU_HIT_CARVEOUT, ENABLED));
+ }
+ }
+
+ void FinalizeCarveoutSecureScratchRegisters() {
+ /* Define carveout scratch values. */
+ constexpr uintptr_t WarmbootCarveoutAddress = MemoryRegionDram.GetAddress();
+ constexpr size_t WarmbootCarveoutSize = 128_KB;
+
+ #define MC_ENABLE_CLIENT_ACCESS(INDEX, WHICH) MC_REG_BITS_ENUM(CLIENT_ACCESS##INDEX##_##WHICH, ENABLE)
+
+ constexpr u32 WarmbootCarveoutClientAccess0 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(0, AVPCARM7R),
+ MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBSLVR));
+
+ constexpr u32 WarmbootCarveoutClientAccess1 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(1, AVPCARM7W));
+
+ #undef MC_ENABLE_CLIENT_ACCESS
+
+ constexpr u32 WarmbootCarveoutForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE),
+ MC_REG_BITS_ENUM(CLIENT_ACCESS0_PPCSAHBSLVR, ENABLE));
+
+ constexpr u32 WarmbootCarveoutForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE));
+
+ constexpr u32 WarmbootCarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS),
+ MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, UNLOCKED),
+ MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE));
+
+ /* Save the carveout values into secure scratch. */
+
+ /* Save MC_SECURITY_CARVEOUT4_BOM. */
+ reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH51, REG_BITS_VALUE( 0, 15, WarmbootCarveoutAddress >> 17));
+
+ /* Save MC_SECURITY_CARVEOUT4_BOM_HI. */
+ reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH16, REG_BITS_VALUE(30, 2, WarmbootCarveoutAddress >> 32));
+
+ /* Save MC_SECURITY_CARVEOUT4_SIZE_128KB. */
+ reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH55, REG_BITS_VALUE(12, 12, WarmbootCarveoutSize / 128_KB));
+
+ /* Save MC_SECURITY_CARVEOUT4_CLIENT_ACCESS. */
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH74, WarmbootCarveoutClientAccess0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH75, WarmbootCarveoutClientAccess1);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH76, 0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH77, 0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH78, 0);
+
+ /* Save MC_SECURITY_CARVEOUT4_FORCE_INTERNAL_ACCESS. */
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH99, WarmbootCarveoutForceInternalAccess0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH100, WarmbootCarveoutForceInternalAccess1);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH101, 0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH102, 0);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH103, 0);
+
+ /* Save MC_SECURITY_CARVEOUT4_CFG0. */
+ reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH39, REG_BITS_VALUE(0, 27, WarmbootCarveoutConfig));
+ }
+
+ void EnableBpmpSmmu() {
+ /* Define the ASID contents. */
+ constexpr int BpmpAsid = 1;
+ constexpr uintptr_t BpmpAsidPde = MemoryRegionPhysicalDeviceSecurityEngine.GetAddress();
+
+ /* Configure the ASID. */
+ reg::Write(MC + MC_SMMU_PTB_ASID, MC_REG_BITS_VALUE(SMMU_PTB_ASID_CURRENT_ASID, BpmpAsid));
+
+ reg::Write(MC + MC_SMMU_PTB_DATA, MC_REG_BITS_VALUE(SMMU_PTB_DATA_ASID_PDE_BASE, BpmpAsidPde / 4_KB),
+ MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_NONSECURE, DISABLE),
+ MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_WRITABLE, DISABLE),
+ MC_REG_BITS_ENUM (SMMU_PTB_DATA_ASID_READABLE, DISABLE));
+
+ /* Configure the BPMP and PPCS1 to use the asid. */
+ reg::Write(MC + MC_SMMU_AVPC_ASID, MC_REG_BITS_ENUM(SMMU_AVPC_ASID_AVPC_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_AVPC_ASID_AVPC_ASID, BpmpAsid));
+ reg::Write(MC + MC_SMMU_PPCS1_ASID, MC_REG_BITS_ENUM(SMMU_PPCS1_ASID_PPCS1_SMMU_ENABLE, ENABLE), MC_REG_BITS_VALUE(SMMU_PPCS1_ASID_PPCS1_ASID, BpmpAsid));
+
+ /* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */
+ reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0);
+ reg::Read (MC + MC_SMMU_TLB_CONFIG);
+
+ /* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */
+ reg::Write(MC + MC_SMMU_TLB_FLUSH, 0);
+ 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 SetupLogForBoot() {
+ log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate(), secmon::GetLogFlags());
+ log::SendText("OHAYO\n", 6);
+ log::Flush();
+ }
+
+ void LogExitLp0() {
+ /* NOTE: Nintendo only does this on dev, but we will always do it. */
+ if (true /* !pkg1::IsProduction() */) {
+ SetupLogForBoot();
+ }
+ }
+
+ void SetupForLp0Exit() {
+ /* Exit HiZ mode in charger, if we need to. */
+ const auto target_fw = GetTargetFirmware();
+ const bool force_exit_hiz_mode = (target_fw < TargetFirmware_4_0_0) || (target_fw < TargetFirmware_8_0_0 && fuse::GetHardwareType() == fuse::HardwareType_Icosa);
+ if (force_exit_hiz_mode || smc::IsChargerHiZModeEnabled()) {
+ ExitChargerHiZMode();
+ }
+
+ /* Refill the random cache, which is volatile and thus wiped on warmboot. */
+ smc::FillRandomCache();
+
+ /* Unlock the security engine. */
+ secmon::smc::UnlockSecurityEngine();
+ }
+
+ }
+
+ void Setup1() {
+ /* Load the global configuration context. */
+ InitializeConfigurationContext();
+
+ /* Initialize uart for logging. */
+ SetupLogForBoot();
+
+ /* Initialize the security engine. */
+ se::Initialize();
+
+ /* Initialize the gic. */
+ 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));
+ }
+
+ void SetupSocSecurity() {
+ /* Set the fuse visibility. */
+ clkrst::SetFuseVisibility(true);
+
+ /* Set fuses as only secure-writable. */
+ fuse::SetWriteSecureOnly();
+
+ /* Lockout the fuses. */
+ fuse::Lockout();
+
+ /* Set the security engine to secure mode. */
+ se::SetSecure(true);
+
+ /* Verify the security engine's sticky bits. */
+ VerifySecurityEngineStickyBits();
+
+ /* Verify the security engine's Aes slots contain correct contents. */
+ VerifySecurityEngineAesKeySlotTestVector();
+
+ /* Clear aes keyslots. */
+ ClearAesKeySlots();
+
+ /* Clear rsa keyslots. */
+ ClearRsaKeySlots();
+
+ /* Overwrite keys that we want to be random with random contents. */
+ se::InitializeRandom();
+ se::ConfigureAutomaticContextSave();
+ se::SetRandomKey(pkg1::AesKeySlot_Temporary);
+ se::GenerateSrk();
+ se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
+
+ /* Initialize pmc secure scratch. */
+ if (GetSocType() == fuse::SocType_Erista) {
+ pmc::InitializeRandomScratch();
+ }
+ pmc::LockSecureRegister(pmc::SecureRegister_Srk);
+
+ /* Setup secure registers. */
+ SetupSecureRegisters();
+
+ /* Setup the smmu. */
+ SetupSmmu();
+
+ /* Clear the cpu reset vector. */
+ reg::Write(EVP + EVP_CPU_RESET_VECTOR, 0);
+
+ /* Configure the SB registers to our start address. */
+ constexpr u32 ResetVectorLow = static_cast((PhysicalTzramProgramResetVector >> 0));
+ constexpr u32 ResetVectorHigh = static_cast((PhysicalTzramProgramResetVector >> BITSIZEOF(u32)));
+
+ /* Write our reset vector to the secure boot registers. */
+ reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_AA64_RESET_LOW, ResetVectorLow | 1);
+ reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_AA64_RESET_HIGH, ResetVectorHigh);
+
+ /* Disable non-secure writes to the reset vector. */
+ reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_CSR, SB_REG_BITS_ENUM(CSR_NS_RST_VEC_WR_DIS, DISABLE));
+
+ /* Read back SB_CSR to make sure our non-secure write disable takes. */
+ reg::Read(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_CSR);
+
+ /* Write our reset vector to scratch registers used by warmboot, and lock those scratch registers. */
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH34, ResetVectorLow);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH35, ResetVectorHigh);
+ pmc::LockSecureRegister(pmc::SecureRegister_ResetVector);
+
+ /* Setup the security engine interrupt. */
+ constexpr int SecurityEngineInterruptId = 90;
+ constexpr u8 SecurityEngineInterruptCoreMask = (1 << 3);
+ gic::SetPriority (SecurityEngineInterruptId, gic::HighestPriority);
+ gic::SetInterruptGroup(SecurityEngineInterruptId, 0);
+ gic::SetEnable (SecurityEngineInterruptId, true);
+ gic::SetSpiTargetCpu (SecurityEngineInterruptId, SecurityEngineInterruptCoreMask);
+ gic::SetSpiMode (SecurityEngineInterruptId, gic::InterruptMode_Level);
+
+ /* Setup the activity monitor interrupt. */
+ constexpr int ActivityMonitorInterruptId = 77;
+ constexpr u8 ActivityMonitorInterruptCoreMask = (1 << 3);
+ gic::SetPriority (ActivityMonitorInterruptId, gic::HighestPriority);
+ gic::SetInterruptGroup(ActivityMonitorInterruptId, 0);
+ gic::SetEnable (ActivityMonitorInterruptId, true);
+ gic::SetSpiTargetCpu (ActivityMonitorInterruptId, ActivityMonitorInterruptCoreMask);
+ gic::SetSpiMode (ActivityMonitorInterruptId, gic::InterruptMode_Level);
+
+ /* Setup the mariko fatal error interrupt. */
+ constexpr u8 MarikoFatalInterruptCoreMask = 0b1111;
+ gic::SetPriority (MarikoFatalErrorInterruptId, gic::HighestPriority);
+ gic::SetInterruptGroup(MarikoFatalErrorInterruptId, 0);
+ gic::SetEnable (MarikoFatalErrorInterruptId, true);
+ gic::SetSpiTargetCpu (MarikoFatalErrorInterruptId, 0);
+ gic::SetSpiMode (MarikoFatalErrorInterruptId, gic::InterruptMode_Level);
+
+ /* If we're coldboot, perform one-time setup. */
+ if (g_is_cold_boot) {
+ /* Register all interrupt handlers. */
+ SetInterruptHandler(SecurityEngineInterruptId, SecurityEngineInterruptCoreMask, se::HandleInterrupt);
+ SetInterruptHandler(ActivityMonitorInterruptId, ActivityMonitorInterruptCoreMask, actmon::HandleInterrupt);
+ SetInterruptHandler(MarikoFatalErrorInterruptId, MarikoFatalInterruptCoreMask, secmon::HandleMarikoFatalErrorInterrupt);
+
+ /* We're expecting the other cores to come out of reset. */
+ for (int i = 1; i < NumCores; ++i) {
+ SetResetExpected(i, true);
+ }
+
+ /* We only coldboot once. */
+ g_is_cold_boot = false;
+ }
+ }
+
+ 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();
+
+ /* Generate a random srk. */
+ se::GenerateSrk();
+
+ /* 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() {
+ /* Setup the GPU carveout. */
+ SetupGpuCarveout();
+
+ /* Configure the two kernel carveouts. */
+ SetupKernelCarveouts();
+
+ /* Disable the ARC. */
+ DisableArc();
+
+ /* Disable untranslated memory accesses by devices. */
+ DisableUntranslatedDeviceMemoryAccess();
+
+ /* Further protections aren't applied on <= 1.0.0. */
+ if (GetTargetFirmware() <= TargetFirmware_1_0_0) {
+ return;
+ }
+
+ /* Finalize and lock the carveout scratch registers. */
+ FinalizeCarveoutSecureScratchRegisters();
+ pmc::LockSecureRegister(pmc::SecureRegister_Carveout);
+
+ /* Clear all the BPMP exception vectors to a fixed value. */
+ constexpr u32 BpmpExceptionVector = 0x7D000000;
+ reg::Write(EVP + EVP_COP_RESET_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_UNDEF_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_SWI_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_PREFETCH_ABORT_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_DATA_ABORT_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_RSVD_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_IRQ_VECTOR, BpmpExceptionVector);
+ reg::Write(EVP + EVP_COP_FIQ_VECTOR, BpmpExceptionVector);
+
+ /* Disable arbitration for the bpmp. */
+ reg::ReadWrite(SYSTEM + AHB_ARBITRATION_DISABLE, AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_COP, DISABLE));
+
+ /* Turn on the SMMU for the BPMP. */
+ EnableBpmpSmmu();
+
+ /* Wait until the flow controller reports that the BPMP is halted. */
+ while (!reg::HasValue(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP))) {
+ util::WaitMicroSeconds(1);
+ }
+
+ /* Enable clock to the activity monitor. */
+ clkrst::EnableActmonClock();
+
+ /* If JTAG is disabled, disable JTAG. */
+ if (!secmon::IsJtagEnabled()) {
+ reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
+ FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_JTAG, DISABLED));
+
+ /* Turn on the activity monitor to prevent booting up the bpmp. */
+ actmon::StartMonitoringBpmp(ActmonInterruptHandler);
+ }
+ }
+
+ void SetupPmcAndMcSecure() {
+ // const auto target_fw = GetTargetFirmware();
+
+ // if (target_fw >= TargetFirmware_2_0_0) {
+ // /* Set the PMC secure. */ I REFUSE
+ // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE));
+ // }
+
+ // if (target_fw >= TargetFirmware_4_0_0) {
+ // /* Set the MC secure. */ I REFUSE
+ // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE),
+ // SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE),
+ // SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE));
+ // }
+ return;
+ }
+
+ void SetupCpuCoreContext() {
+ /* Get the tsc frequency. */
+ const u32 tsc_frequency = reg::Read(MemoryRegionVirtualDeviceSysCtr0.GetAddress() + SYSCTR0_CNTFID0);
+
+ /* Setup the secure EL2/EL1 system registers. */
+ SetupSecureEl2AndEl1SystemRegisters();
+
+ /* Setup the non-secure system registers. */
+ SetupNonSecureSystemRegisters(tsc_frequency);
+
+ /* Reset the cpu flow controller registers. */
+ flow::ResetCpuRegisters(hw::GetCurrentCoreId());
+
+ /* Initialize the core unique gic registers. */
+ gic::InitializeCoreUnique();
+
+ /* Configure cpu fiq. */
+ constexpr int FiqInterruptId = 28;
+ gic::SetPriority (FiqInterruptId, gic::HighestPriority);
+ gic::SetInterruptGroup(FiqInterruptId, 0);
+ gic::SetEnable (FiqInterruptId, true);
+
+ /* Restore the cpu's debug registers. */
+ RestoreDebugRegisters();
+ }
+
+ void SetupCpuSErrorDebug() {
+ /* Get whether we should enable SError debug. */
+ const auto &bc_data = secmon::GetBootConfig().data;
+ const bool enabled = bc_data.IsDevelopmentFunctionEnabled() && bc_data.IsSErrorDebugEnabled();
+
+ /* Get and set scr_el3. */
+ {
+ util::BitPack32 scr;
+ HW_CPU_GET_SCR_EL3(scr);
+
+ scr.Set(enabled ? 0 : 1);
+ HW_CPU_SET_SCR_EL3(scr);
+ }
+
+ /* Prevent reordering instructions around this call. */
+ hw::InstructionSynchronizationBarrier();
+ }
+
+ void SetKernelCarveoutRegion(int index, uintptr_t address, size_t size) {
+ /* Configure the carveout. */
+ auto &carveout = g_kernel_carveouts[index];
+ carveout.address = address;
+ carveout.size = size;
+
+ SetupKernelCarveouts();
+ }
+
+}
\ No newline at end of file
diff --git a/Source/Atmosphere-Patches/secmon_smc_power_management.cpp b/Source/Atmosphere-Patches/secmon_smc_power_management.cpp
new file mode 100644
index 00000000..4d2214da
--- /dev/null
+++ b/Source/Atmosphere-Patches/secmon_smc_power_management.cpp
@@ -0,0 +1,571 @@
+/*
+ * Copyright (c) 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 .
+ */
+#include
+#include "../secmon_cache.hpp"
+#include "../secmon_cpu_context.hpp"
+#include "../secmon_error.hpp"
+#include "../secmon_misc.hpp"
+#include "secmon_smc_power_management.hpp"
+#include "secmon_smc_se_lock.hpp"
+
+#include "sc7fw_bin.h"
+
+namespace ams::secmon {
+
+ /* Declare assembly functionality. */
+ void *GetCoreExceptionStackVirtual();
+
+}
+
+namespace ams::secmon::smc {
+
+ /* Declare assembly power-management functionality. */
+ void PivotStackAndInvoke(void *stack, void (*function)());
+ void FinalizePowerOff();
+
+ namespace {
+
+ constexpr inline const uintptr_t PMC = MemoryRegionVirtualDevicePmc.GetAddress();
+ constexpr inline const uintptr_t APB_MISC = MemoryRegionVirtualDeviceApbMisc.GetAddress();
+ constexpr inline const uintptr_t GPIO = MemoryRegionVirtualDeviceGpio.GetAddress();
+ constexpr inline const uintptr_t CLK_RST = MemoryRegionVirtualDeviceClkRst.GetAddress();
+ constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress();
+ constexpr inline const uintptr_t FLOW_CTLR = MemoryRegionVirtualDeviceFlowController.GetAddress();
+ constexpr inline const uintptr_t AHB_ARBC = MemoryRegionVirtualDeviceSystem.GetAddress();
+
+ constexpr inline uintptr_t CommonSmcStackTop = MemoryRegionVirtualTzramVolatileData.GetEndAddress() - (0x80 * (NumCores - 1));
+
+ enum PowerStateType {
+ PowerStateType_StandBy = 0,
+ PowerStateType_PowerDown = 1,
+ };
+
+ enum PowerStateId {
+ PowerStateId_Sc7 = 27,
+ };
+
+ /* http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf Page 46 */
+ struct SuspendCpuPowerState {
+ using StateId = util::BitPack32::Field< 0, 16, PowerStateId>;
+ using StateType = util::BitPack32::Field<16, 1, PowerStateType>;
+ using PowerLevel = util::BitPack32::Field<24, 2, u32>;
+ };
+
+ constinit bool g_charger_hi_z_mode_enabled = false;
+
+ constinit const reg::BitsMask CpuPowerGateStatusMasks[NumCores] = {
+ PMC_REG_BITS_MASK(PWRGATE_STATUS_CE0),
+ PMC_REG_BITS_MASK(PWRGATE_STATUS_CE1),
+ PMC_REG_BITS_MASK(PWRGATE_STATUS_CE2),
+ PMC_REG_BITS_MASK(PWRGATE_STATUS_CE3),
+ };
+
+ constinit const APBDEV_PMC_PWRGATE_TOGGLE_PARTID CpuPowerGateTogglePartitionIds[NumCores] = {
+ APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE0,
+ APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE1,
+ APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE2,
+ APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE3,
+ };
+
+ bool IsCpuPoweredOn(const reg::BitsMask mask) {
+ return reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, REG_BITS_VALUE_FROM_MASK(mask, APBDEV_PMC_PWRGATE_STATUS_STATUS_ON));
+ }
+
+ void PowerOnCpu(const reg::BitsMask mask, u32 toggle_partid) {
+ /* If the cpu is already on, we have nothing to do. */
+ if (IsCpuPoweredOn(mask)) {
+ return;
+ }
+
+ /* Wait until nothing is being powergated. */
+ int timeout = 5000;
+ while (true) {
+ if (reg::HasValue(PMC + APBDEV_PMC_PWRGATE_TOGGLE, PMC_REG_BITS_ENUM(PWRGATE_TOGGLE_START, DISABLE))) {
+ break;
+ }
+
+ util::WaitMicroSeconds(1);
+ if ((--timeout) < 0) {
+ /* NOTE: Nintendo doesn't do any error handling here... */
+ return;
+ }
+ }
+
+ /* Toggle on the cpu partition. */
+ reg::Write(PMC + APBDEV_PMC_PWRGATE_TOGGLE, PMC_REG_BITS_ENUM (PWRGATE_TOGGLE_START, ENABLE),
+ PMC_REG_BITS_VALUE(PWRGATE_TOGGLE_PARTID, toggle_partid));
+
+ /* Wait up to 5000 us for the powergate to complete. */
+ timeout = 5000;
+ while (true) {
+ if (IsCpuPoweredOn(mask)) {
+ break;
+ }
+
+ util::WaitMicroSeconds(1);
+ if ((--timeout) < 0) {
+ /* NOTE: Nintendo doesn't do any error handling here... */
+ return;
+ }
+ }
+ }
+
+ void ResetCpu(int which_core) {
+ reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET, REG_BITS_VALUE(which_core + 0x00, 1, 1), /* CPURESETn */
+ REG_BITS_VALUE(which_core + 0x10, 1, 1)); /* CORERESETn */
+ }
+
+ void StartCpu(int which_core) {
+ reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR, REG_BITS_VALUE(which_core + 0x00, 1, 1), /* CPURESETn */
+ REG_BITS_VALUE(which_core + 0x10, 1, 1)); /* CORERESETn */
+ }
+
+ void PowerOffCpuImpl() {
+ /* Get the current core id. */
+ const auto core_id = hw::GetCurrentCoreId();
+
+ /* Configure the flow controller to prepare for shutting down the current core. */
+ flow::SetCpuCsr(core_id, FLOW_CTLR_CPUN_CSR_ENABLE_EXT_POWERGATE_CPU_ONLY);
+ flow::SetHaltCpuEvents(core_id, false);
+ flow::SetCc4Ctrl(core_id, 0);
+
+ /* Save the core's context for restoration on next power-on. */
+ SaveDebugRegisters();
+ SetCoreOff();
+
+ /* Ensure there are no pending memory transactions prior to our power-down. */
+ FlushEntireDataCache();
+
+ /* Finalize our powerdown and wait for an interrupt. */
+ FinalizePowerOff();
+ }
+
+ void ValidateSocStateForSuspend() {
+ /* Validate that all other cores are off. */
+ AMS_ABORT_UNLESS(reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, PMC_REG_BITS_VALUE(PWRGATE_STATUS_CE123, 0)));
+
+ /* Horizon-OC: Halt BPMP here as hoc-clk may be running it, and if it's running there will be a panic. */
+ const bool jtag = IsJtagEnabled();
+ reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
+ FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, jtag, ENABLED, DISABLED));
+
+ /* Validate that the bpmp is appropriately halted. */
+ AMS_ABORT_UNLESS(reg::Read(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS) == reg::Encode(FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP),
+ FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, jtag, ENABLED, DISABLED)));
+
+ /* Further validations aren't guaranteed on < 6.0.0. */
+ if (GetTargetFirmware() < TargetFirmware_6_0_0) {
+ return;
+ }
+
+ /* Validate that USB2, APB-DMA, AHB-DMA are held in reset. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_USB2_RST, ENABLE),
+ CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_APBDMA_RST, ENABLE),
+ CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_AHBDMA_RST, ENABLE)));
+
+ /* Validate that USBD is held in reset. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_REG_BITS_ENUM(RST_DEVICES_L_SWR_USBD_RST, ENABLE)));
+
+ /* Validate that AHB-DMA, USB, USB2, COP are not allowed to arbitrate on the AHB. */
+ AMS_ABORT_UNLESS(reg::HasValue(AHB_ARBC + AHB_ARBITRATION_DISABLE, AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_COP, DISABLE),
+ AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_AHBDMA, DISABLE),
+ AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB, DISABLE),
+ AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB2, DISABLE)));
+
+ /* Validate that the GPIO controller has clock enabled. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_L_CLK_ENB_GPIO, ENABLE)));
+
+ /* Validate that both FUSE and KFUSE have clock enabled. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_FUSE, ENABLE),
+ CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_KFUSE, ENABLE)));
+
+ /* Validate that all of IRAM has clock enabled. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMA, ENABLE),
+ CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMB, ENABLE),
+ CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMC, ENABLE),
+ CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMD, ENABLE)));
+
+ /* Validate that ACTMON has clock enabled. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_V_CLK_ENB_ACTMON, ENABLE)));
+
+ /* Validate that ENTROPY has clock enabled. */
+ AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_W_CLK_ENB_ENTROPY, ENABLE)));
+ }
+
+ void GenerateCryptographicallyRandomBytes(void * const dst, int size) {
+ /* Flush the region we're about to fill to ensure consistency with the SE. */
+ hw::FlushDataCache(dst, size);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Generate random bytes. */
+ se::GenerateRandomBytes(dst, size);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Flush to ensure the CPU sees consistent data for the region. */
+ hw::FlushDataCache(dst, size);
+ hw::DataSynchronizationBarrierInnerShareable();
+ }
+
+ void SaveSecureContextForErista() {
+ /* Generate a random key source. */
+ util::AlignedBuffer key_source;
+ GenerateCryptographicallyRandomBytes(key_source, se::AesBlockSize);
+
+ const u32 * const key_source_32 = reinterpret_cast(static_cast(key_source));
+
+ /* Ensure that the key source registers are not locked. */
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceReadWrite) != pmc::LockState::Locked);
+
+ /* Write the key source, lock writes to the key source, and verify that the key source is write-locked. */
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH24, key_source_32[0]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH25, key_source_32[1]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH26, key_source_32[2]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH27, key_source_32[3]);
+ pmc::LockSecureRegister(pmc::SecureRegister_KeySourceWrite);
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceWrite) == pmc::LockState::Locked);
+
+ /* Verify the key source is correct in registers, and read-lock the key source registers. */
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH24) == key_source_32[0]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH25) == key_source_32[1]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH26) == key_source_32[2]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH27) == key_source_32[3]);
+ pmc::LockSecureRegister(pmc::SecureRegister_KeySourceRead);
+
+ /* Ensure that the key source registers are locked. */
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceReadWrite) == pmc::LockState::Locked);
+
+ /* Generate a random kek into keyslot 2. */
+ se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek);
+
+ /* Verify that the se is in a validate state, context save, and validate again. */
+ {
+ se::ValidateErrStatus();
+ ON_SCOPE_EXIT { se::ValidateErrStatus(); };
+
+ {
+ /* Transition to non-secure mode for the duration of the context save operation. */
+ se::SetSecure(false);
+ ON_SCOPE_EXIT { se::SetSecure(true); };
+
+ /* Get a pointer to the context storage. */
+ se::Context * const context = MemoryRegionVirtualDramSecureDataStoreSecurityEngineState.GetPointer();
+ static_assert(MemoryRegionVirtualDramSecureDataStoreSecurityEngineState.GetSize() == sizeof(*context));
+
+ /* Save the context. */
+ se::SaveContext(context);
+
+ /* Ensure that the cpu sees consistent data. */
+ hw::FlushDataCache(context, sizeof(*context));
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Write the context pointer to pmc scratch, so that the bootrom will restore it on wake. */
+ reg::Write(PMC + APBDEV_PMC_SCRATCH43, MemoryRegionPhysicalDramSecureDataStoreSecurityEngineState.GetAddress());
+ }
+ }
+
+ /* Clear keyslot 3, and then derive the save key. */
+ se::ClearAesKeySlot(pkg1::AesKeySlot_TzramSaveKey);
+ se::SetEncryptedAesKey256(pkg1::AesKeySlot_TzramSaveKey, pkg1::AesKeySlot_TzramSaveKek, key_source, se::AesBlockSize);
+
+ /* Declare a temporary block to be used as both iv and mac. */
+ u32 temp_block[se::AesBlockSize / sizeof(u32)] = {};
+
+ /* Ensure that the SE sees consistent data for tzram. */
+ const void * const tzram_save_src = MemoryRegionVirtualTzramReadOnlyAlias.GetPointer() + MemoryRegionVirtualTzramVolatileData.GetSize() + MemoryRegionVirtualTzramVolatileStack.GetSize();
+ void * const tzram_save_dst = MemoryRegionVirtualIramSc7Work.GetPointer();
+ constexpr size_t TzramSaveSize = MemoryRegionVirtualDramSecureDataStoreTzram.GetSize();
+
+ hw::FlushDataCache(tzram_save_src, TzramSaveSize);
+ hw::FlushDataCache(tzram_save_dst, TzramSaveSize);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Encrypt tzram using our random key. */
+ se::EncryptAes256Cbc(tzram_save_dst, TzramSaveSize, pkg1::AesKeySlot_TzramSaveKey, tzram_save_src, TzramSaveSize, temp_block, se::AesBlockSize);
+ hw::FlushDataCache(tzram_save_dst, TzramSaveSize);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Copy the data from work space to the secure storage destination. */
+ void * const tzram_store_dst = MemoryRegionVirtualDramSecureDataStoreTzram.GetPointer();
+ std::memcpy(tzram_store_dst, tzram_save_dst, TzramSaveSize);
+ hw::FlushDataCache(tzram_store_dst, TzramSaveSize);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Compute cmac of tzram into our temporary block. */
+ se::ComputeAes256Cmac(temp_block, se::AesBlockSize, pkg1::AesKeySlot_TzramSaveKey, tzram_save_src, TzramSaveSize);
+
+ /* Ensure that the cmac registers are not locked. */
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacReadWrite) != pmc::LockState::Locked);
+
+ /* Write the cmac, lock writes to the cmac, and verify that the cmac is write-locked. */
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH112, temp_block[0]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH113, temp_block[1]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH114, temp_block[2]);
+ reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH115, temp_block[3]);
+ pmc::LockSecureRegister(pmc::SecureRegister_CmacWrite);
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacWrite) == pmc::LockState::Locked);
+
+ /* Verify the key source is correct in registers, and read-lock the key source registers. */
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH112) == temp_block[0]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH113) == temp_block[1]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH114) == temp_block[2]);
+ AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH115) == temp_block[3]);
+ pmc::LockSecureRegister(pmc::SecureRegister_CmacRead);
+
+ /* Ensure that the key source registers are locked. */
+ AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacReadWrite) == pmc::LockState::Locked);
+ }
+
+ void SaveSecureContextForMariko() {
+ /* Save security engine context to TZRAM SE carveout (inaccessible to cpu). */
+ se::SaveContextAutomatic();
+
+ /* Save TZRAM to shadow-TZRAM in always-on power domain. */
+ se::SaveTzramAutomatic();
+ }
+
+ void SaveSecureContext() {
+ /* Save the appropriate secure context. */
+ const auto soc_type = GetSocType();
+ if (soc_type == fuse::SocType_Erista) {
+ SaveSecureContextForErista();
+ } else /* if (soc_type == fuse::SocType_Mariko) */ {
+ SaveSecureContextForMariko();
+ }
+
+ /* Save the debug code. */
+ #if defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING)
+ {
+ const void * const debug_code_src = MemoryRegionVirtualDebugCode.GetPointer();
+ void * const debug_code_dst = MemoryRegionVirtualDramDebugDataStore.GetPointer();
+ std::memcpy(debug_code_dst, debug_code_src, MemoryRegionVirtualDebugCode.GetSize());
+ hw::FlushDataCache(debug_code_dst, MemoryRegionVirtualDebugCode.GetSize());
+ hw::DataSynchronizationBarrierInnerShareable();
+ }
+ #endif
+ }
+
+ void LoadAndStartSc7BpmpFirmware() {
+ /* Set BPMP reset. */
+ reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_COP_RST, ENABLE));
+
+ /* Set the PMC as insecure, so that the BPMP firmware can access it. */
+ reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, DISABLE));
+
+ /* Set the exception vectors for the bpmp. RESET should point to RESET, all others should point to generic exception/panic. */
+ constexpr const u32 Sc7FirmwareResetVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x0);
+ constexpr const u32 Sc7FirmwarePanicVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x4);
+
+ reg::Write(EVP + EVP_COP_RESET_VECTOR, Sc7FirmwareResetVector);
+ reg::Write(EVP + EVP_COP_UNDEF_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_SWI_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_PREFETCH_ABORT_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_DATA_ABORT_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_RSVD_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_IRQ_VECTOR, Sc7FirmwarePanicVector);
+ reg::Write(EVP + EVP_COP_FIQ_VECTOR, Sc7FirmwarePanicVector);
+
+ /* Disable activity monitor bpmp monitoring, so that we don't panic upon bpmp wake. */
+ actmon::StopMonitoringBpmp();
+
+ /* Load the bpmp firmware. */
+ void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer();
+ std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size);
+ hw::FlushDataCache(sc7fw_load_address, sc7fw_bin_size);
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Ensure that the bpmp firmware was loaded. */
+ AMS_ABORT_UNLESS(crypto::IsSameBytes(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size));
+
+ /* Clear BPMP reset. */
+ reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_COP_RST, ENABLE));
+
+ /* Start the bpmp. */
+ reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_NONE));
+ }
+
+ void SaveSecureContextAndSuspend() {
+ /* Ensure there are no pending memory transactions before we continue */
+ FlushEntireDataCache();
+ hw::DataSynchronizationBarrierInnerShareable();
+
+ /* Save all secure context (security engine state + tzram). */
+ SaveSecureContext();
+
+ /* Load and start the sc7 firmware on the bpmp. */
+ if (GetTargetFirmware() >= TargetFirmware_2_0_0) {
+ LoadAndStartSc7BpmpFirmware();
+ }
+
+ /* Log our suspension. */
+ /* NOTE: Nintendo only does this on dev, but we will always do it. */
+ if (true /* !pkg1::IsProduction() */) {
+ log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate(), secmon::GetLogFlags());
+ log::SendText("OYASUMI\n", 8);
+ log::Flush();
+ }
+
+ /* If we're on erista, configure the bootrom to allow our custom warmboot firmware. */
+ if (GetSocType() == fuse::SocType_Erista) {
+ reg::Write(PMC + APBDEV_PMC_SCRATCH31, 0x2202E012);
+ reg::Write(PMC + APBDEV_PMC_SCRATCH32, 0x6001DC28);
+ }
+
+ /* Finalize our powerdown and wait for an interrupt. */
+ FinalizePowerOff();
+ }
+
+ SmcResult SuspendCpuImpl(SmcArguments &args) {
+ /* Decode arguments. */
+ const util::BitPack32 power_state = { static_cast(args.r[1]) };
+ const uintptr_t entry_point = args.r[2];
+ const uintptr_t context_id = args.r[3];
+
+ const auto state_type = power_state.Get();
+ const auto state_id = power_state.Get();
+
+ const auto core_id = hw::GetCurrentCoreId();
+
+ /* Validate arguments. */
+ SMC_R_UNLESS(state_type == PowerStateType_PowerDown, PsciDenied);
+ SMC_R_UNLESS(state_id == PowerStateId_Sc7, PsciDenied);
+
+ /* Orchestrate charger transition to Hi-Z mode if needed. */
+ if (IsChargerHiZModeEnabled()) {
+ /* Ensure we can do comms over i2c-1. */
+ clkrst::EnableI2c1Clock();
+
+ /* If the charger isn't in hi-z mode, perform a transition. */
+ if (!charger::IsHiZMode()) {
+ charger::EnterHiZMode();
+
+ /* Wait up to 50ms for the transition to complete. */
+ const auto start_time = util::GetMicroSeconds();
+ auto current_time = start_time;
+ while ((current_time - start_time) <= 50'000) {
+ if (auto intr_status = reg::Read(GPIO + 0x634); (intr_status & 1) == 0) {
+ /* Wait 256 us to ensure the transition completes. */
+ util::WaitMicroSeconds(256);
+ break;
+ }
+ current_time = util::GetMicroSeconds();
+ }
+ }
+
+ /* Disable i2c-1, since we're done communicating over it. */
+ clkrst::DisableI2c1Clock();
+ }
+
+ /* Enable wake event detection. */
+ pmc::EnableWakeEventDetection();
+
+ /* Ensure that i2c-5 is usable for communicating with the pmic. */
+ clkrst::EnableI2c5Clock();
+ i2c::Initialize(i2c::Port_5);
+
+ /* Orchestrate sleep entry with the pmic. */
+ pmic::EnableSleep();
+
+ /* Ensure that the soc is in a state valid for us to suspend. */
+ if (GetTargetFirmware() >= TargetFirmware_2_0_0) {
+ ValidateSocStateForSuspend();
+ }
+
+ /* Configure the pmc for sc7 entry. */
+ pmc::ConfigureForSc7Entry();
+
+ /* Configure the flow controller for sc7 entry. */
+ flow::SetCc4Ctrl(core_id, 0);
+ flow::SetHaltCpuEvents(core_id, false);
+ flow::ClearL2FlushControl();
+ flow::SetCpuCsr(core_id, FLOW_CTLR_CPUN_CSR_ENABLE_EXT_POWERGATE_CPU_TURNOFF_CPURAIL);
+
+ /* Save the entry context. */
+ SetEntryContext(core_id, entry_point, context_id);
+
+ /* Configure the cpu context for reset. */
+ SaveDebugRegisters();
+ SetCoreOff();
+ SetResetExpected(true);
+
+ /* Switch to use the common smc stack (all other cores are off), and perform suspension. */
+ PivotStackAndInvoke(reinterpret_cast(CommonSmcStackTop), SaveSecureContextAndSuspend);
+
+ /* This code will never be reached. */
+ __builtin_unreachable();
+ }
+
+ }
+
+ void PowerOffCpu() {
+ /* Get the current core id. */
+ const auto core_id = hw::GetCurrentCoreId();
+
+ /* Note that we're expecting a reset for the current core. */
+ SetResetExpected(true);
+
+ /* If we're on the final core, shut down directly. Otherwise, invoke with special stack. */
+ if (core_id == NumCores - 1) {
+ PowerOffCpuImpl();
+ } else {
+ PivotStackAndInvoke(GetCoreExceptionStackVirtual(), PowerOffCpuImpl);
+ }
+
+ /* This code will never be reached. */
+ __builtin_unreachable();
+ }
+
+ SmcResult SmcPowerOffCpu(SmcArguments &args) {
+ AMS_UNUSED(args);
+
+ PowerOffCpu();
+ }
+
+ SmcResult SmcPowerOnCpu(SmcArguments &args) {
+ /* Get and validate the core to power on. */
+ const int which_core = args.r[1];
+ SMC_R_UNLESS(0 <= which_core && which_core < NumCores, PsciInvalidParameters);
+
+ /* Ensure the core isn't already on. */
+ SMC_R_UNLESS(!IsCoreOn(which_core), PsciAlreadyOn);
+
+ /* Save the entry context. */
+ SetEntryContext(which_core, args.r[2], args.r[3]);
+
+ /* Reset the cpu. */
+ ResetCpu(which_core);
+
+ /* Turn on the core. */
+ PowerOnCpu(CpuPowerGateStatusMasks[which_core], CpuPowerGateTogglePartitionIds[which_core]);
+
+ /* Start the core. */
+ StartCpu(which_core);
+
+ return SmcResult::PsciSuccess;
+ }
+
+ SmcResult SmcSuspendCpu(SmcArguments &args) {
+ return LockSecurityEngineAndInvoke(args, SuspendCpuImpl);
+ }
+
+ bool IsChargerHiZModeEnabled() {
+ return g_charger_hi_z_mode_enabled;
+ }
+
+ void SetChargerHiZModeEnabled(bool en) {
+ g_charger_hi_z_mode_enabled = en;
+ }
+
+}
diff --git a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
index 88757041..36932196 100644
--- a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
+++ b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp
@@ -99,16 +99,23 @@ namespace ams::secmon::smc {
#include "secmon_define_pmc_access_table.inc"
#include "secmon_define_mc_access_table.inc"
#include "secmon_define_emc_access_table.inc"
+ #include "secmon_define_emc01_access_table.inc"
+ #include "secmon_define_flow_controller_access_table.inc"
+ #include "secmon_define_exception_vectors_access_table.inc"
#include "secmon_define_rtc_pmc_access_table.inc"
#include "secmon_define_mc01_access_table.inc"
constexpr const AccessTableEntry AccessTables[] = {
- { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
- { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
- { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
- { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
- { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
- { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
+ { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
+ { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
+ { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
+ { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, },
+ { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, },
+ { FlowControllerAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceFlowController.GetAddress(), FlowControllerAccessTable::Address, FlowControllerAccessTable::Size, },
+ { ExceptionVectorsAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExceptionVectors.GetAddress(), ExceptionVectorsAccessTable::Address, ExceptionVectorsAccessTable::Size, },
+ { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
+ { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
+ { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
};
constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) {
@@ -170,12 +177,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/build.sh b/build.sh
index 3eb311aa..5d133558 100644
--- a/build.sh
+++ b/build.sh
@@ -76,13 +76,21 @@ if [ "$NO_EXO" -eq 0 ]; then
EXO_DEST="build/atmosphere/exosphere/program/source/smc"
LIBEXO_DEST="build/atmosphere/libraries/libexosphere/include/exosphere/secmon"
- cp -v "$EXO_SRC/secmon_emc_access_table_data.inc" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_define_emc_access_table.inc" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_rtc_pmc_access_table_data.inc" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_define_rtc_pmc_access_table.inc" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_smc_register_access.cpp" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_smc_handler.cpp" "$EXO_DEST/"
- cp -v "$EXO_SRC/secmon_memory_layout.hpp" "$LIBEXO_DEST/"
+ cp -v "$EXO_SRC/secmon_setup.cpp" "$EXO_PROGRAM_DEST/"
+ cp -v "$EXO_SRC/secmon_define_emc_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_emc_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_define_emc01_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_emc01_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_define_rtc_pmc_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_rtc_pmc_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_define_flow_controller_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_flow_controller_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_define_exception_vectors_access_table.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_exception_vectors_access_table_data.inc" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_smc_register_access.cpp" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_smc_handler.cpp" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_smc_power_management.cpp" "$EXO_DEST/"
+ cp -v "$EXO_SRC/secmon_memory_layout.hpp" "$LIBEXO_DEST/"
fi
echo