1 /* $NetBSD: mdsetimage.c,v 1.15 2001/03/21 23:46:48 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1996 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the 18 * NetBSD Project. See http://www.netbsd.org/ for 19 * information about NetBSD. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * 34 * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>> 35 */ 36 37 #include <sys/cdefs.h> 38 #ifndef lint 39 __COPYRIGHT( 40 "@(#) Copyright (c) 1996 Christopher G. Demetriou.\ 41 All rights reserved.\n"); 42 #endif /* not lint */ 43 44 #ifndef lint 45 __RCSID("$NetBSD: mdsetimage.c,v 1.15 2001/03/21 23:46:48 cgd Exp $"); 46 #endif /* not lint */ 47 48 #include <sys/types.h> 49 #include <sys/mman.h> 50 #include <sys/stat.h> 51 52 #include <err.h> 53 #include <fcntl.h> 54 #include <limits.h> 55 #include <nlist.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 60 #include "extern.h" 61 62 int main __P((int, char *[])); 63 static void usage __P((void)) __attribute__((noreturn)); 64 static int find_md_root __P((const char *, const char *, size_t, 65 const struct nlist *, size_t *, u_int32_t *)); 66 67 static struct nlist md_root_nlist[] = { 68 #define X_MD_ROOT_IMAGE 0 69 { "_md_root_image" }, 70 #define X_MD_ROOT_SIZE 1 71 { "_md_root_size" }, 72 { NULL } 73 }; 74 75 int verbose; 76 #ifdef NLIST_AOUT 77 /* 78 * Since we can't get the text address from an a.out executable, we 79 * need to be able to specify it. Note: there's no way to test to 80 * see if the user entered a valid address! 81 */ 82 int T_flag_specified; /* the -T flag was specified */ 83 u_long text_start; /* Start of kernel text */ 84 #endif /* NLIST_AOUT */ 85 86 int 87 main(argc, argv) 88 int argc; 89 char *argv[]; 90 { 91 struct stat ksb, fssb; 92 size_t md_root_offset; 93 u_int32_t md_root_size; 94 const char *kfile, *fsfile; 95 char *mappedkfile; 96 int ch, kfd, fsfd, rv; 97 98 setprogname(argv[0]); 99 100 while ((ch = getopt(argc, argv, "T:v")) != -1) 101 switch (ch) { 102 case 'v': 103 verbose = 1; 104 break; 105 case 'T': 106 #ifdef NLIST_AOUT 107 T_flag_specified = 1; 108 text_start = strtoul(optarg, NULL, 0); 109 break; 110 #endif /* NLIST_AOUT */ 111 /* FALLTHROUGH */ 112 case '?': 113 default: 114 usage(); 115 } 116 argc -= optind; 117 argv += optind; 118 119 if (argc != 2) 120 usage(); 121 kfile = argv[0]; 122 fsfile = argv[1]; 123 124 if ((kfd = open(kfile, O_RDWR, 0)) == -1) 125 err(1, "open %s", kfile); 126 127 if ((rv = __fdnlist(kfd, md_root_nlist)) != 0) 128 errx(1, "could not find symbols in %s", kfile); 129 if (verbose) 130 fprintf(stderr, "got symbols from %s\n", kfile); 131 132 if (fstat(kfd, &ksb) == -1) 133 err(1, "fstat %s", kfile); 134 if (ksb.st_size != (size_t)ksb.st_size) 135 errx(1, "%s too big to map", kfile); 136 137 if ((mappedkfile = mmap(NULL, ksb.st_size, PROT_READ | PROT_WRITE, 138 MAP_FILE | MAP_SHARED, kfd, 0)) == (caddr_t)-1) 139 err(1, "mmap %s", kfile); 140 if (verbose) 141 fprintf(stderr, "mapped %s\n", kfile); 142 143 if (find_md_root(kfile, mappedkfile, ksb.st_size, md_root_nlist, 144 &md_root_offset, &md_root_size) != 0) 145 errx(1, "could not find md root buffer in %s", kfile); 146 147 if ((fsfd = open(fsfile, O_RDONLY, 0)) == -1) 148 err(1, "open %s", fsfile); 149 if (fstat(fsfd, &fssb) == -1) 150 err(1, "fstat %s", fsfile); 151 if (fssb.st_size != (size_t)fssb.st_size) 152 errx(1, "fs image is too big"); 153 if (fssb.st_size > md_root_size) 154 errx(1, "fs image (%lld bytes) too big for buffer (%lu bytes)", 155 (long long)fssb.st_size, (unsigned long)md_root_size); 156 157 if (verbose) 158 fprintf(stderr, "copying image from %s into %s\n", fsfile, 159 kfile); 160 if ((rv = read(fsfd, mappedkfile + md_root_offset, 161 fssb.st_size)) != fssb.st_size) { 162 if (rv == -1) 163 err(1, "read %s", fsfile); 164 else 165 errx(1, "unexpected EOF reading %s", fsfile); 166 } 167 if (verbose) 168 fprintf(stderr, "done copying image\n"); 169 170 close(fsfd); 171 172 munmap(mappedkfile, ksb.st_size); 173 close(kfd); 174 175 if (verbose) 176 fprintf(stderr, "exiting\n"); 177 exit(0); 178 } 179 180 static void 181 usage() 182 { 183 184 fprintf(stderr, 185 "usage: %s kernel_file fsimage_file\n", 186 getprogname()); 187 exit(1); 188 } 189 190 191 struct { 192 const char *name; 193 int (*check) __P((const char *, size_t)); 194 int (*findoff) __P((const char *, size_t, u_long, size_t *)); 195 } exec_formats[] = { 196 #ifdef NLIST_AOUT 197 { "a.out", check_aout, findoff_aout, }, 198 #endif 199 #ifdef NLIST_ECOFF 200 { "ECOFF", check_ecoff, findoff_ecoff, }, 201 #endif 202 #ifdef NLIST_ELF32 203 { "ELF32", check_elf32, findoff_elf32, }, 204 #endif 205 #ifdef NLIST_ELF64 206 { "ELF64", check_elf64, findoff_elf64, }, 207 #endif 208 #ifdef NLIST_COFF 209 { "COFF", check_coff, findoff_coff, }, 210 #endif 211 }; 212 213 static int 214 find_md_root(fname, mappedfile, mappedsize, nl, rootoffp, rootsizep) 215 const char *fname, *mappedfile; 216 size_t mappedsize; 217 const struct nlist *nl; 218 size_t *rootoffp; 219 u_int32_t *rootsizep; 220 { 221 int i, n; 222 size_t rootsizeoff; 223 224 n = sizeof exec_formats / sizeof exec_formats[0]; 225 for (i = 0; i < n; i++) { 226 if ((*exec_formats[i].check)(mappedfile, mappedsize) == 0) 227 break; 228 } 229 if (i == n) { 230 warnx("%s: unknown executable format", fname); 231 return (1); 232 } 233 234 if (verbose) { 235 fprintf(stderr, "%s is an %s binary\n", fname, 236 exec_formats[i].name); 237 #ifdef NLIST_AOUT 238 if (T_flag_specified) 239 fprintf(stderr, "kernel text loads at 0x%lx\n", 240 text_start); 241 #endif 242 } 243 244 if ((*exec_formats[i].findoff)(mappedfile, mappedsize, 245 nl[X_MD_ROOT_SIZE].n_value, &rootsizeoff) != 0) { 246 warnx("couldn't find offset for %s in %s", 247 nl[X_MD_ROOT_SIZE].n_name, fname); 248 return (1); 249 } 250 if (verbose) 251 fprintf(stderr, "%s is at offset %#lx in %s\n", 252 nl[X_MD_ROOT_SIZE].n_name, 253 (unsigned long)rootsizeoff, fname); 254 *rootsizep = *(u_int32_t *)&mappedfile[rootsizeoff]; 255 if (verbose) 256 fprintf(stderr, "%s has value %#x\n", 257 nl[X_MD_ROOT_SIZE].n_name, *rootsizep); 258 259 if ((*exec_formats[i].findoff)(mappedfile, mappedsize, 260 nl[X_MD_ROOT_IMAGE].n_value, rootoffp) != 0) { 261 warnx("couldn't find offset for %s in %s", 262 nl[X_MD_ROOT_IMAGE].n_name, fname); 263 return (1); 264 } 265 if (verbose) 266 fprintf(stderr, "%s is at offset %#lx in %s\n", 267 nl[X_MD_ROOT_IMAGE].n_name, 268 (unsigned long)(*rootoffp), fname); 269 270 return (0); 271 } 272