Home | History | Annotate | Download | only in dtc
      1 /*
      2  * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
      3  *
      4  * Author:
      5  *	 Pantelis Antoniou <pantelis.antoniou (at) konsulko.com>
      6  *
      7  * This program is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU General Public License as
      9  * published by the Free Software Foundation; either version 2 of
     10  * the License, or (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this program; if not, write to the Free Software
     19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
     20  * MA 02111-1307 USA
     21  */
     22 
     23 #include <assert.h>
     24 #include <ctype.h>
     25 #include <getopt.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <alloca.h>
     30 
     31 #include <libfdt.h>
     32 
     33 #include "util.h"
     34 
     35 /* Usage related data. */
     36 static const char usage_synopsis[] =
     37 	"apply a number of overlays to a base blob\n"
     38 	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
     39 	"\n"
     40 	USAGE_TYPE_MSG;
     41 static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
     42 static struct option const usage_long_opts[] = {
     43 	{"input",            required_argument, NULL, 'i'},
     44 	{"output",	     required_argument, NULL, 'o'},
     45 	{"verbose",	           no_argument, NULL, 'v'},
     46 	USAGE_COMMON_LONG_OPTS,
     47 };
     48 static const char * const usage_opts_help[] = {
     49 	"Input base DT blob",
     50 	"Output DT blob",
     51 	"Verbose messages",
     52 	USAGE_COMMON_OPTS_HELP
     53 };
     54 
     55 int verbose = 0;
     56 
     57 static int do_fdtoverlay(const char *input_filename,
     58 			 const char *output_filename,
     59 			 int argc, char *argv[])
     60 {
     61 	char *blob = NULL;
     62 	char **ovblob = NULL;
     63 	off_t blob_len, ov_len, total_len;
     64 	int i, ret = -1;
     65 
     66 	blob = utilfdt_read_len(input_filename, &blob_len);
     67 	if (!blob) {
     68 		fprintf(stderr, "\nFailed to read base blob %s\n",
     69 				input_filename);
     70 		goto out_err;
     71 	}
     72 	ret = 0;
     73 
     74 	/* allocate blob pointer array */
     75 	ovblob = alloca(sizeof(*ovblob) * argc);
     76 	memset(ovblob, 0, sizeof(*ovblob) * argc);
     77 
     78 	/* read and keep track of the overlay blobs */
     79 	total_len = 0;
     80 	for (i = 0; i < argc; i++) {
     81 		ovblob[i] = utilfdt_read_len(argv[i], &ov_len);
     82 		if (!ovblob[i]) {
     83 			fprintf(stderr, "\nFailed to read overlay %s\n",
     84 					argv[i]);
     85 			goto out_err;
     86 		}
     87 		total_len += ov_len;
     88 	}
     89 
     90 	/* grow the blob to worst case */
     91 	blob_len = fdt_totalsize(blob) + total_len;
     92 	blob = xrealloc(blob, blob_len);
     93 	fdt_open_into(blob, blob, blob_len);
     94 
     95 	/* apply the overlays in sequence */
     96 	for (i = 0; i < argc; i++) {
     97 		ret = fdt_overlay_apply(blob, ovblob[i]);
     98 		if (ret) {
     99 			fprintf(stderr, "\nFailed to apply %s (%d)\n",
    100 					argv[i], ret);
    101 			goto out_err;
    102 		}
    103 	}
    104 
    105 	fdt_pack(blob);
    106 	ret = utilfdt_write(output_filename, blob);
    107 	if (ret)
    108 		fprintf(stderr, "\nFailed to write output blob %s\n",
    109 				output_filename);
    110 
    111 out_err:
    112 	if (ovblob) {
    113 		for (i = 0; i < argc; i++) {
    114 			if (ovblob[i])
    115 				free(ovblob[i]);
    116 		}
    117 	}
    118 	free(blob);
    119 
    120 	return ret;
    121 }
    122 
    123 int main(int argc, char *argv[])
    124 {
    125 	int opt, i;
    126 	char *input_filename = NULL;
    127 	char *output_filename = NULL;
    128 
    129 	while ((opt = util_getopt_long()) != EOF) {
    130 		switch (opt) {
    131 		case_USAGE_COMMON_FLAGS
    132 
    133 		case 'i':
    134 			input_filename = optarg;
    135 			break;
    136 		case 'o':
    137 			output_filename = optarg;
    138 			break;
    139 		case 'v':
    140 			verbose = 1;
    141 			break;
    142 		}
    143 	}
    144 
    145 	if (!input_filename)
    146 		usage("missing input file");
    147 
    148 	if (!output_filename)
    149 		usage("missing output file");
    150 
    151 	argv += optind;
    152 	argc -= optind;
    153 
    154 	if (argc <= 0)
    155 		usage("missing overlay file(s)");
    156 
    157 	if (verbose) {
    158 		printf("input  = %s\n", input_filename);
    159 		printf("output = %s\n", output_filename);
    160 		for (i = 0; i < argc; i++)
    161 			printf("overlay[%d] = %s\n", i, argv[i]);
    162 	}
    163 
    164 	if (do_fdtoverlay(input_filename, output_filename, argc, argv))
    165 		return 1;
    166 
    167 	return 0;
    168 }
    169