144aaaed1SSimon Glass /* 244aaaed1SSimon Glass * Logging support 344aaaed1SSimon Glass * 444aaaed1SSimon Glass * Copyright (c) 2017 Google, Inc 544aaaed1SSimon Glass * Written by Simon Glass <sjg@chromium.org> 644aaaed1SSimon Glass * 744aaaed1SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 844aaaed1SSimon Glass */ 944aaaed1SSimon Glass 1044aaaed1SSimon Glass #ifndef __LOG_H 1144aaaed1SSimon Glass #define __LOG_H 1244aaaed1SSimon Glass 13*9530301cSSimon Glass #include <dm/uclass-id.h> 14*9530301cSSimon Glass #include <linux/list.h> 15*9530301cSSimon Glass 16*9530301cSSimon Glass /** Log levels supported, ranging from most to least important */ 17*9530301cSSimon Glass enum log_level_t { 18*9530301cSSimon Glass LOGL_EMERG = 0, /*U-Boot is unstable */ 19*9530301cSSimon Glass LOGL_ALERT, /* Action must be taken immediately */ 20*9530301cSSimon Glass LOGL_CRIT, /* Critical conditions */ 21*9530301cSSimon Glass LOGL_ERR, /* Error that prevents something from working */ 22*9530301cSSimon Glass LOGL_WARNING, /* Warning may prevent optimial operation */ 23*9530301cSSimon Glass LOGL_NOTICE, /* Normal but significant condition, printf() */ 24*9530301cSSimon Glass LOGL_INFO, /* General information message */ 25*9530301cSSimon Glass LOGL_DEBUG, /* Basic debug-level message */ 26*9530301cSSimon Glass LOGL_DEBUG_CONTENT, /* Debug message showing full message content */ 27*9530301cSSimon Glass LOGL_DEBUG_IO, /* Debug message showing hardware I/O access */ 28*9530301cSSimon Glass 29*9530301cSSimon Glass LOGL_COUNT, 30*9530301cSSimon Glass LOGL_FIRST = LOGL_EMERG, 31*9530301cSSimon Glass LOGL_MAX = LOGL_DEBUG, 32*9530301cSSimon Glass }; 33*9530301cSSimon Glass 34*9530301cSSimon Glass /** 35*9530301cSSimon Glass * Log categories supported. Most of these correspond to uclasses (i.e. 36*9530301cSSimon Glass * enum uclass_id) but there are also some more generic categories 37*9530301cSSimon Glass */ 38*9530301cSSimon Glass enum log_category_t { 39*9530301cSSimon Glass LOGC_FIRST = 0, /* First part mirrors UCLASS_... */ 40*9530301cSSimon Glass 41*9530301cSSimon Glass LOGC_NONE = UCLASS_COUNT, 42*9530301cSSimon Glass LOGC_ARCH, 43*9530301cSSimon Glass LOGC_BOARD, 44*9530301cSSimon Glass LOGC_CORE, 45*9530301cSSimon Glass LOGC_DT, 46*9530301cSSimon Glass 47*9530301cSSimon Glass LOGC_COUNT, 48*9530301cSSimon Glass LOGC_END, 49*9530301cSSimon Glass }; 50*9530301cSSimon Glass 51*9530301cSSimon Glass /* Helper to cast a uclass ID to a log category */ 52*9530301cSSimon Glass static inline int log_uc_cat(enum uclass_id id) 53*9530301cSSimon Glass { 54*9530301cSSimon Glass return (enum log_category_t)id; 55*9530301cSSimon Glass } 56*9530301cSSimon Glass 57*9530301cSSimon Glass /** 58*9530301cSSimon Glass * _log() - Internal function to emit a new log record 59*9530301cSSimon Glass * 60*9530301cSSimon Glass * @cat: Category of log record (indicating which subsystem generated it) 61*9530301cSSimon Glass * @level: Level of log record (indicating its severity) 62*9530301cSSimon Glass * @file: File name of file where log record was generated 63*9530301cSSimon Glass * @line: Line number in file where log record was generated 64*9530301cSSimon Glass * @func: Function where log record was generated 65*9530301cSSimon Glass * @fmt: printf() format string for log record 66*9530301cSSimon Glass * @...: Optional parameters, according to the format string @fmt 67*9530301cSSimon Glass * @return 0 if log record was emitted, -ve on error 68*9530301cSSimon Glass */ 69*9530301cSSimon Glass int _log(enum log_category_t cat, enum log_level_t level, const char *file, 70*9530301cSSimon Glass int line, const char *func, const char *fmt, ...); 71*9530301cSSimon Glass 72*9530301cSSimon Glass /* Define this at the top of a file to add a prefix to debug messages */ 73*9530301cSSimon Glass #ifndef pr_fmt 74*9530301cSSimon Glass #define pr_fmt(fmt) fmt 75*9530301cSSimon Glass #endif 76*9530301cSSimon Glass 77*9530301cSSimon Glass /* Use a default category if this file does not supply one */ 78*9530301cSSimon Glass #ifndef LOG_CATEGORY 79*9530301cSSimon Glass #define LOG_CATEGORY LOGC_NONE 80*9530301cSSimon Glass #endif 81*9530301cSSimon Glass 82*9530301cSSimon Glass /* 83*9530301cSSimon Glass * This header may be including when CONFIG_LOG is disabled, in which case 84*9530301cSSimon Glass * CONFIG_LOG_MAX_LEVEL is not defined. Add a check for this. 85*9530301cSSimon Glass */ 86*9530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 87*9530301cSSimon Glass #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL) 88*9530301cSSimon Glass #else 89*9530301cSSimon Glass #define _LOG_MAX_LEVEL LOGL_INFO 90*9530301cSSimon Glass #endif 91*9530301cSSimon Glass 92*9530301cSSimon Glass /* Emit a log record if the level is less that the maximum */ 93*9530301cSSimon Glass #define log(_cat, _level, _fmt, _args...) ({ \ 94*9530301cSSimon Glass int _l = _level; \ 95*9530301cSSimon Glass if (_l <= _LOG_MAX_LEVEL) \ 96*9530301cSSimon Glass _log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \ 97*9530301cSSimon Glass __func__, \ 98*9530301cSSimon Glass pr_fmt(_fmt), ##_args); \ 99*9530301cSSimon Glass }) 100*9530301cSSimon Glass 10144aaaed1SSimon Glass #ifdef DEBUG 10244aaaed1SSimon Glass #define _DEBUG 1 10344aaaed1SSimon Glass #else 10444aaaed1SSimon Glass #define _DEBUG 0 10544aaaed1SSimon Glass #endif 10644aaaed1SSimon Glass 10744aaaed1SSimon Glass #ifdef CONFIG_SPL_BUILD 10844aaaed1SSimon Glass #define _SPL_BUILD 1 10944aaaed1SSimon Glass #else 11044aaaed1SSimon Glass #define _SPL_BUILD 0 11144aaaed1SSimon Glass #endif 11244aaaed1SSimon Glass 113*9530301cSSimon Glass #if !_DEBUG && CONFIG_IS_ENABLED(LOG) 114*9530301cSSimon Glass 115*9530301cSSimon Glass #define debug_cond(cond, fmt, args...) \ 116*9530301cSSimon Glass do { \ 117*9530301cSSimon Glass if (1) \ 118*9530301cSSimon Glass log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \ 119*9530301cSSimon Glass } while (0) 120*9530301cSSimon Glass 121*9530301cSSimon Glass #else /* _DEBUG */ 122*9530301cSSimon Glass 12344aaaed1SSimon Glass /* 12444aaaed1SSimon Glass * Output a debug text when condition "cond" is met. The "cond" should be 12544aaaed1SSimon Glass * computed by a preprocessor in the best case, allowing for the best 12644aaaed1SSimon Glass * optimization. 12744aaaed1SSimon Glass */ 12844aaaed1SSimon Glass #define debug_cond(cond, fmt, args...) \ 12944aaaed1SSimon Glass do { \ 13044aaaed1SSimon Glass if (cond) \ 13144aaaed1SSimon Glass printf(pr_fmt(fmt), ##args); \ 13244aaaed1SSimon Glass } while (0) 13344aaaed1SSimon Glass 134*9530301cSSimon Glass #endif /* _DEBUG */ 135*9530301cSSimon Glass 13644aaaed1SSimon Glass /* Show a message if DEBUG is defined in a file */ 13744aaaed1SSimon Glass #define debug(fmt, args...) \ 13844aaaed1SSimon Glass debug_cond(_DEBUG, fmt, ##args) 13944aaaed1SSimon Glass 14044aaaed1SSimon Glass /* Show a message if not in SPL */ 14144aaaed1SSimon Glass #define warn_non_spl(fmt, args...) \ 14244aaaed1SSimon Glass debug_cond(!_SPL_BUILD, fmt, ##args) 14344aaaed1SSimon Glass 14444aaaed1SSimon Glass /* 14544aaaed1SSimon Glass * An assertion is run-time check done in debug mode only. If DEBUG is not 14644aaaed1SSimon Glass * defined then it is skipped. If DEBUG is defined and the assertion fails, 14744aaaed1SSimon Glass * then it calls panic*( which may or may not reset/halt U-Boot (see 14844aaaed1SSimon Glass * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found 14944aaaed1SSimon Glass * before release, and after release it is hoped that they don't matter. But 15044aaaed1SSimon Glass * in any case these failing assertions cannot be fixed with a reset (which 15144aaaed1SSimon Glass * may just do the same assertion again). 15244aaaed1SSimon Glass */ 15344aaaed1SSimon Glass void __assert_fail(const char *assertion, const char *file, unsigned int line, 15444aaaed1SSimon Glass const char *function); 15544aaaed1SSimon Glass #define assert(x) \ 15644aaaed1SSimon Glass ({ if (!(x) && _DEBUG) \ 15744aaaed1SSimon Glass __assert_fail(#x, __FILE__, __LINE__, __func__); }) 15844aaaed1SSimon Glass 159*9530301cSSimon Glass /** 160*9530301cSSimon Glass * struct log_rec - a single log record 161*9530301cSSimon Glass * 162*9530301cSSimon Glass * Holds information about a single record in the log 163*9530301cSSimon Glass * 164*9530301cSSimon Glass * Members marked as 'not allocated' are stored as pointers and the caller is 165*9530301cSSimon Glass * responsible for making sure that the data pointed to is not overwritten. 166*9530301cSSimon Glass * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log 167*9530301cSSimon Glass * system. 168*9530301cSSimon Glass * 169*9530301cSSimon Glass * @cat: Category, representing a uclass or part of U-Boot 170*9530301cSSimon Glass * @level: Severity level, less severe is higher 171*9530301cSSimon Glass * @file: Name of file where the log record was generated (not allocated) 172*9530301cSSimon Glass * @line: Line number where the log record was generated 173*9530301cSSimon Glass * @func: Function where the log record was generated (not allocated) 174*9530301cSSimon Glass * @msg: Log message (allocated) 175*9530301cSSimon Glass */ 176*9530301cSSimon Glass struct log_rec { 177*9530301cSSimon Glass enum log_category_t cat; 178*9530301cSSimon Glass enum log_level_t level; 179*9530301cSSimon Glass const char *file; 180*9530301cSSimon Glass int line; 181*9530301cSSimon Glass const char *func; 182*9530301cSSimon Glass const char *msg; 183*9530301cSSimon Glass }; 184*9530301cSSimon Glass 185*9530301cSSimon Glass struct log_device; 186*9530301cSSimon Glass 187*9530301cSSimon Glass /** 188*9530301cSSimon Glass * struct log_driver - a driver which accepts and processes log records 189*9530301cSSimon Glass * 190*9530301cSSimon Glass * @name: Name of driver 191*9530301cSSimon Glass */ 192*9530301cSSimon Glass struct log_driver { 193*9530301cSSimon Glass const char *name; 194*9530301cSSimon Glass /** 195*9530301cSSimon Glass * emit() - emit a log record 196*9530301cSSimon Glass * 197*9530301cSSimon Glass * Called by the log system to pass a log record to a particular driver 198*9530301cSSimon Glass * for processing. The filter is checked before calling this function. 199*9530301cSSimon Glass */ 200*9530301cSSimon Glass int (*emit)(struct log_device *ldev, struct log_rec *rec); 201*9530301cSSimon Glass }; 202*9530301cSSimon Glass 203*9530301cSSimon Glass /** 204*9530301cSSimon Glass * struct log_device - an instance of a log driver 205*9530301cSSimon Glass * 206*9530301cSSimon Glass * Since drivers are set up at build-time we need to have a separate device for 207*9530301cSSimon Glass * the run-time aspects of drivers (currently just a list of filters to apply 208*9530301cSSimon Glass * to records send to this device). 209*9530301cSSimon Glass * 210*9530301cSSimon Glass * @next_filter_num: Seqence number of next filter filter added (0=no filters 211*9530301cSSimon Glass * yet). This increments with each new filter on the device, but never 212*9530301cSSimon Glass * decrements 213*9530301cSSimon Glass * @drv: Pointer to driver for this device 214*9530301cSSimon Glass * @filter_head: List of filters for this device 215*9530301cSSimon Glass * @sibling_node: Next device in the list of all devices 216*9530301cSSimon Glass */ 217*9530301cSSimon Glass struct log_device { 218*9530301cSSimon Glass int next_filter_num; 219*9530301cSSimon Glass struct log_driver *drv; 220*9530301cSSimon Glass struct list_head filter_head; 221*9530301cSSimon Glass struct list_head sibling_node; 222*9530301cSSimon Glass }; 223*9530301cSSimon Glass 224*9530301cSSimon Glass enum { 225*9530301cSSimon Glass LOGF_MAX_CATEGORIES = 5, /* maximum categories per filter */ 226*9530301cSSimon Glass }; 227*9530301cSSimon Glass 228*9530301cSSimon Glass enum log_filter_flags { 229*9530301cSSimon Glass LOGFF_HAS_CAT = 1 << 0, /* Filter has a category list */ 230*9530301cSSimon Glass }; 231*9530301cSSimon Glass 232*9530301cSSimon Glass /** 233*9530301cSSimon Glass * struct log_filter - criterial to filter out log messages 234*9530301cSSimon Glass * 235*9530301cSSimon Glass * @filter_num: Sequence number of this filter. This is returned when adding a 236*9530301cSSimon Glass * new filter, and must be provided when removing a previously added 237*9530301cSSimon Glass * filter. 238*9530301cSSimon Glass * @flags: Flags for this filter (LOGFF_...) 239*9530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 240*9530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 241*9530301cSSimon Glass * can be provided 242*9530301cSSimon Glass * @max_level: Maximum log level to allow 243*9530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 244*9530301cSSimon Glass * files are permitted 245*9530301cSSimon Glass * @sibling_node: Next filter in the list of filters for this log device 246*9530301cSSimon Glass */ 247*9530301cSSimon Glass struct log_filter { 248*9530301cSSimon Glass int filter_num; 249*9530301cSSimon Glass int flags; 250*9530301cSSimon Glass enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; 251*9530301cSSimon Glass enum log_level_t max_level; 252*9530301cSSimon Glass const char *file_list; 253*9530301cSSimon Glass struct list_head sibling_node; 254*9530301cSSimon Glass }; 255*9530301cSSimon Glass 256*9530301cSSimon Glass #define LOG_DRIVER(_name) \ 257*9530301cSSimon Glass ll_entry_declare(struct log_driver, _name, log_driver) 258*9530301cSSimon Glass 259*9530301cSSimon Glass /** 260*9530301cSSimon Glass * log_add_filter() - Add a new filter to a log device 261*9530301cSSimon Glass * 262*9530301cSSimon Glass * @drv_name: Driver name to add the filter to (since each driver only has a 263*9530301cSSimon Glass * single device) 264*9530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 265*9530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 266*9530301cSSimon Glass * can be provided 267*9530301cSSimon Glass * @max_level: Maximum log level to allow 268*9530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 269*9530301cSSimon Glass * files are permitted 270*9530301cSSimon Glass * @return the sequence number of the new filter (>=0) if the filter was added, 271*9530301cSSimon Glass * or a -ve value on error 272*9530301cSSimon Glass */ 273*9530301cSSimon Glass int log_add_filter(const char *drv_name, enum log_category_t cat_list[], 274*9530301cSSimon Glass enum log_level_t max_level, const char *file_list); 275*9530301cSSimon Glass 276*9530301cSSimon Glass /** 277*9530301cSSimon Glass * log_remove_filter() - Remove a filter from a log device 278*9530301cSSimon Glass * 279*9530301cSSimon Glass * @drv_name: Driver name to remove the filter from (since each driver only has 280*9530301cSSimon Glass * a single device) 281*9530301cSSimon Glass * @filter_num: Filter number to remove (as returned by log_add_filter()) 282*9530301cSSimon Glass * @return 0 if the filter was removed, -ENOENT if either the driver or the 283*9530301cSSimon Glass * filter number was not found 284*9530301cSSimon Glass */ 285*9530301cSSimon Glass int log_remove_filter(const char *drv_name, int filter_num); 286*9530301cSSimon Glass 287*9530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 288*9530301cSSimon Glass /** 289*9530301cSSimon Glass * log_init() - Set up the log system ready for use 290*9530301cSSimon Glass * 291*9530301cSSimon Glass * @return 0 if OK, -ENOMEM if out of memory 292*9530301cSSimon Glass */ 293*9530301cSSimon Glass int log_init(void); 294*9530301cSSimon Glass #else 295*9530301cSSimon Glass static inline int log_init(void) 296*9530301cSSimon Glass { 297*9530301cSSimon Glass return 0; 298*9530301cSSimon Glass } 299*9530301cSSimon Glass #endif 300*9530301cSSimon Glass 30144aaaed1SSimon Glass #endif 302