dtc.c revision 302408
1139749Simp/*
2113584Ssimokawa * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3103285Sikob *
4103285Sikob *
5103285Sikob * This program is free software; you can redistribute it and/or
6103285Sikob * modify it under the terms of the GNU General Public License as
7103285Sikob * published by the Free Software Foundation; either version 2 of the
8103285Sikob * License, or (at your option) any later version.
9103285Sikob *
10103285Sikob *  This program is distributed in the hope that it will be useful,
11103285Sikob *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12103285Sikob *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13103285Sikob *  General Public License for more details.
14103285Sikob *
15103285Sikob *  You should have received a copy of the GNU General Public License
16103285Sikob *  along with this program; if not, write to the Free Software
17106802Ssimokawa *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18103285Sikob *                                                                   USA
19103285Sikob */
20103285Sikob
21103285Sikob#include "dtc.h"
22103285Sikob#include "srcpos.h"
23103285Sikob
24103285Sikob/*
25103285Sikob * Command line options
26103285Sikob */
27103285Sikobint quiet;		/* Level of quietness */
28103285Sikobint reservenum;		/* Number of memory reservation slots */
29103285Sikobint minsize;		/* Minimum blob size */
30103285Sikobint padsize;		/* Additional padding to blob */
31103285Sikobint phandle_format = PHANDLE_BOTH;	/* Use linux,phandle or phandle properties */
32103285Sikob
33103285Sikobstatic void fill_fullpaths(struct node *tree, const char *prefix)
34103285Sikob{
35103285Sikob	struct node *child;
36103285Sikob	const char *unit;
37106802Ssimokawa
38103285Sikob	tree->fullpath = join_path(prefix, tree->name);
39103285Sikob
40103285Sikob	unit = strchr(tree->name, '@');
41103285Sikob	if (unit)
42103285Sikob		tree->basenamelen = unit - tree->name;
43103285Sikob	else
44103285Sikob		tree->basenamelen = strlen(tree->name);
45103285Sikob
46103285Sikob	for_each_child(tree, child)
47103285Sikob		fill_fullpaths(child, tree->fullpath);
48103285Sikob}
49103285Sikob
50103285Sikob/* Usage related data. */
51103285Sikobstatic const char usage_synopsis[] = "dtc [options] <input file>";
52103285Sikobstatic const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
53113584Ssimokawastatic struct option const usage_long_opts[] = {
54103285Sikob	{"quiet",            no_argument, NULL, 'q'},
55103285Sikob	{"in-format",         a_argument, NULL, 'I'},
56103285Sikob	{"out",               a_argument, NULL, 'o'},
57127468Ssimokawa	{"out-format",        a_argument, NULL, 'O'},
58117067Ssimokawa	{"out-version",       a_argument, NULL, 'V'},
59117067Ssimokawa	{"out-dependency",    a_argument, NULL, 'd'},
60117067Ssimokawa	{"reserve",           a_argument, NULL, 'R'},
61127468Ssimokawa	{"space",             a_argument, NULL, 'S'},
62127468Ssimokawa	{"pad",               a_argument, NULL, 'p'},
63127468Ssimokawa	{"boot-cpu",          a_argument, NULL, 'b'},
64127468Ssimokawa	{"force",            no_argument, NULL, 'f'},
65127468Ssimokawa	{"include",           a_argument, NULL, 'i'},
66127468Ssimokawa	{"sort",             no_argument, NULL, 's'},
67127468Ssimokawa	{"phandle",           a_argument, NULL, 'H'},
68127468Ssimokawa	{"warning",           a_argument, NULL, 'W'},
69103285Sikob	{"error",             a_argument, NULL, 'E'},
70103285Sikob	{"help",             no_argument, NULL, 'h'},
71113584Ssimokawa	{"version",          no_argument, NULL, 'v'},
72103285Sikob	{NULL,               no_argument, NULL, 0x0},
73103285Sikob};
74103285Sikobstatic const char * const usage_opts_help[] = {
75127468Ssimokawa	"\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
76103285Sikob	"\n\tInput formats are:\n"
77103285Sikob	 "\t\tdts - device tree source text\n"
78106802Ssimokawa	 "\t\tdtb - device tree blob\n"
79103285Sikob	 "\t\tfs  - /proc/device-tree style directory",
80103285Sikob	"\n\tOutput file",
81113584Ssimokawa	"\n\tOutput formats are:\n"
82103285Sikob	 "\t\tdts - device tree source text\n"
83103285Sikob	 "\t\tdtb - device tree blob\n"
84113584Ssimokawa	 "\t\tasm - assembler source",
85103285Sikob	"\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION);
86103285Sikob	"\n\tOutput dependency file",
87103285Sikob	"\n\ttMake space for <number> reserve map entries (for dtb and asm output)",
88103285Sikob	"\n\tMake the blob at least <bytes> long (extra space)",
89103285Sikob	"\n\tAdd padding to the blob of <bytes> long (extra space)",
90103285Sikob	"\n\tSet the physical boot cpu",
91103285Sikob	"\n\tTry to produce output even if the input tree has errors",
92103285Sikob	"\n\tAdd a path to search for include files",
93103285Sikob	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
94113584Ssimokawa	"\n\tValid phandle formats are:\n"
95116376Ssimokawa	 "\t\tlegacy - \"linux,phandle\" properties only\n"
96124378Ssimokawa	 "\t\tepapr  - \"phandle\" properties only\n"
97129585Sdfr	 "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
98103285Sikob	"\n\tEnable/disable warnings (prefix with \"no-\")",
99103285Sikob	"\n\tEnable/disable errors (prefix with \"no-\")",
100103285Sikob	"\n\tPrint this help and exit",
101103285Sikob	"\n\tPrint version and exit",
102103285Sikob	NULL,
103103285Sikob};
104103285Sikob
105103285Sikobint main(int argc, char *argv[])
106103285Sikob{
107103285Sikob	struct boot_info *bi;
108103285Sikob	const char *inform = "dts";
109103285Sikob	const char *outform = "dts";
110103285Sikob	const char *outname = "-";
111103285Sikob	const char *depname = NULL;
112103285Sikob	bool force = false, sort = false;
113103285Sikob	const char *arg;
114103285Sikob	int opt;
115103285Sikob	FILE *outf = NULL;
116103285Sikob	int outversion = DEFAULT_FDT_VERSION;
117103285Sikob	long long cmdline_boot_cpuid = -1;
118103285Sikob
119103285Sikob	quiet      = 0;
120103285Sikob	reservenum = 0;
121103285Sikob	minsize    = 0;
122103285Sikob	padsize    = 0;
123103285Sikob
124103285Sikob	while ((opt = util_getopt_long()) != EOF) {
125124169Ssimokawa		switch (opt) {
126124169Ssimokawa		case 'I':
127124169Ssimokawa			inform = optarg;
128124169Ssimokawa			break;
129124169Ssimokawa		case 'O':
130124169Ssimokawa			outform = optarg;
131124169Ssimokawa			break;
132124169Ssimokawa		case 'o':
133129585Sdfr			outname = optarg;
134129585Sdfr			break;
135124169Ssimokawa		case 'V':
136124169Ssimokawa			outversion = strtol(optarg, NULL, 0);
137124169Ssimokawa			break;
138124169Ssimokawa		case 'd':
139113584Ssimokawa			depname = optarg;
140129585Sdfr			break;
141113584Ssimokawa		case 'R':
142124169Ssimokawa			reservenum = strtol(optarg, NULL, 0);
143124169Ssimokawa			break;
144124169Ssimokawa		case 'S':
145124169Ssimokawa			minsize = strtol(optarg, NULL, 0);
146113584Ssimokawa			break;
147124169Ssimokawa		case 'p':
148124169Ssimokawa			padsize = strtol(optarg, NULL, 0);
149129585Sdfr			break;
150129585Sdfr		case 'f':
151129585Sdfr			force = true;
152129585Sdfr			break;
153124169Ssimokawa		case 'q':
154124169Ssimokawa			quiet++;
155124169Ssimokawa			break;
156113584Ssimokawa		case 'b':
157113584Ssimokawa			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
158113584Ssimokawa			break;
159103285Sikob		case 'i':
160103285Sikob			srcfile_add_search_path(optarg);
161103285Sikob			break;
162103285Sikob		case 'v':
163103285Sikob			util_version();
164103285Sikob		case 'H':
165103285Sikob			if (streq(optarg, "legacy"))
166103285Sikob				phandle_format = PHANDLE_LEGACY;
167103285Sikob			else if (streq(optarg, "epapr"))
168112523Ssimokawa				phandle_format = PHANDLE_EPAPR;
169103285Sikob			else if (streq(optarg, "both"))
170103285Sikob				phandle_format = PHANDLE_BOTH;
171103285Sikob			else
172103285Sikob				die("Invalid argument \"%s\" to -H option\n",
173103285Sikob				    optarg);
174103285Sikob			break;
175103285Sikob
176103285Sikob		case 's':
177103285Sikob			sort = true;
178103285Sikob			break;
179103285Sikob
180103285Sikob		case 'W':
181103285Sikob			parse_checks_option(true, false, optarg);
182103285Sikob			break;
183103285Sikob
184103285Sikob		case 'E':
185103285Sikob			parse_checks_option(false, true, optarg);
186103285Sikob			break;
187103285Sikob
188103285Sikob		case 'h':
189103285Sikob			usage(NULL);
190103285Sikob		default:
191103285Sikob			usage("unknown option");
192103285Sikob		}
193103285Sikob	}
194103285Sikob
195103285Sikob	if (argc > (optind+1))
196103285Sikob		usage("missing files");
197113584Ssimokawa	else if (argc < (optind+1))
198103285Sikob		arg = "-";
199103285Sikob	else
200103285Sikob		arg = argv[optind];
201103285Sikob
202103285Sikob	/* minsize and padsize are mutually exclusive */
203103285Sikob	if (minsize && padsize)
204103285Sikob		die("Can't set both -p and -S\n");
205103285Sikob
206103285Sikob	if (depname) {
207103285Sikob		depfile = fopen(depname, "w");
208103285Sikob		if (!depfile)
209103285Sikob			die("Couldn't open dependency file %s: %s\n", depname,
210103285Sikob			    strerror(errno));
211103285Sikob		fprintf(depfile, "%s:", outname);
212103285Sikob	}
213103285Sikob
214103285Sikob	if (streq(inform, "dts"))
215103285Sikob		bi = dt_from_source(arg);
216103285Sikob	else if (streq(inform, "fs"))
217103285Sikob		bi = dt_from_fs(arg);
218103285Sikob	else if(streq(inform, "dtb"))
219103285Sikob		bi = dt_from_blob(arg);
220103285Sikob	else
221103285Sikob		die("Unknown input format \"%s\"\n", inform);
222103285Sikob
223103285Sikob	if (depfile) {
224103285Sikob		fputc('\n', depfile);
225103285Sikob		fclose(depfile);
226103285Sikob	}
227103285Sikob
228103285Sikob	if (cmdline_boot_cpuid != -1)
229103285Sikob		bi->boot_cpuid_phys = cmdline_boot_cpuid;
230103285Sikob
231103285Sikob	fill_fullpaths(bi->dt, "");
232103285Sikob	process_checks(force, bi);
233103285Sikob
234103285Sikob	if (sort)
235103285Sikob		sort_tree(bi);
236103285Sikob
237103285Sikob	if (streq(outname, "-")) {
238103285Sikob		outf = stdout;
239103285Sikob	} else {
240103285Sikob		outf = fopen(outname, "w");
241103285Sikob		if (! outf)
242103285Sikob			die("Couldn't open output file %s: %s\n",
243103285Sikob			    outname, strerror(errno));
244103285Sikob	}
245103285Sikob
246103285Sikob	if (streq(outform, "dts")) {
247103285Sikob		dt_to_source(outf, bi);
248103285Sikob	} else if (streq(outform, "dtb")) {
249103285Sikob		dt_to_blob(outf, bi, outversion);
250103285Sikob	} else if (streq(outform, "asm")) {
251103285Sikob		dt_to_asm(outf, bi, outversion);
252103285Sikob	} else if (streq(outform, "null")) {
253103285Sikob		/* do nothing */
254103285Sikob	} else {
255103285Sikob		die("Unknown output format \"%s\"\n", outform);
256103285Sikob	}
257103285Sikob
258103285Sikob	exit(0);
259103285Sikob}
260103285Sikob