mdsetimage.c revision 1.22 1 /* $NetBSD: mdsetimage.c,v 1.22 2016/09/21 16:29:48 christos 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.22 2016/09/21 16:29:48 christos 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 <stdio.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 #include <string.h>
54
55 #include "bin.h"
56
57 #define CHUNKSIZE (64 * 1024)
58
59 static void usage(void) __attribute__((noreturn));
60
61 int verbose;
62 int extract;
63 int setsize;
64
65 static const char *progname;
66 #undef setprogname
67 #define setprogname(x) (void)(progname = (x))
68 #undef getprogname
69 #define getprogname() (progname)
70
71 int
72 main(int argc, char *argv[])
73 {
74 int ch, kfd, fsfd, rv;
75 struct stat ksb, fssb;
76 size_t md_root_image_offset, md_root_size_offset;
77 u_int32_t md_root_size_value;
78 const char *kfile, *fsfile;
79 char *mappedkfile;
80 char *bfdname = NULL;
81 void *bin;
82 ssize_t left_to_copy;
83 const char *md_root_image = "_md_root_image";
84 const char *md_root_size = "_md_root_size";
85 unsigned long text_start = ~0;
86
87 setprogname(argv[0]);
88
89 while ((ch = getopt(argc, argv, "I:S:b:svx")) != -1)
90 switch (ch) {
91 case 'I':
92 md_root_image = optarg;
93 break;
94 case 'S':
95 md_root_size = optarg;
96 break;
97 case 'T':
98 text_start = strtoul(optarg, NULL, 0);
99 break;
100 case 'b':
101 bfdname = optarg;
102 break;
103 case 's':
104 setsize = 1;
105 break;
106 case 'v':
107 verbose = 1;
108 break;
109 case 'x':
110 extract = 1;
111 break;
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 (extract) {
125 if ((kfd = open(kfile, O_RDONLY, 0)) == -1)
126 err(1, "open %s", kfile);
127 } else {
128 if ((kfd = open(kfile, O_RDWR, 0)) == -1)
129 err(1, "open %s", kfile);
130 }
131
132 if (fstat(kfd, &ksb) == -1)
133 err(1, "fstat %s", kfile);
134 if ((uintmax_t)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,
138 MAP_FILE | MAP_PRIVATE, kfd, 0)) == (caddr_t)-1)
139 err(1, "mmap %s", kfile);
140 if (verbose)
141 fprintf(stderr, "mapped %s\n", kfile);
142
143 bin = bin_open(kfd, kfile, bfdname);
144
145 if (bin_find_md_root(bin, mappedkfile, ksb.st_size, text_start,
146 md_root_image, md_root_size, &md_root_image_offset,
147 &md_root_size_offset, &md_root_size_value, verbose) != 0)
148 errx(1, "could not find symbols in %s", kfile);
149 if (verbose)
150 fprintf(stderr, "got symbols from %s\n", kfile);
151
152 if (verbose)
153 fprintf(stderr, "root @ %#zx/%u\n",
154 md_root_image_offset, md_root_size_value);
155
156 munmap(mappedkfile, ksb.st_size);
157
158 if (extract) {
159 if ((fsfd = open(fsfile, O_WRONLY|O_CREAT, 0777)) == -1)
160 err(1, "open %s", fsfile);
161 left_to_copy = md_root_size_value;
162 } else {
163 if ((fsfd = open(fsfile, O_RDONLY, 0)) == -1)
164 err(1, "open %s", fsfile);
165 if (fstat(fsfd, &fssb) == -1)
166 err(1, "fstat %s", fsfile);
167 if ((uintmax_t)fssb.st_size != (size_t)fssb.st_size)
168 errx(1, "fs image is too big");
169 if (fssb.st_size > md_root_size_value)
170 errx(1, "fs image (%td bytes) too big for buffer"
171 " (%u bytes)", fssb.st_size, md_root_size_value);
172 left_to_copy = fssb.st_size;
173 }
174
175 if (verbose)
176 fprintf(stderr, "copying image %s %s %s (%zd bytes)\n", fsfile,
177 (extract ? "from" : "into"), kfile, left_to_copy);
178
179 if (lseek(kfd, md_root_image_offset, SEEK_SET) !=
180 (off_t)md_root_image_offset)
181 err(1, "seek %s", kfile);
182 while (left_to_copy > 0) {
183 char buf[CHUNKSIZE];
184 ssize_t todo;
185 int rfd;
186 int wfd;
187 const char *rfile;
188 const char *wfile;
189 if (extract) {
190 rfd = kfd;
191 rfile = kfile;
192 wfd = fsfd;
193 wfile = fsfile;
194 } else {
195 rfd = fsfd;
196 rfile = fsfile;
197 wfd = kfd;
198 wfile = kfile;
199 }
200
201 todo = (left_to_copy > CHUNKSIZE) ? CHUNKSIZE : left_to_copy;
202 if ((rv = read(rfd, buf, todo)) != todo) {
203 if (rv == -1)
204 err(1, "read %s", rfile);
205 else
206 errx(1, "unexpected EOF reading %s", rfile);
207 }
208 if ((rv = write(wfd, buf, todo)) != todo) {
209 if (rv == -1)
210 err(1, "write %s", wfile);
211 else
212 errx(1, "short write writing %s", wfile);
213 }
214 left_to_copy -= todo;
215 }
216 if (verbose)
217 fprintf(stderr, "done copying image\n");
218 if (setsize && !extract) {
219 char buf[sizeof(uint32_t)];
220
221 if (verbose)
222 fprintf(stderr, "setting md_root_size to %llu\n",
223 (unsigned long long) fssb.st_size);
224 if (lseek(kfd, md_root_size_offset, SEEK_SET) !=
225 (off_t)md_root_size_offset)
226 err(1, "seek %s", kfile);
227 bin_put_32(bin, fssb.st_size, buf);
228 if (write(kfd, buf, sizeof(buf)) != sizeof(buf))
229 err(1, "write %s", kfile);
230 }
231
232 close(fsfd);
233 close(kfd);
234
235 if (verbose)
236 fprintf(stderr, "exiting\n");
237
238 bin_close(bin);
239 return 0;
240 }
241
242 static void
243 usage(void)
244 {
245 const char **list;
246
247 fprintf(stderr, "Usage: %s [-svx] [-b bfdname] [-I image_symbol] "
248 "[-S size_symbol] [-T address] kernel image\n", getprogname());
249 fprintf(stderr, "Supported targets:");
250 for (list = bin_supported_targets(); *list != NULL; list++)
251 fprintf(stderr, " %s", *list);
252 fprintf(stderr, "\n");
253 exit(1);
254 }
255