autoconf.c revision 1.15 1 /* $NetBSD: autoconf.c,v 1.15 2012/07/29 18:05:47 mlelstv Exp $ */
2 /* NetBSD: autoconf.c,v 1.75 2003/12/30 12:33:22 pk Exp */
3
4 /*-
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * William Jolitz.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
36 */
37
38 /*
39 * Setup the system to run on the current machine.
40 *
41 * Configure() is called at boot time and initializes the vba
42 * device tables and the memory controller monitoring. Available
43 * devices are determined (from possibilities mentioned in ioconf.c),
44 * and the drivers are initialized.
45 */
46
47 #include <sys/cdefs.h>
48 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.15 2012/07/29 18:05:47 mlelstv Exp $");
49
50 #include "opt_xen.h"
51 #include "opt_compat_oldboot.h"
52 #include "opt_multiprocessor.h"
53 #include "opt_nfs_boot.h"
54
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/buf.h>
58 #include <sys/disklabel.h>
59 #include <sys/disk.h>
60 #include <sys/conf.h>
61 #ifdef COMPAT_OLDBOOT
62 #include <sys/reboot.h>
63 #endif
64 #include <sys/device.h>
65 #include <sys/vnode.h>
66 #include <sys/fcntl.h>
67 #include <sys/dkio.h>
68 #include <sys/proc.h>
69 #include <sys/kauth.h>
70
71 #ifdef NFS_BOOT_BOOTSTATIC
72 #include <net/if.h>
73 #include <net/if_ether.h>
74 #include <netinet/in.h>
75 #include <nfs/rpcv2.h>
76 #include <nfs/nfsproto.h>
77 #include <nfs/nfs.h>
78 #include <nfs/nfsmount.h>
79 #include <nfs/nfsdiskless.h>
80 #include <xen/if_xennetvar.h>
81 #endif
82
83 #include <machine/pte.h>
84 #include <machine/cpu.h>
85 #include <machine/gdt.h>
86 #include <machine/pcb.h>
87 #include <machine/bootinfo.h>
88
89 static void findroot(void);
90 static int is_valid_disk(device_t);
91
92 struct disklist *x86_alldisks;
93 int x86_ndisks;
94
95 #include "bios32.h"
96 #if NBIOS32 > 0
97 #include <machine/bios32.h>
98 #endif
99
100 #include "opt_pcibios.h"
101 #ifdef PCIBIOS
102 #include <dev/pci/pcireg.h>
103 #include <dev/pci/pcivar.h>
104 #include <i386/pci/pcibios.h>
105 #endif
106
107 #include "opt_kvm86.h"
108 #ifdef KVM86
109 #include <machine/kvm86.h>
110 #endif
111
112 /*
113 * Determine i/o configuration for a machine.
114 */
115 void
116 cpu_configure(void)
117 {
118 struct pcb *pcb;
119
120 startrtclock();
121
122 #if NBIOS32 > 0 && defined(DOM0OPS)
123 if (xendomain_is_dom0())
124 bios32_init();
125 #endif /* NBIOS32 > 0 && DOM0OPS */
126 #ifdef PCIBIOS
127 pcibios_init();
128 #endif
129
130 #ifdef KVM86
131 kvm86_init();
132 #endif
133
134 if (config_rootfound("mainbus", NULL) == NULL)
135 panic("configure: mainbus not configured");
136
137 #ifdef INTRDEBUG
138 intr_printconfig();
139 #endif
140
141 /* resync cr0 after FPU configuration */
142 pcb = lwp_getpcb(&lwp0);
143 pcb->pcb_cr0 = rcr0();
144 #ifdef MULTIPROCESSOR
145 /* propagate this to the idle pcb's. */
146 cpu_init_idle_lwps();
147 #endif
148
149 spl0();
150 }
151
152 void
153 cpu_rootconf(void)
154 {
155 findroot();
156
157 printf("boot device: %s\n",
158 booted_device ? device_xname(booted_device) : "<unknown>");
159 rootconf();
160 }
161
162
163 /*
164 * Attempt to find the device from which we were booted.
165 * If we can do so, and not instructed not to do so,
166 * change rootdev to correspond to the load device.
167 */
168 void
169 findroot(void)
170 {
171 device_t dv;
172 deviter_t di;
173 union xen_cmdline_parseinfo xcp;
174
175 if (booted_device)
176 return;
177
178 xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp);
179
180 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
181 dv != NULL;
182 dv = deviter_next(&di)) {
183 bool is_ifnet, is_disk;
184 const char *devname;
185
186 is_ifnet = (device_class(dv) == DV_IFNET);
187 is_disk = is_valid_disk(dv);
188 devname = device_xname(dv);
189
190 if (!is_ifnet && !is_disk)
191 continue;
192
193 if (is_disk && xcp.xcp_bootdev[0] == 0) {
194 booted_device = dv;
195 break;
196 }
197
198 if (strncmp(xcp.xcp_bootdev, devname, strlen(devname)))
199 continue;
200
201 if (is_disk && strlen(xcp.xcp_bootdev) > strlen(devname)) {
202 booted_partition = toupper(
203 xcp.xcp_bootdev[strlen(devname)]) - 'A';
204 }
205
206 booted_device = dv;
207 break;
208 }
209 deviter_release(&di);
210 }
211
212 #include "pci.h"
213
214 #include <dev/isa/isavar.h>
215 #if NPCI > 0
216 #include <dev/pci/pcivar.h>
217 #endif
218
219
220 #if defined(NFS_BOOT_BOOTSTATIC) && defined(DOM0OPS)
221 static int
222 dom0_bootstatic_callback(struct nfs_diskless *nd)
223 {
224 #if 0
225 struct ifnet *ifp = nd->nd_ifp;
226 #endif
227 int flags = 0;
228 union xen_cmdline_parseinfo xcp;
229 struct sockaddr_in *sin;
230
231 memset(&xcp, 0, sizeof(xcp.xcp_netinfo));
232 xcp.xcp_netinfo.xi_ifno = 0; /* XXX first interface hardcoded */
233 xcp.xcp_netinfo.xi_root = nd->nd_root.ndm_host;
234 xen_parse_cmdline(XEN_PARSE_NETINFO, &xcp);
235
236 if (xcp.xcp_netinfo.xi_root[0] != '\0') {
237 flags |= NFS_BOOT_HAS_SERVER;
238 if (strchr(xcp.xcp_netinfo.xi_root, ':') != NULL)
239 flags |= NFS_BOOT_HAS_ROOTPATH;
240 }
241
242 nd->nd_myip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[0]);
243 nd->nd_gwip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[2]);
244 nd->nd_mask.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[3]);
245
246 sin = (struct sockaddr_in *) &nd->nd_root.ndm_saddr;
247 memset((void *)sin, 0, sizeof(*sin));
248 sin->sin_len = sizeof(*sin);
249 sin->sin_family = AF_INET;
250 sin->sin_addr.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[1]);
251
252 if (nd->nd_myip.s_addr)
253 flags |= NFS_BOOT_HAS_MYIP;
254 if (nd->nd_gwip.s_addr)
255 flags |= NFS_BOOT_HAS_GWIP;
256 if (nd->nd_mask.s_addr)
257 flags |= NFS_BOOT_HAS_MASK;
258 if (sin->sin_addr.s_addr)
259 flags |= NFS_BOOT_HAS_SERVADDR;
260
261 return flags;
262 }
263 #endif
264
265 void
266 device_register(device_t dev, void *aux)
267 {
268 /*
269 * Handle network interfaces here, the attachment information is
270 * not available driver independently later.
271 * For disks, there is nothing useful available at attach time.
272 */
273 #if NXENNET_HYPERVISOR > 0 || NXENNET_XENBUS > 0 || defined(DOM0OPS)
274 if (device_class(dev) == DV_IFNET) {
275 union xen_cmdline_parseinfo xcp;
276
277 #ifdef NFS_BOOT_BOOTSTATIC
278 #ifdef DOM0OPS
279 if (xendomain_is_privileged()) {
280 nfs_bootstatic_callback = dom0_bootstatic_callback;
281 } else
282 #endif
283 #if NXENNET_HYPERVISOR > 0 || NXENNET_XENBUS > 0
284 nfs_bootstatic_callback = xennet_bootstatic_callback;
285 #endif
286 #endif
287 xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp);
288 if (strncmp(xcp.xcp_bootdev, device_xname(dev),
289 sizeof(xcp.xcp_bootdev)) == 0)
290 {
291 goto found;
292 }
293 }
294 #endif
295 if (device_class(dev) == DV_IFNET) {
296 struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
297 if (bin == NULL)
298 return;
299
300 /*
301 * We don't check the driver name against the device name
302 * passed by the boot ROM. The ROM should stay usable
303 * if the driver gets obsoleted.
304 * The physical attachment information (checked below)
305 * must be sufficient to identify the device.
306 */
307
308 if (bin->bus == BI_BUS_ISA &&
309 device_is_a(device_parent(dev), "isa")) {
310 struct isa_attach_args *iaa = aux;
311
312 /* compare IO base address */
313 /* XXXJRT what about multiple I/O addrs? */
314 if (iaa->ia_nio > 0 &&
315 bin->addr.iobase == iaa->ia_io[0].ir_addr)
316 goto found;
317 }
318 #if NPCI > 0
319 if (bin->bus == BI_BUS_PCI &&
320 device_is_a(device_parent(dev), "pci")) {
321 struct pci_attach_args *paa = aux;
322 int b, d, f;
323
324 /*
325 * Calculate BIOS representation of:
326 *
327 * <bus,device,function>
328 *
329 * and compare.
330 */
331 pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
332 if (bin->addr.tag == ((b << 8) | (d << 3) | f))
333 goto found;
334 }
335 #endif
336 }
337 return;
338
339 found:
340 if (booted_device) {
341 /* XXX should be a "panic()" */
342 printf("warning: double match for boot device (%s, %s)\n",
343 device_xname(booted_device), device_xname(dev));
344 return;
345 }
346 booted_device = dev;
347 }
348
349 static int
350 is_valid_disk(device_t dv)
351 {
352
353 if (device_class(dv) != DV_DISK)
354 return (0);
355
356 return (device_is_a(dv, "dk") ||
357 device_is_a(dv, "sd") ||
358 device_is_a(dv, "wd") ||
359 device_is_a(dv, "ld") ||
360 device_is_a(dv, "ed") ||
361 device_is_a(dv, "xbd"));
362 }
363