1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
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))