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