cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dtc.c (9466B)


      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 */
     14int quiet;		/* Level of quietness */
     15unsigned int reservenum;/* Number of memory reservation slots */
     16int minsize;		/* Minimum blob size */
     17int padsize;		/* Additional padding to blob */
     18int alignsize;		/* Additional padding to blob accroding to the alignsize */
     19int phandle_format = PHANDLE_EPAPR;	/* Use linux,phandle or phandle properties */
     20int generate_symbols;	/* enable symbols & fixup support */
     21int generate_fixups;		/* suppress generation of fixups on symbol support */
     22int auto_label_aliases;		/* auto generate labels -> aliases */
     23int annotate;		/* Level of annotation: 1 for input source location
     24			   >1 for full input source location. */
     25
     26static int is_power_of_2(int x)
     27{
     28	return (x > 0) && ((x & (x - 1)) == 0);
     29}
     30
     31static 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. */
     49static const char usage_synopsis[] = "dtc [options] <input file>";
     50static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv";
     51static 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};
     76static 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
    114static 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, ".dtbo"))
    126		return "dtb";
    127	if (!strcasecmp(s, ".dtb"))
    128		return "dtb";
    129	return fallback;
    130}
    131
    132static const char *guess_input_format(const char *fname, const char *fallback)
    133{
    134	struct stat statbuf;
    135	fdt32_t magic;
    136	FILE *f;
    137
    138	if (stat(fname, &statbuf) != 0)
    139		return fallback;
    140
    141	if (S_ISDIR(statbuf.st_mode))
    142		return "fs";
    143
    144	if (!S_ISREG(statbuf.st_mode))
    145		return fallback;
    146
    147	f = fopen(fname, "r");
    148	if (f == NULL)
    149		return fallback;
    150	if (fread(&magic, 4, 1, f) != 1) {
    151		fclose(f);
    152		return fallback;
    153	}
    154	fclose(f);
    155
    156	if (fdt32_to_cpu(magic) == FDT_MAGIC)
    157		return "dtb";
    158
    159	return guess_type_by_name(fname, fallback);
    160}
    161
    162int main(int argc, char *argv[])
    163{
    164	struct dt_info *dti;
    165	const char *inform = NULL;
    166	const char *outform = NULL;
    167	const char *outname = "-";
    168	const char *depname = NULL;
    169	bool force = false, sort = false;
    170	const char *arg;
    171	int opt;
    172	FILE *outf = NULL;
    173	int outversion = DEFAULT_FDT_VERSION;
    174	long long cmdline_boot_cpuid = -1;
    175
    176	quiet      = 0;
    177	reservenum = 0;
    178	minsize    = 0;
    179	padsize    = 0;
    180	alignsize  = 0;
    181
    182	while ((opt = util_getopt_long()) != EOF) {
    183		switch (opt) {
    184		case 'I':
    185			inform = optarg;
    186			break;
    187		case 'O':
    188			outform = optarg;
    189			break;
    190		case 'o':
    191			outname = optarg;
    192			break;
    193		case 'V':
    194			outversion = strtol(optarg, NULL, 0);
    195			break;
    196		case 'd':
    197			depname = optarg;
    198			break;
    199		case 'R':
    200			reservenum = strtoul(optarg, NULL, 0);
    201			break;
    202		case 'S':
    203			minsize = strtol(optarg, NULL, 0);
    204			break;
    205		case 'p':
    206			padsize = strtol(optarg, NULL, 0);
    207			break;
    208		case 'a':
    209			alignsize = strtol(optarg, NULL, 0);
    210			if (!is_power_of_2(alignsize))
    211				die("Invalid argument \"%d\" to -a option\n",
    212				    alignsize);
    213			break;
    214		case 'f':
    215			force = true;
    216			break;
    217		case 'q':
    218			quiet++;
    219			break;
    220		case 'b':
    221			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
    222			break;
    223		case 'i':
    224			srcfile_add_search_path(optarg);
    225			break;
    226		case 'v':
    227			util_version();
    228		case 'H':
    229			if (streq(optarg, "legacy"))
    230				phandle_format = PHANDLE_LEGACY;
    231			else if (streq(optarg, "epapr"))
    232				phandle_format = PHANDLE_EPAPR;
    233			else if (streq(optarg, "both"))
    234				phandle_format = PHANDLE_BOTH;
    235			else
    236				die("Invalid argument \"%s\" to -H option\n",
    237				    optarg);
    238			break;
    239
    240		case 's':
    241			sort = true;
    242			break;
    243
    244		case 'W':
    245			parse_checks_option(true, false, optarg);
    246			break;
    247
    248		case 'E':
    249			parse_checks_option(false, true, optarg);
    250			break;
    251
    252		case '@':
    253			generate_symbols = 1;
    254			break;
    255		case 'A':
    256			auto_label_aliases = 1;
    257			break;
    258		case 'T':
    259			annotate++;
    260			break;
    261
    262		case 'h':
    263			usage(NULL);
    264		default:
    265			usage("unknown option");
    266		}
    267	}
    268
    269	if (argc > (optind+1))
    270		usage("missing files");
    271	else if (argc < (optind+1))
    272		arg = "-";
    273	else
    274		arg = argv[optind];
    275
    276	/* minsize and padsize are mutually exclusive */
    277	if (minsize && padsize)
    278		die("Can't set both -p and -S\n");
    279
    280	if (depname) {
    281		depfile = fopen(depname, "w");
    282		if (!depfile)
    283			die("Couldn't open dependency file %s: %s\n", depname,
    284			    strerror(errno));
    285		fprintf(depfile, "%s:", outname);
    286	}
    287
    288	if (inform == NULL)
    289		inform = guess_input_format(arg, "dts");
    290	if (outform == NULL) {
    291		outform = guess_type_by_name(outname, NULL);
    292		if (outform == NULL) {
    293			if (streq(inform, "dts"))
    294				outform = "dtb";
    295			else
    296				outform = "dts";
    297		}
    298	}
    299	if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
    300		die("--annotate requires -I dts -O dts\n");
    301	if (streq(inform, "dts"))
    302		dti = dt_from_source(arg);
    303	else if (streq(inform, "fs"))
    304		dti = dt_from_fs(arg);
    305	else if(streq(inform, "dtb"))
    306		dti = dt_from_blob(arg);
    307	else
    308		die("Unknown input format \"%s\"\n", inform);
    309
    310	dti->outname = outname;
    311
    312	if (depfile) {
    313		fputc('\n', depfile);
    314		fclose(depfile);
    315	}
    316
    317	if (cmdline_boot_cpuid != -1)
    318		dti->boot_cpuid_phys = cmdline_boot_cpuid;
    319
    320	fill_fullpaths(dti->dt, "");
    321
    322	/* on a plugin, generate by default */
    323	if (dti->dtsflags & DTSF_PLUGIN) {
    324		generate_fixups = 1;
    325	}
    326
    327	process_checks(force, dti);
    328
    329	if (auto_label_aliases)
    330		generate_label_tree(dti, "aliases", false);
    331
    332	if (generate_symbols)
    333		generate_label_tree(dti, "__symbols__", true);
    334
    335	if (generate_fixups) {
    336		generate_fixups_tree(dti, "__fixups__");
    337		generate_local_fixups_tree(dti, "__local_fixups__");
    338	}
    339
    340	if (sort)
    341		sort_tree(dti);
    342
    343	if (streq(outname, "-")) {
    344		outf = stdout;
    345	} else {
    346		outf = fopen(outname, "wb");
    347		if (! outf)
    348			die("Couldn't open output file %s: %s\n",
    349			    outname, strerror(errno));
    350	}
    351
    352	if (streq(outform, "dts")) {
    353		dt_to_source(outf, dti);
    354#ifndef NO_YAML
    355	} else if (streq(outform, "yaml")) {
    356		if (!streq(inform, "dts"))
    357			die("YAML output format requires dts input format\n");
    358		dt_to_yaml(outf, dti);
    359#endif
    360	} else if (streq(outform, "dtb")) {
    361		dt_to_blob(outf, dti, outversion);
    362	} else if (streq(outform, "asm")) {
    363		dt_to_asm(outf, dti, outversion);
    364	} else if (streq(outform, "null")) {
    365		/* do nothing */
    366	} else {
    367		die("Unknown output format \"%s\"\n", outform);
    368	}
    369
    370	exit(0);
    371}