File Index
Files and directories
Sign in
FILE

fdtoverlay.c

File preview with syntax highlighting.

linux-6.19.14/scripts/dtc/fdtoverlay.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
  4 *
  5 * Author:
  6 *	 Pantelis Antoniou <pantelis.antoniou@konsulko.com>
  7 */
  8
  9#include <assert.h>
 10#include <ctype.h>
 11#include <getopt.h>
 12#include <stdio.h>
 13#include <stdlib.h>
 14#include <string.h>
 15#include <inttypes.h>
 16
 17#include <libfdt.h>
 18
 19#include "util.h"
 20
 21#define BUF_INCREMENT	65536
 22
 23/* Usage related data. */
 24static const char usage_synopsis[] =
 25	"apply a number of overlays to a base blob\n"
 26	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
 27static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
 28static 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,
 33};
 34static const char * const usage_opts_help[] = {
 35	"Input base DT blob",
 36	"Output DT blob",
 37	"Verbose messages",
 38	USAGE_COMMON_OPTS_HELP
 39};
 40
 41int verbose = 0;
 42
 43static void *apply_one(char *base, const char *overlay, size_t *buf_len,
 44		       const char *name)
 45{
 46	char *tmp = NULL;
 47	char *tmpo;
 48	int ret;
 49	bool has_symbols;
 50
 51	/*
 52	 * We take copies first, because a failed apply can trash
 53	 * both the base blob and the overlay
 54	 */
 55	tmpo = xmalloc(fdt_totalsize(overlay));
 56
 57	do {
 58		tmp = xrealloc(tmp, *buf_len);
 59		ret = fdt_open_into(base, tmp, *buf_len);
 60		if (ret) {
 61			fprintf(stderr,
 62				"\nFailed to make temporary copy: %s\n",
 63				fdt_strerror(ret));
 64			goto fail;
 65		}
 66		ret = fdt_path_offset(tmp, "/__symbols__");
 67		has_symbols = ret >= 0;
 68
 69		memcpy(tmpo, overlay, fdt_totalsize(overlay));
 70
 71		ret = fdt_overlay_apply(tmp, tmpo);
 72		if (ret == -FDT_ERR_NOSPACE) {
 73			*buf_len += BUF_INCREMENT;
 74		}
 75	} while (ret == -FDT_ERR_NOSPACE);
 76
 77	if (ret) {
 78		fprintf(stderr, "\nFailed to apply '%s': %s\n",
 79			name, fdt_strerror(ret));
 80		if (!has_symbols) {
 81			fprintf(stderr,
 82				"base blob does not have a '/__symbols__' node, "
 83				"make sure you have compiled the base blob with '-@' option\n");
 84		}
 85		goto fail;
 86	}
 87
 88	free(base);
 89	free(tmpo);
 90	return tmp;
 91
 92fail:
 93	free(tmpo);
 94	if (tmp)
 95		free(tmp);
 96
 97	return NULL;
 98}
 99static int do_fdtoverlay(const char *input_filename,
100			 const char *output_filename,
101			 int argc, char *argv[])
102{
103	char *blob = NULL;
104	char **ovblob = NULL;
105	size_t buf_len;
106	int i, ret = -1;
107
108	blob = utilfdt_read(input_filename, &buf_len);
109	if (!blob) {
110		fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
111		goto out_err;
112	}
113	if (fdt_totalsize(blob) > buf_len) {
114		fprintf(stderr,
115 "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
116			(unsigned long)buf_len, fdt_totalsize(blob));
117		goto out_err;
118	}
119
120	/* allocate blob pointer array */
121	ovblob = xmalloc(sizeof(*ovblob) * argc);
122	memset(ovblob, 0, sizeof(*ovblob) * argc);
123
124	/* read and keep track of the overlay blobs */
125	for (i = 0; i < argc; i++) {
126		size_t ov_len;
127		ovblob[i] = utilfdt_read(argv[i], &ov_len);
128		if (!ovblob[i]) {
129			fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
130			goto out_err;
131		}
132		if (fdt_totalsize(ovblob[i]) > ov_len) {
133			fprintf(stderr,
134"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
135				argv[i], (unsigned long)ov_len,
136				fdt_totalsize(ovblob[i]));
137			goto out_err;
138		}
139	}
140
141	buf_len = fdt_totalsize(blob);
142
143	/* apply the overlays in sequence */
144	for (i = 0; i < argc; i++) {
145		blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
146		if (!blob)
147			goto out_err;
148	}
149
150	fdt_pack(blob);
151	ret = utilfdt_write(output_filename, blob);
152	if (ret)
153		fprintf(stderr, "\nFailed to write '%s'\n",
154			output_filename);
155
156out_err:
157	if (ovblob) {
158		for (i = 0; i < argc; i++) {
159			if (ovblob[i])
160				free(ovblob[i]);
161		}
162		free(ovblob);
163	}
164	free(blob);
165
166	return ret;
167}
168
169int main(int argc, char *argv[])
170{
171	int opt, i;
172	char *input_filename = NULL;
173	char *output_filename = NULL;
174
175	while ((opt = util_getopt_long()) != EOF) {
176		switch (opt) {
177		case_USAGE_COMMON_FLAGS
178
179		case 'i':
180			input_filename = optarg;
181			break;
182		case 'o':
183			output_filename = optarg;
184			break;
185		case 'v':
186			verbose = 1;
187			break;
188		}
189	}
190
191	if (!input_filename)
192		usage("missing input file");
193
194	if (!output_filename)
195		usage("missing output file");
196
197	argv += optind;
198	argc -= optind;
199
200	if (argc <= 0)
201		usage("missing overlay file(s)");
202
203	if (verbose) {
204		printf("input  = %s\n", input_filename);
205		printf("output = %s\n", output_filename);
206		for (i = 0; i < argc; i++)
207			printf("overlay[%d] = %s\n", i, argv[i]);
208	}
209
210	if (do_fdtoverlay(input_filename, output_filename, argc, argv))
211		return 1;
212
213	return 0;
214}
~/ Read-only file preview.