1*492c086fSandvar /* $NetBSD: vax.c,v 1.20 2022/01/24 09:14:38 andvar Exp $ */
2c37fa0ceSlukem
3c37fa0ceSlukem /*-
4c37fa0ceSlukem * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
5c37fa0ceSlukem * All rights reserved.
6c37fa0ceSlukem *
7c37fa0ceSlukem * This code is derived from software contributed to The NetBSD Foundation
8c37fa0ceSlukem * by Simon Burge.
9c37fa0ceSlukem *
10c37fa0ceSlukem * This code is derived from software contributed to The NetBSD Foundation
11c37fa0ceSlukem * by Luke Mewburn of Wasabi Systems.
12c37fa0ceSlukem *
13c37fa0ceSlukem * Redistribution and use in source and binary forms, with or without
14c37fa0ceSlukem * modification, are permitted provided that the following conditions
15c37fa0ceSlukem * are met:
16c37fa0ceSlukem * 1. Redistributions of source code must retain the above copyright
17c37fa0ceSlukem * notice, this list of conditions and the following disclaimer.
18c37fa0ceSlukem * 2. Redistributions in binary form must reproduce the above copyright
19c37fa0ceSlukem * notice, this list of conditions and the following disclaimer in the
20c37fa0ceSlukem * documentation and/or other materials provided with the distribution.
21c37fa0ceSlukem *
22c37fa0ceSlukem * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23c37fa0ceSlukem * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24c37fa0ceSlukem * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25c37fa0ceSlukem * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26c37fa0ceSlukem * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27c37fa0ceSlukem * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28c37fa0ceSlukem * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29c37fa0ceSlukem * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30c37fa0ceSlukem * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31c37fa0ceSlukem * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32c37fa0ceSlukem * POSSIBILITY OF SUCH DAMAGE.
33c37fa0ceSlukem */
34c37fa0ceSlukem
35c37fa0ceSlukem /*
36c37fa0ceSlukem * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
37c37fa0ceSlukem *
38c37fa0ceSlukem * Redistribution and use in source and binary forms, with or without
39c37fa0ceSlukem * modification, are permitted provided that the following conditions
40c37fa0ceSlukem * are met:
41c37fa0ceSlukem * 1. Redistributions of source code must retain the above copyright
42c37fa0ceSlukem * notice, this list of conditions and the following disclaimer.
43c37fa0ceSlukem * 2. Redistributions in binary form must reproduce the above copyright
44c37fa0ceSlukem * notice, this list of conditions and the following disclaimer in the
45c37fa0ceSlukem * documentation and/or other materials provided with the distribution.
46c37fa0ceSlukem * 3. All advertising materials mentioning features or use of this software
47c37fa0ceSlukem * must display the following acknowledgement:
48c37fa0ceSlukem * This product includes software developed by Christopher G. Demetriou
49c37fa0ceSlukem * for the NetBSD Project.
50c37fa0ceSlukem * 4. The name of the author may not be used to endorse or promote products
51c37fa0ceSlukem * derived from this software without specific prior written permission
52c37fa0ceSlukem *
53c37fa0ceSlukem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54c37fa0ceSlukem * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55c37fa0ceSlukem * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
56c37fa0ceSlukem * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
57c37fa0ceSlukem * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
58c37fa0ceSlukem * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59c37fa0ceSlukem * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60c37fa0ceSlukem * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61c37fa0ceSlukem * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
62c37fa0ceSlukem * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63c37fa0ceSlukem */
64c37fa0ceSlukem
65171d6532Slukem #if HAVE_NBTOOL_CONFIG_H
66171d6532Slukem #include "nbtool_config.h"
674887cf34Stv #endif
684887cf34Stv
69171d6532Slukem #include <sys/cdefs.h>
70171d6532Slukem #if !defined(__lint)
71*492c086fSandvar __RCSID("$NetBSD: vax.c,v 1.20 2022/01/24 09:14:38 andvar Exp $");
72171d6532Slukem #endif /* !__lint */
73171d6532Slukem
74c37fa0ceSlukem #include <sys/param.h>
75252b8260Smatt #ifdef HAVE_NBTOOL_CONFIG_H
76252b8260Smatt #include <nbinclude/vax/disklabel.h>
77252b8260Smatt #else
78e23a017dSmartin #include <sys/disklabel.h>
79252b8260Smatt #endif
80c37fa0ceSlukem
81c37fa0ceSlukem #include <assert.h>
82c37fa0ceSlukem #include <err.h>
83c37fa0ceSlukem #include <stddef.h>
84c37fa0ceSlukem #include <stdio.h>
85c37fa0ceSlukem #include <stdlib.h>
86e23a017dSmartin #include <string.h>
87c37fa0ceSlukem #include <unistd.h>
88c37fa0ceSlukem
89c37fa0ceSlukem #include "installboot.h"
90c37fa0ceSlukem
91039e2096Schristos #define VAX_LABELOFFSET 64
92039e2096Schristos
9367c2857bSmartin #ifndef __CTASSERT
9467c2857bSmartin #define __CTASSERT(X)
9567c2857bSmartin #endif
9667c2857bSmartin
97c37fa0ceSlukem static int load_bootstrap(ib_params *, char **,
988eb8919eSlukem uint32_t *, uint32_t *, size_t *);
99c37fa0ceSlukem
100cce659e2Sdsl static int vax_clearboot(ib_params *);
101cce659e2Sdsl static int vax_setboot(ib_params *);
102cce659e2Sdsl
103e5c09b19Sthorpej struct ib_mach ib_mach_vax = {
104e5c09b19Sthorpej .name = "vax",
105e5c09b19Sthorpej .setboot = vax_setboot,
106e5c09b19Sthorpej .clearboot = vax_clearboot,
107e5c09b19Sthorpej .editboot = no_editboot,
108e5c09b19Sthorpej .valid_flags = IB_STAGE1START | IB_APPEND | IB_SUNSUM,
109e5c09b19Sthorpej };
110cce659e2Sdsl
111cce659e2Sdsl static int
vax_clearboot(ib_params * params)112c37fa0ceSlukem vax_clearboot(ib_params *params)
113c37fa0ceSlukem {
114c37fa0ceSlukem struct vax_boot_block bb;
115c37fa0ceSlukem ssize_t rv;
116c37fa0ceSlukem
117c37fa0ceSlukem assert(params != NULL);
118c37fa0ceSlukem assert(params->fsfd != -1);
119c37fa0ceSlukem assert(params->filesystem != NULL);
120e23a017dSmartin __CTASSERT(sizeof(bb)==VAX_BOOT_BLOCK_BLOCKSIZE);
121c37fa0ceSlukem
122c37fa0ceSlukem rv = pread(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
123c37fa0ceSlukem if (rv == -1) {
124c37fa0ceSlukem warn("Reading `%s'", params->filesystem);
125c37fa0ceSlukem return (0);
126c37fa0ceSlukem } else if (rv != sizeof(bb)) {
127c37fa0ceSlukem warnx("Reading `%s': short read", params->filesystem);
128c37fa0ceSlukem return (0);
129c37fa0ceSlukem }
130c37fa0ceSlukem
131e23a017dSmartin if (bb.bb_id_offset*2 >= VAX_BOOT_BLOCK_BLOCKSIZE
132c37fa0ceSlukem || bb.bb_magic1 != VAX_BOOT_MAGIC1) {
133c37fa0ceSlukem warnx(
134c37fa0ceSlukem "Old boot block magic number invalid; boot block invalid");
135c37fa0ceSlukem return (0);
136c37fa0ceSlukem }
137c37fa0ceSlukem
138c37fa0ceSlukem bb.bb_id_offset = 1;
139c37fa0ceSlukem bb.bb_mbone = 0;
140c37fa0ceSlukem bb.bb_lbn_hi = 0;
141c37fa0ceSlukem bb.bb_lbn_low = 0;
142c37fa0ceSlukem
143c37fa0ceSlukem if (params->flags & IB_SUNSUM) {
1448eb8919eSlukem uint16_t sum;
145c37fa0ceSlukem
1468eb8919eSlukem sum = compute_sunsum((uint16_t *)&bb);
1478eb8919eSlukem if (! set_sunsum(params, (uint16_t *)&bb, sum))
148c37fa0ceSlukem return (0);
149c37fa0ceSlukem }
150c37fa0ceSlukem
151c37fa0ceSlukem if (params->flags & IB_VERBOSE)
152c37fa0ceSlukem printf("%slearing boot block\n",
153c37fa0ceSlukem (params->flags & IB_NOWRITE) ? "Not c" : "C");
154c37fa0ceSlukem if (params->flags & IB_NOWRITE)
155c37fa0ceSlukem return (1);
156c37fa0ceSlukem
157c37fa0ceSlukem rv = pwrite(params->fsfd, &bb, sizeof(bb), VAX_BOOT_BLOCK_OFFSET);
158c37fa0ceSlukem if (rv == -1) {
159c37fa0ceSlukem warn("Writing `%s'", params->filesystem);
160c37fa0ceSlukem return (0);
161c37fa0ceSlukem } else if (rv != sizeof(bb)) {
162c37fa0ceSlukem warnx("Writing `%s': short write", params->filesystem);
163c37fa0ceSlukem return (0);
164c37fa0ceSlukem }
165c37fa0ceSlukem
166c37fa0ceSlukem return (1);
167c37fa0ceSlukem }
168c37fa0ceSlukem
169cce659e2Sdsl static int
vax_setboot(ib_params * params)170c37fa0ceSlukem vax_setboot(ib_params *params)
171c37fa0ceSlukem {
172c37fa0ceSlukem struct stat bootstrapsb;
173e23a017dSmartin struct vax_boot_block *bb;
1748eb8919eSlukem uint32_t startblock;
1758eb8919eSlukem int retval;
176e23a017dSmartin char *bootstrapbuf, oldbb[VAX_BOOT_BLOCK_BLOCKSIZE];
177c37fa0ceSlukem size_t bootstrapsize;
1788eb8919eSlukem uint32_t bootstrapload, bootstrapexec;
179c37fa0ceSlukem ssize_t rv;
180c37fa0ceSlukem
181c37fa0ceSlukem assert(params != NULL);
182c37fa0ceSlukem assert(params->fsfd != -1);
183c37fa0ceSlukem assert(params->filesystem != NULL);
184d2804426Slukem assert(params->s1fd != -1);
185d2804426Slukem assert(params->stage1 != NULL);
186c37fa0ceSlukem
187e23a017dSmartin /* see sys/arch/vax/boot/xxboot/start.S for explanation */
188e23a017dSmartin __CTASSERT(offsetof(struct vax_boot_block,bb_magic1) == 0x19e);
189e23a017dSmartin __CTASSERT(sizeof(struct vax_boot_block) == VAX_BOOT_BLOCK_BLOCKSIZE);
190e23a017dSmartin
191e23a017dSmartin startblock = 0;
192c37fa0ceSlukem retval = 0;
193c37fa0ceSlukem bootstrapbuf = NULL;
194c37fa0ceSlukem
195d2804426Slukem if (fstat(params->s1fd, &bootstrapsb) == -1) {
196d2804426Slukem warn("Examining `%s'", params->stage1);
197c37fa0ceSlukem goto done;
198c37fa0ceSlukem }
199c37fa0ceSlukem if (!S_ISREG(bootstrapsb.st_mode)) {
200d2804426Slukem warnx("`%s' must be a regular file", params->stage1);
201c37fa0ceSlukem goto done;
202c37fa0ceSlukem }
203c37fa0ceSlukem if (! load_bootstrap(params, &bootstrapbuf, &bootstrapload,
204c37fa0ceSlukem &bootstrapexec, &bootstrapsize))
205c37fa0ceSlukem goto done;
206c37fa0ceSlukem
207e23a017dSmartin /* read old boot block */
208e23a017dSmartin rv = pread(params->fsfd, oldbb, sizeof(oldbb), VAX_BOOT_BLOCK_OFFSET);
209c37fa0ceSlukem if (rv == -1) {
210c37fa0ceSlukem warn("Reading `%s'", params->filesystem);
211c37fa0ceSlukem goto done;
212e23a017dSmartin } else if (rv != sizeof(oldbb)) {
213c37fa0ceSlukem warnx("Reading `%s': short read", params->filesystem);
214c37fa0ceSlukem goto done;
215c37fa0ceSlukem }
216c37fa0ceSlukem
217e23a017dSmartin /*
218e23a017dSmartin * Copy disklabel from old boot block to new.
219039e2096Schristos * Assume everything between VAX_LABELOFFSET and the start of
220e23a017dSmartin * the param block is scratch area and can be copied over.
221e23a017dSmartin */
222039e2096Schristos memcpy(bootstrapbuf + VAX_LABELOFFSET,
223039e2096Schristos oldbb + VAX_LABELOFFSET,
224039e2096Schristos offsetof(struct vax_boot_block,bb_magic1) - VAX_LABELOFFSET);
225e23a017dSmartin
226*492c086fSandvar /* point to bootblock at beginning of bootstrap */
227e23a017dSmartin bb = (struct vax_boot_block*)bootstrapbuf;
228e23a017dSmartin
229c37fa0ceSlukem /* fill in the updated boot block fields */
230c37fa0ceSlukem if (params->flags & IB_APPEND) {
231c37fa0ceSlukem struct stat filesyssb;
232c37fa0ceSlukem
233c37fa0ceSlukem if (fstat(params->fsfd, &filesyssb) == -1) {
234c37fa0ceSlukem warn("Examining `%s'", params->filesystem);
235c37fa0ceSlukem goto done;
236c37fa0ceSlukem }
237c37fa0ceSlukem if (!S_ISREG(filesyssb.st_mode)) {
238c37fa0ceSlukem warnx(
239d2804426Slukem "`%s' must be a regular file to append a bootstrap",
240c37fa0ceSlukem params->filesystem);
241c37fa0ceSlukem goto done;
242c37fa0ceSlukem }
243c37fa0ceSlukem startblock = howmany(filesyssb.st_size,
244c37fa0ceSlukem VAX_BOOT_BLOCK_BLOCKSIZE);
245e23a017dSmartin bb->bb_lbn_hi = htole16((uint16_t) (startblock >> 16));
246e23a017dSmartin bb->bb_lbn_low = htole16((uint16_t) (startblock >> 0));
247c37fa0ceSlukem }
248c37fa0ceSlukem
249c37fa0ceSlukem if (params->flags & IB_SUNSUM) {
2508eb8919eSlukem uint16_t sum;
251c37fa0ceSlukem
252e23a017dSmartin sum = compute_sunsum((uint16_t *)bb);
253e23a017dSmartin if (! set_sunsum(params, (uint16_t *)bb, sum))
254c37fa0ceSlukem goto done;
255c37fa0ceSlukem }
256c37fa0ceSlukem
257c37fa0ceSlukem if (params->flags & IB_VERBOSE) {
258d9e55fcaSlukem printf("Bootstrap start sector: %u\n", startblock);
259e23a017dSmartin printf("Bootstrap sector count: %u\n", le32toh(bb->bb_size));
260c37fa0ceSlukem printf("%sriting bootstrap\n",
261c37fa0ceSlukem (params->flags & IB_NOWRITE) ? "Not w" : "W");
262c37fa0ceSlukem }
263c37fa0ceSlukem if (params->flags & IB_NOWRITE) {
264c37fa0ceSlukem retval = 1;
265c37fa0ceSlukem goto done;
266c37fa0ceSlukem }
267e23a017dSmartin rv = pwrite(params->fsfd, bootstrapbuf, bootstrapsize, 0);
268c37fa0ceSlukem if (rv == -1) {
269c37fa0ceSlukem warn("Writing `%s'", params->filesystem);
270c37fa0ceSlukem goto done;
2712b2f4703Slukem } else if ((size_t)rv != bootstrapsize) {
272c37fa0ceSlukem warnx("Writing `%s': short write", params->filesystem);
273c37fa0ceSlukem goto done;
274c37fa0ceSlukem }
275c37fa0ceSlukem retval = 1;
276c37fa0ceSlukem
277c37fa0ceSlukem done:
278c37fa0ceSlukem if (bootstrapbuf)
279c37fa0ceSlukem free(bootstrapbuf);
280c37fa0ceSlukem return (retval);
281c37fa0ceSlukem }
282c37fa0ceSlukem
283c37fa0ceSlukem static int
load_bootstrap(ib_params * params,char ** data,uint32_t * loadaddr,uint32_t * execaddr,size_t * len)284c37fa0ceSlukem load_bootstrap(ib_params *params, char **data,
2858eb8919eSlukem uint32_t *loadaddr, uint32_t *execaddr, size_t *len)
286c37fa0ceSlukem {
287c37fa0ceSlukem ssize_t cc;
288c37fa0ceSlukem size_t buflen;
289c37fa0ceSlukem
290c37fa0ceSlukem buflen = 512 * (VAX_BOOT_SIZE + 1);
291c37fa0ceSlukem *data = malloc(buflen);
292c37fa0ceSlukem if (*data == NULL) {
293c37fa0ceSlukem warn("Allocating %lu bytes", (unsigned long) buflen);
294c37fa0ceSlukem return (0);
295c37fa0ceSlukem }
296c37fa0ceSlukem
297d2804426Slukem cc = pread(params->s1fd, *data, buflen, 0);
298c37fa0ceSlukem if (cc <= 0) {
299d2804426Slukem warn("Reading `%s'", params->stage1);
300c37fa0ceSlukem return (0);
301c37fa0ceSlukem }
302c37fa0ceSlukem if (cc > 512 * VAX_BOOT_SIZE) {
303d2804426Slukem warnx("`%s': too large", params->stage1);
304c37fa0ceSlukem return (0);
305c37fa0ceSlukem }
306c37fa0ceSlukem
307c37fa0ceSlukem *len = roundup(cc, VAX_BOOT_BLOCK_BLOCKSIZE);
308c37fa0ceSlukem *loadaddr = VAX_BOOT_LOAD;
309c37fa0ceSlukem *execaddr = VAX_BOOT_ENTRY;
310c37fa0ceSlukem return (1);
311c37fa0ceSlukem }
312