pmax.c revision 1.9 1 /* $NetBSD: pmax.c,v 1.9 2002/05/15 02:18:23 lukem 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.9 2002/05/15 02:18:23 lukem Exp $");
105 #endif /* !__lint */
106
107 #if HAVE_CONFIG_H
108 #include "config.h"
109 #endif
110
111 #include <sys/param.h>
112
113 #include <assert.h>
114 #include <err.h>
115 #include <stddef.h>
116 #include <stdio.h>
117 #include <stdlib.h>
118 #include <string.h>
119 #include <unistd.h>
120
121 #include <sys/exec_elf.h>
122
123 #include "installboot.h"
124
125 static int load_bootstrap(ib_params *, char **,
126 uint32_t *, uint32_t *, size_t *);
127
128
129 int
130 pmax_parseopt(ib_params *params, const char *option)
131 {
132
133 if (parseoptionflag(params, option, IB_APPEND | IB_SUNSUM))
134 return (1);
135
136 warnx("Unknown -o option `%s'", option);
137 return (0);
138 }
139
140 int
141 pmax_clearboot(ib_params *params)
142 {
143 struct pmax_boot_block bb;
144 ssize_t rv;
145
146 assert(params != NULL);
147 assert(params->fsfd != -1);
148 assert(params->filesystem != NULL);
149 assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
150
151 if (params->flags & (IB_STAGE1START | IB_APPEND)) {
152 warnx("Can't use `-b bno' or `-o append' with `-c'");
153 return (0);
154 }
155 if (params->flags & IB_STAGE2START) {
156 warnx("`-B bno' is not supported for %s",
157 params->machine->name);
158 return (0);
159 }
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 pmax_boot_block bb;
209 uint32_t startblock;
210 int retval;
211 char *bootstrapbuf;
212 size_t bootstrapsize;
213 uint32_t bootstrapload, bootstrapexec;
214 ssize_t rv;
215
216 assert(params != NULL);
217 assert(params->fsfd != -1);
218 assert(params->filesystem != NULL);
219 assert(params->s1fd != -1);
220 assert(params->stage1 != NULL);
221 assert(sizeof(struct pmax_boot_block) == PMAX_BOOT_BLOCK_BLOCKSIZE);
222
223 retval = 0;
224 bootstrapbuf = NULL;
225
226 if ((params->flags & IB_STAGE1START) &&
227 (params->flags & IB_APPEND)) {
228 warnx("Can't use `-b bno' with `-o append'");
229 goto done;
230 }
231 if (params->flags & IB_STAGE2START) {
232 warnx("`-B bno' is not supported for %s",
233 params->machine->name);
234 goto done;
235 }
236
237 if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
238 &bootstrapexec, &bootstrapsize))
239 goto done;
240
241 rv = pread(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
242 if (rv == -1) {
243 warn("Reading `%s'", params->filesystem);
244 goto done;
245 } else if (rv != sizeof(bb)) {
246 warnx("Reading `%s': short read", params->filesystem);
247 goto done;
248 }
249
250 /* fill in the updated boot block fields */
251 if (params->flags & IB_APPEND) {
252 if (! S_ISREG(params->fsstat.st_mode)) {
253 warnx(
254 "`%s' must be a regular file to append a bootstrap",
255 params->filesystem);
256 goto done;
257 }
258 startblock = howmany(params->fsstat.st_size,
259 PMAX_BOOT_BLOCK_BLOCKSIZE);
260 } else if (params->flags & IB_STAGE1START) {
261 startblock = params->s1start;
262 } else {
263 startblock = PMAX_BOOT_BLOCK_OFFSET / PMAX_BOOT_BLOCK_BLOCKSIZE
264 + 1;
265 }
266
267 bb.map[0].start_block = htole32(startblock);
268 bb.map[0].num_blocks =
269 htole32(howmany(bootstrapsize, PMAX_BOOT_BLOCK_BLOCKSIZE));
270 bb.magic = htole32(PMAX_BOOT_MAGIC);
271 bb.load_addr = htole32(bootstrapload);
272 bb.exec_addr = htole32(bootstrapexec);
273 bb.mode = htole32(PMAX_BOOTMODE_CONTIGUOUS);
274
275 if (params->flags & IB_SUNSUM) {
276 uint16_t sum;
277
278 sum = compute_sunsum((uint16_t *)&bb);
279 if (! set_sunsum(params, (uint16_t *)&bb, sum))
280 goto done;
281 }
282
283 if (params->flags & IB_VERBOSE) {
284 printf("Bootstrap start sector: %u\n",
285 le32toh(bb.map[0].start_block));
286 printf("Bootstrap sector count: %u\n",
287 le32toh(bb.map[0].num_blocks));
288 printf("Bootstrap load address: %#x\n",
289 le32toh(bb.load_addr));
290 printf("Bootstrap exec address: %#x\n",
291 le32toh(bb.exec_addr));
292 printf("%sriting bootstrap\n",
293 (params->flags & IB_NOWRITE) ? "Not w" : "W");
294 }
295 if (params->flags & IB_NOWRITE) {
296 retval = 1;
297 goto done;
298 }
299 rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
300 startblock * PMAX_BOOT_BLOCK_BLOCKSIZE);
301 if (rv == -1) {
302 warn("Writing `%s'", params->filesystem);
303 goto done;
304 } else if (rv != bootstrapsize) {
305 warnx("Writing `%s': short write", params->filesystem);
306 goto done;
307 }
308
309 if (params->flags & IB_VERBOSE)
310 printf("Writing boot block\n");
311 rv = pwrite(params->fsfd, &bb, sizeof(bb), PMAX_BOOT_BLOCK_OFFSET);
312 if (rv == -1) {
313 warn("Writing `%s'", params->filesystem);
314 goto done;
315 } else if (rv != sizeof(bb)) {
316 warnx("Writing `%s': short write", params->filesystem);
317 goto done;
318 } else {
319 retval = 1;
320 }
321
322 done:
323 if (bootstrapbuf)
324 free(bootstrapbuf);
325 return (retval);
326 }
327
328
329 #define MAX_SEGMENTS 10 /* We can load up to 10 segments */
330
331 struct seglist {
332 Elf32_Addr addr;
333 Elf32_Off f_offset;
334 Elf32_Word f_size;
335 };
336
337 static int
338 load_bootstrap(ib_params *params, char **data,
339 uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
340 {
341 int i, nsegs;
342 Elf32_Addr lowaddr, highaddr;
343 Elf32_Ehdr ehdr;
344 Elf32_Phdr phdr;
345 struct seglist seglist[MAX_SEGMENTS];
346
347 if ((pread(params->s1fd, &ehdr, sizeof(ehdr), 0)) != sizeof(ehdr)) {
348 warn("Reading `%s'", params->stage1);
349 return (0);
350 }
351 if ((memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) ||
352 (ehdr.e_ident[EI_CLASS] != ELFCLASS32)) {
353 warnx("No ELF header in `%s'", params->stage1);
354 return (0);
355 }
356
357 nsegs = highaddr = 0;
358 lowaddr = (uint32_t) ULONG_MAX;
359
360 for (i = 0; i < le16toh(ehdr.e_phnum); i++) {
361 if (pread(params->s1fd, &phdr, sizeof(phdr),
362 (off_t) le32toh(ehdr.e_phoff) + i * sizeof(phdr))
363 != sizeof(phdr)) {
364 warn("Reading `%s'", params->stage1);
365 return (0);
366 }
367 if (le32toh(phdr.p_type) != PT_LOAD)
368 continue;
369
370 seglist[nsegs].addr = le32toh(phdr.p_paddr);
371 seglist[nsegs].f_offset = le32toh(phdr.p_offset);
372 seglist[nsegs].f_size = le32toh(phdr.p_filesz);
373 nsegs++;
374
375 if (le32toh(phdr.p_paddr) < lowaddr)
376 lowaddr = le32toh(phdr.p_paddr);
377 if (le32toh(phdr.p_paddr) + le32toh(phdr.p_filesz) > highaddr)
378 highaddr = le32toh(phdr.p_paddr) +
379 le32toh(phdr.p_filesz);
380 }
381
382 *loadaddr = lowaddr;
383 *execaddr = le32toh(ehdr.e_entry);
384 *len = roundup(highaddr - lowaddr, PMAX_BOOT_BLOCK_BLOCKSIZE);
385 if ((*data = malloc(*len)) == NULL) {
386 warn("Allocating %lu bytes", (unsigned long) *len);
387 return (0);
388 }
389
390 /* Now load the bootstrap into memory */
391 for (i = 0; i < nsegs; i++) {
392 if (pread(params->s1fd, *data + seglist[i].addr - lowaddr,
393 seglist[i].f_size, (off_t)seglist[i].f_offset)
394 != seglist[i].f_size) {
395 warn("Reading `%s'", params->stage1);
396 return (0);
397 }
398 }
399 return (1);
400 }
401