summaryrefslogtreecommitdiff
path: root/include/common/debug.h
blob: e0b3a1c67b1b6f0bfca78142c49dcfc0c4918f6f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef DEBUG_H
#define DEBUG_H

#include <lib/utils_def.h>

/*
 * The log output macros print output to the console. These macros produce
 * compiled log output only if the LOG_LEVEL defined in the makefile (or the
 * make command line) is greater or equal than the level required for that
 * type of log output.
 *
 * The format expected is the same as for printf(). For example:
 * INFO("Info %s.\n", "message")    -> INFO:    Info message.
 * WARN("Warning %s.\n", "message") -> WARNING: Warning message.
 */

#define LOG_LEVEL_NONE			U(0)
#define LOG_LEVEL_ERROR			U(10)
#define LOG_LEVEL_NOTICE		U(20)
#define LOG_LEVEL_WARNING		U(30)
#define LOG_LEVEL_INFO			U(40)
#define LOG_LEVEL_VERBOSE		U(50)

#ifndef __ASSEMBLER__

#include <cdefs.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>

#include <drivers/console.h>

/*
 * Define Log Markers corresponding to each log level which will
 * be embedded in the format string and is expected by tf_log() to determine
 * the log level.
 */
#define LOG_MARKER_ERROR		"\xa"	/* 10 */
#define LOG_MARKER_NOTICE		"\x14"	/* 20 */
#define LOG_MARKER_WARNING		"\x1e"	/* 30 */
#define LOG_MARKER_INFO			"\x28"	/* 40 */
#define LOG_MARKER_VERBOSE		"\x32"	/* 50 */

/*
 * If the log output is too low then this macro is used in place of tf_log()
 * below. The intent is to get the compiler to evaluate the function call for
 * type checking and format specifier correctness but let it optimize it out.
 */
#define no_tf_log(fmt, ...)				\
	do {						\
		if (false) {				\
			tf_log(fmt, ##__VA_ARGS__);	\
		}					\
	} while (false)

#if LOG_LEVEL >= LOG_LEVEL_ERROR
# define ERROR(...)	tf_log(LOG_MARKER_ERROR __VA_ARGS__)
# define ERROR_NL()	tf_log_newline(LOG_MARKER_ERROR)
#else
# define ERROR(...)	no_tf_log(LOG_MARKER_ERROR __VA_ARGS__)
# define ERROR_NL()
#endif

#if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...)	tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#else
# define NOTICE(...)	no_tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#endif

#if LOG_LEVEL >= LOG_LEVEL_WARNING
# define WARN(...)	tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#else
# define WARN(...)	no_tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#endif

#if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...)	tf_log(LOG_MARKER_INFO __VA_ARGS__)
#else
# define INFO(...)	no_tf_log(LOG_MARKER_INFO __VA_ARGS__)
#endif

#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
# define VERBOSE(...)	tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#else
# define VERBOSE(...)	no_tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#endif

const char *get_el_str(unsigned int el);

#if ENABLE_BACKTRACE
void backtrace(const char *cookie);
#else
#define backtrace(x)
#endif

void __dead2 el3_panic(void);
void __dead2 report_elx_panic(void);

#define panic()				\
	do {				\
		backtrace(__func__);	\
		console_flush();	\
		el3_panic();		\
	} while (false)

#if CRASH_REPORTING
/* --------------------------------------------------------------------
 * do_lower_el_panic assumes it's called due to a panic from a lower EL
 * This call will not return.
 * --------------------------------------------------------------------
 */
#define	lower_el_panic()		\
	do {				\
		console_flush();	\
		report_elx_panic();	\
	} while (false)
#else
#define	lower_el_panic()
#endif

/* Function called when stack protection check code detects a corrupted stack */
void __dead2 __stack_chk_fail(void);

void tf_log(const char *fmt, ...) __printflike(1, 2);
void tf_log_newline(const char log_fmt[2]);
void tf_log_set_max_level(unsigned int log_level);

#endif /* __ASSEMBLER__ */
#endif /* DEBUG_H */