boot98cfg.c revision 148049
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: head/usr.sbin/boot98cfg/boot98cfg.c 148049 2005-07-15 14:37:40Z nyan $"); 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> 6864126Skato#include <paths.h> 6964126Skato#include <stdio.h> 7064126Skato#include <stdlib.h> 7164126Skato#include <string.h> 7264126Skato#include <unistd.h> 7364126Skato 74110678Snyan#define BOOTSIZE 0x2000 7564126Skato#define IPLSIZE 512 /* IPL size */ 7664126Skato#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 7764126Skato#define BOOTMENUOFF 0x400 7864126Skato 79110678Snyanu_char boot0buf[BOOTSIZE]; 80110678Snyanu_char ipl[IPLSIZE]; 81110678Snyanu_char menu[BOOTMENUSIZE]; 8264126Skato 83148049Snyanstatic int read_boot(const char *, u_char *); 84148049Snyanstatic int write_boot(const char *, u_char *); 85148049Snyanstatic char *mkrdev(char *); 86148049Snyanstatic void usage(void); 87148049Snyan 8864126Skato/* 89148049Snyan * Boot manager installation/configuration utility. 9064126Skato */ 9164126Skatoint 9264126Skatomain(int argc, char *argv[]) 9364126Skato{ 9464126Skato char *endptr; 9578715Sdd const char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 9664126Skato char *iplbakpath = NULL, *menubakpath = NULL; 9764126Skato char *disk; 9864126Skato int B_flag = 0; 9964126Skato int c; 100110678Snyan int fd1; 10164126Skato int n; 10264126Skato int secsize = 512; 10364126Skato int v_flag = 0, version; 10464126Skato 10564126Skato while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 10664126Skato switch (c) { 10764126Skato case 'B': 10864126Skato B_flag = 1; 10964126Skato break; 11064126Skato case 'F': 11164126Skato menubakpath = optarg; 11264126Skato break; 11364126Skato case 'f': 11464126Skato iplbakpath = optarg; 11564126Skato break; 11664126Skato case 'i': 11764126Skato iplpath = optarg; 11864126Skato break; 11964126Skato case 'm': 12064126Skato menupath = optarg; 12164126Skato break; 12264126Skato case 's': 12364126Skato secsize = strtol(optarg, &endptr, 0); 124126652Snyan if (errno || *optarg == '\0' || *endptr) 12564126Skato errx(1, "%s: Bad argument to -s option", 12664126Skato optarg); 12764126Skato switch (secsize) { 12864126Skato case 256: 12964126Skato case 512: 13064126Skato case 1024: 13164126Skato case 2048: 13264126Skato break; 13364126Skato default: 13464126Skato errx(1, "%s: unsupported sector size", optarg); 13564126Skato break; 13664126Skato } 13764126Skato break; 13864126Skato case 'v': 13964126Skato v_flag = 1; 14064126Skato version = strtol(optarg, &endptr, 0); 141126652Snyan if (errno || *optarg == '\0' || *endptr || 14264126Skato version < 0 || version > 255) 14364126Skato errx(1, "%s: Bad argument to -s option", 14464126Skato optarg); 14564126Skato break; 14664126Skato default: 14764126Skato usage(); 14864126Skato /* NOTREACHED */ 14964126Skato break; 15064126Skato } 15164126Skato } 15264126Skato argc -= optind; 15364126Skato argv += optind; 15464126Skato if (argc != 1) 15564126Skato usage(); 15664126Skato disk = mkrdev(*argv); 15764126Skato 158110678Snyan read_boot(disk, boot0buf); 15964126Skato 16064126Skato if (iplbakpath != NULL) { 16164126Skato fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 16264126Skato if (fd1 < 0) 16364126Skato err(1, "%s", iplbakpath); 16464126Skato n = write(fd1, boot0buf, IPLSIZE); 16564126Skato if (n == -1) 16664126Skato err(1, "%s", iplbakpath); 16764126Skato if (n != IPLSIZE) 16864126Skato errx(1, "%s: short write", iplbakpath); 16964126Skato close(fd1); 17064126Skato } 17164126Skato 17264126Skato if (menubakpath != NULL) { 17364126Skato fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 17464126Skato if (fd1 < 0) 17564126Skato err(1, "%s", menubakpath); 17664126Skato n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 17764126Skato if (n == -1) 17864126Skato err(1, "%s", menubakpath); 17964126Skato if (n != BOOTMENUSIZE) 18064126Skato errx(1, "%s: short write", menubakpath); 18164126Skato close(fd1); 18264126Skato } 18364126Skato 18464126Skato if (B_flag) { 18564126Skato /* Read IPL (boot0). */ 18664126Skato fd1 = open(iplpath, O_RDONLY); 18764126Skato if (fd1 < 0) 18864126Skato err(1, "%s", disk); 18964126Skato n = read(fd1, ipl, IPLSIZE); 19064126Skato if (n < 0) 19164126Skato err(1, "%s", iplpath); 19264126Skato if (n != IPLSIZE) 19364126Skato errx(1, "%s: invalid file", iplpath); 19464126Skato close(fd1); 19564126Skato 19664126Skato /* Read HDD boot menu (boot0.5). */ 19764126Skato fd1 = open(menupath, O_RDONLY); 19864126Skato if (fd1 < 0) 19964126Skato err(1, "%s", disk); 20064126Skato n = read(fd1, menu, BOOTMENUSIZE); 20164126Skato if (n < 0) 20264126Skato err(1, "%s", menupath); 20364126Skato if (n != BOOTMENUSIZE) 20464126Skato errx(1, "%s: invalid file", menupath); 20564126Skato close(fd1); 20664126Skato 20764126Skato memcpy(boot0buf, ipl, IPLSIZE); 20864126Skato memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 20964126Skato } 21064126Skato 21164126Skato /* Set version number field. */ 21264126Skato if (v_flag) 21364126Skato *(boot0buf + secsize - 4) = (u_char)version; 21464126Skato 215110678Snyan if (B_flag || v_flag) 216110678Snyan write_boot(disk, boot0buf); 217110678Snyan 21864126Skato return 0; 21964126Skato} 220148049Snyan 221148049Snyanstatic int 222148049Snyanread_boot(const char *disk, u_char *boot) 223148049Snyan{ 224148049Snyan int fd, n; 225148049Snyan 226148049Snyan /* Read IPL, partition table and HDD boot menu. */ 227148049Snyan fd = open(disk, O_RDONLY); 228148049Snyan if (fd < 0) 229148049Snyan err(1, "%s", disk); 230148049Snyan n = read(fd, boot, BOOTSIZE); 231148049Snyan if (n != BOOTSIZE) 232148049Snyan errx(1, "%s: short read", disk); 233148049Snyan close(fd); 234148049Snyan 235148049Snyan return 0; 236148049Snyan} 237148049Snyan 238148049Snyanstatic int 239148049Snyanwrite_boot(const char *disk, u_char *boot) 240148049Snyan{ 241148049Snyan int fd, n, i; 242148049Snyan char buf[MAXPATHLEN]; 243148049Snyan 244148049Snyan fd = open(disk, O_RDWR); 245148049Snyan if (fd != -1) { 246148049Snyan if (lseek(fd, 0, SEEK_SET) == -1) 247148049Snyan err(1, "%s", disk); 248148049Snyan if ((n = write(fd, boot, BOOTSIZE)) < 0) 249148049Snyan err(1, "%s", disk); 250148049Snyan if (n != BOOTSIZE) 251148049Snyan errx(1, "%s: short write", disk); 252148049Snyan close(fd); 253148049Snyan return 0; 254148049Snyan } 255148049Snyan 256148049Snyan for (i = 0; i < NDOSPART; i++) { 257148049Snyan snprintf(buf, sizeof(buf), "%ss%d", disk, i + 1); 258148049Snyan fd = open(buf, O_RDONLY); 259148049Snyan if (fd < 0) 260148049Snyan continue; 261148049Snyan n = ioctl(fd, DIOCSPC98, boot); 262148049Snyan if (n != 0) 263148049Snyan err(1, "%s: ioctl DIOCSPC98", disk); 264148049Snyan close(fd); 265148049Snyan return 0; 266148049Snyan } 267148049Snyan 268148049Snyan err(1, "%s", disk); 269148049Snyan} 270148049Snyan 271148049Snyan/* 272148049Snyan * Produce a device path for a "canonical" name, where appropriate. 273148049Snyan */ 274148049Snyanstatic char * 275148049Snyanmkrdev(char *fname) 276148049Snyan{ 277148049Snyan char buf[MAXPATHLEN]; 278148049Snyan struct stat sb; 279148049Snyan char *s; 280148049Snyan 281148049Snyan s = (char *)fname; 282148049Snyan if (!strchr(fname, '/')) { 283148049Snyan snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname); 284148049Snyan if (stat(buf, &sb)) 285148049Snyan snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 286148049Snyan if (!(s = strdup(buf))) 287148049Snyan err(1, NULL); 288148049Snyan } 289148049Snyan return s; 290148049Snyan} 291148049Snyan 292148049Snyan/* 293148049Snyan * Display usage information. 294148049Snyan */ 295148049Snyanstatic void 296148049Snyanusage(void) 297148049Snyan{ 298148049Snyan fprintf(stderr, 299148049Snyan "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n" 300148049Snyan " [-f ipl.bak][-F menu.bak] disk\n"); 301148049Snyan exit(1); 302148049Snyan} 303