Print this page
6198 Let's EOL cachefs
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/swapgeneric.c
+++ new/usr/src/uts/common/os/swapgeneric.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1982, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 24 */
24 25
25 26 /*
26 27 * Configure root, swap and dump devices.
27 28 */
28 29
29 30 #include <sys/types.h>
30 31 #include <sys/param.h>
31 32 #include <sys/sysmacros.h>
32 33 #include <sys/signal.h>
33 34 #include <sys/cred.h>
34 35 #include <sys/proc.h>
35 36 #include <sys/user.h>
36 37 #include <sys/conf.h>
37 38 #include <sys/buf.h>
38 39 #include <sys/systm.h>
39 40 #include <sys/vm.h>
40 41 #include <sys/reboot.h>
41 42 #include <sys/file.h>
42 43 #include <sys/vfs.h>
43 44 #include <sys/vnode.h>
44 45 #include <sys/errno.h>
45 46 #include <sys/kmem.h>
46 47 #include <sys/uio.h>
47 48 #include <sys/open.h>
48 49 #include <sys/mount.h>
49 50 #include <sys/kobj.h>
50 51 #include <sys/bootconf.h>
51 52 #include <sys/sysconf.h>
52 53 #include <sys/modctl.h>
53 54 #include <sys/autoconf.h>
54 55 #include <sys/debug.h>
55 56 #include <sys/fs/snode.h>
56 57 #include <fs/fs_subr.h>
57 58 #include <sys/socket.h>
58 59 #include <net/if.h>
59 60
60 61 #include <sys/mkdev.h>
61 62 #include <sys/cmn_err.h>
62 63 #include <sys/console.h>
63 64
64 65 #include <sys/conf.h>
65 66 #include <sys/ddi.h>
66 67 #include <sys/sunddi.h>
67 68 #include <sys/hwconf.h>
68 69 #include <sys/dc_ki.h>
69 70 #include <sys/promif.h>
70 71 #include <sys/bootprops.h>
71 72
72 73 /*
73 74 * Local routines
74 75 */
75 76 static int preload_module(struct sysparam *, void *);
76 77 static struct vfssw *getfstype(char *, char *, size_t);
77 78 static int getphysdev(char *, char *, size_t);
78 79 static int load_bootpath_drivers(char *bootpath);
79 80 static int load_boot_driver(char *drv);
80 81 static int load_boot_platform_modules(char *drv);
81 82 static dev_info_t *path_to_devinfo(char *path);
82 83 static boolean_t netboot_over_ib(char *bootpath);
83 84 static boolean_t netboot_over_iscsi(void);
84 85
85 86 /*
86 87 * Module linkage information for the kernel.
87 88 */
88 89 static struct modlmisc modlmisc = {
89 90 &mod_miscops, "root and swap configuration"
90 91 };
91 92
92 93 static struct modlinkage modlinkage = {
93 94 MODREV_1, (void *)&modlmisc, NULL
94 95 };
95 96
96 97 int
97 98 _init(void)
98 99 {
99 100 return (mod_install(&modlinkage));
100 101 }
101 102
102 103 int
103 104 _fini(void)
104 105 {
105 106 return (mod_remove(&modlinkage));
106 107 }
107 108
108 109 int
109 110 _info(struct modinfo *modinfop)
110 111 {
111 112 return (mod_info(&modlinkage, modinfop));
112 113 }
113 114
114 115 extern ib_boot_prop_t *iscsiboot_prop;
115 116 /*
116 117 * Configure root file system.
117 118 */
118 119 int
119 120 rootconf(void)
120 121 {
121 122 int error;
122 123 struct vfssw *vsw;
123 124 extern void pm_init(void);
124 125 int ret = -1;
125 126 BMDPRINTF(("rootconf: fstype %s\n", rootfs.bo_fstype));
126 127 BMDPRINTF(("rootconf: name %s\n", rootfs.bo_name));
127 128 BMDPRINTF(("rootconf: flags 0x%x\n", rootfs.bo_flags));
128 129 BMDPRINTF(("rootconf: obp_bootpath %s\n", obp_bootpath));
129 130
130 131 /*
131 132 * Install cluster modules that were only loaded during
132 133 * loadrootmodules().
133 134 */
134 135 if (error = clboot_rootconf())
135 136 return (error);
136 137
137 138 if (root_is_svm) {
138 139 (void) strncpy(rootfs.bo_name, obp_bootpath, BO_MAXOBJNAME);
139 140
140 141 BMDPRINTF(("rootconf: svm: rootfs name %s\n", rootfs.bo_name));
141 142 BMDPRINTF(("rootconf: svm: svm name %s\n", svm_bootpath));
142 143 }
143 144
144 145 /*
145 146 * Run _init on the root filesystem (we already loaded it
146 147 * but we've been waiting until now to _init it) which will
147 148 * have the side-effect of running vsw_init() on this vfs.
148 149 * Because all the nfs filesystems are lumped into one
149 150 * module we need to special case it.
150 151 */
151 152 if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
152 153 if (modload("fs", "nfs") == -1) {
153 154 cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
154 155 rootfs.bo_fstype);
155 156 return (ENXIO);
156 157 }
157 158 } else {
158 159 if (modload("fs", rootfs.bo_fstype) == -1) {
159 160 cmn_err(CE_CONT, "Cannot initialize %s filesystem\n",
160 161 rootfs.bo_fstype);
161 162 return (ENXIO);
162 163 }
163 164 }
164 165 RLOCK_VFSSW();
165 166 vsw = vfs_getvfsswbyname(rootfs.bo_fstype);
166 167 RUNLOCK_VFSSW();
167 168 if (vsw == NULL) {
168 169 cmn_err(CE_CONT, "Cannot find %s filesystem\n",
169 170 rootfs.bo_fstype);
170 171 return (ENXIO);
171 172 }
172 173 VFS_INIT(rootvfs, &vsw->vsw_vfsops, (caddr_t)0);
173 174 VFS_HOLD(rootvfs);
174 175
175 176 if (root_is_svm) {
176 177 rootvfs->vfs_flag |= VFS_RDONLY;
177 178 }
178 179
179 180 /*
180 181 * This pm-releated call has to occur before root is mounted since we
181 182 * need to power up all devices. It is placed after VFS_INIT() such
182 183 * that opening a device via ddi_lyr_ interface just before root has
183 184 * been mounted would work.
184 185 */
185 186 pm_init();
186 187
187 188 if (netboot && iscsiboot_prop) {
188 189 cmn_err(CE_WARN, "NFS boot and iSCSI boot"
189 190 " shouldn't happen in the same time");
190 191 return (EINVAL);
191 192 }
192 193
193 194 if (netboot || iscsiboot_prop) {
194 195 ret = strplumb();
195 196 if (ret != 0) {
196 197 cmn_err(CE_WARN, "Cannot plumb network device %d", ret);
197 198 return (EFAULT);
198 199 }
199 200 }
200 201
201 202 if ((ret == 0) && iscsiboot_prop) {
202 203 ret = modload("drv", "iscsi");
203 204 /* -1 indicates fail */
204 205 if (ret == -1) {
205 206 cmn_err(CE_WARN, "Failed to load iscsi module");
206 207 iscsi_boot_prop_free();
207 208 return (EINVAL);
208 209 } else {
209 210 if (!i_ddi_attach_pseudo_node("iscsi")) {
210 211 cmn_err(CE_WARN,
211 212 "Failed to attach iscsi driver");
212 213 iscsi_boot_prop_free();
213 214 return (ENODEV);
214 215 }
215 216 }
216 217 }
217 218
218 219 /*
219 220 * ufs_mountroot() ends up calling getrootdev()
220 221 * (below) which actually triggers the _init, identify,
221 222 * probe and attach of the drivers that make up root device
222 223 * bush; these are also quietly waiting in memory.
223 224 */
224 225 BMDPRINTF(("rootconf: calling VFS_MOUNTROOT %s\n", rootfs.bo_fstype));
225 226
226 227 error = VFS_MOUNTROOT(rootvfs, ROOT_INIT);
227 228 vfs_unrefvfssw(vsw);
228 229 rootdev = rootvfs->vfs_dev;
229 230
230 231 if (error)
231 232 cmn_err(CE_CONT, "Cannot mount root on %s fstype %s\n",
232 233 rootfs.bo_name, rootfs.bo_fstype);
233 234 else
234 235 cmn_err(CE_CONT, "?root on %s fstype %s\n",
235 236 rootfs.bo_name, rootfs.bo_fstype);
236 237 return (error);
237 238 }
238 239
239 240 /*
240 241 * Remount root on an SVM mirror root device
241 242 * Only supported on UFS filesystems at present
242 243 */
243 244 int
244 245 svm_rootconf(void)
245 246 {
246 247 int error;
247 248 extern int ufs_remountroot(struct vfs *vfsp);
248 249
249 250 ASSERT(root_is_svm == 1);
250 251
251 252 if (strcmp(rootfs.bo_fstype, "ufs") != 0) {
252 253 cmn_err(CE_CONT, "Mounting root on %s with filesystem "
253 254 "type %s is not supported\n",
254 255 rootfs.bo_name, rootfs.bo_fstype);
255 256 return (EINVAL);
256 257 }
257 258
258 259 (void) strncpy(rootfs.bo_name, svm_bootpath, BO_MAXOBJNAME);
259 260
260 261 BMDPRINTF(("svm_rootconf: rootfs %s\n", rootfs.bo_name));
261 262
262 263 error = ufs_remountroot(rootvfs);
263 264
264 265 if (error) {
265 266 cmn_err(CE_CONT, "Cannot remount root on %s fstype %s\n",
266 267 rootfs.bo_name, rootfs.bo_fstype);
267 268 } else {
268 269 cmn_err(CE_CONT, "?root remounted on %s fstype %s\n",
269 270 rootfs.bo_name, rootfs.bo_fstype);
270 271 }
271 272 return (error);
272 273 }
273 274
274 275 /*
275 276 * Under the assumption that our root file system is on a
276 277 * disk partition, get the dev_t of the partition in question.
277 278 *
278 279 * By now, boot has faithfully loaded all our modules into memory, and
279 280 * we've taken over resource management. Before we go any further, we
280 281 * have to fire up the device drivers and stuff we need to mount the
281 282 * root filesystem. That's what we do here. Fingers crossed.
282 283 */
283 284 dev_t
284 285 getrootdev(void)
285 286 {
286 287 dev_t d;
287 288
288 289 d = ddi_pathname_to_dev_t(rootfs.bo_name);
289 290 if ((d == NODEV) && (iscsiboot_prop != NULL)) {
290 291 /* Give it another try with the 'disk' path */
291 292 get_iscsi_bootpath_phy(rootfs.bo_name);
292 293 d = ddi_pathname_to_dev_t(rootfs.bo_name);
293 294 }
294 295 if (d == NODEV)
295 296 cmn_err(CE_CONT, "Cannot assemble drivers for root %s\n",
296 297 rootfs.bo_name);
297 298 return (d);
298 299 }
299 300
300 301 /*
301 302 * If booted with ASKNAME, prompt on the console for a filesystem
302 303 * name and return it.
303 304 */
304 305 void
305 306 getfsname(char *askfor, char *name, size_t namelen)
306 307 {
307 308 if (boothowto & RB_ASKNAME) {
308 309 printf("%s name: ", askfor);
309 310 console_gets(name, namelen);
310 311 }
311 312 }
312 313
313 314 /*ARGSUSED1*/
314 315 static int
315 316 preload_module(struct sysparam *sysp, void *p)
316 317 {
317 318 static char *wmesg = "forceload of %s failed";
318 319 char *name;
319 320
320 321 name = sysp->sys_ptr;
321 322 BMDPRINTF(("preload_module: %s\n", name));
322 323 if (modloadonly(NULL, name) < 0)
323 324 cmn_err(CE_WARN, wmesg, name);
324 325 return (0);
325 326 }
326 327
327 328 /*
328 329 * We want to load all the modules needed to mount the root filesystem,
329 330 * so that when we start the ball rolling in 'getrootdev', every module
330 331 * should already be in memory, just waiting to be init-ed.
331 332 */
332 333
333 334 int
334 335 loadrootmodules(void)
335 336 {
336 337 struct vfssw *vsw;
337 338 char *this;
338 339 char *name;
339 340 int err;
340 341 int i, proplen;
341 342 extern char *impl_module_list[];
342 343 extern char *platform_module_list[];
343 344
344 345 /* Make sure that the PROM's devinfo tree has been created */
345 346 ASSERT(ddi_root_node());
346 347
347 348 BMDPRINTF(("loadrootmodules: fstype %s\n", rootfs.bo_fstype));
348 349 BMDPRINTF(("loadrootmodules: name %s\n", rootfs.bo_name));
349 350 BMDPRINTF(("loadrootmodules: flags 0x%x\n", rootfs.bo_flags));
350 351
351 352 /*
352 353 * zzz We need to honor what's in rootfs if it's not null.
353 354 * non-null means use what's there. This way we can
354 355 * change rootfs with /etc/system AND with tunetool.
355 356 */
356 357 if (root_is_svm) {
357 358 /* user replaced rootdev, record obp_bootpath */
358 359 obp_bootpath[0] = '\0';
359 360 (void) getphysdev("root", obp_bootpath, BO_MAXOBJNAME);
360 361 BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
361 362 } else {
362 363 /*
363 364 * Get the root fstype and root device path from boot.
364 365 */
365 366 rootfs.bo_fstype[0] = '\0';
366 367 rootfs.bo_name[0] = '\0';
367 368 }
368 369
369 370 /*
370 371 * This lookup will result in modloadonly-ing the root
371 372 * filesystem module - it gets _init-ed in rootconf()
372 373 */
373 374 if ((vsw = getfstype("root", rootfs.bo_fstype, BO_MAXFSNAME)) == NULL)
374 375 return (ENXIO); /* in case we have no file system types */
375 376
376 377 (void) strcpy(rootfs.bo_fstype, vsw->vsw_name);
377 378
378 379 vfs_unrefvfssw(vsw);
379 380
380 381 /*
381 382 * Load the favored drivers of the implementation.
382 383 * e.g. 'sbus' and possibly 'zs' (even).
383 384 *
384 385 * Called whilst boot is still loaded (because boot does
385 386 * the i/o for us), and DDI services are unavailable.
386 387 */
387 388 BMDPRINTF(("loadrootmodules: impl_module_list\n"));
388 389 for (i = 0; (this = impl_module_list[i]) != NULL; i++) {
389 390 if ((err = load_boot_driver(this)) != 0) {
390 391 cmn_err(CE_WARN, "Cannot load drv/%s", this);
391 392 return (err);
392 393 }
393 394 }
394 395 /*
395 396 * Now load the platform modules (if any)
396 397 */
397 398 BMDPRINTF(("loadrootmodules: platform_module_list\n"));
398 399 for (i = 0; (this = platform_module_list[i]) != NULL; i++) {
399 400 if ((err = load_boot_platform_modules(this)) != 0) {
400 401 cmn_err(CE_WARN, "Cannot load drv/%s", this);
401 402 return (err);
402 403 }
403 404 }
404 405
405 406 loop:
406 407 (void) getphysdev("root", rootfs.bo_name, BO_MAXOBJNAME);
407 408 /*
408 409 * Given a physical pathname, load the correct set of driver
409 410 * modules into memory, including all possible parents.
410 411 *
411 412 * NB: The code sets the variable 'name' for error reporting.
412 413 */
413 414 err = 0;
414 415 BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
415 416 if (root_is_svm == 0) {
416 417 BMDPRINTF(("loadrootmodules: rootfs %s\n", rootfs.bo_name));
417 418 name = rootfs.bo_name;
418 419 err = load_bootpath_drivers(rootfs.bo_name);
419 420 }
420 421
421 422 /*
422 423 * Load driver modules in obp_bootpath, this is always
423 424 * required for mountroot to succeed. obp_bootpath is
424 425 * is set if rootdev is set via /etc/system, which is
425 426 * the case if booting of a SVM/VxVM mirror.
426 427 */
427 428 if ((err == 0) && obp_bootpath[0] != '\0') {
428 429 BMDPRINTF(("loadrootmodules: obp_bootpath %s\n", obp_bootpath));
429 430 name = obp_bootpath;
430 431 err = load_bootpath_drivers(obp_bootpath);
431 432 }
432 433
433 434 if (err != 0) {
434 435 cmn_err(CE_CONT, "Cannot load drivers for %s\n", name);
435 436 goto out;
436 437 }
437 438
438 439 /*
439 440 * Check to see if the booter performed DHCP configuration
440 441 * ("bootp-response" boot property exists). If so, then before
441 442 * bootops disappears we need to save the value of this property
442 443 * such that the userland dhcpagent can adopt the DHCP management
443 444 * of our primary network interface.
444 445 */
445 446 proplen = BOP_GETPROPLEN(bootops, "bootp-response");
446 447 if (proplen > 0) {
447 448 dhcack = kmem_zalloc(proplen, KM_SLEEP);
448 449 if (BOP_GETPROP(bootops, "bootp-response", dhcack) == -1) {
449 450 cmn_err(CE_WARN, "BOP_GETPROP of "
450 451 "\"bootp-response\" failed\n");
451 452 kmem_free(dhcack, dhcacklen);
452 453 dhcack = NULL;
453 454 goto out;
454 455 }
455 456 dhcacklen = proplen;
456 457
457 458 /*
458 459 * Fetch the "netdev-path" boot property (if it exists), and
459 460 * stash it for later use by sysinfo(SI_DHCP_CACHE, ...).
460 461 */
461 462 proplen = BOP_GETPROPLEN(bootops, "netdev-path");
462 463 if (proplen > 0) {
463 464 netdev_path = kmem_zalloc(proplen, KM_SLEEP);
464 465 if (BOP_GETPROP(bootops, "netdev-path",
465 466 (uchar_t *)netdev_path) == -1) {
466 467 cmn_err(CE_WARN, "BOP_GETPROP of "
467 468 "\"netdev-path\" failed\n");
468 469 kmem_free(netdev_path, proplen);
469 470 goto out;
470 471 }
471 472 }
472 473 }
473 474
474 475 /*
475 476 * Preload (load-only, no init) all modules which
476 477 * were added to the /etc/system file with the
477 478 * FORCELOAD keyword.
478 479 */
479 480 BMDPRINTF(("loadrootmodules: preload_module\n"));
480 481 (void) mod_sysctl_type(MOD_FORCELOAD, preload_module, NULL);
481 482
482 483 /*
483 484 * If we booted otw then load in the plumbing
484 485 * routine now while we still can. If we didn't
485 486 * boot otw then we will load strplumb in main().
486 487 *
487 488 * NFS is actually a set of modules, the core routines,
488 489 * a diskless helper module, rpcmod, and the tli interface. Load
489 490 * them now while we still can.
490 491 *
491 492 * Because we glomb all versions of nfs into a single module
492 493 * we check based on the initial string "nfs".
493 494 *
494 495 * XXX: A better test for this is to see if device_type
495 496 * XXX: from the PROM is "network".
496 497 */
497 498
498 499 if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0) {
499 500 ++netboot;
500 501
501 502 /*
502 503 * Preload (load-only, no init) the dacf module. We cannot
503 504 * init the module because one of its requisite modules is
504 505 * dld whose _init function will call taskq_create(), which
505 506 * will panic the system at this point.
506 507 */
507 508 if ((err = modloadonly("dacf", "net_dacf")) < 0) {
508 509 cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
509 510 goto out;
510 511 }
511 512 if ((err = modload("misc", "tlimod")) < 0) {
512 513 cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
513 514 goto out;
514 515 }
515 516 if ((err = modload("strmod", "rpcmod")) < 0) {
516 517 cmn_err(CE_CONT, "Cannot load strmod/rpcmod\n");
517 518 goto out;
518 519 }
519 520 if ((err = modload("misc", "nfs_dlboot")) < 0) {
520 521 cmn_err(CE_CONT, "Cannot load misc/nfs_dlboot\n");
521 522 goto out;
522 523 }
523 524 if ((err = modload("mac", "mac_ether")) < 0) {
524 525 cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
525 526 goto out;
526 527 }
527 528 if ((err = modload("misc", "strplumb")) < 0) {
528 529 cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
529 530 goto out;
530 531 }
531 532 if ((err = strplumb_load()) < 0) {
532 533 goto out;
533 534 }
534 535 }
535 536 if (netboot_over_iscsi() == B_TRUE) {
536 537 /* iscsi boot */
537 538 if ((err = modloadonly("dacf", "net_dacf")) < 0) {
538 539 cmn_err(CE_CONT, "Cannot load dacf/net_dacf\n");
539 540 goto out;
540 541 }
541 542 if ((err = modload("misc", "tlimod")) < 0) {
542 543 cmn_err(CE_CONT, "Cannot load misc/tlimod\n");
543 544 goto out;
544 545 }
545 546 if ((err = modload("mac", "mac_ether")) < 0) {
546 547 cmn_err(CE_CONT, "Cannot load mac/mac_ether\n");
547 548 goto out;
548 549 }
549 550 if ((err = modloadonly("drv", "iscsi")) < 0) {
550 551 cmn_err(CE_CONT, "Cannot load drv/iscsi\n");
551 552 goto out;
552 553 }
553 554 if ((err = modloadonly("drv", "ssd")) < 0) {
554 555 cmn_err(CE_CONT, "Cannot load drv/ssd\n");
555 556 goto out;
556 557 }
557 558 if ((err = modloadonly("drv", "sd")) < 0) {
558 559 cmn_err(CE_CONT, "Cannot load drv/sd\n");
559 560 goto out;
560 561 }
561 562 if ((err = modload("misc", "strplumb")) < 0) {
562 563 cmn_err(CE_CONT, "Cannot load misc/strplumb\n");
563 564 goto out;
564 565 }
565 566 if ((err = strplumb_load()) < 0) {
566 567 goto out;
567 568 }
568 569 }
569 570 /*
570 571 * Preload modules needed for booting as a cluster.
571 572 */
572 573 err = clboot_loadrootmodules();
573 574
574 575 out:
575 576 if (err != 0 && (boothowto & RB_ASKNAME))
576 577 goto loop;
577 578
578 579 return (err);
579 580 }
580 581
581 582 static int
582 583 get_bootpath_prop(char *bootpath)
583 584 {
584 585 if (root_is_ramdisk) {
585 586 if (BOP_GETPROP(bootops, "bootarchive", bootpath) == -1)
586 587 return (-1);
587 588 (void) strlcat(bootpath, ":a", BO_MAXOBJNAME);
588 589 } else {
589 590 /*
590 591 * Look for the 1275 compliant name 'bootpath' first,
591 592 * but make certain it has a non-NULL value as well.
592 593 */
593 594 if ((BOP_GETPROP(bootops, "bootpath", bootpath) == -1) ||
594 595 strlen(bootpath) == 0) {
595 596 if (BOP_GETPROP(bootops,
596 597 "boot-path", bootpath) == -1)
597 598 return (-1);
598 599 }
599 600 if (memcmp(bootpath, BP_ISCSI_DISK,
600 601 strlen(BP_ISCSI_DISK)) == 0) {
601 602 /* iscsi boot */
602 603 get_iscsi_bootpath_vhci(bootpath);
603 604 }
604 605 }
605 606 return (0);
606 607 }
607 608
608 609 static int
609 610 get_fstype_prop(char *fstype)
610 611 {
611 612 char *prop = (root_is_ramdisk) ? "archive-fstype" : "fstype";
612 613
613 614 return (BOP_GETPROP(bootops, prop, fstype));
614 615 }
615 616
616 617 /*
617 618 * Get the name of the root or swap filesystem type, and return
618 619 * the corresponding entry in the vfs switch.
619 620 *
620 621 * If we're not asking the user, and we're trying to find the
621 622 * root filesystem type, we ask boot for the filesystem
622 623 * type that it came from and use that. Similarly, if we're
623 624 * trying to find the swap filesystem, we try and derive it from
624 625 * the root filesystem type.
↓ open down ↓ |
592 lines elided |
↑ open up ↑ |
625 626 *
626 627 * If we are booting via NFS we currently have these options:
627 628 * nfs - dynamically choose NFS V2. V3, or V4 (default)
628 629 * nfs2 - force NFS V2
629 630 * nfs3 - force NFS V3
630 631 * nfs4 - force NFS V4
631 632 * Because we need to maintain backward compatibility with the naming
632 633 * convention that the NFS V2 filesystem name is "nfs" (see vfs_conf.c)
633 634 * we need to map "nfs" => "nfsdyn" and "nfs2" => "nfs". The dynamic
634 635 * nfs module will map the type back to either "nfs", "nfs3", or "nfs4".
635 - * This is only for root filesystems, all other uses such as cachefs
636 - * will expect that "nfs" == NFS V2.
636 + * This is only for root filesystems, all other uses will expect
637 + * that "nfs" == NFS V2.
637 638 *
638 639 * If the filesystem isn't already loaded, vfs_getvfssw() will load
639 640 * it for us, but if (at the time we call it) modrootloaded is
640 641 * still not set, it won't run the filesystems _init routine (and
641 642 * implicitly it won't run the filesystems vsw_init() entry either).
642 643 * We do that explicitly in rootconf().
643 644 */
644 645 static struct vfssw *
645 646 getfstype(char *askfor, char *fsname, size_t fsnamelen)
646 647 {
647 648 struct vfssw *vsw;
648 649 static char defaultfs[BO_MAXFSNAME];
649 650 int root = 0;
650 651
651 652 if (strcmp(askfor, "root") == 0) {
652 653 (void) get_fstype_prop(defaultfs);
653 654 root++;
654 655 } else {
655 656 (void) strcpy(defaultfs, "swapfs");
656 657 }
657 658
658 659 if (boothowto & RB_ASKNAME) {
659 660 for (*fsname = '\0'; *fsname == '\0'; *fsname = '\0') {
660 661 printf("%s filesystem type [%s]: ", askfor, defaultfs);
661 662 console_gets(fsname, fsnamelen);
662 663 if (*fsname == '\0')
663 664 (void) strcpy(fsname, defaultfs);
664 665 if (root) {
665 666 if (strcmp(fsname, "nfs2") == 0)
666 667 (void) strcpy(fsname, "nfs");
667 668 else if (strcmp(fsname, "nfs") == 0)
668 669 (void) strcpy(fsname, "nfsdyn");
669 670 }
670 671 if ((vsw = vfs_getvfssw(fsname)) != NULL)
671 672 return (vsw);
672 673 printf("Unknown filesystem type '%s'\n", fsname);
673 674 }
674 675 } else if (*fsname == '\0') {
675 676 fsname = defaultfs;
676 677 }
677 678 if (*fsname == '\0') {
678 679 return (NULL);
679 680 }
680 681
681 682 if (root) {
682 683 if (strcmp(fsname, "nfs2") == 0)
683 684 (void) strcpy(fsname, "nfs");
684 685 else if (strcmp(fsname, "nfs") == 0)
685 686 (void) strcpy(fsname, "nfsdyn");
686 687 }
687 688
688 689 return (vfs_getvfssw(fsname));
689 690 }
690 691
691 692
692 693 /*
693 694 * Get a physical device name, and maybe load and attach
694 695 * the driver.
695 696 *
696 697 * XXX Need better checking of whether or not a device
697 698 * actually exists if the user typed in a pathname.
698 699 *
699 700 * XXX Are we sure we want to expose users to this sort
700 701 * of physical namespace gobbledygook (now there's
701 702 * a word to conjure with..)
702 703 *
703 704 * XXX Note that on an OBP machine, we can easily ask the
704 705 * prom and pretty-print some plausible set of bootable
705 706 * devices. We can also user the prom to verify any
706 707 * such device. Later tim.. later.
707 708 */
708 709 static int
709 710 getphysdev(char *askfor, char *name, size_t namelen)
710 711 {
711 712 static char fmt[] = "Enter physical name of %s device\n[%s]: ";
712 713 dev_t dev;
713 714 static char defaultpath[BO_MAXOBJNAME];
714 715
715 716 /*
716 717 * Establish 'default' values - we get the root device from
717 718 * boot, and we infer the swap device is the same but with
718 719 * a 'b' on the end instead of an 'a'. A first stab at
719 720 * ease-of-use ..
720 721 */
721 722 if (strcmp(askfor, "root") == 0) {
722 723 if (get_bootpath_prop(defaultpath) == -1)
723 724 boothowto |= RB_ASKNAME | RB_VERBOSE;
724 725 } else {
725 726 (void) strcpy(defaultpath, rootfs.bo_name);
726 727 defaultpath[strlen(defaultpath) - 1] = 'b';
727 728 }
728 729
729 730 retry:
730 731 if (boothowto & RB_ASKNAME) {
731 732 printf(fmt, askfor, defaultpath);
732 733 console_gets(name, namelen);
733 734 }
734 735 if (*name == '\0')
735 736 (void) strcpy(name, defaultpath);
736 737
737 738 if (strcmp(askfor, "swap") == 0) {
738 739
739 740 /*
740 741 * Try to load and install the swap device driver.
741 742 */
742 743 dev = ddi_pathname_to_dev_t(name);
743 744
744 745 if (dev == (dev_t)-1) {
745 746 printf("Not a supported device for swap.\n");
746 747 boothowto |= RB_ASKNAME | RB_VERBOSE;
747 748 goto retry;
748 749 }
749 750
750 751 /*
751 752 * Ensure that we're not trying to swap on the floppy.
752 753 */
753 754 if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
754 755 printf("Too dangerous to swap on the floppy\n");
755 756 if (boothowto & RB_ASKNAME)
756 757 goto retry;
757 758 return (-1);
758 759 }
759 760 }
760 761
761 762 return (0);
762 763 }
763 764
764 765
765 766 /*
766 767 * Load a driver needed to boot.
767 768 */
768 769 static int
769 770 load_boot_driver(char *drv)
770 771 {
771 772 char *drvname;
772 773 major_t major;
773 774 #ifdef sparc
774 775 struct devnames *dnp;
775 776 ddi_prop_t *propp;
776 777 char *module;
777 778 char *dir, *mf;
778 779 int plen;
779 780 int mlen;
780 781 #endif /* sparc */
781 782
782 783 if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
783 784 cmn_err(CE_CONT, "%s: no major number\n", drv);
784 785 return (-1);
785 786 }
786 787 /*
787 788 * resolve aliases
788 789 */
789 790 drvname = ddi_major_to_name(major);
790 791
791 792 #ifdef DEBUG
792 793 if (strcmp(drv, drvname) == 0) {
793 794 BMDPRINTF(("load_boot_driver: %s\n", drv));
794 795 } else {
795 796 BMDPRINTF(("load_boot_driver: %s -> %s\n", drv, drvname));
796 797 }
797 798 #endif /* DEBUG */
798 799
799 800 if (modloadonly("drv", drvname) == -1) {
800 801 cmn_err(CE_CONT, "%s: cannot load driver\n", drvname);
801 802 return (-1);
802 803 }
803 804
804 805 #ifdef sparc
805 806 /*
806 807 * NOTE: this can be removed when newboot-sparc is delivered.
807 808 *
808 809 * Check to see if the driver had a 'ddi-forceload' global driver.conf
809 810 * property to identify additional modules that need to be loaded.
810 811 * The driver still needs to use ddi_modopen() to open these modules,
811 812 * but the 'ddi-forceload' property allows the modules to be loaded
812 813 * into memory prior to lights-out, so that driver ddi_modopen()
813 814 * calls during lights-out (when mounting root) will work correctly.
814 815 * Use of 'ddi-forceload' is only required for drivers involved in
815 816 * getting root mounted.
816 817 */
817 818 dnp = &devnamesp[major];
818 819 if (dnp->dn_global_prop_ptr && dnp->dn_global_prop_ptr->prop_list &&
819 820 ((propp = i_ddi_prop_search(DDI_DEV_T_ANY,
820 821 "ddi-forceload", DDI_PROP_TYPE_STRING,
821 822 &dnp->dn_global_prop_ptr->prop_list)) != NULL)) {
822 823
823 824 module = (char *)propp->prop_val;
824 825 plen = propp->prop_len;
825 826 while (plen > 0) {
826 827 mlen = strlen(module);
827 828 mf = strrchr(module, '/');
828 829 if (mf) {
829 830 dir = module;
830 831 *mf++ = '\0'; /* '/' -> '\0' */
831 832 } else {
832 833 dir = "misc";
833 834 mf = module;
834 835 }
835 836 if (modloadonly(dir, mf) == -1)
836 837 cmn_err(CE_CONT,
837 838 "misc/%s: can't load module\n", mf);
838 839 if (mf != module)
839 840 *(mf - 1) = '/'; /* '\0' -> '/' */
840 841
841 842 module += mlen + 1;
842 843 plen -= mlen + 1;
843 844 }
844 845 }
845 846 #endif /* sparc */
846 847
847 848 return (0);
848 849 }
849 850
850 851
851 852 /*
852 853 * For a given instance, load that driver and its parents
853 854 */
854 855 static int
855 856 load_parent_drivers(dev_info_t *dip, char *path)
856 857 {
857 858 int rval = 0;
858 859 major_t major = DDI_MAJOR_T_NONE;
859 860 char *drv;
860 861 char *p;
861 862
862 863 while (dip) {
863 864 /* check for path-oriented alias */
864 865 if (path)
865 866 major = ddi_name_to_major(path);
866 867 else
867 868 major = DDI_MAJOR_T_NONE;
868 869
869 870 if (major != DDI_MAJOR_T_NONE)
870 871 drv = ddi_major_to_name(major);
871 872 else
872 873 drv = ddi_binding_name(dip);
873 874
874 875 if (load_boot_driver(drv) != 0)
875 876 rval = -1;
876 877
877 878 dip = ddi_get_parent(dip);
878 879 if (path) {
879 880 p = strrchr(path, '/');
880 881 if (p)
881 882 *p = 0;
882 883 }
883 884 }
884 885
885 886 return (rval);
886 887 }
887 888
888 889
889 890 /*
890 891 * For a given path to a boot device,
891 892 * load that driver and all its parents.
892 893 */
893 894 static int
894 895 load_bootpath_drivers(char *bootpath)
895 896 {
896 897 dev_info_t *dip;
897 898 char *pathcopy;
898 899 int pathcopy_len;
899 900 int rval;
900 901 char *p;
901 902 int proplen;
902 903 char iscsi_network_path[BO_MAXOBJNAME];
903 904
904 905 if (bootpath == NULL || *bootpath == 0)
905 906 return (-1);
906 907
907 908 BMDPRINTF(("load_bootpath_drivers: %s\n", bootpath));
908 909 #ifdef _OBP
909 910 if (netboot_over_iscsi()) {
910 911 /* iscsi boot */
911 912 if (root_is_ramdisk) {
912 913 if (modloadonly("drv", "ramdisk") < 0)
913 914 return (-1);
914 915 }
915 916 proplen = BOP_GETPROPLEN(bootops, BP_ISCSI_NETWORK_BOOTPATH);
916 917 if (proplen > 0) {
917 918 if (BOP_GETPROP(bootops, BP_ISCSI_NETWORK_BOOTPATH,
918 919 iscsi_network_path) > 0) {
919 920 p = strchr(iscsi_network_path, ':');
920 921 if (p != NULL) {
921 922 *p = '\0';
922 923 }
923 924 pathcopy = i_ddi_strdup(iscsi_network_path,
924 925 KM_SLEEP);
925 926 pathcopy_len = strlen(pathcopy) + 1;
926 927 } else {
927 928 return (-1);
928 929 }
929 930 } else {
930 931 return (-1);
931 932 }
932 933 } else {
933 934 #endif
934 935 pathcopy = i_ddi_strdup(bootpath, KM_SLEEP);
935 936 pathcopy_len = strlen(pathcopy) + 1;
936 937 #ifdef _OBP
937 938 }
938 939 #endif
939 940 dip = path_to_devinfo(pathcopy);
940 941
941 942 #if defined(__i386) || defined(__amd64)
942 943 /*
943 944 * i386 does not provide stub nodes for all boot devices,
944 945 * but we should be able to find the node for the parent,
945 946 * and the leaf of the boot path should be the driver name,
946 947 * which we go ahead and load here.
947 948 */
948 949 if (dip == NULL) {
949 950 char *leaf;
950 951
951 952 /*
952 953 * Find last slash to build the full path to the
953 954 * parent of the leaf boot device
954 955 */
955 956 p = strrchr(pathcopy, '/');
956 957 *p++ = 0;
957 958
958 959 /*
959 960 * Now isolate the driver name of the leaf device
960 961 */
961 962 leaf = p;
962 963 p = strchr(leaf, '@');
963 964 *p = 0;
964 965
965 966 BMDPRINTF(("load_bootpath_drivers: parent=%s leaf=%s\n",
966 967 bootpath, leaf));
967 968
968 969 dip = path_to_devinfo(pathcopy);
969 970 if (leaf) {
970 971 rval = load_boot_driver(leaf, NULL);
971 972 if (rval == -1) {
972 973 kmem_free(pathcopy, pathcopy_len);
973 974 return (NULL);
974 975 }
975 976 }
976 977 }
977 978 #endif
978 979
979 980 if (dip == NULL) {
980 981 cmn_err(CE_WARN, "can't bind driver for boot path <%s>",
981 982 bootpath);
982 983 kmem_free(pathcopy, pathcopy_len);
983 984 return (NULL);
984 985 }
985 986
986 987 /*
987 988 * Load IP over IB driver when netbooting over IB.
988 989 * As per IB 1275 binding, IP over IB is represented as
989 990 * service on the top of the HCA node. So, there is no
990 991 * PROM node and generic framework cannot pre-load
991 992 * IP over IB driver based on the bootpath. The following
992 993 * code preloads IP over IB driver when doing netboot over
993 994 * InfiniBand.
994 995 */
995 996 if (netboot_over_ib(bootpath) &&
996 997 modloadonly("drv", "ibp") == -1) {
997 998 cmn_err(CE_CONT, "ibp: cannot load platform driver\n");
998 999 kmem_free(pathcopy, pathcopy_len);
999 1000 return (NULL);
1000 1001 }
1001 1002
1002 1003 /*
1003 1004 * The PROM node for hubs have incomplete compatible
1004 1005 * properties and therefore do not bind to the hubd driver.
1005 1006 * As a result load_bootpath_drivers() loads the usb_mid driver
1006 1007 * for hub nodes rather than the hubd driver. This causes
1007 1008 * mountroot failures when booting off USB storage. To prevent
1008 1009 * this, if we are booting via USB hubs, we preload the hubd driver.
1009 1010 */
1010 1011 if (strstr(bootpath, "/hub@") && modloadonly("drv", "hubd") == -1) {
1011 1012 cmn_err(CE_WARN, "bootpath contains a USB hub, "
1012 1013 "but cannot load hubd driver");
1013 1014 }
1014 1015
1015 1016 /* get rid of minor node at end of copy (if not already done above) */
1016 1017 p = strrchr(pathcopy, '/');
1017 1018 if (p) {
1018 1019 p = strchr(p, ':');
1019 1020 if (p)
1020 1021 *p = 0;
1021 1022 }
1022 1023
1023 1024 rval = load_parent_drivers(dip, pathcopy);
1024 1025 kmem_free(pathcopy, pathcopy_len);
1025 1026 return (rval);
1026 1027 }
1027 1028
1028 1029
1029 1030
1030 1031
1031 1032 /*
1032 1033 * Load drivers required for a platform
1033 1034 * Since all hardware nodes should be available in the device
1034 1035 * tree, walk the per-driver list and load the parents of
1035 1036 * each node found. If not a hardware node, try to load it.
1036 1037 * Pseudo nexus is already loaded.
1037 1038 */
1038 1039 static int
1039 1040 load_boot_platform_modules(char *drv)
1040 1041 {
1041 1042 major_t major;
1042 1043 dev_info_t *dip;
1043 1044 char *drvname;
1044 1045 int rval = 0;
1045 1046
1046 1047 if ((major = ddi_name_to_major(drv)) == DDI_MAJOR_T_NONE) {
1047 1048 cmn_err(CE_CONT, "%s: no major number\n", drv);
1048 1049 return (-1);
1049 1050 }
1050 1051
1051 1052 /*
1052 1053 * resolve aliases
1053 1054 */
1054 1055 drvname = ddi_major_to_name(major);
1055 1056 if ((major = ddi_name_to_major(drvname)) == DDI_MAJOR_T_NONE)
1056 1057 return (-1);
1057 1058
1058 1059 #ifdef DEBUG
1059 1060 if (strcmp(drv, drvname) == 0) {
1060 1061 BMDPRINTF(("load_boot_platform_modules: %s\n", drv));
1061 1062 } else {
1062 1063 BMDPRINTF(("load_boot_platform_modules: %s -> %s\n",
1063 1064 drv, drvname));
1064 1065 }
1065 1066 #endif /* DEBUG */
1066 1067
1067 1068 dip = devnamesp[major].dn_head;
1068 1069 if (dip == NULL) {
1069 1070 /* pseudo node, not-enumerated, needs to be loaded */
1070 1071 if (modloadonly("drv", drvname) == -1) {
1071 1072 cmn_err(CE_CONT, "%s: cannot load platform driver\n",
1072 1073 drvname);
1073 1074 rval = -1;
1074 1075 }
1075 1076 } else {
1076 1077 while (dip) {
1077 1078 if (load_parent_drivers(dip, NULL) != 0)
1078 1079 rval = -1;
1079 1080 dip = ddi_get_next(dip);
1080 1081 }
1081 1082 }
1082 1083
1083 1084 return (rval);
1084 1085 }
1085 1086
1086 1087
1087 1088 /*
1088 1089 * i_find_node: Internal routine used by path_to_devinfo
1089 1090 * to locate a given nodeid in the device tree.
1090 1091 */
1091 1092 struct i_path_findnode {
1092 1093 pnode_t nodeid;
1093 1094 dev_info_t *dip;
1094 1095 };
1095 1096
1096 1097 static int
1097 1098 i_path_find_node(dev_info_t *dev, void *arg)
1098 1099 {
1099 1100 struct i_path_findnode *f = (struct i_path_findnode *)arg;
1100 1101
1101 1102
1102 1103 if (ddi_get_nodeid(dev) == (int)f->nodeid) {
1103 1104 f->dip = dev;
1104 1105 return (DDI_WALK_TERMINATE);
1105 1106 }
1106 1107 return (DDI_WALK_CONTINUE);
1107 1108 }
1108 1109
1109 1110 /*
1110 1111 * Return the devinfo node to a boot device
1111 1112 */
1112 1113 static dev_info_t *
1113 1114 path_to_devinfo(char *path)
1114 1115 {
1115 1116 struct i_path_findnode fn;
1116 1117 extern dev_info_t *top_devinfo;
1117 1118
1118 1119 /*
1119 1120 * Get the nodeid of the given pathname, if such a mapping exists.
1120 1121 */
1121 1122 fn.dip = NULL;
1122 1123 fn.nodeid = prom_finddevice(path);
1123 1124 if (fn.nodeid != OBP_BADNODE) {
1124 1125 /*
1125 1126 * Find the nodeid in our copy of the device tree and return
1126 1127 * whatever name we used to bind this node to a driver.
1127 1128 */
1128 1129 ddi_walk_devs(top_devinfo, i_path_find_node, (void *)(&fn));
1129 1130 }
1130 1131
1131 1132 #ifdef DEBUG
1132 1133 /*
1133 1134 * If we're bound to something other than the nodename,
1134 1135 * note that in the message buffer and system log.
1135 1136 */
1136 1137 if (fn.dip) {
1137 1138 char *p, *q;
1138 1139
1139 1140 p = ddi_binding_name(fn.dip);
1140 1141 q = ddi_node_name(fn.dip);
1141 1142 if (p && q && (strcmp(p, q) != 0)) {
1142 1143 BMDPRINTF(("path_to_devinfo: %s bound to %s\n",
1143 1144 path, p));
1144 1145 }
1145 1146 }
1146 1147 #endif /* DEBUG */
1147 1148
1148 1149 return (fn.dip);
1149 1150 }
1150 1151
1151 1152 /*
1152 1153 * This routine returns B_TRUE if the bootpath corresponds to
1153 1154 * IP over IB driver.
1154 1155 *
1155 1156 * The format of the bootpath for the IP over IB looks like
1156 1157 * /pci@1f,700000/pci@1/ib@0:port=1,pkey=8001,protocol=ip
1157 1158 *
1158 1159 * The minor node portion "port=1,pkey=8001,protocol=ip" represents
1159 1160 * IP over IB driver.
1160 1161 */
1161 1162 static boolean_t
1162 1163 netboot_over_ib(char *bootpath)
1163 1164 {
1164 1165
1165 1166 char *temp;
1166 1167 boolean_t ret = B_FALSE;
1167 1168 pnode_t node = prom_finddevice(bootpath);
1168 1169 int len;
1169 1170 char devicetype[OBP_MAXDRVNAME];
1170 1171
1171 1172 /* Is this IB node ? */
1172 1173 if (node == OBP_BADNODE || node == OBP_NONODE) {
1173 1174 return (B_FALSE);
1174 1175 }
1175 1176 len = prom_getproplen(node, OBP_DEVICETYPE);
1176 1177 if (len <= 1 || len >= OBP_MAXDRVNAME)
1177 1178 return (B_FALSE);
1178 1179
1179 1180 (void) prom_getprop(node, OBP_DEVICETYPE, (caddr_t)devicetype);
1180 1181
1181 1182 if (strncmp("ib", devicetype, 2) == 0) {
1182 1183 /* Check for proper IP over IB string */
1183 1184 if ((temp = strstr(bootpath, ":port=")) != NULL) {
1184 1185 if ((temp = strstr(temp, ",pkey=")) != NULL)
1185 1186 if ((temp = strstr(temp,
1186 1187 ",protocol=ip")) != NULL) {
1187 1188 ret = B_TRUE;
1188 1189 }
1189 1190 }
1190 1191 }
1191 1192 return (ret);
1192 1193 }
1193 1194
1194 1195 static boolean_t
1195 1196 netboot_over_iscsi(void)
1196 1197 {
1197 1198 int proplen;
1198 1199 boolean_t ret = B_FALSE;
1199 1200 char bootpath[OBP_MAXPATHLEN];
1200 1201
1201 1202 proplen = BOP_GETPROPLEN(bootops, BP_BOOTPATH);
1202 1203 if (proplen > 0) {
1203 1204 if (BOP_GETPROP(bootops, BP_BOOTPATH, bootpath) > 0) {
1204 1205 if (memcmp(bootpath, BP_ISCSI_DISK,
1205 1206 strlen(BP_ISCSI_DISK)) == 0) {
1206 1207 ret = B_TRUE;
1207 1208 }
1208 1209 }
1209 1210 }
1210 1211 return (ret);
1211 1212 }
↓ open down ↓ |
565 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX