1 /* $NetBSD: autoconf.c,v 1.17 2023/12/20 15:34:46 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.17 2023/12/20 15:34:46 thorpej Exp $");
31
32 #include "opt_md.h"
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 #include <sys/disklabel.h>
38 #include <sys/conf.h>
39 #include <sys/vnode.h>
40 #include <sys/fcntl.h>
41 #include <sys/proc.h>
42 #include <sys/disk.h>
43 #include <sys/kauth.h>
44
45 #include <dev/i2c/i2cvar.h>
46
47 #include <machine/intr.h>
48 #include <machine/bootconfig.h>
49 #include <machine/bootinfo.h>
50 #include <machine/config_hook.h>
51
52 static int is_valid_disk(device_t dv);
53 static int match_bootdisk(device_t dv, struct btinfo_bootdisk *bid);
54 static void findroot(void);
55
56 void
cpu_configure(void)57 cpu_configure(void)
58 {
59
60 splhigh();
61 splserial();
62
63 config_hook_init();
64
65 if (config_rootfound("mainbus", NULL) == NULL)
66 panic("no mainbus found");
67
68 /* Configuration is finished, turn on interrupts. */
69 spl0();
70 }
71
72 static int
is_valid_disk(device_t dv)73 is_valid_disk(device_t dv)
74 {
75
76 if (device_class(dv) != DV_DISK)
77 return 0;
78
79 return (device_is_a(dv, "dk") ||
80 device_is_a(dv, "sd") ||
81 device_is_a(dv, "wd") ||
82 device_is_a(dv, "ld"));
83 }
84
85 /*
86 * Helper function for findroot():
87 * Return non-zero if disk device matches bootinfo.
88 */
89 static int
match_bootdisk(device_t dv,struct btinfo_bootdisk * bid)90 match_bootdisk(device_t dv, struct btinfo_bootdisk *bid)
91 {
92 struct vnode *tmpvn;
93 int error;
94 struct disklabel label;
95 int found = 0;
96
97 if (device_is_a(dv, "dk"))
98 return 0;
99
100 /*
101 * A disklabel is required here. The boot loader doesn't refuse
102 * to boot from a disk without a label, but this is normally not
103 * wanted.
104 */
105 if (bid->labelsector == -1)
106 return 0;
107
108 if ((tmpvn = opendisk(dv)) == NULL)
109 return 0;
110
111 VOP_UNLOCK(tmpvn);
112 error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED);
113 vn_lock(tmpvn, LK_EXCLUSIVE | LK_RETRY);
114 if (error) {
115 /*
116 * XXX Can't happen -- open() would have errored out
117 * or faked one up.
118 */
119 printf("match_bootdisk: can't get label for dev %s (%d)\n",
120 device_xname(dv), error);
121 goto closeout;
122 }
123
124 /* Compare with our data. */
125 if (label.d_type == bid->label.type &&
126 label.d_checksum == bid->label.checksum &&
127 strncmp(label.d_packname, bid->label.packname, 16) == 0)
128 found = 1;
129
130 closeout:
131 VOP_CLOSE(tmpvn, FREAD, NOCRED);
132 vput(tmpvn);
133 return found;
134 }
135
136 static void
findroot(void)137 findroot(void)
138 {
139 struct btinfo_rootdevice *biv;
140 struct btinfo_bootdisk *bid;
141 device_t dv;
142 deviter_t di;
143
144 if (booted_device)
145 return;
146
147 if ((biv = lookup_bootinfo(BTINFO_ROOTDEVICE)) != NULL) {
148 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
149 dv != NULL;
150 dv = deviter_next(&di)) {
151 cfdata_t cd;
152 size_t len;
153
154 if (device_class(dv) != DV_DISK)
155 continue;
156
157 cd = device_cfdata(dv);
158 len = strlen(cd->cf_name);
159
160 if (strncmp(cd->cf_name, biv->devname, len) == 0 &&
161 biv->devname[len] - '0' == cd->cf_unit) {
162 booted_device = dv;
163 booted_partition = biv->devname[len + 1] - 'a';
164 break;
165 }
166 }
167 deviter_release(&di);
168 if (dv != NULL)
169 return;
170 }
171
172 if ((bid = lookup_bootinfo(BTINFO_BOOTDISK)) != NULL) {
173 /*
174 * Scan all disk devices for ones that match the passed data.
175 * Don't break if one is found, to get possible multiple
176 * matches - for problem tracking. Use the first match anyway
177 * because lower device numbers are more likely to be the
178 * boot device.
179 */
180 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
181 dv != NULL;
182 dv = deviter_next(&di)) {
183 if (device_class(dv) != DV_DISK)
184 continue;
185
186 if (is_valid_disk(dv)) {
187 if (match_bootdisk(dv, bid))
188 goto bootdisk_found;
189 }
190 continue;
191
192 bootdisk_found:
193 if (booted_device) {
194 printf("WARNING: double match for boot "
195 "device (%s, %s)\n",
196 device_xname(booted_device),
197 device_xname(dv));
198 continue;
199 }
200 booted_device = dv;
201 booted_partition = bid->partition;
202 }
203 deviter_release(&di);
204
205 if (booted_device)
206 return;
207 }
208 }
209
210 void
cpu_rootconf(void)211 cpu_rootconf(void)
212 {
213
214 findroot();
215
216 aprint_normal("boot device: %s\n",
217 booted_device ? device_xname(booted_device) : "<unknown>");
218 rootconf();
219 }
220
221 void
device_register(device_t dev,void * aux)222 device_register(device_t dev, void *aux)
223 {
224
225 /*
226 * I2C bus conntected to pxaiic(4) for zaudio(4) devices has
227 * limited capabilities.
228 */
229 if (device_is_a(dev, "iic") &&
230 device_is_a(device_parent(dev), "ziic")) {
231 (void)prop_dictionary_set_string_nocopy(device_properties(dev),
232 I2C_PROP_INDIRECT_PROBE_STRATEGY, I2C_PROBE_STRATEGY_NONE);
233 }
234 }
235