1/* 2 * Copyright (c) KATO Takenori, 2000. 3 * 4 * All rights reserved. Unpublished rights reserved under the copyright 5 * laws of Japan. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer as 13 * the first lines of this file unmodified. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright (c) 1999 Robert Nordier 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 49 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 50 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 51 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 52 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 54 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 55 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 58#include <sys/cdefs.h> 59__FBSDID("$FreeBSD$"); 60 61#include <sys/param.h> 62#include <sys/diskpc98.h> 63#include <sys/stat.h> 64 65#include <err.h> 66#include <errno.h> 67#include <fcntl.h> 68#include <libgeom.h> 69#include <paths.h> 70#include <stdio.h> 71#include <stdlib.h> 72#include <string.h> 73#include <unistd.h> 74 75#define BOOTSIZE 0x2000 76#define IPLSIZE 512 /* IPL size */ 77#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 78#define BOOTMENUOFF 0x400 79 80u_char boot0buf[BOOTSIZE]; 81u_char ipl[IPLSIZE]; 82u_char menu[BOOTMENUSIZE]; 83 84static int read_boot(const char *, u_char *); 85static int write_boot(const char *, u_char *); 86static char *mkrdev(const char *); 87static void usage(void); 88 89/* 90 * Boot manager installation/configuration utility. 91 */ 92int 93main(int argc, char *argv[]) 94{ 95 char *endptr; 96 const char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 97 char *iplbakpath = NULL, *menubakpath = NULL; 98 char *disk; 99 int B_flag = 0; 100 int c; 101 int fd1; 102 int n; 103 int secsize = 512; 104 int v_flag = 0, version; 105 106 while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 107 switch (c) { 108 case 'B': 109 B_flag = 1; 110 break; 111 case 'F': 112 menubakpath = optarg; 113 break; 114 case 'f': 115 iplbakpath = optarg; 116 break; 117 case 'i': 118 iplpath = optarg; 119 break; 120 case 'm': 121 menupath = optarg; 122 break; 123 case 's': 124 secsize = strtol(optarg, &endptr, 0); 125 if (errno || *optarg == '\0' || *endptr) 126 errx(1, "%s: Bad argument to -s option", 127 optarg); 128 switch (secsize) { 129 case 256: 130 case 512: 131 case 1024: 132 case 2048: 133 break; 134 default: 135 errx(1, "%s: unsupported sector size", optarg); 136 break; 137 } 138 break; 139 case 'v': 140 v_flag = 1; 141 version = strtol(optarg, &endptr, 0); 142 if (errno || *optarg == '\0' || *endptr || 143 version < 0 || version > 255) 144 errx(1, "%s: Bad argument to -v option", 145 optarg); 146 break; 147 default: 148 usage(); 149 /* NOTREACHED */ 150 break; 151 } 152 } 153 argc -= optind; 154 argv += optind; 155 if (argc != 1) 156 usage(); 157 disk = mkrdev(*argv); 158 159 read_boot(disk, boot0buf); 160 161 if (iplbakpath != NULL) { 162 fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 163 if (fd1 < 0) 164 err(1, "%s", iplbakpath); 165 n = write(fd1, boot0buf, IPLSIZE); 166 if (n == -1) 167 err(1, "%s", iplbakpath); 168 if (n != IPLSIZE) 169 errx(1, "%s: short write", iplbakpath); 170 close(fd1); 171 } 172 173 if (menubakpath != NULL) { 174 fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 175 if (fd1 < 0) 176 err(1, "%s", menubakpath); 177 n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 178 if (n == -1) 179 err(1, "%s", menubakpath); 180 if (n != BOOTMENUSIZE) 181 errx(1, "%s: short write", menubakpath); 182 close(fd1); 183 } 184 185 if (B_flag) { 186 /* Read IPL (boot0). */ 187 fd1 = open(iplpath, O_RDONLY); 188 if (fd1 < 0) 189 err(1, "%s", disk); 190 n = read(fd1, ipl, IPLSIZE); 191 if (n < 0) 192 err(1, "%s", iplpath); 193 if (n != IPLSIZE) 194 errx(1, "%s: invalid file", iplpath); 195 close(fd1); 196 197 /* Read HDD boot menu (boot0.5). */ 198 fd1 = open(menupath, O_RDONLY); 199 if (fd1 < 0) 200 err(1, "%s", disk); 201 n = read(fd1, menu, BOOTMENUSIZE); 202 if (n < 0) 203 err(1, "%s", menupath); 204 if (n != BOOTMENUSIZE) 205 errx(1, "%s: invalid file", menupath); 206 close(fd1); 207 208 memcpy(boot0buf, ipl, IPLSIZE); 209 memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 210 } 211 212 /* Set version number field. */ 213 if (v_flag) 214 *(boot0buf + secsize - 4) = (u_char)version; 215 216 if (B_flag || v_flag) 217 write_boot(disk, boot0buf); 218 219 return 0; 220} 221 222static int 223read_boot(const char *disk, u_char *boot) 224{ 225 int fd, n; 226 227 /* Read IPL, partition table and HDD boot menu. */ 228 fd = open(disk, O_RDONLY); 229 if (fd < 0) 230 err(1, "%s", disk); 231 n = read(fd, boot, BOOTSIZE); 232 if (n != BOOTSIZE) 233 errx(1, "%s: short read", disk); 234 close(fd); 235 236 return 0; 237} 238 239static int 240write_boot(const char *disk, u_char *boot) 241{ 242 int fd, n, i; 243 char buf[MAXPATHLEN]; 244 const char *q; 245 struct gctl_req *grq; 246 247 fd = open(disk, O_WRONLY, 0666); 248 if (fd != -1) { 249 if ((n = write(fd, boot, BOOTSIZE)) < 0) 250 err(1, "%s", disk); 251 if (n != BOOTSIZE) 252 errx(1, "%s: short write", disk); 253 close(fd); 254 return 0; 255 } 256 257 grq = gctl_get_handle(); 258 gctl_ro_param(grq, "verb", -1, "write PC98"); 259 gctl_ro_param(grq, "class", -1, "PC98"); 260 q = strrchr(disk, '/'); 261 if (q == NULL) 262 q = disk; 263 else 264 q++; 265 gctl_ro_param(grq, "geom", -1, q); 266 gctl_ro_param(grq, "data", BOOTSIZE, boot); 267 q = gctl_issue(grq); 268 if (q == NULL) 269 return 0; 270 271 warnx("%s: %s", disk, q); 272 gctl_free(grq); 273 274 for (i = 0; i < PC98_NPARTS; i++) { 275 snprintf(buf, sizeof(buf), "%ss%d", disk, i + 1); 276 fd = open(buf, O_RDONLY); 277 if (fd < 0) 278 continue; 279 n = ioctl(fd, DIOCSPC98, boot); 280 if (n != 0) 281 err(1, "%s: ioctl DIOCSPC98", disk); 282 close(fd); 283 return 0; 284 } 285 286 err(1, "%s", disk); 287} 288 289/* 290 * Produce a device path for a "canonical" name, where appropriate. 291 */ 292static char * 293mkrdev(const char *fname) 294{ 295 char buf[MAXPATHLEN]; 296 char *s; 297 298 if (!strchr(fname, '/')) { 299 snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 300 s = strdup(buf); 301 } else 302 s = strdup(fname); 303 304 if (s == NULL) 305 errx(1, "No more memory"); 306 return s; 307} 308 309/* 310 * Display usage information. 311 */ 312static void 313usage(void) 314{ 315 fprintf(stderr, 316 "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n" 317 " [-f ipl.bak][-F menu.bak] disk\n"); 318 exit(1); 319} 320