root/scripts/dtc/dtc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_power_of_2
  2. fill_fullpaths
  3. guess_type_by_name
  4. guess_input_format
  5. main

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

/* [<][>][^][v][top][bottom][index][help] */