xref: /openbsd-src/usr.sbin/mksuncd/mksuncd.c (revision 3ec9f6c666125fcceba82f9441e651a7c9939b74)
1*3ec9f6c6Sjsg /*	$OpenBSD: mksuncd.c,v 1.5 2021/12/23 09:17:19 jsg Exp $	*/
249061340Sderaadt 
349061340Sderaadt /*
449061340Sderaadt  * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
549061340Sderaadt  * All rights reserved.
649061340Sderaadt  *
749061340Sderaadt  * Redistribution and use in source and binary forms, with or without
849061340Sderaadt  * modification, are permitted provided that the following conditions
949061340Sderaadt  * are met:
1049061340Sderaadt  * 1. Redistributions of source code must retain the above copyright
1149061340Sderaadt  *    notice, this list of conditions and the following disclaimer.
1249061340Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
1349061340Sderaadt  *    notice, this list of conditions and the following disclaimer in the
1449061340Sderaadt  *    documentation and/or other materials provided with the distribution.
1549061340Sderaadt  *
1649061340Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1749061340Sderaadt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1849061340Sderaadt  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1949061340Sderaadt  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2049061340Sderaadt  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2149061340Sderaadt  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2249061340Sderaadt  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2349061340Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2449061340Sderaadt  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2549061340Sderaadt  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2649061340Sderaadt  * POSSIBILITY OF SUCH DAMAGE.
2749061340Sderaadt  */
2849061340Sderaadt 
2949061340Sderaadt /*
3049061340Sderaadt  * WARNING! WARNING!
3149061340Sderaadt  * This program is not type safe (it assumes sparc type sizes) and not
3249061340Sderaadt  * endian safe (assumes sparc endianness).
3349061340Sderaadt  * WARNING! WARNING!
3449061340Sderaadt  */
3549061340Sderaadt 
3649061340Sderaadt /*
3749061340Sderaadt  * Copyright (c) 1992, 1993
3849061340Sderaadt  *	The Regents of the University of California.  All rights reserved.
3949061340Sderaadt  *
4049061340Sderaadt  * This software was developed by the Computer Systems Engineering group
4149061340Sderaadt  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
4249061340Sderaadt  * contributed to Berkeley.
4349061340Sderaadt  *
4449061340Sderaadt  * All advertising materials mentioning features or use of this software
4549061340Sderaadt  * must display the following acknowledgement:
4649061340Sderaadt  *	This product includes software developed by the University of
4749061340Sderaadt  *	California, Lawrence Berkeley Laboratory.
4849061340Sderaadt  *
4949061340Sderaadt  * Redistribution and use in source and binary forms, with or without
5049061340Sderaadt  * modification, are permitted provided that the following conditions
5149061340Sderaadt  * are met:
5249061340Sderaadt  * 1. Redistributions of source code must retain the above copyright
5349061340Sderaadt  *    notice, this list of conditions and the following disclaimer.
5449061340Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
5549061340Sderaadt  *    notice, this list of conditions and the following disclaimer in the
5649061340Sderaadt  *    documentation and/or other materials provided with the distribution.
5749061340Sderaadt  * 3. Neither the name of the University nor the names of its contributors
5849061340Sderaadt  *    may be used to endorse or promote products derived from this software
5949061340Sderaadt  *    without specific prior written permission.
6049061340Sderaadt  *
6149061340Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6249061340Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6349061340Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6449061340Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6549061340Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6649061340Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6749061340Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6849061340Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6949061340Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
7049061340Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
7149061340Sderaadt  * SUCH DAMAGE.
7249061340Sderaadt  *
7349061340Sderaadt  *	@(#)sun_disklabel.h	8.1 (Berkeley) 6/11/93
7449061340Sderaadt  */
7549061340Sderaadt 
7649061340Sderaadt #include <stdio.h>
7749061340Sderaadt #include <sys/types.h>
7849061340Sderaadt #include <sys/stat.h>
7949061340Sderaadt #include <unistd.h>
8049061340Sderaadt #include <fcntl.h>
8149061340Sderaadt #include <err.h>
8249061340Sderaadt #include <string.h>
8349061340Sderaadt 
8449061340Sderaadt /*
8549061340Sderaadt  * SunOS disk label layout (only relevant portions discovered here).
8649061340Sderaadt  * JLW XXX should get these definitions from elsewhere, oh well.
8749061340Sderaadt  */
8849061340Sderaadt 
8949061340Sderaadt #define	SUN_DKMAGIC	55998
9049061340Sderaadt 
9149061340Sderaadt /* partition info */
9249061340Sderaadt struct sun_dkpart {
9349061340Sderaadt 	int	sdkp_cyloffset;		/* starting cylinder */
9449061340Sderaadt 	int	sdkp_nsectors;		/* number of sectors */
9549061340Sderaadt };
9649061340Sderaadt 
9749061340Sderaadt struct sun_disklabel {			/* total size = 512 bytes */
9849061340Sderaadt 	char	sl_text[128];
9949061340Sderaadt 	char	sl_xxx1[292];
10049061340Sderaadt #define sl_bsdlabel	sl_xxx1		/* Embedded OpenBSD label */
10149061340Sderaadt 	u_short sl_rpm;			/* rotational speed */
10249061340Sderaadt 	u_short	sl_pcylinders;		/* number of physical cyls */
10349061340Sderaadt #define	sl_pcyl	 sl_pcylinders		/* XXX: old sun3 */
10449061340Sderaadt 	u_short sl_sparespercyl;	/* spare sectors per cylinder */
10549061340Sderaadt 	char	sl_xxx3[4];
10649061340Sderaadt 	u_short sl_interleave;		/* interleave factor */
10749061340Sderaadt 	u_short	sl_ncylinders;		/* data cylinders */
10849061340Sderaadt 	u_short	sl_acylinders;		/* alternate cylinders */
10949061340Sderaadt 	u_short	sl_ntracks;		/* tracks per cylinder */
11049061340Sderaadt 	u_short	sl_nsectors;		/* sectors per track */
11149061340Sderaadt 	char	sl_xxx4[4];
11249061340Sderaadt 	struct sun_dkpart sl_part[8];	/* partition layout */
11349061340Sderaadt 	u_short	sl_magic;		/* == SUN_DKMAGIC */
11449061340Sderaadt 	u_short	sl_cksum;		/* xor checksum of all shorts */
11549061340Sderaadt };
11649061340Sderaadt 
11749061340Sderaadt int expand_file(int, off_t);
11849061340Sderaadt void usage(void);
11949061340Sderaadt int adjust_base(int, struct sun_disklabel *);
12049061340Sderaadt int get_label(int, struct sun_disklabel *);
12149061340Sderaadt int append_osfile(int, int);
12249061340Sderaadt off_t cylindersize(int, struct sun_disklabel *);
12349061340Sderaadt int adjust_label(int, struct sun_disklabel *, int, off_t, off_t);
12449061340Sderaadt 
12549061340Sderaadt int
expand_file(int f,off_t len)12649061340Sderaadt expand_file(int f, off_t len)
12749061340Sderaadt {
12849061340Sderaadt 	char buf[1024];
12949061340Sderaadt 	off_t i;
13049061340Sderaadt 
13149061340Sderaadt 	if (lseek(f, 0, SEEK_END) == -1)
13249061340Sderaadt 		return (-1);
13349061340Sderaadt 	bzero(buf, sizeof(buf));
13449061340Sderaadt 	while (len) {
13549061340Sderaadt 		i = (sizeof(buf) < len) ? sizeof(buf) : len;
13649061340Sderaadt 		if (write(f, buf, i) != i)
13749061340Sderaadt 			return (-1);
13849061340Sderaadt 		len -= i;
13949061340Sderaadt 	}
14049061340Sderaadt 	return (0);
14149061340Sderaadt }
14249061340Sderaadt 
14349061340Sderaadt void
usage(void)14449061340Sderaadt usage(void)
14549061340Sderaadt {
146338ae9d4Sderaadt 	fprintf(stderr, "usage: mksuncd partition isoimage bootimage\n");
14749061340Sderaadt }
14849061340Sderaadt 
14949061340Sderaadt /*
15049061340Sderaadt  * Adjust size of base to meet a cylinder boundary.
15149061340Sderaadt  */
15249061340Sderaadt int
adjust_base(int f,struct sun_disklabel * slp)15349061340Sderaadt adjust_base(int f, struct sun_disklabel *slp)
15449061340Sderaadt {
15549061340Sderaadt 	struct stat st;
15649061340Sderaadt 	off_t sz;
15749061340Sderaadt 
15849061340Sderaadt 	if (lseek(f, 0, SEEK_END) == -1)
15949061340Sderaadt 		err(1, "lseek");
16049061340Sderaadt 
16149061340Sderaadt 	if (fstat(f, &st) == -1)
16249061340Sderaadt 		err(1, "fstat");
16349061340Sderaadt 
16449061340Sderaadt 	sz = ((off_t)slp->sl_nsectors) *
16549061340Sderaadt 	    ((off_t)slp->sl_ntracks) * ((off_t)512);
16649061340Sderaadt 
16749061340Sderaadt 	if ((st.st_size % sz) != 0) {
16849061340Sderaadt 		if (expand_file(f, sz - (st.st_size % sz)))
16949061340Sderaadt 			err(1, "expand_file");
17049061340Sderaadt 	}
17149061340Sderaadt 
17249061340Sderaadt 	return (0);
17349061340Sderaadt }
17449061340Sderaadt 
17549061340Sderaadt int
get_label(int f,struct sun_disklabel * slp)17649061340Sderaadt get_label(int f, struct sun_disklabel *slp)
17749061340Sderaadt {
17849061340Sderaadt 	int r;
17949061340Sderaadt 
18049061340Sderaadt 	if (lseek(f, 0, SEEK_SET) == -1)
18149061340Sderaadt 		err(1, "lseek");
18249061340Sderaadt 
18349061340Sderaadt 	r = read(f, slp, sizeof(*slp));
18449061340Sderaadt 	if (r == -1)
18549061340Sderaadt 		err(1, "read");
18649061340Sderaadt 	if (r != sizeof(*slp))
18749061340Sderaadt 		errx(1, "short read");
18849061340Sderaadt 
18949061340Sderaadt 	if (slp->sl_ntracks == 0 || slp->sl_ncylinders == 0 ||
19049061340Sderaadt 	    slp->sl_nsectors == 0)
19149061340Sderaadt 		errx(1, "bogus disklabel");
19249061340Sderaadt 
19349061340Sderaadt 	return (0);
19449061340Sderaadt }
19549061340Sderaadt 
19649061340Sderaadt int
main(int argc,char ** argv)19749061340Sderaadt main(int argc, char **argv)
19849061340Sderaadt {
19949061340Sderaadt 	struct sun_disklabel sl;
20049061340Sderaadt 	int part, bf, of;
20149061340Sderaadt 	off_t cylstart, cylsize;
20249061340Sderaadt 
20349061340Sderaadt 	if (argc != 4) {
20449061340Sderaadt 		usage();
20549061340Sderaadt 		return (1);
20649061340Sderaadt 	}
20749061340Sderaadt 
20849061340Sderaadt 	if (argv[1] == NULL || strlen(argv[1]) != 1 ||
20949061340Sderaadt 	    (argv[1][0] < 'a' || argv[1][0] > 'h')) {
21049061340Sderaadt 		usage();
21149061340Sderaadt 		return (1);
21249061340Sderaadt 	}
21349061340Sderaadt 	part = argv[1][0] - 'a';
21449061340Sderaadt 
21549061340Sderaadt 	if (argv[2] == NULL || argv[3] == NULL) {
21649061340Sderaadt 		usage();
21749061340Sderaadt 		return (1);
21849061340Sderaadt 	}
21949061340Sderaadt 
22049061340Sderaadt 	bf = open(argv[2], O_RDWR);
22149061340Sderaadt 	if (bf == -1)
22249061340Sderaadt 		err(1, "open");
22349061340Sderaadt 
22449061340Sderaadt 	of = open(argv[3], O_RDONLY);
22549061340Sderaadt 	if (of == -1)
22649061340Sderaadt 		err(1, "open");
22749061340Sderaadt 
228ad1978efSderaadt 	if (pledge("stdio", NULL) == -1)
229ad1978efSderaadt 		err(1, "pledge");
230ad1978efSderaadt 
23149061340Sderaadt 	if (get_label(bf, &sl))
23249061340Sderaadt 		return (1);
23349061340Sderaadt 
23449061340Sderaadt 	if (adjust_base(bf, &sl))
23549061340Sderaadt 		return (1);
23649061340Sderaadt 
23749061340Sderaadt 	cylstart = cylindersize(bf, &sl);
23849061340Sderaadt 	cylsize = cylindersize(of, &sl);
23949061340Sderaadt 
24049061340Sderaadt 	if (append_osfile(bf, of))
24149061340Sderaadt 		return (1);
24249061340Sderaadt 
24349061340Sderaadt 	if (adjust_base(bf, &sl))
24449061340Sderaadt 		return (1);
24549061340Sderaadt 
24649061340Sderaadt 	if (adjust_label(bf, &sl, part, cylstart, cylsize))
24749061340Sderaadt 		return (1);
24849061340Sderaadt 
24949061340Sderaadt 	close(bf);
25049061340Sderaadt 	close(of);
25149061340Sderaadt 
25249061340Sderaadt 	return (0);
25349061340Sderaadt }
25449061340Sderaadt 
25549061340Sderaadt /*
25649061340Sderaadt  * Put our entry into the disklabel, recompute label checksum, and
25749061340Sderaadt  * write it back to the disk.
25849061340Sderaadt  */
25949061340Sderaadt int
adjust_label(int f,struct sun_disklabel * slp,int part,off_t start,off_t size)26049061340Sderaadt adjust_label(int f, struct sun_disklabel *slp, int part, off_t start, off_t size)
26149061340Sderaadt {
26249061340Sderaadt 	u_short sum = 0, *sp;
26349061340Sderaadt 	int i;
26449061340Sderaadt 
26549061340Sderaadt 	if (start > 65535)
26649061340Sderaadt 		errx(1, "start too large! %lld", (long long)start);
267*3ec9f6c6Sjsg 	if (part < 0 || part >= 8)
26849061340Sderaadt 		errx(1, "invalid partition: %d", part);
26949061340Sderaadt 	slp->sl_part[part].sdkp_cyloffset = start;
27049061340Sderaadt 	slp->sl_part[part].sdkp_nsectors =
27149061340Sderaadt 	    size * slp->sl_nsectors * slp->sl_ntracks;
27249061340Sderaadt 
27349061340Sderaadt 	slp->sl_cksum = 0;
27449061340Sderaadt 	sp = (u_short *)slp;
27549061340Sderaadt 	for (i = 0; i < sizeof(*slp)/sizeof(u_short); i++) {
27649061340Sderaadt 		sum ^= *sp;
27749061340Sderaadt 		sp++;
27849061340Sderaadt 	}
27949061340Sderaadt 	slp->sl_cksum = sum;
28049061340Sderaadt 
28149061340Sderaadt 	if (lseek(f, 0, SEEK_SET) == -1)
28249061340Sderaadt 		return (-1);
28349061340Sderaadt 
28449061340Sderaadt 	i = write(f, slp, sizeof(*slp));
285df69c215Sderaadt 	if (i == -1)
28649061340Sderaadt 		err(1, "write modified label");
28749061340Sderaadt 	if (i != sizeof(*slp))
28849061340Sderaadt 		errx(1, "short write modified label");
28949061340Sderaadt 	return (0);
29049061340Sderaadt }
29149061340Sderaadt 
29249061340Sderaadt int
append_osfile(int outf,int inf)29349061340Sderaadt append_osfile(int outf, int inf)
29449061340Sderaadt {
29549061340Sderaadt 	char buf[512];
29649061340Sderaadt 	int r, len;
29749061340Sderaadt 
29849061340Sderaadt 	while (1) {
29949061340Sderaadt 		len = read(inf, buf, sizeof(buf));
300df69c215Sderaadt 		if (len == -1)
30149061340Sderaadt 			err(1, "read osfile");
30249061340Sderaadt 		if (len == 0)
30349061340Sderaadt 			return (0);
30449061340Sderaadt 
30549061340Sderaadt 		r = write(outf, buf, len);
306df69c215Sderaadt 		if (r == -1)
30749061340Sderaadt 			err(1, "write basefile");
30849061340Sderaadt 		if (r != len)
30949061340Sderaadt 			errx(1, "short write basefile");
31049061340Sderaadt 	}
31149061340Sderaadt }
31249061340Sderaadt 
31349061340Sderaadt off_t
cylindersize(int f,struct sun_disklabel * slp)31449061340Sderaadt cylindersize(int f, struct sun_disklabel *slp)
31549061340Sderaadt {
31649061340Sderaadt 	struct stat st;
31749061340Sderaadt 	off_t sz, r;
31849061340Sderaadt 
31949061340Sderaadt 	if (fstat(f, &st) == -1)
32049061340Sderaadt 		err(1, "fstat");
32149061340Sderaadt 
32249061340Sderaadt 	sz = ((off_t)slp->sl_nsectors) *
32349061340Sderaadt 	    ((off_t)slp->sl_ntracks) * ((off_t)512);
32449061340Sderaadt 
32549061340Sderaadt 	r = st.st_size / sz;
32649061340Sderaadt 
32749061340Sderaadt 	if ((st.st_size % sz) == 0)
32849061340Sderaadt 		return (r);
32949061340Sderaadt 	return (r + 1);
33049061340Sderaadt }
331