• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
3  *
4  * Author:
5  *	 Pantelis Antoniou <pantelis.antoniou@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 
do_fdtoverlay(const char * input_filename,const char * output_filename,int argc,char * argv[])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 
main(int argc,char * argv[])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