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