summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2020-07-17 08:03:57 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2020-07-17 08:03:57 +0000
commit9c3ebab344c210f63472587b920035fd415238b4 (patch)
tree07cf0c051604fd2563c3fc8764d1846464a726b2 /usr.sbin
parent8ea8350f9052b02a54fc2a56a50caf9360268f99 (diff)
Add powerpc64 support; straight copy from octeon.
ok deraadt@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/installboot/Makefile4
-rw-r--r--usr.sbin/installboot/powerpc64_installboot.c244
2 files changed, 247 insertions, 1 deletions
diff --git a/usr.sbin/installboot/Makefile b/usr.sbin/installboot/Makefile
index 1938d3bd5e6..2e81ae586ff 100644
--- a/usr.sbin/installboot/Makefile
+++ b/usr.sbin/installboot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.21 2020/06/27 15:35:29 deraadt Exp $
+# $OpenBSD: Makefile,v 1.22 2020/07/17 08:03:56 kettenis Exp $
PROG= installboot
SRCS= installboot.c util.c
@@ -27,6 +27,8 @@ SRCS += landisk_installboot.c
SRCS += loongson_installboot.c
.elif ${MACHINE} == "macppc"
SRCS += macppc_installboot.c
+.elif ${MACHINE} == "powerpc64"
+SRCS += powerpc64_installboot.c
.elif ${MACHINE} == "octeon"
SRCS += octeon_installboot.c
.elif ${MACHINE} == "sparc64"
diff --git a/usr.sbin/installboot/powerpc64_installboot.c b/usr.sbin/installboot/powerpc64_installboot.c
new file mode 100644
index 00000000000..49acc56a13c
--- /dev/null
+++ b/usr.sbin/installboot/powerpc64_installboot.c
@@ -0,0 +1,244 @@
+/* $OpenBSD: powerpc64_installboot.c,v 1.1 2020/07/17 08:03:56 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2011 Joel Sing <jsing@openbsd.org>
+ * Copyright (c) 2010 Otto Moerbeek <otto@openbsd.org>
+ * Copyright (c) 2003 Tom Cosgrove <tom.cosgrove@arches-consulting.com>
+ * Copyright (c) 1997 Michael Shalayeff
+ * 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.
+ */
+
+#include <sys/param.h> /* DEV_BSIZE */
+#include <sys/disklabel.h>
+#include <sys/dkio.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <util.h>
+#include <endian.h>
+
+#include "installboot.h"
+
+static void write_filesystem(struct disklabel *, char);
+static int findmbrfat(int, struct disklabel *);
+
+void
+md_init(void)
+{
+}
+
+void
+md_loadboot(void)
+{
+}
+
+void
+md_installboot(int devfd, char *dev)
+{
+ struct disklabel dl;
+ int part;
+
+ /* Get and check disklabel. */
+ if (ioctl(devfd, DIOCGDINFO, &dl) == -1)
+ err(1, "disklabel: %s", dev);
+ if (dl.d_magic != DISKMAGIC)
+ errx(1, "bad disklabel magic=0x%08x", dl.d_magic);
+
+ /* Warn on unknown disklabel types. */
+ if (dl.d_type == 0)
+ warnx("disklabel type unknown");
+
+ part = findmbrfat(devfd, &dl);
+ if (part != -1) {
+ write_filesystem(&dl, (char)part);
+ return;
+ }
+}
+
+
+static void
+write_filesystem(struct disklabel *dl, char part)
+{
+ static char *fsckfmt = "/sbin/fsck_msdos %s >/dev/null";
+ static char *newfsfmt ="/sbin/newfs_msdos %s >/dev/null";
+ struct ufs_args args;
+ char cmd[60];
+ char dst[PATH_MAX];
+ char *src;
+ size_t mntlen, pathlen, srclen;
+ int rslt;
+
+ src = NULL;
+
+ /* Create directory for temporary mount point. */
+ strlcpy(dst, "/tmp/installboot.XXXXXXXXXX", sizeof(dst));
+ if (mkdtemp(dst) == NULL)
+ err(1, "mkdtemp('%s') failed", dst);
+ mntlen = strlen(dst);
+
+ /* Mount <duid>.<part> as msdos filesystem. */
+ memset(&args, 0, sizeof(args));
+ rslt = asprintf(&args.fspec,
+ "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c",
+ dl->d_uid[0], dl->d_uid[1], dl->d_uid[2], dl->d_uid[3],
+ dl->d_uid[4], dl->d_uid[5], dl->d_uid[6], dl->d_uid[7],
+ part);
+ if (rslt == -1) {
+ warn("bad special device");
+ goto rmdir;
+ }
+
+ args.export_info.ex_root = -2;
+ args.export_info.ex_flags = 0;
+
+ if (mount(MOUNT_MSDOS, dst, 0, &args) == -1) {
+ /* Try fsck'ing it. */
+ rslt = snprintf(cmd, sizeof(cmd), fsckfmt, args.fspec);
+ if (rslt >= sizeof(cmd)) {
+ warnx("can't build fsck command");
+ rslt = -1;
+ goto rmdir;
+ }
+ rslt = system(cmd);
+ if (rslt == -1) {
+ warn("system('%s') failed", cmd);
+ goto rmdir;
+ }
+ if (mount(MOUNT_MSDOS, dst, 0, &args) == -1) {
+ /* Try newfs'ing it. */
+ rslt = snprintf(cmd, sizeof(cmd), newfsfmt,
+ args.fspec);
+ if (rslt >= sizeof(cmd)) {
+ warnx("can't build newfs command");
+ rslt = -1;
+ goto rmdir;
+ }
+ rslt = system(cmd);
+ if (rslt == -1) {
+ warn("system('%s') failed", cmd);
+ goto rmdir;
+ }
+ rslt = mount(MOUNT_MSDOS, dst, 0, &args);
+ if (rslt == -1) {
+ warn("unable to mount MSDOS partition");
+ goto rmdir;
+ }
+ }
+ }
+
+ /*
+ * Copy /usr/mdec/boot to /mnt/boot.
+ */
+ pathlen = strlen(dst);
+ if (strlcat(dst, "/boot", sizeof(dst)) >= sizeof(dst)) {
+ rslt = -1;
+ warn("unable to build /boot path");
+ goto umount;
+ }
+ src = fileprefix(root, "/usr/mdec/boot");
+ if (src == NULL) {
+ rslt = -1;
+ goto umount;
+ }
+ srclen = strlen(src);
+ if (verbose)
+ fprintf(stderr, "%s %s to %s\n",
+ (nowrite ? "would copy" : "copying"), src, dst);
+ if (!nowrite) {
+ rslt = filecopy(src, dst);
+ if (rslt == -1)
+ goto umount;
+ }
+
+ rslt = 0;
+
+umount:
+ dst[mntlen] = '\0';
+ if (unmount(dst, MNT_FORCE) == -1)
+ err(1, "unmount('%s') failed", dst);
+
+rmdir:
+ free(args.fspec);
+ dst[mntlen] = '\0';
+ if (rmdir(dst) == -1)
+ err(1, "rmdir('%s') failed", dst);
+
+ free(src);
+
+ if (rslt == -1)
+ exit(1);
+}
+
+int
+findmbrfat(int devfd, struct disklabel *dl)
+{
+ struct dos_partition dp[NDOSPART];
+ ssize_t len;
+ u_int64_t start = 0;
+ int i;
+ u_int8_t *secbuf;
+
+ if ((secbuf = malloc(dl->d_secsize)) == NULL)
+ err(1, NULL);
+
+ /* Read MBR. */
+ len = pread(devfd, secbuf, dl->d_secsize, 0);
+ if (len != dl->d_secsize)
+ err(4, "can't read mbr");
+ memcpy(dp, &secbuf[DOSPARTOFF], sizeof(dp));
+
+ for (i = 0; i < NDOSPART; i++) {
+ if (dp[i].dp_typ == DOSPTYP_UNUSED)
+ continue;
+ if (dp[i].dp_typ == DOSPTYP_FAT16L ||
+ dp[i].dp_typ == DOSPTYP_FAT32L ||
+ dp[i].dp_typ == DOSPTYP_FAT16B)
+ start = letoh32(dp[i].dp_start);
+ }
+
+ free(secbuf);
+
+ if (start) {
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ if (DL_GETPSIZE(&dl->d_partitions[i]) > 0 &&
+ DL_GETPOFFSET(&dl->d_partitions[i]) == start)
+ return ('a' + i);
+ }
+ }
+
+ return (-1);
+}