xref: /rk3399_rockchip-uboot/include/log.h (revision 519ddfff4fa792342eabdc5badc5603d90024765)
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,
453f1540d6SSimon Glass 	LOGC_DM,	/* Core driver-model */
463f1540d6SSimon Glass 	LOGC_DT,	/* Device-tree */
473f1540d6SSimon Glass 	LOGC_EFI,	/* EFI implementation */
483f1540d6SSimon 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 */
log_uc_cat(enum uclass_id id)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 
162*519ddfffSSimon Glass #ifdef CONFIG_LOG_ERROR_RETURN
163*519ddfffSSimon Glass #define log_ret(_ret) ({ \
164*519ddfffSSimon Glass 	int __ret = (_ret); \
165*519ddfffSSimon Glass 	if (__ret < 0) \
166*519ddfffSSimon Glass 		log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \
167*519ddfffSSimon Glass 	__ret; \
168*519ddfffSSimon Glass 	})
169*519ddfffSSimon Glass #define log_msg_ret(_msg, _ret) ({ \
170*519ddfffSSimon Glass 	int __ret = (_ret); \
171*519ddfffSSimon Glass 	if (__ret < 0) \
172*519ddfffSSimon Glass 		log(LOG_CATEGORY, LOGL_ERR, "%s: returning err=%d\n", _msg, \
173*519ddfffSSimon Glass 		    __ret); \
174*519ddfffSSimon Glass 	__ret; \
175*519ddfffSSimon Glass 	})
176*519ddfffSSimon Glass #else
177*519ddfffSSimon Glass #define log_ret(_ret) (_ret)
178*519ddfffSSimon Glass #define log_msg_ret(_msg, _ret) (_ret)
179*519ddfffSSimon Glass #endif
180*519ddfffSSimon Glass 
1819530301cSSimon Glass /**
1829530301cSSimon Glass  * struct log_rec - a single log record
1839530301cSSimon Glass  *
1849530301cSSimon Glass  * Holds information about a single record in the log
1859530301cSSimon Glass  *
1869530301cSSimon Glass  * Members marked as 'not allocated' are stored as pointers and the caller is
1879530301cSSimon Glass  * responsible for making sure that the data pointed to is not overwritten.
1889530301cSSimon Glass  * Memebers marked as 'allocated' are allocated (e.g. via strdup()) by the log
1899530301cSSimon Glass  * system.
1909530301cSSimon Glass  *
1919530301cSSimon Glass  * @cat: Category, representing a uclass or part of U-Boot
1929530301cSSimon Glass  * @level: Severity level, less severe is higher
1939530301cSSimon Glass  * @file: Name of file where the log record was generated (not allocated)
1949530301cSSimon Glass  * @line: Line number where the log record was generated
1959530301cSSimon Glass  * @func: Function where the log record was generated (not allocated)
1969530301cSSimon Glass  * @msg: Log message (allocated)
1979530301cSSimon Glass  */
1989530301cSSimon Glass struct log_rec {
1999530301cSSimon Glass 	enum log_category_t cat;
2009530301cSSimon Glass 	enum log_level_t level;
2019530301cSSimon Glass 	const char *file;
2029530301cSSimon Glass 	int line;
2039530301cSSimon Glass 	const char *func;
2049530301cSSimon Glass 	const char *msg;
2059530301cSSimon Glass };
2069530301cSSimon Glass 
2079530301cSSimon Glass struct log_device;
2089530301cSSimon Glass 
2099530301cSSimon Glass /**
2109530301cSSimon Glass  * struct log_driver - a driver which accepts and processes log records
2119530301cSSimon Glass  *
2129530301cSSimon Glass  * @name: Name of driver
2139530301cSSimon Glass  */
2149530301cSSimon Glass struct log_driver {
2159530301cSSimon Glass 	const char *name;
2169530301cSSimon Glass 	/**
2179530301cSSimon Glass 	 * emit() - emit a log record
2189530301cSSimon Glass 	 *
2199530301cSSimon Glass 	 * Called by the log system to pass a log record to a particular driver
2209530301cSSimon Glass 	 * for processing. The filter is checked before calling this function.
2219530301cSSimon Glass 	 */
2229530301cSSimon Glass 	int (*emit)(struct log_device *ldev, struct log_rec *rec);
2239530301cSSimon Glass };
2249530301cSSimon Glass 
2259530301cSSimon Glass /**
2269530301cSSimon Glass  * struct log_device - an instance of a log driver
2279530301cSSimon Glass  *
2289530301cSSimon Glass  * Since drivers are set up at build-time we need to have a separate device for
2299530301cSSimon Glass  * the run-time aspects of drivers (currently just a list of filters to apply
2309530301cSSimon Glass  * to records send to this device).
2319530301cSSimon Glass  *
2329530301cSSimon Glass  * @next_filter_num: Seqence number of next filter filter added (0=no filters
2339530301cSSimon Glass  *	yet). This increments with each new filter on the device, but never
2349530301cSSimon Glass  *	decrements
2359530301cSSimon Glass  * @drv: Pointer to driver for this device
2369530301cSSimon Glass  * @filter_head: List of filters for this device
2379530301cSSimon Glass  * @sibling_node: Next device in the list of all devices
2389530301cSSimon Glass  */
2399530301cSSimon Glass struct log_device {
2409530301cSSimon Glass 	int next_filter_num;
2419530301cSSimon Glass 	struct log_driver *drv;
2429530301cSSimon Glass 	struct list_head filter_head;
2439530301cSSimon Glass 	struct list_head sibling_node;
2449530301cSSimon Glass };
2459530301cSSimon Glass 
2469530301cSSimon Glass enum {
2479530301cSSimon Glass 	LOGF_MAX_CATEGORIES = 5,	/* maximum categories per filter */
2489530301cSSimon Glass };
2499530301cSSimon Glass 
2509530301cSSimon Glass enum log_filter_flags {
2519530301cSSimon Glass 	LOGFF_HAS_CAT		= 1 << 0,	/* Filter has a category list */
2529530301cSSimon Glass };
2539530301cSSimon Glass 
2549530301cSSimon Glass /**
2559530301cSSimon Glass  * struct log_filter - criterial to filter out log messages
2569530301cSSimon Glass  *
2579530301cSSimon Glass  * @filter_num: Sequence number of this filter.  This is returned when adding a
2589530301cSSimon Glass  *	new filter, and must be provided when removing a previously added
2599530301cSSimon Glass  *	filter.
2609530301cSSimon Glass  * @flags: Flags for this filter (LOGFF_...)
2619530301cSSimon Glass  * @cat_list: List of categories to allow (terminated by LOGC_none). If empty
2629530301cSSimon Glass  *	then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries
2639530301cSSimon Glass  *	can be provided
2649530301cSSimon Glass  * @max_level: Maximum log level to allow
2659530301cSSimon Glass  * @file_list: List of files to allow, separated by comma. If NULL then all
2669530301cSSimon Glass  *	files are permitted
2679530301cSSimon Glass  * @sibling_node: Next filter in the list of filters for this log device
2689530301cSSimon Glass  */
2699530301cSSimon Glass struct log_filter {
2709530301cSSimon Glass 	int filter_num;
2719530301cSSimon Glass 	int flags;
2729530301cSSimon Glass 	enum log_category_t cat_list[LOGF_MAX_CATEGORIES];
2739530301cSSimon Glass 	enum log_level_t max_level;
2749530301cSSimon Glass 	const char *file_list;
2759530301cSSimon Glass 	struct list_head sibling_node;
2769530301cSSimon Glass };
2779530301cSSimon Glass 
2789530301cSSimon Glass #define LOG_DRIVER(_name) \
2799530301cSSimon Glass 	ll_entry_declare(struct log_driver, _name, log_driver)
2809530301cSSimon Glass 
28173991b07SSimon Glass /* Handle the 'log test' command */
28273991b07SSimon Glass int do_log_test(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
28373991b07SSimon Glass 
2849530301cSSimon Glass /**
2859530301cSSimon Glass  * log_add_filter() - Add a new filter to a log device
2869530301cSSimon Glass  *
2879530301cSSimon Glass  * @drv_name: Driver name to add the filter to (since each driver only has a
2889530301cSSimon Glass  *	single device)
2899530301cSSimon Glass  * @cat_list: List of categories to allow (terminated by LOGC_none). If empty
2909530301cSSimon Glass  *	then all categories are permitted. Up to LOGF_MAX_CATEGORIES entries
2919530301cSSimon Glass  *	can be provided
2929530301cSSimon Glass  * @max_level: Maximum log level to allow
2939530301cSSimon Glass  * @file_list: List of files to allow, separated by comma. If NULL then all
2949530301cSSimon Glass  *	files are permitted
2959530301cSSimon Glass  * @return the sequence number of the new filter (>=0) if the filter was added,
2969530301cSSimon Glass  *	or a -ve value on error
2979530301cSSimon Glass  */
2989530301cSSimon Glass int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
2999530301cSSimon Glass 		   enum log_level_t max_level, const char *file_list);
3009530301cSSimon Glass 
3019530301cSSimon Glass /**
3029530301cSSimon Glass  * log_remove_filter() - Remove a filter from a log device
3039530301cSSimon Glass  *
3049530301cSSimon Glass  * @drv_name: Driver name to remove the filter from (since each driver only has
3059530301cSSimon Glass  *	a single device)
3069530301cSSimon Glass  * @filter_num: Filter number to remove (as returned by log_add_filter())
3079530301cSSimon Glass  * @return 0 if the filter was removed, -ENOENT if either the driver or the
3089530301cSSimon Glass  *	filter number was not found
3099530301cSSimon Glass  */
3109530301cSSimon Glass int log_remove_filter(const char *drv_name, int filter_num);
3119530301cSSimon Glass 
3129530301cSSimon Glass #if CONFIG_IS_ENABLED(LOG)
3139530301cSSimon Glass /**
3149530301cSSimon Glass  * log_init() - Set up the log system ready for use
3159530301cSSimon Glass  *
3169530301cSSimon Glass  * @return 0 if OK, -ENOMEM if out of memory
3179530301cSSimon Glass  */
3189530301cSSimon Glass int log_init(void);
3199530301cSSimon Glass #else
log_init(void)3209530301cSSimon Glass static inline int log_init(void)
3219530301cSSimon Glass {
3229530301cSSimon Glass 	return 0;
3239530301cSSimon Glass }
3249530301cSSimon Glass #endif
3259530301cSSimon Glass 
32644aaaed1SSimon Glass #endif
327