sparc.c revision 1.1 1 1.1 pk /* $NetBSD: sparc.c,v 1.1 2002/05/06 16:24:46 pk Exp $ */
2 1.1 pk
3 1.1 pk /*-
4 1.1 pk * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
5 1.1 pk * All rights reserved.
6 1.1 pk *
7 1.1 pk * This code is derived from software contributed to The NetBSD Foundation
8 1.1 pk * by Matt Fredette, Paul Kranenburg, and Luke Mewburn.
9 1.1 pk *
10 1.1 pk * Redistribution and use in source and binary forms, with or without
11 1.1 pk * modification, are permitted provided that the following conditions
12 1.1 pk * are met:
13 1.1 pk * 1. Redistributions of source code must retain the above copyright
14 1.1 pk * notice, this list of conditions and the following disclaimer.
15 1.1 pk * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 pk * notice, this list of conditions and the following disclaimer in the
17 1.1 pk * documentation and/or other materials provided with the distribution.
18 1.1 pk * 3. All advertising materials mentioning features or use of this software
19 1.1 pk * must display the following acknowledgement:
20 1.1 pk * This product includes software developed by the NetBSD
21 1.1 pk * Foundation, Inc. and its contributors.
22 1.1 pk * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.1 pk * contributors may be used to endorse or promote products derived
24 1.1 pk * from this software without specific prior written permission.
25 1.1 pk *
26 1.1 pk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.1 pk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.1 pk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.1 pk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.1 pk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.1 pk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.1 pk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.1 pk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.1 pk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.1 pk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.1 pk * POSSIBILITY OF SUCH DAMAGE.
37 1.1 pk */
38 1.1 pk
39 1.1 pk #include <sys/cdefs.h>
40 1.1 pk #if defined(__RCSID) && !defined(__lint)
41 1.1 pk __RCSID("$NetBSD: sparc.c,v 1.1 2002/05/06 16:24:46 pk Exp $");
42 1.1 pk #endif /* !__lint */
43 1.1 pk
44 1.1 pk #if HAVE_CONFIG_H
45 1.1 pk #include "config.h"
46 1.1 pk #endif
47 1.1 pk
48 1.1 pk #include <sys/param.h>
49 1.1 pk #include <sys/stat.h>
50 1.1 pk
51 1.1 pk #include <assert.h>
52 1.1 pk #include <err.h>
53 1.1 pk #include <stddef.h>
54 1.1 pk #include <stdio.h>
55 1.1 pk #include <stdlib.h>
56 1.1 pk #include <string.h>
57 1.1 pk #include <unistd.h>
58 1.1 pk
59 1.1 pk #if HAVE_CONFIG_H
60 1.1 pk #include "../../sys/sys/bootblock.h"
61 1.1 pk #else
62 1.1 pk #include <sys/bootblock.h>
63 1.1 pk #endif
64 1.1 pk
65 1.1 pk #include "installboot.h"
66 1.1 pk
67 1.1 pk int
68 1.1 pk sparc_clearboot(ib_params *params)
69 1.1 pk {
70 1.1 pk char bb[SPARC_BOOT_BLOCK_MAX_SIZE];
71 1.1 pk ssize_t rv;
72 1.1 pk
73 1.1 pk assert(params != NULL);
74 1.1 pk assert(params->fsfd != -1);
75 1.1 pk assert(params->filesystem != NULL);
76 1.1 pk
77 1.1 pk if (params->flags & IB_STARTBLOCK) {
78 1.1 pk warnx("Can't use `-b bno' with `-c'");
79 1.1 pk return (0);
80 1.1 pk }
81 1.1 pk
82 1.1 pk /* first check that it _could_ exist here */
83 1.1 pk rv = pread(params->fsfd, &bb, sizeof(bb), SPARC_BOOT_BLOCK_OFFSET);
84 1.1 pk if (rv == -1) {
85 1.1 pk warn("Reading `%s'", params->filesystem);
86 1.1 pk return (0);
87 1.1 pk } else if (rv != sizeof(bb)) {
88 1.1 pk warnx("Reading `%s': short read", params->filesystem);
89 1.1 pk return (0);
90 1.1 pk }
91 1.1 pk
92 1.1 pk /* now clear it out to nothing */
93 1.1 pk memset(&bb, 0, sizeof(bb));
94 1.1 pk
95 1.1 pk if (params->flags & IB_VERBOSE)
96 1.1 pk printf("%slearing boot block\n",
97 1.1 pk (params->flags & IB_NOWRITE) ? "Not c" : "C");
98 1.1 pk if (params->flags & IB_NOWRITE)
99 1.1 pk return (1);
100 1.1 pk
101 1.1 pk rv = pwrite(params->fsfd, &bb, sizeof(bb), SPARC_BOOT_BLOCK_OFFSET);
102 1.1 pk if (rv == -1) {
103 1.1 pk warn("Writing `%s'", params->filesystem);
104 1.1 pk return (0);
105 1.1 pk } else if (rv != sizeof(bb)) {
106 1.1 pk warnx("Writing `%s': short write", params->filesystem);
107 1.1 pk return (0);
108 1.1 pk }
109 1.1 pk
110 1.1 pk return (1);
111 1.1 pk }
112 1.1 pk
113 1.1 pk int
114 1.1 pk sparc_setboot(ib_params *params)
115 1.1 pk {
116 1.1 pk struct stat bootstrapsb;
117 1.1 pk char bb[SPARC_BOOT_BLOCK_MAX_SIZE];
118 1.1 pk uint32_t startblock;
119 1.1 pk int retval;
120 1.1 pk ssize_t rv;
121 1.1 pk size_t bbi;
122 1.1 pk struct sparc_bbinfo *bbinfop; /* bbinfo in prototype image */
123 1.1 pk uint32_t maxblk, nblk, blk_i;
124 1.1 pk ib_block *blocks = NULL;
125 1.1 pk
126 1.1 pk assert(params != NULL);
127 1.1 pk assert(params->fsfd != -1);
128 1.1 pk assert(params->filesystem != NULL);
129 1.1 pk assert(params->fstype != NULL);
130 1.1 pk assert(params->s1fd != -1);
131 1.1 pk assert(params->stage1 != NULL);
132 1.1 pk assert(SPARC_BBINFO_MAGICSIZE == 32);
133 1.1 pk
134 1.1 pk if (params->stage2 == NULL) {
135 1.1 pk warnx("You must provide the name of the secondary bootstrap");
136 1.1 pk return (0);
137 1.1 pk }
138 1.1 pk
139 1.1 pk retval = 0;
140 1.1 pk
141 1.1 pk if (fstat(params->s1fd, &bootstrapsb) == -1) {
142 1.1 pk warn("Examining `%s'", params->stage1);
143 1.1 pk goto done;
144 1.1 pk }
145 1.1 pk if (!S_ISREG(bootstrapsb.st_mode)) {
146 1.1 pk warnx("`%s' must be a regular file", params->stage1);
147 1.1 pk goto done;
148 1.1 pk }
149 1.1 pk if (bootstrapsb.st_size > sizeof(bb)) {
150 1.1 pk warnx("`%s' cannot be larger than %lu bytes",
151 1.1 pk params->stage1, (unsigned long)sizeof(bb));
152 1.1 pk goto done;
153 1.1 pk }
154 1.1 pk
155 1.1 pk /*
156 1.1 pk * Read 1st stage boot program
157 1.1 pk * Leave room for a 32-byte a.out header.
158 1.1 pk */
159 1.1 pk memset(&bb, 0, sizeof(bb));
160 1.1 pk rv = read(params->s1fd, bb + 32, sizeof(bb) - 32);
161 1.1 pk if (rv == -1) {
162 1.1 pk warn("Reading `%s'", params->stage1);
163 1.1 pk goto done;
164 1.1 pk }
165 1.1 pk
166 1.1 pk /*
167 1.1 pk * Quick sanity check that the bootstrap given
168 1.1 pk * is *not* an ELF executable.
169 1.1 pk */
170 1.1 pk if (memcmp(bb + 32 + 1, "ELF", strlen("ELF")) == 0) {
171 1.1 pk warnx("`%s' is an ELF executable; need raw binary",
172 1.1 pk params->stage1);
173 1.1 pk goto done;
174 1.1 pk }
175 1.1 pk
176 1.1 pk /* Look for the bbinfo structure. */
177 1.1 pk for (bbi = 0; bbi < sizeof(bb); bbi += sizeof(uint32_t)) {
178 1.1 pk bbinfop = (void *) (bb + bbi);
179 1.1 pk if (memcmp(bbinfop->bbi_magic, SPARC_BBINFO_MAGIC,
180 1.1 pk SPARC_BBINFO_MAGICSIZE) == 0)
181 1.1 pk break;
182 1.1 pk }
183 1.1 pk if (bbi >= sizeof(bb)) {
184 1.1 pk warnx("`%s' does not have a bbinfo structure\n",
185 1.1 pk params->stage1);
186 1.1 pk goto done;
187 1.1 pk }
188 1.1 pk maxblk = be32toh(bbinfop->bbi_block_count);
189 1.1 pk if (maxblk == 0 || maxblk > (sizeof(bb) / sizeof(uint32_t))) {
190 1.1 pk warnx("bbinfo structure in `%s' has preposterous size `%u'",
191 1.1 pk params->stage1, maxblk);
192 1.1 pk goto done;
193 1.1 pk }
194 1.1 pk
195 1.1 pk /* Allocate space for our block list. */
196 1.1 pk blocks = malloc(sizeof(*blocks) * maxblk);
197 1.1 pk if (blocks == NULL) {
198 1.1 pk warn("Allocating %lu bytes",
199 1.1 pk (unsigned long) sizeof(*blocks) * maxblk);
200 1.1 pk goto done;
201 1.1 pk }
202 1.1 pk
203 1.1 pk /* Make sure the (probably new) secondary bootstrap is on disk. */
204 1.1 pk sync(); sleep(1); sync();
205 1.1 pk
206 1.1 pk /* Collect the blocks for the secondary bootstrap. */
207 1.1 pk nblk = maxblk;
208 1.1 pk if (! params->fstype->findstage2(params, &nblk, blocks))
209 1.1 pk goto done;
210 1.1 pk if (nblk == 0) {
211 1.1 pk warnx("Secondary bootstrap `%s' is empty",
212 1.1 pk params->stage2);
213 1.1 pk goto done;
214 1.1 pk }
215 1.1 pk
216 1.1 pk /* Save those blocks in the primary bootstrap. */
217 1.1 pk bbinfop->bbi_block_count = htobe32(nblk);
218 1.1 pk bbinfop->bbi_block_size = htobe32(blocks[0].blocksize);
219 1.1 pk for (blk_i = 0; blk_i < nblk; blk_i++) {
220 1.1 pk bbinfop->bbi_block_table[blk_i] =
221 1.1 pk htobe32(blocks[blk_i].block);
222 1.1 pk if (blocks[blk_i].blocksize < blocks[0].blocksize &&
223 1.1 pk blk_i + 1 != nblk) {
224 1.1 pk warnx("Secondary bootstrap `%s' blocks do not have " \
225 1.1 pk "a uniform size\n", params->stage2);
226 1.1 pk goto done;
227 1.1 pk }
228 1.1 pk }
229 1.1 pk
230 1.1 pk /*
231 1.1 pk * sun4c/sun4m PROMs require an a.out(5) format header.
232 1.1 pk * Old-style sun4 PROMs do not expect a header at all.
233 1.1 pk * To deal with this, we construct a header that is also executable
234 1.1 pk * code containing a forward branch that gets us past the 32-byte
235 1.1 pk * header where the actual code begins. In assembly:
236 1.1 pk * .word MAGIC ! a NOP
237 1.1 pk * ba,a start !
238 1.1 pk * .skip 24 ! pad
239 1.1 pk * start:
240 1.1 pk */
241 1.1 pk #define SUN_MAGIC 0x01030107
242 1.1 pk #define SUN4_BASTART 0x30800007 /* i.e.: ba,a `start' */
243 1.1 pk *((uint32_t *)bb) = htobe32(SUN_MAGIC);
244 1.1 pk *((uint32_t *)bb + 1) = htobe32(SUN4_BASTART);
245 1.1 pk
246 1.1 pk if (params->flags & IB_STARTBLOCK)
247 1.1 pk startblock = params->startblock;
248 1.1 pk else
249 1.1 pk startblock =
250 1.1 pk SPARC_BOOT_BLOCK_OFFSET / SPARC_BOOT_BLOCK_BLOCKSIZE;
251 1.1 pk
252 1.1 pk if (params->flags & IB_VERBOSE) {
253 1.1 pk printf("Bootstrap start sector: %u\n", startblock);
254 1.1 pk printf("Bootstrap byte count: %u\n", (unsigned)rv);
255 1.1 pk printf("Bootstrap block table: %u entries avail, %u used:",
256 1.1 pk maxblk, nblk);
257 1.1 pk for (blk_i = 0; blk_i < nblk; blk_i++)
258 1.1 pk printf(" %u", blocks[blk_i].block);
259 1.1 pk printf("\n%sriting bootstrap\n",
260 1.1 pk (params->flags & IB_NOWRITE) ? "Not w" : "W");
261 1.1 pk }
262 1.1 pk if (params->flags & IB_NOWRITE) {
263 1.1 pk retval = 1;
264 1.1 pk goto done;
265 1.1 pk }
266 1.1 pk
267 1.1 pk rv = pwrite(params->fsfd, &bb, sizeof(bb),
268 1.1 pk startblock * SPARC_BOOT_BLOCK_BLOCKSIZE);
269 1.1 pk if (rv == -1) {
270 1.1 pk warn("Writing `%s'", params->filesystem);
271 1.1 pk goto done;
272 1.1 pk } else if (rv != sizeof(bb)) {
273 1.1 pk warnx("Writing `%s': short write", params->filesystem);
274 1.1 pk goto done;
275 1.1 pk } else {
276 1.1 pk
277 1.1 pk /* Sync filesystems (to clean in-memory superblock?) */
278 1.1 pk sync();
279 1.1 pk
280 1.1 pk retval = 1;
281 1.1 pk }
282 1.1 pk
283 1.1 pk done:
284 1.1 pk if (blocks != NULL)
285 1.1 pk free (blocks);
286 1.1 pk return (retval);
287 1.1 pk }
288