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