164126Skato/* 264126Skato * Copyright (c) KATO Takenori, 2000. 364126Skato * 464126Skato * All rights reserved. Unpublished rights reserved under the copyright 564126Skato * laws of Japan. 664126Skato * 764126Skato * Redistribution and use in source and binary forms, with or without 864126Skato * modification, are permitted provided that the following conditions 964126Skato * are met: 1064126Skato * 1164126Skato * 1. Redistributions of source code must retain the above copyright 1264126Skato * notice, this list of conditions and the following disclaimer as 1364126Skato * the first lines of this file unmodified. 1464126Skato * 2. Redistributions in binary form must reproduce the above copyright 1564126Skato * notice, this list of conditions and the following disclaimer in the 1664126Skato * documentation and/or other materials provided with the distribution. 1764126Skato * 3. The name of the author may not be used to endorse or promote products 1864126Skato * derived from this software without specific prior written permission. 1964126Skato * 2064126Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2164126Skato * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2264126Skato * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2364126Skato * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2464126Skato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2564126Skato * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2664126Skato * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2764126Skato * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2864126Skato * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2964126Skato * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3064126Skato */ 3164126Skato 3264126Skato/* 3364126Skato * Copyright (c) 1999 Robert Nordier 3464126Skato * All rights reserved. 3564126Skato * 3664126Skato * Redistribution and use in source and binary forms, with or without 3764126Skato * modification, are permitted provided that the following conditions 3864126Skato * are met: 3964126Skato * 1. Redistributions of source code must retain the above copyright 4064126Skato * notice, this list of conditions and the following disclaimer. 4164126Skato * 2. Redistributions in binary form must reproduce the above copyright 4264126Skato * notice, this list of conditions and the following disclaimer in the 4364126Skato * documentation and/or other materials provided with the distribution. 4464126Skato * 4564126Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 4664126Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4764126Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4864126Skato * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 4964126Skato * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 5064126Skato * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 5164126Skato * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 5264126Skato * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 5364126Skato * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 5464126Skato * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 5564126Skato * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5664126Skato */ 5764126Skato 58148049Snyan#include <sys/cdefs.h> 59148049Snyan__FBSDID("$FreeBSD$"); 60148049Snyan 6164126Skato#include <sys/param.h> 62148049Snyan#include <sys/diskpc98.h> 6364126Skato#include <sys/stat.h> 6464126Skato 6564126Skato#include <err.h> 6664126Skato#include <errno.h> 6764126Skato#include <fcntl.h> 68148064Snyan#include <libgeom.h> 6964126Skato#include <paths.h> 7064126Skato#include <stdio.h> 7164126Skato#include <stdlib.h> 7264126Skato#include <string.h> 7364126Skato#include <unistd.h> 7464126Skato 75110678Snyan#define BOOTSIZE 0x2000 7664126Skato#define IPLSIZE 512 /* IPL size */ 7764126Skato#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 7864126Skato#define BOOTMENUOFF 0x400 7964126Skato 80110678Snyanu_char boot0buf[BOOTSIZE]; 81110678Snyanu_char ipl[IPLSIZE]; 82110678Snyanu_char menu[BOOTMENUSIZE]; 8364126Skato 84148049Snyanstatic int read_boot(const char *, u_char *); 85148049Snyanstatic int write_boot(const char *, u_char *); 86148064Snyanstatic char *mkrdev(const char *); 87148049Snyanstatic void usage(void); 88148049Snyan 8964126Skato/* 90148049Snyan * Boot manager installation/configuration utility. 9164126Skato */ 9264126Skatoint 9364126Skatomain(int argc, char *argv[]) 9464126Skato{ 9564126Skato char *endptr; 9678715Sdd const char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 9764126Skato char *iplbakpath = NULL, *menubakpath = NULL; 9864126Skato char *disk; 9964126Skato int B_flag = 0; 10064126Skato int c; 101110678Snyan int fd1; 10264126Skato int n; 10364126Skato int secsize = 512; 10464126Skato int v_flag = 0, version; 10564126Skato 10664126Skato while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 10764126Skato switch (c) { 10864126Skato case 'B': 10964126Skato B_flag = 1; 11064126Skato break; 11164126Skato case 'F': 11264126Skato menubakpath = optarg; 11364126Skato break; 11464126Skato case 'f': 11564126Skato iplbakpath = optarg; 11664126Skato break; 11764126Skato case 'i': 11864126Skato iplpath = optarg; 11964126Skato break; 12064126Skato case 'm': 12164126Skato menupath = optarg; 12264126Skato break; 12364126Skato case 's': 12464126Skato secsize = strtol(optarg, &endptr, 0); 125126652Snyan if (errno || *optarg == '\0' || *endptr) 12664126Skato errx(1, "%s: Bad argument to -s option", 12764126Skato optarg); 12864126Skato switch (secsize) { 12964126Skato case 256: 13064126Skato case 512: 13164126Skato case 1024: 13264126Skato case 2048: 13364126Skato break; 13464126Skato default: 13564126Skato errx(1, "%s: unsupported sector size", optarg); 13664126Skato break; 13764126Skato } 13864126Skato break; 13964126Skato case 'v': 14064126Skato v_flag = 1; 14164126Skato version = strtol(optarg, &endptr, 0); 142126652Snyan if (errno || *optarg == '\0' || *endptr || 14364126Skato version < 0 || version > 255) 144174764Simp errx(1, "%s: Bad argument to -v option", 14564126Skato optarg); 14664126Skato break; 14764126Skato default: 14864126Skato usage(); 14964126Skato /* NOTREACHED */ 15064126Skato break; 15164126Skato } 15264126Skato } 15364126Skato argc -= optind; 15464126Skato argv += optind; 15564126Skato if (argc != 1) 15664126Skato usage(); 15764126Skato disk = mkrdev(*argv); 15864126Skato 159110678Snyan read_boot(disk, boot0buf); 16064126Skato 16164126Skato if (iplbakpath != NULL) { 16264126Skato fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 16364126Skato if (fd1 < 0) 16464126Skato err(1, "%s", iplbakpath); 16564126Skato n = write(fd1, boot0buf, IPLSIZE); 16664126Skato if (n == -1) 16764126Skato err(1, "%s", iplbakpath); 16864126Skato if (n != IPLSIZE) 16964126Skato errx(1, "%s: short write", iplbakpath); 17064126Skato close(fd1); 17164126Skato } 17264126Skato 17364126Skato if (menubakpath != NULL) { 17464126Skato fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 17564126Skato if (fd1 < 0) 17664126Skato err(1, "%s", menubakpath); 17764126Skato n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 17864126Skato if (n == -1) 17964126Skato err(1, "%s", menubakpath); 18064126Skato if (n != BOOTMENUSIZE) 18164126Skato errx(1, "%s: short write", menubakpath); 18264126Skato close(fd1); 18364126Skato } 18464126Skato 18564126Skato if (B_flag) { 18664126Skato /* Read IPL (boot0). */ 18764126Skato fd1 = open(iplpath, O_RDONLY); 18864126Skato if (fd1 < 0) 18964126Skato err(1, "%s", disk); 19064126Skato n = read(fd1, ipl, IPLSIZE); 19164126Skato if (n < 0) 19264126Skato err(1, "%s", iplpath); 19364126Skato if (n != IPLSIZE) 19464126Skato errx(1, "%s: invalid file", iplpath); 19564126Skato close(fd1); 19664126Skato 19764126Skato /* Read HDD boot menu (boot0.5). */ 19864126Skato fd1 = open(menupath, O_RDONLY); 19964126Skato if (fd1 < 0) 20064126Skato err(1, "%s", disk); 20164126Skato n = read(fd1, menu, BOOTMENUSIZE); 20264126Skato if (n < 0) 20364126Skato err(1, "%s", menupath); 20464126Skato if (n != BOOTMENUSIZE) 20564126Skato errx(1, "%s: invalid file", menupath); 20664126Skato close(fd1); 20764126Skato 20864126Skato memcpy(boot0buf, ipl, IPLSIZE); 20964126Skato memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 21064126Skato } 21164126Skato 21264126Skato /* Set version number field. */ 21364126Skato if (v_flag) 21464126Skato *(boot0buf + secsize - 4) = (u_char)version; 21564126Skato 216110678Snyan if (B_flag || v_flag) 217110678Snyan write_boot(disk, boot0buf); 218110678Snyan 21964126Skato return 0; 22064126Skato} 221148049Snyan 222148049Snyanstatic int 223148049Snyanread_boot(const char *disk, u_char *boot) 224148049Snyan{ 225148049Snyan int fd, n; 226148049Snyan 227148049Snyan /* Read IPL, partition table and HDD boot menu. */ 228148049Snyan fd = open(disk, O_RDONLY); 229148049Snyan if (fd < 0) 230148049Snyan err(1, "%s", disk); 231148049Snyan n = read(fd, boot, BOOTSIZE); 232148049Snyan if (n != BOOTSIZE) 233148049Snyan errx(1, "%s: short read", disk); 234148049Snyan close(fd); 235148049Snyan 236148049Snyan return 0; 237148049Snyan} 238148049Snyan 239148049Snyanstatic int 240148049Snyanwrite_boot(const char *disk, u_char *boot) 241148049Snyan{ 242148049Snyan int fd, n, i; 243148049Snyan char buf[MAXPATHLEN]; 244148064Snyan const char *q; 245148064Snyan struct gctl_req *grq; 246148049Snyan 247148064Snyan fd = open(disk, O_WRONLY, 0666); 248148049Snyan if (fd != -1) { 249148049Snyan if ((n = write(fd, boot, BOOTSIZE)) < 0) 250148049Snyan err(1, "%s", disk); 251148049Snyan if (n != BOOTSIZE) 252148049Snyan errx(1, "%s: short write", disk); 253148049Snyan close(fd); 254148049Snyan return 0; 255148049Snyan } 256148049Snyan 257148064Snyan grq = gctl_get_handle(); 258148064Snyan gctl_ro_param(grq, "verb", -1, "write PC98"); 259148064Snyan gctl_ro_param(grq, "class", -1, "PC98"); 260148064Snyan q = strrchr(disk, '/'); 261148064Snyan if (q == NULL) 262148064Snyan q = disk; 263148064Snyan else 264148064Snyan q++; 265148064Snyan gctl_ro_param(grq, "geom", -1, q); 266148064Snyan gctl_ro_param(grq, "data", BOOTSIZE, boot); 267148064Snyan q = gctl_issue(grq); 268148064Snyan if (q == NULL) 269148064Snyan return 0; 270148064Snyan 271148064Snyan warnx("%s: %s", disk, q); 272148064Snyan gctl_free(grq); 273148064Snyan 274254015Smarcel for (i = 0; i < PC98_NPARTS; i++) { 275148049Snyan snprintf(buf, sizeof(buf), "%ss%d", disk, i + 1); 276148049Snyan fd = open(buf, O_RDONLY); 277148049Snyan if (fd < 0) 278148049Snyan continue; 279148049Snyan n = ioctl(fd, DIOCSPC98, boot); 280148049Snyan if (n != 0) 281148049Snyan err(1, "%s: ioctl DIOCSPC98", disk); 282148049Snyan close(fd); 283148049Snyan return 0; 284148049Snyan } 285148049Snyan 286148049Snyan err(1, "%s", disk); 287148049Snyan} 288148049Snyan 289148049Snyan/* 290148049Snyan * Produce a device path for a "canonical" name, where appropriate. 291148049Snyan */ 292148049Snyanstatic char * 293148064Snyanmkrdev(const char *fname) 294148049Snyan{ 295148049Snyan char buf[MAXPATHLEN]; 296148049Snyan char *s; 297148049Snyan 298148049Snyan if (!strchr(fname, '/')) { 299148064Snyan snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 300148064Snyan s = strdup(buf); 301148064Snyan } else 302148064Snyan s = strdup(fname); 303148064Snyan 304148064Snyan if (s == NULL) 305148064Snyan errx(1, "No more memory"); 306148049Snyan return s; 307148049Snyan} 308148049Snyan 309148049Snyan/* 310148049Snyan * Display usage information. 311148049Snyan */ 312148049Snyanstatic void 313148049Snyanusage(void) 314148049Snyan{ 315148049Snyan fprintf(stderr, 316148049Snyan "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n" 317148049Snyan " [-f ipl.bak][-F menu.bak] disk\n"); 318148049Snyan exit(1); 319148049Snyan} 320