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 <inttypes.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 size_t blob_len, ov_len, total_len;
64 int i, ret = -1;
65
66 blob = utilfdt_read(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 if (fdt_totalsize(blob) > blob_len) {
73 fprintf(stderr,
74 "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
75 (unsigned long)blob_len, fdt_totalsize(blob));
76 goto out_err;
77 }
78 ret = 0;
79
80 /* allocate blob pointer array */
81 ovblob = malloc(sizeof(*ovblob) * argc);
82 memset(ovblob, 0, sizeof(*ovblob) * argc);
83
84 /* read and keep track of the overlay blobs */
85 total_len = 0;
86 for (i = 0; i < argc; i++) {
87 ovblob[i] = utilfdt_read(argv[i], &ov_len);
88 if (!ovblob[i]) {
89 fprintf(stderr, "\nFailed to read overlay %s\n",
90 argv[i]);
91 goto out_err;
92 }
93 total_len += ov_len;
94 }
95
96 /* grow the blob to worst case */
97 blob_len = fdt_totalsize(blob) + total_len;
98 blob = xrealloc(blob, blob_len);
99 fdt_open_into(blob, blob, blob_len);
100
101 /* apply the overlays in sequence */
102 for (i = 0; i < argc; i++) {
103 ret = fdt_overlay_apply(blob, ovblob[i]);
104 if (ret) {
105 fprintf(stderr, "\nFailed to apply %s (%d)\n",
106 argv[i], ret);
107 goto out_err;
108 }
109 }
110
111 fdt_pack(blob);
112 ret = utilfdt_write(output_filename, blob);
113 if (ret)
114 fprintf(stderr, "\nFailed to write output blob %s\n",
115 output_filename);
116
117 out_err:
118 if (ovblob) {
119 for (i = 0; i < argc; i++) {
120 if (ovblob[i])
121 free(ovblob[i]);
122 }
123 free(ovblob);
124 }
125 free(blob);
126
127 return ret;
128 }
129
main(int argc,char * argv[])130 int main(int argc, char *argv[])
131 {
132 int opt, i;
133 char *input_filename = NULL;
134 char *output_filename = NULL;
135
136 while ((opt = util_getopt_long()) != EOF) {
137 switch (opt) {
138 case_USAGE_COMMON_FLAGS
139
140 case 'i':
141 input_filename = optarg;
142 break;
143 case 'o':
144 output_filename = optarg;
145 break;
146 case 'v':
147 verbose = 1;
148 break;
149 }
150 }
151
152 if (!input_filename)
153 usage("missing input file");
154
155 if (!output_filename)
156 usage("missing output file");
157
158 argv += optind;
159 argc -= optind;
160
161 if (argc <= 0)
162 usage("missing overlay file(s)");
163
164 if (verbose) {
165 printf("input = %s\n", input_filename);
166 printf("output = %s\n", output_filename);
167 for (i = 0; i < argc; i++)
168 printf("overlay[%d] = %s\n", i, argv[i]);
169 }
170
171 if (do_fdtoverlay(input_filename, output_filename, argc, argv))
172 return 1;
173
174 return 0;
175 }
176