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