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