1 /* 2 * Copyright (c) 2017 Konsulko Group Inc. All rights reserved. 3 * 4 * Author: 5 * Pantelis Antoniou <pantelis.antoniou (at) konsulko.com> 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * MA 02111-1307 USA 21 */ 22 23 #include <assert.h> 24 #include <ctype.h> 25 #include <getopt.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <alloca.h> 30 31 #include <libfdt.h> 32 33 #include "util.h" 34 35 /* Usage related data. */ 36 static const char usage_synopsis[] = 37 "apply a number of overlays to a base blob\n" 38 " fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]\n" 39 "\n" 40 USAGE_TYPE_MSG; 41 static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS; 42 static struct option const usage_long_opts[] = { 43 {"input", required_argument, NULL, 'i'}, 44 {"output", required_argument, NULL, 'o'}, 45 {"verbose", no_argument, NULL, 'v'}, 46 USAGE_COMMON_LONG_OPTS, 47 }; 48 static const char * const usage_opts_help[] = { 49 "Input base DT blob", 50 "Output DT blob", 51 "Verbose messages", 52 USAGE_COMMON_OPTS_HELP 53 }; 54 55 int verbose = 0; 56 57 static int do_fdtoverlay(const char *input_filename, 58 const char *output_filename, 59 int argc, char *argv[]) 60 { 61 char *blob = NULL; 62 char **ovblob = NULL; 63 off_t blob_len, ov_len, total_len; 64 int i, ret = -1; 65 66 blob = utilfdt_read_len(input_filename, &blob_len); 67 if (!blob) { 68 fprintf(stderr, "\nFailed to read base blob %s\n", 69 input_filename); 70 goto out_err; 71 } 72 ret = 0; 73 74 /* allocate blob pointer array */ 75 ovblob = alloca(sizeof(*ovblob) * argc); 76 memset(ovblob, 0, sizeof(*ovblob) * argc); 77 78 /* read and keep track of the overlay blobs */ 79 total_len = 0; 80 for (i = 0; i < argc; i++) { 81 ovblob[i] = utilfdt_read_len(argv[i], &ov_len); 82 if (!ovblob[i]) { 83 fprintf(stderr, "\nFailed to read overlay %s\n", 84 argv[i]); 85 goto out_err; 86 } 87 total_len += ov_len; 88 } 89 90 /* grow the blob to worst case */ 91 blob_len = fdt_totalsize(blob) + total_len; 92 blob = xrealloc(blob, blob_len); 93 fdt_open_into(blob, blob, blob_len); 94 95 /* apply the overlays in sequence */ 96 for (i = 0; i < argc; i++) { 97 ret = fdt_overlay_apply(blob, ovblob[i]); 98 if (ret) { 99 fprintf(stderr, "\nFailed to apply %s (%d)\n", 100 argv[i], ret); 101 goto out_err; 102 } 103 } 104 105 fdt_pack(blob); 106 ret = utilfdt_write(output_filename, blob); 107 if (ret) 108 fprintf(stderr, "\nFailed to write output blob %s\n", 109 output_filename); 110 111 out_err: 112 if (ovblob) { 113 for (i = 0; i < argc; i++) { 114 if (ovblob[i]) 115 free(ovblob[i]); 116 } 117 } 118 free(blob); 119 120 return ret; 121 } 122 123 int main(int argc, char *argv[]) 124 { 125 int opt, i; 126 char *input_filename = NULL; 127 char *output_filename = NULL; 128 129 while ((opt = util_getopt_long()) != EOF) { 130 switch (opt) { 131 case_USAGE_COMMON_FLAGS 132 133 case 'i': 134 input_filename = optarg; 135 break; 136 case 'o': 137 output_filename = optarg; 138 break; 139 case 'v': 140 verbose = 1; 141 break; 142 } 143 } 144 145 if (!input_filename) 146 usage("missing input file"); 147 148 if (!output_filename) 149 usage("missing output file"); 150 151 argv += optind; 152 argc -= optind; 153 154 if (argc <= 0) 155 usage("missing overlay file(s)"); 156 157 if (verbose) { 158 printf("input = %s\n", input_filename); 159 printf("output = %s\n", output_filename); 160 for (i = 0; i < argc; i++) 161 printf("overlay[%d] = %s\n", i, argv[i]); 162 } 163 164 if (do_fdtoverlay(input_filename, output_filename, argc, argv)) 165 return 1; 166 167 return 0; 168 } 169