blob: 9c5618cdf5800d717213afedc137a1e5565ee6bd [file] [log] [blame]
Pantelis Antoniou42409142017-06-14 17:51:11 +03001/*
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. */
36static 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;
41static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
42static 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};
48static 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
55int verbose = 0;
56
57static 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
111out_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
123int 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}