source: SVN/rincon/u-boot/common/cmd_fdt.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 22.0 KB
Line 
1/*
2 * (C) Copyright 2007
3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
4 * Based on code written by:
5 *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
6 *   Matthew McClintock <msm@freescale.com>
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
24 * MA 02111-1307 USA
25 */
26
27#include <common.h>
28#include <command.h>
29#include <linux/ctype.h>
30#include <linux/types.h>
31#include <asm/global_data.h>
32#include <fdt.h>
33#include <libfdt.h>
34#include <fdt_support.h>
35
36#define MAX_LEVEL       32              /* how deeply nested we will go */
37#define SCRATCHPAD      1024            /* bytes of scratchpad memory */
38
39/*
40 * Global data (for the gd->bd)
41 */
42DECLARE_GLOBAL_DATA_PTR;
43
44static int fdt_valid(void);
45static int fdt_parse_prop(char **newval, int count, char *data, int *len);
46static int fdt_print(const char *pathp, char *prop, int depth);
47
48/*
49 * The working_fdt points to our working flattened device tree.
50 */
51struct fdt_header *working_fdt;
52
53void set_working_fdt_addr(void *addr)
54{
55        char buf[17];
56
57        working_fdt = addr;
58
59        sprintf(buf, "%lx", (unsigned long)addr);
60        setenv("fdtaddr", buf);
61}
62
63/*
64 * Flattened Device Tree command, see the help for parameter definitions.
65 */
66int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
67{
68        if (argc < 2) {
69                printf ("Usage:\n%s\n", cmdtp->usage);
70                return 1;
71        }
72
73        /********************************************************************
74         * Set the address of the fdt
75         ********************************************************************/
76        if (argv[1][0] == 'a') {
77                unsigned long addr;
78                /*
79                 * Set the address [and length] of the fdt.
80                 */
81                if (argc == 2) {
82                        if (!fdt_valid()) {
83                                return 1;
84                        }
85                        printf("The address of the fdt is %p\n", working_fdt);
86                        return 0;
87                }
88
89                addr = simple_strtoul(argv[2], NULL, 16);
90                set_working_fdt_addr((void *)addr);
91
92                if (!fdt_valid()) {
93                        return 1;
94                }
95
96                if (argc >= 4) {
97                        int  len;
98                        int  err;
99                        /*
100                         * Optional new length
101                         */
102                        len = simple_strtoul(argv[3], NULL, 16);
103                        if (len < fdt_totalsize(working_fdt)) {
104                                printf ("New length %d < existing length %d, "
105                                        "ignoring.\n",
106                                        len, fdt_totalsize(working_fdt));
107                        } else {
108                                /*
109                                 * Open in place with a new length.
110                                 */
111                                err = fdt_open_into(working_fdt, working_fdt, len);
112                                if (err != 0) {
113                                        printf ("libfdt fdt_open_into(): %s\n",
114                                                fdt_strerror(err));
115                                }
116                        }
117                }
118
119        /********************************************************************
120         * Move the working_fdt
121         ********************************************************************/
122        } else if (strncmp(argv[1], "mo", 2) == 0) {
123                struct fdt_header *newaddr;
124                int  len;
125                int  err;
126
127                if (argc < 4) {
128                        printf ("Usage:\n%s\n", cmdtp->usage);
129                        return 1;
130                }
131
132                /*
133                 * Set the address and length of the fdt.
134                 */
135                working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
136                if (!fdt_valid()) {
137                        return 1;
138                }
139
140                newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
141
142                /*
143                 * If the user specifies a length, use that.  Otherwise use the
144                 * current length.
145                 */
146                if (argc <= 4) {
147                        len = fdt_totalsize(working_fdt);
148                } else {
149                        len = simple_strtoul(argv[4], NULL, 16);
150                        if (len < fdt_totalsize(working_fdt)) {
151                                printf ("New length 0x%X < existing length "
152                                        "0x%X, aborting.\n",
153                                        len, fdt_totalsize(working_fdt));
154                                return 1;
155                        }
156                }
157
158                /*
159                 * Copy to the new location.
160                 */
161                err = fdt_open_into(working_fdt, newaddr, len);
162                if (err != 0) {
163                        printf ("libfdt fdt_open_into(): %s\n",
164                                fdt_strerror(err));
165                        return 1;
166                }
167                working_fdt = newaddr;
168
169        /********************************************************************
170         * Make a new node
171         ********************************************************************/
172        } else if (strncmp(argv[1], "mk", 2) == 0) {
173                char *pathp;            /* path */
174                char *nodep;            /* new node to add */
175                int  nodeoffset;        /* node offset from libfdt */
176                int  err;
177
178                /*
179                 * Parameters: Node path, new node to be appended to the path.
180                 */
181                if (argc < 4) {
182                        printf ("Usage:\n%s\n", cmdtp->usage);
183                        return 1;
184                }
185
186                pathp = argv[2];
187                nodep = argv[3];
188
189                nodeoffset = fdt_path_offset (working_fdt, pathp);
190                if (nodeoffset < 0) {
191                        /*
192                         * Not found or something else bad happened.
193                         */
194                        printf ("libfdt fdt_path_offset() returned %s\n",
195                                fdt_strerror(nodeoffset));
196                        return 1;
197                }
198                err = fdt_add_subnode(working_fdt, nodeoffset, nodep);
199                if (err < 0) {
200                        printf ("libfdt fdt_add_subnode(): %s\n",
201                                fdt_strerror(err));
202                        return 1;
203                }
204
205        /********************************************************************
206         * Set the value of a property in the working_fdt.
207         ********************************************************************/
208        } else if (argv[1][0] == 's') {
209                char *pathp;            /* path */
210                char *prop;             /* property */
211                int  nodeoffset;        /* node offset from libfdt */
212                static char data[SCRATCHPAD];   /* storage for the property */
213                int  len;               /* new length of the property */
214                int  ret;               /* return value */
215
216                /*
217                 * Parameters: Node path, property, optional value.
218                 */
219                if (argc < 4) {
220                        printf ("Usage:\n%s\n", cmdtp->usage);
221                        return 1;
222                }
223
224                pathp  = argv[2];
225                prop   = argv[3];
226                if (argc == 4) {
227                        len = 0;
228                } else {
229                        ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
230                        if (ret != 0)
231                                return ret;
232                }
233
234                nodeoffset = fdt_path_offset (working_fdt, pathp);
235                if (nodeoffset < 0) {
236                        /*
237                         * Not found or something else bad happened.
238                         */
239                        printf ("libfdt fdt_path_offset() returned %s\n",
240                                fdt_strerror(nodeoffset));
241                        return 1;
242                }
243
244                ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
245                if (ret < 0) {
246                        printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret));
247                        return 1;
248                }
249
250        /********************************************************************
251         * Print (recursive) / List (single level)
252         ********************************************************************/
253        } else if ((argv[1][0] == 'p') || (argv[1][0] == 'l')) {
254                int depth = MAX_LEVEL;  /* how deep to print */
255                char *pathp;            /* path */
256                char *prop;             /* property */
257                int  ret;               /* return value */
258                static char root[2] = "/";
259
260                /*
261                 * list is an alias for print, but limited to 1 level
262                 */
263                if (argv[1][0] == 'l') {
264                        depth = 1;
265                }
266
267                /*
268                 * Get the starting path.  The root node is an oddball,
269                 * the offset is zero and has no name.
270                 */
271                if (argc == 2)
272                        pathp = root;
273                else
274                        pathp = argv[2];
275                if (argc > 3)
276                        prop = argv[3];
277                else
278                        prop = NULL;
279
280                ret = fdt_print(pathp, prop, depth);
281                if (ret != 0)
282                        return ret;
283
284        /********************************************************************
285         * Remove a property/node
286         ********************************************************************/
287        } else if (strncmp(argv[1], "rm", 2) == 0) {
288                int  nodeoffset;        /* node offset from libfdt */
289                int  err;
290
291                /*
292                 * Get the path.  The root node is an oddball, the offset
293                 * is zero and has no name.
294                 */
295                nodeoffset = fdt_path_offset (working_fdt, argv[2]);
296                if (nodeoffset < 0) {
297                        /*
298                         * Not found or something else bad happened.
299                         */
300                        printf ("libfdt fdt_path_offset() returned %s\n",
301                                fdt_strerror(nodeoffset));
302                        return 1;
303                }
304                /*
305                 * Do the delete.  A fourth parameter means delete a property,
306                 * otherwise delete the node.
307                 */
308                if (argc > 3) {
309                        err = fdt_delprop(working_fdt, nodeoffset, argv[3]);
310                        if (err < 0) {
311                                printf("libfdt fdt_delprop():  %s\n",
312                                        fdt_strerror(err));
313                                return err;
314                        }
315                } else {
316                        err = fdt_del_node(working_fdt, nodeoffset);
317                        if (err < 0) {
318                                printf("libfdt fdt_del_node():  %s\n",
319                                        fdt_strerror(err));
320                                return err;
321                        }
322                }
323
324        /********************************************************************
325         * Display header info
326         ********************************************************************/
327        } else if (argv[1][0] == 'h') {
328                u32 version = fdt_version(working_fdt);
329                printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt));
330                printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt),
331                       fdt_totalsize(working_fdt));
332                printf("off_dt_struct:\t\t0x%x\n",
333                       fdt_off_dt_struct(working_fdt));
334                printf("off_dt_strings:\t\t0x%x\n",
335                       fdt_off_dt_strings(working_fdt));
336                printf("off_mem_rsvmap:\t\t0x%x\n",
337                       fdt_off_mem_rsvmap(working_fdt));
338                printf("version:\t\t%d\n", version);
339                printf("last_comp_version:\t%d\n",
340                       fdt_last_comp_version(working_fdt));
341                if (version >= 2)
342                        printf("boot_cpuid_phys:\t0x%x\n",
343                                fdt_boot_cpuid_phys(working_fdt));
344                if (version >= 3)
345                        printf("size_dt_strings:\t0x%x\n",
346                                fdt_size_dt_strings(working_fdt));
347                if (version >= 17)
348                        printf("size_dt_struct:\t\t0x%x\n",
349                                fdt_size_dt_struct(working_fdt));
350                printf("number mem_rsv:\t\t0x%x\n",
351                       fdt_num_mem_rsv(working_fdt));
352                printf("\n");
353
354        /********************************************************************
355         * Set boot cpu id
356         ********************************************************************/
357        } else if (strncmp(argv[1], "boo", 3) == 0) {
358                unsigned long tmp = simple_strtoul(argv[2], NULL, 16);
359                fdt_set_boot_cpuid_phys(working_fdt, tmp);
360
361        /********************************************************************
362         * memory command
363         ********************************************************************/
364        } else if (strncmp(argv[1], "me", 2) == 0) {
365                uint64_t addr, size;
366                int err;
367#ifdef CFG_64BIT_STRTOUL
368                        addr = simple_strtoull(argv[2], NULL, 16);
369                        size = simple_strtoull(argv[3], NULL, 16);
370#else
371                        addr = simple_strtoul(argv[2], NULL, 16);
372                        size = simple_strtoul(argv[3], NULL, 16);
373#endif
374                err = fdt_fixup_memory(working_fdt, addr, size);
375                if (err < 0)
376                        return err;
377
378        /********************************************************************
379         * mem reserve commands
380         ********************************************************************/
381        } else if (strncmp(argv[1], "rs", 2) == 0) {
382                if (argv[2][0] == 'p') {
383                        uint64_t addr, size;
384                        int total = fdt_num_mem_rsv(working_fdt);
385                        int j, err;
386                        printf("index\t\t   start\t\t    size\n");
387                        printf("-------------------------------"
388                                "-----------------\n");
389                        for (j = 0; j < total; j++) {
390                                err = fdt_get_mem_rsv(working_fdt, j, &addr, &size);
391                                if (err < 0) {
392                                        printf("libfdt fdt_get_mem_rsv():  %s\n",
393                                                        fdt_strerror(err));
394                                        return err;
395                                }
396                                printf("    %x\t%08x%08x\t%08x%08x\n", j,
397                                        (u32)(addr >> 32),
398                                        (u32)(addr & 0xffffffff),
399                                        (u32)(size >> 32),
400                                        (u32)(size & 0xffffffff));
401                        }
402                } else if (argv[2][0] == 'a') {
403                        uint64_t addr, size;
404                        int err;
405#ifdef CFG_64BIT_STRTOUL
406                        addr = simple_strtoull(argv[3], NULL, 16);
407                        size = simple_strtoull(argv[4], NULL, 16);
408#else
409                        addr = simple_strtoul(argv[3], NULL, 16);
410                        size = simple_strtoul(argv[4], NULL, 16);
411#endif
412                        err = fdt_add_mem_rsv(working_fdt, addr, size);
413
414                        if (err < 0) {
415                                printf("libfdt fdt_add_mem_rsv():  %s\n",
416                                        fdt_strerror(err));
417                                return err;
418                        }
419                } else if (argv[2][0] == 'd') {
420                        unsigned long idx = simple_strtoul(argv[3], NULL, 16);
421                        int err = fdt_del_mem_rsv(working_fdt, idx);
422
423                        if (err < 0) {
424                                printf("libfdt fdt_del_mem_rsv():  %s\n",
425                                        fdt_strerror(err));
426                                return err;
427                        }
428                } else {
429                        /* Unrecognized command */
430                        printf ("Usage:\n%s\n", cmdtp->usage);
431                        return 1;
432                }
433        }
434#ifdef CONFIG_OF_BOARD_SETUP
435        /* Call the board-specific fixup routine */
436        else if (strncmp(argv[1], "boa", 3) == 0)
437                ft_board_setup(working_fdt, gd->bd);
438#endif
439        /* Create a chosen node */
440        else if (argv[1][0] == 'c') {
441                unsigned long initrd_start = 0, initrd_end = 0;
442
443                if ((argc != 2) && (argc != 4)) {
444                        printf ("Usage:\n%s\n", cmdtp->usage);
445                        return 1;
446                }
447
448                if (argc == 4) {
449                        initrd_start = simple_strtoul(argv[2], NULL, 16);
450                        initrd_end = simple_strtoul(argv[3], NULL, 16);
451                }
452
453                fdt_chosen(working_fdt, 1);
454                fdt_initrd(working_fdt, initrd_start, initrd_end, 1);
455        }
456        /* resize the fdt */
457        else if (strncmp(argv[1], "re", 2) == 0) {
458                fdt_resize(working_fdt);
459        }
460        else {
461                /* Unrecognized command */
462                printf ("Usage:\n%s\n", cmdtp->usage);
463                return 1;
464        }
465
466        return 0;
467}
468
469/****************************************************************************/
470
471static int fdt_valid(void)
472{
473        int  err;
474
475        if (working_fdt == NULL) {
476                printf ("The address of the fdt is invalid (NULL).\n");
477                return 0;
478        }
479
480        err = fdt_check_header(working_fdt);
481        if (err == 0)
482                return 1;       /* valid */
483
484        if (err < 0) {
485                printf("libfdt fdt_check_header(): %s", fdt_strerror(err));
486                /*
487                 * Be more informative on bad version.
488                 */
489                if (err == -FDT_ERR_BADVERSION) {
490                        if (fdt_version(working_fdt) <
491                            FDT_FIRST_SUPPORTED_VERSION) {
492                                printf (" - too old, fdt %d < %d",
493                                        fdt_version(working_fdt),
494                                        FDT_FIRST_SUPPORTED_VERSION);
495                                working_fdt = NULL;
496                        }
497                        if (fdt_last_comp_version(working_fdt) >
498                            FDT_LAST_SUPPORTED_VERSION) {
499                                printf (" - too new, fdt %d > %d",
500                                        fdt_version(working_fdt),
501                                        FDT_LAST_SUPPORTED_VERSION);
502                                working_fdt = NULL;
503                        }
504                        return 0;
505                }
506                printf("\n");
507                return 0;
508        }
509        return 1;
510}
511
512/****************************************************************************/
513
514/*
515 * Parse the user's input, partially heuristic.  Valid formats:
516 * <0x00112233 4 05>    - an array of cells.  Numbers follow standard
517 *                      C conventions.
518 * [00 11 22 .. nn] - byte stream
519 * "string"     - If the the value doesn't start with "<" or "[", it is
520 *                      treated as a string.  Note that the quotes are
521 *                      stripped by the parser before we get the string.
522 * newval: An array of strings containing the new property as specified
523 *      on the command line
524 * count: The number of strings in the array
525 * data: A bytestream to be placed in the property
526 * len: The length of the resulting bytestream
527 */
528static int fdt_parse_prop(char **newval, int count, char *data, int *len)
529{
530        char *cp;               /* temporary char pointer */
531        char *newp;             /* temporary newval char pointer */
532        unsigned long tmp;      /* holds converted values */
533        int stridx = 0;
534
535        *len = 0;
536        newp = newval[0];
537
538        /* An array of cells */
539        if (*newp == '<') {
540                newp++;
541                while ((*newp != '>') && (stridx < count)) {
542                        /*
543                         * Keep searching until we find that last ">"
544                         * That way users don't have to escape the spaces
545                         */
546                        if (*newp == '\0') {
547                                newp = newval[++stridx];
548                                continue;
549                        }
550
551                        cp = newp;
552                        tmp = simple_strtoul(cp, &newp, 0);
553                        *(uint32_t *)data = __cpu_to_be32(tmp);
554                        data  += 4;
555                        *len += 4;
556
557                        /* If the ptr didn't advance, something went wrong */
558                        if ((newp - cp) <= 0) {
559                                printf("Sorry, I could not convert \"%s\"\n",
560                                        cp);
561                                return 1;
562                        }
563
564                        while (*newp == ' ')
565                                newp++;
566                }
567
568                if (*newp != '>') {
569                        printf("Unexpected character '%c'\n", *newp);
570                        return 1;
571                }
572        } else if (*newp == '[') {
573                /*
574                 * Byte stream.  Convert the values.
575                 */
576                newp++;
577                while ((*newp != ']') && (stridx < count)) {
578                        tmp = simple_strtoul(newp, &newp, 16);
579                        *data++ = tmp & 0xFF;
580                        *len    = *len + 1;
581                        while (*newp == ' ')
582                                newp++;
583                        if (*newp != '\0')
584                                newp = newval[++stridx];
585                }
586                if (*newp != ']') {
587                        printf("Unexpected character '%c'\n", *newp);
588                        return 1;
589                }
590        } else {
591                /*
592                 * Assume it is a string.  Copy it into our data area for
593                 * convenience (including the terminating '\0').
594                 */
595                while (stridx < count) {
596                        *len = strlen(newp) + 1;
597                        strcpy(data, newp);
598                        newp = newval[++stridx];
599                }
600        }
601        return 0;
602}
603
604/****************************************************************************/
605
606/*
607 * Heuristic to guess if this is a string or concatenated strings.
608 */
609
610static int is_printable_string(const void *data, int len)
611{
612        const char *s = data;
613
614        /* zero length is not */
615        if (len == 0)
616                return 0;
617
618        /* must terminate with zero */
619        if (s[len - 1] != '\0')
620                return 0;
621
622        /* printable or a null byte (concatenated strings) */
623        while (((*s == '\0') || isprint(*s)) && (len > 0)) {
624                /*
625                 * If we see a null, there are three possibilities:
626                 * 1) If len == 1, it is the end of the string, printable
627                 * 2) Next character also a null, not printable.
628                 * 3) Next character not a null, continue to check.
629                 */
630                if (s[0] == '\0') {
631                        if (len == 1)
632                                return 1;
633                        if (s[1] == '\0')
634                                return 0;
635                }
636                s++;
637                len--;
638        }
639
640        /* Not the null termination, or not done yet: not printable */
641        if (*s != '\0' || (len != 0))
642                return 0;
643
644        return 1;
645}
646
647
648/*
649 * Print the property in the best format, a heuristic guess.  Print as
650 * a string, concatenated strings, a byte, word, double word, or (if all
651 * else fails) it is printed as a stream of bytes.
652 */
653static void print_data(const void *data, int len)
654{
655        int j;
656
657        /* no data, don't print */
658        if (len == 0)
659                return;
660
661        /*
662         * It is a string, but it may have multiple strings (embedded '\0's).
663         */
664        if (is_printable_string(data, len)) {
665                puts("\"");
666                j = 0;
667                while (j < len) {
668                        if (j > 0)
669                                puts("\", \"");
670                        puts(data);
671                        j    += strlen(data) + 1;
672                        data += strlen(data) + 1;
673                }
674                puts("\"");
675                return;
676        }
677
678        if ((len %4) == 0) {
679                const u32 *p;
680
681                printf("<");
682                for (j = 0, p = data; j < len/4; j ++)
683                        printf("0x%x%s", p[j], j < (len/4 - 1) ? " " : "");
684                printf(">");
685        } else { /* anything else... hexdump */
686                const u8 *s;
687
688                printf("[");
689                for (j = 0, s = data; j < len; j++)
690                        printf("%02x%s", s[j], j < len - 1 ? " " : "");
691                printf("]");
692        }
693}
694
695/****************************************************************************/
696
697/*
698 * Recursively print (a portion of) the working_fdt.  The depth parameter
699 * determines how deeply nested the fdt is printed.
700 */
701static int fdt_print(const char *pathp, char *prop, int depth)
702{
703        static char tabs[MAX_LEVEL+1] =
704                "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
705                "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
706        const void *nodep;      /* property node pointer */
707        int  nodeoffset;        /* node offset from libfdt */
708        int  nextoffset;        /* next node offset from libfdt */
709        uint32_t tag;           /* tag */
710        int  len;               /* length of the property */
711        int  level = 0;         /* keep track of nesting level */
712        const struct fdt_property *fdt_prop;
713
714        nodeoffset = fdt_path_offset (working_fdt, pathp);
715        if (nodeoffset < 0) {
716                /*
717                 * Not found or something else bad happened.
718                 */
719                printf ("libfdt fdt_path_offset() returned %s\n",
720                        fdt_strerror(nodeoffset));
721                return 1;
722        }
723        /*
724         * The user passed in a property as well as node path.
725         * Print only the given property and then return.
726         */
727        if (prop) {
728                nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len);
729                if (len == 0) {
730                        /* no property value */
731                        printf("%s %s\n", pathp, prop);
732                        return 0;
733                } else if (len > 0) {
734                        printf("%s = ", prop);
735                        print_data (nodep, len);
736                        printf("\n");
737                        return 0;
738                } else {
739                        printf ("libfdt fdt_getprop(): %s\n",
740                                fdt_strerror(len));
741                        return 1;
742                }
743        }
744
745        /*
746         * The user passed in a node path and no property,
747         * print the node and all subnodes.
748         */
749        while(level >= 0) {
750                tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
751                switch(tag) {
752                case FDT_BEGIN_NODE:
753                        pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
754                        if (level <= depth) {
755                                if (pathp == NULL)
756                                        pathp = "/* NULL pointer error */";
757                                if (*pathp == '\0')
758                                        pathp = "/";    /* root is nameless */
759                                printf("%s%s {\n",
760                                        &tabs[MAX_LEVEL - level], pathp);
761                        }
762                        level++;
763                        if (level >= MAX_LEVEL) {
764                                printf("Nested too deep, aborting.\n");
765                                return 1;
766                        }
767                        break;
768                case FDT_END_NODE:
769                        level--;
770                        if (level <= depth)
771                                printf("%s};\n", &tabs[MAX_LEVEL - level]);
772                        if (level == 0) {
773                                level = -1;             /* exit the loop */
774                        }
775                        break;
776                case FDT_PROP:
777                        fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
778                                        sizeof(*fdt_prop));
779                        pathp    = fdt_string(working_fdt,
780                                        fdt32_to_cpu(fdt_prop->nameoff));
781                        len      = fdt32_to_cpu(fdt_prop->len);
782                        nodep    = fdt_prop->data;
783                        if (len < 0) {
784                                printf ("libfdt fdt_getprop(): %s\n",
785                                        fdt_strerror(len));
786                                return 1;
787                        } else if (len == 0) {
788                                /* the property has no value */
789                                if (level <= depth)
790                                        printf("%s%s;\n",
791                                                &tabs[MAX_LEVEL - level],
792                                                pathp);
793                        } else {
794                                if (level <= depth) {
795                                        printf("%s%s = ",
796                                                &tabs[MAX_LEVEL - level],
797                                                pathp);
798                                        print_data (nodep, len);
799                                        printf(";\n");
800                                }
801                        }
802                        break;
803                case FDT_NOP:
804                        printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]);
805                        break;
806                case FDT_END:
807                        return 1;
808                default:
809                        if (level <= depth)
810                                printf("Unknown tag 0x%08X\n", tag);
811                        return 1;
812                }
813                nodeoffset = nextoffset;
814        }
815        return 0;
816}
817
818/********************************************************************/
819
820U_BOOT_CMD(
821        fdt,    255,    0,      do_fdt,
822        "fdt     - flattened device tree utility commands\n",
823            "addr   <addr> [<length>]        - Set the fdt location to <addr>\n"
824#ifdef CONFIG_OF_BOARD_SETUP
825        "fdt boardsetup                      - Do board-specific set up\n"
826#endif
827        "fdt move   <fdt> <newaddr> <length> - Copy the fdt to <addr> and make it active\n"
828        "fdt resize                          - Resize fdt to size + padding to 4k addr\n"
829        "fdt print  <path> [<prop>]          - Recursive print starting at <path>\n"
830        "fdt list   <path> [<prop>]          - Print one level starting at <path>\n"
831        "fdt set    <path> <prop> [<val>]    - Set <property> [to <val>]\n"
832        "fdt mknode <path> <node>            - Create a new node after <path>\n"
833        "fdt rm     <path> [<prop>]          - Delete the node or <property>\n"
834        "fdt header                          - Display header info\n"
835        "fdt bootcpu <id>                    - Set boot cpuid\n"
836        "fdt memory <addr> <size>            - Add/Update memory node\n"
837        "fdt rsvmem print                    - Show current mem reserves\n"
838        "fdt rsvmem add <addr> <size>        - Add a mem reserve\n"
839        "fdt rsvmem delete <index>           - Delete a mem reserves\n"
840        "fdt chosen [<start> <end>]          - Add/update the /chosen branch in the tree\n"
841        "                                        <start>/<end> - initrd start/end addr\n"
842        "NOTE: Dereference aliases by omiting the leading '/', "
843                "e.g. fdt print ethernet0.\n"
844);
Note: See TracBrowser for help on using the repository browser.