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