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