xref: /netbsd-src/sys/arch/landisk/landisk/autoconf.c (revision a6ce3504542ed8b086b0b8c7681fff4540e0cdd8)
1 /*	$NetBSD: autoconf.c,v 1.11 2023/12/20 15:00:08 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.11 2023/12/20 15:00:08 thorpej Exp $");
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <sys/disklabel.h>
36 #include <sys/conf.h>
37 #include <sys/vnode.h>
38 #include <sys/fcntl.h>
39 #include <sys/disk.h>
40 #include <sys/proc.h>
41 #include <sys/kauth.h>
42 
43 #include <machine/bootinfo.h>
44 #include <machine/intr.h>
45 
46 void
cpu_configure(void)47 cpu_configure(void)
48 {
49 
50 	/* Start configuration */
51 	splhigh();
52 	intr_init();
53 
54 	if (config_rootfound("mainbus", NULL) == NULL)
55 		panic("no mainbus found");
56 
57 	/* Configuration is finished, turn on interrupts. */
58 	spl0();
59 }
60 
61 static int
is_valid_disk(device_t dv)62 is_valid_disk(device_t dv)
63 {
64 	const char *name;
65 
66 	if (device_class(dv) != DV_DISK)
67 		return (0);
68 
69 	name = device_cfdata(dv)->cf_name;
70 
71 	return (strcmp(name, "sd") == 0 || strcmp(name, "wd") == 0 ||
72 		strcmp(name, "ld") == 0);
73 }
74 
75 /*
76  * Helper function for findroot():
77  * Return non-zero if disk device matches bootinfo.
78  */
79 static int
match_bootdisk(device_t dv,struct btinfo_bootdisk * bid)80 match_bootdisk(device_t dv, struct btinfo_bootdisk *bid)
81 {
82 	struct vnode *tmpvn;
83 	int error;
84 	struct disklabel label;
85 	int found = 0;
86 	int bmajor;
87 
88 	/*
89 	 * A disklabel is required here.  The boot loader doesn't refuse
90 	 * to boot from a disk without a label, but this is normally not
91 	 * wanted.
92 	 */
93 	if (bid->labelsector == -1)
94 		return (0);
95 
96 	/*
97 	 * Lookup major number for disk block device.
98 	 */
99 	bmajor = devsw_name2blk(device_xname(dv), NULL, 0);
100 	if (bmajor == -1)
101 		return (0);	/* XXX panic ??? */
102 
103 	/*
104 	 * Fake a temporary vnode for the disk, open it, and read
105 	 * the disklabel for comparison.
106 	 */
107 	if (bdevvp(MAKEDISKDEV(bmajor, device_unit(dv), RAW_PART), &tmpvn))
108 		panic("match_bootdisk: can't alloc vnode");
109 	vn_lock(tmpvn, LK_EXCLUSIVE | LK_RETRY);
110 	error = VOP_OPEN(tmpvn, FREAD, NOCRED);
111 	if (error) {
112 #ifndef DEBUG
113 		/*
114 		 * Ignore errors caused by missing device, partition,
115 		 * or medium.
116 		 */
117 		if (error != ENXIO && error != ENODEV)
118 #endif
119 			aprint_error("match_bootdisk: can't open dev %s (%d)\n",
120 			    device_xname(dv), error);
121 		vput(tmpvn);
122 		return (0);
123 	}
124 	VOP_UNLOCK(tmpvn);
125 	error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED);
126 	if (error) {
127 		/*
128 		 * XXX Can't happen -- open() would have errored out
129 		 * or faked one up.
130 		 */
131 		aprint_error("match_bootdisk: can't get label for dev %s (%d)\n",
132 		    device_xname(dv), error);
133 		goto closeout;
134 	}
135 
136 	/* Compare with our data. */
137 	if (label.d_type == bid->label.type &&
138 	    label.d_checksum == bid->label.checksum &&
139 	    strncmp(label.d_packname, bid->label.packname, 16) == 0)
140 	    	found = 1;
141 
142 closeout:
143 	vn_lock(tmpvn, LK_EXCLUSIVE | LK_RETRY);
144 	VOP_CLOSE(tmpvn, FREAD, NOCRED);
145 	vput(tmpvn);
146 	return (found);
147 }
148 
149 /*
150  * Attempt to find the device from which we were booted.  If we can do so,
151  * and not instructed not to do so, change rootdev to correspond to the
152  * load device.
153  */
154 static void
findroot(void)155 findroot(void)
156 {
157 	struct btinfo_bootdisk *bid;
158 	device_t dv;
159 	deviter_t di;
160 
161 	if (booted_device)
162 		return;
163 
164 	if ((bid = lookup_bootinfo(BTINFO_BOOTDISK)) != NULL) {
165 		/*
166 		 * Scan all disk devices for ones that match the passed data.
167 		 * Don't break if one is found, to get possible multiple
168 		 * matches - for problem tracking.  Use the first match anyway
169 		 * because lower device numbers are more likely to be the
170 		 * boot device.
171 		 */
172 		for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
173 		     dv != NULL;
174 		     dv = deviter_next(&di)) {
175 			if (device_class(dv) != DV_DISK)
176 				continue;
177 
178 			if (is_valid_disk(dv)) {
179 				if (match_bootdisk(dv, bid) == 0)
180 				    	continue;
181 				goto bootdisk_found;
182 			}
183 			continue;
184 
185 bootdisk_found:
186 			if (booted_device) {
187 				aprint_error("WARNING: double match for boot "
188 				    "device (%s, %s)\n",
189 				    device_xname(booted_device), device_xname(dv));
190 				continue;
191 			}
192 			booted_device = dv;
193 			booted_partition = bid->partition;
194 		}
195 		deviter_release(&di);
196 
197 		if (booted_device)
198 			return;
199 	}
200 }
201 
202 void
cpu_rootconf(void)203 cpu_rootconf(void)
204 {
205 
206 	findroot();
207 
208 	aprint_normal("boot device: %s\n",
209 	    booted_device ? device_xname(booted_device) : "<unknown>");
210 	rootconf();
211 }
212