1 1.10 andvar /* $NetBSD: next68k.c,v 1.10 2023/02/14 20:27:17 andvar Exp $ */ 2 1.1 cl 3 1.1 cl /*- 4 1.1 cl * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 1.1 cl * All rights reserved. 6 1.1 cl * 7 1.1 cl * This code is derived from software contributed to The NetBSD Foundation 8 1.1 cl * by David Laight and Christian Limpach. 9 1.1 cl * 10 1.1 cl * Redistribution and use in source and binary forms, with or without 11 1.1 cl * modification, are permitted provided that the following conditions 12 1.1 cl * are met: 13 1.1 cl * 1. Redistributions of source code must retain the above copyright 14 1.1 cl * notice, this list of conditions and the following disclaimer. 15 1.1 cl * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 cl * notice, this list of conditions and the following disclaimer in the 17 1.1 cl * documentation and/or other materials provided with the distribution. 18 1.1 cl * 19 1.1 cl * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 cl * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 cl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 cl * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 cl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 cl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 cl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 cl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 cl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 cl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 cl * POSSIBILITY OF SUCH DAMAGE. 30 1.1 cl */ 31 1.1 cl 32 1.1 cl #if HAVE_NBTOOL_CONFIG_H 33 1.1 cl #include "nbtool_config.h" 34 1.1 cl #endif 35 1.1 cl 36 1.2 lukem #include <sys/cdefs.h> 37 1.2 lukem #if !defined(__lint) 38 1.10 andvar __RCSID("$NetBSD: next68k.c,v 1.10 2023/02/14 20:27:17 andvar Exp $"); 39 1.2 lukem #endif /* !__lint */ 40 1.2 lukem 41 1.1 cl #include <sys/param.h> 42 1.1 cl 43 1.1 cl #include <assert.h> 44 1.1 cl #include <err.h> 45 1.1 cl #include <md5.h> 46 1.1 cl #include <stddef.h> 47 1.1 cl #include <stdio.h> 48 1.1 cl #include <stdlib.h> 49 1.1 cl #include <string.h> 50 1.1 cl #include <unistd.h> 51 1.1 cl 52 1.1 cl #include "installboot.h" 53 1.1 cl 54 1.1 cl static uint16_t nextstep_checksum(const void *, const void *); 55 1.4 dsl static int next68k_setboot(ib_params *); 56 1.4 dsl 57 1.9 thorpej struct ib_mach ib_mach_next68k = { 58 1.9 thorpej .name = "next68k", 59 1.9 thorpej .setboot = next68k_setboot, 60 1.9 thorpej .clearboot = no_clearboot, 61 1.9 thorpej .editboot = no_editboot, 62 1.9 thorpej }; 63 1.1 cl 64 1.1 cl static uint16_t 65 1.1 cl nextstep_checksum(const void *vbuf, const void *vlimit) 66 1.1 cl { 67 1.1 cl const uint16_t *buf = vbuf; 68 1.1 cl const uint16_t *limit = vlimit; 69 1.3 jmc u_int sum = 0; 70 1.1 cl 71 1.1 cl while (buf < limit) { 72 1.1 cl sum += be16toh(*buf++); 73 1.1 cl } 74 1.1 cl sum += (sum >> 16); 75 1.1 cl return (sum & 0xffff); 76 1.1 cl } 77 1.1 cl 78 1.4 dsl static int 79 1.1 cl next68k_setboot(ib_params *params) 80 1.1 cl { 81 1.1 cl int retval, labelupdated; 82 1.1 cl uint8_t *bootbuf; 83 1.6 lukem size_t bootsize; 84 1.1 cl ssize_t rv; 85 1.1 cl uint32_t cd_secsize; 86 1.1 cl int sec_netonb_mult; 87 1.1 cl struct next68k_disklabel *next68klabel; 88 1.1 cl uint16_t *checksum; 89 1.1 cl uint32_t fp, b0, b1; 90 1.1 cl 91 1.1 cl assert(params != NULL); 92 1.1 cl assert(params->fsfd != -1); 93 1.1 cl assert(params->filesystem != NULL); 94 1.1 cl assert(params->s1fd != -1); 95 1.1 cl assert(params->stage1 != NULL); 96 1.1 cl 97 1.1 cl retval = 0; 98 1.1 cl labelupdated = 0; 99 1.1 cl bootbuf = NULL; 100 1.1 cl 101 1.1 cl next68klabel = malloc(NEXT68K_LABEL_SIZE); 102 1.1 cl if (next68klabel == NULL) { 103 1.2 lukem warn("Allocating %lu bytes", (unsigned long)NEXT68K_LABEL_SIZE); 104 1.1 cl goto done; 105 1.1 cl } 106 1.1 cl 107 1.1 cl /* 108 1.1 cl * Read in the next68k disklabel 109 1.1 cl */ 110 1.1 cl rv = pread(params->fsfd, next68klabel, NEXT68K_LABEL_SIZE, 111 1.7 tsutsui NEXT68K_LABEL_SECTOR * params->sectorsize + NEXT68K_LABEL_OFFSET); 112 1.1 cl if (rv == -1) { 113 1.1 cl warn("Reading `%s'", params->filesystem); 114 1.1 cl goto done; 115 1.1 cl } 116 1.1 cl if (rv != NEXT68K_LABEL_SIZE) { 117 1.1 cl warnx("Reading `%s': short read", params->filesystem); 118 1.1 cl goto done; 119 1.1 cl } 120 1.1 cl if (be32toh(next68klabel->cd_version) == NEXT68K_LABEL_CD_V3) { 121 1.1 cl checksum = &next68klabel->NEXT68K_LABEL_cd_v3_checksum; 122 1.1 cl } else { 123 1.1 cl checksum = &next68klabel->cd_checksum; 124 1.1 cl } 125 1.1 cl if (nextstep_checksum (next68klabel, checksum) != 126 1.1 cl be16toh(*checksum)) { 127 1.2 lukem warn("Disklabel checksum invalid on `%s'", 128 1.1 cl params->filesystem); 129 1.1 cl goto done; 130 1.1 cl } 131 1.1 cl 132 1.1 cl cd_secsize = be32toh(next68klabel->cd_secsize); 133 1.7 tsutsui sec_netonb_mult = (cd_secsize / params->sectorsize); 134 1.1 cl 135 1.1 cl /* 136 1.1 cl * Allocate a buffer, with space to round up the input file 137 1.1 cl * to the next block size boundary, and with space for the boot 138 1.1 cl * block. 139 1.1 cl */ 140 1.1 cl bootsize = roundup(params->s1stat.st_size, cd_secsize); 141 1.1 cl 142 1.1 cl bootbuf = malloc(bootsize); 143 1.1 cl if (bootbuf == NULL) { 144 1.6 lukem warn("Allocating %zu bytes", bootsize); 145 1.1 cl goto done; 146 1.1 cl } 147 1.1 cl memset(bootbuf, 0, bootsize); 148 1.1 cl 149 1.1 cl /* 150 1.1 cl * Read the file into the buffer. 151 1.1 cl */ 152 1.1 cl rv = pread(params->s1fd, bootbuf, params->s1stat.st_size, 0); 153 1.1 cl if (rv == -1) { 154 1.1 cl warn("Reading `%s'", params->stage1); 155 1.1 cl goto done; 156 1.1 cl } else if (rv != params->s1stat.st_size) { 157 1.1 cl warnx("Reading `%s': short read", params->stage1); 158 1.1 cl goto done; 159 1.1 cl } 160 1.1 cl 161 1.8 msaitoh if (bootsize > be16toh(next68klabel->cd_front) * cd_secsize - 162 1.1 cl NEXT68K_LABEL_SIZE) { 163 1.1 cl warnx("Boot program is larger than front porch space"); 164 1.1 cl goto done; 165 1.1 cl } 166 1.1 cl 167 1.1 cl fp = be16toh(next68klabel->cd_front); 168 1.1 cl b0 = be32toh(next68klabel->cd_boot_blkno[0]); 169 1.1 cl b1 = be32toh(next68klabel->cd_boot_blkno[1]); 170 1.1 cl 171 1.1 cl if (b0 > fp) 172 1.1 cl b0 = fp; 173 1.1 cl if (b1 > fp) 174 1.1 cl b1 = fp; 175 1.1 cl if (((bootsize / cd_secsize) > b1 - b0) || 176 1.1 cl ((bootsize / cd_secsize) > fp - b1)) { 177 1.1 cl if (2 * bootsize > (fp * cd_secsize - NEXT68K_LABEL_SIZE)) 178 1.1 cl /* can only fit one copy */ 179 1.1 cl b0 = b1 = NEXT68K_LABEL_SIZE / cd_secsize; 180 1.1 cl else { 181 1.8 msaitoh if (2 * bootsize > (fp * cd_secsize - 182 1.7 tsutsui NEXT68K_LABEL_DEFAULTBOOT0_1 * 183 1.7 tsutsui params->sectorsize)) 184 1.1 cl /* can fit two copies starting after label */ 185 1.1 cl b0 = NEXT68K_LABEL_SIZE / cd_secsize; 186 1.1 cl else 187 1.1 cl /* can fit two copies starting at default 1 */ 188 1.1 cl b0 = NEXT68K_LABEL_DEFAULTBOOT0_1 / 189 1.1 cl sec_netonb_mult; 190 1.1 cl /* try to fit 2nd copy at default 2 */ 191 1.1 cl b1 = NEXT68K_LABEL_DEFAULTBOOT0_2 / sec_netonb_mult; 192 1.1 cl if (fp < b1) 193 1.1 cl b1 = fp; 194 1.1 cl if (bootsize / cd_secsize > (fp - b1)) 195 1.1 cl /* fit 2nd copy before front porch */ 196 1.1 cl b1 = fp - bootsize / cd_secsize; 197 1.1 cl } 198 1.1 cl } 199 1.6 lukem if (next68klabel->cd_boot_blkno[0] != (int32_t)htobe32(b0)) { 200 1.1 cl next68klabel->cd_boot_blkno[0] = htobe32(b0); 201 1.1 cl labelupdated = 1; 202 1.1 cl } 203 1.6 lukem if (next68klabel->cd_boot_blkno[1] != (int32_t)htobe32(b1)) { 204 1.1 cl next68klabel->cd_boot_blkno[1] = htobe32(b1); 205 1.1 cl labelupdated = 1; 206 1.1 cl } 207 1.1 cl if (params->flags & IB_VERBOSE) 208 1.10 andvar printf("Boot program locations%s: %d %d\n", 209 1.1 cl labelupdated ? " updated" : "", b0 * sec_netonb_mult, 210 1.1 cl b1 * sec_netonb_mult); 211 1.1 cl 212 1.1 cl if (params->flags & IB_NOWRITE) { 213 1.1 cl retval = 1; 214 1.1 cl goto done; 215 1.1 cl } 216 1.1 cl 217 1.1 cl /* 218 1.1 cl * Write the updated next68k disklabel 219 1.1 cl */ 220 1.1 cl if (labelupdated) { 221 1.1 cl if (params->flags & IB_VERBOSE) 222 1.1 cl printf ("Writing updated label\n"); 223 1.1 cl *checksum = htobe16(nextstep_checksum (next68klabel, 224 1.1 cl checksum)); 225 1.1 cl rv = pwrite(params->fsfd, next68klabel, NEXT68K_LABEL_SIZE, 226 1.7 tsutsui NEXT68K_LABEL_SECTOR * params->sectorsize + 227 1.7 tsutsui NEXT68K_LABEL_OFFSET); 228 1.1 cl if (rv == -1) { 229 1.1 cl warn("Writing `%s'", params->filesystem); 230 1.1 cl goto done; 231 1.1 cl } 232 1.1 cl if (rv != NEXT68K_LABEL_SIZE) { 233 1.1 cl warnx("Writing `%s': short write", params->filesystem); 234 1.1 cl goto done; 235 1.1 cl } 236 1.1 cl } 237 1.8 msaitoh 238 1.1 cl b0 *= sec_netonb_mult; 239 1.1 cl b1 *= sec_netonb_mult; 240 1.1 cl 241 1.1 cl /* 242 1.1 cl * Write boot program to locations b0 and b1 (if different). 243 1.1 cl */ 244 1.1 cl for (;;) { 245 1.1 cl if (params->flags & IB_VERBOSE) 246 1.1 cl printf ("Writing boot program at %d\n", b0); 247 1.7 tsutsui rv = pwrite(params->fsfd, bootbuf, bootsize, 248 1.7 tsutsui b0 * params->sectorsize); 249 1.1 cl if (rv == -1) { 250 1.1 cl warn("Writing `%s' at %d", params->filesystem, b0); 251 1.1 cl goto done; 252 1.1 cl } 253 1.6 lukem if ((size_t)rv != bootsize) { 254 1.8 msaitoh warnx("Writing `%s' at %d: short write", 255 1.1 cl params->filesystem, b0); 256 1.1 cl goto done; 257 1.1 cl } 258 1.1 cl if (b0 == b1) 259 1.1 cl break; 260 1.1 cl b0 = b1; 261 1.1 cl } 262 1.1 cl 263 1.1 cl retval = 1; 264 1.1 cl 265 1.1 cl done: 266 1.1 cl if (bootbuf) 267 1.1 cl free(bootbuf); 268 1.1 cl if (next68klabel) 269 1.1 cl free(next68klabel); 270 1.1 cl return retval; 271 1.1 cl } 272