Add an option show_of_embedded used in SPL to dump the used device tree.

Signed-off-by: Patrick Delaunay <patrick.delau...@st.com>
---

Changes in v2:
- add new option for spl test: show embedded dtb

 arch/sandbox/cpu/spl.c           | 188 +++++++++++++++++++++++++++++++++++++++
 arch/sandbox/cpu/start.c         |   9 ++
 arch/sandbox/include/asm/state.h |   1 +
 3 files changed, 198 insertions(+)

diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c
index 2ca4cd6..d3d9b08 100644
--- a/arch/sandbox/cpu/spl.c
+++ b/arch/sandbox/cpu/spl.c
@@ -46,6 +46,190 @@ static int spl_board_load_image(struct spl_image_info 
*spl_image,
 }
 SPL_LOAD_IMAGE_METHOD("sandbox", 0, BOOT_DEVICE_BOARD, spl_board_load_image);
 
+#ifdef CONFIG_OF_EMBED
+/****************************************************************************/
+/* the next functions mainly copyied from cmd fdt for SPL sandbox test */
+
+#include <linux/ctype.h>
+
+#define CMD_FDT_MAX_DUMP 64
+#define MAX_LEVEL      32              /* how deeply nested we will go */
+
+/*
+ * Heuristic to guess if this is a string or concatenated strings.
+ */
+
+static int is_printable_string(const void *data, int len)
+{
+       const char *s = data;
+
+       /* zero length is not */
+       if (len == 0)
+               return 0;
+
+       /* must terminate with zero or '\n' */
+       if (s[len - 1] != '\0' && s[len - 1] != '\n')
+               return 0;
+
+       /* printable or a null byte (concatenated strings) */
+       while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) {
+               /*
+                * If we see a null, there are three possibilities:
+                * 1) If len == 1, it is the end of the string, printable
+                * 2) Next character also a null, not printable.
+                * 3) Next character not a null, continue to check.
+                */
+               if (s[0] == '\0') {
+                       if (len == 1)
+                               return 1;
+                       if (s[1] == '\0')
+                               return 0;
+               }
+               s++;
+               len--;
+       }
+
+       /* Not the null termination, or not done yet: not printable */
+       if (*s != '\0' || len != 0)
+               return 0;
+
+       return 1;
+}
+
+/*
+ * Print the property in the best format, a heuristic guess.  Print as
+ * a string, concatenated strings, a byte, word, double word, or (if all
+ * else fails) it is printed as a stream of bytes.
+ */
+static void print_data(const void *data, int len)
+{
+       int j;
+
+       /* no data, don't print */
+       if (len == 0)
+               return;
+
+       /*
+        * It is a string, but it may have multiple strings (embedded '\0's).
+        */
+       if (is_printable_string(data, len)) {
+               puts("\"");
+               j = 0;
+               while (j < len) {
+                       if (j > 0)
+                               puts("\", \"");
+                       puts(data);
+                       j    += strlen(data) + 1;
+                       data += strlen(data) + 1;
+               }
+               puts("\"");
+               return;
+       }
+
+       if ((len % 4) == 0) {
+               if (len > CMD_FDT_MAX_DUMP) {
+                       printf("* 0x%p [0x%08x]", data, len);
+               } else {
+                       const __be32 *p;
+
+                       printf("<");
+                       for (j = 0, p = data; j < len / 4; j++)
+                               printf("0x%08x%s", fdt32_to_cpu(p[j]),
+                                      j < (len / 4 - 1) ? " " : "");
+                       printf(">");
+               }
+       } else { /* anything else... hexdump */
+               if (len > CMD_FDT_MAX_DUMP) {
+                       printf("* 0x%p [0x%08x]", data, len);
+               } else {
+                       const u8 *s;
+
+                       printf("[");
+                       for (j = 0, s = data; j < len; j++)
+                               printf("%02x%s", s[j], j < len - 1 ? " " : "");
+                       printf("]");
+               }
+       }
+}
+
+/*
+ * Recursively print the working_fdt.
+ */
+static int fdt_print(const struct fdt_header *working_fdt)
+{
+       static char tabs[MAX_LEVEL + 1] =
+               "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
+               "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
+       const void *nodep;      /* property node pointer */
+       int  nodeoffset = 0;    /* node offset from libfdt */
+       int  nextoffset;        /* next node offset from libfdt */
+       u32  tag;               /* tag */
+       int  len;               /* length of the property */
+       int  level = 0;         /* keep track of nesting level */
+       const struct fdt_property *fdt_prop;
+       const char *pathp;
+
+       /* print the node and all subnodes. */
+       while (level >= 0) {
+               tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
+               switch (tag) {
+               case FDT_BEGIN_NODE:
+                       pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
+                       if (!pathp)
+                               pathp = "/* NULL pointer error */";
+                       if (*pathp == '\0')
+                               pathp = "/";    /* root is nameless */
+                       printf("%s%s {\n",
+                              &tabs[MAX_LEVEL - level], pathp);
+                       level++;
+                       break;
+               case FDT_END_NODE:
+                       level--;
+                       printf("%s};\n", &tabs[MAX_LEVEL - level]);
+                       if (level == 0)
+                               level = -1;             /* exit the loop */
+                       break;
+               case FDT_PROP:
+                       fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
+                                                 sizeof(*fdt_prop));
+                       pathp    = fdt_string(working_fdt,
+                                             fdt32_to_cpu(fdt_prop->nameoff));
+                       len      = fdt32_to_cpu(fdt_prop->len);
+                       nodep    = fdt_prop->data;
+                       if (len < 0) {
+                               printf("libfdt fdt_getprop(): %s\n",
+                                      fdt_strerror(len));
+                               return 1;
+                       } else if (len == 0) {
+                               /* the property has no value */
+                               printf("%s%s;\n",
+                                      &tabs[MAX_LEVEL - level],
+                                      pathp);
+                       } else {
+                               printf("%s%s = ",
+                                      &tabs[MAX_LEVEL - level],
+                                      pathp);
+                               print_data(nodep, len);
+                               printf(";\n");
+                       }
+                       break;
+               case FDT_NOP:
+                       printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
+                       break;
+               case FDT_END:
+                       return 1;
+               default:
+                       return 1;
+               }
+               nodeoffset = nextoffset;
+       }
+
+       return 0;
+}
+
+/***************************************************************************/
+#endif
+
 void spl_board_init(void)
 {
        struct sandbox_state *state = state_get_current();
@@ -63,6 +247,10 @@ void spl_board_init(void)
                     uclass_next_device(&dev))
                        ;
        }
