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