1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
6 * Pantelis Antoniou <pantelis.antoniou@konsulko.com>
21 #define BUF_INCREMENT 65536
23 /* Usage related data. */
24 static const char usage_synopsis
[] =
25 "apply a number of overlays to a base blob\n"
26 " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
27 static const char usage_short_opts
[] = "i:o:v" USAGE_COMMON_SHORT_OPTS
;
28 static struct option
const usage_long_opts
[] = {
29 {"input", required_argument
, NULL
, 'i'},
30 {"output", required_argument
, NULL
, 'o'},
31 {"verbose", no_argument
, NULL
, 'v'},
32 USAGE_COMMON_LONG_OPTS
,
34 static const char * const usage_opts_help
[] = {
38 USAGE_COMMON_OPTS_HELP
43 static void *apply_one(char *base
, const char *overlay
, size_t *buf_len
,
51 * We take copies first, because a failed apply can trash
52 * both the base blob and the overlay
54 tmpo
= xmalloc(fdt_totalsize(overlay
));
57 tmp
= xrealloc(tmp
, *buf_len
);
58 ret
= fdt_open_into(base
, tmp
, *buf_len
);
61 "\nFailed to make temporary copy: %s\n",
66 memcpy(tmpo
, overlay
, fdt_totalsize(overlay
));
68 ret
= fdt_overlay_apply(tmp
, tmpo
);
69 if (ret
== -FDT_ERR_NOSPACE
) {
70 *buf_len
+= BUF_INCREMENT
;
72 } while (ret
== -FDT_ERR_NOSPACE
);
75 fprintf(stderr
, "\nFailed to apply '%s': %s\n",
76 name
, fdt_strerror(ret
));
91 static int do_fdtoverlay(const char *input_filename
,
92 const char *output_filename
,
93 int argc
, char *argv
[])
100 blob
= utilfdt_read(input_filename
, &buf_len
);
102 fprintf(stderr
, "\nFailed to read '%s'\n", input_filename
);
105 if (fdt_totalsize(blob
) > buf_len
) {
107 "\nBase blob is incomplete (%lu / %" PRIu32
" bytes read)\n",
108 (unsigned long)buf_len
, fdt_totalsize(blob
));
112 /* allocate blob pointer array */
113 ovblob
= xmalloc(sizeof(*ovblob
) * argc
);
114 memset(ovblob
, 0, sizeof(*ovblob
) * argc
);
116 /* read and keep track of the overlay blobs */
117 for (i
= 0; i
< argc
; i
++) {
119 ovblob
[i
] = utilfdt_read(argv
[i
], &ov_len
);
121 fprintf(stderr
, "\nFailed to read '%s'\n", argv
[i
]);
124 if (fdt_totalsize(ovblob
[i
]) > ov_len
) {
126 "\nOverlay '%s' is incomplete (%lu / %" PRIu32
" bytes read)\n",
127 argv
[i
], (unsigned long)ov_len
,
128 fdt_totalsize(ovblob
[i
]));
133 buf_len
= fdt_totalsize(blob
);
135 /* apply the overlays in sequence */
136 for (i
= 0; i
< argc
; i
++) {
137 blob
= apply_one(blob
, ovblob
[i
], &buf_len
, argv
[i
]);
143 ret
= utilfdt_write(output_filename
, blob
);
145 fprintf(stderr
, "\nFailed to write '%s'\n",
150 for (i
= 0; i
< argc
; i
++) {
161 int main(int argc
, char *argv
[])
164 char *input_filename
= NULL
;
165 char *output_filename
= NULL
;
167 while ((opt
= util_getopt_long()) != EOF
) {
169 case_USAGE_COMMON_FLAGS
172 input_filename
= optarg
;
175 output_filename
= optarg
;
184 usage("missing input file");
186 if (!output_filename
)
187 usage("missing output file");
193 usage("missing overlay file(s)");
196 printf("input = %s\n", input_filename
);
197 printf("output = %s\n", output_filename
);
198 for (i
= 0; i
< argc
; i
++)
199 printf("overlay[%d] = %s\n", i
, argv
[i
]);
202 if (do_fdtoverlay(input_filename
, output_filename
, argc
, argv
))