]> Git Repo - linux.git/blob - scripts/dtc/fdtoverlay.c
Linux 6.14-rc3
[linux.git] / scripts / dtc / fdtoverlay.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 <[email protected]>
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. */
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,
33 };
34 static 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
41 int verbose = 0;
42
43 static 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
50         /*
51          * We take copies first, because a failed apply can trash
52          * both the base blob and the overlay
53          */
54         tmpo = xmalloc(fdt_totalsize(overlay));
55
56         do {
57                 tmp = xrealloc(tmp, *buf_len);
58                 ret = fdt_open_into(base, tmp, *buf_len);
59                 if (ret) {
60                         fprintf(stderr,
61                                 "\nFailed to make temporary copy: %s\n",
62                                 fdt_strerror(ret));
63                         goto fail;
64                 }
65
66                 memcpy(tmpo, overlay, fdt_totalsize(overlay));
67
68                 ret = fdt_overlay_apply(tmp, tmpo);
69                 if (ret == -FDT_ERR_NOSPACE) {
70                         *buf_len += BUF_INCREMENT;
71                 }
72         } while (ret == -FDT_ERR_NOSPACE);
73
74         if (ret) {
75                 fprintf(stderr, "\nFailed to apply '%s': %s\n",
76                         name, fdt_strerror(ret));
77                 goto fail;
78         }
79
80         free(base);
81         free(tmpo);
82         return tmp;
83
84 fail:
85         free(tmpo);
86         if (tmp)
87                 free(tmp);
88
89         return NULL;
90 }
91 static int do_fdtoverlay(const char *input_filename,
92                          const char *output_filename,
93                          int argc, char *argv[])
94 {
95         char *blob = NULL;
96         char **ovblob = NULL;
97         size_t buf_len;
98         int i, ret = -1;
99
100         blob = utilfdt_read(input_filename, &buf_len);
101         if (!blob) {
102                 fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
103                 goto out_err;
104         }
105         if (fdt_totalsize(blob) > buf_len) {
106                 fprintf(stderr,
107  "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
108                         (unsigned long)buf_len, fdt_totalsize(blob));
109                 goto out_err;
110         }
111
112         /* allocate blob pointer array */
113         ovblob = xmalloc(sizeof(*ovblob) * argc);
114         memset(ovblob, 0, sizeof(*ovblob) * argc);
115
116         /* read and keep track of the overlay blobs */
117         for (i = 0; i < argc; i++) {
118                 size_t ov_len;
119                 ovblob[i] = utilfdt_read(argv[i], &ov_len);
120                 if (!ovblob[i]) {
121                         fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
122                         goto out_err;
123                 }
124                 if (fdt_totalsize(ovblob[i]) > ov_len) {
125                         fprintf(stderr,
126 "\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
127                                 argv[i], (unsigned long)ov_len,
128                                 fdt_totalsize(ovblob[i]));
129                         goto out_err;
130                 }
131         }
132
133         buf_len = fdt_totalsize(blob);
134
135         /* apply the overlays in sequence */
136         for (i = 0; i < argc; i++) {
137                 blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
138                 if (!blob)
139                         goto out_err;
140         }
141
142         fdt_pack(blob);
143         ret = utilfdt_write(output_filename, blob);
144         if (ret)
145                 fprintf(stderr, "\nFailed to write '%s'\n",
146                         output_filename);
147
148 out_err:
149         if (ovblob) {
150                 for (i = 0; i < argc; i++) {
151                         if (ovblob[i])
152                                 free(ovblob[i]);
153                 }
154                 free(ovblob);
155         }
156         free(blob);
157
158         return ret;
159 }
160
161 int main(int argc, char *argv[])
162 {
163         int opt, i;
164         char *input_filename = NULL;
165         char *output_filename = NULL;
166
167         while ((opt = util_getopt_long()) != EOF) {
168                 switch (opt) {
169                 case_USAGE_COMMON_FLAGS
170
171                 case 'i':
172                         input_filename = optarg;
173                         break;
174                 case 'o':
175                         output_filename = optarg;
176                         break;
177                 case 'v':
178                         verbose = 1;
179                         break;
180                 }
181         }
182
183         if (!input_filename)
184                 usage("missing input file");
185
186         if (!output_filename)
187                 usage("missing output file");
188
189         argv += optind;
190         argc -= optind;
191
192         if (argc <= 0)
193                 usage("missing overlay file(s)");
194
195         if (verbose) {
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]);
200         }
201
202         if (do_fdtoverlay(input_filename, output_filename, argc, argv))
203                 return 1;
204
205         return 0;
206 }
This page took 0.03986 seconds and 4 git commands to generate.