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