14f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin/*
24f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Copyright (C) 2016 The Android Open Source Project
34f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
44f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Licensed under the Apache License, Version 2.0 (the "License");
54f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * you may not use this file except in compliance with the License.
64f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * You may obtain a copy of the License at
74f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
84f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *      http://www.apache.org/licenses/LICENSE-2.0
94f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin *
104f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * Unless required by applicable law or agreed to in writing, software
114f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * distributed under the License is distributed on an "AS IS" BASIS,
124f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * See the License for the specific language governing permissions and
144f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin * limitations under the License.
154f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin */
164f00eda9fa05364edd719b05b88e4445682eeee5SzuWei Lin
172dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin#include <getopt.h>
182dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin#include <stdio.h>
192dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin#include <stdlib.h>
202dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin#include <string.h>
212dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin#include <unistd.h>
222dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
232dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin/*
242dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * The parameters to generate testing DTS
252dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * /dts-v1/ /plugin/;           <- header and plugin
262dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * /{
272dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *   level0 {                   <- depth
282dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *     level1 {
292dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *       ...
302dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *       node0: node0 {         <- node
312dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *         unused0 {}           <- unused
322dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *         unused1 {}
332dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *         ...
342dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *         status="disabled";
352dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *       }
362dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *       ...
372dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *     };
382dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *   };
392dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * };
402dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *
412dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * &node0 {                     <- append
422dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *    new_prop="foo";
432dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * }
442dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * ...
452dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *
462dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * &node0 {                     <- override
472dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin *    status="okay";
482dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * }
492dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin * ...
502dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin */
512dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
522dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic const char short_options[] = "Hpd:u:n:a:w:o:";
532dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic struct option long_options[] = {
542dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "no-header",    no_argument,       NULL, 'H' },
552dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "plugin",       no_argument,       NULL, 'p' },
562dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "depth",        required_argument, NULL, 'd' },
572dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "unused",       required_argument, NULL, 'u' },
582dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "node",         required_argument, NULL, 'n' },
592dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "append",       required_argument, NULL, 'a' },
602dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "override",     required_argument, NULL, 'w' },
612dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { "output",       required_argument, NULL, 'o' },
622dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  { 0,              0,                 NULL, 0 }
632dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin};
642dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
652dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstruct gen_params {
662dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int no_header;    /* Doesn't add header */
672dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int plugin;       /* Add /plugin/ in header */
682dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int depth;        /* the depth of a node, 0 means generate on root node */
692dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int unused_num;   /* unused child nodes per node */
702dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int node_num;     /* the number to generate nodes */
712dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int append_num;   /* the number to generate appending references */
722dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int override_num; /* the number to generate overriding references */
732dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin};
742dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
752dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
762dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_header(FILE *fp, int is_plugin) {
772dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  fprintf(fp, "/dts-v1/;\n");
782dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  if (is_plugin) {
792dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "/plugin/;\n");
802dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
812dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  fprintf(fp, "\n");
822dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
832dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
842dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_root_begin(FILE *fp, int depth) {
852dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  fprintf(fp, "/ {\n");
862dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
872dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int i;
882dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  for (i = 0; i < depth; i++) {
892dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "level%d {\n", i);
902dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
912dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
922dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
932dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_root_end(FILE *fp, int depth) {
942dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int i;
952dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  for (i = 0; i < depth; i++) {
962dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "};\n");
972dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
982dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
992dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  fprintf(fp, "};\n\n");
1002dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1012dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1022dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_unused_nodes(FILE *fp, int count) {
1032dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int i;
1042dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  for (i = 0; i < count; i++) {
1052dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "unused%d {};\n", i);
1062dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1072dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1082dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1092dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_prop_str(FILE *fp, const char *prop, const char *value) {
1102dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  /* TODO: should escape value */
1112dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  fprintf(fp, "%s=\"%s\";\n", prop, value);
1122dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1132dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1142dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_nodes(FILE *fp, int count, const char *prop, const char *value) {
1152dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int i;
1162dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  for (i = 0; i < count; i++) {
1172dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "node%d: node%d {\n", i, i);
1182dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_prop_str(fp, prop, value);
1192dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "};\n\n");
1202dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1212dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1222dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1232dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic void output_ref_nodes(FILE *fp, int start_id, int count,
1242dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin                      const char *prop, const char *value) {
1252dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int i;
1262dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  for (i = start_id; i < start_id + count; i++) {
1272dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "&node%d {\n", i);
1282dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_prop_str(fp, prop, value);
1292dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fprintf(fp, "};\n\n");
1302dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1312dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1322dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1332dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linstatic int gen_dts(FILE *fp, const struct gen_params *params) {
1342dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  if (!params->no_header) {
1352dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_header(fp, params->plugin);
1362dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1372dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1382dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  if (params->node_num > 0) {
1392dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_root_begin(fp, params->depth);
1402dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_unused_nodes(fp, params->unused_num);
1412dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_nodes(fp, params->node_num, "status", "disabled");
1422dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    output_root_end(fp, params->depth);
1432dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1442dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1452dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  int start_id = 0;
1462dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  output_ref_nodes(fp, start_id, params->append_num, "new_prop", "bar");
1472dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  start_id += params->append_num;
1482dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  output_ref_nodes(fp, start_id, params->override_num, "status", "okay");
1492dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1502dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  return 0;
1512dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
1522dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1532dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Linint main(int argc, char *argv[]) {
1542dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  const char *filename = NULL;
1552dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  struct gen_params params;
1562dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  memset(&params, 0, sizeof(struct gen_params));
1572dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1582dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  while (1) {
1592dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    int option_index = 0;
1602dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    int c = getopt_long(argc, argv, short_options, long_options, &option_index);
1612dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    if (c == -1) {
1622dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1632dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    }
1642dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    switch (c) {
1652dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'H':
1662dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.no_header = 1;
1672dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1682dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'p':
1692dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.plugin = 1;
1702dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1712dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'd':
1722dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.depth = atoi(optarg);
1732dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1742dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'u':
1752dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.unused_num = atoi(optarg);
1762dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1772dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'n':
1782dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.node_num = atoi(optarg);
1792dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1802dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'a':
1812dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.append_num = atoi(optarg);
1822dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1832dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'w':
1842dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      params.override_num = atoi(optarg);
1852dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1862dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case 'o':
1872dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      filename = optarg;
1882dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1892dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    case '?':
1902dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      break;
1912dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    }
1922dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
1932dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
1942dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  FILE *fp = NULL;
1952dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  if (filename) {
1962dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fp = fopen(filename, "wt");
1972dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    if (fp == NULL) {
1982dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      fprintf(stderr, "Can not create file: ", filename);
1992dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin      return -1;
2002dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    }
2012dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
2022dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
2032dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  gen_dts(fp ? fp : stdout, &params);
2042dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
2052dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  if (fp) {
2062dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin    fclose(fp);
2072dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  }
2082dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin
2092dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin  return 0;
2102dcb17e2252b17f56e1793bcf6ac479dc6e48319SzuWei Lin}
211