1 | /* $NetBSD: autoconf.c,v 1.17 2014/04/03 15:53:05 christos 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.17 2014/04/03 15:53:05 christos 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 int is_valid_disk(device_t); |
90 | |
91 | struct disklist *x86_alldisks; |
92 | int x86_ndisks; |
93 | |
94 | #include "bios32.h" |
95 | #if NBIOS32 > 0 |
96 | #include <machine/bios32.h> |
97 | #endif |
98 | |
99 | #include "opt_pcibios.h" |
100 | #ifdef PCIBIOS |
101 | #include <dev/pci/pcireg.h> |
102 | #include <dev/pci/pcivar.h> |
103 | #include <i386/pci/pcibios.h> |
104 | #endif |
105 | |
106 | /* |
107 | * Determine i/o configuration for a machine. |
108 | */ |
109 | void |
110 | cpu_configure(void) |
111 | { |
112 | struct pcb *pcb; |
113 | |
114 | startrtclock(); |
115 | |
116 | #if NBIOS32 > 0 && defined(DOM0OPS) |
117 | if (xendomain_is_dom0()) |
118 | bios32_init(); |
119 | #endif /* NBIOS32 > 0 && DOM0OPS */ |
120 | #ifdef PCIBIOS |
121 | pcibios_init(); |
122 | #endif |
123 | |
124 | if (config_rootfound("mainbus" , NULL) == NULL) |
125 | panic("configure: mainbus not configured" ); |
126 | |
127 | #ifdef INTRDEBUG |
128 | intr_printconfig(); |
129 | #endif |
130 | |
131 | /* resync cr0 after FPU configuration */ |
132 | pcb = lwp_getpcb(&lwp0); |
133 | pcb->pcb_cr0 = rcr0(); |
134 | #ifdef MULTIPROCESSOR |
135 | /* propagate this to the idle pcb's. */ |
136 | cpu_init_idle_lwps(); |
137 | #endif |
138 | |
139 | spl0(); |
140 | } |
141 | |
142 | void |
143 | cpu_rootconf(void) |
144 | { |
145 | cpu_bootconf(); |
146 | |
147 | printf("boot device: %s\n" , |
148 | booted_device ? device_xname(booted_device) : "<unknown>" ); |
149 | rootconf(); |
150 | } |
151 | |
152 | |
153 | /* |
154 | * Attempt to find the device from which we were booted. |
155 | */ |
156 | void |
157 | cpu_bootconf(void) |
158 | { |
159 | device_t dv; |
160 | deviter_t di; |
161 | union xen_cmdline_parseinfo xcp; |
162 | |
163 | if (booted_device) |
164 | return; |
165 | |
166 | xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp); |
167 | |
168 | for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); |
169 | dv != NULL; |
170 | dv = deviter_next(&di)) { |
171 | bool is_ifnet, is_disk; |
172 | const char *devname; |
173 | |
174 | is_ifnet = (device_class(dv) == DV_IFNET); |
175 | is_disk = is_valid_disk(dv); |
176 | devname = device_xname(dv); |
177 | |
178 | if (!is_ifnet && !is_disk) |
179 | continue; |
180 | |
181 | if (is_disk && xcp.xcp_bootdev[0] == 0) { |
182 | booted_device = dv; |
183 | break; |
184 | } |
185 | |
186 | if (strncmp(xcp.xcp_bootdev, devname, strlen(devname))) |
187 | continue; |
188 | |
189 | if (is_disk && strlen(xcp.xcp_bootdev) > strlen(devname)) { |
190 | booted_partition = toupper( |
191 | xcp.xcp_bootdev[strlen(devname)]) - 'A'; |
192 | } |
193 | |
194 | booted_device = dv; |
195 | break; |
196 | } |
197 | deviter_release(&di); |
198 | } |
199 | |
200 | #include "pci.h" |
201 | |
202 | #include <dev/isa/isavar.h> |
203 | #if NPCI > 0 |
204 | #include <dev/pci/pcivar.h> |
205 | #endif |
206 | |
207 | |
208 | #if defined(NFS_BOOT_BOOTSTATIC) && defined(DOM0OPS) |
209 | static int |
210 | dom0_bootstatic_callback(struct nfs_diskless *nd) |
211 | { |
212 | #if 0 |
213 | struct ifnet *ifp = nd->nd_ifp; |
214 | #endif |
215 | int flags = 0; |
216 | union xen_cmdline_parseinfo xcp; |
217 | struct sockaddr_in *sin; |
218 | |
219 | memset(&xcp, 0, sizeof(xcp.xcp_netinfo)); |
220 | xcp.xcp_netinfo.xi_ifno = 0; /* XXX first interface hardcoded */ |
221 | xcp.xcp_netinfo.xi_root = nd->nd_root.ndm_host; |
222 | xen_parse_cmdline(XEN_PARSE_NETINFO, &xcp); |
223 | |
224 | if (xcp.xcp_netinfo.xi_root[0] != '\0') { |
225 | flags |= NFS_BOOT_HAS_SERVER; |
226 | if (strchr(xcp.xcp_netinfo.xi_root, ':') != NULL) |
227 | flags |= NFS_BOOT_HAS_ROOTPATH; |
228 | } |
229 | |
230 | nd->nd_myip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[0]); |
231 | nd->nd_gwip.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[2]); |
232 | nd->nd_mask.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[3]); |
233 | |
234 | sin = (struct sockaddr_in *) &nd->nd_root.ndm_saddr; |
235 | memset((void *)sin, 0, sizeof(*sin)); |
236 | sin->sin_len = sizeof(*sin); |
237 | sin->sin_family = AF_INET; |
238 | sin->sin_addr.s_addr = ntohl(xcp.xcp_netinfo.xi_ip[1]); |
239 | |
240 | if (nd->nd_myip.s_addr) |
241 | flags |= NFS_BOOT_HAS_MYIP; |
242 | if (nd->nd_gwip.s_addr) |
243 | flags |= NFS_BOOT_HAS_GWIP; |
244 | if (nd->nd_mask.s_addr) |
245 | flags |= NFS_BOOT_HAS_MASK; |
246 | if (sin->sin_addr.s_addr) |
247 | flags |= NFS_BOOT_HAS_SERVADDR; |
248 | |
249 | return flags; |
250 | } |
251 | #endif |
252 | |
253 | void |
254 | device_register(device_t dev, void *aux) |
255 | { |
256 | /* |
257 | * Handle network interfaces here, the attachment information is |
258 | * not available driver independently later. |
259 | * For disks, there is nothing useful available at attach time. |
260 | */ |
261 | #if NXENNET_HYPERVISOR > 0 || NXENNET_XENBUS > 0 || defined(DOM0OPS) |
262 | if (device_class(dev) == DV_IFNET) { |
263 | union xen_cmdline_parseinfo xcp; |
264 | |
265 | #ifdef NFS_BOOT_BOOTSTATIC |
266 | #ifdef DOM0OPS |
267 | if (xendomain_is_privileged()) { |
268 | nfs_bootstatic_callback = dom0_bootstatic_callback; |
269 | } else |
270 | #endif |
271 | #if NXENNET_HYPERVISOR > 0 || NXENNET_XENBUS > 0 |
272 | nfs_bootstatic_callback = xennet_bootstatic_callback; |
273 | #endif |
274 | #endif |
275 | xen_parse_cmdline(XEN_PARSE_BOOTDEV, &xcp); |
276 | if (strncmp(xcp.xcp_bootdev, device_xname(dev), |
277 | sizeof(xcp.xcp_bootdev)) == 0) |
278 | { |
279 | goto found; |
280 | } |
281 | } |
282 | #endif |
283 | if (device_class(dev) == DV_IFNET) { |
284 | struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF); |
285 | if (bin == NULL) |
286 | return; |
287 | |
288 | /* |
289 | * We don't check the driver name against the device name |
290 | * passed by the boot ROM. The ROM should stay usable |
291 | * if the driver gets obsoleted. |
292 | * The physical attachment information (checked below) |
293 | * must be sufficient to identify the device. |
294 | */ |
295 | |
296 | if (bin->bus == BI_BUS_ISA && |
297 | device_is_a(device_parent(dev), "isa" )) { |
298 | struct isa_attach_args *iaa = aux; |
299 | |
300 | /* compare IO base address */ |
301 | /* XXXJRT what about multiple I/O addrs? */ |
302 | if (iaa->ia_nio > 0 && |
303 | bin->addr.iobase == iaa->ia_io[0].ir_addr) |
304 | goto found; |
305 | } |
306 | #if NPCI > 0 |
307 | if (bin->bus == BI_BUS_PCI && |
308 | device_is_a(device_parent(dev), "pci" )) { |
309 | struct pci_attach_args *paa = aux; |
310 | int b, d, f; |
311 | |
312 | /* |
313 | * Calculate BIOS representation of: |
314 | * |
315 | * <bus,device,function> |
316 | * |
317 | * and compare. |
318 | */ |
319 | pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f); |
320 | if (bin->addr.tag == ((b << 8) | (d << 3) | f)) |
321 | goto found; |
322 | } |
323 | #endif |
324 | } |
325 | return; |
326 | |
327 | found: |
328 | if (booted_device) { |
329 | /* XXX should be a "panic()" */ |
330 | printf("warning: double match for boot device (%s, %s)\n" , |
331 | device_xname(booted_device), device_xname(dev)); |
332 | return; |
333 | } |
334 | booted_device = dev; |
335 | } |
336 | |
337 | static int |
338 | is_valid_disk(device_t dv) |
339 | { |
340 | |
341 | if (device_class(dv) != DV_DISK) |
342 | return (0); |
343 | |
344 | return (device_is_a(dv, "dk" ) || |
345 | device_is_a(dv, "sd" ) || |
346 | device_is_a(dv, "wd" ) || |
347 | device_is_a(dv, "ld" ) || |
348 | device_is_a(dv, "ed" ) || |
349 | device_is_a(dv, "xbd" )); |
350 | } |
351 | |