1/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 *                                                                   USA
19 */
20
21#include "dtc.h"
22#include "srcpos.h"
23
24/*
25 * Command line options
26 */
27int quiet;		/* Level of quietness */
28int reservenum;		/* Number of memory reservation slots */
29int minsize;		/* Minimum blob size */
30int padsize;		/* Additional padding to blob */
31int phandle_format = PHANDLE_BOTH;	/* Use linux,phandle or phandle properties */
32
33static void fill_fullpaths(struct node *tree, const char *prefix)
34{
35	struct node *child;
36	const char *unit;
37
38	tree->fullpath = join_path(prefix, tree->name);
39
40	unit = strchr(tree->name, '@');
41	if (unit)
42		tree->basenamelen = unit - tree->name;
43	else
44		tree->basenamelen = strlen(tree->name);
45
46	for_each_child(tree, child)
47		fill_fullpaths(child, tree->fullpath);
48}
49
50/* Usage related data. */
51#define FDT_VERSION(version)	_FDT_VERSION(version)
52#define _FDT_VERSION(version)	#version
53static const char usage_synopsis[] = "dtc [options] <input file>";
54static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
55static struct option const usage_long_opts[] = {
56	{"quiet",            no_argument, NULL, 'q'},
57	{"in-format",         a_argument, NULL, 'I'},
58	{"out",               a_argument, NULL, 'o'},
59	{"out-format",        a_argument, NULL, 'O'},
60	{"out-version",       a_argument, NULL, 'V'},
61	{"out-dependency",    a_argument, NULL, 'd'},
62	{"reserve",           a_argument, NULL, 'R'},
63	{"space",             a_argument, NULL, 'S'},
64	{"pad",               a_argument, NULL, 'p'},
65	{"boot-cpu",          a_argument, NULL, 'b'},
66	{"force",            no_argument, NULL, 'f'},
67	{"include",           a_argument, NULL, 'i'},
68	{"sort",             no_argument, NULL, 's'},
69	{"phandle",           a_argument, NULL, 'H'},
70	{"warning",           a_argument, NULL, 'W'},
71	{"error",             a_argument, NULL, 'E'},
72	{"help",             no_argument, NULL, 'h'},
73	{"version",          no_argument, NULL, 'v'},
74	{NULL,               no_argument, NULL, 0x0},
75};
76static const char * const usage_opts_help[] = {
77	"\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
78	"\n\tInput formats are:\n"
79	 "\t\tdts - device tree source text\n"
80	 "\t\tdtb - device tree blob\n"
81	 "\t\tfs  - /proc/device-tree style directory",
82	"\n\tOutput file",
83	"\n\tOutput formats are:\n"
84	 "\t\tdts - device tree source text\n"
85	 "\t\tdtb - device tree blob\n"
86	 "\t\tasm - assembler source",
87	"\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
88	"\n\tOutput dependency file",
89	"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
90	"\n\tMake the blob at least <bytes> long (extra space)",
91	"\n\tAdd padding to the blob of <bytes> long (extra space)",
92	"\n\tSet the physical boot cpu",
93	"\n\tTry to produce output even if the input tree has errors",
94	"\n\tAdd a path to search for include files",
95	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
96	"\n\tValid phandle formats are:\n"
97	 "\t\tlegacy - \"linux,phandle\" properties only\n"
98	 "\t\tepapr  - \"phandle\" properties only\n"
99	 "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
100	"\n\tEnable/disable warnings (prefix with \"no-\")",
101	"\n\tEnable/disable errors (prefix with \"no-\")",
102	"\n\tPrint this help and exit",
103	"\n\tPrint version and exit",
104	NULL,
105};
106
107int main(int argc, char *argv[])
108{
109	struct boot_info *bi;
110	const char *inform = "dts";
111	const char *outform = "dts";
112	const char *outname = "-";
113	const char *depname = NULL;
114	bool force = false, sort = false;
115	const char *arg;
116	int opt;
117	FILE *outf = NULL;
118	int outversion = DEFAULT_FDT_VERSION;
119	long long cmdline_boot_cpuid = -1;
120
121	quiet      = 0;
122	reservenum = 0;
123	minsize    = 0;
124	padsize    = 0;
125
126	while ((opt = util_getopt_long()) != EOF) {
127		switch (opt) {
128		case 'I':
129			inform = optarg;
130			break;
131		case 'O':
132			outform = optarg;
133			break;
134		case 'o':
135			outname = optarg;
136			break;
137		case 'V':
138			outversion = strtol(optarg, NULL, 0);
139			break;
140		case 'd':
141			depname = optarg;
142			break;
143		case 'R':
144			reservenum = strtol(optarg, NULL, 0);
145			break;
146		case 'S':
147			minsize = strtol(optarg, NULL, 0);
148			break;
149		case 'p':
150			padsize = strtol(optarg, NULL, 0);
151			break;
152		case 'f':
153			force = true;
154			break;
155		case 'q':
156			quiet++;
157			break;
158		case 'b':
159			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
160			break;
161		case 'i':
162			srcfile_add_search_path(optarg);
163			break;
164		case 'v':
165			util_version();
166		case 'H':
167			if (streq(optarg, "legacy"))
168				phandle_format = PHANDLE_LEGACY;
169			else if (streq(optarg, "epapr"))
170				phandle_format = PHANDLE_EPAPR;
171			else if (streq(optarg, "both"))
172				phandle_format = PHANDLE_BOTH;
173			else
174				die("Invalid argument \"%s\" to -H option\n",
175				    optarg);
176			break;
177
178		case 's':
179			sort = true;
180			break;
181
182		case 'W':
183			parse_checks_option(true, false, optarg);
184			break;
185
186		case 'E':
187			parse_checks_option(false, true, optarg);
188			break;
189
190		case 'h':
191			usage(NULL);
192		default:
193			usage("unknown option");
194		}
195	}
196
197	if (argc > (optind+1))
198		usage("missing files");
199	else if (argc < (optind+1))
200		arg = "-";
201	else
202		arg = argv[optind];
203
204	/* minsize and padsize are mutually exclusive */
205	if (minsize && padsize)
206		die("Can't set both -p and -S\n");
207
208	if (depname) {
209		depfile = fopen(depname, "w");
210		if (!depfile)
211			die("Couldn't open dependency file %s: %s\n", depname,
212			    strerror(errno));
213		fprintf(depfile, "%s:", outname);
214	}
215
216	if (streq(inform, "dts"))
217		bi = dt_from_source(arg);
218	else if (streq(inform, "fs"))
219		bi = dt_from_fs(arg);
220	else if(streq(inform, "dtb"))
221		bi = dt_from_blob(arg);
222	else
223		die("Unknown input format \"%s\"\n", inform);
224
225	if (depfile) {
226		fputc('\n', depfile);
227		fclose(depfile);
228	}
229
230	if (cmdline_boot_cpuid != -1)
231		bi->boot_cpuid_phys = cmdline_boot_cpuid;
232
233	fill_fullpaths(bi->dt, "");
234	process_checks(force, bi);
235
236	if (sort)
237		sort_tree(bi);
238
239	if (streq(outname, "-")) {
240		outf = stdout;
241	} else {
242		outf = fopen(outname, "wb");
243		if (! outf)
244			die("Couldn't open output file %s: %s\n",
245			    outname, strerror(errno));
246	}
247
248	if (streq(outform, "dts")) {
249		dt_to_source(outf, bi);
250	} else if (streq(outform, "dtb")) {
251		dt_to_blob(outf, bi, outversion);
252	} else if (streq(outform, "asm")) {
253		dt_to_asm(outf, bi, outversion);
254	} else if (streq(outform, "null")) {
255		/* do nothing */
256	} else {
257		die("Unknown output format \"%s\"\n", outform);
258	}
259
260	exit(0);
261}
262