1*91f16700Schasinglulu/* 2*91f16700Schasinglulu * Copyright (c) 2014-2023 Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu#include <arch.h> 8*91f16700Schasinglulu#include <asm_macros.S> 9*91f16700Schasinglulu#include <common/debug.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu .globl asm_print_str 12*91f16700Schasinglulu .globl asm_print_hex 13*91f16700Schasinglulu .globl asm_print_hex_bits 14*91f16700Schasinglulu .globl asm_print_newline 15*91f16700Schasinglulu .globl asm_assert 16*91f16700Schasinglulu .globl el3_panic 17*91f16700Schasinglulu .globl elx_panic 18*91f16700Schasinglulu 19*91f16700Schasinglulu/* Since the max decimal input number is 65536 */ 20*91f16700Schasinglulu#define MAX_DEC_DIVISOR 10000 21*91f16700Schasinglulu/* The offset to add to get ascii for numerals '0 - 9' */ 22*91f16700Schasinglulu#define ASCII_OFFSET_NUM 0x30 23*91f16700Schasinglulu 24*91f16700Schasinglulu#if ENABLE_ASSERTIONS 25*91f16700Schasinglulu.section .rodata.assert_str, "aS" 26*91f16700Schasingluluassert_msg1: 27*91f16700Schasinglulu .asciz "ASSERT: File " 28*91f16700Schasingluluassert_msg2: 29*91f16700Schasinglulu .asciz " Line " 30*91f16700Schasinglulu 31*91f16700Schasinglulu /* 32*91f16700Schasinglulu * This macro is intended to be used to print the 33*91f16700Schasinglulu * line number in decimal. Used by asm_assert macro. 34*91f16700Schasinglulu * The max number expected is 65536. 35*91f16700Schasinglulu * In: x4 = the decimal to print. 36*91f16700Schasinglulu * Clobber: x30, x0, x1, x2, x5, x6 37*91f16700Schasinglulu */ 38*91f16700Schasinglulu .macro asm_print_line_dec 39*91f16700Schasinglulu mov x6, #10 /* Divide by 10 after every loop iteration */ 40*91f16700Schasinglulu mov x5, #MAX_DEC_DIVISOR 41*91f16700Schasingluludec_print_loop: 42*91f16700Schasinglulu udiv x0, x4, x5 /* Get the quotient */ 43*91f16700Schasinglulu msub x4, x0, x5, x4 /* Find the remainder */ 44*91f16700Schasinglulu add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ 45*91f16700Schasinglulu bl plat_crash_console_putc 46*91f16700Schasinglulu udiv x5, x5, x6 /* Reduce divisor */ 47*91f16700Schasinglulu cbnz x5, dec_print_loop 48*91f16700Schasinglulu .endm 49*91f16700Schasinglulu 50*91f16700Schasinglulu 51*91f16700Schasinglulu/* --------------------------------------------------------------------------- 52*91f16700Schasinglulu * Assertion support in assembly. 53*91f16700Schasinglulu * The below function helps to support assertions in assembly where we do not 54*91f16700Schasinglulu * have a C runtime stack. Arguments to the function are : 55*91f16700Schasinglulu * x0 - File name 56*91f16700Schasinglulu * x1 - Line no 57*91f16700Schasinglulu * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6. 58*91f16700Schasinglulu * --------------------------------------------------------------------------- 59*91f16700Schasinglulu */ 60*91f16700Schasinglulufunc asm_assert 61*91f16700Schasinglulu#if LOG_LEVEL >= LOG_LEVEL_INFO 62*91f16700Schasinglulu /* 63*91f16700Schasinglulu * Only print the output if LOG_LEVEL is higher or equal to 64*91f16700Schasinglulu * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu mov x5, x0 67*91f16700Schasinglulu mov x6, x1 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* Ensure the console is initialized */ 70*91f16700Schasinglulu bl plat_crash_console_init 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Check if the console is initialized */ 73*91f16700Schasinglulu cbz x0, _assert_loop 74*91f16700Schasinglulu 75*91f16700Schasinglulu /* The console is initialized */ 76*91f16700Schasinglulu adr x4, assert_msg1 77*91f16700Schasinglulu bl asm_print_str 78*91f16700Schasinglulu mov x4, x5 79*91f16700Schasinglulu bl asm_print_str 80*91f16700Schasinglulu adr x4, assert_msg2 81*91f16700Schasinglulu bl asm_print_str 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* Check if line number higher than max permitted */ 84*91f16700Schasinglulu tst x6, #~0xffff 85*91f16700Schasinglulu b.ne _assert_loop 86*91f16700Schasinglulu mov x4, x6 87*91f16700Schasinglulu asm_print_line_dec 88*91f16700Schasinglulu bl plat_crash_console_flush 89*91f16700Schasinglulu_assert_loop: 90*91f16700Schasinglulu#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */ 91*91f16700Schasinglulu no_ret plat_panic_handler 92*91f16700Schasingluluendfunc asm_assert 93*91f16700Schasinglulu#endif /* ENABLE_ASSERTIONS */ 94*91f16700Schasinglulu 95*91f16700Schasinglulu/* 96*91f16700Schasinglulu * This function prints a string from address in x4. 97*91f16700Schasinglulu * In: x4 = pointer to string. 98*91f16700Schasinglulu * Clobber: x30, x0, x1, x2, x3 99*91f16700Schasinglulu */ 100*91f16700Schasinglulufunc asm_print_str 101*91f16700Schasinglulu mov x3, x30 102*91f16700Schasinglulu1: 103*91f16700Schasinglulu ldrb w0, [x4], #0x1 104*91f16700Schasinglulu cbz x0, 2f 105*91f16700Schasinglulu bl plat_crash_console_putc 106*91f16700Schasinglulu b 1b 107*91f16700Schasinglulu2: 108*91f16700Schasinglulu ret x3 109*91f16700Schasingluluendfunc asm_print_str 110*91f16700Schasinglulu 111*91f16700Schasinglulu/* 112*91f16700Schasinglulu * This function prints a hexadecimal number in x4. 113*91f16700Schasinglulu * In: x4 = the hexadecimal to print. 114*91f16700Schasinglulu * Clobber: x30, x0 - x3, x5 115*91f16700Schasinglulu */ 116*91f16700Schasinglulufunc asm_print_hex 117*91f16700Schasinglulu mov x5, #64 /* No of bits to convert to ascii */ 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* Convert to ascii number of bits in x5 */ 120*91f16700Schasingluluasm_print_hex_bits: 121*91f16700Schasinglulu mov x3, x30 122*91f16700Schasinglulu1: 123*91f16700Schasinglulu sub x5, x5, #4 124*91f16700Schasinglulu lsrv x0, x4, x5 125*91f16700Schasinglulu and x0, x0, #0xf 126*91f16700Schasinglulu cmp x0, #0xA 127*91f16700Schasinglulu b.lo 2f 128*91f16700Schasinglulu /* Add by 0x27 in addition to ASCII_OFFSET_NUM 129*91f16700Schasinglulu * to get ascii for characters 'a - f'. 130*91f16700Schasinglulu */ 131*91f16700Schasinglulu add x0, x0, #0x27 132*91f16700Schasinglulu2: 133*91f16700Schasinglulu add x0, x0, #ASCII_OFFSET_NUM 134*91f16700Schasinglulu bl plat_crash_console_putc 135*91f16700Schasinglulu cbnz x5, 1b 136*91f16700Schasinglulu ret x3 137*91f16700Schasingluluendfunc asm_print_hex 138*91f16700Schasinglulu 139*91f16700Schasinglulu/* 140*91f16700Schasinglulu * Helper function to print newline to console 141*91f16700Schasinglulu * Clobber: x0 142*91f16700Schasinglulu */ 143*91f16700Schasinglulufunc asm_print_newline 144*91f16700Schasinglulu mov x0, '\n' 145*91f16700Schasinglulu b plat_crash_console_putc 146*91f16700Schasingluluendfunc asm_print_newline 147*91f16700Schasinglulu 148*91f16700Schasinglulu /*********************************************************** 149*91f16700Schasinglulu * The common implementation of el3_panic for all BL stages 150*91f16700Schasinglulu ***********************************************************/ 151*91f16700Schasinglulu 152*91f16700Schasinglulu.section .rodata.panic_str, "aS" 153*91f16700Schasinglulu panic_msg: .asciz "PANIC at PC : 0x" 154*91f16700Schasinglulu 155*91f16700Schasinglulufunc elx_panic 156*91f16700Schasinglulu#if CRASH_REPORTING && defined(IMAGE_BL31) 157*91f16700Schasinglulu b report_elx_panic 158*91f16700Schasinglulu#endif /* CRASH_REPORTING && IMAGE_BL31 */ 159*91f16700Schasinglulu 160*91f16700Schasinglulu b panic_common 161*91f16700Schasingluluendfunc elx_panic 162*91f16700Schasinglulu 163*91f16700Schasinglulu/* --------------------------------------------------------------------------- 164*91f16700Schasinglulu * el3_panic assumes that it is invoked from a C Runtime Environment ie a 165*91f16700Schasinglulu * valid stack exists. This call will not return. 166*91f16700Schasinglulu * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6 167*91f16700Schasinglulu * --------------------------------------------------------------------------- 168*91f16700Schasinglulu */ 169*91f16700Schasinglulu 170*91f16700Schasinglulufunc el3_panic 171*91f16700Schasinglulu#if CRASH_REPORTING && defined(IMAGE_BL31) 172*91f16700Schasinglulu b report_el3_panic 173*91f16700Schasinglulu#endif /* CRASH_REPORTING && IMAGE_BL31 */ 174*91f16700Schasinglulu 175*91f16700Schasinglulupanic_common: 176*91f16700Schasinglulu mov x6, x30 177*91f16700Schasinglulu bl plat_crash_console_init 178*91f16700Schasinglulu 179*91f16700Schasinglulu /* Check if the console is initialized */ 180*91f16700Schasinglulu cbz x0, _panic_handler 181*91f16700Schasinglulu 182*91f16700Schasinglulu /* The console is initialized */ 183*91f16700Schasinglulu adr x4, panic_msg 184*91f16700Schasinglulu bl asm_print_str 185*91f16700Schasinglulu mov x4, x6 186*91f16700Schasinglulu 187*91f16700Schasinglulu /* The panic location is lr -4 */ 188*91f16700Schasinglulu sub x4, x4, #4 189*91f16700Schasinglulu bl asm_print_hex 190*91f16700Schasinglulu 191*91f16700Schasinglulu /* Print new line */ 192*91f16700Schasinglulu bl asm_print_newline 193*91f16700Schasinglulu 194*91f16700Schasinglulu bl plat_crash_console_flush 195*91f16700Schasinglulu 196*91f16700Schasinglulu_panic_handler: 197*91f16700Schasinglulu /* Pass to plat_panic_handler the address from where el3_panic was 198*91f16700Schasinglulu * called, not the address of the call from el3_panic. */ 199*91f16700Schasinglulu mov x30, x6 200*91f16700Schasinglulu b plat_panic_handler 201*91f16700Schasinglulu 202*91f16700Schasingluluendfunc el3_panic 203