xref: /openbsd-src/usr.sbin/installboot/softraid.c (revision 808c65001a8f417e47b5d11110894acfa47f0f8a)
1 /*	$OpenBSD: softraid.c,v 1.2 2013/12/28 11:26:57 jsing Exp $	*/
2 /*
3  * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/param.h>
19 #include <sys/dkio.h>
20 #include <sys/ioctl.h>
21 
22 #include <dev/biovar.h>
23 
24 #include <err.h>
25 #include <stdio.h>
26 #include <string.h>
27 
28 #include "installboot.h"
29 
30 static int sr_volume(int, char *, int *, int *);
31 
32 void
33 sr_installboot(int devfd, char *dev)
34 {
35 	int	vol = -1, ndisks = 0, disk;
36 
37 	/* Use the normal process if this is not a softraid volume. */
38 	if (!sr_volume(devfd, dev, &vol, &ndisks)) {
39 		md_installboot(devfd, dev);
40 		return;
41 	}
42 
43 	/* Install boot loader in softraid volume. */
44 	sr_install_bootldr(devfd, dev);
45 
46 	/* Install boot block on each disk that is part of this volume. */
47 	for (disk = 0; disk < ndisks; disk++)
48 		sr_install_bootblk(devfd, vol, disk);
49 }
50 
51 int
52 sr_volume(int devfd, char *dev, int *vol, int *disks)
53 {
54 	struct	bioc_inq bi;
55 	struct	bioc_vol bv;
56 	int	i;
57 
58 	/*
59 	 * Determine if the given device is a softraid volume.
60 	 */
61 
62 	/* Get volume information. */
63 	memset(&bi, 0, sizeof(bi));
64 	if (ioctl(devfd, BIOCINQ, &bi) == -1)
65 		return 0;
66 
67 	/* XXX - softraid volumes will always have a "softraid0" controller. */
68 	if (strncmp(bi.bi_dev, "softraid0", sizeof("softraid0")))
69 		return 0;
70 
71 	/*
72 	 * XXX - this only works with the real disk name (e.g. sd0) - this
73 	 * should be extracted from the device name, or better yet, fixed in
74 	 * the softraid ioctl.
75 	 */
76 	/* Locate specific softraid volume. */
77 	for (i = 0; i < bi.bi_novol; i++) {
78 		memset(&bv, 0, sizeof(bv));
79 		bv.bv_volid = i;
80 		if (ioctl(devfd, BIOCVOL, &bv) == -1)
81 			err(1, "BIOCVOL");
82 
83 		if (strncmp(dev, bv.bv_dev, sizeof(bv.bv_dev)) == 0) {
84 			*vol = i;
85 			*disks = bv.bv_nodisk;
86 			break;
87 		}
88 	}
89 
90 	if (verbose)
91 		fprintf(stderr, "%s: softraid volume with %i disk(s)\n",
92 		    dev, *disks);
93 
94 	return 1;
95 }
96