boot98cfg.c revision 174764
1133759Srwatson/* 2133759Srwatson * Copyright (c) KATO Takenori, 2000. 3133759Srwatson * 4133759Srwatson * All rights reserved. Unpublished rights reserved under the copyright 5133759Srwatson * laws of Japan. 6133759Srwatson * 7133759Srwatson * Redistribution and use in source and binary forms, with or without 8133759Srwatson * modification, are permitted provided that the following conditions 9133759Srwatson * are met: 10133759Srwatson * 11133759Srwatson * 1. Redistributions of source code must retain the above copyright 12133759Srwatson * notice, this list of conditions and the following disclaimer as 13133759Srwatson * the first lines of this file unmodified. 14133759Srwatson * 2. Redistributions in binary form must reproduce the above copyright 15133759Srwatson * notice, this list of conditions and the following disclaimer in the 16133759Srwatson * documentation and/or other materials provided with the distribution. 17133759Srwatson * 3. The name of the author may not be used to endorse or promote products 18133759Srwatson * derived from this software without specific prior written permission. 19133759Srwatson * 20133759Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21133759Srwatson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22133759Srwatson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23133759Srwatson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24133759Srwatson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25133759Srwatson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26133759Srwatson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27133759Srwatson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28133759Srwatson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29133759Srwatson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30133770Srwatson */ 31133759Srwatson 32133770Srwatson/* 33133770Srwatson * Copyright (c) 1999 Robert Nordier 34133770Srwatson * All rights reserved. 35133770Srwatson * 36133759Srwatson * Redistribution and use in source and binary forms, with or without 37133759Srwatson * modification, are permitted provided that the following conditions 38133759Srwatson * are met: 39133759Srwatson * 1. Redistributions of source code must retain the above copyright 40133759Srwatson * notice, this list of conditions and the following disclaimer. 41133759Srwatson * 2. Redistributions in binary form must reproduce the above copyright 42133759Srwatson * notice, this list of conditions and the following disclaimer in the 43133759Srwatson * documentation and/or other materials provided with the distribution. 44133759Srwatson * 45133759Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 46133759Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47214631Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 48133759Srwatson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 49133759Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 50133759Srwatson * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 51133759Srwatson * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 52142722Sobrien * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53133759Srwatson * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 54133759Srwatson * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 55133759Srwatson * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56142722Sobrien */ 57133759Srwatson 58133759Srwatson#include <sys/cdefs.h> 59133759Srwatson__FBSDID("$FreeBSD: head/usr.sbin/boot98cfg/boot98cfg.c 174764 2007-12-19 03:31:44Z imp $"); 60133759Srwatson 61133759Srwatson#include <sys/param.h> 62133759Srwatson#include <sys/diskpc98.h> 63133759Srwatson#include <sys/stat.h> 64133759Srwatson 65133759Srwatson#include <err.h> 66133759Srwatson#include <errno.h> 67133759Srwatson#include <fcntl.h> 68133759Srwatson#include <libgeom.h> 69133759Srwatson#include <paths.h> 70133759Srwatson#include <stdio.h> 71142722Sobrien#include <stdlib.h> 72133759Srwatson#include <string.h> 73133759Srwatson#include <unistd.h> 74133759Srwatson 75133759Srwatson#define BOOTSIZE 0x2000 76133759Srwatson#define IPLSIZE 512 /* IPL size */ 77142722Sobrien#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 78142722Sobrien#define BOOTMENUOFF 0x400 79133759Srwatson 80133759Srwatsonu_char boot0buf[BOOTSIZE]; 81133759Srwatsonu_char ipl[IPLSIZE]; 82133759Srwatsonu_char menu[BOOTMENUSIZE]; 83133759Srwatson 84133759Srwatsonstatic int read_boot(const char *, u_char *); 85133759Srwatsonstatic int write_boot(const char *, u_char *); 86133759Srwatsonstatic char *mkrdev(const char *); 87133759Srwatsonstatic void usage(void); 88133759Srwatson 89133759Srwatson/* 90142722Sobrien * Boot manager installation/configuration utility. 91142722Sobrien */ 92133759Srwatsonint 93133759Srwatsonmain(int argc, char *argv[]) 94133759Srwatson{ 95133759Srwatson char *endptr; 96133759Srwatson const char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 97133759Srwatson char *iplbakpath = NULL, *menubakpath = NULL; 98133759Srwatson char *disk; 99133759Srwatson int B_flag = 0; 100133759Srwatson int c; 101133759Srwatson int fd1; 102133759Srwatson int n; 103133759Srwatson int secsize = 512; 104133759Srwatson int v_flag = 0, version; 105133759Srwatson 106133759Srwatson while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 107133759Srwatson switch (c) { 108133759Srwatson case 'B': 109133759Srwatson B_flag = 1; 110133759Srwatson break; 111133759Srwatson case 'F': 112133759Srwatson menubakpath = optarg; 113133759Srwatson break; 114142722Sobrien case 'f': 115142722Sobrien iplbakpath = optarg; 116142722Sobrien break; 117142722Sobrien case 'i': 118142722Sobrien iplpath = optarg; 119142722Sobrien break; 120142765Spjd case 'm': 121142722Sobrien menupath = optarg; 122142722Sobrien break; 123142722Sobrien case 's': 124142722Sobrien secsize = strtol(optarg, &endptr, 0); 125142722Sobrien if (errno || *optarg == '\0' || *endptr) 126142722Sobrien errx(1, "%s: Bad argument to -s option", 127142722Sobrien optarg); 128142722Sobrien switch (secsize) { 129142722Sobrien case 256: 130142722Sobrien case 512: 131142722Sobrien case 1024: 132142722Sobrien case 2048: 133142722Sobrien break; 134142722Sobrien default: 135133759Srwatson errx(1, "%s: unsupported sector size", optarg); 136133759Srwatson break; 137133759Srwatson } 138133759Srwatson break; 139133759Srwatson case 'v': 140133759Srwatson v_flag = 1; 141133759Srwatson version = strtol(optarg, &endptr, 0); 142133759Srwatson if (errno || *optarg == '\0' || *endptr || 143133759Srwatson version < 0 || version > 255) 144133759Srwatson errx(1, "%s: Bad argument to -v option", 145133759Srwatson optarg); 146133759Srwatson break; 147133759Srwatson default: 148133759Srwatson usage(); 149142722Sobrien /* NOTREACHED */ 150142722Sobrien break; 151133759Srwatson } 152133759Srwatson } 153133759Srwatson argc -= optind; 154142722Sobrien argv += optind; 155133759Srwatson if (argc != 1) 156133759Srwatson usage(); 157133759Srwatson disk = mkrdev(*argv); 158133759Srwatson 159133759Srwatson read_boot(disk, boot0buf); 160133759Srwatson 161133759Srwatson if (iplbakpath != NULL) { 162133759Srwatson fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 163133759Srwatson if (fd1 < 0) 164133759Srwatson err(1, "%s", iplbakpath); 165133759Srwatson n = write(fd1, boot0buf, IPLSIZE); 166133759Srwatson if (n == -1) 167133759Srwatson err(1, "%s", iplbakpath); 168133759Srwatson if (n != IPLSIZE) 169133759Srwatson errx(1, "%s: short write", iplbakpath); 170133759Srwatson close(fd1); 171133759Srwatson } 172133759Srwatson 173133759Srwatson if (menubakpath != NULL) { 174133759Srwatson fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 175133759Srwatson if (fd1 < 0) 176133759Srwatson err(1, "%s", menubakpath); 177133759Srwatson n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 178133759Srwatson if (n == -1) 179133759Srwatson err(1, "%s", menubakpath); 180133759Srwatson if (n != BOOTMENUSIZE) 181133759Srwatson errx(1, "%s: short write", menubakpath); 182133759Srwatson close(fd1); 183133759Srwatson } 184133759Srwatson 185133759Srwatson if (B_flag) { 186133759Srwatson /* Read IPL (boot0). */ 187133759Srwatson fd1 = open(iplpath, O_RDONLY); 188133759Srwatson if (fd1 < 0) 189133759Srwatson err(1, "%s", disk); 190133759Srwatson n = read(fd1, ipl, IPLSIZE); 191133759Srwatson if (n < 0) 192133759Srwatson err(1, "%s", iplpath); 193133759Srwatson if (n != IPLSIZE) 194133759Srwatson errx(1, "%s: invalid file", iplpath); 195133759Srwatson close(fd1); 196133759Srwatson 197133759Srwatson /* Read HDD boot menu (boot0.5). */ 198133759Srwatson fd1 = open(menupath, O_RDONLY); 199133759Srwatson if (fd1 < 0) 200133759Srwatson err(1, "%s", disk); 201133759Srwatson n = read(fd1, menu, BOOTMENUSIZE); 202133759Srwatson if (n < 0) 203133759Srwatson err(1, "%s", menupath); 204133759Srwatson if (n != BOOTMENUSIZE) 205133759Srwatson errx(1, "%s: invalid file", menupath); 206174898Srwatson close(fd1); 207133759Srwatson 208133759Srwatson memcpy(boot0buf, ipl, IPLSIZE); 209133759Srwatson memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 210133759Srwatson } 211133759Srwatson 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 < NDOSPART; 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