--- /dev/null
+.\" $OpenBSD: mksuncd.1,v 1.1 2008/08/22 15:48:32 deraadt Exp $
+.\"
+.\" Copyright (c) 2001 Jason L. Wright (jason@thought.net)
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+.\" (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+.\" SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd $Mdocdate: August 22 2008 $
+.Dt MKSUNCD 1
+.Os
+.Sh NAME
+.Nm mksuncd
+.Nd add a bootable ufs partition to a filesystem image
+.Sh SYNOPSIS
+.Nm mksuncd
+.Ar partition-letter
+.Ar imagefile
+.Ar ufsfile
+.Sh DESCRIPTION
+The
+.Nm
+utility adds the file
+.Ar ufsfile
+to the end of
+.Ar imagefile .
+.Ar ufsfile
+is assumed to be a bootable filesystem image and
+.Ar imagefile
+is assumed to be something like an ISO 9660 filesystem.
+A Sun-style disklabel is expected to already be present
+at the beginning of
+.Ar imagefile ,
+and
+.Nm
+will update that label so that the partition (a-h) given by
+.Ar partition-letter
+points to
+.Ar ufsfile
+within
+.Ar imagefile .
+.Pp
+Based on the label in
+.Ar imagefile ,
+that file is padded so that added files are always on cylinder boundaries.
+This is a requirement of the PROM.
+.Sh BUGS
+This program is not endian or type safe.
+It makes several assumptions about both based on its
+SPARC bias.
--- /dev/null
+/* $OpenBSD: mksuncd.c,v 1.1 2008/08/22 15:48:32 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * WARNING! WARNING!
+ * This program is not type safe (it assumes sparc type sizes) and not
+ * endian safe (assumes sparc endianness).
+ * WARNING! WARNING!
+ */
+
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sun_disklabel.h 8.1 (Berkeley) 6/11/93
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <string.h>
+
+/*
+ * SunOS disk label layout (only relevant portions discovered here).
+ * JLW XXX should get these definitions from elsewhere, oh well.
+ */
+
+#define SUN_DKMAGIC 55998
+
+/* partition info */
+struct sun_dkpart {
+ int sdkp_cyloffset; /* starting cylinder */
+ int sdkp_nsectors; /* number of sectors */
+};
+
+struct sun_disklabel { /* total size = 512 bytes */
+ char sl_text[128];
+ char sl_xxx1[292];
+#define sl_bsdlabel sl_xxx1 /* Embedded OpenBSD label */
+ u_short sl_rpm; /* rotational speed */
+ u_short sl_pcylinders; /* number of physical cyls */
+#define sl_pcyl sl_pcylinders /* XXX: old sun3 */
+ u_short sl_sparespercyl; /* spare sectors per cylinder */
+ char sl_xxx3[4];
+ u_short sl_interleave; /* interleave factor */
+ u_short sl_ncylinders; /* data cylinders */
+ u_short sl_acylinders; /* alternate cylinders */
+ u_short sl_ntracks; /* tracks per cylinder */
+ u_short sl_nsectors; /* sectors per track */
+ char sl_xxx4[4];
+ struct sun_dkpart sl_part[8]; /* partition layout */
+ u_short sl_magic; /* == SUN_DKMAGIC */
+ u_short sl_cksum; /* xor checksum of all shorts */
+};
+
+int expand_file(int, off_t);
+void usage(void);
+int adjust_base(int, struct sun_disklabel *);
+int get_label(int, struct sun_disklabel *);
+int append_osfile(int, int);
+off_t cylindersize(int, struct sun_disklabel *);
+int adjust_label(int, struct sun_disklabel *, int, off_t, off_t);
+
+int
+expand_file(int f, off_t len)
+{
+ char buf[1024];
+ off_t i;
+
+ if (lseek(f, 0, SEEK_END) == -1)
+ return (-1);
+ bzero(buf, sizeof(buf));
+ while (len) {
+ i = (sizeof(buf) < len) ? sizeof(buf) : len;
+ if (write(f, buf, i) != i)
+ return (-1);
+ len -= i;
+ }
+ return (0);
+}
+
+void
+usage(void)
+{
+ fprintf(stderr, "setpart partition baseimage bootimage\n");
+}
+
+/*
+ * Adjust size of base to meet a cylinder boundary.
+ */
+int
+adjust_base(int f, struct sun_disklabel *slp)
+{
+ struct stat st;
+ off_t sz;
+
+ if (lseek(f, 0, SEEK_END) == -1)
+ err(1, "lseek");
+
+ if (fstat(f, &st) == -1)
+ err(1, "fstat");
+
+ sz = ((off_t)slp->sl_nsectors) *
+ ((off_t)slp->sl_ntracks) * ((off_t)512);
+
+ if ((st.st_size % sz) != 0) {
+ if (expand_file(f, sz - (st.st_size % sz)))
+ err(1, "expand_file");
+ }
+
+ return (0);
+}
+
+int
+get_label(int f, struct sun_disklabel *slp)
+{
+ int r;
+
+ if (lseek(f, 0, SEEK_SET) == -1)
+ err(1, "lseek");
+
+ r = read(f, slp, sizeof(*slp));
+ if (r == -1)
+ err(1, "read");
+ if (r != sizeof(*slp))
+ errx(1, "short read");
+
+ if (slp->sl_ntracks == 0 || slp->sl_ncylinders == 0 ||
+ slp->sl_nsectors == 0)
+ errx(1, "bogus disklabel");
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sun_disklabel sl;
+ int part, bf, of;
+ off_t cylstart, cylsize;
+
+ if (argc != 4) {
+ usage();
+ return (1);
+ }
+
+ if (argv[1] == NULL || strlen(argv[1]) != 1 ||
+ (argv[1][0] < 'a' || argv[1][0] > 'h')) {
+ usage();
+ return (1);
+ }
+ part = argv[1][0] - 'a';
+
+ if (argv[2] == NULL || argv[3] == NULL) {
+ usage();
+ return (1);
+ }
+
+ bf = open(argv[2], O_RDWR);
+ if (bf == -1)
+ err(1, "open");
+
+ of = open(argv[3], O_RDONLY);
+ if (of == -1)
+ err(1, "open");
+
+ if (get_label(bf, &sl))
+ return (1);
+
+ if (adjust_base(bf, &sl))
+ return (1);
+
+ cylstart = cylindersize(bf, &sl);
+ cylsize = cylindersize(of, &sl);
+
+ if (append_osfile(bf, of))
+ return (1);
+
+ if (adjust_base(bf, &sl))
+ return (1);
+
+ if (adjust_label(bf, &sl, part, cylstart, cylsize))
+ return (1);
+
+ close(bf);
+ close(of);
+
+ return (0);
+}
+
+/*
+ * Put our entry into the disklabel, recompute label checksum, and
+ * write it back to the disk.
+ */
+int
+adjust_label(int f, struct sun_disklabel *slp, int part, off_t start, off_t size)
+{
+ u_short sum = 0, *sp;
+ int i;
+
+ if (start > 65535)
+ errx(1, "start too large! %lld", (long long)start);
+ if (part < 0 || part > 8)
+ errx(1, "invalid partition: %d", part);
+ slp->sl_part[part].sdkp_cyloffset = start;
+ slp->sl_part[part].sdkp_nsectors =
+ size * slp->sl_nsectors * slp->sl_ntracks;
+
+ slp->sl_cksum = 0;
+ sp = (u_short *)slp;
+ for (i = 0; i < sizeof(*slp)/sizeof(u_short); i++) {
+ sum ^= *sp;
+ sp++;
+ }
+ slp->sl_cksum = sum;
+
+ if (lseek(f, 0, SEEK_SET) == -1)
+ return (-1);
+
+ i = write(f, slp, sizeof(*slp));
+ if (i < 0)
+ err(1, "write modified label");
+ if (i != sizeof(*slp))
+ errx(1, "short write modified label");
+ return (0);
+}
+
+int
+append_osfile(int outf, int inf)
+{
+ char buf[512];
+ int r, len;
+
+ while (1) {
+ len = read(inf, buf, sizeof(buf));
+ if (len < 0)
+ err(1, "read osfile");
+ if (len == 0)
+ return (0);
+
+ r = write(outf, buf, len);
+ if (r < 0)
+ err(1, "write basefile");
+ if (r != len)
+ errx(1, "short write basefile");
+ }
+}
+
+off_t
+cylindersize(int f, struct sun_disklabel *slp)
+{
+ struct stat st;
+ off_t sz, r;
+
+ if (fstat(f, &st) == -1)
+ err(1, "fstat");
+
+ sz = ((off_t)slp->sl_nsectors) *
+ ((off_t)slp->sl_ntracks) * ((off_t)512);
+
+ r = st.st_size / sz;
+
+ if ((st.st_size % sz) == 0)
+ return (r);
+ return (r + 1);
+}