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