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 do_panic 17 .globl el3_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 do_panic for all BL stages 150 ***********************************************************/ 151 152.section .rodata.panic_str, "aS" 153 panic_msg: .asciz "PANIC at PC : 0x" 154 155/* --------------------------------------------------------------------------- 156 * do_panic assumes that it is invoked from a C Runtime Environment ie a 157 * valid stack exists. This call will not return. 158 * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6 159 * --------------------------------------------------------------------------- 160 */ 161 162func do_panic 163#if CRASH_REPORTING && defined(IMAGE_BL31) 164 b report_el3_panic 165#endif /* CRASH_REPORTING && IMAGE_BL31 */ 166 167panic_common: 168/* 169 * el3_panic will be redefined by the BL31 170 * crash reporting mechanism (if enabled) 171 */ 172el3_panic: 173 mov x6, x30 174 bl plat_crash_console_init 175 176 /* Check if the console is initialized */ 177 cbz x0, _panic_handler 178 179 /* The console is initialized */ 180 adr x4, panic_msg 181 bl asm_print_str 182 mov x4, x6 183 184 /* The panic location is lr -4 */ 185 sub x4, x4, #4 186 bl asm_print_hex 187 188 /* Print new line */ 189 bl asm_print_newline 190 191 bl plat_crash_console_flush 192 193_panic_handler: 194 /* Pass to plat_panic_handler the address from where el3_panic was 195 * called, not the address of the call from el3_panic. */ 196 mov x30, x6 197 b plat_panic_handler 198 199endfunc do_panic