summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorStefan Sperling <stsp@cvs.openbsd.org>2014-11-26 20:30:42 +0000
committerStefan Sperling <stsp@cvs.openbsd.org>2014-11-26 20:30:42 +0000
commit34b9f1984c0dc531d6656a31445bc2c592fca5de (patch)
tree329b9fd6c2359335cd7772a7b2dfbd7d0c912f77 /sys
parent9a4025874f62637b384dc4628eeabced98cde476 (diff)
Introduce softraid boot support to sparc64 ofwboot.
sparc64 machines should now be able to boot from softraid raid1 and crypto. Tested on sun blade100, sunfire v240, and sun t1000 ldom guests. Lots of encouragement from deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/stand/ofwboot/Locore.c6
-rw-r--r--sys/arch/sparc64/stand/ofwboot/Makefile20
-rw-r--r--sys/arch/sparc64/stand/ofwboot/boot.c102
-rw-r--r--sys/arch/sparc64/stand/ofwboot/disk.h50
-rw-r--r--sys/arch/sparc64/stand/ofwboot/diskprobe.c128
-rw-r--r--sys/arch/sparc64/stand/ofwboot/elf64_exec.c48
-rw-r--r--sys/arch/sparc64/stand/ofwboot/ofdev.c201
-rw-r--r--sys/arch/sparc64/stand/ofwboot/ofdev.h6
-rw-r--r--sys/arch/sparc64/stand/ofwboot/vers.c2
9 files changed, 498 insertions, 65 deletions
diff --git a/sys/arch/sparc64/stand/ofwboot/Locore.c b/sys/arch/sparc64/stand/ofwboot/Locore.c
index 03d9d989b30..6dee8661f77 100644
--- a/sys/arch/sparc64/stand/ofwboot/Locore.c
+++ b/sys/arch/sparc64/stand/ofwboot/Locore.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: Locore.c,v 1.11 2014/11/26 19:47:03 stsp Exp $ */
+/* $OpenBSD: Locore.c,v 1.12 2014/11/26 20:30:41 stsp Exp $ */
/* $NetBSD: Locore.c,v 1.1 2000/08/20 14:58:36 mrg Exp $ */
/*
@@ -77,6 +77,10 @@ _rtt(void)
cell_t nreturns;
} args;
+#ifdef SOFTRAID
+ sr_clear_keys();
+#endif
+
args.name = ADR2CELL("exit");
args.nargs = 0;
args.nreturns = 0;
diff --git a/sys/arch/sparc64/stand/ofwboot/Makefile b/sys/arch/sparc64/stand/ofwboot/Makefile
index 39847c92686..b3af441c6d2 100644
--- a/sys/arch/sparc64/stand/ofwboot/Makefile
+++ b/sys/arch/sparc64/stand/ofwboot/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.18 2012/08/30 19:29:14 pascal Exp $
+# $OpenBSD: Makefile,v 1.19 2014/11/26 20:30:41 stsp Exp $
# $NetBSD: Makefile,v 1.2 2001/03/04 14:50:05 mrg Exp $
CURDIR= ${.CURDIR}
@@ -13,13 +13,28 @@ WARNS= 0
PROG?= ofwboot
NOMAN= ja, man!
+.if ${PROG} == "ofwboot"
+SOFTRAID?= yes
+.else
+SOFTRAID?= no
+.endif
+
.PATH: ${S}/arch/sparc64/sparc64
SRCS= srt0.s Locore.c alloc.c boot.c elf64_exec.c net.c netif_of.c \
ofdev.c vers.c
+.if ${SOFTRAID:L} == "yes"
+SRCS+= diskprobe.c softraid.c
+.endif
.PATH: ${S}/lib/libkern/arch/sparc64 ${S}/lib/libkern
SRCS+= strlcpy.c strcmp.c strlcat.c strlen.c
+.if ${SOFTRAID:L} == "yes"
+.PATH: ${S}/lib/libsa
+SRCS+= aes_xts.c explicit_bzero.c hmac_sha1.c sha1.c pbkdf2.c \
+ rijndael.c
+.endif
+
CWARNFLAGS+= -Wno-main
AFLAGS+= -Wa,-Av9a
AFLAGS+= -x assembler-with-cpp -D_LOCORE -D__ELF__ -fno-pie
@@ -48,6 +63,9 @@ CPPFLAGS+= -DRELOC=0x${RELOC}
#
CPPFLAGS+= -DSPARC_BOOT_UFS
#CPPFLAGS+= -DSPARC_BOOT_HSFS
+.if ${SOFTRAID:L} == "yes"
+CPPFLAGS+= -DSOFTRAID
+.endif
.if !make(libdep) && !make(sadep) && !make(salibdir) && !make(obj)
.BEGIN:
diff --git a/sys/arch/sparc64/stand/ofwboot/boot.c b/sys/arch/sparc64/stand/ofwboot/boot.c
index 87e0f2f0432..d4641ee80ad 100644
--- a/sys/arch/sparc64/stand/ofwboot/boot.c
+++ b/sys/arch/sparc64/stand/ofwboot/boot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: boot.c,v 1.20 2013/12/28 21:00:21 kettenis Exp $ */
+/* $OpenBSD: boot.c,v 1.21 2014/11/26 20:30:41 stsp Exp $ */
/* $NetBSD: boot.c,v 1.3 2001/05/31 08:55:19 mrg Exp $ */
/*
* Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved.
@@ -56,6 +56,16 @@
#include <machine/cpu.h>
+#ifdef SOFTRAID
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <dev/biovar.h>
+#include <dev/softraidvar.h>
+
+#include "disk.h"
+#include "softraid.h"
+#endif
+
#include "ofdev.h"
#include "openfirm.h"
@@ -254,6 +264,9 @@ loadfile(int fd, char *args)
close(fd);
+#ifdef SOFTRAID
+ sr_clear_keys();
+#endif
chain(entry, args, ssym, esym);
/* NOTREACHED */
@@ -286,6 +299,67 @@ fail:
return (-1);
}
+#ifdef SOFTRAID
+/* Set bootdev_dip to the software boot volume, if specified. */
+static int
+srbootdev(const char *bootline)
+{
+ struct sr_boot_volume *bv;
+ struct diskinfo *dip;
+ int unit;
+
+ bootdev_dip = NULL;
+
+ /*
+ * Look for softraid disks in bootline.
+ * E.g. 'sr0', 'sr0:bsd', or 'sr0a:/bsd'
+ */
+ if (bootline[0] == 's' && bootline[1] == 'r' &&
+ '0' <= bootline[2] && bootline[2] <= '9') {
+ unit = bootline[2] - '0';
+
+ /* Create a fake diskinfo for this softraid volume. */
+ SLIST_FOREACH(bv, &sr_volumes, sbv_link)
+ if (bv->sbv_unit == unit)
+ break;
+ if (bv == NULL) {
+ printf("Unknown device: sr%d\n", unit);
+ return ENODEV;
+ }
+
+ if ((bv->sbv_flags & BIOC_SCBOOTABLE) == 0) {
+ printf("device sr%d is not bootable\n", unit);
+ return ENODEV;
+ }
+
+ if (bv->sbv_level == 'C' && bv->sbv_keys == NULL)
+ if (sr_crypto_decrypt_keys(bv) != 0)
+ return EPERM;
+
+ if (bv->sbv_diskinfo == NULL) {
+ dip = alloc(sizeof(struct diskinfo));
+ bzero(dip, sizeof(*dip));
+ dip->sr_vol = bv;
+ bv->sbv_diskinfo = dip;
+ }
+
+ /* strategy() and devopen() will use bootdev_dip */
+ bootdev_dip = bv->sbv_diskinfo;
+
+ /* Attempt to read disklabel. */
+ bv->sbv_part = 'c';
+ if (sr_getdisklabel(bv, &dip->disklabel)) {
+ free(bv->sbv_diskinfo, sizeof(struct diskinfo));
+ bv->sbv_diskinfo = NULL;
+ bootdev_dip = NULL;
+ return ERDLAB;
+ }
+ }
+
+ return 0;
+}
+#endif
+
int
main()
{
@@ -294,6 +368,9 @@ main()
char bootline[512]; /* Should check size? */
char *cp;
int i, fd;
+#ifdef SOFTRAID
+ int err;
+#endif
char **bootlp;
char *just_bootline[2];
@@ -309,6 +386,16 @@ main()
exit();
}
+#ifdef SOFTRAID
+ diskprobe();
+ srprobe();
+ err = srbootdev(bootline);
+ if (err) {
+ printf("Cannot boot from softraid: %s\n", strerror(err));
+ _rtt();
+ }
+#endif
+
/*
* case 1: boot net -a
* -> gets loop
@@ -364,20 +451,13 @@ main()
cp = bootline;
#else
strlcpy(bootline, opened_name, sizeof bootline);
- cp = bootline + strlen(bootline);
- *cp++ = ' ';
#endif
- *cp = '-';
if (boothowto & RB_ASKNAME)
- *++cp = 'a';
+ strlcat(bootline, " -a", sizeof bootline);
if (boothowto & RB_SINGLE)
- *++cp = 's';
+ strlcat(bootline, " -s", sizeof bootline);
if (boothowto & RB_KDB)
- *++cp = 'd';
- if (*cp == '-')
- *--cp = 0;
- else
- *++cp = 0;
+ strlcat(bootline, " -d", sizeof bootline);
#ifdef __notyet__
OF_setprop(chosen, "bootargs", bootline, strlen(bootline) + 1);
#endif
diff --git a/sys/arch/sparc64/stand/ofwboot/disk.h b/sys/arch/sparc64/stand/ofwboot/disk.h
new file mode 100644
index 00000000000..043cc09a64c
--- /dev/null
+++ b/sys/arch/sparc64/stand/ofwboot/disk.h
@@ -0,0 +1,50 @@
+/* $OpenBSD: disk.h,v 1.1 2014/11/26 20:30:41 stsp Exp $ */
+
+/*
+ * Copyright (c) 1997 Tobias Weingartner
+ * 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 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.
+ *
+ */
+
+#ifndef _DISK_H
+#define _DISK_H
+
+#include <sys/queue.h>
+
+/* All the info on a disk we've found */
+struct diskinfo {
+ char path[256];
+ struct disklabel disklabel;
+ struct sr_boot_volume *sr_vol;
+
+ TAILQ_ENTRY(diskinfo) list;
+};
+TAILQ_HEAD(disklist_lh, diskinfo);
+
+/* List of probed disks. */
+extern struct disklist_lh disklist;
+
+extern struct diskinfo *bootdev_dip;
+
+#endif /* _DISK_H */
diff --git a/sys/arch/sparc64/stand/ofwboot/diskprobe.c b/sys/arch/sparc64/stand/ofwboot/diskprobe.c
new file mode 100644
index 00000000000..7c554781a0e
--- /dev/null
+++ b/sys/arch/sparc64/stand/ofwboot/diskprobe.c
@@ -0,0 +1,128 @@
+/* $OpenBSD: diskprobe.c,v 1.1 2014/11/26 20:30:41 stsp Exp $ */
+
+/*
+ * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org>
+ * Copyright (c) 2014 Stefan Sperling <stsp@openbsd.org>
+ *
+ * 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 <sys/param.h>
+#include <sys/disklabel.h>
+
+#include <lib/libsa/stand.h>
+
+#include "ofdev.h"
+#include "disk.h"
+#include "openfirm.h"
+
+/* List of disk devices we found/probed */
+struct disklist_lh disklist;
+
+struct diskinfo *bootdev_dip;
+
+void
+new_diskinfo(int node)
+{
+ struct diskinfo *dip;
+ struct of_dev ofdev;
+ int ihandle = -1;
+
+ dip = alloc(sizeof(*dip));
+ bzero(dip, sizeof(*dip));
+
+ if (OF_package_to_path(node, dip->path, sizeof(dip->path)) > 0)
+ DPRINTF("found disk %s\n", dip->path);
+ else {
+ DPRINTF("could not get path for disk node %x\n", node);
+ goto bad;
+ }
+
+ ihandle = OF_open(dip->path);
+ if (ihandle == -1)
+ goto bad;
+
+ bzero(&ofdev, sizeof(ofdev));
+ ofdev.handle = ihandle;
+ ofdev.type = OFDEV_DISK;
+ ofdev.bsize = DEV_BSIZE;
+ if (load_disklabel(&ofdev, &dip->disklabel) != 0)
+ goto bad;
+ OF_close(ihandle);
+ TAILQ_INSERT_TAIL(&disklist, dip, list);
+
+ return;
+bad:
+ if (ihandle != -1)
+ OF_close(ihandle);
+ free(dip, sizeof(*dip));
+}
+
+#ifdef BOOT_DEBUG
+void dump_node(int node)
+{
+ char buf[32];
+
+ printf("node %x ", node);
+ if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0)
+ printf("type %s ", buf);
+ if (OF_getprop(node, "name", buf, sizeof(buf)) > 0)
+ printf("name %s ", buf);
+ printf("\n");
+}
+#endif
+
+/*
+ * Hunt through the device tree for disks. There should be no need to
+ * go more than four levels deep.
+ */
+void
+diskprobe(void)
+{
+ int node, child, stack[4], depth;
+ char buf[32];
+
+ stack[0] = OF_peer(0);
+ if (stack[0] == 0)
+ return;
+ depth = 0;
+ TAILQ_INIT(&disklist);
+
+ for (;;) {
+ node = stack[depth];
+
+ if (node == 0 || node == -1) {
+ if (--depth < 0)
+ return;
+
+ stack[depth] = OF_peer(stack[depth]);
+ continue;
+ }
+
+#ifdef BOOT_DEBUG
+ dump_node(node);
+#endif
+ if ((OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "block") == 0 &&
+ OF_getprop(node, "name", buf, sizeof(buf)) > 0 &&
+ strcmp(buf, "disk") == 0)) {
+ new_diskinfo(node);
+ }
+
+ child = OF_child(node);
+ if (child != 0 && child != -1 && depth < 3)
+ stack[++depth] = child;
+ else
+ stack[depth] = OF_peer(stack[depth]);
+ }
+}
diff --git a/sys/arch/sparc64/stand/ofwboot/elf64_exec.c b/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
index 029249ce121..720e7d99ee8 100644
--- a/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
+++ b/sys/arch/sparc64/stand/ofwboot/elf64_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: elf64_exec.c,v 1.6 2014/07/12 21:03:38 tedu Exp $ */
+/* $OpenBSD: elf64_exec.c,v 1.7 2014/11/26 20:30:41 stsp Exp $ */
/* $NetBSD: elfXX_exec.c,v 1.2 2001/08/15 20:08:15 eeh Exp $ */
/*
@@ -54,6 +54,19 @@
#include <sys/param.h>
#include <sys/exec_elf.h>
+#include <machine/boot_flag.h>
+
+#ifdef SOFTRAID
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/disklabel.h>
+#include <dev/biovar.h>
+#include <dev/softraidvar.h>
+
+#include "disk.h"
+#include "softraid.h"
+#endif
+
#include "openfirm.h"
int
@@ -65,6 +78,10 @@ elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void **ssymp, void **esymp)
u_int align;
int i, first = 1;
int n;
+ struct openbsd_bootdata *obd;
+#ifdef SOFTRAID
+ struct sr_boot_volume *bv;
+#endif
/*
* Don't display load address for ELF; it's encoded in
@@ -79,6 +96,35 @@ elf64_exec(int fd, Elf_Ehdr *elf, u_int64_t *entryp, void **ssymp, void **esymp)
return (1);
}
+ if (phdr.p_type == PT_OPENBSD_BOOTDATA) {
+ memset((void *) (long)phdr.p_paddr, 0, phdr.p_filesz);
+
+ if (phdr.p_filesz < sizeof(struct openbsd_bootdata))
+ continue;
+
+ obd = (struct openbsd_bootdata *)(long)phdr.p_paddr;
+ obd->version = BOOTDATA_VERSION;
+ obd->len = sizeof(struct openbsd_bootdata);
+#ifdef SOFTRAID
+ /*
+ * If booting from softraid we must pass additional
+ * information to the kernel:
+ * 1) The uuid of the softraid volume we booted from.
+ * 2) The maskkey for decryption, if applicable.
+ */
+ if (bootdev_dip && bootdev_dip->sr_vol) {
+ bv = bootdev_dip->sr_vol;
+ memcpy(obd->sr_uuid, bv->sbv_uuid.sui_id,
+ sizeof(obd->sr_uuid));
+ if (bv->sbv_maskkey)
+ memcpy(obd->sr_maskkey, bv->sbv_maskkey,
+ sizeof(obd->sr_maskkey));
+ }
+
+#endif
+ continue;
+ }
+
if (phdr.p_type == PT_OPENBSD_RANDOMIZE) {
int m, pos;
diff --git a/sys/arch/sparc64/stand/ofwboot/ofdev.c b/sys/arch/sparc64/stand/ofwboot/ofdev.c
index 5330ee8a221..b81d08e82b1 100644
--- a/sys/arch/sparc64/stand/ofwboot/ofdev.c
+++ b/sys/arch/sparc64/stand/ofwboot/ofdev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofdev.c,v 1.22 2014/06/08 16:01:00 jsg Exp $ */
+/* $OpenBSD: ofdev.c,v 1.23 2014/11/26 20:30:41 stsp Exp $ */
/* $NetBSD: ofdev.c,v 1.1 2000/08/20 14:58:41 mrg Exp $ */
/*
@@ -47,6 +47,12 @@
#include <lib/libsa/nfs.h>
#endif
+#ifdef SOFTRAID
+#include <sys/queue.h>
+#include <dev/softraidvar.h>
+#include "disk.h"
+#endif
+
#include <dev/sun/disklabel.h>
#include "ofdev.h"
@@ -106,7 +112,7 @@ filename(char *str, char *ppart)
return 0;
}
-static int
+int
strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
size_t *rsize)
{
@@ -116,6 +122,12 @@ strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf,
if (rw != F_READ)
return EPERM;
+#ifdef SOFTRAID
+ /* Intercept strategy for softraid volumes. */
+ if (dev->type == OFDEV_SOFTRAID)
+ return sr_strategy(bootdev_dip->sr_vol, rw,
+ blk, size, buf, rsize);
+#endif
if (dev->type != OFDEV_DISK)
panic("strategy");
@@ -151,8 +163,15 @@ devclose(struct open_file *of)
if (op->type == OFDEV_NET)
net_close(op);
#endif
+#ifdef SOFTRAID
+ if (op->type == OFDEV_SOFTRAID) {
+ op->handle = -1;
+ return 0;
+ }
+#endif
OF_close(op->handle);
op->handle = -1;
+ return 0;
}
struct devsw devsw[1] = {
@@ -407,7 +426,6 @@ search_label(struct of_dev *devp, u_long off, char *buf, struct disklabel *lp,
struct mbr_partition *p;
int i;
u_long poff;
- static int recursion;
struct disklabel *dlp;
struct sun_disklabel *slp;
@@ -448,6 +466,38 @@ search_label(struct of_dev *devp, u_long off, char *buf, struct disklabel *lp,
}
int
+load_disklabel(struct of_dev *ofdev, struct disklabel *label)
+{
+ char buf[DEV_BSIZE];
+ size_t read;
+ int error = 0;
+ char *errmsg = NULL;
+
+ /* First try to find a disklabel without MBR partitions */
+ DNPRINTF(BOOT_D_OFDEV, "load_disklabel: trying to read disklabel\n");
+ if (strategy(ofdev, F_READ,
+ LABELSECTOR, DEV_BSIZE, buf, &read) != 0
+ || read != DEV_BSIZE
+ || (errmsg = getdisklabel(buf, label))) {
+#ifdef BOOT_DEBUG
+ if (errmsg)
+ DNPRINTF(BOOT_D_OFDEV,
+ "load_disklabel: getdisklabel says %s\n", errmsg);
+#endif
+ /* Else try MBR partitions */
+ errmsg = search_label(ofdev, LABELSECTOR, buf,
+ label, 0);
+ if (errmsg) {
+ printf("load_disklabel: search_label says %s\n",
+ errmsg);
+ error = ERDLAB;
+ }
+ }
+
+ return (error);
+}
+
+int
devopen(struct open_file *of, const char *name, char **file)
{
char *cp;
@@ -456,9 +506,10 @@ devopen(struct open_file *of, const char *name, char **file)
char buf[DEV_BSIZE];
struct disklabel label;
int handle, part;
- size_t read;
- char *errmsg = NULL;
int error = 0;
+#ifdef SOFTRAID
+ char volno;
+#endif
if (ofdev.handle != -1)
panic("devopen");
@@ -466,27 +517,98 @@ devopen(struct open_file *of, const char *name, char **file)
return EPERM;
DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name);
strlcpy(fname, name, sizeof fname);
- cp = filename(fname, &partition);
- if (cp) {
- strlcpy(buf, cp, sizeof buf);
- *cp = 0;
- }
- if (!cp || !*buf)
- strlcpy(buf, DEFAULT_KERNEL, sizeof buf);
- if (!*fname)
- strlcpy(fname, bootdev, sizeof fname);
- strlcpy(opened_name, fname, sizeof opened_name);
- if (partition) {
- cp = opened_name + strlen(opened_name);
- *cp++ = ':';
- *cp++ = partition;
- *cp = 0;
+#ifdef SOFTRAID
+ if (bootdev_dip) {
+ if (fname[0] == 's' && fname[1] == 'r' &&
+ '0' <= fname[2] && fname[2] <= '9') {
+ volno = fname[2];
+ if ('a' <= fname[3] &&
+ fname[3] <= 'a' + MAXPARTITIONS) {
+ partition = fname[3];
+ if (fname[4] == ':')
+ cp = &fname[5];
+ else
+ cp = &fname[4];
+ } else {
+ partition = 'a';
+ cp = &fname[3];
+ }
+ } else {
+ volno = '0';
+ partition = 'a';
+ cp = &fname[0];
+ }
+ snprintf(buf, sizeof buf, "sr%c:%c", volno, partition);
+ strlcpy(opened_name, buf, sizeof opened_name);
+ *file = opened_name + strlen(opened_name);
+ if (!*cp)
+ strlcpy(buf, DEFAULT_KERNEL, sizeof buf);
+ else
+ snprintf(buf, sizeof buf, "%s%s",
+ *cp == '/' ? "" : "/", cp);
+ strlcat(opened_name, buf, sizeof opened_name);
+ } else {
+#endif
+ cp = filename(fname, &partition);
+ if (cp) {
+ strlcpy(buf, cp, sizeof buf);
+ *cp = 0;
+ }
+ if (!cp || !*buf)
+ strlcpy(buf, DEFAULT_KERNEL, sizeof buf);
+ if (!*fname)
+ strlcpy(fname, bootdev, sizeof fname);
+ strlcpy(opened_name, fname,
+ partition ? (sizeof opened_name) - 2 : sizeof opened_name);
+ if (partition) {
+ cp = opened_name + strlen(opened_name);
+ *cp++ = ':';
+ *cp++ = partition;
+ *cp = 0;
+ }
+ if (*buf != '/')
+ strlcat(opened_name, "/", sizeof opened_name);
+ strlcat(opened_name, buf, sizeof opened_name);
+ *file = opened_name + strlen(fname) + 1;
+#ifdef SOFTRAID
}
- if (*buf != '/')
- strlcat(opened_name, "/", sizeof opened_name);
- strlcat(opened_name, buf, sizeof opened_name);
- *file = opened_name + strlen(fname) + 1;
+#endif
DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname);
+#ifdef SOFTRAID
+ if (bootdev_dip) {
+ /* Redirect to the softraid boot volume. */
+ struct partition *pp;
+
+ bzero(&ofdev, sizeof ofdev);
+ ofdev.type = OFDEV_SOFTRAID;
+
+ if (partition) {
+ if (partition < 'a' ||
+ partition >= 'a' + MAXPARTITIONS) {
+ printf("invalid partition '%c'\n", partition);
+ return EINVAL;
+ }
+ part = partition - 'a';
+ pp = &bootdev_dip->disklabel.d_partitions[part];
+ if (pp->p_fstype == FS_UNUSED || pp->p_size == 0) {
+ printf("invalid partition '%c'\n", partition);
+ return EINVAL;
+ }
+ bootdev_dip->sr_vol->sbv_part = partition;
+ } else
+ bootdev_dip->sr_vol->sbv_part = 'a';
+
+ of->f_dev = devsw;
+ of->f_devdata = &ofdev;
+
+#ifdef SPARC_BOOT_UFS
+ bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]);
+#else
+#error "-DSOFTRAID requires -DSPARC_BOOT_UFS"
+#endif
+ return 0;
+ }
+#endif
if ((handle = OF_finddevice(fname)) == -1)
return ENOENT;
DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname);
@@ -504,32 +626,13 @@ devopen(struct open_file *of, const char *name, char **file)
DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname);
bzero(&ofdev, sizeof ofdev);
ofdev.handle = handle;
+ ofdev.type = OFDEV_DISK;
+ ofdev.bsize = DEV_BSIZE;
if (!strcmp(buf, "block")) {
- ofdev.type = OFDEV_DISK;
- ofdev.bsize = DEV_BSIZE;
- /* First try to find a disklabel without MBR partitions */
- DNPRINTF(BOOT_D_OFDEV, "devopen: trying to read disklabel\n");
- if (strategy(&ofdev, F_READ,
- LABELSECTOR, DEV_BSIZE, buf, &read) != 0
- || read != DEV_BSIZE
- || (errmsg = getdisklabel(buf, &label))) {
-#ifdef BOOT_DEBUG
- if (errmsg)
- DNPRINTF(BOOT_D_OFDEV,
- "devopen: getdisklabel says %s\n", errmsg);
-#endif
- /* Else try MBR partitions */
- errmsg = search_label(&ofdev, LABELSECTOR, buf,
- &label, 0);
- if (errmsg) {
- printf("devopen: search_label says %s\n", errmsg);
- error = ERDLAB;
- }
- if (error && error != ERDLAB)
- goto bad;
- }
-
- if (error == ERDLAB) {
+ error = load_disklabel(&ofdev, &label);
+ if (error && error != ERDLAB)
+ goto bad;
+ else if (error == ERDLAB) {
if (partition)
/* User specified a parititon, but there is none */
goto bad;
diff --git a/sys/arch/sparc64/stand/ofwboot/ofdev.h b/sys/arch/sparc64/stand/ofwboot/ofdev.h
index 33cc9328561..a3ec6a9f63a 100644
--- a/sys/arch/sparc64/stand/ofwboot/ofdev.h
+++ b/sys/arch/sparc64/stand/ofwboot/ofdev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ofdev.h,v 1.4 2009/11/04 12:03:57 jsing Exp $ */
+/* $OpenBSD: ofdev.h,v 1.5 2014/11/26 20:30:41 stsp Exp $ */
/* $NetBSD: ofdev.h,v 1.1 2000/08/20 14:58:41 mrg Exp $ */
/*
@@ -56,10 +56,14 @@ struct of_dev {
/* Known types: */
#define OFDEV_NET 1
#define OFDEV_DISK 2
+#define OFDEV_SOFTRAID 3
#define DEFAULT_KERNEL "/bsd"
extern char opened_name[];
extern int floppyboot;
+int load_disklabel(struct of_dev *, struct disklabel *);
+int strategy(void *, int, daddr32_t, size_t, void *, size_t *);
+
#endif
diff --git a/sys/arch/sparc64/stand/ofwboot/vers.c b/sys/arch/sparc64/stand/ofwboot/vers.c
index 52bef9115ec..4fa0f5f0eb2 100644
--- a/sys/arch/sparc64/stand/ofwboot/vers.c
+++ b/sys/arch/sparc64/stand/ofwboot/vers.c
@@ -1 +1 @@
-const char version[] = "1.6";
+const char version[] = "1.7";