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