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, 45*3f1540d6SSimon Glass LOGC_DM, /* Core driver-model */ 46*3f1540d6SSimon Glass LOGC_DT, /* Device-tree */ 47*3f1540d6SSimon Glass LOGC_EFI, /* EFI implementation */ 48*3f1540d6SSimon Glass LOGC_ALLOC, /* Memory allocation */ 499530301cSSimon Glass 509530301cSSimon Glass LOGC_COUNT, 519530301cSSimon Glass LOGC_END, 529530301cSSimon Glass }; 539530301cSSimon Glass 549530301cSSimon Glass /* Helper to cast a uclass ID to a log category */ 559530301cSSimon Glass static inline int log_uc_cat(enum uclass_id id) 569530301cSSimon Glass { 579530301cSSimon Glass return (enum log_category_t)id; 589530301cSSimon Glass } 599530301cSSimon Glass 609530301cSSimon Glass /** 619530301cSSimon Glass * _log() - Internal function to emit a new log record 629530301cSSimon Glass * 639530301cSSimon Glass * @cat: Category of log record (indicating which subsystem generated it) 649530301cSSimon Glass * @level: Level of log record (indicating its severity) 659530301cSSimon Glass * @file: File name of file where log record was generated 669530301cSSimon Glass * @line: Line number in file where log record was generated 679530301cSSimon Glass * @func: Function where log record was generated 689530301cSSimon Glass * @fmt: printf() format string for log record 699530301cSSimon Glass * @...: Optional parameters, according to the format string @fmt 709530301cSSimon Glass * @return 0 if log record was emitted, -ve on error 719530301cSSimon Glass */ 729530301cSSimon Glass int _log(enum log_category_t cat, enum log_level_t level, const char *file, 739530301cSSimon Glass int line, const char *func, const char *fmt, ...); 749530301cSSimon Glass 759530301cSSimon Glass /* Define this at the top of a file to add a prefix to debug messages */ 769530301cSSimon Glass #ifndef pr_fmt 779530301cSSimon Glass #define pr_fmt(fmt) fmt 789530301cSSimon Glass #endif 799530301cSSimon Glass 809530301cSSimon Glass /* Use a default category if this file does not supply one */ 819530301cSSimon Glass #ifndef LOG_CATEGORY 829530301cSSimon Glass #define LOG_CATEGORY LOGC_NONE 839530301cSSimon Glass #endif 849530301cSSimon Glass 859530301cSSimon Glass /* 869530301cSSimon Glass * This header may be including when CONFIG_LOG is disabled, in which case 879530301cSSimon Glass * CONFIG_LOG_MAX_LEVEL is not defined. Add a check for this. 889530301cSSimon Glass */ 899530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 909530301cSSimon Glass #define _LOG_MAX_LEVEL CONFIG_VAL(LOG_MAX_LEVEL) 919530301cSSimon Glass #else 929530301cSSimon Glass #define _LOG_MAX_LEVEL LOGL_INFO 939530301cSSimon Glass #endif 949530301cSSimon Glass 959530301cSSimon Glass /* Emit a log record if the level is less that the maximum */ 969530301cSSimon Glass #define log(_cat, _level, _fmt, _args...) ({ \ 979530301cSSimon Glass int _l = _level; \ 989530301cSSimon Glass if (_l <= _LOG_MAX_LEVEL) \ 999530301cSSimon Glass _log((enum log_category_t)(_cat), _l, __FILE__, __LINE__, \ 1009530301cSSimon Glass __func__, \ 1019530301cSSimon Glass pr_fmt(_fmt), ##_args); \ 1029530301cSSimon Glass }) 1039530301cSSimon Glass 10444aaaed1SSimon Glass #ifdef DEBUG 10544aaaed1SSimon Glass #define _DEBUG 1 10644aaaed1SSimon Glass #else 10744aaaed1SSimon Glass #define _DEBUG 0 10844aaaed1SSimon Glass #endif 10944aaaed1SSimon Glass 11044aaaed1SSimon Glass #ifdef CONFIG_SPL_BUILD 11144aaaed1SSimon Glass #define _SPL_BUILD 1 11244aaaed1SSimon Glass #else 11344aaaed1SSimon Glass #define _SPL_BUILD 0 11444aaaed1SSimon Glass #endif 11544aaaed1SSimon Glass 1169530301cSSimon Glass #if !_DEBUG && CONFIG_IS_ENABLED(LOG) 1179530301cSSimon Glass 1189530301cSSimon Glass #define debug_cond(cond, fmt, args...) \ 1199530301cSSimon Glass do { \ 1209530301cSSimon Glass if (1) \ 1219530301cSSimon Glass log(LOG_CATEGORY, LOGL_DEBUG, fmt, ##args); \ 1229530301cSSimon Glass } while (0) 1239530301cSSimon Glass 1249530301cSSimon Glass #else /* _DEBUG */ 1259530301cSSimon Glass 12644aaaed1SSimon Glass /* 12744aaaed1SSimon Glass * Output a debug text when condition "cond" is met. The "cond" should be 12844aaaed1SSimon Glass * computed by a preprocessor in the best case, allowing for the best 12944aaaed1SSimon Glass * optimization. 13044aaaed1SSimon Glass */ 13144aaaed1SSimon Glass #define debug_cond(cond, fmt, args...) \ 13244aaaed1SSimon Glass do { \ 13344aaaed1SSimon Glass if (cond) \ 13444aaaed1SSimon Glass printf(pr_fmt(fmt), ##args); \ 13544aaaed1SSimon Glass } while (0) 13644aaaed1SSimon Glass 1379530301cSSimon Glass #endif /* _DEBUG */ 1389530301cSSimon Glass 13944aaaed1SSimon Glass /* Show a message if DEBUG is defined in a file */ 14044aaaed1SSimon Glass #define debug(fmt, args...) \ 14144aaaed1SSimon Glass debug_cond(_DEBUG, fmt, ##args) 14244aaaed1SSimon Glass 14344aaaed1SSimon Glass /* Show a message if not in SPL */ 14444aaaed1SSimon Glass #define warn_non_spl(fmt, args...) \ 14544aaaed1SSimon Glass debug_cond(!_SPL_BUILD, fmt, ##args) 14644aaaed1SSimon Glass 14744aaaed1SSimon Glass /* 14844aaaed1SSimon Glass * An assertion is run-time check done in debug mode only. If DEBUG is not 14944aaaed1SSimon Glass * defined then it is skipped. If DEBUG is defined and the assertion fails, 15044aaaed1SSimon Glass * then it calls panic*( which may or may not reset/halt U-Boot (see 15144aaaed1SSimon Glass * CONFIG_PANIC_HANG), It is hoped that all failing assertions are found 15244aaaed1SSimon Glass * before release, and after release it is hoped that they don't matter. But 15344aaaed1SSimon Glass * in any case these failing assertions cannot be fixed with a reset (which 15444aaaed1SSimon Glass * may just do the same assertion again). 15544aaaed1SSimon Glass */ 15644aaaed1SSimon Glass void __assert_fail(const char *assertion, const char *file, unsigned int line, 15744aaaed1SSimon Glass const char *function); 15844aaaed1SSimon Glass #define assert(x) \ 15944aaaed1SSimon Glass ({ if (!(x) && _DEBUG) \ 16044aaaed1SSimon Glass __assert_fail(#x, __FILE__, __LINE__, __func__); }) 16144aaaed1SSimon Glass 1629530301cSSimon Glass /** 1639530301cSSimon Glass * struct log_rec - a single log record 1649530301cSSimon Glass * 1659530301cSSimon Glass * Holds information about a single record in the log 1669530301cSSimon Glass * 1679530301cSSimon Glass * Members marked as 'not allocated' are stored as pointers and the caller is 1689530301cSSimon Glass * responsible for making sure that the data pointed to is not overwritten. 1699530301cSSimon Glass * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log 1709530301cSSimon Glass * system. 1719530301cSSimon Glass * 1729530301cSSimon Glass * @cat: Category, representing a uclass or part of U-Boot 1739530301cSSimon Glass * @level: Severity level, less severe is higher 1749530301cSSimon Glass * @file: Name of file where the log record was generated (not allocated) 1759530301cSSimon Glass * @line: Line number where the log record was generated 1769530301cSSimon Glass * @func: Function where the log record was generated (not allocated) 1779530301cSSimon Glass * @msg: Log message (allocated) 1789530301cSSimon Glass */ 1799530301cSSimon Glass struct log_rec { 1809530301cSSimon Glass enum log_category_t cat; 1819530301cSSimon Glass enum log_level_t level; 1829530301cSSimon Glass const char *file; 1839530301cSSimon Glass int line; 1849530301cSSimon Glass const char *func; 1859530301cSSimon Glass const char *msg; 1869530301cSSimon Glass }; 1879530301cSSimon Glass 1889530301cSSimon Glass struct log_device; 1899530301cSSimon Glass 1909530301cSSimon Glass /** 1919530301cSSimon Glass * struct log_driver - a driver which accepts and processes log records 1929530301cSSimon Glass * 1939530301cSSimon Glass * @name: Name of driver 1949530301cSSimon Glass */ 1959530301cSSimon Glass struct log_driver { 1969530301cSSimon Glass const char *name; 1979530301cSSimon Glass /** 1989530301cSSimon Glass * emit() - emit a log record 1999530301cSSimon Glass * 2009530301cSSimon Glass * Called by the log system to pass a log record to a particular driver 2019530301cSSimon Glass * for processing. The filter is checked before calling this function. 2029530301cSSimon Glass */ 2039530301cSSimon Glass int (*emit)(struct log_device *ldev, struct log_rec *rec); 2049530301cSSimon Glass }; 2059530301cSSimon Glass 2069530301cSSimon Glass /** 2079530301cSSimon Glass * struct log_device - an instance of a log driver 2089530301cSSimon Glass * 2099530301cSSimon Glass * Since drivers are set up at build-time we need to have a separate device for 2109530301cSSimon Glass * the run-time aspects of drivers (currently just a list of filters to apply 2119530301cSSimon Glass * to records send to this device). 2129530301cSSimon Glass * 2139530301cSSimon Glass * @next_filter_num: Seqence number of next filter filter added (0=no filters 2149530301cSSimon Glass * yet). This increments with each new filter on the device, but never 2159530301cSSimon Glass * decrements 2169530301cSSimon Glass * @drv: Pointer to driver for this device 2179530301cSSimon Glass * @filter_head: List of filters for this device 2189530301cSSimon Glass * @sibling_node: Next device in the list of all devices 2199530301cSSimon Glass */ 2209530301cSSimon Glass struct log_device { 2219530301cSSimon Glass int next_filter_num; 2229530301cSSimon Glass struct log_driver *drv; 2239530301cSSimon Glass struct list_head filter_head; 2249530301cSSimon Glass struct list_head sibling_node; 2259530301cSSimon Glass }; 2269530301cSSimon Glass 2279530301cSSimon Glass enum { 2289530301cSSimon Glass LOGF_MAX_CATEGORIES = 5, /* maximum categories per filter */ 2299530301cSSimon Glass }; 2309530301cSSimon Glass 2319530301cSSimon Glass enum log_filter_flags { 2329530301cSSimon Glass LOGFF_HAS_CAT = 1 << 0, /* Filter has a category list */ 2339530301cSSimon Glass }; 2349530301cSSimon Glass 2359530301cSSimon Glass /** 2369530301cSSimon Glass * struct log_filter - criterial to filter out log messages 2379530301cSSimon Glass * 2389530301cSSimon Glass * @filter_num: Sequence number of this filter. This is returned when adding a 2399530301cSSimon Glass * new filter, and must be provided when removing a previously added 2409530301cSSimon Glass * filter. 2419530301cSSimon Glass * @flags: Flags for this filter (LOGFF_...) 2429530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 2439530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 2449530301cSSimon Glass * can be provided 2459530301cSSimon Glass * @max_level: Maximum log level to allow 2469530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 2479530301cSSimon Glass * files are permitted 2489530301cSSimon Glass * @sibling_node: Next filter in the list of filters for this log device 2499530301cSSimon Glass */ 2509530301cSSimon Glass struct log_filter { 2519530301cSSimon Glass int filter_num; 2529530301cSSimon Glass int flags; 2539530301cSSimon Glass enum log_category_t cat_list[LOGF_MAX_CATEGORIES]; 2549530301cSSimon Glass enum log_level_t max_level; 2559530301cSSimon Glass const char *file_list; 2569530301cSSimon Glass struct list_head sibling_node; 2579530301cSSimon Glass }; 2589530301cSSimon Glass 2599530301cSSimon Glass #define LOG_DRIVER(_name) \ 2609530301cSSimon Glass ll_entry_declare(struct log_driver, _name, log_driver) 2619530301cSSimon Glass 26273991b07SSimon Glass /* Handle the 'log test' command */ 26373991b07SSimon Glass int do_log_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); 26473991b07SSimon Glass 2659530301cSSimon Glass /** 2669530301cSSimon Glass * log_add_filter() - Add a new filter to a log device 2679530301cSSimon Glass * 2689530301cSSimon Glass * @drv_name: Driver name to add the filter to (since each driver only has a 2699530301cSSimon Glass * single device) 2709530301cSSimon Glass * @cat_list: List of categories to allow (terminated by LOGC_none). If empty 2719530301cSSimon Glass * then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries 2729530301cSSimon Glass * can be provided 2739530301cSSimon Glass * @max_level: Maximum log level to allow 2749530301cSSimon Glass * @file_list: List of files to allow, separated by comma. If NULL then all 2759530301cSSimon Glass * files are permitted 2769530301cSSimon Glass * @return the sequence number of the new filter (>=0) if the filter was added, 2779530301cSSimon Glass * or a -ve value on error 2789530301cSSimon Glass */ 2799530301cSSimon Glass int log_add_filter(const char *drv_name, enum log_category_t cat_list[], 2809530301cSSimon Glass enum log_level_t max_level, const char *file_list); 2819530301cSSimon Glass 2829530301cSSimon Glass /** 2839530301cSSimon Glass * log_remove_filter() - Remove a filter from a log device 2849530301cSSimon Glass * 2859530301cSSimon Glass * @drv_name: Driver name to remove the filter from (since each driver only has 2869530301cSSimon Glass * a single device) 2879530301cSSimon Glass * @filter_num: Filter number to remove (as returned by log_add_filter()) 2889530301cSSimon Glass * @return 0 if the filter was removed, -ENOENT if either the driver or the 2899530301cSSimon Glass * filter number was not found 2909530301cSSimon Glass */ 2919530301cSSimon Glass int log_remove_filter(const char *drv_name, int filter_num); 2929530301cSSimon Glass 2939530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG) 2949530301cSSimon Glass /** 2959530301cSSimon Glass * log_init() - Set up the log system ready for use 2969530301cSSimon Glass * 2979530301cSSimon Glass * @return 0 if OK, -ENOMEM if out of memory 2989530301cSSimon Glass */ 2999530301cSSimon Glass int log_init(void); 3009530301cSSimon Glass #else 3019530301cSSimon Glass static inline int log_init(void) 3029530301cSSimon Glass { 3039530301cSSimon Glass return 0; 3049530301cSSimon Glass } 3059530301cSSimon Glass #endif 3069530301cSSimon Glass 30744aaaed1SSimon Glass #endif 308