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