xref: /netbsd-src/usr.sbin/installboot/arch/vax.c (revision 9e5598221a2c624e83b603ca49c69b4e980cb723)
1 /*	$NetBSD: vax.c,v 1.4 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 Christopher G. Demetriou.  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 Christopher G. Demetriou
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 #include <sys/cdefs.h>
73 #if defined(__RCSID) && !defined(__lint)
74 __RCSID("$NetBSD: vax.c,v 1.4 2002/04/25 18:11:54 tv Exp $");
75 #endif	/* !__lint */
76 
77 #if HAVE_CONFIG_H
78 #include "config.h"
79 #endif
80 
81 #include <sys/param.h>
82 #include <sys/stat.h>
83 
84 #include <assert.h>
85 #include <err.h>
86 #include <stddef.h>
87 #include <stdio.h>
88 #include <stdlib.h>
89 #include <unistd.h>
90 
91 #if HAVE_CONFIG_H
92 #include "../../sys/dev/dec/dec_boot.h"
93 #else
94 #include <dev/dec/dec_boot.h>
95 #endif
96 
97 #include "installboot.h"
98 
99 static int	load_bootstrap(ib_params *, char **,
100 		    uint32_t *, uint32_t *, size_t *);
101 
102 
103 int
104 vax_parseopt(ib_params *params, const char *option)
105 {
106 
107 	if (parseoptionflag(params, option, IB_APPEND | IB_SUNSUM))
108 		return (1);
109 
110 	warnx("Unknown -o option `%s'", option);
111 	return (0);
112 }
113 
114 int
115 vax_clearboot(ib_params *params)
116 {
117 	struct vax_boot_block	bb;
118 	ssize_t			rv;
119 
120 	assert(params != NULL);
121 	assert(params->fsfd != -1);
122 	assert(params->filesystem != NULL);
123 	assert(sizeof(struct vax_boot_block) == VAX_BOOT_BLOCK_BLOCKSIZE);
124 
125 	if (params->flags & (IB_STARTBLOCK | IB_APPEND)) {
126 		warnx("Can't use `-b bno' or `-o append' with `-c'");
127 		return (0);
128 	}
129 	rv = pread(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
130 	if (rv == -1) {
131 		warn("Reading `%s'", params->filesystem);
132 		return (0);
133 	} else if (rv != sizeof(bb)) {
134 		warnx("Reading `%s': short read", params->filesystem);
135 		return (0);
136 	}
137 
138 	if (bb.bb_id_offset * 2 != offsetof(struct vax_boot_block, bb_magic1)
139 	    || bb.bb_magic1 != VAX_BOOT_MAGIC1) {
140 		warnx(
141 		    "Old boot block magic number invalid; boot block invalid");
142 		return (0);
143 	}
144 
145 	bb.bb_id_offset = 1;
146 	bb.bb_mbone = 0;
147 	bb.bb_lbn_hi = 0;
148 	bb.bb_lbn_low = 0;
149 
150 	if (params->flags & IB_SUNSUM) {
151 		uint16_t	sum;
152 
153 		sum = compute_sunsum((uint16_t *)&bb);
154 		if (! set_sunsum(params, (uint16_t *)&bb, sum))
155 			return (0);
156 	}
157 
158 	if (params->flags & IB_VERBOSE)
159 		printf("%slearing boot block\n",
160 		    (params->flags & IB_NOWRITE) ? "Not c" : "C");
161 	if (params->flags & IB_NOWRITE)
162 		return (1);
163 
164 	rv = pwrite(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
165 	if (rv == -1) {
166 		warn("Writing `%s'", params->filesystem);
167 		return (0);
168 	} else if (rv != sizeof(bb)) {
169 		warnx("Writing `%s': short write", params->filesystem);
170 		return (0);
171 	}
172 
173 	return (1);
174 }
175 
176 int
177 vax_setboot(ib_params *params)
178 {
179 	struct stat		bootstrapsb;
180 	struct vax_boot_block	bb;
181 	uint32_t		startblock;
182 	int			retval;
183 	char			*bootstrapbuf;
184 	size_t			bootstrapsize;
185 	uint32_t		bootstrapload, bootstrapexec;
186 	ssize_t			rv;
187 
188 	assert(params != NULL);
189 	assert(params->fsfd != -1);
190 	assert(params->filesystem != NULL);
191 	assert(params->s1fd != -1);
192 	assert(params->stage1 != NULL);
193 	assert(sizeof(struct vax_boot_block) == VAX_BOOT_BLOCK_BLOCKSIZE);
194 
195 	retval = 0;
196 	bootstrapbuf = NULL;
197 
198 	if ((params->flags & IB_STARTBLOCK) &&
199 	    (params->flags & IB_APPEND)) {
200 		warnx("Can't use `-b bno' with `-o append'");
201 		goto done;
202 	}
203 
204 	if (fstat(params->s1fd, &bootstrapsb) == -1) {
205 		warn("Examining `%s'", params->stage1);
206 		goto done;
207 	}
208 	if (!S_ISREG(bootstrapsb.st_mode)) {
209 		warnx("`%s' must be a regular file", params->stage1);
210 		goto done;
211 	}
212 	if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
213 	    &bootstrapexec, &bootstrapsize))
214 		goto done;
215 
216 	rv = pread(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
217 	if (rv == -1) {
218 		warn("Reading `%s'", params->filesystem);
219 		goto done;
220 	} else if (rv != sizeof(bb)) {
221 		warnx("Reading `%s': short read", params->filesystem);
222 		goto done;
223 	}
224 
225 		/* fill in the updated boot block fields */
226 	if (params->flags & IB_APPEND) {
227 		struct stat	filesyssb;
228 
229 		if (fstat(params->fsfd, &filesyssb) == -1) {
230 			warn("Examining `%s'", params->filesystem);
231 			goto done;
232 		}
233 		if (!S_ISREG(filesyssb.st_mode)) {
234 			warnx(
235 		    "`%s' must be a regular file to append a bootstrap",
236 			    params->filesystem);
237 			goto done;
238 		}
239 		startblock = howmany(filesyssb.st_size,
240 		    VAX_BOOT_BLOCK_BLOCKSIZE);
241 	} else if (params->flags & IB_STARTBLOCK) {
242 		startblock = params->startblock;
243 	} else {
244 		startblock = VAX_BOOT_BLOCK_OFFSET / VAX_BOOT_BLOCK_BLOCKSIZE
245 		    + 1;
246 	}
247 
248 	bb.bb_id_offset = offsetof(struct vax_boot_block, bb_magic1) / 2;
249 	bb.bb_mbone = 1;
250 	bb.bb_lbn_hi = htole16((uint16_t) (startblock >> 16));
251 	bb.bb_lbn_low = htole16((uint16_t) (startblock >>  0));
252 	/*
253 	 * Now the identification block
254 	 */
255 	bb.bb_magic1 = VAX_BOOT_MAGIC1;
256 	bb.bb_mbz1 = 0;
257 	bb.bb_sum1 = ~(bb.bb_magic1 + bb.bb_mbz1 + bb.bb_pad1);
258 
259 	bb.bb_mbz2 = 0;
260 	bb.bb_volinfo = VAX_BOOT_VOLINFO_NONE;
261 	bb.bb_pad2a = 0;
262 	bb.bb_pad2b = 0;
263 
264 	bb.bb_size = htole32(bootstrapsize / VAX_BOOT_BLOCK_BLOCKSIZE);
265 	bb.bb_load = htole32(VAX_BOOT_LOAD);
266 	bb.bb_entry = htole32(VAX_BOOT_ENTRY);
267 	bb.bb_sum3 = htole32(le32toh(bb.bb_size) + le32toh(bb.bb_load) \
268 	    + le32toh(bb.bb_entry));
269 
270 	if (params->flags & IB_SUNSUM) {
271 		uint16_t	sum;
272 
273 		sum = compute_sunsum((uint16_t *)&bb);
274 		if (! set_sunsum(params, (uint16_t *)&bb, sum))
275 			goto done;
276 	}
277 
278 	if (params->flags & IB_VERBOSE) {
279 		printf("Bootstrap start sector: %#x\n", startblock);
280 		printf("Bootstrap sector count: %#x\n", le32toh(bb.bb_size));
281 		printf("%sriting bootstrap\n",
282 		    (params->flags & IB_NOWRITE) ? "Not w" : "W");
283 	}
284 	if (params->flags & IB_NOWRITE) {
285 		retval = 1;
286 		goto done;
287 	}
288 	rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize,
289 	     startblock * VAX_BOOT_BLOCK_BLOCKSIZE);
290 	if (rv == -1) {
291 		warn("Writing `%s'", params->filesystem);
292 		goto done;
293 	} else if (rv != bootstrapsize) {
294 		warnx("Writing `%s': short write", params->filesystem);
295 		goto done;
296 	}
297 
298 	if (params->flags & IB_VERBOSE)
299 		printf("Writing boot block\n");
300 	rv = pwrite(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
301 	if (rv == -1) {
302 		warn("Writing `%s'", params->filesystem);
303 		goto done;
304 	} else if (rv != sizeof(bb)) {
305 		warnx("Writing `%s': short write", params->filesystem);
306 		goto done;
307 	} else {
308 		retval = 1;
309 	}
310 
311  done:
312 	if (bootstrapbuf)
313 		free(bootstrapbuf);
314 	return (retval);
315 }
316 
317 static int
318 load_bootstrap(ib_params *params, char **data,
319 	uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
320 {
321 	ssize_t	cc;
322 	size_t	buflen;
323 
324 	buflen = 512 * (VAX_BOOT_SIZE + 1);
325 	*data = malloc(buflen);
326 	if (*data == NULL) {
327 		warn("Allocating %lu bytes", (unsigned long) buflen);
328 		return (0);
329 	}
330 
331 	cc = pread(params->s1fd, *data, buflen, 0);
332 	if (cc <= 0) {
333 		warn("Reading `%s'", params->stage1);
334 		return (0);
335 	}
336 	if (cc > 512 * VAX_BOOT_SIZE) {
337 		warnx("`%s': too large", params->stage1);
338 		return (0);
339 	}
340 
341 	*len = roundup(cc, VAX_BOOT_BLOCK_BLOCKSIZE);
342 	*loadaddr = VAX_BOOT_LOAD;
343 	*execaddr = VAX_BOOT_ENTRY;
344 	return (1);
345 }
346