pmax.c revision 1.5 1 /* $NetBSD: pmax.c,v 1.5 2002/04/25 18:11:54 tv Exp $ */
2
3 /*-
4 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Simon Burge.
9 *
10 * This code is derived from software contributed to The NetBSD Foundation
11 * by Luke Mewburn of Wasabi Systems.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the NetBSD
24 * Foundation, Inc. and its contributors.
25 * 4. Neither the name of The NetBSD Foundation nor the names of its
26 * contributors may be used to endorse or promote products derived
27 * from this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 /*
43 * Copyright (c) 1999 Ross Harvey. All rights reserved.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by Ross Harvey
56 * for the NetBSD Project.
57 * 4. The name of the author may not be used to endorse or promote products
58 * derived from this software without specific prior written permission
59 *
60 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
61 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
62 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
63 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
64 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
65 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
66 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
67 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
68 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
69 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
70 */
71
72 /*
73 * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
74 *
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
77 * are met:
78 * 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer.
80 * 2. Redistributions in binary form must reproduce the above copyright
81 * notice, this list of conditions and the following disclaimer in the
82 * documentation and/or other materials provided with the distribution.
83 * 3. All advertising materials mentioning features or use of this software
84 * must display the following acknowledgement:
85 * This product includes software developed by Christopher G. Demetriou
86 * for the NetBSD Project.
87 * 4. The name of the author may not be used to endorse or promote products
88 * derived from this software without specific prior written permission
89 *
90 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
91 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
92 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
93 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
94 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
95 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
96 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
97 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
98 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
99 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
100 */
101
102 #include <sys/cdefs.h>
103 #if defined(__RCSID) && !defined(__lint)
104 __RCSID("$NetBSD: pmax.c,v 1.5 2002/04/25 18:11:54 tv Exp $");
105 #endif /* !__lint */
106
107 #if HAVE_CONFIG_H
108 #include "config.h"
109 #endif
110
111 #include <sys/param.h>
112 #include <sys/stat.h>
113
114 #include <assert.h>
115 #include <err.h>
116 #include <stddef.h>
117 #include <stdio.h>
118 #include <stdlib.h>
119 #include <string.h>
120 #include <unistd.h>
121
122 #include <sys/exec_elf.h>
123 #if HAVE_CONFIG_H
124 #include "../../sys/dev/dec/dec_boot.h"
125 #else
126 #include <dev/dec/dec_boot.h>
127 #endif
128
129 #include "installboot.h"
130
131 static int load_bootstrap(ib_params *, char **,
132 uint32_t *, uint32_t *, size_t *);
133
134
135 int
136 pmax_parseopt(ib_params *params, const char *option)
137 {
138
139 if (parseoptionflag(params, option, IB_APPEND | IB_SUNSUM))
140 return (1);
141
142 warnx("Unknown -o option `%s'", option);
143 return (0);
144 }
145
146 int
147 pmax_clearboot(ib_params *params)
148 {
149 struct pmax_boot_block bb;
150 ssize_t rv;
151
152 assert(params != NULL);
153 assert(params->fsfd != -1);
154 assert(params->filesystem != NULL);
155 assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
156
157 if (params->flags & (IB_STARTBLOCK | IB_APPEND)) {
158 warnx("Can't use `-b bno' or `-o append' with `-c'");
159 return (0);
160 }
161 rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
162 if (rv == -1) {
163 warn("Reading `%s'", params->filesystem);
164 return (0);
165 } else if (rv != sizeof(bb)) {
166 warnx("Reading `%s': short read", params->filesystem);
167 return (0);
168 }
169
170 if (le32toh(bb.magic) != PMAX_BOOT_MAGIC) {
171 warnx(
172 "Old boot block magic number invalid; boot block invalid");
173 return (0);
174 }
175
176 bb.map[0].num_blocks = bb.map[0].start_block = bb.mode = 0;
177 bb.magic = htole32(PMAX_BOOT_MAGIC);
178
179 if (params->flags & IB_SUNSUM) {
180 uint16_t sum;
181
182 sum = compute_sunsum((uint16_t *)&bb);
183 if (! set_sunsum(params, (uint16_t *)&bb, sum))
184 return (0);
185 }
186
187 if (params->flags & IB_VERBOSE)
188 printf("%slearing boot block\n",
189 (params->flags & IB_NOWRITE) ? "Not c" : "C");
190 if (params->flags & IB_NOWRITE)
191 return (1);
192
193 rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
194 if (rv == -1) {
195 warn("Writing `%s'", params->filesystem);
196 return (0);
197 } else if (rv != sizeof(bb)) {
198 warnx("Writing `%s': short write", params->filesystem);
199 return (0);
200 }
201
202 return (1);
203 }
204
205 int
206 pmax_setboot(ib_params *params)
207 {
208 struct stat bootstrapsb;
209 struct pmax_boot_block bb;
210 uint32_t startblock;
211 int retval;
212 char *bootstrapbuf;
213 size_t bootstrapsize;
214 uint32_t bootstrapload, bootstrapexec;
215 ssize_t rv;
216
217 assert(params != NULL);
218 assert(params->fsfd != -1);
219 assert(params->filesystem != NULL);
220 assert(params->s1fd != -1);
221 assert(params->stage1 != NULL);
222 assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
223
224 retval = 0;
225 bootstrapbuf = NULL;
226
227 if ((params->flags & IB_STARTBLOCK) &&
228 (params->flags & IB_APPEND)) {
229 warnx("Can't use `-b bno' with `-o append'");
230 goto done;
231 }
232
233 if (fstat(params->s1fd, &bootstrapsb) == -1) {
234 warn("Examining `%s'", params->stage1);
235 goto done;
236 }
237 if (!S_ISREG(bootstrapsb.st_mode)) {
238 warnx("`%s' must be a regular file", params->stage1);
239 goto done;
240 }
241 if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
242 &bootstrapexec, &bootstrapsize))
243 goto done;
244
245 rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
246 if (rv == -1) {
247 warn("Reading `%s'", params->filesystem);
248 goto done;
249 } else if (rv != sizeof(bb)) {
250 warnx("Reading `%s': short read", params->filesystem);
251 goto done;
252 }
253
254 /* fill in the updated boot block fields */
255 if (params->flags & IB_APPEND) {
256 struct stat filesyssb;
257
258 if (fstat(params->fsfd, &filesyssb) == -1) {
259 warn("Examining `%s'", params->filesystem);
260 goto done;
261 }
262 if (!S_ISREG(filesyssb.st_mode)) {
263 warnx(
264 "`%s' must be a regular file to append a bootstrap",
265 params->filesystem);
266 goto done;
267 }
268 startblock = howmany(filesyssb.st_size,
269 PMAX_BOOT_BLOCK_BLOCKSIZE);
270 } else if (params->flags & IB_STARTBLOCK) {
271 startblock = params->startblock;
272 } else {
273 startblock = PMAX_BOOT_BLOCK_OFFSET / PMAX_BOOT_BLOCK_BLOCKSIZE
274 + 1;
275 }
276
277 bb.map[0].start_block = htole32(startblock);
278 bb.map[0].num_blocks =
279 htole32(howmany(bootstrapsize, PMAX_BOOT_BLOCK_BLOCKSIZE));
280 bb.magic = htole32(PMAX_BOOT_MAGIC);
281 bb.load_addr = htole32(bootstrapload);
282 bb.exec_addr = htole32(bootstrapexec);
283 bb.mode = htole32(PMAX_BOOTMODE_CONTIGUOUS);
284
285 if (params->flags & IB_SUNSUM) {
286 uint16_t sum;
287
288 sum = compute_sunsum((uint16_t *)&bb);
289 if (! set_sunsum(params, (uint16_t *)&bb, sum))
290 goto done;
291 }
292
293 if (params->flags & IB_VERBOSE) {
294 printf("Bootstrap start sector: %#x\n",
295 le32toh(bb.map[0].start_block));
296 printf("Bootstrap sector count: %#x\n",
297 le32toh(bb.map[0].num_blocks));
298 printf("Bootstrap load address: %#x\n",
299 le32toh(bb.load_addr));
300 printf("Bootstrap exec address: %#x\n",
301 le32toh(bb.exec_addr));
302 printf("%sriting bootstrap\n",
303 (params->flags & IB_NOWRITE) ? "Not w" : "W");
304 }
305 if (params->flags & IB_NOWRITE) {
306 retval = 1;
307 goto done;
308 }
309 rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
310 startblock * PMAX_BOOT_BLOCK_BLOCKSIZE);
311 if (rv == -1) {
312 warn("Writing `%s'", params->filesystem);
313 goto done;
314 } else if (rv != bootstrapsize) {
315 warnx("Writing `%s': short write", params->filesystem);
316 goto done;
317 }
318
319 if (params->flags & IB_VERBOSE)
320 printf("Writing boot block\n");
321 rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
322 if (rv == -1) {
323 warn("Writing `%s'", params->filesystem);
324 goto done;
325 } else if (rv != sizeof(bb)) {
326 warnx("Writing `%s': short write", params->filesystem);
327 goto done;
328 } else {
329 retval = 1;
330 }
331
332 done:
333 if (bootstrapbuf)
334 free(bootstrapbuf);
335 return (retval);
336 }
337
338
339 #define MAX_SEGMENTS 10 /* We can load up to 10 segments */
340
341 struct seglist {
342 Elf32_Addr addr;
343 Elf32_Off f_offset;
344 Elf32_Word f_size;
345 };
346
347 static int
348 load_bootstrap(ib_params *params, char **data,
349 uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
350 {
351 int i, nsegs;
352 Elf32_Addr lowaddr, highaddr;
353 Elf32_Ehdr ehdr;
354 Elf32_Phdr phdr;
355 struct seglist seglist[MAX_SEGMENTS];
356
357 if ((pread(params->s1fd, &ehdr, sizeof(ehdr), 0)) != sizeof(ehdr)) {
358 warn("Reading `%s'", params->stage1);
359 return (0);
360 }
361 if ((memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) ||
362 (ehdr.e_ident[EI_CLASS] != ELFCLASS32)) {
363 warnx("No ELF header in `%s'", params->stage1);
364 return (0);
365 }
366
367 nsegs = highaddr = 0;
368 lowaddr = (uint32_t) ULONG_MAX;
369
370 for (i = 0; i < le16toh(ehdr.e_phnum); i++) {
371 if (pread(params->s1fd, &phdr, sizeof(phdr),
372 (off_t) le32toh(ehdr.e_phoff) + i * sizeof(phdr))
373 != sizeof(phdr)) {
374 warn("Reading `%s'", params->stage1);
375 return (0);
376 }
377 if (le32toh(phdr.p_type) != PT_LOAD)
378 continue;
379
380 seglist[nsegs].addr = le32toh(phdr.p_paddr);
381 seglist[nsegs].f_offset = le32toh(phdr.p_offset);
382 seglist[nsegs].f_size = le32toh(phdr.p_filesz);
383 nsegs++;
384
385 if (le32toh(phdr.p_paddr) < lowaddr)
386 lowaddr = le32toh(phdr.p_paddr);
387 if (le32toh(phdr.p_paddr) + le32toh(phdr.p_filesz) > highaddr)
388 highaddr = le32toh(phdr.p_paddr) +
389 le32toh(phdr.p_filesz);
390 }
391
392 *loadaddr = lowaddr;
393 *execaddr = le32toh(ehdr.e_entry);
394 *len = roundup(highaddr - lowaddr, PMAX_BOOT_BLOCK_BLOCKSIZE);
395 if ((*data = malloc(*len)) == NULL) {
396 warn("Allocating %lu bytes", (unsigned long) *len);
397 return (0);
398 }
399
400 /* Now load the bootstrap into memory */
401 for (i = 0; i < nsegs; i++) {
402 if (pread(params->s1fd, *data + seglist[i].addr - lowaddr,
403 seglist[i].f_size, (off_t)seglist[i].f_offset)
404 != seglist[i].f_size) {
405 warn("Reading `%s'", params->stage1);
406 return (0);
407 }
408 }
409 return (1);
410 }
411