mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-02 06:19:12 +00:00
fusee-primary: fix reboot-to-self for decompressed code
This commit is contained in:
parent
ff7e52a1c1
commit
2b81ed7315
3 changed files with 108 additions and 1 deletions
|
@ -32,6 +32,11 @@ SECTIONS
|
|||
KEEP( *(.text.start) )
|
||||
KEEP( *(.init) )
|
||||
. = ALIGN(32);
|
||||
PROVIDE (__reboot_start__ = ABSOLUTE(.));
|
||||
KEEP( *(.reboot*) )
|
||||
. = ALIGN(4);
|
||||
PROVIDE (__reboot_end__ = ABSOLUTE(.));
|
||||
. = ALIGN(32);
|
||||
} >main :crt0
|
||||
|
||||
.chainloader_loadable :
|
||||
|
@ -59,6 +64,7 @@ SECTIONS
|
|||
{
|
||||
. = ALIGN(32);
|
||||
/* .text */
|
||||
*(.text.reboot_to_self)
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.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 u32
|
||||
|
||||
extern uint8_t __reboot_start__[], __reboot_end__[];
|
||||
|
||||
void wait(uint32_t microseconds) {
|
||||
uint32_t old_time = TIMERUS_CNTR_1US_0;
|
||||
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));
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
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) {
|
||||
|
|
Loading…
Reference in a new issue