+#ifdef CONFIG_OF_EMBED
+       if (state->show_of_embedded)
+               fdt_print(gd->fdt_blob);
+#endif
 }
 
 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 82828f0..8116e3c 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -293,6 +293,15 @@ static int sandbox_cmdline_cb_show_of_platdata(struct 
sandbox_state *state,
 }
 SANDBOX_CMDLINE_OPT(show_of_platdata, 0, "Show of-platdata in SPL");
 
+static int sandbox_cmdline_cb_show_of_embedded(struct sandbox_state *state,
+                                              const char *arg)
+{
+       state->show_of_embedded = true;
+
+       return 0;
+}
+SANDBOX_CMDLINE_OPT(show_of_embedded, 0, "Show of-embedded in SPL");
+
 int board_run_command(const char *cmdline)
 {
        printf("## Commands are disabled. Please enable CONFIG_CMDLINE.\n");
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 2d773d3..c8142c8 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -90,6 +90,7 @@ struct sandbox_state {
        bool show_test_output;          /* Don't suppress stdout in tests */
        int default_log_level;          /* Default log level for sandbox */
        bool show_of_platdata;          /* Show of-platdata in SPL */
+       bool show_of_embedded;          /* Show of-embedded in SPL */
        bool ram_buf_read;              /* true if we read the RAM buffer */
 
        /* Pointer to information for each SPI bus/cs */
-- 
2.7.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to