1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2020-2023, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #ifndef FWK_LOG_H
9 #define FWK_LOG_H
10 
11 #include <fwk_attributes.h>
12 #include <fwk_io.h>
13 #include <fwk_macros.h>
14 
15 #if FWK_HAS_INCLUDE(<fmw_log.h>)
16 #    include <fmw_log.h> /* cppcheck-suppress missingIncludeSystem */
17 #endif
18 
19 /*!
20  * \addtogroup GroupLibFramework Framework
21  * \{
22  */
23 
24 /*!
25  * \addtogroup GroupLogging Logging
26  *
27  *  \details This framework component provides logging facilities to the
28  *      firmware. It is intended to be simple and flexible to enable robust
29  *      string logging for user consumption.
30  *
31  *      This component provides five filter levels for logging messages.
32  *      Log messages are assigned a filter level based on the logging macro
33  *      used. These macros are as follows:
34  *
35  *       - ::FWK_LOG_DEBUG
36  *       - ::FWK_LOG_INFO
37  *       - ::FWK_LOG_WARN
38  *       - ::FWK_LOG_ERR
39  *       - ::FWK_LOG_CRIT
40  *
41  *      For a brief description of the meaning of each level, see the
42  *      documentation for each macro.
43  *
44  *      The value of the `FWK_LOG_LEVEL` macro, which can be set through the
45  *      build system configuration options, determines the minimum level a log
46  *      message must be for it to be included in the binary.
47  *
48  *      If buffering has been enabled then log messages may be buffered to
49  *      reduce overall firmware response latency; these buffered log messages
50  *      will be flushed once the system has reached an idle state. By default,
51  *      buffering is disabled in debug mode and enabled for all platforms in
52  *      release mode, but this behaviour can be adjusted by configuring
53  *      ::FMW_LOG_BUFFER_SIZE.
54  *
55  *      The device used for logging can also be adjusted through
56  *      ::FMW_LOG_DRAIN_ID. The default behaviour resorts to using the entity
57  *      described by ::FMW_IO_STDOUT_ID as the logging device.
58  *
59  *      If a message is too large to fit into the remaining space of the
60  *      internal buffer, the message will be dropped.
61  *
62  *      Note that log messages are terminated at the column dictated by
63  *      ::FMW_LOG_COLUMNS, or the earliest newline.
64  * \{
65  */
66 
67 /*!
68  * \def FMW_LOG_DRAIN_ID
69  *
70  * \brief Identifier of the log drain.
71  *
72  * \details The log drain represents an entity to which logging messages will
73  *      be written, and defaults to ::FMW_IO_STDOUT_ID. Replacing the log drain
74  *      identifier allows log messages and normal input/output to be separated.
75  */
76 #ifndef FMW_LOG_DRAIN_ID
77 #    define FMW_LOG_DRAIN_ID FMW_IO_STDOUT_ID
78 #endif
79 
80 /*!
81  * \def FMW_LOG_BUFFER_SIZE
82  *
83  * \brief Size of the internal log buffer in bytes.
84  *
85  * \details Log messages, for reasons of performance, are buffered unless an
86  *      always-on backend is currently in use (and a dynamic backend is not).
87  *      This definition dictates the size of the buffer, and can be overridden
88  *      by each individual firmware through a definition in a `<fmw_log.h>`
89  *      header.
90  *
91  * \note This definition has a default value of four kilobytes in release builds
92  *      and zero in debug builds.
93  *
94  * \note Setting this definition to a value of `0` will disable buffering. If
95  *      buffering is disabled, messages will be transmitted immediately.
96  */
97 
98 #ifndef FMW_LOG_BUFFER_SIZE
99 #    ifdef BUILD_MODE_DEBUG
100 #        define FMW_LOG_BUFFER_SIZE 0
101 #    else
102 #        define FMW_LOG_BUFFER_SIZE (4 * FWK_KIB)
103 #    endif
104 #endif
105 
106 #if FMW_LOG_BUFFER_SIZE > 0
107 /*!
108  * \def FWK_LOG_BUFFERED
109  *
110  * \brief Determines whether buffering has been enabled within the logging
111  *      framework.
112  */
113 #    define FWK_LOG_BUFFERED
114 #endif
115 
116 /*!
117  * \def FMW_LOG_COLUMNS
118  *
119  * \brief Number of columns per line the framework will limit itself to.
120  *
121  * \details Messages printed using any of the logging functions will be limited
122  *      to this column count.
123  *
124  * \note This definition has a default value of `80`.
125  */
126 
127 #ifndef FMW_LOG_COLUMNS
128 #    define FMW_LOG_COLUMNS 80
129 #endif
130 
131 /*!
132  * \addtogroup GroupLoggingLevels Filter Levels
133  *
134  * \details The logging framework uses *filter levels* to rank the criticality
135  *      of messages, and to filter them if desired. Filtering happens at
136  *      preprocessing-time, and consequently filtered messages do not contribute
137  *      to the image.
138  * \{
139  */
140 
141 /*!
142  * \def FWK_LOG_LEVEL_DEBUG
143  *
144  * \brief *Debug* filter level.
145  *
146  * \details Messages assigned this filter level represent messages used for
147  *      diagnosing problems.
148  *
149  * \def FWK_LOG_LEVEL_INFO
150  *
151  * \brief *Informational* log level.
152  *
153  * \details Messages assigned this filter level represent informational
154  *      messages.
155  *
156  * \def FWK_LOG_LEVEL_WARN
157  *
158  * \brief *Warning* log level.
159  *
160  * \details Messages assigned this filter level represent warnings about
161  *      possible errors.
162  *
163  * \def FWK_LOG_LEVEL_ERROR
164  *
165  * \brief *Error* log level.
166  *
167  * \details Messages assigned this filter level represent non-fatal errors.
168  *
169  * \def FWK_LOG_LEVEL_CRIT
170  *
171  * \brief *Critical* log level.
172  *
173  * \details Messages assigned this filter level represent fatal errors.
174  */
175 
176 #define FWK_LOG_LEVEL_DEBUG 0
177 #define FWK_LOG_LEVEL_INFO 1
178 #define FWK_LOG_LEVEL_WARN 2
179 #define FWK_LOG_LEVEL_ERROR 3
180 #define FWK_LOG_LEVEL_CRIT 4
181 
182 /*!
183  * \}
184  */
185 
186 /*!
187  * \brief Flush the logging backend.
188  *
189  * \details Flushing ensures that all data buffered by either the framework or
190  *      the logging backend has been fully written to all logging backends
191  *      before the function returns.
192  *
193  * \warning Flushing can be an expensive operation, and should only be used when
194  *      you absolutely need to make sure there is no more buffered data (such
195  *      as before powering down a logging backend).
196  */
197 #define FWK_LOG_FLUSH() fwk_log_flush()
198 
199 /*!
200  * \def FWK_TRACE
201  *
202  * \brief Trace a message.
203  *
204  * \param[in] ... Format string and any associated parameters.
205  */
206 
207 #ifdef FWK_TRACE_ENABLE
208 #    define FWK_TRACE(...) fwk_log_printf(__VA_ARGS__)
209 #else
210 #    define FWK_TRACE(...)
211 #endif
212 
213 /*!
214  * \def FWK_LOG_DEBUG
215  *
216  * \brief Log a [debug](::FWK_LOG_LEVEL_DEBUG) message.
217  *
218  * \param[in] ... Format string and any associated parameters.
219  */
220 
221 #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_DEBUG
222 #    define FWK_LOG_DEBUG(...) fwk_log_printf(__VA_ARGS__)
223 #else
224 #    define FWK_LOG_DEBUG(...)
225 #endif
226 
227 /*!
228  * \def FWK_LOG_INFO
229  *
230  * \brief Log an [informational](::FWK_LOG_LEVEL_INFO) message.
231  *
232  * \param[in] ... Format string and any associated parameters.
233  */
234 
235 #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_INFO
236 #    define FWK_LOG_INFO(...) fwk_log_printf(__VA_ARGS__)
237 #else
238 #    define FWK_LOG_INFO(...)
239 #endif
240 
241 /*!
242  * \def FWK_LOG_WARN
243  *
244  * \brief Log a [warning](::FWK_LOG_LEVEL_WARN) message.
245  *
246  * \param[in] ... Format string and any associated parameters.
247  */
248 
249 #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_WARN
250 #    define FWK_LOG_WARN(...) fwk_log_printf(__VA_ARGS__)
251 #else
252 #    define FWK_LOG_WARN(...)
253 #endif
254 
255 /*!
256  * \def FWK_LOG_ERR
257  *
258  * \brief Log an [error](::FWK_LOG_LEVEL_ERROR) message.
259  *
260  * \param[in] ... Format string and any associated parameters.
261  */
262 
263 #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_ERROR
264 #    define FWK_LOG_ERR(...) fwk_log_printf(__VA_ARGS__)
265 #else
266 #    define FWK_LOG_ERR(...)
267 #endif
268 
269 /*!
270  * \def FWK_LOG_CRIT
271  *
272  * \brief Log a [critical](::FWK_LOG_LEVEL_CRIT) message.
273  *
274  * \param[in] ... Format string and any associated parameters.
275  */
276 
277 #if FWK_LOG_LEVEL <= FWK_LOG_LEVEL_CRIT
278 #    define FWK_LOG_CRIT(...) fwk_log_printf(__VA_ARGS__)
279 #else
280 #    define FWK_LOG_CRIT(...)
281 #endif
282 
283 /*!
284  * \internal
285  *
286  * \brief Log a message with a specified filter level.
287  *
288  * \param[in] format Format string.
289  * \param[in] ... Associated parameters.
290  */
291 void fwk_log_printf(const char *format, ...) FWK_PRINTF(1, 2);
292 
293 /*!
294  * \internal
295  *
296  * \brief Flush the logging backend(s).
297  */
298 void fwk_log_flush(void);
299 
300 /*!
301  * \internal
302  *
303  * \brief Unbuffer a single character and send it to the logging backend.
304  *
305  * \details This function is reserved for the framework implementation, and is
306  *      used by the scheduler to print opportunistically when idling, and when
307  *      flushing to flush the buffer to the logging backend.
308  *
309  * \retval ::FWK_PENDING The character was unbuffered successfully but there are
310  *      still characters remaining in the buffer.
311  * \retval ::FWK_SUCCESS The character was unbuffered successfully and the
312  *      buffer is now empty.
313  * \retval ::FWK_E_DEVICE The backend returned an error.
314  *
315  * \return Status code representing the result of the operation.
316  */
317 int fwk_log_unbuffer(void);
318 
319 /*!
320  * \internal
321  *
322  * \brief Initialize the logging component.
323  *
324  * \details Initializes the logging framework component, making logging
325  *      facilities to the framework and, later, modules.
326  *
327  * \return Status code representing the result of the operation.
328  */
329 int fwk_log_init(void);
330 
331 /*!
332  * \}
333  */
334 
335 /*!
336  * \}
337  */
338 
339 #endif /* FWK_LOG_H */
340