boot98cfg.c revision 64126
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 * $FreeBSD: head/usr.sbin/boot98cfg/boot98cfg.c 64126 2000-08-02 10:11:08Z kato $ 3264126Skato */ 3364126Skato 3464126Skato/* 3564126Skato * Copyright (c) 1999 Robert Nordier 3664126Skato * All rights reserved. 3764126Skato * 3864126Skato * Redistribution and use in source and binary forms, with or without 3964126Skato * modification, are permitted provided that the following conditions 4064126Skato * are met: 4164126Skato * 1. Redistributions of source code must retain the above copyright 4264126Skato * notice, this list of conditions and the following disclaimer. 4364126Skato * 2. Redistributions in binary form must reproduce the above copyright 4464126Skato * notice, this list of conditions and the following disclaimer in the 4564126Skato * documentation and/or other materials provided with the distribution. 4664126Skato * 4764126Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND 4864126Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4964126Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 5064126Skato * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 5164126Skato * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 5264126Skato * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 5364126Skato * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 5464126Skato * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 5564126Skato * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 5664126Skato * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 5764126Skato * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 5864126Skato */ 5964126Skato 6064126Skato#include <sys/param.h> 6164126Skato#include <sys/stat.h> 6264126Skato 6364126Skato#include <err.h> 6464126Skato#include <errno.h> 6564126Skato#include <fcntl.h> 6664126Skato#include <paths.h> 6764126Skato#include <stdio.h> 6864126Skato#include <stdlib.h> 6964126Skato#include <string.h> 7064126Skato#include <unistd.h> 7164126Skato 7264126Skato#define IPLSIZE 512 /* IPL size */ 7364126Skato#define BOOTMENUSIZE 7168 /* Max HDD boot menu size */ 7464126Skato#define BOOTMENUOFF 0x400 7564126Skato 7664126Skatostatic char *mkrdev(char *); 7764126Skatostatic void usage(void); 7864126Skato 7964126Skatou_char boot0buf[0x2000]; 8064126Skatochar ipl[IPLSIZE]; 8164126Skatochar menu[BOOTMENUSIZE]; 8264126Skato 8364126Skato/* 8464126Skato * Produce a device path for a "canonical" name, where appropriate. 8564126Skato */ 8664126Skatostatic char * 8764126Skatomkrdev(char *fname) 8864126Skato{ 8964126Skato char buf[MAXPATHLEN]; 9064126Skato struct stat sb; 9164126Skato char *s; 9264126Skato 9364126Skato s = (char *)fname; 9464126Skato if (!strchr(fname, '/')) { 9564126Skato snprintf(buf, sizeof(buf), "%sr%s", _PATH_DEV, fname); 9664126Skato if (stat(buf, &sb)) 9764126Skato snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname); 9864126Skato if (!(s = strdup(buf))) 9964126Skato err(1, NULL); 10064126Skato } 10164126Skato return s; 10264126Skato} 10364126Skato 10464126Skatostatic void 10564126Skatousage(void) 10664126Skato{ 10764126Skato fprintf(stderr, 10864126Skato "boot98cfg [-B][-i boot0][-m boot0.5][-s secsize][-v version]\n" 10964126Skato " [-f ipl.bak][-F menu.bak] disk\n"); 11064126Skato exit(1); 11164126Skato} 11264126Skato 11364126Skatoint 11464126Skatomain(int argc, char *argv[]) 11564126Skato{ 11664126Skato char *endptr; 11764126Skato char *iplpath = "/boot/boot0", *menupath = "/boot/boot0.5"; 11864126Skato char *iplbakpath = NULL, *menubakpath = NULL; 11964126Skato char *disk; 12064126Skato int B_flag = 0; 12164126Skato int c; 12264126Skato int fd, fd1; 12364126Skato int n; 12464126Skato int secsize = 512; 12564126Skato int v_flag = 0, version; 12664126Skato 12764126Skato while ((c = getopt(argc, argv, "BF:f:i:m:s:v:")) != -1) { 12864126Skato switch (c) { 12964126Skato case 'B': 13064126Skato B_flag = 1; 13164126Skato break; 13264126Skato case 'F': 13364126Skato menubakpath = optarg; 13464126Skato break; 13564126Skato case 'f': 13664126Skato iplbakpath = optarg; 13764126Skato break; 13864126Skato case 'i': 13964126Skato iplpath = optarg; 14064126Skato break; 14164126Skato case 'm': 14264126Skato menupath = optarg; 14364126Skato break; 14464126Skato case 's': 14564126Skato secsize = strtol(optarg, &endptr, 0); 14664126Skato if (errno || *optarg == NULL || *endptr) 14764126Skato errx(1, "%s: Bad argument to -s option", 14864126Skato optarg); 14964126Skato switch (secsize) { 15064126Skato case 256: 15164126Skato case 512: 15264126Skato case 1024: 15364126Skato case 2048: 15464126Skato break; 15564126Skato default: 15664126Skato errx(1, "%s: unsupported sector size", optarg); 15764126Skato break; 15864126Skato } 15964126Skato break; 16064126Skato case 'v': 16164126Skato v_flag = 1; 16264126Skato version = strtol(optarg, &endptr, 0); 16364126Skato if (errno || *optarg == NULL || *endptr || 16464126Skato version < 0 || version > 255) 16564126Skato errx(1, "%s: Bad argument to -s option", 16664126Skato optarg); 16764126Skato break; 16864126Skato default: 16964126Skato usage(); 17064126Skato /* NOTREACHED */ 17164126Skato break; 17264126Skato } 17364126Skato } 17464126Skato argc -= optind; 17564126Skato argv += optind; 17664126Skato if (argc != 1) 17764126Skato usage(); 17864126Skato disk = mkrdev(*argv); 17964126Skato 18064126Skato /* Read IPL, partition table and HDD boot menu. */ 18164126Skato fd = open(disk, O_RDWR); 18264126Skato if (fd < 0) 18364126Skato err(1, "%s", disk); 18464126Skato n = read(fd, boot0buf, 0x2000); 18564126Skato if (n != 0x2000) 18664126Skato errx(1, "%s: short read", disk); 18764126Skato if (!B_flag && !v_flag) 18864126Skato close(fd); 18964126Skato 19064126Skato if (iplbakpath != NULL) { 19164126Skato fd1 = open(iplbakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 19264126Skato if (fd1 < 0) 19364126Skato err(1, "%s", iplbakpath); 19464126Skato n = write(fd1, boot0buf, IPLSIZE); 19564126Skato if (n == -1) 19664126Skato err(1, "%s", iplbakpath); 19764126Skato if (n != IPLSIZE) 19864126Skato errx(1, "%s: short write", iplbakpath); 19964126Skato close(fd1); 20064126Skato } 20164126Skato 20264126Skato if (menubakpath != NULL) { 20364126Skato fd1 = open(menubakpath, O_WRONLY | O_CREAT | O_TRUNC, 0666); 20464126Skato if (fd1 < 0) 20564126Skato err(1, "%s", menubakpath); 20664126Skato n = write(fd1, boot0buf + BOOTMENUOFF, BOOTMENUSIZE); 20764126Skato if (n == -1) 20864126Skato err(1, "%s", menubakpath); 20964126Skato if (n != BOOTMENUSIZE) 21064126Skato errx(1, "%s: short write", menubakpath); 21164126Skato close(fd1); 21264126Skato } 21364126Skato 21464126Skato if (B_flag) { 21564126Skato /* Read IPL (boot0). */ 21664126Skato fd1 = open(iplpath, O_RDONLY); 21764126Skato if (fd1 < 0) 21864126Skato err(1, "%s", disk); 21964126Skato n = read(fd1, ipl, IPLSIZE); 22064126Skato if (n < 0) 22164126Skato err(1, "%s", iplpath); 22264126Skato if (n != IPLSIZE) 22364126Skato errx(1, "%s: invalid file", iplpath); 22464126Skato close(fd1); 22564126Skato 22664126Skato /* Read HDD boot menu (boot0.5). */ 22764126Skato fd1 = open(menupath, O_RDONLY); 22864126Skato if (fd1 < 0) 22964126Skato err(1, "%s", disk); 23064126Skato n = read(fd1, menu, BOOTMENUSIZE); 23164126Skato if (n < 0) 23264126Skato err(1, "%s", menupath); 23364126Skato if (n != BOOTMENUSIZE) 23464126Skato errx(1, "%s: invalid file", menupath); 23564126Skato close(fd1); 23664126Skato 23764126Skato memcpy(boot0buf, ipl, IPLSIZE); 23864126Skato memcpy(boot0buf + BOOTMENUOFF, menu, BOOTMENUSIZE); 23964126Skato } 24064126Skato 24164126Skato /* Set version number field. */ 24264126Skato if (v_flag) 24364126Skato *(boot0buf + secsize - 4) = (u_char)version; 24464126Skato 24564126Skato if (B_flag || v_flag) { 24664126Skato if (lseek(fd, 0, SEEK_SET) == -1 || 24764126Skato (n = write(fd, boot0buf, 0x2000)) < 0 || 24864126Skato close(fd)) 24964126Skato err(1, "%s", disk); 25064126Skato if (n != 0x2000) 25164126Skato errx(1, "%s: short write", disk); 25264126Skato } 25364126Skato 25464126Skato return 0; 25564126Skato} 256