1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "dtc.h"
22
23char *join_path(char *path, char *name)
24{
25 int lenp = strlen(path);
26 int lenn = strlen(name);
27 int len;
28 int needslash = 1;
29 char *str;
30
31 len = lenp + lenn + 2;
32 if ((lenp > 0) && (path[lenp-1] == '/')) {
33 needslash = 0;
34 len--;
35 }
36
37 str = xmalloc(len);
38 memcpy(str, path, lenp);
39 if (needslash) {
40 str[lenp] = '/';
41 lenp++;
42 }
43 memcpy(str+lenp, name, lenn+1);
44 return str;
45}
46
47void fill_fullpaths(struct node *tree, char *prefix)
48{
49 struct node *child;
50 char *unit;
51
52 tree->fullpath = join_path(prefix, tree->name);
53
54 unit = strchr(tree->name, '@');
55 if (unit)
56 tree->basenamelen = unit - tree->name;
57 else
58 tree->basenamelen = strlen(tree->name);
59
60 for_each_child(tree, child)
61 fill_fullpaths(child, tree->fullpath);
62}
63
64
65
66
67
68FILE *fopenfile(char *fname)
69{
70 FILE *f = NULL;
71
72 if (streq(fname, "-")){
73 f = stdin;
74 } else {
75 struct stat buf;
76 if (stat(fname, &buf) < 0) {
77 errno = EISDIR;
78 goto no;
79 }
80
81 if (! S_ISREG(buf.st_mode)){
82 errno = EISDIR;
83 goto no;
84 }
85
86 f = fopen(fname, "r");
87 }
88
89no:
90
91 return f;
92}
93
94FILE *dtc_open_file(char *fname)
95{
96 FILE *f = fopenfile(fname);
97
98 if (! f)
99 die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
100
101 return f;
102}
103
104
105static void usage(void)
106{
107 fprintf(stderr, "Usage:\n");
108 fprintf(stderr, "\tdtc [options] <input file>\n");
109 fprintf(stderr, "\nOptions:\n");
110 fprintf(stderr, "\t-I <input format>\n");
111 fprintf(stderr, "\t\tInput formats are:\n");
112 fprintf(stderr, "\t\t\tdts - device tree source text\n");
113 fprintf(stderr, "\t\t\tdtb - device tree blob\n");
114 fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
115 fprintf(stderr, "\t-O <output format>\n");
116 fprintf(stderr, "\t\tOutput formats are:\n");
117 fprintf(stderr, "\t\t\tdts - device tree source text\n");
118 fprintf(stderr, "\t\t\tdtb - device tree blob\n");
119 fprintf(stderr, "\t\t\tasm - assembler source\n");
120 fprintf(stderr, "\t\t\tcoreboot (or just lb) - coreboot source\n");
121 fprintf(stderr, "\t-V <output version>\n");
122 fprintf(stderr, "\t\tBlob version to produce, defaults to 3 (relevant for dtb\n\t\tand asm output only)\n");
123 fprintf(stderr, "\t-R <number>\n");
124 fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
125 fprintf(stderr, "\t-b <number>\n");
126 fprintf(stderr, "\t\tSet the physical boot cpu\n");
127 fprintf(stderr, "\t-f\n");
128 fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
129 exit(2);
130}
131
132int main(int argc, char *argv[])
133{
134 struct boot_info *bi=NULL;
135 char *inform = "dts";
136 char *outform = "dts";
137 char *outname = "-";
138 int force = 0;
139 char *arg=NULL;
140 int opt;
141 FILE *inf = NULL;
142 FILE *outf = NULL;
143 int outversion = 3;
144 int reservenum = 1;
145 int boot_cpuid_phys = 0xfeedbeef;
146
147 while ((opt = getopt(argc, argv, "I:O:o:V:R:fb:")) != EOF) {
148 switch (opt) {
149 case 'I':
150 inform = optarg;
151 break;
152 case 'O':
153 outform = optarg;
154 break;
155 case 'o':
156 outname = optarg;
157 break;
158 case 'V':
159 outversion = strtol(optarg, NULL, 0);
160 break;
161 case 'R':
162 reservenum = strtol(optarg, NULL, 0);
163 break;
164 case 'f':
165 force = 1;
166 break;
167 case 'b':
168 boot_cpuid_phys = strtol(optarg, NULL, 0);
169 break;
170 default:
171 usage();
172 }
173 }
174
175 if (argc > (optind+1))
176 usage();
177 else if (argc < (optind+1))
178 arg = "-";
179 else
180 arg = argv[optind];
181
182
183
184 fprintf(stderr, " DTC %s (%s->%s)\n",
185 arg, inform, outform);
186
187 if (streq(inform, "dts")) {
188 inf = dtc_open_file(arg);
189 bi = dt_from_source(inf);
190 } else if (streq(inform, "fs")) {
191 bi = dt_from_fs(arg);
192 } else if(streq(inform, "dtb")) {
193 inf = dtc_open_file(arg);
194 bi = dt_from_blob(inf);
195 } else {
196 die("Unknown input format \"%s\"\n", inform);
197 }
198
199 if (inf && (inf != stdin))
200 fclose(inf);
201
202 if (! bi || ! bi->dt)
203 die("Couldn't read input tree\n");
204
205 if (! check_device_tree(bi->dt, outversion, boot_cpuid_phys)) {
206 fprintf(stderr, "Input tree has errors\n");
207 if (! force)
208 exit(1);
209 }
210
211 if (streq(outname, "-")) {
212 outf = stdout;
213 } else {
214 outf = fopen(outname, "w");
215 if (! outf)
216 die("Couldn't open output file %s: %s\n",
217 outname, strerror(errno));
218 }
219
220 if (streq(outform, "dts")) {
221 dt_to_source(outf, bi);
222 } else if (streq(outform, "dtb")) {
223 dt_to_blob(outf, bi, outversion, boot_cpuid_phys);
224 } else if (streq(outform, "asm")) {
225 dt_to_asm(outf, bi, outversion, boot_cpuid_phys);
226 } else if (streq(outform, "C")) {
227 dt_to_C(outf, bi, outversion, boot_cpuid_phys);
228 } else if (streq(outform, "coreboot") || streq(outform, "lb")) {
229 dt_to_coreboot(outf, bi, outversion, boot_cpuid_phys);
230 } else if (streq(outform, "corebootinclude") || streq(outform, "lbh")) {
231 dt_to_corebooth(outf, bi, outversion, boot_cpuid_phys);
232 } else if (streq(outform, "null")) {
233
234 } else {
235 die("Unknown output format \"%s\"\n", outform);
236 }
237
238 exit(0);
239}
240