| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: autoconf.c,v 1.57 2021/05/22 15:05:36 thorpej Exp $ */ | | 1 | /* $NetBSD: autoconf.c,v 1.58 2021/07/09 01:29:20 thorpej Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1992, 1993 | | 4 | * Copyright (c) 1992, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This software was developed by the Computer Systems Engineering group | | 7 | * This software was developed by the Computer Systems Engineering group |
8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | | 8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and |
9 | * contributed to Berkeley. | | 9 | * contributed to Berkeley. |
10 | * | | 10 | * |
11 | * All advertising materials mentioning features or use of this software | | 11 | * All advertising materials mentioning features or use of this software |
12 | * must display the following acknowledgement: | | 12 | * must display the following acknowledgement: |
13 | * This product includes software developed by the University of | | 13 | * This product includes software developed by the University of |
14 | * California, Lawrence Berkeley Laboratory. | | 14 | * California, Lawrence Berkeley Laboratory. |
| @@ -32,52 +32,54 @@ | | | @@ -32,52 +32,54 @@ |
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
38 | * SUCH DAMAGE. | | 38 | * SUCH DAMAGE. |
39 | * | | 39 | * |
40 | * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 | | 40 | * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 |
41 | */ | | 41 | */ |
42 | | | 42 | |
43 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ | | 43 | #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ |
44 | | | 44 | |
45 | __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.57 2021/05/22 15:05:36 thorpej Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.58 2021/07/09 01:29:20 thorpej Exp $"); |
46 | | | 46 | |
47 | #include "pci.h" | | 47 | #include "pci.h" |
48 | | | 48 | |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | #include <sys/systm.h> | | 50 | #include <sys/systm.h> |
51 | #include <sys/buf.h> | | 51 | #include <sys/buf.h> |
52 | #include <sys/disklabel.h> | | 52 | #include <sys/disklabel.h> |
53 | #include <sys/reboot.h> | | 53 | #include <sys/reboot.h> |
54 | #include <sys/device.h> | | 54 | #include <sys/device.h> |
55 | #include <sys/conf.h> | | 55 | #include <sys/conf.h> |
56 | #include <dev/cons.h> | | 56 | #include <dev/cons.h> |
57 | | | 57 | |
58 | #include <dev/pci/pcivar.h> | | 58 | #include <dev/pci/pcivar.h> |
59 | | | 59 | |
| | | 60 | #include <net/if.h> |
| | | 61 | #include <net/if_ether.h> |
| | | 62 | |
60 | #include <machine/autoconf.h> | | 63 | #include <machine/autoconf.h> |
61 | #include <machine/alpha.h> | | 64 | #include <machine/alpha.h> |
62 | #include <machine/cpu.h> | | 65 | #include <machine/cpu.h> |
63 | #include <machine/prom.h> | | 66 | #include <machine/prom.h> |
64 | #include <machine/cpuconf.h> | | 67 | #include <machine/cpuconf.h> |
65 | #include <machine/intr.h> | | 68 | #include <machine/intr.h> |
66 | | | 69 | |
67 | struct bootdev_data *bootdev_data; | | 70 | struct bootdev_data *bootdev_data; |
68 | | | 71 | |
69 | void parse_prom_bootdev(void); | | 72 | static void parse_prom_bootdev(void); |
70 | static inline int atoi(const char *); | | | |
71 | | | 73 | |
72 | /* | | 74 | /* |
73 | * cpu_configure: | | 75 | * cpu_configure: |
74 | * called at boot time, configure all devices on system | | 76 | * called at boot time, configure all devices on system |
75 | */ | | 77 | */ |
76 | void | | 78 | void |
77 | cpu_configure(void) | | 79 | cpu_configure(void) |
78 | { | | 80 | { |
79 | | | 81 | |
80 | parse_prom_bootdev(); | | 82 | parse_prom_bootdev(); |
81 | | | 83 | |
82 | /* | | 84 | /* |
83 | * Disable interrupts during autoconfiguration. splhigh() won't | | 85 | * Disable interrupts during autoconfiguration. splhigh() won't |
| @@ -128,42 +130,142 @@ qemu_find_rootdev(void) | | | @@ -128,42 +130,142 @@ qemu_find_rootdev(void) |
128 | /* Now strip any partition letter off the end. */ | | 130 | /* Now strip any partition letter off the end. */ |
129 | while (ecp != cp) { | | 131 | while (ecp != cp) { |
130 | if (*ecp >= '0' && *ecp <= '9') { | | 132 | if (*ecp >= '0' && *ecp <= '9') { |
131 | break; | | 133 | break; |
132 | } | | 134 | } |
133 | *ecp-- = '\0'; | | 135 | *ecp-- = '\0'; |
134 | } | | 136 | } |
135 | | | 137 | |
136 | snprintf(bootinfo.booted_dev, sizeof(bootinfo.booted_dev), | | 138 | snprintf(bootinfo.booted_dev, sizeof(bootinfo.booted_dev), |
137 | "root=%s", cp); | | 139 | "root=%s", cp); |
138 | booted_device = device_find_by_xname(cp); | | 140 | booted_device = device_find_by_xname(cp); |
139 | } | | 141 | } |
140 | | | 142 | |
| | | 143 | static bool |
| | | 144 | parse_dec_macaddr(const char *str, uint8_t enaddr[ETHER_ADDR_LEN]) |
| | | 145 | { |
| | | 146 | char *cp; |
| | | 147 | long long l; |
| | | 148 | int i; |
| | | 149 | |
| | | 150 | /* |
| | | 151 | * DEC Ethernet address strings are formatted like so: |
| | | 152 | * |
| | | 153 | * XX-XX-XX-XX-XX-XX |
| | | 154 | */ |
| | | 155 | |
| | | 156 | for (i = 0; i < ETHER_ADDR_LEN; i++) { |
| | | 157 | l = strtoll(str, &cp, 16); |
| | | 158 | if (l < 0 || l > 0xff) { |
| | | 159 | /* Not a valid MAC address. */ |
| | | 160 | return false; |
| | | 161 | } |
| | | 162 | if (*cp == '-') { |
| | | 163 | /* Octet separator. */ |
| | | 164 | enaddr[i] = (uint8_t)l; |
| | | 165 | str = cp + 1; |
| | | 166 | continue; |
| | | 167 | } |
| | | 168 | if (*cp == ' ' || *cp == '\0') { |
| | | 169 | /* End of the string. */ |
| | | 170 | enaddr[i] = (uint8_t)l; |
| | | 171 | return i == ETHER_ADDR_LEN - 1; |
| | | 172 | } |
| | | 173 | /* Bogus character. */ |
| | | 174 | break; |
| | | 175 | } |
| | | 176 | |
| | | 177 | /* Encountered bogus character or didn't reach end of string. */ |
| | | 178 | return false; |
| | | 179 | } |
| | | 180 | |
| | | 181 | static void |
| | | 182 | netboot_find_rootdev_planb(void) |
| | | 183 | { |
| | | 184 | struct psref psref; |
| | | 185 | uint8_t enaddr[ETHER_ADDR_LEN]; |
| | | 186 | char ifname[IFNAMSIZ]; |
| | | 187 | int i; |
| | | 188 | |
| | | 189 | if (strncasecmp(bootinfo.booted_dev, "BOOTP ", 6) != 0 && |
| | | 190 | strncasecmp(bootinfo.booted_dev, "MOP ", 4) != 0) { |
| | | 191 | /* We weren't netbooted. */ |
| | | 192 | return; |
| | | 193 | } |
| | | 194 | |
| | | 195 | for (i = 2; bootinfo.booted_dev[i] != '\0'; i++) { |
| | | 196 | if (bootinfo.booted_dev[i] == '-') { |
| | | 197 | if (parse_dec_macaddr(&bootinfo.booted_dev[i - 2], |
| | | 198 | enaddr)) { |
| | | 199 | /* Found it! */ |
| | | 200 | break; |
| | | 201 | } |
| | | 202 | } |
| | | 203 | } |
| | | 204 | if (bootinfo.booted_dev[i] == '\0') { |
| | | 205 | /* No MAC address in string. */ |
| | | 206 | return; |
| | | 207 | } |
| | | 208 | |
| | | 209 | /* Now try to look up the interface by the link address. */ |
| | | 210 | struct ifnet *ifp = if_get_bylla(enaddr, ETHER_ADDR_LEN, &psref); |
| | | 211 | if (ifp == NULL) { |
| | | 212 | /* No interface attached with that MAC address. */ |
| | | 213 | return; |
| | | 214 | } |
| | | 215 | |
| | | 216 | strlcpy(ifname, if_name(ifp), sizeof(ifname)); |
| | | 217 | if_put(ifp, &psref); |
| | | 218 | |
| | | 219 | /* Ok! Now look up the device_t by name! */ |
| | | 220 | booted_device = device_find_by_xname(ifname); |
| | | 221 | } |
| | | 222 | |
141 | void | | 223 | void |
142 | cpu_rootconf(void) | | 224 | cpu_rootconf(void) |
143 | { | | 225 | { |
144 | | | 226 | |
145 | if (booted_device == NULL && alpha_is_qemu) { | | 227 | if (booted_device == NULL && alpha_is_qemu) { |
146 | qemu_find_rootdev(); | | 228 | qemu_find_rootdev(); |
147 | } | | 229 | } |
148 | | | 230 | |
149 | if (booted_device == NULL) { | | 231 | if (booted_device == NULL) { |
| | | 232 | /* |
| | | 233 | * It's possible that we netbooted from an Ethernet |
| | | 234 | * interface that can't be matched via the usual |
| | | 235 | * logic in device_register() (a DE204 in an ISA slot, |
| | | 236 | * for example). In these cases, the console may have |
| | | 237 | * provided us with a MAC address that we can use to |
| | | 238 | * try and find the interface, * e.g.: |
| | | 239 | * |
| | | 240 | * BOOTP 1 1 0 0 0 5 0 08-00-2B-xx-xx-xx 1 |
| | | 241 | */ |
| | | 242 | netboot_find_rootdev_planb(); |
| | | 243 | } |
| | | 244 | |
| | | 245 | if (booted_device == NULL) { |
150 | printf("WARNING: can't figure what device matches \"%s\"\n", | | 246 | printf("WARNING: can't figure what device matches \"%s\"\n", |
151 | bootinfo.booted_dev); | | 247 | bootinfo.booted_dev); |
152 | } | | 248 | } |
153 | rootconf(); | | 249 | rootconf(); |
154 | } | | 250 | } |
155 | | | 251 | |
156 | void | | 252 | static inline int |
| | | 253 | atoi(const char *s) |
| | | 254 | { |
| | | 255 | return (int)strtoll(s, NULL, 10); |
| | | 256 | } |
| | | 257 | |
| | | 258 | static void |
157 | parse_prom_bootdev(void) | | 259 | parse_prom_bootdev(void) |
158 | { | | 260 | { |
159 | static char hacked_boot_dev[128]; | | 261 | static char hacked_boot_dev[128]; |
160 | static struct bootdev_data bd; | | 262 | static struct bootdev_data bd; |
161 | char *cp, *scp, *boot_fields[8]; | | 263 | char *cp, *scp, *boot_fields[8]; |
162 | int i, done; | | 264 | int i, done; |
163 | | | 265 | |
164 | booted_device = NULL; | | 266 | booted_device = NULL; |
165 | booted_partition = 0; | | 267 | booted_partition = 0; |
166 | bootdev_data = NULL; | | 268 | bootdev_data = NULL; |
167 | | | 269 | |
168 | memcpy(hacked_boot_dev, bootinfo.booted_dev, | | 270 | memcpy(hacked_boot_dev, bootinfo.booted_dev, |
169 | uimin(sizeof bootinfo.booted_dev, sizeof hacked_boot_dev)); | | 271 | uimin(sizeof bootinfo.booted_dev, sizeof hacked_boot_dev)); |
| @@ -203,32 +305,26 @@ parse_prom_bootdev(void) | | | @@ -203,32 +305,26 @@ parse_prom_bootdev(void) |
203 | bd.boot_dev_type = atoi(boot_fields[6]); | | 305 | bd.boot_dev_type = atoi(boot_fields[6]); |
204 | bd.ctrl_dev_type = boot_fields[7]; | | 306 | bd.ctrl_dev_type = boot_fields[7]; |
205 | | | 307 | |
206 | #if 0 | | 308 | #if 0 |
207 | printf("parsed: proto = %s, bus = %d, slot = %d, channel = %d,\n", | | 309 | printf("parsed: proto = %s, bus = %d, slot = %d, channel = %d,\n", |
208 | bd.protocol, bd.bus, bd.slot, bd.channel); | | 310 | bd.protocol, bd.bus, bd.slot, bd.channel); |
209 | printf("\tremote = %s, unit = %d, dev_type = %d, ctrl_type = %s\n", | | 311 | printf("\tremote = %s, unit = %d, dev_type = %d, ctrl_type = %s\n", |
210 | bd.remote_address, bd.unit, bd.boot_dev_type, bd.ctrl_dev_type); | | 312 | bd.remote_address, bd.unit, bd.boot_dev_type, bd.ctrl_dev_type); |
211 | #endif | | 313 | #endif |
212 | | | 314 | |
213 | bootdev_data = &bd; | | 315 | bootdev_data = &bd; |
214 | } | | 316 | } |
215 | | | 317 | |
216 | static inline int | | | |
217 | atoi(const char *s) | | | |
218 | { | | | |
219 | return (int)strtoll(s, NULL, 10); | | | |
220 | } | | | |
221 | | | | |
222 | void | | 318 | void |
223 | device_register(device_t dev, void *aux) | | 319 | device_register(device_t dev, void *aux) |
224 | { | | 320 | { |
225 | #if NPCI > 0 | | 321 | #if NPCI > 0 |
226 | device_t parent = device_parent(dev); | | 322 | device_t parent = device_parent(dev); |
227 | | | 323 | |
228 | if (parent != NULL && device_is_a(parent, "pci")) | | 324 | if (parent != NULL && device_is_a(parent, "pci")) |
229 | device_pci_register(dev, aux); | | 325 | device_pci_register(dev, aux); |
230 | #endif | | 326 | #endif |
231 | | | 327 | |
232 | if (bootdev_data == NULL) { | | 328 | if (bootdev_data == NULL) { |
233 | /* | | 329 | /* |
234 | * There is no hope. | | 330 | * There is no hope. |