diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-08-22 15:48:33 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2008-08-22 15:48:33 +0000 |
commit | 663874d02e9ad66b553df1f7cd8ab57e9a9c0275 (patch) | |
tree | ad30444042cebee38b09562053f8c5241d434a77 /usr.sbin/mksuncd/mksuncd.c | |
parent | 4a6ad36fa248a7cfdaac4a6469050ed96dfb0762 (diff) |
move mksuncd to here (but still only sparc64 build)
Diffstat (limited to 'usr.sbin/mksuncd/mksuncd.c')
-rw-r--r-- | usr.sbin/mksuncd/mksuncd.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/usr.sbin/mksuncd/mksuncd.c b/usr.sbin/mksuncd/mksuncd.c new file mode 100644 index 00000000000..26d50ae4910 --- /dev/null +++ b/usr.sbin/mksuncd/mksuncd.c @@ -0,0 +1,327 @@ +/* $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); +} |