+/*
+ * Recursively print (a portion of) the working_fdt. The depth parameter
+ * determines how deeply nested the fdt is printed.
+ */
+static int fdt_print(const char *pathp, char *prop, int depth)
+{
+ 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; /* node offset from libfdt */
+ int nextoffset; /* next node offset from libfdt */
+ uint32_t tag; /* tag */
+ int len; /* length of the property */
+ int level = 0; /* keep track of nesting level */
+ const struct fdt_property *fdt_prop;
+
+ nodeoffset = fdt_path_offset (working_fdt, pathp);
+ if (nodeoffset < 0) {
+ /*
+ * Not found or something else bad happened.
+ */
+ printf ("libfdt fdt_path_offset() returned %s\n",
+ fdt_strerror(nodeoffset));
+ return 1;
+ }
+ /*
+ * The user passed in a property as well as node path.
+ * Print only the given property and then return.
+ */
+ if (prop) {
+ nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
+ if (len == 0) {
+ /* no property value */
+ printf("%s %s\n", pathp, prop);
+ return 0;
+ } else if (len > 0) {
+ printf("%s = ", prop);
+ print_data (nodep, len);
+ printf("\n");
+ return 0;
+ } else {
+ printf ("libfdt fdt_getprop(): %s\n",
+ fdt_strerror(len));
+ return 1;
+ }
+ }
+
+ /*
+ * The user passed in a node path and no property,
+ * 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 (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ printf("%s%s {\n",
+ &tabs[MAX_LEVEL - level], pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level <= depth)
+ 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 */
+ if (level <= depth)
+ printf("%s%s;\n",
+ &tabs[MAX_LEVEL - level],
+ pathp);
+ } else {
+ if (level <= depth) {
+ 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:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ nodeoffset = nextoffset;
+ }
+ return 0;
+}
+
+/********************************************************************/
+#ifdef CONFIG_SYS_LONGHELP
+static char fdt_help_text[] =
+ "addr [-c] <addr> [<length>] - Set the [control] fdt location to <addr>\n"
+#ifdef CONFIG_OF_BOARD_SETUP
+ "fdt boardsetup - Do board-specific set up\n"
+#endif
+ "fdt move <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
+ "fdt resize - Resize fdt to size + padding to 4k addr\n"