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