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 139530301cSSimon Glass #include <dm/uclass-id.h> 149530301cSSimon Glass #include <linux/list.h> 159530301cSSimon Glass 169530301cSSimon Glass /** Log levels supported, ranging from most to least important */ 179530301cSSimon Glass enum log_level_t { 189530301cSSimon Glass LOGL_EMERG = 0, /*U-Boot is unstable */ 199530301cSSimon Glass LOGL_ALERT, /* Action must be taken immediately */ 209530301cSSimon Glass LOGL_CRIT, /* Critical conditions */ 219530301cSSimon Glass LOGL_ERR, /* Error that prevents something from working */ 229530301cSSimon Glass LOGL_WARNING, /* Warning may prevent optimial operation */ 239530301cSSimon Glass LOGL_NOTICE, /* Normal but significant condition, printf() */ 249530301cSSimon Glass LOGL_INFO, /* General information message */ 259530301cSSimon Glass LOGL_DEBUG, /* Basic debug-level message */ 269530301cSSimon Glass LOGL_DEBUG_CONTENT, /* Debug message showing full message content */ 279530301cSSimon Glass LOGL_DEBUG_IO, /* Debug message showing hardware I/O access */ 289530301cSSimon Glass 299530301cSSimon Glass LOGL_COUNT, 309530301cSSimon Glass LOGL_FIRST = LOGL_EMERG, 319530301cSSimon Glass LOGL_MAX = LOGL_DEBUG, 329530301cSSimon Glass }; 339530301cSSimon Glass 349530301cSSimon Glass /** 359530301cSSimon Glass * Log categories supported. Most of these correspond to uclasses (i.e. 369530301cSSimon Glass * enum uclass_id) but there are also some more generic categories 379530301cSSimon Glass */ 389530301cSSimon Glass enum log_category_t { 399530301cSSimon Glass LOGC_FIRST = 0, /* First part mirrors UCLASS_... */ 409530301cSSimon Glass 419530301cSSimon Glass LOGC_NONE = UCLASS_COUNT, 429530301cSSimon Glass LOGC_ARCH, 439530301cSSimon Glass LOGC_BOARD, 449530301cSSimon Glass LOGC_CORE, 459530301cSSimon Glass LOGC_DT, 469530301cSSimon Glass 479530301cSSimon Glass LOGC_COUNT, 489530301cSSimon Glass LOGC_END, 499530301cSSimon Glass }; 509530301cSSimon Glass 519530301cSSimon Glass /* Helper to cast a uclass ID to a log category */ 529530301cSSimon Glass static inline int log_uc_cat(enum uclass_id id) 539530301cSSimon Glass { 549530301cSSimon Glass return (enum log_category_t)id; 559530301cSSimon Glass } 569530301cSSimon Glass 579530301cSSimon Glass /** 589530301cSSimon Glass * _log() - Internal function to emit a new log record 599530301cSSimon Glass * 609530301cSSimon Glass * @cat: Category of log record (indicating which subsystem generated it) 619530301cSSimon Glass * @level: Level of log record (indicating its severity) 629530301cSSimon Glass * @file: File name of file where log record was generated 639530301cSSimon Glass * @line: Line number in file where log record was generated 649530301cSSimon Glass * @func: Function where log record was generated 659530301cSSimon Glass * @fmt: printf() format string for log record 669530301cSSimon Glass * @...: Optional parameters, according to the format string @fmt 679530301cSSimon Glass * @return 0 if log record was emitted, -ve on error 689530301cSSimon Glass */ 699530301cSSimon Glass int _log(enum log_category_t cat, enum log_level_t level, const char *file, 709530301cSSimon Glass int line, const char *func, const char *fmt, ...); 719530301cSSimon Glass 729530301cSSimon Glass /* Define this at the top of a file to add a prefix to debug messages */ 739530301cSSimon Glass #ifndef pr_fmt 749530301cSSimon Glass #define pr_fmt(fmt) fmt 759530301cSSimon Glass #endif 769530301cSSimon Glass 779530301cSSimon Glass /* Use a default category if this file does not supply one */ 789530301cSSimon Glass #ifndef LOG_CATEGORY 799530301cSSimon Glass #define LOG_CATEGORY LOGC_NONE 809530301cSSimon Glass #endif 819530301cSSimon Glass 829530301cSSimon Glass /* 839530301cSSimon Glass * This header may be including when CONFIG_LOG is disabled, in which case 849530301cSSimon Glass * CONFIG_LOG_MAX_LEVEL is not defined. Add a check for this. 859530301cSSimon Glass */ 869530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 879530301cSSimon Glass #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL) 889530301cSSimon Glass #else 899530301cSSimon Glass #define _LOG_MAX_LEVEL LOGL_INFO 909530301cSSimon Glass #endif 919530301cSSimon Glass 929530301cSSimon Glass /* Emit a log record if the level is less that the maximum */ 939530301cSSimon Glass #define log(_cat, _level, _fmt, _args...) ({ \ 949530301cSSimon Glass int _l = _level; \ 959530301cSSimon Glass if (_l <= _LOG_MAX_LEVEL) \ 969530301cSSimon Glass _log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \ 979530301cSSimon Glass __func__, \ 989530301cSSimon Glass pr_fmt(_fmt), ##_args); \ 999530301cSSimon Glass }) 1009530301cSSimon 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 1139530301cSSimon Glass #if !_DEBUG && CONFIG_IS_ENABLED(LOG) 1149530301cSSimon Glass 1159530301cSSimon Glass #define debug_cond(cond, fmt, args...) \ 1169530301cSSimon Glass do { \ 1179530301cSSimon Glass if (1) \ 1189530301cSSimon Glass log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \ 1199530301cSSimon Glass } while (0) 1209530301cSSimon Glass 1219530301cSSimon Glass #else /* _DEBUG */ 1229530301cSSimon 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 1349530301cSSimon Glass #endif /* _DEBUG */ 1359530301cSSimon 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 1599530301cSSimon Glass /** 1609530301cSSimon Glass * struct log_rec - a single log record 1619530301cSSimon Glass * 1629530301cSSimon Glass * Holds information about a single record in the log 1639530301cSSimon Glass * 1649530301cSSimon Glass * Members marked as 'not allocated' are stored as pointers and the caller is 1659530301cSSimon Glass * responsible for making sure that the data pointed to is not overwritten. 1669530301cSSimon Glass * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log 1679530301cSSimon Glass * system. 1689530301cSSimon Glass * 1699530301cSSimon Glass * @cat: Category, representing a uclass or part of U-Boot 1709530301cSSimon Glass * @level: Severity level, less severe is higher 1719530301cSSimon Glass * @file: Name of file where the log record was generated (not allocated) 1729530301cSSimon Glass * @line: Line number where the log record was generated 1739530301cSSimon Glass * @func: Function where the log record was generated (not allocated) 1749530301cSSimon Glass * @msg: Log message (allocated) 1759530301cSSimon Glass */ 1769530301cSSimon Glass struct log_rec { 1779530301cSSimon Glass enum log_category_t cat; 1789530301cSSimon Glass enum log_level_t level; 1799530301cSSimon Glass const char *file; 1809530301cSSimon Glass int line; 1819530301cSSimon Glass const char *func; 1829530301cSSimon Glass const char *msg; 1839530301cSSimon Glass }; 1849530301cSSimon Glass 1859530301cSSimon Glass struct log_device; 1869530301cSSimon Glass 1879530301cSSimon Glass /** 1889530301cSSimon Glass * struct log_driver - a driver which accepts and processes log records 1899530301cSSimon Glass * 1909530301cSSimon Glass * @name: Name of driver 1919530301cSSimon Glass */ 1929530301cSSimon Glass struct log_driver { 1939530301cSSimon Glass const char *name; 1949530301cSSimon Glass /** 1959530301cSSimon Glass * emit() - emit a log record 1969530301cSSimon Glass * 1979530301cSSimon Glass * Called by the log system to pass a log record to a particular driver 1989530301cSSimon Glass * for processing. The filter is checked before calling this function. 1999530301cSSimon Glass */ 2009530301cSSimon Glass int (*emit)(struct log_device *ldev, struct log_rec *rec); 2019530301cSSimon Glass }; 2029530301cSSimon Glass 2039530301cSSimon Glass /** 2049530301cSSimon Glass * struct log_device - an instance of a log driver 2059530301cSSimon Glass * 2069530301cSSimon Glass * Since drivers are set up at build-time we need to have a separate device for 2079530301cSSimon Glass * the run-time aspects of drivers (currently just a list of filters to apply 2089530301cSSimon Glass * to records send to this device). 2099530301cSSimon Glass * 2109530301cSSimon Glass * @next_filter_num: Seqence number of next filter filter added (0=no filters 2119530301cSSimon Glass * yet). This increments with each new filter on the device, but never 2129530301cSSimon Glass * decrements 2139530301cSSimon Glass * @drv: Pointer to driver for this device 2149530301cSSimon Glass * @filter_head: List of filters for this device 2159530301cSSimon Glass * @sibling_node: Next device in the list of all devices 2169530301cSSimon Glass */ 2179530301cSSimon Glass struct log_device { 2189530301cSSimon Glass int next_filter_num; 2199530301cSSimon Glass struct log_driver *drv; 2209530301cSSimon Glass struct list_head filter_head; 2219530301cSSimon Glass struct list_head sibling_node; 2229530301cSSimon Glass }; 2239530301cSSimon Glass 2249530301cSSimon Glass enum { 2259530301cSSimon Glass LOGF_MAX_CATEGORIES = 5, /* maximum categories per filter */ 2269530301cSSimon Glass }; 2279530301cSSimon Glass 2289530301cSSimon Glass enum log_filter_flags { 2299530301cSSimon Glass LOGFF_HAS_CAT = 1 << 0, /* Filter has a category list */ 2309530301cSSimon Glass }; 2319530301cSSimon Glass 2329530301cSSimon Glass /** 2339530301cSSimon Glass * struct log_filter - criterial to filter out log messages 2349530301cSSimon Glass * 2359530301cSSimon Glass * @filter_num: Sequence number of this filter. This is returned when adding a 2369530301cSSimon Glass * new filter, and must be provided when removing a previously added 2379530301cSSimon Glass * filter. 2389530301cSSimon Glass * @flags: Flags for this filter (LOGFF_...) 2399530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 2409530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 2419530301cSSimon Glass * can be provided 2429530301cSSimon Glass * @max_level: Maximum log level to allow 2439530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 2449530301cSSimon Glass * files are permitted 2459530301cSSimon Glass * @sibling_node: Next filter in the list of filters for this log device 2469530301cSSimon Glass */ 2479530301cSSimon Glass struct log_filter { 2489530301cSSimon Glass int filter_num; 2499530301cSSimon Glass int flags; 2509530301cSSimon Glass enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; 2519530301cSSimon Glass enum log_level_t max_level; 2529530301cSSimon Glass const char *file_list; 2539530301cSSimon Glass struct list_head sibling_node; 2549530301cSSimon Glass }; 2559530301cSSimon Glass 2569530301cSSimon Glass #define LOG_DRIVER(_name) \ 2579530301cSSimon Glass ll_entry_declare(struct log_driver, _name, log_driver) 2589530301cSSimon Glass 259*73991b07SSimon Glass /* Handle the 'log test' command */ 260*73991b07SSimon Glass int do_log_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); 261*73991b07SSimon Glass 2629530301cSSimon Glass /** 2639530301cSSimon Glass * log_add_filter() - Add a new filter to a log device 2649530301cSSimon Glass * 2659530301cSSimon Glass * @drv_name: Driver name to add the filter to (since each driver only has a 2669530301cSSimon Glass * single device) 2679530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 2689530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 2699530301cSSimon Glass * can be provided 2709530301cSSimon Glass * @max_level: Maximum log level to allow 2719530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 2729530301cSSimon Glass * files are permitted 2739530301cSSimon Glass * @return the sequence number of the new filter (>=0) if the filter was added, 2749530301cSSimon Glass * or a -ve value on error 2759530301cSSimon Glass */ 2769530301cSSimon Glass int log_add_filter(const char *drv_name, enum log_category_t cat_list[], 2779530301cSSimon Glass enum log_level_t max_level, const char *file_list); 2789530301cSSimon Glass 2799530301cSSimon Glass /** 2809530301cSSimon Glass * log_remove_filter() - Remove a filter from a log device 2819530301cSSimon Glass * 2829530301cSSimon Glass * @drv_name: Driver name to remove the filter from (since each driver only has 2839530301cSSimon Glass * a single device) 2849530301cSSimon Glass * @filter_num: Filter number to remove (as returned by log_add_filter()) 2859530301cSSimon Glass * @return 0 if the filter was removed, -ENOENT if either the driver or the 2869530301cSSimon Glass * filter number was not found 2879530301cSSimon Glass */ 2889530301cSSimon Glass int log_remove_filter(const char *drv_name, int filter_num); 2899530301cSSimon Glass 2909530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 2919530301cSSimon Glass /** 2929530301cSSimon Glass * log_init() - Set up the log system ready for use 2939530301cSSimon Glass * 2949530301cSSimon Glass * @return 0 if OK, -ENOMEM if out of memory 2959530301cSSimon Glass */ 2969530301cSSimon Glass int log_init(void); 2979530301cSSimon Glass #else 2989530301cSSimon Glass static inline int log_init(void) 2999530301cSSimon Glass { 3009530301cSSimon Glass return 0; 3019530301cSSimon Glass } 3029530301cSSimon Glass #endif 3039530301cSSimon Glass 30444aaaed1SSimon Glass #endif 305