179edff12SRob Herring // SPDX-License-Identifier: GPL-2.0-or-later 279edff12SRob Herring /* 379edff12SRob Herring * Copyright (c) 2017 Konsulko Group Inc. All rights reserved. 479edff12SRob Herring * 579edff12SRob Herring * Author: 679edff12SRob Herring * Pantelis Antoniou <pantelis.antoniou@konsulko.com> 779edff12SRob Herring */ 879edff12SRob Herring 979edff12SRob Herring #include <assert.h> 1079edff12SRob Herring #include <ctype.h> 1179edff12SRob Herring #include <getopt.h> 1279edff12SRob Herring #include <stdio.h> 1379edff12SRob Herring #include <stdlib.h> 1479edff12SRob Herring #include <string.h> 1579edff12SRob Herring #include <inttypes.h> 1679edff12SRob Herring 1779edff12SRob Herring #include <libfdt.h> 1879edff12SRob Herring 1979edff12SRob Herring #include "util.h" 2079edff12SRob Herring 2179edff12SRob Herring #define BUF_INCREMENT 65536 2279edff12SRob Herring 2379edff12SRob Herring /* Usage related data. */ 2479edff12SRob Herring static const char usage_synopsis[] = 2579edff12SRob Herring "apply a number of overlays to a base blob\n" 2612d638f4SRob Herring (Arm) " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]"; 2779edff12SRob Herring static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS; 2879edff12SRob Herring static struct option const usage_long_opts[] = { 2979edff12SRob Herring {"input", required_argument, NULL, 'i'}, 3079edff12SRob Herring {"output", required_argument, NULL, 'o'}, 3179edff12SRob Herring {"verbose", no_argument, NULL, 'v'}, 3279edff12SRob Herring USAGE_COMMON_LONG_OPTS, 3379edff12SRob Herring }; 3479edff12SRob Herring static const char * const usage_opts_help[] = { 3579edff12SRob Herring "Input base DT blob", 3679edff12SRob Herring "Output DT blob", 3779edff12SRob Herring "Verbose messages", 3879edff12SRob Herring USAGE_COMMON_OPTS_HELP 3979edff12SRob Herring }; 4079edff12SRob Herring 4179edff12SRob Herring int verbose = 0; 4279edff12SRob Herring 4379edff12SRob Herring static void *apply_one(char *base, const char *overlay, size_t *buf_len, 4479edff12SRob Herring const char *name) 4579edff12SRob Herring { 4679edff12SRob Herring char *tmp = NULL; 4779edff12SRob Herring char *tmpo; 4879edff12SRob Herring int ret; 4979edff12SRob Herring 5079edff12SRob Herring /* 51*d2a97be3SRob Herring (Arm) * We take copies first, because a failed apply can trash 5279edff12SRob Herring * both the base blob and the overlay 5379edff12SRob Herring */ 5479edff12SRob Herring tmpo = xmalloc(fdt_totalsize(overlay)); 5579edff12SRob Herring 5679edff12SRob Herring do { 5779edff12SRob Herring tmp = xrealloc(tmp, *buf_len); 5879edff12SRob Herring ret = fdt_open_into(base, tmp, *buf_len); 5979edff12SRob Herring if (ret) { 6079edff12SRob Herring fprintf(stderr, 6179edff12SRob Herring "\nFailed to make temporary copy: %s\n", 6279edff12SRob Herring fdt_strerror(ret)); 6379edff12SRob Herring goto fail; 6479edff12SRob Herring } 6579edff12SRob Herring 6679edff12SRob Herring memcpy(tmpo, overlay, fdt_totalsize(overlay)); 6779edff12SRob Herring 6879edff12SRob Herring ret = fdt_overlay_apply(tmp, tmpo); 6979edff12SRob Herring if (ret == -FDT_ERR_NOSPACE) { 7079edff12SRob Herring *buf_len += BUF_INCREMENT; 7179edff12SRob Herring } 7279edff12SRob Herring } while (ret == -FDT_ERR_NOSPACE); 7379edff12SRob Herring 7479edff12SRob Herring if (ret) { 7579edff12SRob Herring fprintf(stderr, "\nFailed to apply '%s': %s\n", 7679edff12SRob Herring name, fdt_strerror(ret)); 7779edff12SRob Herring goto fail; 7879edff12SRob Herring } 7979edff12SRob Herring 8079edff12SRob Herring free(base); 8179edff12SRob Herring free(tmpo); 8279edff12SRob Herring return tmp; 8379edff12SRob Herring 8479edff12SRob Herring fail: 8579edff12SRob Herring free(tmpo); 8679edff12SRob Herring if (tmp) 8779edff12SRob Herring free(tmp); 8879edff12SRob Herring 8979edff12SRob Herring return NULL; 9079edff12SRob Herring } 9179edff12SRob Herring static int do_fdtoverlay(const char *input_filename, 9279edff12SRob Herring const char *output_filename, 9379edff12SRob Herring int argc, char *argv[]) 9479edff12SRob Herring { 9579edff12SRob Herring char *blob = NULL; 9679edff12SRob Herring char **ovblob = NULL; 9779edff12SRob Herring size_t buf_len; 9879edff12SRob Herring int i, ret = -1; 9979edff12SRob Herring 10079edff12SRob Herring blob = utilfdt_read(input_filename, &buf_len); 10179edff12SRob Herring if (!blob) { 10279edff12SRob Herring fprintf(stderr, "\nFailed to read '%s'\n", input_filename); 10379edff12SRob Herring goto out_err; 10479edff12SRob Herring } 10579edff12SRob Herring if (fdt_totalsize(blob) > buf_len) { 10679edff12SRob Herring fprintf(stderr, 10779edff12SRob Herring "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n", 10879edff12SRob Herring (unsigned long)buf_len, fdt_totalsize(blob)); 10979edff12SRob Herring goto out_err; 11079edff12SRob Herring } 11179edff12SRob Herring 11279edff12SRob Herring /* allocate blob pointer array */ 11379edff12SRob Herring ovblob = xmalloc(sizeof(*ovblob) * argc); 11479edff12SRob Herring memset(ovblob, 0, sizeof(*ovblob) * argc); 11579edff12SRob Herring 11679edff12SRob Herring /* read and keep track of the overlay blobs */ 11779edff12SRob Herring for (i = 0; i < argc; i++) { 11879edff12SRob Herring size_t ov_len; 11979edff12SRob Herring ovblob[i] = utilfdt_read(argv[i], &ov_len); 12079edff12SRob Herring if (!ovblob[i]) { 12179edff12SRob Herring fprintf(stderr, "\nFailed to read '%s'\n", argv[i]); 12279edff12SRob Herring goto out_err; 12379edff12SRob Herring } 12479edff12SRob Herring if (fdt_totalsize(ovblob[i]) > ov_len) { 12579edff12SRob Herring fprintf(stderr, 12679edff12SRob Herring "\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n", 12779edff12SRob Herring argv[i], (unsigned long)ov_len, 12879edff12SRob Herring fdt_totalsize(ovblob[i])); 12979edff12SRob Herring goto out_err; 13079edff12SRob Herring } 13179edff12SRob Herring } 13279edff12SRob Herring 13379edff12SRob Herring buf_len = fdt_totalsize(blob); 13479edff12SRob Herring 13579edff12SRob Herring /* apply the overlays in sequence */ 13679edff12SRob Herring for (i = 0; i < argc; i++) { 13779edff12SRob Herring blob = apply_one(blob, ovblob[i], &buf_len, argv[i]); 13879edff12SRob Herring if (!blob) 13979edff12SRob Herring goto out_err; 14079edff12SRob Herring } 14179edff12SRob Herring 14279edff12SRob Herring fdt_pack(blob); 14379edff12SRob Herring ret = utilfdt_write(output_filename, blob); 14479edff12SRob Herring if (ret) 14579edff12SRob Herring fprintf(stderr, "\nFailed to write '%s'\n", 14679edff12SRob Herring output_filename); 14779edff12SRob Herring 14879edff12SRob Herring out_err: 14979edff12SRob Herring if (ovblob) { 15079edff12SRob Herring for (i = 0; i < argc; i++) { 15179edff12SRob Herring if (ovblob[i]) 15279edff12SRob Herring free(ovblob[i]); 15379edff12SRob Herring } 15479edff12SRob Herring free(ovblob); 15579edff12SRob Herring } 15679edff12SRob Herring free(blob); 15779edff12SRob Herring 15879edff12SRob Herring return ret; 15979edff12SRob Herring } 16079edff12SRob Herring 16179edff12SRob Herring int main(int argc, char *argv[]) 16279edff12SRob Herring { 16379edff12SRob Herring int opt, i; 16479edff12SRob Herring char *input_filename = NULL; 16579edff12SRob Herring char *output_filename = NULL; 16679edff12SRob Herring 16779edff12SRob Herring while ((opt = util_getopt_long()) != EOF) { 16879edff12SRob Herring switch (opt) { 16979edff12SRob Herring case_USAGE_COMMON_FLAGS 17079edff12SRob Herring 17179edff12SRob Herring case 'i': 17279edff12SRob Herring input_filename = optarg; 17379edff12SRob Herring break; 17479edff12SRob Herring case 'o': 17579edff12SRob Herring output_filename = optarg; 17679edff12SRob Herring break; 17779edff12SRob Herring case 'v': 17879edff12SRob Herring verbose = 1; 17979edff12SRob Herring break; 18079edff12SRob Herring } 18179edff12SRob Herring } 18279edff12SRob Herring 18379edff12SRob Herring if (!input_filename) 18479edff12SRob Herring usage("missing input file"); 18579edff12SRob Herring 18679edff12SRob Herring if (!output_filename) 18779edff12SRob Herring usage("missing output file"); 18879edff12SRob Herring 18979edff12SRob Herring argv += optind; 19079edff12SRob Herring argc -= optind; 19179edff12SRob Herring 19279edff12SRob Herring if (argc <= 0) 19379edff12SRob Herring usage("missing overlay file(s)"); 19479edff12SRob Herring 19579edff12SRob Herring if (verbose) { 19679edff12SRob Herring printf("input = %s\n", input_filename); 19779edff12SRob Herring printf("output = %s\n", output_filename); 19879edff12SRob Herring for (i = 0; i < argc; i++) 19979edff12SRob Herring printf("overlay[%d] = %s\n", i, argv[i]); 20079edff12SRob Herring } 20179edff12SRob Herring 20279edff12SRob Herring if (do_fdtoverlay(input_filename, output_filename, argc, argv)) 20379edff12SRob Herring return 1; 20479edff12SRob Herring 20579edff12SRob Herring return 0; 20679edff12SRob Herring } 207