11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29fffb55fSDavid Gibson /* 39fffb55fSDavid Gibson * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. 49fffb55fSDavid Gibson */ 59fffb55fSDavid Gibson 691feabc2SRob Herring #include <sys/stat.h> 791feabc2SRob Herring 89fffb55fSDavid Gibson #include "dtc.h" 99fffb55fSDavid Gibson #include "srcpos.h" 109fffb55fSDavid Gibson 119fffb55fSDavid Gibson /* 129fffb55fSDavid Gibson * Command line options 139fffb55fSDavid Gibson */ 149fffb55fSDavid Gibson int quiet; /* Level of quietness */ 159fffb55fSDavid Gibson int reservenum; /* Number of memory reservation slots */ 169fffb55fSDavid Gibson int minsize; /* Minimum blob size */ 179fffb55fSDavid Gibson int padsize; /* Additional padding to blob */ 186f05afcbSRob Herring int alignsize; /* Additional padding to blob accroding to the alignsize */ 194201d057SRob Herring int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */ 206f05afcbSRob Herring int generate_symbols; /* enable symbols & fixup support */ 216f05afcbSRob Herring int generate_fixups; /* suppress generation of fixups on symbol support */ 226f05afcbSRob Herring int auto_label_aliases; /* auto generate labels -> aliases */ 23c2e7075cSRob Herring int annotate; /* Level of annotation: 1 for input source location 24c2e7075cSRob Herring >1 for full input source location. */ 256f05afcbSRob Herring 266f05afcbSRob Herring static int is_power_of_2(int x) 276f05afcbSRob Herring { 286f05afcbSRob Herring return (x > 0) && ((x & (x - 1)) == 0); 296f05afcbSRob Herring } 309fffb55fSDavid Gibson 319fffb55fSDavid Gibson static void fill_fullpaths(struct node *tree, const char *prefix) 329fffb55fSDavid Gibson { 339fffb55fSDavid Gibson struct node *child; 349fffb55fSDavid Gibson const char *unit; 359fffb55fSDavid Gibson 369fffb55fSDavid Gibson tree->fullpath = join_path(prefix, tree->name); 379fffb55fSDavid Gibson 389fffb55fSDavid Gibson unit = strchr(tree->name, '@'); 399fffb55fSDavid Gibson if (unit) 409fffb55fSDavid Gibson tree->basenamelen = unit - tree->name; 419fffb55fSDavid Gibson else 429fffb55fSDavid Gibson tree->basenamelen = strlen(tree->name); 439fffb55fSDavid Gibson 449fffb55fSDavid Gibson for_each_child(tree, child) 459fffb55fSDavid Gibson fill_fullpaths(child, tree->fullpath); 469fffb55fSDavid Gibson } 479fffb55fSDavid Gibson 4873ab39b1SGrant Likely /* Usage related data. */ 4973ab39b1SGrant Likely static const char usage_synopsis[] = "dtc [options] <input file>"; 50c2e7075cSRob Herring static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; 5173ab39b1SGrant Likely static struct option const usage_long_opts[] = { 5273ab39b1SGrant Likely {"quiet", no_argument, NULL, 'q'}, 5373ab39b1SGrant Likely {"in-format", a_argument, NULL, 'I'}, 5473ab39b1SGrant Likely {"out", a_argument, NULL, 'o'}, 5573ab39b1SGrant Likely {"out-format", a_argument, NULL, 'O'}, 5673ab39b1SGrant Likely {"out-version", a_argument, NULL, 'V'}, 5773ab39b1SGrant Likely {"out-dependency", a_argument, NULL, 'd'}, 5873ab39b1SGrant Likely {"reserve", a_argument, NULL, 'R'}, 5973ab39b1SGrant Likely {"space", a_argument, NULL, 'S'}, 6073ab39b1SGrant Likely {"pad", a_argument, NULL, 'p'}, 616f05afcbSRob Herring {"align", a_argument, NULL, 'a'}, 6273ab39b1SGrant Likely {"boot-cpu", a_argument, NULL, 'b'}, 6373ab39b1SGrant Likely {"force", no_argument, NULL, 'f'}, 6473ab39b1SGrant Likely {"include", a_argument, NULL, 'i'}, 6573ab39b1SGrant Likely {"sort", no_argument, NULL, 's'}, 6673ab39b1SGrant Likely {"phandle", a_argument, NULL, 'H'}, 6773ab39b1SGrant Likely {"warning", a_argument, NULL, 'W'}, 6873ab39b1SGrant Likely {"error", a_argument, NULL, 'E'}, 696f05afcbSRob Herring {"symbols", no_argument, NULL, '@'}, 706f05afcbSRob Herring {"auto-alias", no_argument, NULL, 'A'}, 71c2e7075cSRob Herring {"annotate", no_argument, NULL, 'T'}, 7273ab39b1SGrant Likely {"help", no_argument, NULL, 'h'}, 7373ab39b1SGrant Likely {"version", no_argument, NULL, 'v'}, 7473ab39b1SGrant Likely {NULL, no_argument, NULL, 0x0}, 7573ab39b1SGrant Likely }; 7673ab39b1SGrant Likely static const char * const usage_opts_help[] = { 7773ab39b1SGrant Likely "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", 7873ab39b1SGrant Likely "\n\tInput formats are:\n" 7973ab39b1SGrant Likely "\t\tdts - device tree source text\n" 8073ab39b1SGrant Likely "\t\tdtb - device tree blob\n" 8173ab39b1SGrant Likely "\t\tfs - /proc/device-tree style directory", 8273ab39b1SGrant Likely "\n\tOutput file", 8373ab39b1SGrant Likely "\n\tOutput formats are:\n" 8473ab39b1SGrant Likely "\t\tdts - device tree source text\n" 8573ab39b1SGrant Likely "\t\tdtb - device tree blob\n" 86f858927fSRob Herring #ifndef NO_YAML 87f858927fSRob Herring "\t\tyaml - device tree encoded as YAML\n" 88f858927fSRob Herring #endif 8973ab39b1SGrant Likely "\t\tasm - assembler source", 909130ba88SRob Herring "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", 9173ab39b1SGrant Likely "\n\tOutput dependency file", 9247605971SRob Herring "\n\tMake space for <number> reserve map entries (for dtb and asm output)", 9373ab39b1SGrant Likely "\n\tMake the blob at least <bytes> long (extra space)", 9473ab39b1SGrant Likely "\n\tAdd padding to the blob of <bytes> long (extra space)", 956f05afcbSRob Herring "\n\tMake the blob align to the <bytes> (extra space)", 9673ab39b1SGrant Likely "\n\tSet the physical boot cpu", 9773ab39b1SGrant Likely "\n\tTry to produce output even if the input tree has errors", 9873ab39b1SGrant Likely "\n\tAdd a path to search for include files", 9973ab39b1SGrant Likely "\n\tSort nodes and properties before outputting (useful for comparing trees)", 10073ab39b1SGrant Likely "\n\tValid phandle formats are:\n" 10173ab39b1SGrant Likely "\t\tlegacy - \"linux,phandle\" properties only\n" 10273ab39b1SGrant Likely "\t\tepapr - \"phandle\" properties only\n" 10373ab39b1SGrant Likely "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", 10473ab39b1SGrant Likely "\n\tEnable/disable warnings (prefix with \"no-\")", 10573ab39b1SGrant Likely "\n\tEnable/disable errors (prefix with \"no-\")", 1066f05afcbSRob Herring "\n\tEnable generation of symbols", 1076f05afcbSRob Herring "\n\tEnable auto-alias of labels", 108c2e7075cSRob Herring "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", 10973ab39b1SGrant Likely "\n\tPrint this help and exit", 11073ab39b1SGrant Likely "\n\tPrint version and exit", 11173ab39b1SGrant Likely NULL, 11273ab39b1SGrant Likely }; 1139fffb55fSDavid Gibson 11491feabc2SRob Herring static const char *guess_type_by_name(const char *fname, const char *fallback) 11591feabc2SRob Herring { 11691feabc2SRob Herring const char *s; 11791feabc2SRob Herring 11891feabc2SRob Herring s = strrchr(fname, '.'); 11991feabc2SRob Herring if (s == NULL) 12091feabc2SRob Herring return fallback; 12191feabc2SRob Herring if (!strcasecmp(s, ".dts")) 12291feabc2SRob Herring return "dts"; 123f858927fSRob Herring if (!strcasecmp(s, ".yaml")) 124f858927fSRob Herring return "yaml"; 12591feabc2SRob Herring if (!strcasecmp(s, ".dtb")) 12691feabc2SRob Herring return "dtb"; 12791feabc2SRob Herring return fallback; 12891feabc2SRob Herring } 12991feabc2SRob Herring 13091feabc2SRob Herring static const char *guess_input_format(const char *fname, const char *fallback) 13191feabc2SRob Herring { 13291feabc2SRob Herring struct stat statbuf; 13389d12310SRob Herring fdt32_t magic; 13491feabc2SRob Herring FILE *f; 13591feabc2SRob Herring 13691feabc2SRob Herring if (stat(fname, &statbuf) != 0) 13791feabc2SRob Herring return fallback; 13891feabc2SRob Herring 13991feabc2SRob Herring if (S_ISDIR(statbuf.st_mode)) 14091feabc2SRob Herring return "fs"; 14191feabc2SRob Herring 14291feabc2SRob Herring if (!S_ISREG(statbuf.st_mode)) 14391feabc2SRob Herring return fallback; 14491feabc2SRob Herring 14591feabc2SRob Herring f = fopen(fname, "r"); 14691feabc2SRob Herring if (f == NULL) 14791feabc2SRob Herring return fallback; 14891feabc2SRob Herring if (fread(&magic, 4, 1, f) != 1) { 14991feabc2SRob Herring fclose(f); 15091feabc2SRob Herring return fallback; 15191feabc2SRob Herring } 15291feabc2SRob Herring fclose(f); 15391feabc2SRob Herring 15489d12310SRob Herring if (fdt32_to_cpu(magic) == FDT_MAGIC) 15591feabc2SRob Herring return "dtb"; 15691feabc2SRob Herring 15791feabc2SRob Herring return guess_type_by_name(fname, fallback); 15891feabc2SRob Herring } 15991feabc2SRob Herring 1609fffb55fSDavid Gibson int main(int argc, char *argv[]) 1619fffb55fSDavid Gibson { 1626f05afcbSRob Herring struct dt_info *dti; 16391feabc2SRob Herring const char *inform = NULL; 16491feabc2SRob Herring const char *outform = NULL; 1659fffb55fSDavid Gibson const char *outname = "-"; 166136ec204SStephen Warren const char *depname = NULL; 16747605971SRob Herring bool force = false, sort = false; 1689fffb55fSDavid Gibson const char *arg; 1699fffb55fSDavid Gibson int opt; 1709fffb55fSDavid Gibson FILE *outf = NULL; 1719fffb55fSDavid Gibson int outversion = DEFAULT_FDT_VERSION; 1729fffb55fSDavid Gibson long long cmdline_boot_cpuid = -1; 1739fffb55fSDavid Gibson 1749fffb55fSDavid Gibson quiet = 0; 1759fffb55fSDavid Gibson reservenum = 0; 1769fffb55fSDavid Gibson minsize = 0; 1779fffb55fSDavid Gibson padsize = 0; 1786f05afcbSRob Herring alignsize = 0; 1799fffb55fSDavid Gibson 18073ab39b1SGrant Likely while ((opt = util_getopt_long()) != EOF) { 1819fffb55fSDavid Gibson switch (opt) { 1829fffb55fSDavid Gibson case 'I': 1839fffb55fSDavid Gibson inform = optarg; 1849fffb55fSDavid Gibson break; 1859fffb55fSDavid Gibson case 'O': 1869fffb55fSDavid Gibson outform = optarg; 1879fffb55fSDavid Gibson break; 1889fffb55fSDavid Gibson case 'o': 1899fffb55fSDavid Gibson outname = optarg; 1909fffb55fSDavid Gibson break; 1919fffb55fSDavid Gibson case 'V': 1929fffb55fSDavid Gibson outversion = strtol(optarg, NULL, 0); 1939fffb55fSDavid Gibson break; 194136ec204SStephen Warren case 'd': 195136ec204SStephen Warren depname = optarg; 196136ec204SStephen Warren break; 1979fffb55fSDavid Gibson case 'R': 1989fffb55fSDavid Gibson reservenum = strtol(optarg, NULL, 0); 1999fffb55fSDavid Gibson break; 2009fffb55fSDavid Gibson case 'S': 2019fffb55fSDavid Gibson minsize = strtol(optarg, NULL, 0); 2029fffb55fSDavid Gibson break; 2039fffb55fSDavid Gibson case 'p': 2049fffb55fSDavid Gibson padsize = strtol(optarg, NULL, 0); 2059fffb55fSDavid Gibson break; 2066f05afcbSRob Herring case 'a': 2076f05afcbSRob Herring alignsize = strtol(optarg, NULL, 0); 2086f05afcbSRob Herring if (!is_power_of_2(alignsize)) 2096f05afcbSRob Herring die("Invalid argument \"%d\" to -a option\n", 21089d12310SRob Herring alignsize); 2116f05afcbSRob Herring break; 2129fffb55fSDavid Gibson case 'f': 21347605971SRob Herring force = true; 2149fffb55fSDavid Gibson break; 2159fffb55fSDavid Gibson case 'q': 2169fffb55fSDavid Gibson quiet++; 2179fffb55fSDavid Gibson break; 2189fffb55fSDavid Gibson case 'b': 2199fffb55fSDavid Gibson cmdline_boot_cpuid = strtoll(optarg, NULL, 0); 2209fffb55fSDavid Gibson break; 221cd296721SStephen Warren case 'i': 222cd296721SStephen Warren srcfile_add_search_path(optarg); 223cd296721SStephen Warren break; 2249fffb55fSDavid Gibson case 'v': 22573ab39b1SGrant Likely util_version(); 226658f29a5SJohn Bonesio case 'H': 227658f29a5SJohn Bonesio if (streq(optarg, "legacy")) 228658f29a5SJohn Bonesio phandle_format = PHANDLE_LEGACY; 229658f29a5SJohn Bonesio else if (streq(optarg, "epapr")) 230658f29a5SJohn Bonesio phandle_format = PHANDLE_EPAPR; 231658f29a5SJohn Bonesio else if (streq(optarg, "both")) 232658f29a5SJohn Bonesio phandle_format = PHANDLE_BOTH; 233658f29a5SJohn Bonesio else 234658f29a5SJohn Bonesio die("Invalid argument \"%s\" to -H option\n", 235658f29a5SJohn Bonesio optarg); 236658f29a5SJohn Bonesio break; 237658f29a5SJohn Bonesio 238658f29a5SJohn Bonesio case 's': 23947605971SRob Herring sort = true; 240658f29a5SJohn Bonesio break; 241658f29a5SJohn Bonesio 242cd296721SStephen Warren case 'W': 243cd296721SStephen Warren parse_checks_option(true, false, optarg); 244cd296721SStephen Warren break; 245cd296721SStephen Warren 246cd296721SStephen Warren case 'E': 247cd296721SStephen Warren parse_checks_option(false, true, optarg); 248cd296721SStephen Warren break; 249cd296721SStephen Warren 2506f05afcbSRob Herring case '@': 2516f05afcbSRob Herring generate_symbols = 1; 2526f05afcbSRob Herring break; 2536f05afcbSRob Herring case 'A': 2546f05afcbSRob Herring auto_label_aliases = 1; 2556f05afcbSRob Herring break; 256c2e7075cSRob Herring case 'T': 257c2e7075cSRob Herring annotate++; 258c2e7075cSRob Herring break; 2596f05afcbSRob Herring 2609fffb55fSDavid Gibson case 'h': 26173ab39b1SGrant Likely usage(NULL); 2629fffb55fSDavid Gibson default: 26373ab39b1SGrant Likely usage("unknown option"); 2649fffb55fSDavid Gibson } 2659fffb55fSDavid Gibson } 2669fffb55fSDavid Gibson 2679fffb55fSDavid Gibson if (argc > (optind+1)) 26873ab39b1SGrant Likely usage("missing files"); 2699fffb55fSDavid Gibson else if (argc < (optind+1)) 2709fffb55fSDavid Gibson arg = "-"; 2719fffb55fSDavid Gibson else 2729fffb55fSDavid Gibson arg = argv[optind]; 2739fffb55fSDavid Gibson 2749fffb55fSDavid Gibson /* minsize and padsize are mutually exclusive */ 2759fffb55fSDavid Gibson if (minsize && padsize) 2769fffb55fSDavid Gibson die("Can't set both -p and -S\n"); 2779fffb55fSDavid Gibson 278136ec204SStephen Warren if (depname) { 279136ec204SStephen Warren depfile = fopen(depname, "w"); 280136ec204SStephen Warren if (!depfile) 281136ec204SStephen Warren die("Couldn't open dependency file %s: %s\n", depname, 282136ec204SStephen Warren strerror(errno)); 283136ec204SStephen Warren fprintf(depfile, "%s:", outname); 284136ec204SStephen Warren } 285136ec204SStephen Warren 28691feabc2SRob Herring if (inform == NULL) 28791feabc2SRob Herring inform = guess_input_format(arg, "dts"); 28891feabc2SRob Herring if (outform == NULL) { 28991feabc2SRob Herring outform = guess_type_by_name(outname, NULL); 29091feabc2SRob Herring if (outform == NULL) { 29191feabc2SRob Herring if (streq(inform, "dts")) 29291feabc2SRob Herring outform = "dtb"; 29391feabc2SRob Herring else 29491feabc2SRob Herring outform = "dts"; 29591feabc2SRob Herring } 29691feabc2SRob Herring } 297c2e7075cSRob Herring if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) 298c2e7075cSRob Herring die("--annotate requires -I dts -O dts\n"); 2999fffb55fSDavid Gibson if (streq(inform, "dts")) 3006f05afcbSRob Herring dti = dt_from_source(arg); 3019fffb55fSDavid Gibson else if (streq(inform, "fs")) 3026f05afcbSRob Herring dti = dt_from_fs(arg); 3039fffb55fSDavid Gibson else if(streq(inform, "dtb")) 3046f05afcbSRob Herring dti = dt_from_blob(arg); 3059fffb55fSDavid Gibson else 3069fffb55fSDavid Gibson die("Unknown input format \"%s\"\n", inform); 3079fffb55fSDavid Gibson 30889d12310SRob Herring dti->outname = outname; 30989d12310SRob Herring 310136ec204SStephen Warren if (depfile) { 311136ec204SStephen Warren fputc('\n', depfile); 312136ec204SStephen Warren fclose(depfile); 313136ec204SStephen Warren } 314136ec204SStephen Warren 3159fffb55fSDavid Gibson if (cmdline_boot_cpuid != -1) 3166f05afcbSRob Herring dti->boot_cpuid_phys = cmdline_boot_cpuid; 3179fffb55fSDavid Gibson 3186f05afcbSRob Herring fill_fullpaths(dti->dt, ""); 3196f05afcbSRob Herring 3206f05afcbSRob Herring /* on a plugin, generate by default */ 3216f05afcbSRob Herring if (dti->dtsflags & DTSF_PLUGIN) { 3226f05afcbSRob Herring generate_fixups = 1; 3236f05afcbSRob Herring } 3246f05afcbSRob Herring 3259130ba88SRob Herring process_checks(force, dti); 3269130ba88SRob Herring 3276f05afcbSRob Herring if (auto_label_aliases) 3286f05afcbSRob Herring generate_label_tree(dti, "aliases", false); 3296f05afcbSRob Herring 3306f05afcbSRob Herring if (generate_symbols) 3316f05afcbSRob Herring generate_label_tree(dti, "__symbols__", true); 3326f05afcbSRob Herring 3336f05afcbSRob Herring if (generate_fixups) { 3346f05afcbSRob Herring generate_fixups_tree(dti, "__fixups__"); 3356f05afcbSRob Herring generate_local_fixups_tree(dti, "__local_fixups__"); 3366f05afcbSRob Herring } 3379fffb55fSDavid Gibson 338658f29a5SJohn Bonesio if (sort) 3396f05afcbSRob Herring sort_tree(dti); 3409fffb55fSDavid Gibson 3419fffb55fSDavid Gibson if (streq(outname, "-")) { 3429fffb55fSDavid Gibson outf = stdout; 3439fffb55fSDavid Gibson } else { 34447605971SRob Herring outf = fopen(outname, "wb"); 3459fffb55fSDavid Gibson if (! outf) 3469fffb55fSDavid Gibson die("Couldn't open output file %s: %s\n", 3479fffb55fSDavid Gibson outname, strerror(errno)); 3489fffb55fSDavid Gibson } 3499fffb55fSDavid Gibson 3509fffb55fSDavid Gibson if (streq(outform, "dts")) { 3516f05afcbSRob Herring dt_to_source(outf, dti); 352f858927fSRob Herring #ifndef NO_YAML 353f858927fSRob Herring } else if (streq(outform, "yaml")) { 354f858927fSRob Herring if (!streq(inform, "dts")) 355f858927fSRob Herring die("YAML output format requires dts input format\n"); 356f858927fSRob Herring dt_to_yaml(outf, dti); 357f858927fSRob Herring #endif 3589fffb55fSDavid Gibson } else if (streq(outform, "dtb")) { 3596f05afcbSRob Herring dt_to_blob(outf, dti, outversion); 3609fffb55fSDavid Gibson } else if (streq(outform, "asm")) { 3616f05afcbSRob Herring dt_to_asm(outf, dti, outversion); 3629fffb55fSDavid Gibson } else if (streq(outform, "null")) { 3639fffb55fSDavid Gibson /* do nothing */ 3649fffb55fSDavid Gibson } else { 3659fffb55fSDavid Gibson die("Unknown output format \"%s\"\n", outform); 3669fffb55fSDavid Gibson } 3679fffb55fSDavid Gibson 3689fffb55fSDavid Gibson exit(0); 3699fffb55fSDavid Gibson } 370