0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <assert.h>
0010 #include <ctype.h>
0011 #include <getopt.h>
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <string.h>
0015 #include <inttypes.h>
0016
0017 #include <libfdt.h>
0018
0019 #include "util.h"
0020
0021 #define BUF_INCREMENT 65536
0022
0023
0024 static const char usage_synopsis[] =
0025 "apply a number of overlays to a base blob\n"
0026 " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n"
0027 "\n"
0028 USAGE_TYPE_MSG;
0029 static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
0030 static struct option const usage_long_opts[] = {
0031 {"input", required_argument, NULL, 'i'},
0032 {"output", required_argument, NULL, 'o'},
0033 {"verbose", no_argument, NULL, 'v'},
0034 USAGE_COMMON_LONG_OPTS,
0035 };
0036 static const char * const usage_opts_help[] = {
0037 "Input base DT blob",
0038 "Output DT blob",
0039 "Verbose messages",
0040 USAGE_COMMON_OPTS_HELP
0041 };
0042
0043 int verbose = 0;
0044
0045 static void *apply_one(char *base, const char *overlay, size_t *buf_len,
0046 const char *name)
0047 {
0048 char *tmp = NULL;
0049 char *tmpo;
0050 int ret;
0051
0052
0053
0054
0055
0056 tmpo = xmalloc(fdt_totalsize(overlay));
0057
0058 do {
0059 tmp = xrealloc(tmp, *buf_len);
0060 ret = fdt_open_into(base, tmp, *buf_len);
0061 if (ret) {
0062 fprintf(stderr,
0063 "\nFailed to make temporary copy: %s\n",
0064 fdt_strerror(ret));
0065 goto fail;
0066 }
0067
0068 memcpy(tmpo, overlay, fdt_totalsize(overlay));
0069
0070 ret = fdt_overlay_apply(tmp, tmpo);
0071 if (ret == -FDT_ERR_NOSPACE) {
0072 *buf_len += BUF_INCREMENT;
0073 }
0074 } while (ret == -FDT_ERR_NOSPACE);
0075
0076 if (ret) {
0077 fprintf(stderr, "\nFailed to apply '%s': %s\n",
0078 name, fdt_strerror(ret));
0079 goto fail;
0080 }
0081
0082 free(base);
0083 free(tmpo);
0084 return tmp;
0085
0086 fail:
0087 free(tmpo);
0088 if (tmp)
0089 free(tmp);
0090
0091 return NULL;
0092 }
0093 static int do_fdtoverlay(const char *input_filename,
0094 const char *output_filename,
0095 int argc, char *argv[])
0096 {
0097 char *blob = NULL;
0098 char **ovblob = NULL;
0099 size_t buf_len;
0100 int i, ret = -1;
0101
0102 blob = utilfdt_read(input_filename, &buf_len);
0103 if (!blob) {
0104 fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
0105 goto out_err;
0106 }
0107 if (fdt_totalsize(blob) > buf_len) {
0108 fprintf(stderr,
0109 "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
0110 (unsigned long)buf_len, fdt_totalsize(blob));
0111 goto out_err;
0112 }
0113
0114
0115 ovblob = xmalloc(sizeof(*ovblob) * argc);
0116 memset(ovblob, 0, sizeof(*ovblob) * argc);
0117
0118
0119 for (i = 0; i < argc; i++) {
0120 size_t ov_len;
0121 ovblob[i] = utilfdt_read(argv[i], &ov_len);
0122 if (!ovblob[i]) {
0123 fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
0124 goto out_err;
0125 }
0126 if (fdt_totalsize(ovblob[i]) > ov_len) {
0127 fprintf(stderr,
0128 "\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
0129 argv[i], (unsigned long)ov_len,
0130 fdt_totalsize(ovblob[i]));
0131 goto out_err;
0132 }
0133 }
0134
0135 buf_len = fdt_totalsize(blob);
0136
0137
0138 for (i = 0; i < argc; i++) {
0139 blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
0140 if (!blob)
0141 goto out_err;
0142 }
0143
0144 fdt_pack(blob);
0145 ret = utilfdt_write(output_filename, blob);
0146 if (ret)
0147 fprintf(stderr, "\nFailed to write '%s'\n",
0148 output_filename);
0149
0150 out_err:
0151 if (ovblob) {
0152 for (i = 0; i < argc; i++) {
0153 if (ovblob[i])
0154 free(ovblob[i]);
0155 }
0156 free(ovblob);
0157 }
0158 free(blob);
0159
0160 return ret;
0161 }
0162
0163 int main(int argc, char *argv[])
0164 {
0165 int opt, i;
0166 char *input_filename = NULL;
0167 char *output_filename = NULL;
0168
0169 while ((opt = util_getopt_long()) != EOF) {
0170 switch (opt) {
0171 case_USAGE_COMMON_FLAGS
0172
0173 case 'i':
0174 input_filename = optarg;
0175 break;
0176 case 'o':
0177 output_filename = optarg;
0178 break;
0179 case 'v':
0180 verbose = 1;
0181 break;
0182 }
0183 }
0184
0185 if (!input_filename)
0186 usage("missing input file");
0187
0188 if (!output_filename)
0189 usage("missing output file");
0190
0191 argv += optind;
0192 argc -= optind;
0193
0194 if (argc <= 0)
0195 usage("missing overlay file(s)");
0196
0197 if (verbose) {
0198 printf("input = %s\n", input_filename);
0199 printf("output = %s\n", output_filename);
0200 for (i = 0; i < argc; i++)
0201 printf("overlay[%d] = %s\n", i, argv[i]);
0202 }
0203
0204 if (do_fdtoverlay(input_filename, output_filename, argc, argv))
0205 return 1;
0206
0207 return 0;
0208 }