dtc.c revision 1.1.1.2 1 1.1.1.2 skrll /* $NetBSD: dtc.c,v 1.1.1.2 2017/06/08 15:59:15 skrll Exp $ */
2 1.1.1.2 skrll
3 1.1 macallan /*
4 1.1 macallan * (C) Copyright David Gibson <dwg (at) au1.ibm.com>, IBM Corporation. 2005.
5 1.1 macallan *
6 1.1 macallan *
7 1.1 macallan * This program is free software; you can redistribute it and/or
8 1.1 macallan * modify it under the terms of the GNU General Public License as
9 1.1 macallan * published by the Free Software Foundation; either version 2 of the
10 1.1 macallan * License, or (at your option) any later version.
11 1.1 macallan *
12 1.1 macallan * This program is distributed in the hope that it will be useful,
13 1.1 macallan * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 macallan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 1.1 macallan * General Public License for more details.
16 1.1 macallan *
17 1.1 macallan * You should have received a copy of the GNU General Public License
18 1.1 macallan * along with this program; if not, write to the Free Software
19 1.1 macallan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 1.1 macallan * USA
21 1.1 macallan */
22 1.1 macallan
23 1.1 macallan #include <sys/stat.h>
24 1.1 macallan
25 1.1 macallan #include "dtc.h"
26 1.1 macallan #include "srcpos.h"
27 1.1 macallan
28 1.1 macallan /*
29 1.1 macallan * Command line options
30 1.1 macallan */
31 1.1 macallan int quiet; /* Level of quietness */
32 1.1 macallan int reservenum; /* Number of memory reservation slots */
33 1.1 macallan int minsize; /* Minimum blob size */
34 1.1 macallan int padsize; /* Additional padding to blob */
35 1.1.1.2 skrll int alignsize; /* Additional padding to blob accroding to the alignsize */
36 1.1 macallan int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
37 1.1.1.2 skrll int generate_symbols; /* enable symbols & fixup support */
38 1.1.1.2 skrll int generate_fixups; /* suppress generation of fixups on symbol support */
39 1.1.1.2 skrll int auto_label_aliases; /* auto generate labels -> aliases */
40 1.1.1.2 skrll
41 1.1.1.2 skrll static int is_power_of_2(int x)
42 1.1.1.2 skrll {
43 1.1.1.2 skrll return (x > 0) && ((x & (x - 1)) == 0);
44 1.1.1.2 skrll }
45 1.1 macallan
46 1.1 macallan static void fill_fullpaths(struct node *tree, const char *prefix)
47 1.1 macallan {
48 1.1 macallan struct node *child;
49 1.1 macallan const char *unit;
50 1.1 macallan
51 1.1 macallan tree->fullpath = join_path(prefix, tree->name);
52 1.1 macallan
53 1.1 macallan unit = strchr(tree->name, '@');
54 1.1 macallan if (unit)
55 1.1 macallan tree->basenamelen = unit - tree->name;
56 1.1 macallan else
57 1.1 macallan tree->basenamelen = strlen(tree->name);
58 1.1 macallan
59 1.1 macallan for_each_child(tree, child)
60 1.1 macallan fill_fullpaths(child, tree->fullpath);
61 1.1 macallan }
62 1.1 macallan
63 1.1 macallan /* Usage related data. */
64 1.1 macallan #define FDT_VERSION(version) _FDT_VERSION(version)
65 1.1 macallan #define _FDT_VERSION(version) #version
66 1.1 macallan static const char usage_synopsis[] = "dtc [options] <input file>";
67 1.1.1.2 skrll static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
68 1.1 macallan static struct option const usage_long_opts[] = {
69 1.1 macallan {"quiet", no_argument, NULL, 'q'},
70 1.1 macallan {"in-format", a_argument, NULL, 'I'},
71 1.1 macallan {"out", a_argument, NULL, 'o'},
72 1.1 macallan {"out-format", a_argument, NULL, 'O'},
73 1.1 macallan {"out-version", a_argument, NULL, 'V'},
74 1.1 macallan {"out-dependency", a_argument, NULL, 'd'},
75 1.1 macallan {"reserve", a_argument, NULL, 'R'},
76 1.1 macallan {"space", a_argument, NULL, 'S'},
77 1.1 macallan {"pad", a_argument, NULL, 'p'},
78 1.1.1.2 skrll {"align", a_argument, NULL, 'a'},
79 1.1 macallan {"boot-cpu", a_argument, NULL, 'b'},
80 1.1 macallan {"force", no_argument, NULL, 'f'},
81 1.1 macallan {"include", a_argument, NULL, 'i'},
82 1.1 macallan {"sort", no_argument, NULL, 's'},
83 1.1 macallan {"phandle", a_argument, NULL, 'H'},
84 1.1 macallan {"warning", a_argument, NULL, 'W'},
85 1.1 macallan {"error", a_argument, NULL, 'E'},
86 1.1.1.2 skrll {"symbols", no_argument, NULL, '@'},
87 1.1.1.2 skrll {"auto-alias", no_argument, NULL, 'A'},
88 1.1 macallan {"help", no_argument, NULL, 'h'},
89 1.1 macallan {"version", no_argument, NULL, 'v'},
90 1.1 macallan {NULL, no_argument, NULL, 0x0},
91 1.1 macallan };
92 1.1 macallan static const char * const usage_opts_help[] = {
93 1.1 macallan "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
94 1.1 macallan "\n\tInput formats are:\n"
95 1.1 macallan "\t\tdts - device tree source text\n"
96 1.1 macallan "\t\tdtb - device tree blob\n"
97 1.1 macallan "\t\tfs - /proc/device-tree style directory",
98 1.1 macallan "\n\tOutput file",
99 1.1 macallan "\n\tOutput formats are:\n"
100 1.1 macallan "\t\tdts - device tree source text\n"
101 1.1 macallan "\t\tdtb - device tree blob\n"
102 1.1 macallan "\t\tasm - assembler source",
103 1.1 macallan "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
104 1.1 macallan "\n\tOutput dependency file",
105 1.1 macallan "\n\tMake space for <number> reserve map entries (for dtb and asm output)",
106 1.1 macallan "\n\tMake the blob at least <bytes> long (extra space)",
107 1.1 macallan "\n\tAdd padding to the blob of <bytes> long (extra space)",
108 1.1.1.2 skrll "\n\tMake the blob align to the <bytes> (extra space)",
109 1.1 macallan "\n\tSet the physical boot cpu",
110 1.1 macallan "\n\tTry to produce output even if the input tree has errors",
111 1.1 macallan "\n\tAdd a path to search for include files",
112 1.1 macallan "\n\tSort nodes and properties before outputting (useful for comparing trees)",
113 1.1 macallan "\n\tValid phandle formats are:\n"
114 1.1 macallan "\t\tlegacy - \"linux,phandle\" properties only\n"
115 1.1 macallan "\t\tepapr - \"phandle\" properties only\n"
116 1.1 macallan "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
117 1.1 macallan "\n\tEnable/disable warnings (prefix with \"no-\")",
118 1.1 macallan "\n\tEnable/disable errors (prefix with \"no-\")",
119 1.1.1.2 skrll "\n\tEnable generation of symbols",
120 1.1.1.2 skrll "\n\tEnable auto-alias of labels",
121 1.1 macallan "\n\tPrint this help and exit",
122 1.1 macallan "\n\tPrint version and exit",
123 1.1 macallan NULL,
124 1.1 macallan };
125 1.1 macallan
126 1.1 macallan static const char *guess_type_by_name(const char *fname, const char *fallback)
127 1.1 macallan {
128 1.1 macallan const char *s;
129 1.1 macallan
130 1.1 macallan s = strrchr(fname, '.');
131 1.1 macallan if (s == NULL)
132 1.1 macallan return fallback;
133 1.1 macallan if (!strcasecmp(s, ".dts"))
134 1.1 macallan return "dts";
135 1.1 macallan if (!strcasecmp(s, ".dtb"))
136 1.1 macallan return "dtb";
137 1.1 macallan return fallback;
138 1.1 macallan }
139 1.1 macallan
140 1.1 macallan static const char *guess_input_format(const char *fname, const char *fallback)
141 1.1 macallan {
142 1.1 macallan struct stat statbuf;
143 1.1.1.2 skrll fdt32_t magic;
144 1.1 macallan FILE *f;
145 1.1 macallan
146 1.1 macallan if (stat(fname, &statbuf) != 0)
147 1.1 macallan return fallback;
148 1.1 macallan
149 1.1 macallan if (S_ISDIR(statbuf.st_mode))
150 1.1 macallan return "fs";
151 1.1 macallan
152 1.1 macallan if (!S_ISREG(statbuf.st_mode))
153 1.1 macallan return fallback;
154 1.1 macallan
155 1.1 macallan f = fopen(fname, "r");
156 1.1 macallan if (f == NULL)
157 1.1 macallan return fallback;
158 1.1 macallan if (fread(&magic, 4, 1, f) != 1) {
159 1.1 macallan fclose(f);
160 1.1 macallan return fallback;
161 1.1 macallan }
162 1.1 macallan fclose(f);
163 1.1 macallan
164 1.1.1.2 skrll if (fdt32_to_cpu(magic) == FDT_MAGIC)
165 1.1 macallan return "dtb";
166 1.1 macallan
167 1.1 macallan return guess_type_by_name(fname, fallback);
168 1.1 macallan }
169 1.1 macallan
170 1.1 macallan int main(int argc, char *argv[])
171 1.1 macallan {
172 1.1.1.2 skrll struct dt_info *dti;
173 1.1 macallan const char *inform = NULL;
174 1.1 macallan const char *outform = NULL;
175 1.1 macallan const char *outname = "-";
176 1.1 macallan const char *depname = NULL;
177 1.1 macallan bool force = false, sort = false;
178 1.1 macallan const char *arg;
179 1.1 macallan int opt;
180 1.1 macallan FILE *outf = NULL;
181 1.1 macallan int outversion = DEFAULT_FDT_VERSION;
182 1.1 macallan long long cmdline_boot_cpuid = -1;
183 1.1 macallan
184 1.1 macallan quiet = 0;
185 1.1 macallan reservenum = 0;
186 1.1 macallan minsize = 0;
187 1.1 macallan padsize = 0;
188 1.1.1.2 skrll alignsize = 0;
189 1.1 macallan
190 1.1 macallan while ((opt = util_getopt_long()) != EOF) {
191 1.1 macallan switch (opt) {
192 1.1 macallan case 'I':
193 1.1 macallan inform = optarg;
194 1.1 macallan break;
195 1.1 macallan case 'O':
196 1.1 macallan outform = optarg;
197 1.1 macallan break;
198 1.1 macallan case 'o':
199 1.1 macallan outname = optarg;
200 1.1 macallan break;
201 1.1 macallan case 'V':
202 1.1 macallan outversion = strtol(optarg, NULL, 0);
203 1.1 macallan break;
204 1.1 macallan case 'd':
205 1.1 macallan depname = optarg;
206 1.1 macallan break;
207 1.1 macallan case 'R':
208 1.1 macallan reservenum = strtol(optarg, NULL, 0);
209 1.1 macallan break;
210 1.1 macallan case 'S':
211 1.1 macallan minsize = strtol(optarg, NULL, 0);
212 1.1 macallan break;
213 1.1 macallan case 'p':
214 1.1 macallan padsize = strtol(optarg, NULL, 0);
215 1.1 macallan break;
216 1.1.1.2 skrll case 'a':
217 1.1.1.2 skrll alignsize = strtol(optarg, NULL, 0);
218 1.1.1.2 skrll if (!is_power_of_2(alignsize))
219 1.1.1.2 skrll die("Invalid argument \"%d\" to -a option\n",
220 1.1.1.2 skrll alignsize);
221 1.1.1.2 skrll break;
222 1.1 macallan case 'f':
223 1.1 macallan force = true;
224 1.1 macallan break;
225 1.1 macallan case 'q':
226 1.1 macallan quiet++;
227 1.1 macallan break;
228 1.1 macallan case 'b':
229 1.1 macallan cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
230 1.1 macallan break;
231 1.1 macallan case 'i':
232 1.1 macallan srcfile_add_search_path(optarg);
233 1.1 macallan break;
234 1.1 macallan case 'v':
235 1.1 macallan util_version();
236 1.1 macallan case 'H':
237 1.1 macallan if (streq(optarg, "legacy"))
238 1.1 macallan phandle_format = PHANDLE_LEGACY;
239 1.1 macallan else if (streq(optarg, "epapr"))
240 1.1 macallan phandle_format = PHANDLE_EPAPR;
241 1.1 macallan else if (streq(optarg, "both"))
242 1.1 macallan phandle_format = PHANDLE_BOTH;
243 1.1 macallan else
244 1.1 macallan die("Invalid argument \"%s\" to -H option\n",
245 1.1 macallan optarg);
246 1.1 macallan break;
247 1.1 macallan
248 1.1 macallan case 's':
249 1.1 macallan sort = true;
250 1.1 macallan break;
251 1.1 macallan
252 1.1 macallan case 'W':
253 1.1 macallan parse_checks_option(true, false, optarg);
254 1.1 macallan break;
255 1.1 macallan
256 1.1 macallan case 'E':
257 1.1 macallan parse_checks_option(false, true, optarg);
258 1.1 macallan break;
259 1.1 macallan
260 1.1.1.2 skrll case '@':
261 1.1.1.2 skrll generate_symbols = 1;
262 1.1.1.2 skrll break;
263 1.1.1.2 skrll case 'A':
264 1.1.1.2 skrll auto_label_aliases = 1;
265 1.1.1.2 skrll break;
266 1.1.1.2 skrll
267 1.1 macallan case 'h':
268 1.1 macallan usage(NULL);
269 1.1 macallan default:
270 1.1 macallan usage("unknown option");
271 1.1 macallan }
272 1.1 macallan }
273 1.1 macallan
274 1.1 macallan if (argc > (optind+1))
275 1.1 macallan usage("missing files");
276 1.1 macallan else if (argc < (optind+1))
277 1.1 macallan arg = "-";
278 1.1 macallan else
279 1.1 macallan arg = argv[optind];
280 1.1 macallan
281 1.1 macallan /* minsize and padsize are mutually exclusive */
282 1.1 macallan if (minsize && padsize)
283 1.1 macallan die("Can't set both -p and -S\n");
284 1.1 macallan
285 1.1 macallan if (depname) {
286 1.1 macallan depfile = fopen(depname, "w");
287 1.1 macallan if (!depfile)
288 1.1 macallan die("Couldn't open dependency file %s: %s\n", depname,
289 1.1 macallan strerror(errno));
290 1.1 macallan fprintf(depfile, "%s:", outname);
291 1.1 macallan }
292 1.1 macallan
293 1.1 macallan if (inform == NULL)
294 1.1 macallan inform = guess_input_format(arg, "dts");
295 1.1 macallan if (outform == NULL) {
296 1.1 macallan outform = guess_type_by_name(outname, NULL);
297 1.1 macallan if (outform == NULL) {
298 1.1 macallan if (streq(inform, "dts"))
299 1.1 macallan outform = "dtb";
300 1.1 macallan else
301 1.1 macallan outform = "dts";
302 1.1 macallan }
303 1.1 macallan }
304 1.1 macallan if (streq(inform, "dts"))
305 1.1.1.2 skrll dti = dt_from_source(arg);
306 1.1 macallan else if (streq(inform, "fs"))
307 1.1.1.2 skrll dti = dt_from_fs(arg);
308 1.1 macallan else if(streq(inform, "dtb"))
309 1.1.1.2 skrll dti = dt_from_blob(arg);
310 1.1 macallan else
311 1.1 macallan die("Unknown input format \"%s\"\n", inform);
312 1.1 macallan
313 1.1.1.2 skrll dti->outname = outname;
314 1.1.1.2 skrll
315 1.1 macallan if (depfile) {
316 1.1 macallan fputc('\n', depfile);
317 1.1 macallan fclose(depfile);
318 1.1 macallan }
319 1.1 macallan
320 1.1 macallan if (cmdline_boot_cpuid != -1)
321 1.1.1.2 skrll dti->boot_cpuid_phys = cmdline_boot_cpuid;
322 1.1.1.2 skrll
323 1.1.1.2 skrll fill_fullpaths(dti->dt, "");
324 1.1.1.2 skrll process_checks(force, dti);
325 1.1.1.2 skrll
326 1.1.1.2 skrll /* on a plugin, generate by default */
327 1.1.1.2 skrll if (dti->dtsflags & DTSF_PLUGIN) {
328 1.1.1.2 skrll generate_fixups = 1;
329 1.1.1.2 skrll }
330 1.1 macallan
331 1.1.1.2 skrll if (auto_label_aliases)
332 1.1.1.2 skrll generate_label_tree(dti, "aliases", false);
333 1.1.1.2 skrll
334 1.1.1.2 skrll if (generate_symbols)
335 1.1.1.2 skrll generate_label_tree(dti, "__symbols__", true);
336 1.1.1.2 skrll
337 1.1.1.2 skrll if (generate_fixups) {
338 1.1.1.2 skrll generate_fixups_tree(dti, "__fixups__");
339 1.1.1.2 skrll generate_local_fixups_tree(dti, "__local_fixups__");
340 1.1.1.2 skrll }
341 1.1 macallan
342 1.1 macallan if (sort)
343 1.1.1.2 skrll sort_tree(dti);
344 1.1 macallan
345 1.1 macallan if (streq(outname, "-")) {
346 1.1 macallan outf = stdout;
347 1.1 macallan } else {
348 1.1 macallan outf = fopen(outname, "wb");
349 1.1 macallan if (! outf)
350 1.1 macallan die("Couldn't open output file %s: %s\n",
351 1.1 macallan outname, strerror(errno));
352 1.1 macallan }
353 1.1 macallan
354 1.1 macallan if (streq(outform, "dts")) {
355 1.1.1.2 skrll dt_to_source(outf, dti);
356 1.1 macallan } else if (streq(outform, "dtb")) {
357 1.1.1.2 skrll dt_to_blob(outf, dti, outversion);
358 1.1 macallan } else if (streq(outform, "asm")) {
359 1.1.1.2 skrll dt_to_asm(outf, dti, outversion);
360 1.1 macallan } else if (streq(outform, "null")) {
361 1.1 macallan /* do nothing */
362 1.1 macallan } else {
363 1.1 macallan die("Unknown output format \"%s\"\n", outform);
364 1.1 macallan }
365 1.1 macallan
366 1.1 macallan exit(0);
367 1.1 macallan }
368