1 /* $NetBSD: mdsetimage.c,v 1.25 2020/06/14 18:24:21 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1996, 2002 Christopher G. Demetriou 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>> 30 */ 31 32 #if HAVE_NBTOOL_CONFIG_H 33 #include "nbtool_config.h" 34 #endif 35 36 #include <sys/cdefs.h> 37 #if !defined(lint) 38 __COPYRIGHT("@(#) Copyright (c) 1996\ 39 Christopher G. Demetriou. All rights reserved."); 40 __RCSID("$NetBSD: mdsetimage.c,v 1.25 2020/06/14 18:24:21 tsutsui Exp $"); 41 #endif /* not lint */ 42 43 #include <sys/types.h> 44 #include <sys/mman.h> 45 #include <sys/stat.h> 46 47 #include <err.h> 48 #include <fcntl.h> 49 #include <limits.h> 50 #include <stdint.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <string.h> 55 56 #include "bin.h" 57 58 #define CHUNKSIZE (64 * 1024) 59 60 static void usage(void) __attribute__((noreturn)); 61 62 int verbose; 63 int extract; 64 int setsize; 65 66 static const char *progname; 67 #undef setprogname 68 #define setprogname(x) (void)(progname = (x)) 69 #undef getprogname 70 #define getprogname() (progname) 71 72 int 73 main(int argc, char *argv[]) 74 { 75 int ch, kfd, fsfd, rv; 76 struct stat ksb, fssb; 77 size_t md_root_image_offset, md_root_size_offset; 78 u_int32_t md_root_size_value; 79 const char *kfile, *fsfile; 80 char *mappedkfile; 81 char *bfdname = NULL; 82 void *bin; 83 ssize_t left_to_copy; 84 const char *md_root_image = "_md_root_image"; 85 const char *md_root_size = "_md_root_size"; 86 unsigned long text_start = ~0; 87 88 setprogname(argv[0]); 89 90 while ((ch = getopt(argc, argv, "I:S:b:svx")) != -1) 91 switch (ch) { 92 case 'I': 93 md_root_image = optarg; 94 break; 95 case 'S': 96 md_root_size = optarg; 97 break; 98 case 'T': 99 text_start = strtoul(optarg, NULL, 0); 100 break; 101 case 'b': 102 bfdname = optarg; 103 break; 104 case 's': 105 setsize = 1; 106 break; 107 case 'v': 108 verbose = 1; 109 break; 110 case 'x': 111 extract = 1; 112 break; 113 case '?': 114 default: 115 usage(); 116 } 117 argc -= optind; 118 argv += optind; 119 120 if (argc != 2) 121 usage(); 122 kfile = argv[0]; 123 fsfile = argv[1]; 124 125 if (extract) { 126 if ((kfd = open(kfile, O_RDONLY, 0)) == -1) 127 err(1, "open %s", kfile); 128 } else { 129 if ((kfd = open(kfile, O_RDWR, 0)) == -1) 130 err(1, "open %s", kfile); 131 } 132 133 if (fstat(kfd, &ksb) == -1) 134 err(1, "fstat %s", kfile); 135 if ((uintmax_t)ksb.st_size != (size_t)ksb.st_size) 136 errx(1, "%s too big to map", kfile); 137 138 if ((mappedkfile = mmap(NULL, ksb.st_size, PROT_READ, 139 MAP_FILE | MAP_PRIVATE, kfd, 0)) == (caddr_t)-1) 140 err(1, "mmap %s", kfile); 141 if (verbose) 142 fprintf(stderr, "mapped %s\n", kfile); 143 144 bin = bin_open(kfd, kfile, bfdname); 145 146 if (bin_find_md_root(bin, mappedkfile, ksb.st_size, text_start, 147 md_root_image, md_root_size, &md_root_image_offset, 148 &md_root_size_offset, &md_root_size_value, verbose) != 0) 149 errx(1, "could not find symbols in %s", kfile); 150 if (verbose) 151 fprintf(stderr, "got symbols from %s\n", kfile); 152 153 if (verbose) 154 fprintf(stderr, "root @ %#zx/%u\n", 155 md_root_image_offset, md_root_size_value); 156 157 munmap(mappedkfile, ksb.st_size); 158 159 if (extract) { 160 if ((fsfd = open(fsfile, O_WRONLY|O_CREAT, 0777)) == -1) 161 err(1, "open %s", fsfile); 162 left_to_copy = md_root_size_value; 163 } else { 164 if ((fsfd = open(fsfile, O_RDONLY, 0)) == -1) 165 err(1, "open %s", fsfile); 166 if (fstat(fsfd, &fssb) == -1) 167 err(1, "fstat %s", fsfile); 168 if ((uintmax_t)fssb.st_size != (size_t)fssb.st_size) 169 errx(1, "fs image %s is too big", fsfile); 170 if (fssb.st_size > md_root_size_value) 171 errx(1, "fs image %s (%jd bytes) too big for buffer" 172 " (%u bytes)", fsfile, (intmax_t) fssb.st_size, 173 md_root_size_value); 174 left_to_copy = fssb.st_size; 175 } 176 177 if (verbose) 178 fprintf(stderr, "copying image %s %s %s (%zd bytes)\n", fsfile, 179 (extract ? "from" : "into"), kfile, left_to_copy); 180 181 if (lseek(kfd, md_root_image_offset, SEEK_SET) != 182 (off_t)md_root_image_offset) 183 err(1, "seek %s", kfile); 184 while (left_to_copy > 0) { 185 char buf[CHUNKSIZE]; 186 ssize_t todo; 187 int rfd; 188 int wfd; 189 const char *rfile; 190 const char *wfile; 191 if (extract) { 192 rfd = kfd; 193 rfile = kfile; 194 wfd = fsfd; 195 wfile = fsfile; 196 } else { 197 rfd = fsfd; 198 rfile = fsfile; 199 wfd = kfd; 200 wfile = kfile; 201 } 202 203 todo = (left_to_copy > CHUNKSIZE) ? CHUNKSIZE : left_to_copy; 204 if ((rv = read(rfd, buf, todo)) != todo) { 205 if (rv == -1) 206 err(1, "read %s", rfile); 207 else 208 errx(1, "unexpected EOF reading %s", rfile); 209 } 210 if ((rv = write(wfd, buf, todo)) != todo) { 211 if (rv == -1) 212 err(1, "write %s", wfile); 213 else 214 errx(1, "short write writing %s", wfile); 215 } 216 left_to_copy -= todo; 217 } 218 if (verbose) 219 fprintf(stderr, "done copying image\n"); 220 if (setsize && !extract) { 221 char buf[sizeof(uint32_t)]; 222 223 if (verbose) 224 fprintf(stderr, "setting md_root_size to %jd\n", 225 (intmax_t) fssb.st_size); 226 if (lseek(kfd, md_root_size_offset, SEEK_SET) != 227 (off_t)md_root_size_offset) 228 err(1, "seek %s", kfile); 229 bin_put_32(bin, fssb.st_size, buf); 230 if (write(kfd, buf, sizeof(buf)) != sizeof(buf)) 231 err(1, "write %s", kfile); 232 } 233 234 close(fsfd); 235 close(kfd); 236 237 if (verbose) 238 fprintf(stderr, "exiting\n"); 239 240 bin_close(bin); 241 return 0; 242 } 243 244 static void 245 usage(void) 246 { 247 const char **list; 248 249 fprintf(stderr, "Usage: %s [-svx] [-b bfdname] [-I image_symbol] " 250 "[-S size_symbol] [-T address] kernel image\n", getprogname()); 251 fprintf(stderr, "Supported targets:"); 252 for (list = bin_supported_targets(); *list != NULL; list++) 253 fprintf(stderr, " %s", *list); 254 fprintf(stderr, "\n"); 255 exit(1); 256 } 257