mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-19 08:52:25 +00:00
fusee-primary: fix reboot-to-self for decompressed code
This commit is contained in:
parent
7ed9bdd374
commit
dc52610bd8
3 changed files with 108 additions and 1 deletions
|
@ -32,6 +32,11 @@ SECTIONS
|
||||||
KEEP( *(.text.start) )
|
KEEP( *(.text.start) )
|
||||||
KEEP( *(.init) )
|
KEEP( *(.init) )
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__reboot_start__ = ABSOLUTE(.));
|
||||||
|
KEEP( *(.reboot*) )
|
||||||
|
. = ALIGN(4);
|
||||||
|
PROVIDE (__reboot_end__ = ABSOLUTE(.));
|
||||||
|
. = ALIGN(32);
|
||||||
} >main :crt0
|
} >main :crt0
|
||||||
|
|
||||||
.chainloader_loadable :
|
.chainloader_loadable :
|
||||||
|
@ -59,6 +64,7 @@ SECTIONS
|
||||||
{
|
{
|
||||||
. = ALIGN(32);
|
. = ALIGN(32);
|
||||||
/* .text */
|
/* .text */
|
||||||
|
*(.text.reboot_to_self)
|
||||||
*(.text)
|
*(.text)
|
||||||
*(.text.*)
|
*(.text.*)
|
||||||
*(.glue_7)
|
*(.glue_7)
|
||||||
|
|
76
fusee/fusee-primary/fusee-primary-main/src/reboot_start.s
Normal file
76
fusee/fusee-primary/fusee-primary-main/src/reboot_start.s
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.macro CLEAR_GPR_REG_ITER
|
||||||
|
mov r\@, #0
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.section .reboot.start, "ax", %progbits
|
||||||
|
.arm
|
||||||
|
.align 5
|
||||||
|
.global reboot_start
|
||||||
|
.type reboot_start, %function
|
||||||
|
reboot_start:
|
||||||
|
/* Switch to system mode, mask all interrupts, clear all flags */
|
||||||
|
msr cpsr_cxsf, #0xDF
|
||||||
|
|
||||||
|
/* Relocate reboot start to 0x4003E000. */
|
||||||
|
ldr r0, =0x4003E000
|
||||||
|
adr r1, reboot_start
|
||||||
|
cmp r0, r1
|
||||||
|
beq 1f
|
||||||
|
|
||||||
|
mov r2, #0x1000
|
||||||
|
0:
|
||||||
|
ldmia r1!, {r5-r12}
|
||||||
|
stmia r0!, {r5-r12}
|
||||||
|
subs r2, #0x20
|
||||||
|
bne 0b
|
||||||
|
|
||||||
|
ldr r0, =0x4003E000
|
||||||
|
adr r1, reboot_start
|
||||||
|
adr r2, 1f
|
||||||
|
sub r2, r2, r1
|
||||||
|
add r2, r2, r0
|
||||||
|
bx r2
|
||||||
|
|
||||||
|
1:
|
||||||
|
|
||||||
|
/* Restore our low iram code. */
|
||||||
|
ldr r0, =0x40008000
|
||||||
|
ldr r1, =0x40030000
|
||||||
|
mov r2, #0x8000
|
||||||
|
0:
|
||||||
|
ldmia r1!, {r5-r12}
|
||||||
|
stmia r0!, {r5-r12}
|
||||||
|
subs r2, #0x20
|
||||||
|
bne 0b
|
||||||
|
|
||||||
|
/* Restore our upper stub code. */
|
||||||
|
ldr r0, =0x40010000
|
||||||
|
ldr r1, =0x4003D000
|
||||||
|
mov r2, #0x1000
|
||||||
|
0:
|
||||||
|
ldmia r1!, {r5-r12}
|
||||||
|
stmia r0!, {r5-r12}
|
||||||
|
subs r2, #0x20
|
||||||
|
bne 0b
|
||||||
|
|
||||||
|
/* Jump to start. */
|
||||||
|
ldr r0, =0x40008000
|
||||||
|
bx r0
|
||||||
|
|
||||||
|
0: b 0b
|
|
@ -37,6 +37,8 @@
|
||||||
#undef u8
|
#undef u8
|
||||||
#undef u32
|
#undef u32
|
||||||
|
|
||||||
|
extern uint8_t __reboot_start__[], __reboot_end__[];
|
||||||
|
|
||||||
void wait(uint32_t microseconds) {
|
void wait(uint32_t microseconds) {
|
||||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||||
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
while (TIMERUS_CNTR_1US_0 - old_time <= microseconds) {
|
||||||
|
@ -80,8 +82,31 @@ __attribute__((noreturn)) void reboot_to_self(void) {
|
||||||
write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i));
|
write32le((void *)0x4003F000, i, read32le(rebootstub_bin, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy our low part into safe IRAM. */
|
||||||
|
for (size_t i = 0; i < 0x8000; i += sizeof(uint32_t)) {
|
||||||
|
write32le((void *)0x40030000, i, read32le((void *)0x40008000, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy our start page into fatal IRAM. */
|
||||||
|
for (size_t i = 0; i < 0x1000; i += sizeof(uint32_t)) {
|
||||||
|
write32le((void *)0x4003D000, i, read32le((void *)0x40010000, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy our reboot handler to the rebootstub target. */
|
||||||
|
for (size_t i = 0; i < (__reboot_end__ - __reboot_start__); i += sizeof(uint32_t)) {
|
||||||
|
write32le((void *)0x40010000, i, read32le(__reboot_start__, i));
|
||||||
|
}
|
||||||
|
|
||||||
/* Trigger warm reboot. */
|
/* Trigger warm reboot. */
|
||||||
pmc_reboot(1 << 0);
|
APBDEV_PMC_SCRATCH0_0 = (1 << 0);
|
||||||
|
|
||||||
|
/* Reset the processor. */
|
||||||
|
APBDEV_PMC_CONTROL = BIT(4);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
/* Wait for reboot. */
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
|
__attribute__((noreturn)) void wait_for_button_and_reboot(void) {
|
||||||
|
|
Loading…
Reference in a new issue