Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
0004  */
0005 
0006 #include <sys/stat.h>
0007 
0008 #include "dtc.h"
0009 #include "srcpos.h"
0010 
0011 /*
0012  * Command line options
0013  */
0014 int quiet;      /* Level of quietness */
0015 unsigned int reservenum;/* Number of memory reservation slots */
0016 int minsize;        /* Minimum blob size */
0017 int padsize;        /* Additional padding to blob */
0018 int alignsize;      /* Additional padding to blob accroding to the alignsize */
0019 int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties */
0020 int generate_symbols;   /* enable symbols & fixup support */
0021 int generate_fixups;        /* suppress generation of fixups on symbol support */
0022 int auto_label_aliases;     /* auto generate labels -> aliases */
0023 int annotate;       /* Level of annotation: 1 for input source location
0024                >1 for full input source location. */
0025 
0026 static int is_power_of_2(int x)
0027 {
0028     return (x > 0) && ((x & (x - 1)) == 0);
0029 }
0030 
0031 static void fill_fullpaths(struct node *tree, const char *prefix)
0032 {
0033     struct node *child;
0034     const char *unit;
0035 
0036     tree->fullpath = join_path(prefix, tree->name);
0037 
0038     unit = strchr(tree->name, '@');
0039     if (unit)
0040         tree->basenamelen = unit - tree->name;
0041     else
0042         tree->basenamelen = strlen(tree->name);
0043 
0044     for_each_child(tree, child)
0045         fill_fullpaths(child, tree->fullpath);
0046 }
0047 
0048 /* Usage related data. */
0049 static const char usage_synopsis[] = "dtc [options] <input file>";
0050 static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
0051 static struct option const usage_long_opts[] = {
0052     {"quiet",            no_argument, NULL, 'q'},
0053     {"in-format",         a_argument, NULL, 'I'},
0054     {"out",               a_argument, NULL, 'o'},
0055     {"out-format",        a_argument, NULL, 'O'},
0056     {"out-version",       a_argument, NULL, 'V'},
0057     {"out-dependency",    a_argument, NULL, 'd'},
0058     {"reserve",           a_argument, NULL, 'R'},
0059     {"space",             a_argument, NULL, 'S'},
0060     {"pad",               a_argument, NULL, 'p'},
0061     {"align",             a_argument, NULL, 'a'},
0062     {"boot-cpu",          a_argument, NULL, 'b'},
0063     {"force",            no_argument, NULL, 'f'},
0064     {"include",           a_argument, NULL, 'i'},
0065     {"sort",             no_argument, NULL, 's'},
0066     {"phandle",           a_argument, NULL, 'H'},
0067     {"warning",           a_argument, NULL, 'W'},
0068     {"error",             a_argument, NULL, 'E'},
0069     {"symbols",      no_argument, NULL, '@'},
0070     {"auto-alias",       no_argument, NULL, 'A'},
0071     {"annotate",         no_argument, NULL, 'T'},
0072     {"help",             no_argument, NULL, 'h'},
0073     {"version",          no_argument, NULL, 'v'},
0074     {NULL,               no_argument, NULL, 0x0},
0075 };
0076 static const char * const usage_opts_help[] = {
0077     "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
0078     "\n\tInput formats are:\n"
0079      "\t\tdts - device tree source text\n"
0080      "\t\tdtb - device tree blob\n"
0081      "\t\tfs  - /proc/device-tree style directory",
0082     "\n\tOutput file",
0083     "\n\tOutput formats are:\n"
0084      "\t\tdts - device tree source text\n"
0085      "\t\tdtb - device tree blob\n"
0086 #ifndef NO_YAML
0087      "\t\tyaml - device tree encoded as YAML\n"
0088 #endif
0089      "\t\tasm - assembler source",
0090     "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
0091     "\n\tOutput dependency file",
0092     "\n\tMake space for <number> reserve map entries (for dtb and asm output)",
0093     "\n\tMake the blob at least <bytes> long (extra space)",
0094     "\n\tAdd padding to the blob of <bytes> long (extra space)",
0095     "\n\tMake the blob align to the <bytes> (extra space)",
0096     "\n\tSet the physical boot cpu",
0097     "\n\tTry to produce output even if the input tree has errors",
0098     "\n\tAdd a path to search for include files",
0099     "\n\tSort nodes and properties before outputting (useful for comparing trees)",
0100     "\n\tValid phandle formats are:\n"
0101      "\t\tlegacy - \"linux,phandle\" properties only\n"
0102      "\t\tepapr  - \"phandle\" properties only\n"
0103      "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
0104     "\n\tEnable/disable warnings (prefix with \"no-\")",
0105     "\n\tEnable/disable errors (prefix with \"no-\")",
0106     "\n\tEnable generation of symbols",
0107     "\n\tEnable auto-alias of labels",
0108     "\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
0109     "\n\tPrint this help and exit",
0110     "\n\tPrint version and exit",
0111     NULL,
0112 };
0113 
0114 static const char *guess_type_by_name(const char *fname, const char *fallback)
0115 {
0116     const char *s;
0117 
0118     s = strrchr(fname, '.');
0119     if (s == NULL)
0120         return fallback;
0121     if (!strcasecmp(s, ".dts"))
0122         return "dts";
0123     if (!strcasecmp(s, ".yaml"))
0124         return "yaml";
0125     if (!strcasecmp(s, ".dtbo"))
0126         return "dtb";
0127     if (!strcasecmp(s, ".dtb"))
0128         return "dtb";
0129     return fallback;
0130 }
0131 
0132 static const char *guess_input_format(const char *fname, const char *fallback)
0133 {
0134     struct stat statbuf;
0135     fdt32_t magic;
0136     FILE *f;
0137 
0138     if (stat(fname, &statbuf) != 0)
0139         return fallback;
0140 
0141     if (S_ISDIR(statbuf.st_mode))
0142         return "fs";
0143 
0144     if (!S_ISREG(statbuf.st_mode))
0145         return fallback;
0146 
0147     f = fopen(fname, "r");
0148     if (f == NULL)
0149         return fallback;
0150     if (fread(&magic, 4, 1, f) != 1) {
0151         fclose(f);
0152         return fallback;
0153     }
0154     fclose(f);
0155 
0156     if (fdt32_to_cpu(magic) == FDT_MAGIC)
0157         return "dtb";
0158 
0159     return guess_type_by_name(fname, fallback);
0160 }
0161 
0162 int main(int argc, char *argv[])
0163 {
0164     struct dt_info *dti;
0165     const char *inform = NULL;
0166     const char *outform = NULL;
0167     const char *outname = "-";
0168     const char *depname = NULL;
0169     bool force = false, sort = false;
0170     const char *arg;
0171     int opt;
0172     FILE *outf = NULL;
0173     int outversion = DEFAULT_FDT_VERSION;
0174     long long cmdline_boot_cpuid = -1;
0175 
0176     quiet      = 0;
0177     reservenum = 0;
0178     minsize    = 0;
0179     padsize    = 0;
0180     alignsize  = 0;
0181 
0182     while ((opt = util_getopt_long()) != EOF) {
0183         switch (opt) {
0184         case 'I':
0185             inform = optarg;
0186             break;
0187         case 'O':
0188             outform = optarg;
0189             break;
0190         case 'o':
0191             outname = optarg;
0192             break;
0193         case 'V':
0194             outversion = strtol(optarg, NULL, 0);
0195             break;
0196         case 'd':
0197             depname = optarg;
0198             break;
0199         case 'R':
0200             reservenum = strtoul(optarg, NULL, 0);
0201             break;
0202         case 'S':
0203             minsize = strtol(optarg, NULL, 0);
0204             break;
0205         case 'p':
0206             padsize = strtol(optarg, NULL, 0);
0207             break;
0208         case 'a':
0209             alignsize = strtol(optarg, NULL, 0);
0210             if (!is_power_of_2(alignsize))
0211                 die("Invalid argument \"%d\" to -a option\n",
0212                     alignsize);
0213             break;
0214         case 'f':
0215             force = true;
0216             break;
0217         case 'q':
0218             quiet++;
0219             break;
0220         case 'b':
0221             cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
0222             break;
0223         case 'i':
0224             srcfile_add_search_path(optarg);
0225             break;
0226         case 'v':
0227             util_version();
0228         case 'H':
0229             if (streq(optarg, "legacy"))
0230                 phandle_format = PHANDLE_LEGACY;
0231             else if (streq(optarg, "epapr"))
0232                 phandle_format = PHANDLE_EPAPR;
0233             else if (streq(optarg, "both"))
0234                 phandle_format = PHANDLE_BOTH;
0235             else
0236                 die("Invalid argument \"%s\" to -H option\n",
0237                     optarg);
0238             break;
0239 
0240         case 's':
0241             sort = true;
0242             break;
0243 
0244         case 'W':
0245             parse_checks_option(true, false, optarg);
0246             break;
0247 
0248         case 'E':
0249             parse_checks_option(false, true, optarg);
0250             break;
0251 
0252         case '@':
0253             generate_symbols = 1;
0254             break;
0255         case 'A':
0256             auto_label_aliases = 1;
0257             break;
0258         case 'T':
0259             annotate++;
0260             break;
0261 
0262         case 'h':
0263             usage(NULL);
0264         default:
0265             usage("unknown option");
0266         }
0267     }
0268 
0269     if (argc > (optind+1))
0270         usage("missing files");
0271     else if (argc < (optind+1))
0272         arg = "-";
0273     else
0274         arg = argv[optind];
0275 
0276     /* minsize and padsize are mutually exclusive */
0277     if (minsize && padsize)
0278         die("Can't set both -p and -S\n");
0279 
0280     if (depname) {
0281         depfile = fopen(depname, "w");
0282         if (!depfile)
0283             die("Couldn't open dependency file %s: %s\n", depname,
0284                 strerror(errno));
0285         fprintf(depfile, "%s:", outname);
0286     }
0287 
0288     if (inform == NULL)
0289         inform = guess_input_format(arg, "dts");
0290     if (outform == NULL) {
0291         outform = guess_type_by_name(outname, NULL);
0292         if (outform == NULL) {
0293             if (streq(inform, "dts"))
0294                 outform = "dtb";
0295             else
0296                 outform = "dts";
0297         }
0298     }
0299     if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
0300         die("--annotate requires -I dts -O dts\n");
0301     if (streq(inform, "dts"))
0302         dti = dt_from_source(arg);
0303     else if (streq(inform, "fs"))
0304         dti = dt_from_fs(arg);
0305     else if(streq(inform, "dtb"))
0306         dti = dt_from_blob(arg);
0307     else
0308         die("Unknown input format \"%s\"\n", inform);
0309 
0310     dti->outname = outname;
0311 
0312     if (depfile) {
0313         fputc('\n', depfile);
0314         fclose(depfile);
0315     }
0316 
0317     if (cmdline_boot_cpuid != -1)
0318         dti->boot_cpuid_phys = cmdline_boot_cpuid;
0319 
0320     fill_fullpaths(dti->dt, "");
0321 
0322     /* on a plugin, generate by default */
0323     if (dti->dtsflags & DTSF_PLUGIN) {
0324         generate_fixups = 1;
0325     }
0326 
0327     process_checks(force, dti);
0328 
0329     if (auto_label_aliases)
0330         generate_label_tree(dti, "aliases", false);
0331 
0332     if (generate_symbols)
0333         generate_label_tree(dti, "__symbols__", true);
0334 
0335     if (generate_fixups) {
0336         generate_fixups_tree(dti, "__fixups__");
0337         generate_local_fixups_tree(dti, "__local_fixups__");
0338     }
0339 
0340     if (sort)
0341         sort_tree(dti);
0342 
0343     if (streq(outname, "-")) {
0344         outf = stdout;
0345     } else {
0346         outf = fopen(outname, "wb");
0347         if (! outf)
0348             die("Couldn't open output file %s: %s\n",
0349                 outname, strerror(errno));
0350     }
0351 
0352     if (streq(outform, "dts")) {
0353         dt_to_source(outf, dti);
0354 #ifndef NO_YAML
0355     } else if (streq(outform, "yaml")) {
0356         if (!streq(inform, "dts"))
0357             die("YAML output format requires dts input format\n");
0358         dt_to_yaml(outf, dti);
0359 #endif
0360     } else if (streq(outform, "dtb")) {
0361         dt_to_blob(outf, dti, outversion);
0362     } else if (streq(outform, "asm")) {
0363         dt_to_asm(outf, dti, outversion);
0364     } else if (streq(outform, "null")) {
0365         /* do nothing */
0366     } else {
0367         die("Unknown output format \"%s\"\n", outform);
0368     }
0369 
0370     exit(0);
0371 }