linux/scripts/dtc/dtc.c
<<
>>
Prefs
   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 */
  29int quiet;              /* Level of quietness */
  30int reservenum;         /* Number of memory reservation slots */
  31int minsize;            /* Minimum blob size */
  32int padsize;            /* Additional padding to blob */
  33int phandle_format = PHANDLE_BOTH;      /* Use linux,phandle or phandle properties */
  34
  35static 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
  55static const char usage_synopsis[] = "dtc [options] <input file>";
  56static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
  57static 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};
  78static 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
 109static 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
 123static 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
 154int 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