From 151d8584e44cea8378dd414e2ef81a19485e5d8c Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Thu, 10 Sep 2026 19:04:20 -0400 Subject: [PATCH] update exosphere patch --- Source/Atmosphere-Patches/diff/README.MD | 1 + .../diff/secmon_memory_layout.diff | 57 + .../Atmosphere-Patches/diff/secmon_setup.diff | 29 + .../diff/secmon_smc_handler.diff | 2 + .../diff/secmon_smc_power_management.diff | 9 + .../diff/secmon_smc_register_access.diff | 22 + .../secmon_define_emc01_access_table.inc | 25 + ..._define_exception_vectors_access_table.inc | 25 + ...on_define_flow_controller_access_table.inc | 25 + .../secmon_emc01_access_table_data.inc | 1040 +++++++++++++ ...on_exception_vectors_access_table_data.inc | 1040 +++++++++++++ ...cmon_flow_controller_access_table_data.inc | 1040 +++++++++++++ .../secmon_memory_layout.hpp | 4 +- Source/Atmosphere-Patches/secmon_setup.cpp | 1290 +++++++++++++++++ .../secmon_smc_power_management.cpp | 571 ++++++++ .../secmon_smc_register_access.cpp | 27 +- build.sh | 22 +- 17 files changed, 5211 insertions(+), 18 deletions(-) create mode 100644 Source/Atmosphere-Patches/diff/README.MD create mode 100644 Source/Atmosphere-Patches/diff/secmon_memory_layout.diff create mode 100644 Source/Atmosphere-Patches/diff/secmon_setup.diff create mode 100644 Source/Atmosphere-Patches/diff/secmon_smc_handler.diff create mode 100644 Source/Atmosphere-Patches/diff/secmon_smc_power_management.diff create mode 100644 Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff create mode 100644 Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc create mode 100644 Source/Atmosphere-Patches/secmon_define_exception_vectors_access_table.inc create mode 100644 Source/Atmosphere-Patches/secmon_define_flow_controller_access_table.inc create mode 100644 Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc create mode 100644 Source/Atmosphere-Patches/secmon_exception_vectors_access_table_data.inc create mode 100644 Source/Atmosphere-Patches/secmon_flow_controller_access_table_data.inc create mode 100644 Source/Atmosphere-Patches/secmon_setup.cpp create mode 100644 Source/Atmosphere-Patches/secmon_smc_power_management.cpp 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