diff --git a/source/common/cache.h b/source/common/cache.h new file mode 100644 index 0000000..92257a5 --- /dev/null +++ b/source/common/cache.h @@ -0,0 +1,43 @@ +/* +* This file is part of Luma3DS +* Copyright (C) 2016-2017 Aurora Wright, TuxSH +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that 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 . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#pragma once + +#include "common.h" + +/*** + The following functions flush the data cache, then waits for all memory transfers to be finished. + The data cache and/or the instruction cache MUST be flushed before doing one of the following: + - rebooting + - powering down + - setting the ARM11 entrypoint to execute a function + - jumping to a payload +***/ + +void flushEntireDCache(void); //actually: "clean and flush" +void flushDCacheRange(void *startAddress, u32 size); +void flushEntireICache(void); +void flushICacheRange(void *startAddress, u32 size); diff --git a/source/common/cache.s b/source/common/cache.s new file mode 100644 index 0000000..fcc55dc --- /dev/null +++ b/source/common/cache.s @@ -0,0 +1,93 @@ +@ This file is part of Luma3DS +@ Copyright (C) 2016-2017 Aurora Wright, TuxSH +@ +@ This program is free software: you can redistribute it and/or modify +@ it under the terms of the GNU General Public License as published by +@ the Free Software Foundation, either version 3 of the License, or +@ (at your option) any later version. +@ +@ This program is distributed in the hope that 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 . +@ +@ Additional Terms 7.b and 7.c of GPLv3 apply to this file: +@ * Requiring preservation of specified reasonable legal notices or +@ author attributions in that material or in the Appropriate Legal +@ Notices displayed by works containing it. +@ * Prohibiting misrepresentation of the origin of that material, +@ or requiring that modified versions of such material be marked in +@ reasonable ways as different from the original version. + +.text +.arm +.align 4 + +.global flushEntireDCache +.type flushEntireDCache, %function +flushEntireDCache: + @ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html, + @ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well + @ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has) + + @ Implemented in bootROM at address 0xffff0830 + mov r1, #0 @ segment counter + outer_loop: + mov r0, #0 @ line counter + + inner_loop: + orr r2, r1, r0 @ generate segment and line address + mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line + add r0, #0x20 @ increment to next line + cmp r0, #0x400 + bne inner_loop + + add r1, #0x40000000 + cmp r1, #0 + bne outer_loop + + mcr p15, 0, r1, c7, c10, 4 @ drain write buffer + bx lr + +.global flushDCacheRange +.type flushDCacheRange, %function +flushDCacheRange: + @ Implemented in bootROM at address 0xffff08a0 + add r1, r0, r1 @ end address + bic r0, #0x1f @ align source address to cache line size (32 bytes) + + flush_dcache_range_loop: + mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding + add r0, #0x20 + cmp r0, r1 + blo flush_dcache_range_loop + + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + bx lr + +.global flushEntireICache +.type flushEntireICache, %function +flushEntireICache: + @ Implemented in bootROM at address 0xffff0ab4 + mov r0, #0 + mcr p15, 0, r0, c7, c5, 0 + bx lr + +.global flushICacheRange +.type flushICacheRange, %function +flushICacheRange: + @ Implemented in bootROM at address 0xffff0ac0 + add r1, r0, r1 @ end address + bic r0, #0x1f @ align source address to cache line size (32 bytes) + + flush_icache_range_loop: + mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding + add r0, #0x20 + cmp r0, r1 + blo flush_icache_range_loop + + bx lr diff --git a/source/common/power.c b/source/common/power.c new file mode 100644 index 0000000..18b90bb --- /dev/null +++ b/source/common/power.c @@ -0,0 +1,19 @@ +#include "power.h" +#include "i2c.h" +#include "cache.h" +#include "ui.h" + +void Reboot() { + ClearScreenF(true, true, COLOR_STD_BG); + flushEntireDCache(); + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); + while(true); +} + +void PowerOff() +{ + ClearScreenF(true, true, COLOR_STD_BG); + flushEntireDCache(); + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); + while (true); +} diff --git a/source/common/power.h b/source/common/power.h index 12c86b3..b37f020 100644 --- a/source/common/power.h +++ b/source/common/power.h @@ -1,12 +1,6 @@ -#include "i2c.h" +#pragma once -inline static void Reboot() { - i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); - while(true); -} +#include "common.h" -inline static void PowerOff() -{ - i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0); - while (true); -} +void Reboot(); +void PowerOff(); diff --git a/source/main.c b/source/main.c index 7fb3384..0cfc161 100644 --- a/source/main.c +++ b/source/main.c @@ -19,6 +19,5 @@ void main(int argc, char** argv) bottom_screen = (u8*)(*(u32*)0x23FFFE08); } u32 godmode_exit = GodMode(); - ClearScreenF(true, true, COLOR_STD_BG); (godmode_exit == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff(); }