mirror of
https://github.com/CTCaer/hekate.git
synced 2024-11-26 19:52:11 +00:00
Add simple exception handling
This adds support for exception handling. It should provide simple and fast reporting of crucial info and full restoration without powering off.
This commit is contained in:
parent
9a5cfdff4c
commit
0462f3b252
8 changed files with 574 additions and 9 deletions
233
bootloader/exception_handlers.S
Normal file
233
bootloader/exception_handlers.S
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 CTCaer
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Armv7tdmi Status register.
|
||||||
|
*
|
||||||
|
* bit0: Mode 0.
|
||||||
|
* bit1: Mode 1.
|
||||||
|
* bit2: Mode 2.
|
||||||
|
* bit3: Mode 3.
|
||||||
|
* bit4: Mode 4.
|
||||||
|
* bit5: Thumb state.
|
||||||
|
* bit6: FIQ disable.
|
||||||
|
* bit7: IRQ disable.
|
||||||
|
* bit8-27: Reserved.
|
||||||
|
* bit28: Overflow condition.
|
||||||
|
* bit29: Carry/Borrow/Extend condition.
|
||||||
|
* bit30: Zero condition.
|
||||||
|
* bit31: Negative/Less than condition.
|
||||||
|
*
|
||||||
|
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||||||
|
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||||
|
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||||
|
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||||
|
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||||
|
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||||
|
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||||
|
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXCP_EN_ADDR 0x4003FFFC
|
||||||
|
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||||
|
#define EXCP_LR_ADDR 0x4003FFF4
|
||||||
|
|
||||||
|
#define EXCP_VEC_BASE 0x6000F000
|
||||||
|
#define EVP_COP_RESET_VECTOR 0x200
|
||||||
|
#define EVP_COP_UNDEF_VECTOR 0x204
|
||||||
|
#define EVP_COP_SWI_VECTOR 0x208
|
||||||
|
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||||||
|
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||||||
|
#define EVP_COP_RSVD_VECTOR 0x214
|
||||||
|
#define EVP_COP_IRQ_VECTOR 0x218
|
||||||
|
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||||
|
|
||||||
|
#define MODE_USR 0x10
|
||||||
|
#define MODE_FIQ 0x11
|
||||||
|
#define MODE_IRQ 0x12
|
||||||
|
#define MODE_SVC 0x13
|
||||||
|
#define MODE_ABT 0x17
|
||||||
|
#define MODE_UDF 0x1B
|
||||||
|
#define MODE_SYS 0x1F
|
||||||
|
#define MODE_MASK 0x1F
|
||||||
|
|
||||||
|
#define FIQ 0x40
|
||||||
|
#define IRQ 0x80
|
||||||
|
|
||||||
|
.section .text._irq_setup
|
||||||
|
.arm
|
||||||
|
|
||||||
|
.extern ipl_main
|
||||||
|
.type ipl_main, %function
|
||||||
|
|
||||||
|
.extern svc_handler
|
||||||
|
.type svc_handler, %function
|
||||||
|
|
||||||
|
.extern irq_handler
|
||||||
|
.type irq_handler, %function
|
||||||
|
|
||||||
|
.extern fiq_setup
|
||||||
|
.type fiq_setup, %function
|
||||||
|
|
||||||
|
.extern fiq_handler
|
||||||
|
.type fiq_handler, %function
|
||||||
|
|
||||||
|
.globl _irq_setup
|
||||||
|
.type _irq_setup, %function
|
||||||
|
_irq_setup:
|
||||||
|
MRS R0, CPSR
|
||||||
|
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||||||
|
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||||||
|
MSR CPSR, R0
|
||||||
|
|
||||||
|
/* Setup IRQ stack pointer */
|
||||||
|
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||||
|
LDR SP, =0x40040000
|
||||||
|
|
||||||
|
/* Setup SYS stack pointer */
|
||||||
|
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||||
|
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||||||
|
|
||||||
|
MOV LR, PC
|
||||||
|
BL setup_vectors
|
||||||
|
/*BL fiq_setup*/
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
BL irq_enable_cpu_irq_exceptions
|
||||||
|
|
||||||
|
B ipl_main
|
||||||
|
B .
|
||||||
|
|
||||||
|
_reset:
|
||||||
|
LDR R0, =EXCP_EN_ADDR
|
||||||
|
LDR R1, =0x30505645 /* EVP0 */
|
||||||
|
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||||||
|
LDR R0, =EXCP_LR_ADDR
|
||||||
|
MOV R1, LR
|
||||||
|
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||||||
|
LDR R0, =__bss_start
|
||||||
|
EOR R1, R1, R1
|
||||||
|
LDR R2, =__bss_end
|
||||||
|
SUB R2, R2, R0
|
||||||
|
BL memset
|
||||||
|
B _irq_setup
|
||||||
|
|
||||||
|
_reset_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x545352 /* RST */
|
||||||
|
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_undefined_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x464455 /* UDF */
|
||||||
|
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_prefetch_abort_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x54424150 /* PABT */
|
||||||
|
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_data_abort_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x54424144 /* DABT */
|
||||||
|
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
.globl irq_enable_cpu_irq_exceptions
|
||||||
|
.type irq_enable_cpu_irq_exceptions, %function
|
||||||
|
irq_enable_cpu_irq_exceptions:
|
||||||
|
MRS R12, CPSR
|
||||||
|
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||||||
|
MSR CPSR, R12
|
||||||
|
BX LR
|
||||||
|
|
||||||
|
.globl irq_disable_cpu_irq_exceptions
|
||||||
|
.type irq_disable_cpu_irq_exceptions, %function
|
||||||
|
irq_disable_cpu_irq_exceptions:
|
||||||
|
MRS R12, CPSR
|
||||||
|
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||||||
|
MSR CPSR, R12
|
||||||
|
BX LR
|
||||||
|
|
||||||
|
_irq_handler:
|
||||||
|
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||||||
|
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||||||
|
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||||||
|
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||||
|
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||||||
|
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||||||
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||||
|
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||||||
|
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||||
|
LDR R12, =irq_handler
|
||||||
|
MOV LR, PC /* Copy the return address to link register */
|
||||||
|
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||||
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||||
|
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||||
|
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||||||
|
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||||||
|
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||||||
|
|
||||||
|
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||||||
|
NOP /* Cant access barked registers immediately */
|
||||||
|
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||||||
|
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||||||
|
|
||||||
|
_fiq_handler:
|
||||||
|
BL fiq_handler
|
||||||
|
|
||||||
|
setup_vectors:
|
||||||
|
/* Setup vectors */
|
||||||
|
LDR R0, =EXCP_VEC_BASE
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_undefined_handler
|
||||||
|
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_prefetch_abort_handler
|
||||||
|
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_data_abort_handler
|
||||||
|
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_irq_handler
|
||||||
|
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_fiq_handler
|
||||||
|
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||||||
|
|
||||||
|
BX LR
|
|
@ -7,6 +7,7 @@ SECTIONS {
|
||||||
*(.text._start);
|
*(.text._start);
|
||||||
*(._boot_cfg);
|
*(._boot_cfg);
|
||||||
*(._ipl_version);
|
*(._ipl_version);
|
||||||
|
*(.text._irq_setup);
|
||||||
*(.text*);
|
*(.text*);
|
||||||
}
|
}
|
||||||
.data : {
|
.data : {
|
||||||
|
|
|
@ -1182,8 +1182,24 @@ static void _patched_rcm_protection()
|
||||||
sdmmc_storage_end(&storage);
|
sdmmc_storage_end(&storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EXCP_EN_ADDR 0x4003FFFC
|
||||||
|
#define EXCP_MAGIC 0x30505645 // EVP0
|
||||||
|
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||||
|
#define EXCP_TYPE_RESET 0x545352 // RST
|
||||||
|
#define EXCP_TYPE_UNDEF 0x464455 // UDF
|
||||||
|
#define EXCP_TYPE_PABRT 0x54424150 // PABT
|
||||||
|
#define EXCP_TYPE_DABRT 0x54424144 // DABT
|
||||||
|
#define EXCP_LR_ADDR 0x4003FFF4
|
||||||
|
|
||||||
static void _show_errors()
|
static void _show_errors()
|
||||||
{
|
{
|
||||||
|
u32 *excp_enabled = (u32 *)EXCP_EN_ADDR;
|
||||||
|
u32 *excp_type = (u32 *)EXCP_TYPE_ADDR;
|
||||||
|
u32 *excp_lr = (u32 *)EXCP_LR_ADDR;
|
||||||
|
|
||||||
|
if (*excp_enabled == EXCP_MAGIC)
|
||||||
|
h_cfg.errors |= ERR_EXCEPT_ENB;
|
||||||
|
|
||||||
if (h_cfg.errors)
|
if (h_cfg.errors)
|
||||||
{
|
{
|
||||||
gfx_clear_grey(0x1B);
|
gfx_clear_grey(0x1B);
|
||||||
|
@ -1195,7 +1211,35 @@ static void _show_errors()
|
||||||
if (h_cfg.errors & ERR_SYSOLD_MTC)
|
if (h_cfg.errors & ERR_SYSOLD_MTC)
|
||||||
WPRINTF("Missing or old Minerva library!\n");
|
WPRINTF("Missing or old Minerva library!\n");
|
||||||
|
|
||||||
|
if (h_cfg.errors & ~ERR_EXCEPT_ENB)
|
||||||
|
{
|
||||||
WPRINTF("\nUpdate your bootloader folder!\n\n");
|
WPRINTF("\nUpdate your bootloader folder!\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h_cfg.errors & ERR_EXCEPT_ENB)
|
||||||
|
{
|
||||||
|
WPRINTFARGS("An exception happened (LR %08X):\n", *excp_lr);
|
||||||
|
switch (*excp_type)
|
||||||
|
{
|
||||||
|
case EXCP_TYPE_RESET:
|
||||||
|
WPRINTF("Reset");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_UNDEF:
|
||||||
|
WPRINTF("Undefined instruction");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_PABRT:
|
||||||
|
WPRINTF("Prefetch abort");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_DABRT:
|
||||||
|
WPRINTF("Data abort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WPRINTF("\n");
|
||||||
|
|
||||||
|
// Clear the exception.
|
||||||
|
*excp_enabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
WPRINTF("Press any key...");
|
WPRINTF("Press any key...");
|
||||||
|
|
||||||
msleep(2000);
|
msleep(2000);
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
.extern memset
|
.extern memset
|
||||||
.type memset, %function
|
.type memset, %function
|
||||||
|
|
||||||
.extern ipl_main
|
.extern _irq_setup
|
||||||
.type ipl_main, %function
|
.type _irq_setup, %function
|
||||||
|
|
||||||
.globl _start
|
.globl _start
|
||||||
.type _start, %function
|
.type _start, %function
|
||||||
|
@ -67,7 +67,7 @@ _real_start:
|
||||||
LDR R2, =__bss_end
|
LDR R2, =__bss_end
|
||||||
SUB R2, R2, R0
|
SUB R2, R2, R0
|
||||||
BL memset
|
BL memset
|
||||||
BL ipl_main
|
BL _irq_setup
|
||||||
B .
|
B .
|
||||||
|
|
||||||
.globl pivot_stack
|
.globl pivot_stack
|
||||||
|
|
233
nyx/nyx_gui/exception_handlers.S
Normal file
233
nyx/nyx_gui/exception_handlers.S
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 CTCaer
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Armv7tdmi Status register.
|
||||||
|
*
|
||||||
|
* bit0: Mode 0.
|
||||||
|
* bit1: Mode 1.
|
||||||
|
* bit2: Mode 2.
|
||||||
|
* bit3: Mode 3.
|
||||||
|
* bit4: Mode 4.
|
||||||
|
* bit5: Thumb state.
|
||||||
|
* bit6: FIQ disable.
|
||||||
|
* bit7: IRQ disable.
|
||||||
|
* bit8-27: Reserved.
|
||||||
|
* bit28: Overflow condition.
|
||||||
|
* bit29: Carry/Borrow/Extend condition.
|
||||||
|
* bit30: Zero condition.
|
||||||
|
* bit31: Negative/Less than condition.
|
||||||
|
*
|
||||||
|
* M[4:0] | Mode | Visible Thumb-state registers | Visible ARM-state registers
|
||||||
|
* 10000 | USER | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||||
|
* 10001 | FIQ | r0–r7, SP_fiq, LR_fiq, PC, CPSR, SPSR_fiq | r0–r7, r8_fiq–r14_fiq, PC, CPSR, SPSR_fiq
|
||||||
|
* 10010 | IRQ | r0–r7, SP_irq, LR_irq, PC, CPSR, SPSR_irq | r0–r12, r13_irq, r14_irq, PC, CPSR, SPSR_irq
|
||||||
|
* 10011 | SVC | r0–r7, SP_svc, LR_svc, PC, CPSR, SPSR_svc | r0–r12, r13_svc, r14_svc, PC, CPSR, SPSR_svc
|
||||||
|
* 10111 | ABRT | r0–r7, SP_abt, LR_abt, PC, CPSR, SPSR_abt | r0–r12, r13_abt, r14_abt, PC, CPSR, SPSR_abt
|
||||||
|
* 11011 | UNDF | r0–r7, SP_und, LR_und, PC, CPSR, SPSR_und | r0–r12, r13_und, r14_und, PC, CPSR, SPSR_und
|
||||||
|
* 11111 | SYS | r0–r7, SP, LR, PC, CPSR | r0–r14, PC, CPSR
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EXCP_EN_ADDR 0x4003FFFC
|
||||||
|
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||||
|
#define EXCP_LR_ADDR 0x4003FFF4
|
||||||
|
|
||||||
|
#define EXCP_VEC_BASE 0x6000F000
|
||||||
|
#define EVP_COP_RESET_VECTOR 0x200
|
||||||
|
#define EVP_COP_UNDEF_VECTOR 0x204
|
||||||
|
#define EVP_COP_SWI_VECTOR 0x208
|
||||||
|
#define EVP_COP_PREFETCH_ABORT_VECTOR 0x20C
|
||||||
|
#define EVP_COP_DATA_ABORT_VECTOR 0x210
|
||||||
|
#define EVP_COP_RSVD_VECTOR 0x214
|
||||||
|
#define EVP_COP_IRQ_VECTOR 0x218
|
||||||
|
#define EVP_COP_FIQ_VECTOR 0x21C
|
||||||
|
|
||||||
|
#define MODE_USR 0x10
|
||||||
|
#define MODE_FIQ 0x11
|
||||||
|
#define MODE_IRQ 0x12
|
||||||
|
#define MODE_SVC 0x13
|
||||||
|
#define MODE_ABT 0x17
|
||||||
|
#define MODE_UDF 0x1B
|
||||||
|
#define MODE_SYS 0x1F
|
||||||
|
#define MODE_MASK 0x1F
|
||||||
|
|
||||||
|
#define FIQ 0x40
|
||||||
|
#define IRQ 0x80
|
||||||
|
|
||||||
|
.section .text._irq_setup
|
||||||
|
.arm
|
||||||
|
|
||||||
|
.extern ipl_main
|
||||||
|
.type ipl_main, %function
|
||||||
|
|
||||||
|
.extern svc_handler
|
||||||
|
.type svc_handler, %function
|
||||||
|
|
||||||
|
.extern irq_handler
|
||||||
|
.type irq_handler, %function
|
||||||
|
|
||||||
|
.extern fiq_setup
|
||||||
|
.type fiq_setup, %function
|
||||||
|
|
||||||
|
.extern fiq_handler
|
||||||
|
.type fiq_handler, %function
|
||||||
|
|
||||||
|
.globl _irq_setup
|
||||||
|
.type _irq_setup, %function
|
||||||
|
_irq_setup:
|
||||||
|
MRS R0, CPSR
|
||||||
|
BIC R0, R0, #MODE_MASK /* Clear mode bits */
|
||||||
|
ORR R0, R0, #(MODE_SVC | IRQ | FIQ) /* SUPERVISOR mode, IRQ/FIQ disabled */
|
||||||
|
MSR CPSR, R0
|
||||||
|
|
||||||
|
/* Setup IRQ stack pointer */
|
||||||
|
MSR CPSR, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||||
|
LDR SP, =0x40040000
|
||||||
|
|
||||||
|
/* Setup SYS stack pointer */
|
||||||
|
MSR CPSR, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||||
|
LDR SP, =0x4003FF00 /* Will be changed later to DRAM */
|
||||||
|
|
||||||
|
MOV LR, PC
|
||||||
|
BL setup_vectors
|
||||||
|
/*BL fiq_setup*/
|
||||||
|
|
||||||
|
/* Enable interrupts */
|
||||||
|
BL irq_enable_cpu_irq_exceptions
|
||||||
|
|
||||||
|
B ipl_main
|
||||||
|
B .
|
||||||
|
|
||||||
|
_reset:
|
||||||
|
LDR R0, =EXCP_EN_ADDR
|
||||||
|
LDR R1, =0x30505645 /* EVP0 */
|
||||||
|
STR R1, [R0] /* EVP0 in EXCP_EN_ADDR */
|
||||||
|
LDR R0, =EXCP_LR_ADDR
|
||||||
|
MOV R1, LR
|
||||||
|
STR R1, [R0] /* Save LR in EXCP_LR_ADDR */
|
||||||
|
LDR R0, =__bss_start
|
||||||
|
EOR R1, R1, R1
|
||||||
|
LDR R2, =__bss_end
|
||||||
|
SUB R2, R2, R0
|
||||||
|
BL memset
|
||||||
|
B _irq_setup
|
||||||
|
|
||||||
|
_reset_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x545352 /* RST */
|
||||||
|
STR R1, [R0] /* RST in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_undefined_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x464455 /* UDF */
|
||||||
|
STR R1, [R0] /* UDF in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_prefetch_abort_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x54424150 /* PABT */
|
||||||
|
STR R1, [R0] /* PABT in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
_data_abort_handler:
|
||||||
|
LDR R0, =EXCP_TYPE_ADDR
|
||||||
|
LDR R1, =0x54424144 /* DABT */
|
||||||
|
STR R1, [R0] /* DABT in EXCP_TYPE_ADDR */
|
||||||
|
B _reset
|
||||||
|
|
||||||
|
.globl irq_enable_cpu_irq_exceptions
|
||||||
|
.type irq_enable_cpu_irq_exceptions, %function
|
||||||
|
irq_enable_cpu_irq_exceptions:
|
||||||
|
MRS R12, CPSR
|
||||||
|
BIC R12, R12, #(IRQ | FIQ) /* IRQ/FIQ enabled */
|
||||||
|
MSR CPSR, R12
|
||||||
|
BX LR
|
||||||
|
|
||||||
|
.globl irq_disable_cpu_irq_exceptions
|
||||||
|
.type irq_disable_cpu_irq_exceptions, %function
|
||||||
|
irq_disable_cpu_irq_exceptions:
|
||||||
|
MRS R12, CPSR
|
||||||
|
ORR R12, R12, #(IRQ | FIQ) /* IRQ/FIQ disabled */
|
||||||
|
MSR CPSR, R12
|
||||||
|
BX LR
|
||||||
|
|
||||||
|
_irq_handler:
|
||||||
|
MOV R13, R0 /* Save R0 in R13_IRQ */
|
||||||
|
SUB R0, LR, #4 /* Put return address in R0_SYS */
|
||||||
|
MOV LR, R1 /* Save R1 in R14_IRQ (LR) */
|
||||||
|
MRS R1, SPSR /* Put the SPSR in R1_SYS */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||||
|
STMFD SP!, {R0, R1} /* SPSR and PC */
|
||||||
|
STMFD SP!, {R2-R3, R12, LR} /* AAPCS-clobbered registers */
|
||||||
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||||
|
SUB SP, SP, #8 /* Make room for stacking R0 and R1 */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_IRQ | IRQ) /* IRQ mode, IRQ disabled */
|
||||||
|
STMFD R0!, {R13, R14} /* Finish saving the context (R0, R1) */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ) /* SYSTEM mode, IRQ disabled */
|
||||||
|
LDR R12, =irq_handler
|
||||||
|
MOV LR, PC /* Copy the return address to link register */
|
||||||
|
BX R12 /* Call the C IRQ handler (ARM/THUMB) */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_SYS | IRQ | FIQ) /* SYSTEM mode, IRQ/FIQ disabled */
|
||||||
|
MOV R0, SP /* Make SP_SYS visible to IRQ mode */
|
||||||
|
ADD SP, SP, #32 /* Fake unstacking 8 registers from SP_SYS */
|
||||||
|
|
||||||
|
MSR CPSR_c, #(MODE_IRQ | IRQ | FIQ) /* IRQ mode, IRQ/FIQ disabled */
|
||||||
|
MOV SP, R0 /* Copy SP_SYS to SP_IRQ */
|
||||||
|
LDR R0, [SP, #28] /* Load the saved SPSR from the stack */
|
||||||
|
MSR SPSR_cxsf, R0 /* Copy it into SPSR_IRQ */
|
||||||
|
|
||||||
|
LDMFD SP, {R0-R3, R12, LR}^ /* Unstack all saved USER/SYSTEM registers */
|
||||||
|
NOP /* Cant access barked registers immediately */
|
||||||
|
LDR LR, [SP, #24] /* Load return address from the SYS stack */
|
||||||
|
MOVS PC, LR /* Return restoring CPSR from SPSR */
|
||||||
|
|
||||||
|
_fiq_handler:
|
||||||
|
BL fiq_handler
|
||||||
|
|
||||||
|
setup_vectors:
|
||||||
|
/* Setup vectors */
|
||||||
|
LDR R0, =EXCP_VEC_BASE
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_RESET_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_undefined_handler
|
||||||
|
STR R1, [R0, #EVP_COP_UNDEF_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_SWI_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_prefetch_abort_handler
|
||||||
|
STR R1, [R0, #EVP_COP_PREFETCH_ABORT_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_data_abort_handler
|
||||||
|
STR R1, [R0, #EVP_COP_DATA_ABORT_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_reset_handler
|
||||||
|
STR R1, [R0, #EVP_COP_RSVD_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_irq_handler
|
||||||
|
STR R1, [R0, #EVP_COP_IRQ_VECTOR]
|
||||||
|
|
||||||
|
LDR R1, =_fiq_handler
|
||||||
|
STR R1, [R0, #EVP_COP_FIQ_VECTOR]
|
||||||
|
|
||||||
|
BX LR
|
|
@ -6,6 +6,7 @@ SECTIONS {
|
||||||
.text : {
|
.text : {
|
||||||
*(.text._start);
|
*(.text._start);
|
||||||
*(._ipl_version);
|
*(._ipl_version);
|
||||||
|
*(.text._irq_setup);
|
||||||
*(.text*);
|
*(.text*);
|
||||||
}
|
}
|
||||||
.data : {
|
.data : {
|
||||||
|
|
|
@ -367,6 +367,59 @@ void load_saved_configuration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define EXCP_EN_ADDR 0x4003FFFC
|
||||||
|
#define EXCP_MAGIC 0x30505645 // EVP0
|
||||||
|
#define EXCP_TYPE_ADDR 0x4003FFF8
|
||||||
|
#define EXCP_TYPE_RESET 0x545352 // RST
|
||||||
|
#define EXCP_TYPE_UNDEF 0x464455 // UDF
|
||||||
|
#define EXCP_TYPE_PABRT 0x54424150 // PABT
|
||||||
|
#define EXCP_TYPE_DABRT 0x54424144 // DABT
|
||||||
|
#define EXCP_LR_ADDR 0x4003FFF4
|
||||||
|
|
||||||
|
static void _show_errors()
|
||||||
|
{
|
||||||
|
u32 *excp_enabled = (u32 *)EXCP_EN_ADDR;
|
||||||
|
u32 *excp_type = (u32 *)EXCP_TYPE_ADDR;
|
||||||
|
u32 *excp_lr = (u32 *)EXCP_LR_ADDR;
|
||||||
|
|
||||||
|
if (*excp_enabled == EXCP_MAGIC)
|
||||||
|
{
|
||||||
|
gfx_clear_grey(0);
|
||||||
|
gfx_con_setpos(0, 0);
|
||||||
|
display_backlight_brightness(100, 1000);
|
||||||
|
|
||||||
|
WPRINTFARGS("An exception happened (LR %08X):\n", *excp_lr);
|
||||||
|
switch (*excp_type)
|
||||||
|
{
|
||||||
|
case EXCP_TYPE_RESET:
|
||||||
|
WPRINTF("Reset");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_UNDEF:
|
||||||
|
WPRINTF("Undefined instruction");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_PABRT:
|
||||||
|
WPRINTF("Prefetch abort");
|
||||||
|
break;
|
||||||
|
case EXCP_TYPE_DABRT:
|
||||||
|
WPRINTF("Data abort");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WPRINTF("\n");
|
||||||
|
|
||||||
|
// Clear the exception.
|
||||||
|
*excp_lr = 0;
|
||||||
|
*excp_type = 0;
|
||||||
|
*excp_enabled = 0;
|
||||||
|
|
||||||
|
WPRINTF("Press any key...");
|
||||||
|
|
||||||
|
msleep(2000);
|
||||||
|
btn_wait();
|
||||||
|
|
||||||
|
reload_nyx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void nyx_init_load_res()
|
void nyx_init_load_res()
|
||||||
{
|
{
|
||||||
bpmp_mmu_enable();
|
bpmp_mmu_enable();
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
.extern memset
|
.extern memset
|
||||||
.type memset, %function
|
.type memset, %function
|
||||||
|
|
||||||
.extern ipl_main
|
.extern _irq_setup
|
||||||
.type ipl_main, %function
|
.type _irq_setup, %function
|
||||||
|
|
||||||
.globl _start
|
.globl _start
|
||||||
.type _start, %function
|
.type _start, %function
|
||||||
|
@ -36,7 +36,7 @@ _start:
|
||||||
|
|
||||||
/* If we are not in the right location already, copy a relocator to upper IRAM. */
|
/* If we are not in the right location already, copy a relocator to upper IRAM. */
|
||||||
ADR R2, _reloc_ipl
|
ADR R2, _reloc_ipl
|
||||||
LDR R3, =0x4003FFE0
|
LDR R3, =0x4003FF00
|
||||||
MOV R4, #(_real_start - _reloc_ipl)
|
MOV R4, #(_real_start - _reloc_ipl)
|
||||||
_copy_loop:
|
_copy_loop:
|
||||||
LDMIA R2!, {R5}
|
LDMIA R2!, {R5}
|
||||||
|
@ -48,7 +48,7 @@ _copy_loop:
|
||||||
LDR R2, =__ipl_end
|
LDR R2, =__ipl_end
|
||||||
SUB R2, R2, R1
|
SUB R2, R2, R1
|
||||||
LDR R3, =_real_start
|
LDR R3, =_real_start
|
||||||
LDR R4, =0x4003FFE0
|
LDR R4, =0x4003FF00
|
||||||
BX R4
|
BX R4
|
||||||
|
|
||||||
_reloc_ipl:
|
_reloc_ipl:
|
||||||
|
@ -67,7 +67,7 @@ _real_start:
|
||||||
LDR R2, =__bss_end
|
LDR R2, =__bss_end
|
||||||
SUB R2, R2, R0
|
SUB R2, R2, R0
|
||||||
BL memset
|
BL memset
|
||||||
BL ipl_main
|
BL _irq_setup
|
||||||
B .
|
B .
|
||||||
|
|
||||||
.globl pivot_stack
|
.globl pivot_stack
|
||||||
|
|
Loading…
Reference in a new issue