1 /* $NetBSD: autoconf.c,v 1.18 2025/05/19 06:16:24 andvar 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.18 2025/05/19 06:16:24 andvar 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 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 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 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 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 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 222 device_register(device_t dev, void *aux) 223 { 224 225 /* 226 * I2C bus connected 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