]> Git Repo - u-boot.git/blobdiff - common/log.c
Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
[u-boot.git] / common / log.c
index c5de99a8d16f27a3f8dfde40f2f9ca91e4d1e322..dfee250b158a77f6284de849953702ba8b5cf537 100644 (file)
@@ -6,9 +6,10 @@
  * Written by Simon Glass <[email protected]>
  */
 
-#include <common.h>
+#include <display_options.h>
 #include <log.h>
 #include <malloc.h>
+#include <asm/global_data.h>
 #include <dm/uclass.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -26,6 +27,10 @@ static const char *const log_cat_name[] = {
        "bloblist",
        "devres",
        "acpi",
+       "boot",
+       "event",
+       "fs",
+       "expo",
 };
 
 _Static_assert(ARRAY_SIZE(log_cat_name) == LOGC_COUNT - LOGC_NONE,
@@ -145,13 +150,13 @@ bool log_has_file(const char *file_list, const char *file)
  *
  * @ldev: Log device to check
  * @rec: Log record to check
- * @return true if @rec is not blocked by the filters in @ldev, false if it is
+ * Return: true if @rec is not blocked by the filters in @ldev, false if it is
  */
 static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
 {
        struct log_filter *filt;
 
-       if (rec->force_debug)
+       if (rec->flags & LOGRECF_FORCE_DEBUG)
                return true;
 
        /* If there are no filters, filter on the default log level */
@@ -162,15 +167,25 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
        }
 
        list_for_each_entry(filt, &ldev->filter_head, sibling_node) {
-               if (rec->level > filt->max_level)
+               if (filt->flags & LOGFF_LEVEL_MIN) {
+                       if (rec->level < filt->level)
+                               continue;
+               } else if (rec->level > filt->level) {
                        continue;
+               }
+
                if ((filt->flags & LOGFF_HAS_CAT) &&
                    !log_has_cat(filt->cat_list, rec->cat))
                        continue;
+
                if (filt->file_list &&
                    !log_has_file(filt->file_list, rec->file))
                        continue;
-               return true;
+
+               if (filt->flags & LOGFF_DENY)
+                       return false;
+               else
+                       return true;
        }
 
        return false;
@@ -187,9 +202,10 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
  * @rec:       log record to dispatch
  * Return:     0 msg sent, 1 msg not sent while already dispatching another msg
  */
-static int log_dispatch(struct log_rec *rec)
+static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args)
 {
        struct log_device *ldev;
+       char buf[CONFIG_SYS_CBSIZE];
 
        /*
         * When a log driver writes messages (e.g. via the network stack) this
@@ -203,8 +219,16 @@ static int log_dispatch(struct log_rec *rec)
        gd->processing_msg = true;
        list_for_each_entry(ldev, &gd->log_head, sibling_node) {
                if ((ldev->flags & LOGDF_ENABLE) &&
-                   log_passes_filters(ldev, rec))
+                   log_passes_filters(ldev, rec)) {
+                       if (!rec->msg) {
+                               int len;
+
+                               len = vsnprintf(buf, sizeof(buf), fmt, args);
+                               rec->msg = buf;
+                               gd->log_cont = len && buf[len - 1] != '\n';
+                       }
                        ldev->drv->emit(ldev, rec);
+               }
        }
        gd->processing_msg = false;
        return 0;
@@ -213,10 +237,12 @@ static int log_dispatch(struct log_rec *rec)
 int _log(enum log_category_t cat, enum log_level_t level, const char *file,
         int line, const char *func, const char *fmt, ...)
 {
-       char buf[CONFIG_SYS_CBSIZE];
        struct log_rec rec;
        va_list args;
 
+       if (!gd)
+               return -ENOSYS;
+
        /* Check for message continuation */
        if (cat == LOGC_CONT)
                cat = gd->logc_prev;
@@ -225,29 +251,75 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
 
        rec.cat = cat;
        rec.level = level & LOGL_LEVEL_MASK;
-       rec.force_debug = level & LOGL_FORCE_DEBUG;
+       rec.flags = 0;
+       if (level & LOGL_FORCE_DEBUG)
+               rec.flags |= LOGRECF_FORCE_DEBUG;
+       if (gd->log_cont)
+               rec.flags |= LOGRECF_CONT;
        rec.file = file;
        rec.line = line;
        rec.func = func;
-       va_start(args, fmt);
-       vsnprintf(buf, sizeof(buf), fmt, args);
-       va_end(args);
-       rec.msg = buf;
-       if (!gd || !(gd->flags & GD_FLG_LOG_READY)) {
-               if (gd)
-                       gd->log_drop_count++;
+       rec.msg = NULL;
+
+       if (!(gd->flags & GD_FLG_LOG_READY)) {
+               gd->log_drop_count++;
+
+               /* display dropped traces with console puts and DEBUG_UART */
+               if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL ||
+                   rec.flags & LOGRECF_FORCE_DEBUG) {
+                       char buf[CONFIG_SYS_CBSIZE];
+
+                       va_start(args, fmt);
+                       vsnprintf(buf, sizeof(buf), fmt, args);
+                       puts(buf);
+                       va_end(args);
+               }
+
                return -ENOSYS;
        }
-       if (!log_dispatch(&rec)) {
+       va_start(args, fmt);
+       if (!log_dispatch(&rec, fmt, args)) {
                gd->logc_prev = cat;
                gd->logl_prev = level;
        }
+       va_end(args);
 
        return 0;
 }
 
-int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
-                  enum log_level_t max_level, const char *file_list)
+#define MAX_LINE_LENGTH_BYTES          64
+#define DEFAULT_LINE_LENGTH_BYTES      16
+
+int _log_buffer(enum log_category_t cat, enum log_level_t level,
+               const char *file, int line, const char *func, ulong addr,
+               const void *data, uint width, uint count, uint linelen)
+{
+       if (linelen * width > MAX_LINE_LENGTH_BYTES)
+               linelen = MAX_LINE_LENGTH_BYTES / width;
+       if (linelen < 1)
+               linelen = DEFAULT_LINE_LENGTH_BYTES / width;
+
+       while (count) {
+               uint thislinelen;
+               char buf[HEXDUMP_MAX_BUF_LENGTH(width * linelen)];
+
+               thislinelen = hexdump_line(addr, data, width, count, linelen,
+                                          buf, sizeof(buf));
+               assert(thislinelen >= 0);
+               _log(cat, level, file, line, func, "%s\n", buf);
+
+               /* update references */
+               data += thislinelen * width;
+               addr += thislinelen * width;
+               count -= thislinelen;
+       }
+
+       return 0;
+}
+
+int log_add_filter_flags(const char *drv_name, enum log_category_t cat_list[],
+                        enum log_level_t level, const char *file_list,
+                        int flags)
 {
        struct log_filter *filt;
        struct log_device *ldev;
@@ -261,6 +333,7 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
        if (!filt)
                return -ENOMEM;
 
+       filt->flags = flags;
        if (cat_list) {
                filt->flags |= LOGFF_HAS_CAT;
                for (i = 0; ; i++) {
@@ -273,7 +346,7 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
                                break;
                }
        }
-       filt->max_level = max_level;
+       filt->level = level;
        if (file_list) {
                filt->file_list = strdup(file_list);
                if (!filt->file_list) {
@@ -282,7 +355,11 @@ int log_add_filter(const char *drv_name, enum log_category_t cat_list[],
                }
        }
        filt->filter_num = ldev->next_filter_num++;
-       list_add_tail(&filt->sibling_node, &ldev->filter_head);
+       /* Add deny filters to the beginning of the list */
+       if (flags & LOGFF_DENY)
+               list_add(&filt->sibling_node, &ldev->filter_head);
+       else
+               list_add_tail(&filt->sibling_node, &ldev->filter_head);
 
        return filt->filter_num;
 
@@ -316,7 +393,7 @@ int log_remove_filter(const char *drv_name, int filter_num)
  * log_find_device_by_drv() - Find a device by its driver
  *
  * @drv: Log driver
- * @return Device associated with that driver, or NULL if not found
+ * Return: Device associated with that driver, or NULL if not found
  */
 static struct log_device *log_find_device_by_drv(struct log_driver *drv)
 {
@@ -350,6 +427,11 @@ int log_device_set_enable(struct log_driver *drv, bool enable)
        return 0;
 }
 
+void log_fixup_for_gd_move(struct global_data *new_gd)
+{
+       new_gd->log_head.prev->next = &new_gd->log_head;
+}
+
 int log_init(void)
 {
        struct log_driver *drv = ll_entry_start(struct log_driver, log_driver);
@@ -359,7 +441,7 @@ int log_init(void)
        /*
         * We cannot add runtime data to the driver since it is likely stored
         * in rodata. Instead, set up a 'device' corresponding to each driver.
-        * We only support having a single device.
+        * We only support having a single device for each driver.
         */
        INIT_LIST_HEAD((struct list_head *)&gd->log_head);
        while (drv < end) {
This page took 0.033371 seconds and 4 git commands to generate.