diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2014-11-26 20:30:42 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2014-11-26 20:30:42 +0000 |
commit | 34b9f1984c0dc531d6656a31445bc2c592fca5de (patch) | |
tree | 329b9fd6c2359335cd7772a7b2dfbd7d0c912f77 /sys | |
parent | 9a4025874f62637b384dc4628eeabced98cde476 (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.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/Makefile | 20 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/boot.c | 102 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/disk.h | 50 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/diskprobe.c | 128 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/elf64_exec.c | 48 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/ofdev.c | 201 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/ofdev.h | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/vers.c | 2 |
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"; |