diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2013-09-29 17:51:35 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2013-09-29 17:51:35 +0000 |
commit | fa6b93ed201771db8d11ef9343f985b5996de11a (patch) | |
tree | 6ee5657bcaf977df14fd0c68a586318e3df1ec69 /sys/arch/aviion | |
parent | da42e31395d08a08b30f86a4da2a810107c5ab24 (diff) |
Simple installboot(8) for aviion. Awaiting boot blocks...
Diffstat (limited to 'sys/arch/aviion')
-rw-r--r-- | sys/arch/aviion/stand/Makefile | 4 | ||||
-rw-r--r-- | sys/arch/aviion/stand/installboot/Makefile | 16 | ||||
-rw-r--r-- | sys/arch/aviion/stand/installboot/installboot.8 | 70 | ||||
-rw-r--r-- | sys/arch/aviion/stand/installboot/installboot.c | 224 |
4 files changed, 312 insertions, 2 deletions
diff --git a/sys/arch/aviion/stand/Makefile b/sys/arch/aviion/stand/Makefile index cd0e25b6fc5..2fc4fcacf31 100644 --- a/sys/arch/aviion/stand/Makefile +++ b/sys/arch/aviion/stand/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.3 2013/09/28 21:59:38 miod Exp $ +# $OpenBSD: Makefile,v 1.4 2013/09/29 17:51:34 miod Exp $ -SUBDIR= a2coff +SUBDIR= a2coff installboot .if ${MACHINE} == "aviion" SUBDIR+= libprom libsa libz diff --git a/sys/arch/aviion/stand/installboot/Makefile b/sys/arch/aviion/stand/installboot/Makefile new file mode 100644 index 00000000000..95150cfef9a --- /dev/null +++ b/sys/arch/aviion/stand/installboot/Makefile @@ -0,0 +1,16 @@ +# $OpenBSD: Makefile,v 1.1 2013/09/29 17:51:34 miod Exp $ + +MAN= installboot.8 +MANSUBDIR= aviion + +.if ${MACHINE} == "aviion" +PROG= installboot +BINDIR= /usr/mdec +DPADD= ${LIBUTIL} +LDADD= -lutil +LDSTATIC= -static +.else +NOPROG= +.endif + +.include <bsd.prog.mk> diff --git a/sys/arch/aviion/stand/installboot/installboot.8 b/sys/arch/aviion/stand/installboot/installboot.8 new file mode 100644 index 00000000000..90e6863b41a --- /dev/null +++ b/sys/arch/aviion/stand/installboot/installboot.8 @@ -0,0 +1,70 @@ +.\" $OpenBSD: installboot.8,v 1.1 2013/09/29 17:51:34 miod Exp $ +.\" +.\" Copyright (c) 1994 Paul Kranenburg +.\" 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. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Paul Kranenburg. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" 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: September 29 2013 $ +.Dt INSTALLBOOT 8 aviion +.Os +.Sh NAME +.Nm installboot +.Nd install a bootstrap on a disk +.Sh SYNOPSIS +.Nm installboot +.Op Fl n +.Op Fl v +.Ar boot +.Ar rawdev +.Sh DESCRIPTION +.Nm installboot +is used to install a boot program into the VDM boot area of a disk. +.Pp +The options are as follows: +.Bl -tag -width flag +.It Fl n +Do not actually write anything on the disk. +.It Fl v +Be verbose, printing out boot area and boot file information. +.El +.Pp +The arguments are: +.Bl -tag -width boot +.It Ar boot +the name of the boot program to be installed. +.It Ar rawdev +the name of the raw disk device in which the boot program is to be installed. +It may be abbreviated into a form recognizable by +.Xr opendev 3 . +.El +.Sh EXAMPLES +.Bd -literal -offset +/usr/mdec/installboot /usr/mdec/boot sd0 +.Ed +.Sh SEE ALSO +.Xr disklabel 8 , +.Xr init 8 diff --git a/sys/arch/aviion/stand/installboot/installboot.c b/sys/arch/aviion/stand/installboot/installboot.c new file mode 100644 index 00000000000..14dd06aa2c5 --- /dev/null +++ b/sys/arch/aviion/stand/installboot/installboot.c @@ -0,0 +1,224 @@ +/* $OpenBSD: installboot.c,v 1.1 2013/09/29 17:51:34 miod Exp $ */ + +/* + * Copyright (c) 2013 Miodrag Vallat. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <unistd.h> +#include <err.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <util.h> +#include <sys/disklabel.h> +#include <sys/stat.h> + +int nowrite, verbose; +char *boot, *dev; + +void analyze_label_sector(uint8_t *, struct vdm_label **, + struct vdm_boot_info **); +void initialize_boot_area(int); +void read_sector(int, uint32_t, void *); +void usage(void); +void write_sector(int, uint32_t, void *); + +#define VDM_BLOCK_SIZE 0x200 + +uint8_t buf[VDM_BLOCK_SIZE]; + +void +usage() +{ + fprintf(stderr, "usage: installboot [-n] <boot> <device>\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int c; + int bootfd, devfd; + size_t chunk; + uint32_t blkno; + struct stat stat; + struct vdm_label *dl; + struct vdm_boot_info *bi; + + while ((c = getopt(argc, argv, "nv")) != -1) { + switch (c) { + case 'n': + nowrite = 1; + break; + case 'v': + verbose = 1; + break; + default: + usage(); + } + } + + if (argc - optind != 2) + usage(); + + boot = argv[optind]; + dev = argv[optind + 1]; + + bootfd = open(boot, O_RDONLY); + if (bootfd < 0) + err(1, "open(%s)", boot); + + if (fstat(bootfd, &stat) != 0) + err(1, "fstat(%s)", boot); + + devfd = opendev(dev, nowrite ? O_RDONLY : O_RDWR, OPENDEV_PART, &dev); + if (devfd < 0) + err(1, "open(%s)", dev); + + /* + * Figure out the boot area span. + * If there is no VDM boot area, set up one. + */ + + read_sector(devfd, VDM_LABEL_SECTOR, buf); + analyze_label_sector(buf, &dl, &bi); + + if (bi == NULL) { + if (verbose) + printf("no boot area found\n"); + if (nowrite) + return 0; + if (verbose) + printf("creating boot area\n"); + initialize_boot_area(devfd); + + read_sector(devfd, VDM_LABEL_SECTOR, buf); + analyze_label_sector(buf, &dl, &bi); + } + + if (bi != NULL) { + if (verbose) + printf("boot area: sectors %u-%u\n", + bi->boot_start, bi->boot_start + bi->boot_size - 1); + } else { + /* should not happen */ + return 1; + } + + /* + * Write the file into the boot area. + */ + + if (stat.st_size > bi->boot_size * VDM_BLOCK_SIZE) + err(1, "boot file too large, boot area is only %u bytes", + bi->boot_size * VDM_BLOCK_SIZE); + + if (nowrite) + return 0; + + blkno = bi->boot_start; + if (verbose) + printf("writing %lld bytes from sector %u onwards\n", + stat.st_size, blkno); + while (stat.st_size != 0) { + if (stat.st_size > sizeof buf) + chunk = sizeof buf; + else { + chunk = stat.st_size; + memset(buf, 0, sizeof buf); + } + if (read(bootfd, buf, chunk) != chunk) + err(1, "read"); + write_sector(devfd, blkno++, buf); + stat.st_size -= chunk; + } + + close(bootfd); + close(devfd); + return 0; +} + +void +read_sector(int fd, uint32_t secno, void *buf) +{ + if (lseek(fd, (off_t)secno * VDM_BLOCK_SIZE, SEEK_SET) == -1) + err(1, "lseek"); + + if (read(fd, buf, VDM_BLOCK_SIZE) != VDM_BLOCK_SIZE) + err(1, "read(%d,%08x)", fd, secno); +} + +void +write_sector(int fd, uint32_t secno, void *buf) +{ + if (lseek(fd, (off_t)secno * VDM_BLOCK_SIZE, SEEK_SET) == -1) + err(1, "lseek"); + + if (write(fd, buf, VDM_BLOCK_SIZE) != VDM_BLOCK_SIZE) + err(1, "write(%d,%08x)", fd, secno); +} + +void +analyze_label_sector(uint8_t *sector, struct vdm_label **dl, + struct vdm_boot_info **dbi) +{ + struct vdm_label *l; + struct vdm_boot_info *bi; + + l = (struct vdm_label *)(sector + VDM_LABEL_OFFSET); + if (betoh32(l->signature) != VDM_LABEL_SIGNATURE) { + l = (struct vdm_label *)(sector + VDM_LABEL_OFFSET_ALT); + if (betoh32(l->signature) != VDM_LABEL_SIGNATURE) + l = NULL; + } + + if (l != NULL) { + bi = (struct vdm_boot_info *) + (sector + VDM_BLOCK_SIZE - sizeof *bi); + if (betoh32(bi->signature) != VDM_LABEL_SIGNATURE) + bi = NULL; + } else + bi = NULL; + + *dl = l; + *dbi = bi; +} + +/* + * Build a minimal VDM label and boot area. + * Allows you to shoot yourself in the foot, badly. + */ +void +initialize_boot_area(int fd) +{ + struct vdm_label dl; + struct vdm_boot_info bi; + + memset(buf, 0, sizeof buf); + memset(&dl, 0, sizeof dl); + memset(&bi, 0, sizeof bi); + + dl.signature = htobe32(VDM_LABEL_SIGNATURE); + bi.signature = htobe32(VDM_LABEL_SIGNATURE); + bi.boot_start = htobe32(LABELSECTOR + 1); + bi.boot_size = htobe32(VDM_BOOT_DEFAULT_SIZE); + bi.version = htobe32(VDM_BOOT_INFO_VERSION); + + memcpy(buf + VDM_LABEL_OFFSET_ALT, &dl, sizeof dl); + memcpy(buf + VDM_BLOCK_SIZE - sizeof bi, &bi, sizeof bi); + + write_sector(fd, VDM_LABEL_SECTOR, buf); +} |