Merge https://gitlab.denx.de/u-boot/custodians/u-boot-marvell
[oweals/u-boot.git] / tools / fdtgrep.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013, Google Inc.
4  * Written by Simon Glass <sjg@chromium.org>
5  *
6  * Perform a grep of an FDT either displaying the source subset or producing
7  * a new .dtb subset which can be used as required.
8  */
9
10 #include <assert.h>
11 #include <ctype.h>
12 #include <errno.h>
13 #include <getopt.h>
14 #include <fcntl.h>
15 #include <stdbool.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20
21 #include "fdt_host.h"
22 #include "libfdt_internal.h"
23
24 /* Define DEBUG to get some debugging output on stderr */
25 #ifdef DEBUG
26 #define debug(a, b...) fprintf(stderr, a, ## b)
27 #else
28 #define debug(a, b...)
29 #endif
30
31 /* A linked list of values we are grepping for */
32 struct value_node {
33         int type;               /* Types this value matches (FDT_IS... mask) */
34         int include;            /* 1 to include matches, 0 to exclude */
35         const char *string;     /* String to match */
36         struct value_node *next;        /* Pointer to next node, or NULL */
37 };
38
39 /* Output formats we support */
40 enum output_t {
41         OUT_DTS,                /* Device tree source */
42         OUT_DTB,                /* Valid device tree binary */
43         OUT_BIN,                /* Fragment of .dtb, for hashing */
44 };
45
46 /* Holds information which controls our output and options */
47 struct display_info {
48         enum output_t output;   /* Output format */
49         int add_aliases;        /* Add aliases node to output */
50         int all;                /* Display all properties/nodes */
51         int colour;             /* Display output in ANSI colour */
52         int region_list;        /* Output a region list */
53         int flags;              /* Flags (FDT_REG_...) */
54         int list_strings;       /* List strings in string table */
55         int show_offset;        /* Show offset */
56         int show_addr;          /* Show address */
57         int header;             /* Output an FDT header */
58         int diff;               /* Show +/- diff markers */
59         int include_root;       /* Include the root node and all properties */
60         int remove_strings;     /* Remove unused strings */
61         int show_dts_version;   /* Put '/dts-v1/;' on the first line */
62         int types_inc;          /* Mask of types that we include (FDT_IS...) */
63         int types_exc;          /* Mask of types that we exclude (FDT_IS...) */
64         int invert;             /* Invert polarity of match */
65         struct value_node *value_head;  /* List of values to match */
66         const char *output_fname;       /* Output filename */
67         FILE *fout;             /* File to write dts/dtb output */
68 };
69
70 static void report_error(const char *where, int err)
71 {
72         fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
73 }
74
75 /* Supported ANSI colours */
76 enum {
77         COL_BLACK,
78         COL_RED,
79         COL_GREEN,
80         COL_YELLOW,
81         COL_BLUE,
82         COL_MAGENTA,
83         COL_CYAN,
84         COL_WHITE,
85
86         COL_NONE = -1,
87 };
88
89 /**
90  * print_ansi_colour() - Print out the ANSI sequence for a colour
91  *
92  * @fout:       Output file
93  * @col:        Colour to output (COL_...), or COL_NONE to reset colour
94  */
95 static void print_ansi_colour(FILE *fout, int col)
96 {
97         if (col == COL_NONE)
98                 fprintf(fout, "\033[0m");
99         else
100                 fprintf(fout, "\033[1;%dm", col + 30);
101 }
102
103
104 /**
105  * value_add() - Add a new value to our list of things to grep for
106  *
107  * @disp:       Display structure, holding info about our options
108  * @headp:      Pointer to header pointer of list
109  * @type:       Type of this value (FDT_IS_...)
110  * @include:    1 if we want to include matches, 0 to exclude
111  * @str:        String value to match
112  */
113 static int value_add(struct display_info *disp, struct value_node **headp,
114                      int type, int include, const char *str)
115 {
116         struct value_node *node;
117
118         /*
119          * Keep track of which types we are excluding/including. We don't
120          * allow both including and excluding things, because it doesn't make
121          * sense. 'Including' means that everything not mentioned is
122          * excluded. 'Excluding' means that everything not mentioned is
123          * included. So using the two together would be meaningless.
124          */
125         if (include)
126                 disp->types_inc |= type;
127         else
128                 disp->types_exc |= type;
129         if (disp->types_inc & disp->types_exc & type) {
130                 fprintf(stderr,
131                         "Cannot use both include and exclude for '%s'\n", str);
132                 return -1;
133         }
134
135         str = strdup(str);
136         if (!str)
137                 goto err_mem;
138         node = malloc(sizeof(*node));
139         if (!node)
140                 goto err_mem;
141         node->next = *headp;
142         node->type = type;
143         node->include = include;
144         node->string = str;
145         *headp = node;
146
147         return 0;
148 err_mem:
149         fprintf(stderr, "Out of memory\n");
150         return -1;
151 }
152
153 static bool util_is_printable_string(const void *data, int len)
154 {
155         const char *s = data;
156         const char *ss, *se;
157
158         /* zero length is not */
159         if (len == 0)
160                 return 0;
161
162         /* must terminate with zero */
163         if (s[len - 1] != '\0')
164                 return 0;
165
166         se = s + len;
167
168         while (s < se) {
169                 ss = s;
170                 while (s < se && *s && isprint((unsigned char)*s))
171                         s++;
172
173                 /* not zero, or not done yet */
174                 if (*s != '\0' || s == ss)
175                         return 0;
176
177                 s++;
178         }
179
180         return 1;
181 }
182
183 static void utilfdt_print_data(const char *data, int len)
184 {
185         int i;
186         const char *p = data;
187         const char *s;
188
189         /* no data, don't print */
190         if (len == 0)
191                 return;
192
193         if (util_is_printable_string(data, len)) {
194                 printf(" = ");
195
196                 s = data;
197                 do {
198                         printf("\"%s\"", s);
199                         s += strlen(s) + 1;
200                         if (s < data + len)
201                                 printf(", ");
202                 } while (s < data + len);
203
204         } else if ((len % 4) == 0) {
205                 const uint32_t *cell = (const uint32_t *)data;
206
207                 printf(" = <");
208                 for (i = 0, len /= 4; i < len; i++)
209                         printf("0x%08x%s", fdt32_to_cpu(cell[i]),
210                                i < (len - 1) ? " " : "");
211                 printf(">");
212         } else {
213                 printf(" = [");
214                 for (i = 0; i < len; i++)
215                         printf("%02x%s", *p++, i < len - 1 ? " " : "");
216                 printf("]");
217         }
218 }
219
220 /**
221  * display_fdt_by_regions() - Display regions of an FDT source
222  *
223  * This dumps an FDT as source, but only certain regions of it. This is the
224  * final stage of the grep - we have a list of regions we want to display,
225  * and this function displays them.
226  *
227  * @disp:       Display structure, holding info about our options
228  * @blob:       FDT blob to display
229  * @region:     List of regions to display
230  * @count:      Number of regions
231  */
232 static int display_fdt_by_regions(struct display_info *disp, const void *blob,
233                 struct fdt_region region[], int count)
234 {
235         struct fdt_region *reg = region, *reg_end = region + count;
236         uint32_t off_mem_rsvmap = fdt_off_mem_rsvmap(blob);
237         int base = fdt_off_dt_struct(blob);
238         int version = fdt_version(blob);
239         int offset, nextoffset;
240         int tag, depth, shift;
241         FILE *f = disp->fout;
242         uint64_t addr, size;
243         int in_region;
244         int file_ofs;
245         int i;
246
247         if (disp->show_dts_version)
248                 fprintf(f, "/dts-v1/;\n");
249
250         if (disp->header) {
251                 fprintf(f, "// magic:\t\t0x%x\n", fdt_magic(blob));
252                 fprintf(f, "// totalsize:\t\t0x%x (%d)\n", fdt_totalsize(blob),
253                         fdt_totalsize(blob));
254                 fprintf(f, "// off_dt_struct:\t0x%x\n",
255                         fdt_off_dt_struct(blob));
256                 fprintf(f, "// off_dt_strings:\t0x%x\n",
257                         fdt_off_dt_strings(blob));
258                 fprintf(f, "// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
259                 fprintf(f, "// version:\t\t%d\n", version);
260                 fprintf(f, "// last_comp_version:\t%d\n",
261                         fdt_last_comp_version(blob));
262                 if (version >= 2) {
263                         fprintf(f, "// boot_cpuid_phys:\t0x%x\n",
264                                 fdt_boot_cpuid_phys(blob));
265                 }
266                 if (version >= 3) {
267                         fprintf(f, "// size_dt_strings:\t0x%x\n",
268                                 fdt_size_dt_strings(blob));
269                 }
270                 if (version >= 17) {
271                         fprintf(f, "// size_dt_struct:\t0x%x\n",
272                                 fdt_size_dt_struct(blob));
273                 }
274                 fprintf(f, "\n");
275         }
276
277         if (disp->flags & FDT_REG_ADD_MEM_RSVMAP) {
278                 const struct fdt_reserve_entry *p_rsvmap;
279
280                 p_rsvmap = (const struct fdt_reserve_entry *)
281                                 ((const char *)blob + off_mem_rsvmap);
282                 for (i = 0; ; i++) {
283                         addr = fdt64_to_cpu(p_rsvmap[i].address);
284                         size = fdt64_to_cpu(p_rsvmap[i].size);
285                         if (addr == 0 && size == 0)
286                                 break;
287
288                         fprintf(f, "/memreserve/ %llx %llx;\n",
289                                 (unsigned long long)addr,
290                                 (unsigned long long)size);
291                 }
292         }
293
294         depth = 0;
295         nextoffset = 0;
296         shift = 4;      /* 4 spaces per indent */
297         do {
298                 const struct fdt_property *prop;
299                 const char *name;
300                 int show;
301                 int len;
302
303                 offset = nextoffset;
304
305                 /*
306                  * Work out the file offset of this offset, and decide
307                  * whether it is in the region list or not
308                  */
309                 file_ofs = base + offset;
310                 if (reg < reg_end && file_ofs >= reg->offset + reg->size)
311                         reg++;
312                 in_region = reg < reg_end && file_ofs >= reg->offset &&
313                                 file_ofs < reg->offset + reg->size;
314                 tag = fdt_next_tag(blob, offset, &nextoffset);
315
316                 if (tag == FDT_END)
317                         break;
318                 show = in_region || disp->all;
319                 if (show && disp->diff)
320                         fprintf(f, "%c", in_region ? '+' : '-');
321
322                 if (!show) {
323                         /* Do this here to avoid 'if (show)' in every 'case' */
324                         if (tag == FDT_BEGIN_NODE)
325                                 depth++;
326                         else if (tag == FDT_END_NODE)
327                                 depth--;
328                         continue;
329                 }
330                 if (tag != FDT_END) {
331                         if (disp->show_addr)
332                                 fprintf(f, "%4x: ", file_ofs);
333                         if (disp->show_offset)
334                                 fprintf(f, "%4x: ", file_ofs - base);
335                 }
336
337                 /* Green means included, red means excluded */
338                 if (disp->colour)
339                         print_ansi_colour(f, in_region ? COL_GREEN : COL_RED);
340
341                 switch (tag) {
342                 case FDT_PROP:
343                         prop = fdt_get_property_by_offset(blob, offset, NULL);
344                         name = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
345                         fprintf(f, "%*s%s", depth * shift, "", name);
346                         utilfdt_print_data(prop->data,
347                                            fdt32_to_cpu(prop->len));
348                         fprintf(f, ";");
349                         break;
350
351                 case FDT_NOP:
352                         fprintf(f, "%*s// [NOP]", depth * shift, "");
353                         break;
354
355                 case FDT_BEGIN_NODE:
356                         name = fdt_get_name(blob, offset, &len);
357                         fprintf(f, "%*s%s {", depth++ * shift, "",
358                                 *name ? name : "/");
359                         break;
360
361                 case FDT_END_NODE:
362                         fprintf(f, "%*s};", --depth * shift, "");
363                         break;
364                 }
365
366                 /* Reset colour back to normal before end of line */
367                 if (disp->colour)
368                         print_ansi_colour(f, COL_NONE);
369                 fprintf(f, "\n");
370         } while (1);
371
372         /* Print a list of strings if requested */
373         if (disp->list_strings) {
374                 const char *str;
375                 int str_base = fdt_off_dt_strings(blob);
376
377                 for (offset = 0; offset < fdt_size_dt_strings(blob);
378                                 offset += strlen(str) + 1) {
379                         str = fdt_string(blob, offset);
380                         int len = strlen(str) + 1;
381                         int show;
382
383                         /* Only print strings that are in the region */
384                         file_ofs = str_base + offset;
385                         in_region = reg < reg_end &&
386                                         file_ofs >= reg->offset &&
387                                         file_ofs + len < reg->offset +
388                                                 reg->size;
389                         show = in_region || disp->all;
390                         if (show && disp->diff)
391                                 printf("%c", in_region ? '+' : '-');
392                         if (disp->show_addr)
393                                 printf("%4x: ", file_ofs);
394                         if (disp->show_offset)
395                                 printf("%4x: ", offset);
396                         printf("%s\n", str);
397                 }
398         }
399
400         return 0;
401 }
402
403 /**
404  * dump_fdt_regions() - Dump regions of an FDT as binary data
405  *
406  * This dumps an FDT as binary, but only certain regions of it. This is the
407  * final stage of the grep - we have a list of regions we want to dump,
408  * and this function dumps them.
409  *
410  * The output of this function may or may not be a valid FDT. To ensure it
411  * is, these disp->flags must be set:
412  *
413  *   FDT_REG_SUPERNODES: ensures that subnodes are preceded by their
414  *              parents. Without this option, fragments of subnode data may be
415  *              output without the supernodes above them. This is useful for
416  *              hashing but cannot produce a valid FDT.
417  *   FDT_REG_ADD_STRING_TAB: Adds a string table to the end of the FDT.
418  *              Without this none of the properties will have names
419  *   FDT_REG_ADD_MEM_RSVMAP: Adds a mem_rsvmap table - an FDT is invalid
420  *              without this.
421  *
422  * @disp:       Display structure, holding info about our options
423  * @blob:       FDT blob to display
424  * @region:     List of regions to display
425  * @count:      Number of regions
426  * @out:        Output destination
427  */
428 static int dump_fdt_regions(struct display_info *disp, const void *blob,
429                 struct fdt_region region[], int count, char *out)
430 {
431         struct fdt_header *fdt;
432         int size, struct_start;
433         int ptr;
434         int i;
435
436         /* Set up a basic header (even if we don't actually write it) */
437         fdt = (struct fdt_header *)out;
438         memset(fdt, '\0', sizeof(*fdt));
439         fdt_set_magic(fdt, FDT_MAGIC);
440         struct_start = FDT_ALIGN(sizeof(struct fdt_header),
441                                         sizeof(struct fdt_reserve_entry));
442         fdt_set_off_mem_rsvmap(fdt, struct_start);
443         fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
444         fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
445
446         /*
447          * Calculate the total size of the regions we are writing out. The
448          * first will be the mem_rsvmap if the FDT_REG_ADD_MEM_RSVMAP flag
449          * is set. The last will be the string table if FDT_REG_ADD_STRING_TAB
450          * is set.
451          */
452         for (i = size = 0; i < count; i++)
453                 size += region[i].size;
454
455         /* Bring in the mem_rsvmap section from the old file if requested */
456         if (count > 0 && (disp->flags & FDT_REG_ADD_MEM_RSVMAP)) {
457                 struct_start += region[0].size;
458                 size -= region[0].size;
459         }
460         fdt_set_off_dt_struct(fdt, struct_start);
461
462         /* Update the header to have the correct offsets/sizes */
463         if (count >= 2 && (disp->flags & FDT_REG_ADD_STRING_TAB)) {
464                 int str_size;
465
466                 str_size = region[count - 1].size;
467                 fdt_set_size_dt_struct(fdt, size - str_size);
468                 fdt_set_off_dt_strings(fdt, struct_start + size - str_size);
469                 fdt_set_size_dt_strings(fdt, str_size);
470                 fdt_set_totalsize(fdt, struct_start + size);
471         }
472
473         /* Write the header if required */
474         ptr = 0;
475         if (disp->header) {
476                 ptr = sizeof(*fdt);
477                 while (ptr < fdt_off_mem_rsvmap(fdt))
478                         out[ptr++] = '\0';
479         }
480
481         /* Output all the nodes including any mem_rsvmap/string table */
482         for (i = 0; i < count; i++) {
483                 struct fdt_region *reg = &region[i];
484
485                 memcpy(out + ptr, (const char *)blob + reg->offset, reg->size);
486                 ptr += reg->size;
487         }
488
489         return ptr;
490 }
491
492 /**
493  * show_region_list() - Print out a list of regions
494  *
495  * The list includes the region offset (absolute offset from start of FDT
496  * blob in bytes) and size
497  *
498  * @reg:        List of regions to print
499  * @count:      Number of regions
500  */
501 static void show_region_list(struct fdt_region *reg, int count)
502 {
503         int i;
504
505         printf("Regions: %d\n", count);
506         for (i = 0; i < count; i++, reg++) {
507                 printf("%d:  %-10x  %-10x\n", i, reg->offset,
508                        reg->offset + reg->size);
509         }
510 }
511
512 static int check_type_include(void *priv, int type, const char *data, int size)
513 {
514         struct display_info *disp = priv;
515         struct value_node *val;
516         int match, none_match = FDT_IS_ANY;
517
518         /* If none of our conditions mention this type, we know nothing */
519         debug("type=%x, data=%s\n", type, data ? data : "(null)");
520         if (!((disp->types_inc | disp->types_exc) & type)) {
521                 debug("   - not in any condition\n");
522                 return -1;
523         }
524
525         /*
526          * Go through the list of conditions. For inclusive conditions, we
527          * return 1 at the first match. For exclusive conditions, we must
528          * check that there are no matches.
529          */
530         if (data) {
531                 for (val = disp->value_head; val; val = val->next) {
532                         if (!(type & val->type))
533                                 continue;
534                         match = fdt_stringlist_contains(data, size,
535                                                         val->string);
536                         debug("      - val->type=%x, str='%s', match=%d\n",
537                               val->type, val->string, match);
538                         if (match && val->include) {
539                                 debug("   - match inc %s\n", val->string);
540                                 return 1;
541                         }
542                         if (match)
543                                 none_match &= ~val->type;
544                 }
545         }
546
547         /*
548          * If this is an exclusive condition, and nothing matches, then we
549          * should return 1.
550          */
551         if ((type & disp->types_exc) && (none_match & type)) {
552                 debug("   - match exc\n");
553                 /*
554                  * Allow FDT_IS_COMPAT to make the final decision in the
555                  * case where there is no specific type
556                  */
557                 if (type == FDT_IS_NODE && disp->types_exc == FDT_ANY_GLOBAL) {
558                         debug("   - supressed exc node\n");
559                         return -1;
560                 }
561                 return 1;
562         }
563
564         /*
565          * Allow FDT_IS_COMPAT to make the final decision in the
566          * case where there is no specific type (inclusive)
567          */
568         if (type == FDT_IS_NODE && disp->types_inc == FDT_ANY_GLOBAL)
569                 return -1;
570
571         debug("   - no match, types_inc=%x, types_exc=%x, none_match=%x\n",
572               disp->types_inc, disp->types_exc, none_match);
573
574         return 0;
575 }
576
577 /**
578  * h_include() - Include handler function for fdt_find_regions()
579  *
580  * This function decides whether to include or exclude a node, property or
581  * compatible string. The function is defined by fdt_find_regions().
582  *
583  * The algorithm is documented in the code - disp->invert is 0 for normal
584  * operation, and 1 to invert the sense of all matches.
585  *
586  * See
587  */
588 static int h_include(void *priv, const void *fdt, int offset, int type,
589                      const char *data, int size)
590 {
591         struct display_info *disp = priv;
592         int inc, len;
593
594         inc = check_type_include(priv, type, data, size);
595         if (disp->include_root && type == FDT_IS_PROP && offset == 0 && inc)
596                 return 1;
597
598         /*
599          * If the node name does not tell us anything, check the
600          * compatible string
601          */
602         if (inc == -1 && type == FDT_IS_NODE) {
603                 debug("   - checking compatible2\n");
604                 data = fdt_getprop(fdt, offset, "compatible", &len);
605                 inc = check_type_include(priv, FDT_IS_COMPAT, data, len);
606         }
607
608         /* If we still have no idea, check for properties in the node */
609         if (inc != 1 && type == FDT_IS_NODE &&
610             (disp->types_inc & FDT_NODE_HAS_PROP)) {
611                 debug("   - checking node '%s'\n",
612                       fdt_get_name(fdt, offset, NULL));
613                 for (offset = fdt_first_property_offset(fdt, offset);
614                      offset > 0 && inc != 1;
615                      offset = fdt_next_property_offset(fdt, offset)) {
616                         const struct fdt_property *prop;
617                         const char *str;
618
619                         prop = fdt_get_property_by_offset(fdt, offset, NULL);
620                         if (!prop)
621                                 continue;
622                         str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
623                         inc = check_type_include(priv, FDT_NODE_HAS_PROP, str,
624                                                  strlen(str));
625                 }
626                 if (inc == -1)
627                         inc = 0;
628         }
629
630         switch (inc) {
631         case 1:
632                 inc = !disp->invert;
633                 break;
634         case 0:
635                 inc = disp->invert;
636                 break;
637         }
638         debug("   - returning %d\n", inc);
639
640         return inc;
641 }
642
643 static int h_cmp_region(const void *v1, const void *v2)
644 {
645         const struct fdt_region *region1 = v1, *region2 = v2;
646
647         return region1->offset - region2->offset;
648 }
649
650 static int fdtgrep_find_regions(const void *fdt,
651                 int (*include_func)(void *priv, const void *fdt, int offset,
652                                  int type, const char *data, int size),
653                 struct display_info *disp, struct fdt_region *region,
654                 int max_regions, char *path, int path_len, int flags)
655 {
656         struct fdt_region_state state;
657         int count;
658         int ret;
659
660         count = 0;
661         ret = fdt_first_region(fdt, include_func, disp,
662                         &region[count++], path, path_len,
663                         disp->flags, &state);
664         while (ret == 0) {
665                 ret = fdt_next_region(fdt, include_func, disp,
666                                 count < max_regions ? &region[count] : NULL,
667                                 path, path_len, disp->flags, &state);
668                 if (!ret)
669                         count++;
670         }
671         if (ret && ret != -FDT_ERR_NOTFOUND)
672                 return ret;
673
674         /* Find all the aliases and add those regions back in */
675         if (disp->add_aliases && count < max_regions) {
676                 int new_count;
677
678                 new_count = fdt_add_alias_regions(fdt, region, count,
679                                                   max_regions, &state);
680                 if (new_count == -FDT_ERR_NOTFOUND) {
681                         /* No alias node found */
682                 } else if (new_count < 0) {
683                         return new_count;
684                 } else if (new_count <= max_regions) {
685                         /*
686                         * The alias regions will now be at the end of the list.
687                         * Sort the regions by offset to get things into the
688                         * right order
689                         */
690                         count = new_count;
691                         qsort(region, count, sizeof(struct fdt_region),
692                               h_cmp_region);
693                 }
694         }
695
696         return count;
697 }
698
699 int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
700 {
701         int fd = 0;     /* assume stdin */
702         char *buf = NULL;
703         off_t bufsize = 1024, offset = 0;
704         int ret = 0;
705
706         *buffp = NULL;
707         if (strcmp(filename, "-") != 0) {
708                 fd = open(filename, O_RDONLY);
709                 if (fd < 0)
710                         return errno;
711         }
712
713         /* Loop until we have read everything */
714         buf = malloc(bufsize);
715         if (!buf)
716                 return -ENOMEM;
717         do {
718                 /* Expand the buffer to hold the next chunk */
719                 if (offset == bufsize) {
720                         bufsize *= 2;
721                         buf = realloc(buf, bufsize);
722                         if (!buf)
723                                 return -ENOMEM;
724                 }
725
726                 ret = read(fd, &buf[offset], bufsize - offset);
727                 if (ret < 0) {
728                         ret = errno;
729                         break;
730                 }
731                 offset += ret;
732         } while (ret != 0);
733
734         /* Clean up, including closing stdin; return errno on error */
735         close(fd);
736         if (ret)
737                 free(buf);
738         else
739                 *buffp = buf;
740         *len = bufsize;
741         return ret;
742 }
743
744 int utilfdt_read_err(const char *filename, char **buffp)
745 {
746         off_t len;
747         return utilfdt_read_err_len(filename, buffp, &len);
748 }
749
750 char *utilfdt_read_len(const char *filename, off_t *len)
751 {
752         char *buff;
753         int ret = utilfdt_read_err_len(filename, &buff, len);
754
755         if (ret) {
756                 fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
757                         strerror(ret));
758                 return NULL;
759         }
760         /* Successful read */
761         return buff;
762 }
763
764 char *utilfdt_read(const char *filename)
765 {
766         off_t len;
767         return utilfdt_read_len(filename, &len);
768 }
769
770 /**
771  * Run the main fdtgrep operation, given a filename and valid arguments
772  *
773  * @param disp          Display information / options
774  * @param filename      Filename of blob file
775  * @param return 0 if ok, -ve on error
776  */
777 static int do_fdtgrep(struct display_info *disp, const char *filename)
778 {
779         struct fdt_region *region = NULL;
780         int max_regions;
781         int count = 100;
782         char path[1024];
783         char *blob;
784         int i, ret;
785
786         blob = utilfdt_read(filename);
787         if (!blob)
788                 return -1;
789         ret = fdt_check_header(blob);
790         if (ret) {
791                 fprintf(stderr, "Error: %s\n", fdt_strerror(ret));
792                 return ret;
793         }
794
795         /* Allow old files, but they are untested */
796         if (fdt_version(blob) < 17 && disp->value_head) {
797                 fprintf(stderr,
798                         "Warning: fdtgrep does not fully support version %d files\n",
799                         fdt_version(blob));
800         }
801
802         /*
803          * We do two passes, since we don't know how many regions we need.
804          * The first pass will count the regions, but if it is too many,
805          * we do another pass to actually record them.
806          */
807         for (i = 0; i < 2; i++) {
808                 region = realloc(region, count * sizeof(struct fdt_region));
809                 if (!region) {
810                         fprintf(stderr, "Out of memory for %d regions\n",
811                                 count);
812                         return -1;
813                 }
814                 max_regions = count;
815                 count = fdtgrep_find_regions(blob,
816                                 h_include, disp,
817                                 region, max_regions, path, sizeof(path),
818                                 disp->flags);
819                 if (count < 0) {
820                         report_error("fdt_find_regions", count);
821                         free(region);
822                         return -1;
823                 }
824                 if (count <= max_regions)
825                         break;
826         }
827         if (count > max_regions) {
828                 free(region);
829                 fprintf(stderr, "Internal error with fdtgrep_find_region()\n");
830                 return -1;
831         }
832
833         /* Optionally print a list of regions */
834         if (disp->region_list)
835                 show_region_list(region, count);
836
837         /* Output either source .dts or binary .dtb */
838         if (disp->output == OUT_DTS) {
839                 ret = display_fdt_by_regions(disp, blob, region, count);
840         } else {
841                 void *fdt;
842                 /* Allow reserved memory section to expand slightly */
843                 int size = fdt_totalsize(blob) + 16;
844
845                 fdt = malloc(size);
846                 if (!fdt) {
847                         fprintf(stderr, "Out_of_memory\n");
848                         ret = -1;
849                         goto err;
850                 }
851                 size = dump_fdt_regions(disp, blob, region, count, fdt);
852                 if (disp->remove_strings) {
853                         void *out;
854
855                         out = malloc(size);
856                         if (!out) {
857                                 fprintf(stderr, "Out_of_memory\n");
858                                 ret = -1;
859                                 goto err;
860                         }
861                         ret = fdt_remove_unused_strings(fdt, out);
862                         if (ret < 0) {
863                                 fprintf(stderr,
864                                         "Failed to remove unused strings: err=%d\n",
865                                         ret);
866                                 goto err;
867                         }
868                         free(fdt);
869                         fdt = out;
870                         ret = fdt_pack(fdt);
871                         if (ret < 0) {
872                                 fprintf(stderr, "Failed to pack: err=%d\n",
873                                         ret);
874                                 goto err;
875                         }
876                         size = fdt_totalsize(fdt);
877                 }
878
879                 if (size != fwrite(fdt, 1, size, disp->fout)) {
880                         fprintf(stderr, "Write failure, %d bytes\n", size);
881                         free(fdt);
882                         ret = 1;
883                         goto err;
884                 }
885                 free(fdt);
886         }
887 err:
888         free(blob);
889         free(region);
890
891         return ret;
892 }
893
894 static const char usage_synopsis[] =
895         "fdtgrep - extract portions from device tree\n"
896         "\n"
897         "Usage:\n"
898         "       fdtgrep <options> <dt file>|-\n\n"
899         "Output formats are:\n"
900         "\tdts - device tree soure text\n"
901         "\tdtb - device tree blob (sets -Hmt automatically)\n"
902         "\tbin - device tree fragment (may not be a valid .dtb)";
903
904 /* Helper for usage_short_opts string constant */
905 #define USAGE_COMMON_SHORT_OPTS "hV"
906
907 /* Helper for aligning long_opts array */
908 #define a_argument required_argument
909
910 /* Helper for usage_long_opts option array */
911 #define USAGE_COMMON_LONG_OPTS \
912         {"help",      no_argument, NULL, 'h'}, \
913         {"version",   no_argument, NULL, 'V'}, \
914         {NULL,        no_argument, NULL, 0x0}
915
916 /* Helper for usage_opts_help array */
917 #define USAGE_COMMON_OPTS_HELP \
918         "Print this help and exit", \
919         "Print version and exit", \
920         NULL
921
922 /* Helper for getopt case statements */
923 #define case_USAGE_COMMON_FLAGS \
924         case 'h': usage(NULL); \
925         case 'V': util_version(); \
926         case '?': usage("unknown option");
927
928 static const char usage_short_opts[] =
929                 "haAc:b:C:defg:G:HIlLmn:N:o:O:p:P:rRsStTv"
930                 USAGE_COMMON_SHORT_OPTS;
931 static struct option const usage_long_opts[] = {
932         {"show-address",        no_argument, NULL, 'a'},
933         {"colour",              no_argument, NULL, 'A'},
934         {"include-node-with-prop", a_argument, NULL, 'b'},
935         {"include-compat",      a_argument, NULL, 'c'},
936         {"exclude-compat",      a_argument, NULL, 'C'},
937         {"diff",                no_argument, NULL, 'd'},
938         {"enter-node",          no_argument, NULL, 'e'},
939         {"show-offset",         no_argument, NULL, 'f'},
940         {"include-match",       a_argument, NULL, 'g'},
941         {"exclude-match",       a_argument, NULL, 'G'},
942         {"show-header",         no_argument, NULL, 'H'},
943         {"show-version",        no_argument, NULL, 'I'},
944         {"list-regions",        no_argument, NULL, 'l'},
945         {"list-strings",        no_argument, NULL, 'L'},
946         {"include-mem",         no_argument, NULL, 'm'},
947         {"include-node",        a_argument, NULL, 'n'},
948         {"exclude-node",        a_argument, NULL, 'N'},
949         {"include-prop",        a_argument, NULL, 'p'},
950         {"exclude-prop",        a_argument, NULL, 'P'},
951         {"remove-strings",      no_argument, NULL, 'r'},
952         {"include-root",        no_argument, NULL, 'R'},
953         {"show-subnodes",       no_argument, NULL, 's'},
954         {"skip-supernodes",     no_argument, NULL, 'S'},
955         {"show-stringtab",      no_argument, NULL, 't'},
956         {"show-aliases",        no_argument, NULL, 'T'},
957         {"out",                 a_argument, NULL, 'o'},
958         {"out-format",          a_argument, NULL, 'O'},
959         {"invert-match",        no_argument, NULL, 'v'},
960         USAGE_COMMON_LONG_OPTS,
961 };
962 static const char * const usage_opts_help[] = {
963         "Display address",
964         "Show all nodes/tags, colour those that match",
965         "Include contains containing property",
966         "Compatible nodes to include in grep",
967         "Compatible nodes to exclude in grep",
968         "Diff: Mark matching nodes with +, others with -",
969         "Enter direct subnode names of matching nodes",
970         "Display offset",
971         "Node/property/compatible string to include in grep",
972         "Node/property/compatible string to exclude in grep",
973         "Output a header",
974         "Put \"/dts-v1/;\" on first line of dts output",
975         "Output a region list",
976         "List strings in string table",
977         "Include mem_rsvmap section in binary output",
978         "Node to include in grep",
979         "Node to exclude in grep",
980         "Property to include in grep",
981         "Property to exclude in grep",
982         "Remove unused strings from string table",
983         "Include root node and all properties",
984         "Show all subnodes matching nodes",
985         "Don't include supernodes of matching nodes",
986         "Include string table in binary output",
987         "Include matching aliases in output",
988         "-o <output file>",
989         "-O <output format>",
990         "Invert the sense of matching (select non-matching lines)",
991         USAGE_COMMON_OPTS_HELP
992 };
993
994 /**
995  * Call getopt_long() with standard options
996  *
997  * Since all util code runs getopt in the same way, provide a helper.
998  */
999 #define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
1000                                        usage_long_opts, NULL)
1001
1002 void util_usage(const char *errmsg, const char *synopsis,
1003                 const char *short_opts, struct option const long_opts[],
1004                 const char * const opts_help[])
1005 {
1006         FILE *fp = errmsg ? stderr : stdout;
1007         const char a_arg[] = "<arg>";
1008         size_t a_arg_len = strlen(a_arg) + 1;
1009         size_t i;
1010         int optlen;
1011
1012         fprintf(fp,
1013                 "Usage: %s\n"
1014                 "\n"
1015                 "Options: -[%s]\n", synopsis, short_opts);
1016
1017         /* prescan the --long opt length to auto-align */
1018         optlen = 0;
1019         for (i = 0; long_opts[i].name; ++i) {
1020                 /* +1 is for space between --opt and help text */
1021                 int l = strlen(long_opts[i].name) + 1;
1022                 if (long_opts[i].has_arg == a_argument)
1023                         l += a_arg_len;
1024                 if (optlen < l)
1025                         optlen = l;
1026         }
1027
1028         for (i = 0; long_opts[i].name; ++i) {
1029                 /* helps when adding new applets or options */
1030                 assert(opts_help[i] != NULL);
1031
1032                 /* first output the short flag if it has one */
1033                 if (long_opts[i].val > '~')
1034                         fprintf(fp, "      ");
1035                 else
1036                         fprintf(fp, "  -%c, ", long_opts[i].val);
1037
1038                 /* then the long flag */
1039                 if (long_opts[i].has_arg == no_argument) {
1040                         fprintf(fp, "--%-*s", optlen, long_opts[i].name);
1041                 } else {
1042                         fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
1043                                 (int)(optlen - strlen(long_opts[i].name) -
1044                                 a_arg_len), "");
1045                 }
1046
1047                 /* finally the help text */
1048                 fprintf(fp, "%s\n", opts_help[i]);
1049         }
1050
1051         if (errmsg) {
1052                 fprintf(fp, "\nError: %s\n", errmsg);
1053                 exit(EXIT_FAILURE);
1054         } else {
1055                 exit(EXIT_SUCCESS);
1056         }
1057 }
1058
1059 /**
1060  * Show usage and exit
1061  *
1062  * If you name all your usage variables with usage_xxx, then you can call this
1063  * help macro rather than expanding all arguments yourself.
1064  *
1065  * @param errmsg        If non-NULL, an error message to display
1066  */
1067 #define usage(errmsg) \
1068         util_usage(errmsg, usage_synopsis, usage_short_opts, \
1069                    usage_long_opts, usage_opts_help)
1070
1071 void util_version(void)
1072 {
1073         printf("Version: %s\n", "(U-Boot)");
1074         exit(0);
1075 }
1076
1077 static void scan_args(struct display_info *disp, int argc, char *argv[])
1078 {
1079         int opt;
1080
1081         while ((opt = util_getopt_long()) != EOF) {
1082                 int type = 0;
1083                 int inc = 1;
1084
1085                 switch (opt) {
1086                 case_USAGE_COMMON_FLAGS
1087                 case 'a':
1088                         disp->show_addr = 1;
1089                         break;
1090                 case 'A':
1091                         disp->all = 1;
1092                         break;
1093                 case 'b':
1094                         type = FDT_NODE_HAS_PROP;
1095                         break;
1096                 case 'C':
1097                         inc = 0;
1098                         /* no break */
1099                 case 'c':
1100                         type = FDT_IS_COMPAT;
1101                         break;
1102                 case 'd':
1103                         disp->diff = 1;
1104                         break;
1105                 case 'e':
1106                         disp->flags |= FDT_REG_DIRECT_SUBNODES;
1107                         break;
1108                 case 'f':
1109                         disp->show_offset = 1;
1110                         break;
1111                 case 'G':
1112                         inc = 0;
1113                         /* no break */
1114                 case 'g':
1115                         type = FDT_ANY_GLOBAL;
1116                         break;
1117                 case 'H':
1118                         disp->header = 1;
1119                         break;
1120                 case 'l':
1121                         disp->region_list = 1;
1122                         break;
1123                 case 'L':
1124                         disp->list_strings = 1;
1125                         break;
1126                 case 'm':
1127                         disp->flags |= FDT_REG_ADD_MEM_RSVMAP;
1128                         break;
1129                 case 'N':
1130                         inc = 0;
1131                         /* no break */
1132                 case 'n':
1133                         type = FDT_IS_NODE;
1134                         break;
1135                 case 'o':
1136                         disp->output_fname = optarg;
1137                         break;
1138                 case 'O':
1139                         if (!strcmp(optarg, "dtb"))
1140                                 disp->output = OUT_DTB;
1141                         else if (!strcmp(optarg, "dts"))
1142                                 disp->output = OUT_DTS;
1143                         else if (!strcmp(optarg, "bin"))
1144                                 disp->output = OUT_BIN;
1145                         else
1146                                 usage("Unknown output format");
1147                         break;
1148                 case 'P':
1149                         inc = 0;
1150                         /* no break */
1151                 case 'p':
1152                         type = FDT_IS_PROP;
1153                         break;
1154                 case 'r':
1155                         disp->remove_strings = 1;
1156                         break;
1157                 case 'R':
1158                         disp->include_root = 1;
1159                         break;
1160                 case 's':
1161                         disp->flags |= FDT_REG_ALL_SUBNODES;
1162                         break;
1163                 case 'S':
1164                         disp->flags &= ~FDT_REG_SUPERNODES;
1165                         break;
1166                 case 't':
1167                         disp->flags |= FDT_REG_ADD_STRING_TAB;
1168                         break;
1169                 case 'T':
1170                         disp->add_aliases = 1;
1171                         break;
1172                 case 'v':
1173                         disp->invert = 1;
1174                         break;
1175                 case 'I':
1176                         disp->show_dts_version = 1;
1177                         break;
1178                 }
1179
1180                 if (type && value_add(disp, &disp->value_head, type, inc,
1181                                       optarg))
1182                         usage("Cannot add value");
1183         }
1184
1185         if (disp->invert && disp->types_exc)
1186                 usage("-v has no meaning when used with 'exclude' conditions");
1187 }
1188
1189 int main(int argc, char *argv[])
1190 {
1191         char *filename = NULL;
1192         struct display_info disp;
1193         int ret;
1194
1195         /* set defaults */
1196         memset(&disp, '\0', sizeof(disp));
1197         disp.flags = FDT_REG_SUPERNODES;        /* Default flags */
1198
1199         scan_args(&disp, argc, argv);
1200
1201         /* Show matched lines in colour if we can */
1202         disp.colour = disp.all && isatty(0);
1203
1204         /* Any additional arguments can match anything, just like -g */
1205         while (optind < argc - 1) {
1206                 if (value_add(&disp, &disp.value_head, FDT_IS_ANY, 1,
1207                               argv[optind++]))
1208                         usage("Cannot add value");
1209         }
1210
1211         if (optind < argc)
1212                 filename = argv[optind++];
1213         if (!filename)
1214                 usage("Missing filename");
1215
1216         /* If a valid .dtb is required, set flags to ensure we get one */
1217         if (disp.output == OUT_DTB) {
1218                 disp.header = 1;
1219                 disp.flags |= FDT_REG_ADD_MEM_RSVMAP | FDT_REG_ADD_STRING_TAB;
1220         }
1221
1222         if (disp.output_fname) {
1223                 disp.fout = fopen(disp.output_fname, "w");
1224                 if (!disp.fout)
1225                         usage("Cannot open output file");
1226         } else {
1227                 disp.fout = stdout;
1228         }
1229
1230         /* Run the grep and output the results */
1231         ret = do_fdtgrep(&disp, filename);
1232         if (disp.output_fname)
1233                 fclose(disp.fout);
1234         if (ret)
1235                 return 1;
1236
1237         return 0;
1238 }