Print this page
9696 add /etc/system.d support
Portions contributed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/modctl.c
+++ new/usr/src/uts/common/os/modctl.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 *
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 /*
23 23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * modctl system call for loadable module support.
28 28 */
29 29
30 30 #include <sys/param.h>
31 31 #include <sys/user.h>
32 32 #include <sys/systm.h>
33 33 #include <sys/exec.h>
34 34 #include <sys/file.h>
35 35 #include <sys/stat.h>
36 36 #include <sys/conf.h>
37 37 #include <sys/time.h>
38 38 #include <sys/reboot.h>
39 39 #include <sys/fs/ufs_fsdir.h>
40 40 #include <sys/kmem.h>
41 41 #include <sys/sysconf.h>
42 42 #include <sys/cmn_err.h>
43 43 #include <sys/ddi.h>
44 44 #include <sys/sunddi.h>
45 45 #include <sys/sunndi.h>
46 46 #include <sys/ndi_impldefs.h>
47 47 #include <sys/ddi_impldefs.h>
48 48 #include <sys/ddi_implfuncs.h>
49 49 #include <sys/bootconf.h>
50 50 #include <sys/dc_ki.h>
51 51 #include <sys/cladm.h>
52 52 #include <sys/dtrace.h>
53 53 #include <sys/kdi.h>
54 54
55 55 #include <sys/devpolicy.h>
56 56 #include <sys/modctl.h>
57 57 #include <sys/kobj.h>
58 58 #include <sys/devops.h>
59 59 #include <sys/autoconf.h>
60 60 #include <sys/hwconf.h>
61 61 #include <sys/callb.h>
62 62 #include <sys/debug.h>
63 63 #include <sys/cpuvar.h>
64 64 #include <sys/sysmacros.h>
65 65 #include <sys/sysevent.h>
66 66 #include <sys/sysevent_impl.h>
67 67 #include <sys/instance.h>
68 68 #include <sys/modhash.h>
69 69 #include <sys/modhash_impl.h>
70 70 #include <sys/dacf_impl.h>
71 71 #include <sys/vfs.h>
72 72 #include <sys/pathname.h>
73 73 #include <sys/console.h>
74 74 #include <sys/policy.h>
75 75 #include <ipp/ipp_impl.h>
76 76 #include <sys/fs/dv_node.h>
77 77 #include <sys/strsubr.h>
78 78 #include <sys/fs/sdev_impl.h>
79 79
80 80 static int mod_circdep(struct modctl *);
81 81 static int modinfo(modid_t, struct modinfo *);
82 82
83 83 static void mod_uninstall_all(void);
84 84 static int mod_getinfo(struct modctl *, struct modinfo *);
85 85 static struct modctl *allocate_modp(const char *, const char *);
86 86
87 87 static int mod_load(struct modctl *, int);
88 88 static void mod_unload(struct modctl *);
89 89 static int modinstall(struct modctl *);
90 90 static int moduninstall(struct modctl *);
91 91
92 92 static struct modctl *mod_hold_by_name_common(struct modctl *, const char *);
93 93 static struct modctl *mod_hold_next_by_id(modid_t);
94 94 static struct modctl *mod_hold_loaded_mod(struct modctl *, char *, int *);
95 95 static struct modctl *mod_hold_installed_mod(char *, int, int, int *);
96 96
97 97 static void mod_release(struct modctl *);
98 98 static void mod_make_requisite(struct modctl *, struct modctl *);
99 99 static int mod_install_requisites(struct modctl *);
100 100 static void check_esc_sequences(char *, char *);
101 101 static struct modctl *mod_hold_by_name_requisite(struct modctl *, char *);
102 102
103 103 /*
104 104 * module loading thread control structure. Calls to kobj_load_module()() are
105 105 * handled off to a separate thead using this structure.
106 106 */
107 107 struct loadmt {
108 108 ksema_t sema;
109 109 struct modctl *mp;
110 110 int usepath;
111 111 kthread_t *owner;
112 112 int retval;
113 113 };
114 114
115 115 static void modload_thread(struct loadmt *);
116 116
117 117 kcondvar_t mod_cv;
118 118 kcondvar_t mod_uninstall_cv; /* Communication between swapper */
119 119 /* and the uninstall daemon. */
120 120 kmutex_t mod_lock; /* protects &modules insert linkage, */
121 121 /* mod_busy, mod_want, and mod_ref. */
122 122 /* blocking operations while holding */
123 123 /* mod_lock should be avoided */
124 124 kmutex_t mod_uninstall_lock; /* protects mod_uninstall_cv */
125 125 kthread_id_t mod_aul_thread;
126 126
127 127 int modunload_wait;
128 128 kmutex_t modunload_wait_mutex;
129 129 kcondvar_t modunload_wait_cv;
130 130 int modunload_active_count;
131 131 int modunload_disable_count;
132 132
133 133 int isminiroot; /* set if running as miniroot */
134 134 int modrootloaded; /* set after root driver and fs are loaded */
135 135 int moddebug = 0x0; /* debug flags for module writers */
136 136 int swaploaded; /* set after swap driver and fs are loaded */
137 137 int bop_io_quiesced = 0; /* set when BOP I/O can no longer be used */
138 138 int last_module_id;
139 139 clock_t mod_uninstall_interval = 0;
140 140 int mod_uninstall_pass_max = 6;
141 141 int mod_uninstall_ref_zero; /* # modules that went mod_ref == 0 */
142 142 int mod_uninstall_pass_exc; /* mod_uninstall_all left new stuff */
143 143
144 144 int ddi_modclose_unload = 1; /* 0 -> just decrement reference */
145 145
146 146 int devcnt_incr = 256; /* allow for additional drivers */
147 147 int devcnt_min = 512; /* and always at least this number */
148 148
149 149 struct devnames *devnamesp;
150 150 struct devnames orphanlist;
151 151
152 152 krwlock_t devinfo_tree_lock; /* obsolete, to be removed */
153 153
154 154 #define MAJBINDFILE "/etc/name_to_major"
155 155 #define SYSBINDFILE "/etc/name_to_sysnum"
156 156
157 157 static char majbind[] = MAJBINDFILE;
158 158 static char sysbind[] = SYSBINDFILE;
159 159 static uint_t mod_autounload_key; /* for module autounload detection */
160 160
161 161 extern int obpdebug;
162 162
163 163 #define DEBUGGER_PRESENT ((boothowto & RB_DEBUG) || (obpdebug != 0))
164 164
165 165 static int minorperm_loaded = 0;
166 166
167 167 void
168 168 mod_setup(void)
169 169 {
170 170 struct sysent *callp;
171 171 int callnum, exectype;
172 172 int num_devs;
173 173 int i;
174 174
175 175 /*
176 176 * Initialize the list of loaded driver dev_ops.
177 177 * XXX - This must be done before reading the system file so that
178 178 * forceloads of drivers will work.
179 179 */
180 180 num_devs = read_binding_file(majbind, mb_hashtab, make_mbind);
181 181 /*
182 182 * Since read_binding_file is common code, it doesn't enforce that all
183 183 * of the binding file entries have major numbers <= MAXMAJ32. Thus,
184 184 * ensure that we don't allocate some massive amount of space due to a
185 185 * bad entry. We can't have major numbers bigger than MAXMAJ32
186 186 * until file system support for larger major numbers exists.
187 187 */
188 188
189 189 /*
190 190 * Leave space for expansion, but not more than L_MAXMAJ32
191 191 */
192 192 devcnt = MIN(num_devs + devcnt_incr, L_MAXMAJ32);
193 193 devcnt = MAX(devcnt, devcnt_min);
194 194 devopsp = kmem_alloc(devcnt * sizeof (struct dev_ops *), KM_SLEEP);
195 195 for (i = 0; i < devcnt; i++)
196 196 devopsp[i] = &mod_nodev_ops;
197 197
198 198 init_devnamesp(devcnt);
199 199
200 200 /*
201 201 * Sync up with the work that the stand-alone linker has already done.
202 202 */
203 203 (void) kobj_sync();
204 204
205 205 if (boothowto & RB_DEBUG)
206 206 kdi_dvec_modavail();
207 207
208 208 make_aliases(mb_hashtab);
209 209
210 210 /*
211 211 * Initialize streams device implementation structures.
212 212 */
213 213 devimpl = kmem_zalloc(devcnt * sizeof (cdevsw_impl_t), KM_SLEEP);
214 214
215 215 /*
216 216 * If the cl_bootstrap module is present,
217 217 * we should be configured as a cluster. Loading this module
218 218 * will set "cluster_bootflags" to non-zero.
219 219 */
220 220 (void) modload("misc", "cl_bootstrap");
221 221
222 222 (void) read_binding_file(sysbind, sb_hashtab, make_mbind);
223 223 init_syscallnames(NSYSCALL);
224 224
225 225 /*
226 226 * Start up dynamic autoconfiguration framework (dacf).
227 227 */
228 228 mod_hash_init();
229 229 dacf_init();
230 230
231 231 /*
232 232 * Start up IP policy framework (ipp).
233 233 */
234 234 ipp_init();
235 235
236 236 /*
237 237 * Allocate loadable native system call locks.
238 238 */
239 239 for (callnum = 0, callp = sysent; callnum < NSYSCALL;
240 240 callnum++, callp++) {
241 241 if (LOADABLE_SYSCALL(callp)) {
242 242 if (mod_getsysname(callnum) != NULL) {
243 243 callp->sy_lock =
244 244 kobj_zalloc(sizeof (krwlock_t), KM_SLEEP);
245 245 rw_init(callp->sy_lock, NULL, RW_DEFAULT, NULL);
246 246 } else {
247 247 callp->sy_flags &= ~SE_LOADABLE;
248 248 callp->sy_callc = nosys;
249 249 }
250 250 #ifdef DEBUG
251 251 } else {
252 252 /*
253 253 * Do some sanity checks on the sysent table
254 254 */
255 255 switch (callp->sy_flags & SE_RVAL_MASK) {
256 256 case SE_32RVAL1:
257 257 /* only r_val1 returned */
258 258 case SE_32RVAL1 | SE_32RVAL2:
259 259 /* r_val1 and r_val2 returned */
260 260 case SE_64RVAL:
261 261 /* 64-bit rval returned */
262 262 break;
263 263 default:
264 264 cmn_err(CE_WARN, "sysent[%d]: bad flags %x",
265 265 callnum, callp->sy_flags);
266 266 }
267 267 #endif
268 268 }
269 269 }
270 270
271 271 #ifdef _SYSCALL32_IMPL
272 272 /*
273 273 * Allocate loadable system call locks for 32-bit compat syscalls
274 274 */
275 275 for (callnum = 0, callp = sysent32; callnum < NSYSCALL;
276 276 callnum++, callp++) {
277 277 if (LOADABLE_SYSCALL(callp)) {
278 278 if (mod_getsysname(callnum) != NULL) {
279 279 callp->sy_lock =
280 280 kobj_zalloc(sizeof (krwlock_t), KM_SLEEP);
281 281 rw_init(callp->sy_lock, NULL, RW_DEFAULT, NULL);
282 282 } else {
283 283 callp->sy_flags &= ~SE_LOADABLE;
284 284 callp->sy_callc = nosys;
285 285 }
286 286 #ifdef DEBUG
287 287 } else {
288 288 /*
289 289 * Do some sanity checks on the sysent table
290 290 */
291 291 switch (callp->sy_flags & SE_RVAL_MASK) {
292 292 case SE_32RVAL1:
293 293 /* only r_val1 returned */
294 294 case SE_32RVAL1 | SE_32RVAL2:
295 295 /* r_val1 and r_val2 returned */
296 296 case SE_64RVAL:
297 297 /* 64-bit rval returned */
298 298 break;
299 299 default:
300 300 cmn_err(CE_WARN, "sysent32[%d]: bad flags %x",
301 301 callnum, callp->sy_flags);
302 302 goto skip;
303 303 }
304 304
305 305 /*
306 306 * Cross-check the native and compatibility tables.
307 307 */
308 308 if (callp->sy_callc == nosys ||
309 309 sysent[callnum].sy_callc == nosys)
310 310 continue;
311 311 /*
312 312 * If only one or the other slot is loadable, then
313 313 * there's an error -- they should match!
314 314 */
315 315 if ((callp->sy_callc == loadable_syscall) ^
316 316 (sysent[callnum].sy_callc == loadable_syscall)) {
317 317 cmn_err(CE_WARN, "sysent[%d] loadable?",
318 318 callnum);
319 319 }
320 320 /*
321 321 * This is more of a heuristic test -- if the
322 322 * system call returns two values in the 32-bit
323 323 * world, it should probably return two 32-bit
324 324 * values in the 64-bit world too.
325 325 */
326 326 if (((callp->sy_flags & SE_32RVAL2) == 0) ^
327 327 ((sysent[callnum].sy_flags & SE_32RVAL2) == 0)) {
328 328 cmn_err(CE_WARN, "sysent[%d] rval2 mismatch!",
329 329 callnum);
330 330 }
331 331 skip:;
332 332 #endif /* DEBUG */
333 333 }
334 334 }
335 335 #endif /* _SYSCALL32_IMPL */
336 336
337 337 /*
338 338 * Allocate loadable exec locks. (Assumes all execs are loadable)
339 339 */
340 340 for (exectype = 0; exectype < nexectype; exectype++) {
341 341 execsw[exectype].exec_lock =
342 342 kobj_zalloc(sizeof (krwlock_t), KM_SLEEP);
343 343 rw_init(execsw[exectype].exec_lock, NULL, RW_DEFAULT, NULL);
344 344 }
345 345
346 346 read_class_file();
347 347
348 348 /* init thread specific structure for mod_uninstall_all */
349 349 tsd_create(&mod_autounload_key, NULL);
350 350 }
351 351
352 352 static int
353 353 modctl_modload(int use_path, char *filename, int *rvp)
354 354 {
355 355 struct modctl *modp;
356 356 int retval = 0;
357 357 char *filenamep;
358 358 int modid;
359 359
360 360 filenamep = kmem_zalloc(MOD_MAXPATH, KM_SLEEP);
361 361
362 362 if (copyinstr(filename, filenamep, MOD_MAXPATH, 0)) {
363 363 retval = EFAULT;
364 364 goto out;
365 365 }
366 366
367 367 filenamep[MOD_MAXPATH - 1] = 0;
368 368 modp = mod_hold_installed_mod(filenamep, use_path, 0, &retval);
369 369
370 370 if (modp == NULL)
371 371 goto out;
372 372
373 373 modp->mod_loadflags |= MOD_NOAUTOUNLOAD;
374 374 modid = modp->mod_id;
375 375 mod_release_mod(modp);
376 376 CPU_STATS_ADDQ(CPU, sys, modload, 1);
377 377 if (rvp != NULL && copyout(&modid, rvp, sizeof (modid)) != 0)
378 378 retval = EFAULT;
379 379 out:
380 380 kmem_free(filenamep, MOD_MAXPATH);
381 381
382 382 return (retval);
383 383 }
384 384
385 385 static int
386 386 modctl_modunload(modid_t id)
387 387 {
388 388 int rval = 0;
389 389
390 390 if (id == 0) {
391 391 #ifdef DEBUG
392 392 /*
393 393 * Turn on mod_uninstall_daemon
394 394 */
395 395 if (mod_uninstall_interval == 0) {
396 396 mod_uninstall_interval = 60;
397 397 modreap();
398 398 return (rval);
399 399 }
400 400 #endif
401 401 mod_uninstall_all();
402 402 } else {
403 403 rval = modunload(id);
404 404 }
405 405 return (rval);
406 406 }
407 407
408 408 static int
409 409 modctl_modinfo(modid_t id, struct modinfo *umodi)
410 410 {
411 411 int retval;
412 412 struct modinfo modi;
413 413 #if defined(_SYSCALL32_IMPL)
414 414 int nobase;
415 415 struct modinfo32 modi32;
416 416 #endif
417 417
418 418 if (get_udatamodel() == DATAMODEL_NATIVE) {
419 419 if (copyin(umodi, &modi, sizeof (struct modinfo)) != 0)
420 420 return (EFAULT);
421 421 }
422 422 #ifdef _SYSCALL32_IMPL
423 423 else {
424 424 bzero(&modi, sizeof (modi));
425 425 if (copyin(umodi, &modi32, sizeof (struct modinfo32)) != 0)
426 426 return (EFAULT);
427 427 modi.mi_info = modi32.mi_info;
428 428 modi.mi_id = modi32.mi_id;
429 429 modi.mi_nextid = modi32.mi_nextid;
430 430 nobase = modi.mi_info & MI_INFO_NOBASE;
431 431 }
432 432 #endif
433 433 /*
434 434 * This flag is -only- for the kernels use.
435 435 */
436 436 modi.mi_info &= ~MI_INFO_LINKAGE;
437 437
438 438 retval = modinfo(id, &modi);
439 439 if (retval)
440 440 return (retval);
441 441
442 442 if (get_udatamodel() == DATAMODEL_NATIVE) {
443 443 if (copyout(&modi, umodi, sizeof (struct modinfo)) != 0)
444 444 retval = EFAULT;
445 445 #ifdef _SYSCALL32_IMPL
446 446 } else {
447 447 int i;
448 448
449 449 if (!nobase && (uintptr_t)modi.mi_base > UINT32_MAX)
450 450 return (EOVERFLOW);
451 451
452 452 modi32.mi_info = modi.mi_info;
453 453 modi32.mi_state = modi.mi_state;
454 454 modi32.mi_id = modi.mi_id;
455 455 modi32.mi_nextid = modi.mi_nextid;
456 456 modi32.mi_base = (caddr32_t)(uintptr_t)modi.mi_base;
457 457 modi32.mi_size = modi.mi_size;
458 458 modi32.mi_rev = modi.mi_rev;
459 459 modi32.mi_loadcnt = modi.mi_loadcnt;
460 460 bcopy(modi.mi_name, modi32.mi_name, sizeof (modi32.mi_name));
461 461 for (i = 0; i < MODMAXLINK32; i++) {
462 462 modi32.mi_msinfo[i].msi_p0 = modi.mi_msinfo[i].msi_p0;
463 463 bcopy(modi.mi_msinfo[i].msi_linkinfo,
464 464 modi32.mi_msinfo[i].msi_linkinfo,
465 465 sizeof (modi32.mi_msinfo[0].msi_linkinfo));
466 466 }
467 467 if (copyout(&modi32, umodi, sizeof (struct modinfo32)) != 0)
468 468 retval = EFAULT;
469 469 #endif
470 470 }
471 471
472 472 return (retval);
473 473 }
474 474
475 475 /*
476 476 * Return the last major number in the range of permissible major numbers.
477 477 */
478 478 /*ARGSUSED*/
479 479 static int
480 480 modctl_modreserve(modid_t id, int *data)
481 481 {
482 482 if (copyout(&devcnt, data, sizeof (devcnt)) != 0)
483 483 return (EFAULT);
484 484 return (0);
485 485 }
486 486
487 487 /* Add/Remove driver and binding aliases */
488 488 static int
489 489 modctl_update_driver_aliases(int add, int *data)
490 490 {
491 491 struct modconfig mc;
492 492 int i, n, rv = 0;
493 493 struct aliases alias;
494 494 struct aliases *ap;
495 495 char name[MAXMODCONFNAME];
496 496 char cname[MAXMODCONFNAME];
497 497 char *drvname;
498 498 int resid;
499 499 struct alias_info {
500 500 char *alias_name;
501 501 int alias_resid;
502 502 } *aliases, *aip;
503 503
504 504 bzero(&mc, sizeof (struct modconfig));
505 505 if (get_udatamodel() == DATAMODEL_NATIVE) {
506 506 if (copyin(data, &mc, sizeof (struct modconfig)) != 0)
507 507 return (EFAULT);
508 508 }
509 509 #ifdef _SYSCALL32_IMPL
510 510 else {
511 511 struct modconfig32 modc32;
512 512 if (copyin(data, &modc32, sizeof (struct modconfig32)) != 0)
513 513 return (EFAULT);
514 514 else {
515 515 bcopy(modc32.drvname, mc.drvname,
516 516 sizeof (modc32.drvname));
517 517 bcopy(modc32.drvclass, mc.drvclass,
518 518 sizeof (modc32.drvclass));
519 519 mc.major = modc32.major;
520 520 mc.flags = modc32.flags;
521 521 mc.num_aliases = modc32.num_aliases;
522 522 mc.ap = (struct aliases *)(uintptr_t)modc32.ap;
523 523 }
524 524 }
525 525 #endif
526 526
527 527 /*
528 528 * If the driver is already in the mb_hashtab, and the name given
529 529 * doesn't match that driver's name, fail. Otherwise, pass, since
530 530 * we may be adding aliases.
531 531 */
532 532 drvname = mod_major_to_name(mc.major);
533 533 if ((drvname != NULL) && strcmp(drvname, mc.drvname) != 0)
534 534 return (EINVAL);
535 535
536 536 /*
537 537 * Precede alias removal by unbinding as many devices as possible.
538 538 */
539 539 if (add == 0) {
540 540 (void) i_ddi_unload_drvconf(mc.major);
541 541 i_ddi_unbind_devs(mc.major);
542 542 }
543 543
544 544 /*
545 545 * Add/remove each supplied driver alias to/from mb_hashtab
546 546 */
547 547 ap = mc.ap;
548 548 if (mc.num_aliases > 0)
549 549 aliases = kmem_zalloc(
550 550 mc.num_aliases * sizeof (struct alias_info), KM_SLEEP);
551 551 aip = aliases;
552 552 for (i = 0; i < mc.num_aliases; i++) {
553 553 bzero(&alias, sizeof (struct aliases));
554 554 if (get_udatamodel() == DATAMODEL_NATIVE) {
555 555 if (copyin(ap, &alias, sizeof (struct aliases)) != 0) {
556 556 rv = EFAULT;
557 557 goto error;
558 558 }
559 559 if (alias.a_len > MAXMODCONFNAME) {
560 560 rv = EINVAL;
561 561 goto error;
562 562 }
563 563 if (copyin(alias.a_name, name, alias.a_len) != 0) {
564 564 rv = EFAULT;
565 565 goto error;
566 566 }
567 567 if (name[alias.a_len - 1] != '\0') {
568 568 rv = EINVAL;
569 569 goto error;
570 570 }
571 571 }
572 572 #ifdef _SYSCALL32_IMPL
573 573 else {
574 574 struct aliases32 al32;
575 575 bzero(&al32, sizeof (struct aliases32));
576 576 if (copyin(ap, &al32, sizeof (struct aliases32)) != 0) {
577 577 rv = EFAULT;
578 578 goto error;
579 579 }
580 580 if (al32.a_len > MAXMODCONFNAME) {
581 581 rv = EINVAL;
582 582 goto error;
583 583 }
584 584 if (copyin((void *)(uintptr_t)al32.a_name,
585 585 name, al32.a_len) != 0) {
586 586 rv = EFAULT;
587 587 goto error;
588 588 }
589 589 if (name[al32.a_len - 1] != '\0') {
590 590 rv = EINVAL;
591 591 goto error;
592 592 }
593 593 alias.a_next = (void *)(uintptr_t)al32.a_next;
594 594 }
595 595 #endif
596 596 check_esc_sequences(name, cname);
597 597 aip->alias_name = strdup(cname);
598 598 ap = alias.a_next;
599 599 aip++;
600 600 }
601 601
602 602 if (add == 0) {
603 603 ap = mc.ap;
604 604 resid = 0;
605 605 aip = aliases;
606 606 /* attempt to unbind all devices bound to each alias */
607 607 for (i = 0; i < mc.num_aliases; i++) {
608 608 n = i_ddi_unbind_devs_by_alias(
609 609 mc.major, aip->alias_name);
610 610 resid += n;
611 611 aip->alias_resid = n;
612 612 }
613 613
614 614 /*
615 615 * If some device bound to an alias remains in use,
616 616 * and override wasn't specified, no change is made to
617 617 * the binding state and we fail the operation.
618 618 */
619 619 if (resid > 0 && ((mc.flags & MOD_UNBIND_OVERRIDE) == 0)) {
620 620 rv = EBUSY;
621 621 goto error;
622 622 }
623 623
624 624 /*
625 625 * No device remains bound of any of the aliases,
626 626 * or force was requested. Mark each alias as
627 627 * inactive via delete_mbind so no future binds
628 628 * to this alias take place and that a new
629 629 * binding can be established.
630 630 */
631 631 aip = aliases;
632 632 for (i = 0; i < mc.num_aliases; i++) {
633 633 if (moddebug & MODDEBUG_BINDING)
634 634 cmn_err(CE_CONT, "Removing binding for %s "
635 635 "(%d active references)\n",
636 636 aip->alias_name, aip->alias_resid);
637 637 delete_mbind(aip->alias_name, mb_hashtab);
638 638 aip++;
639 639 }
640 640 rv = 0;
641 641 } else {
642 642 aip = aliases;
643 643 for (i = 0; i < mc.num_aliases; i++) {
644 644 if (moddebug & MODDEBUG_BINDING)
645 645 cmn_err(CE_NOTE, "Adding binding for '%s'\n",
646 646 aip->alias_name);
647 647 (void) make_mbind(aip->alias_name,
648 648 mc.major, NULL, mb_hashtab);
649 649 aip++;
650 650 }
651 651 /*
652 652 * Try to establish an mbinding for mc.drvname, and add it to
653 653 * devnames. Add class if any after establishing the major
654 654 * number.
655 655 */
656 656 (void) make_mbind(mc.drvname, mc.major, NULL, mb_hashtab);
657 657 if ((rv = make_devname(mc.drvname, mc.major,
658 658 (mc.flags & MOD_ADDMAJBIND_UPDATE) ?
659 659 DN_DRIVER_INACTIVE : 0)) != 0) {
660 660 goto error;
661 661 }
662 662
663 663 if (mc.drvclass[0] != '\0')
664 664 add_class(mc.drvname, mc.drvclass);
665 665 if ((mc.flags & MOD_ADDMAJBIND_UPDATE) == 0) {
666 666 (void) i_ddi_load_drvconf(mc.major);
667 667 }
668 668 }
669 669
670 670 /*
671 671 * Ensure that all nodes are bound to the most appropriate driver
672 672 * possible, attempting demotion and rebind when a more appropriate
673 673 * driver now exists. But not when adding a driver update-only.
674 674 */
675 675 if ((add == 0) || ((mc.flags & MOD_ADDMAJBIND_UPDATE) == 0)) {
676 676 i_ddi_bind_devs();
677 677 i_ddi_di_cache_invalidate();
678 678 }
679 679
680 680 error:
681 681 if (mc.num_aliases > 0) {
682 682 aip = aliases;
683 683 for (i = 0; i < mc.num_aliases; i++) {
684 684 if (aip->alias_name != NULL)
685 685 strfree(aip->alias_name);
686 686 aip++;
687 687 }
688 688 kmem_free(aliases, mc.num_aliases * sizeof (struct alias_info));
689 689 }
690 690 return (rv);
691 691 }
692 692
693 693 static int
694 694 modctl_add_driver_aliases(int *data)
695 695 {
696 696 return (modctl_update_driver_aliases(1, data));
697 697 }
698 698
699 699 static int
700 700 modctl_remove_driver_aliases(int *data)
701 701 {
702 702 return (modctl_update_driver_aliases(0, data));
703 703 }
704 704
705 705 static int
706 706 modctl_rem_major(major_t major)
707 707 {
708 708 struct devnames *dnp;
709 709
710 710 if (major >= devcnt)
711 711 return (EINVAL);
712 712
713 713 /* mark devnames as removed */
714 714 dnp = &devnamesp[major];
715 715 LOCK_DEV_OPS(&dnp->dn_lock);
716 716 if (dnp->dn_name == NULL ||
717 717 (dnp->dn_flags & (DN_DRIVER_REMOVED | DN_TAKEN_GETUDEV))) {
718 718 UNLOCK_DEV_OPS(&dnp->dn_lock);
719 719 return (EINVAL);
720 720 }
721 721 dnp->dn_flags |= DN_DRIVER_REMOVED;
722 722 pm_driver_removed(major);
723 723 UNLOCK_DEV_OPS(&dnp->dn_lock);
724 724
725 725 (void) i_ddi_unload_drvconf(major);
726 726 i_ddi_unbind_devs(major);
727 727 i_ddi_bind_devs();
728 728 i_ddi_di_cache_invalidate();
729 729
730 730 /* purge all the bindings to this driver */
731 731 purge_mbind(major, mb_hashtab);
732 732 return (0);
733 733 }
734 734
735 735 static struct vfs *
736 736 path_to_vfs(char *name)
737 737 {
738 738 vnode_t *vp;
739 739 struct vfs *vfsp;
740 740
741 741 if (lookupname(name, UIO_SYSSPACE, FOLLOW, NULLVPP, &vp))
742 742 return (NULL);
743 743
744 744 vfsp = vp->v_vfsp;
745 745 VN_RELE(vp);
746 746 return (vfsp);
747 747 }
748 748
749 749 static int
750 750 new_vfs_in_modpath()
751 751 {
752 752 static int n_modpath = 0;
753 753 static char *modpath_copy;
754 754 static struct pathvfs {
755 755 char *path;
756 756 struct vfs *vfsp;
757 757 } *pathvfs;
758 758
759 759 int i, new_vfs = 0;
760 760 char *tmp, *tmp1;
761 761 struct vfs *vfsp;
762 762
763 763 if (n_modpath != 0) {
764 764 for (i = 0; i < n_modpath; i++) {
765 765 vfsp = path_to_vfs(pathvfs[i].path);
766 766 if (vfsp != pathvfs[i].vfsp) {
767 767 pathvfs[i].vfsp = vfsp;
768 768 if (vfsp)
769 769 new_vfs = 1;
770 770 }
771 771 }
772 772 return (new_vfs);
773 773 }
774 774
775 775 /*
776 776 * First call, initialize the pathvfs structure
777 777 */
778 778 modpath_copy = i_ddi_strdup(default_path, KM_SLEEP);
779 779 tmp = modpath_copy;
780 780 n_modpath = 1;
781 781 tmp1 = strchr(tmp, ' ');
782 782 while (tmp1) {
783 783 *tmp1 = '\0';
784 784 n_modpath++;
785 785 tmp = tmp1 + 1;
786 786 tmp1 = strchr(tmp, ' ');
787 787 }
788 788
789 789 pathvfs = kmem_zalloc(n_modpath * sizeof (struct pathvfs), KM_SLEEP);
790 790 tmp = modpath_copy;
791 791 for (i = 0; i < n_modpath; i++) {
792 792 pathvfs[i].path = tmp;
793 793 vfsp = path_to_vfs(tmp);
794 794 pathvfs[i].vfsp = vfsp;
795 795 tmp += strlen(tmp) + 1;
796 796 }
797 797 return (1); /* always reread driver.conf the first time */
798 798 }
799 799
800 800 static int
801 801 modctl_load_drvconf(major_t major, int flags)
802 802 {
803 803 int ret;
804 804
805 805 /*
806 806 * devfsadm -u - read all new driver.conf files
807 807 * and bind and configure devices for new drivers.
808 808 */
809 809 if (flags & MOD_LOADDRVCONF_RECONF) {
810 810 (void) i_ddi_load_drvconf(DDI_MAJOR_T_NONE);
811 811 i_ddi_bind_devs();
812 812 i_ddi_di_cache_invalidate();
813 813 return (0);
814 814 }
815 815
816 816 /*
817 817 * update_drv <drv> - reload driver.conf for the specified driver
818 818 */
819 819 if (major != DDI_MAJOR_T_NONE) {
820 820 ret = i_ddi_load_drvconf(major);
821 821 if (ret == 0)
822 822 i_ddi_bind_devs();
823 823 return (ret);
824 824 }
825 825
826 826 /*
827 827 * We are invoked to rescan new driver.conf files. It is
828 828 * only necessary if a new file system was mounted in the
829 829 * module_path. Because rescanning driver.conf files can
830 830 * take some time on older platforms (sun4m), the following
831 831 * code skips unnecessary driver.conf rescans to optimize
832 832 * boot performance.
833 833 */
834 834 if (new_vfs_in_modpath()) {
835 835 (void) i_ddi_load_drvconf(DDI_MAJOR_T_NONE);
836 836 /*
837 837 * If we are still initializing io subsystem,
838 838 * load drivers with ddi-forceattach property
839 839 */
840 840 if (!i_ddi_io_initialized())
841 841 i_ddi_forceattach_drivers();
842 842 }
843 843 return (0);
844 844 }
845 845
846 846 /*
847 847 * Unload driver.conf file and follow up by attempting
848 848 * to rebind devices to more appropriate driver.
849 849 */
850 850 static int
851 851 modctl_unload_drvconf(major_t major)
852 852 {
853 853 int ret;
854 854
855 855 if (major >= devcnt)
856 856 return (EINVAL);
857 857
858 858 ret = i_ddi_unload_drvconf(major);
859 859 if (ret != 0)
860 860 return (ret);
861 861 (void) i_ddi_unbind_devs(major);
862 862 i_ddi_bind_devs();
863 863
864 864 return (0);
865 865 }
866 866
867 867 static void
868 868 check_esc_sequences(char *str, char *cstr)
869 869 {
870 870 int i;
871 871 size_t len;
872 872 char *p;
873 873
874 874 len = strlen(str);
875 875 for (i = 0; i < len; i++, str++, cstr++) {
876 876 if (*str != '\\') {
877 877 *cstr = *str;
878 878 } else {
879 879 p = str + 1;
880 880 /*
881 881 * we only handle octal escape sequences for SPACE
882 882 */
883 883 if (*p++ == '0' && *p++ == '4' && *p == '0') {
884 884 *cstr = ' ';
885 885 str += 3;
886 886 } else {
887 887 *cstr = *str;
888 888 }
889 889 }
890 890 }
891 891 *cstr = 0;
892 892 }
893 893
894 894 static int
895 895 modctl_getmodpathlen(int *data)
896 896 {
897 897 int len;
898 898 len = strlen(default_path);
899 899 if (copyout(&len, data, sizeof (len)) != 0)
900 900 return (EFAULT);
901 901 return (0);
902 902 }
903 903
904 904 static int
905 905 modctl_getmodpath(char *data)
906 906 {
907 907 if (copyout(default_path, data, strlen(default_path) + 1) != 0)
908 908 return (EFAULT);
909 909 return (0);
910 910 }
911 911
912 912 static int
913 913 modctl_read_sysbinding_file(void)
914 914 {
915 915 (void) read_binding_file(sysbind, sb_hashtab, make_mbind);
916 916 return (0);
917 917 }
918 918
919 919 static int
920 920 modctl_getmaj(char *uname, uint_t ulen, int *umajorp)
921 921 {
922 922 char name[256];
923 923 int retval;
924 924 major_t major;
925 925
926 926 if (ulen == 0)
927 927 return (EINVAL);
928 928 if ((retval = copyinstr(uname, name,
929 929 (ulen < 256) ? ulen : 256, 0)) != 0)
930 930 return (retval);
931 931 if ((major = mod_name_to_major(name)) == DDI_MAJOR_T_NONE)
932 932 return (ENODEV);
933 933 if (copyout(&major, umajorp, sizeof (major_t)) != 0)
934 934 return (EFAULT);
935 935 return (0);
936 936 }
937 937
938 938 static char **
939 939 convert_constraint_string(char *constraints, size_t len)
940 940 {
941 941 int i;
942 942 int n;
943 943 char *p;
944 944 char **array;
945 945
946 946 ASSERT(constraints != NULL);
947 947 ASSERT(len > 0);
948 948
949 949 for (i = 0, p = constraints; strlen(p) > 0; i++, p += strlen(p) + 1)
950 950 ;
951 951
952 952 n = i;
953 953
954 954 if (n == 0) {
955 955 kmem_free(constraints, len);
956 956 return (NULL);
957 957 }
958 958
959 959 array = kmem_alloc((n + 1) * sizeof (char *), KM_SLEEP);
960 960
961 961 for (i = 0, p = constraints; i < n; i++, p += strlen(p) + 1) {
962 962 array[i] = i_ddi_strdup(p, KM_SLEEP);
963 963 }
964 964 array[n] = NULL;
965 965
966 966 kmem_free(constraints, len);
967 967
968 968 return (array);
969 969 }
970 970 /*ARGSUSED*/
971 971 static int
972 972 modctl_retire(char *path, char *uconstraints, size_t ulen)
973 973 {
974 974 char *pathbuf;
975 975 char *devpath;
976 976 size_t pathsz;
977 977 int retval;
978 978 char *constraints;
979 979 char **cons_array;
980 980
981 981 if (path == NULL)
982 982 return (EINVAL);
983 983
984 984 if ((uconstraints == NULL) ^ (ulen == 0))
985 985 return (EINVAL);
986 986
987 987 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
988 988 retval = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
989 989 if (retval != 0) {
990 990 kmem_free(pathbuf, MAXPATHLEN);
991 991 return (retval);
992 992 }
993 993 devpath = i_ddi_strdup(pathbuf, KM_SLEEP);
994 994 kmem_free(pathbuf, MAXPATHLEN);
995 995
996 996 /*
997 997 * First check if the device is already retired.
998 998 * If it is, then persist the retire anyway, just in case the retire
999 999 * store has got out of sync with the boot archive.
1000 1000 */
1001 1001 if (e_ddi_device_retired(devpath)) {
1002 1002 cmn_err(CE_NOTE, "Device: already retired: %s", devpath);
1003 1003 (void) e_ddi_retire_persist(devpath);
1004 1004 kmem_free(devpath, strlen(devpath) + 1);
1005 1005 return (0);
1006 1006 }
1007 1007
1008 1008 cons_array = NULL;
1009 1009 if (uconstraints) {
1010 1010 constraints = kmem_alloc(ulen, KM_SLEEP);
1011 1011 if (copyin(uconstraints, constraints, ulen)) {
1012 1012 kmem_free(constraints, ulen);
1013 1013 kmem_free(devpath, strlen(devpath) + 1);
1014 1014 return (EFAULT);
1015 1015 }
1016 1016 cons_array = convert_constraint_string(constraints, ulen);
1017 1017 }
1018 1018
1019 1019 /*
1020 1020 * Try to retire the device first. The following
1021 1021 * routine will return an error only if the device
1022 1022 * is not retireable i.e. retire constraints forbid
1023 1023 * a retire. A return of success from this routine
1024 1024 * indicates that device is retireable.
1025 1025 */
1026 1026 retval = e_ddi_retire_device(devpath, cons_array);
1027 1027 if (retval != DDI_SUCCESS) {
1028 1028 cmn_err(CE_WARN, "constraints forbid retire: %s", devpath);
1029 1029 kmem_free(devpath, strlen(devpath) + 1);
1030 1030 return (ENOTSUP);
1031 1031 }
1032 1032
1033 1033 /*
1034 1034 * Ok, the retire succeeded. Persist the retire.
1035 1035 * If retiring a nexus, we need to only persist the
1036 1036 * nexus retire. Any children of a retired nexus
1037 1037 * are automatically covered by the retire store
1038 1038 * code.
1039 1039 */
1040 1040 retval = e_ddi_retire_persist(devpath);
1041 1041 if (retval != 0) {
1042 1042 cmn_err(CE_WARN, "Failed to persist device retire: error %d: "
1043 1043 "%s", retval, devpath);
1044 1044 kmem_free(devpath, strlen(devpath) + 1);
1045 1045 return (retval);
1046 1046 }
1047 1047 if (moddebug & MODDEBUG_RETIRE)
1048 1048 cmn_err(CE_NOTE, "Persisted retire of device: %s", devpath);
1049 1049
1050 1050 kmem_free(devpath, strlen(devpath) + 1);
1051 1051 return (0);
1052 1052 }
1053 1053
1054 1054 static int
1055 1055 modctl_is_retired(char *path, int *statep)
1056 1056 {
1057 1057 char *pathbuf;
1058 1058 char *devpath;
1059 1059 size_t pathsz;
1060 1060 int error;
1061 1061 int status;
1062 1062
1063 1063 if (path == NULL || statep == NULL)
1064 1064 return (EINVAL);
1065 1065
1066 1066 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1067 1067 error = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
1068 1068 if (error != 0) {
1069 1069 kmem_free(pathbuf, MAXPATHLEN);
1070 1070 return (error);
1071 1071 }
1072 1072 devpath = i_ddi_strdup(pathbuf, KM_SLEEP);
1073 1073 kmem_free(pathbuf, MAXPATHLEN);
1074 1074
1075 1075 if (e_ddi_device_retired(devpath))
1076 1076 status = 1;
1077 1077 else
1078 1078 status = 0;
1079 1079 kmem_free(devpath, strlen(devpath) + 1);
1080 1080
1081 1081 return (copyout(&status, statep, sizeof (status)) ? EFAULT : 0);
1082 1082 }
1083 1083
1084 1084 static int
1085 1085 modctl_unretire(char *path)
1086 1086 {
1087 1087 char *pathbuf;
1088 1088 char *devpath;
1089 1089 size_t pathsz;
1090 1090 int retired;
1091 1091 int retval;
1092 1092
1093 1093 if (path == NULL)
1094 1094 return (EINVAL);
1095 1095
1096 1096 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1097 1097 retval = copyinstr(path, pathbuf, MAXPATHLEN, &pathsz);
1098 1098 if (retval != 0) {
1099 1099 kmem_free(pathbuf, MAXPATHLEN);
1100 1100 return (retval);
1101 1101 }
1102 1102 devpath = i_ddi_strdup(pathbuf, KM_SLEEP);
1103 1103 kmem_free(pathbuf, MAXPATHLEN);
1104 1104
1105 1105 /*
1106 1106 * We check if a device is retired (first) before
1107 1107 * unpersisting the retire, because we use the
1108 1108 * retire store to determine if a device is retired.
1109 1109 * If we unpersist first, the device will always appear
1110 1110 * to be unretired. For the rationale behind unpersisting
1111 1111 * a device that is not retired, see the next comment.
1112 1112 */
1113 1113 retired = e_ddi_device_retired(devpath);
1114 1114
1115 1115 /*
1116 1116 * We call unpersist unconditionally because the lookup
1117 1117 * for retired devices (e_ddi_device_retired()), skips "bypassed"
1118 1118 * devices. We still want to be able remove "bypassed" entries
1119 1119 * from the persistent store, so we unpersist unconditionally
1120 1120 * i.e. whether or not the entry is found on a lookup.
1121 1121 *
1122 1122 * e_ddi_retire_unpersist() returns 1 if it found and cleared
1123 1123 * an entry from the retire store or 0 otherwise.
1124 1124 */
1125 1125 if (e_ddi_retire_unpersist(devpath))
1126 1126 if (moddebug & MODDEBUG_RETIRE) {
1127 1127 cmn_err(CE_NOTE, "Unpersisted retire of device: %s",
1128 1128 devpath);
1129 1129 }
1130 1130
1131 1131 /*
1132 1132 * Check if the device is already unretired. If so,
1133 1133 * the unretire becomes a NOP
1134 1134 */
1135 1135 if (!retired) {
1136 1136 cmn_err(CE_NOTE, "Not retired: %s", devpath);
1137 1137 kmem_free(devpath, strlen(devpath) + 1);
1138 1138 return (0);
1139 1139 }
1140 1140
1141 1141 retval = e_ddi_unretire_device(devpath);
1142 1142 if (retval != 0) {
1143 1143 cmn_err(CE_WARN, "cannot unretire device: error %d, path %s\n",
1144 1144 retval, devpath);
1145 1145 }
1146 1146
1147 1147 kmem_free(devpath, strlen(devpath) + 1);
1148 1148
1149 1149 return (retval);
1150 1150 }
1151 1151
1152 1152 static int
1153 1153 modctl_getname(char *uname, uint_t ulen, int *umajorp)
1154 1154 {
1155 1155 char *name;
1156 1156 major_t major;
1157 1157
1158 1158 if (copyin(umajorp, &major, sizeof (major)) != 0)
1159 1159 return (EFAULT);
1160 1160 if ((name = mod_major_to_name(major)) == NULL)
1161 1161 return (ENODEV);
1162 1162 if ((strlen(name) + 1) > ulen)
1163 1163 return (ENOSPC);
1164 1164 return (copyoutstr(name, uname, ulen, NULL));
1165 1165 }
1166 1166
1167 1167 static int
1168 1168 modctl_devt2instance(dev_t dev, int *uinstancep)
1169 1169 {
1170 1170 int instance;
1171 1171
1172 1172 if ((instance = dev_to_instance(dev)) == -1)
1173 1173 return (EINVAL);
1174 1174
1175 1175 return (copyout(&instance, uinstancep, sizeof (int)));
1176 1176 }
1177 1177
1178 1178 /*
1179 1179 * Return the sizeof of the device id.
1180 1180 */
1181 1181 static int
1182 1182 modctl_sizeof_devid(dev_t dev, uint_t *len)
1183 1183 {
1184 1184 uint_t sz;
1185 1185 ddi_devid_t devid;
1186 1186
1187 1187 /* get device id */
1188 1188 if (ddi_lyr_get_devid(dev, &devid) == DDI_FAILURE)
1189 1189 return (EINVAL);
1190 1190
1191 1191 sz = ddi_devid_sizeof(devid);
1192 1192 ddi_devid_free(devid);
1193 1193
1194 1194 /* copyout device id size */
1195 1195 if (copyout(&sz, len, sizeof (sz)) != 0)
1196 1196 return (EFAULT);
1197 1197
1198 1198 return (0);
1199 1199 }
1200 1200
1201 1201 /*
1202 1202 * Return a copy of the device id.
1203 1203 */
1204 1204 static int
1205 1205 modctl_get_devid(dev_t dev, uint_t len, ddi_devid_t udevid)
1206 1206 {
1207 1207 uint_t sz;
1208 1208 ddi_devid_t devid;
1209 1209 int err = 0;
1210 1210
1211 1211 /* get device id */
1212 1212 if (ddi_lyr_get_devid(dev, &devid) == DDI_FAILURE)
1213 1213 return (EINVAL);
1214 1214
1215 1215 sz = ddi_devid_sizeof(devid);
1216 1216
1217 1217 /* Error if device id is larger than space allocated */
1218 1218 if (sz > len) {
1219 1219 ddi_devid_free(devid);
1220 1220 return (ENOSPC);
1221 1221 }
1222 1222
1223 1223 /* copy out device id */
1224 1224 if (copyout(devid, udevid, sz) != 0)
1225 1225 err = EFAULT;
1226 1226 ddi_devid_free(devid);
↓ open down ↓ |
1226 lines elided |
↑ open up ↑ |
1227 1227 return (err);
1228 1228 }
1229 1229
1230 1230 /*
1231 1231 * return the /devices paths associated with the specified devid and
1232 1232 * minor name.
1233 1233 */
1234 1234 /*ARGSUSED*/
1235 1235 static int
1236 1236 modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag,
1237 - size_t *ulensp, char *upaths)
1237 + size_t *ulensp, char *upaths)
1238 1238 {
1239 1239 ddi_devid_t devid = NULL;
1240 1240 int devid_len;
1241 1241 char *minor_name = NULL;
1242 1242 dev_info_t *dip = NULL;
1243 1243 int circ;
1244 1244 struct ddi_minor_data *dmdp;
1245 1245 char *path = NULL;
1246 1246 int ulens;
1247 1247 int lens;
1248 1248 int len;
1249 1249 dev_t *devlist = NULL;
1250 1250 int ndevs;
1251 1251 int i;
1252 1252 int ret = 0;
1253 1253
1254 1254 /*
1255 1255 * If upaths is NULL then we are only computing the amount of space
1256 1256 * needed to hold the paths and returning the value in *ulensp. If we
1257 1257 * are copying out paths then we get the amount of space allocated by
1258 1258 * the caller. If the actual space needed for paths is larger, or
1259 1259 * things are changing out from under us, then we return EAGAIN.
1260 1260 */
1261 1261 if (upaths) {
1262 1262 if (ulensp == NULL)
1263 1263 return (EINVAL);
1264 1264 if (copyin(ulensp, &ulens, sizeof (ulens)) != 0)
1265 1265 return (EFAULT);
1266 1266 }
1267 1267
1268 1268 /*
1269 1269 * copyin enough of the devid to determine the length then
1270 1270 * reallocate and copy in the entire devid.
1271 1271 */
1272 1272 devid_len = ddi_devid_sizeof(NULL);
1273 1273 devid = kmem_alloc(devid_len, KM_SLEEP);
1274 1274 if (copyin(udevid, devid, devid_len)) {
1275 1275 ret = EFAULT;
1276 1276 goto out;
1277 1277 }
1278 1278 len = devid_len;
1279 1279 devid_len = ddi_devid_sizeof(devid);
1280 1280 kmem_free(devid, len);
1281 1281 devid = kmem_alloc(devid_len, KM_SLEEP);
1282 1282 if (copyin(udevid, devid, devid_len)) {
1283 1283 ret = EFAULT;
1284 1284 goto out;
1285 1285 }
1286 1286
1287 1287 /* copyin the minor name if specified. */
1288 1288 minor_name = uminor_name;
1289 1289 if ((minor_name != DEVID_MINOR_NAME_ALL) &&
1290 1290 (minor_name != DEVID_MINOR_NAME_ALL_CHR) &&
1291 1291 (minor_name != DEVID_MINOR_NAME_ALL_BLK)) {
1292 1292 minor_name = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1293 1293 if (copyinstr(uminor_name, minor_name, MAXPATHLEN, 0)) {
1294 1294 ret = EFAULT;
1295 1295 goto out;
1296 1296 }
1297 1297 }
1298 1298
1299 1299 /*
1300 1300 * Use existing function to resolve the devid into a devlist.
1301 1301 *
1302 1302 * NOTE: there is a loss of spectype information in the current
1303 1303 * ddi_lyr_devid_to_devlist implementation. We work around this by not
1304 1304 * passing down DEVID_MINOR_NAME_ALL here, but reproducing all minor
1305 1305 * node forms in the loop processing the devlist below. It would be
1306 1306 * best if at some point the use of this interface here was replaced
1307 1307 * with a path oriented call.
1308 1308 */
1309 1309 if (ddi_lyr_devid_to_devlist(devid,
1310 1310 (minor_name == DEVID_MINOR_NAME_ALL) ?
1311 1311 DEVID_MINOR_NAME_ALL_CHR : minor_name,
1312 1312 &ndevs, &devlist) != DDI_SUCCESS) {
1313 1313 ret = EINVAL;
1314 1314 goto out;
1315 1315 }
1316 1316
1317 1317 /*
1318 1318 * loop over the devlist, converting each devt to a path and doing
1319 1319 * a copyout of the path and computation of the amount of space
1320 1320 * needed to hold all the paths
1321 1321 */
1322 1322 path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1323 1323 for (i = 0, lens = 0; i < ndevs; i++) {
1324 1324
1325 1325 /* find the dip associated with the dev_t */
1326 1326 if ((dip = e_ddi_hold_devi_by_dev(devlist[i], 0)) == NULL)
1327 1327 continue;
1328 1328
1329 1329 /* loop over all the minor nodes, skipping ones we don't want */
1330 1330 ndi_devi_enter(dip, &circ);
1331 1331 for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) {
1332 1332 if ((dmdp->ddm_dev != devlist[i]) ||
1333 1333 (dmdp->type != DDM_MINOR))
1334 1334 continue;
1335 1335
1336 1336 if ((minor_name != DEVID_MINOR_NAME_ALL) &&
1337 1337 (minor_name != DEVID_MINOR_NAME_ALL_CHR) &&
1338 1338 (minor_name != DEVID_MINOR_NAME_ALL_BLK) &&
1339 1339 strcmp(minor_name, dmdp->ddm_name))
1340 1340 continue;
1341 1341 else {
1342 1342 if ((minor_name == DEVID_MINOR_NAME_ALL_CHR) &&
1343 1343 (dmdp->ddm_spec_type != S_IFCHR))
1344 1344 continue;
1345 1345 if ((minor_name == DEVID_MINOR_NAME_ALL_BLK) &&
1346 1346 (dmdp->ddm_spec_type != S_IFBLK))
1347 1347 continue;
1348 1348 }
1349 1349
1350 1350 (void) ddi_pathname_minor(dmdp, path);
1351 1351 len = strlen(path) + 1;
1352 1352 *(path + len) = '\0'; /* set double termination */
1353 1353 lens += len;
1354 1354
1355 1355 /* copyout the path with double terminations */
1356 1356 if (upaths) {
1357 1357 if (lens > ulens) {
1358 1358 ret = EAGAIN;
1359 1359 goto out;
1360 1360 }
1361 1361 if (copyout(path, upaths, len + 1)) {
1362 1362 ret = EFAULT;
1363 1363 goto out;
1364 1364 }
1365 1365 upaths += len;
1366 1366 }
1367 1367 }
1368 1368 ndi_devi_exit(dip, circ);
1369 1369 ddi_release_devi(dip);
1370 1370 dip = NULL;
1371 1371 }
1372 1372 lens++; /* add one for double termination */
1373 1373
1374 1374 /* copy out the amount of space needed to hold the paths */
1375 1375 if (ulensp && copyout(&lens, ulensp, sizeof (lens))) {
1376 1376 ret = EFAULT;
1377 1377 goto out;
1378 1378 }
1379 1379 ret = 0;
1380 1380
1381 1381 out: if (dip) {
1382 1382 ndi_devi_exit(dip, circ);
1383 1383 ddi_release_devi(dip);
1384 1384 }
1385 1385 if (path)
1386 1386 kmem_free(path, MAXPATHLEN);
1387 1387 if (devlist)
1388 1388 ddi_lyr_free_devlist(devlist, ndevs);
1389 1389 if (minor_name &&
1390 1390 (minor_name != DEVID_MINOR_NAME_ALL) &&
1391 1391 (minor_name != DEVID_MINOR_NAME_ALL_CHR) &&
1392 1392 (minor_name != DEVID_MINOR_NAME_ALL_BLK))
1393 1393 kmem_free(minor_name, MAXPATHLEN);
1394 1394 if (devid)
1395 1395 kmem_free(devid, devid_len);
1396 1396 return (ret);
1397 1397 }
1398 1398
1399 1399 /*
1400 1400 * Return the size of the minor name.
1401 1401 */
1402 1402 static int
1403 1403 modctl_sizeof_minorname(dev_t dev, int spectype, uint_t *len)
1404 1404 {
1405 1405 uint_t sz;
1406 1406 char *name;
1407 1407
1408 1408 /* get the minor name */
1409 1409 if (ddi_lyr_get_minor_name(dev, spectype, &name) == DDI_FAILURE)
1410 1410 return (EINVAL);
1411 1411
1412 1412 sz = strlen(name) + 1;
1413 1413 kmem_free(name, sz);
1414 1414
1415 1415 /* copy out the size of the minor name */
1416 1416 if (copyout(&sz, len, sizeof (sz)) != 0)
1417 1417 return (EFAULT);
1418 1418
1419 1419 return (0);
1420 1420 }
1421 1421
1422 1422 /*
1423 1423 * Return the minor name.
1424 1424 */
1425 1425 static int
1426 1426 modctl_get_minorname(dev_t dev, int spectype, uint_t len, char *uname)
1427 1427 {
1428 1428 uint_t sz;
1429 1429 char *name;
1430 1430 int err = 0;
1431 1431
1432 1432 /* get the minor name */
1433 1433 if (ddi_lyr_get_minor_name(dev, spectype, &name) == DDI_FAILURE)
1434 1434 return (EINVAL);
1435 1435
1436 1436 sz = strlen(name) + 1;
1437 1437
1438 1438 /* Error if the minor name is larger than the space allocated */
1439 1439 if (sz > len) {
1440 1440 kmem_free(name, sz);
1441 1441 return (ENOSPC);
1442 1442 }
1443 1443
1444 1444 /* copy out the minor name */
1445 1445 if (copyout(name, uname, sz) != 0)
1446 1446 err = EFAULT;
1447 1447 kmem_free(name, sz);
1448 1448 return (err);
1449 1449 }
1450 1450
1451 1451 /*
1452 1452 * Return the size of the (dev_t,spectype) devfspath name.
1453 1453 */
1454 1454 static int
1455 1455 modctl_devfspath_len(dev_t dev, int spectype, uint_t *len)
1456 1456 {
1457 1457 uint_t sz;
1458 1458 char *name;
1459 1459
1460 1460 /* get the path name */
1461 1461 name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1462 1462 if (ddi_dev_pathname(dev, spectype, name) == DDI_FAILURE) {
1463 1463 kmem_free(name, MAXPATHLEN);
1464 1464 return (EINVAL);
1465 1465 }
1466 1466
1467 1467 sz = strlen(name) + 1;
1468 1468 kmem_free(name, MAXPATHLEN);
1469 1469
1470 1470 /* copy out the size of the path name */
1471 1471 if (copyout(&sz, len, sizeof (sz)) != 0)
1472 1472 return (EFAULT);
1473 1473
1474 1474 return (0);
1475 1475 }
1476 1476
1477 1477 /*
1478 1478 * Return the (dev_t,spectype) devfspath name.
1479 1479 */
1480 1480 static int
1481 1481 modctl_devfspath(dev_t dev, int spectype, uint_t len, char *uname)
1482 1482 {
1483 1483 uint_t sz;
1484 1484 char *name;
1485 1485 int err = 0;
1486 1486
1487 1487 /* get the path name */
1488 1488 name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1489 1489 if (ddi_dev_pathname(dev, spectype, name) == DDI_FAILURE) {
1490 1490 kmem_free(name, MAXPATHLEN);
1491 1491 return (EINVAL);
1492 1492 }
1493 1493
1494 1494 sz = strlen(name) + 1;
1495 1495
1496 1496 /* Error if the path name is larger than the space allocated */
1497 1497 if (sz > len) {
1498 1498 kmem_free(name, MAXPATHLEN);
1499 1499 return (ENOSPC);
1500 1500 }
1501 1501
1502 1502 /* copy out the path name */
1503 1503 if (copyout(name, uname, sz) != 0)
1504 1504 err = EFAULT;
1505 1505 kmem_free(name, MAXPATHLEN);
1506 1506 return (err);
1507 1507 }
1508 1508
1509 1509 /*
1510 1510 * Return the size of the (major,instance) devfspath name.
1511 1511 */
1512 1512 static int
1513 1513 modctl_devfspath_mi_len(major_t major, int instance, uint_t *len)
1514 1514 {
1515 1515 uint_t sz;
1516 1516 char *name;
1517 1517
1518 1518 /* get the path name */
1519 1519 name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1520 1520 if (e_ddi_majorinstance_to_path(major, instance, name) != DDI_SUCCESS) {
1521 1521 kmem_free(name, MAXPATHLEN);
1522 1522 return (EINVAL);
1523 1523 }
1524 1524
1525 1525 sz = strlen(name) + 1;
1526 1526 kmem_free(name, MAXPATHLEN);
1527 1527
1528 1528 /* copy out the size of the path name */
1529 1529 if (copyout(&sz, len, sizeof (sz)) != 0)
1530 1530 return (EFAULT);
1531 1531
1532 1532 return (0);
1533 1533 }
1534 1534
1535 1535 /*
1536 1536 * Return the (major_instance) devfspath name.
1537 1537 * NOTE: e_ddi_majorinstance_to_path does not require the device to attach to
1538 1538 * return a path - it uses the instance tree.
1539 1539 */
1540 1540 static int
1541 1541 modctl_devfspath_mi(major_t major, int instance, uint_t len, char *uname)
1542 1542 {
1543 1543 uint_t sz;
1544 1544 char *name;
1545 1545 int err = 0;
1546 1546
1547 1547 /* get the path name */
1548 1548 name = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1549 1549 if (e_ddi_majorinstance_to_path(major, instance, name) != DDI_SUCCESS) {
1550 1550 kmem_free(name, MAXPATHLEN);
1551 1551 return (EINVAL);
1552 1552 }
1553 1553
1554 1554 sz = strlen(name) + 1;
1555 1555
1556 1556 /* Error if the path name is larger than the space allocated */
1557 1557 if (sz > len) {
1558 1558 kmem_free(name, MAXPATHLEN);
1559 1559 return (ENOSPC);
1560 1560 }
1561 1561
1562 1562 /* copy out the path name */
1563 1563 if (copyout(name, uname, sz) != 0)
1564 1564 err = EFAULT;
1565 1565 kmem_free(name, MAXPATHLEN);
1566 1566 return (err);
1567 1567 }
1568 1568
1569 1569 static int
1570 1570 modctl_get_fbname(char *path)
1571 1571 {
1572 1572 extern dev_t fbdev;
1573 1573 char *pathname = NULL;
1574 1574 int rval = 0;
1575 1575
1576 1576 /* make sure fbdev is set before we plunge in */
1577 1577 if (fbdev == NODEV)
1578 1578 return (ENODEV);
1579 1579
1580 1580 pathname = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1581 1581 if ((rval = ddi_dev_pathname(fbdev, S_IFCHR,
1582 1582 pathname)) == DDI_SUCCESS) {
1583 1583 if (copyout(pathname, path, strlen(pathname)+1) != 0) {
1584 1584 rval = EFAULT;
1585 1585 }
1586 1586 }
1587 1587 kmem_free(pathname, MAXPATHLEN);
1588 1588 return (rval);
1589 1589 }
1590 1590
1591 1591 /*
1592 1592 * modctl_reread_dacf()
1593 1593 * Reread the dacf rules database from the named binding file.
1594 1594 * If NULL is specified, pass along the NULL, it means 'use the default'.
1595 1595 */
1596 1596 static int
1597 1597 modctl_reread_dacf(char *path)
1598 1598 {
1599 1599 int rval = 0;
1600 1600 char *filename, *filenamep;
1601 1601
1602 1602 filename = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
1603 1603
1604 1604 if (path == NULL) {
1605 1605 filenamep = NULL;
1606 1606 } else {
1607 1607 if (copyinstr(path, filename, MAXPATHLEN, 0) != 0) {
1608 1608 rval = EFAULT;
1609 1609 goto out;
1610 1610 }
1611 1611 filenamep = filename;
1612 1612 filenamep[MAXPATHLEN - 1] = '\0';
1613 1613 }
1614 1614
1615 1615 rval = read_dacf_binding_file(filenamep);
1616 1616 out:
1617 1617 kmem_free(filename, MAXPATHLEN);
1618 1618 return (rval);
1619 1619 }
1620 1620
1621 1621 /*ARGSUSED*/
1622 1622 static int
1623 1623 modctl_modevents(int subcmd, uintptr_t a2, uintptr_t a3, uintptr_t a4,
1624 1624 uint_t flag)
1625 1625 {
1626 1626 int error = 0;
1627 1627 char *filenamep;
1628 1628
1629 1629 switch (subcmd) {
1630 1630
1631 1631 case MODEVENTS_FLUSH:
1632 1632 /* flush all currently queued events */
1633 1633 log_sysevent_flushq(subcmd, flag);
1634 1634 break;
1635 1635
1636 1636 case MODEVENTS_SET_DOOR_UPCALL_FILENAME:
1637 1637 /*
1638 1638 * bind door_upcall to filename
1639 1639 * this should only be done once per invocation
1640 1640 * of the event daemon.
1641 1641 */
1642 1642
1643 1643 filenamep = kmem_zalloc(MOD_MAXPATH, KM_SLEEP);
1644 1644
1645 1645 if (copyinstr((char *)a2, filenamep, MOD_MAXPATH, 0)) {
1646 1646 error = EFAULT;
1647 1647 } else {
1648 1648 error = log_sysevent_filename(filenamep);
1649 1649 }
1650 1650 kmem_free(filenamep, MOD_MAXPATH);
1651 1651 break;
1652 1652
1653 1653 case MODEVENTS_GETDATA:
1654 1654 error = log_sysevent_copyout_data((sysevent_id_t *)a2,
1655 1655 (size_t)a3, (caddr_t)a4);
1656 1656 break;
1657 1657
1658 1658 case MODEVENTS_FREEDATA:
1659 1659 error = log_sysevent_free_data((sysevent_id_t *)a2);
1660 1660 break;
1661 1661 case MODEVENTS_POST_EVENT:
1662 1662 error = log_usr_sysevent((sysevent_t *)a2, (uint32_t)a3,
1663 1663 (sysevent_id_t *)a4);
1664 1664 break;
1665 1665 case MODEVENTS_REGISTER_EVENT:
1666 1666 error = log_sysevent_register((char *)a2, (char *)a3,
1667 1667 (se_pubsub_t *)a4);
1668 1668 break;
1669 1669 default:
1670 1670 error = EINVAL;
1671 1671 }
1672 1672
1673 1673 return (error);
1674 1674 }
1675 1675
1676 1676 static void
1677 1677 free_mperm(mperm_t *mp)
1678 1678 {
1679 1679 int len;
1680 1680
1681 1681 if (mp->mp_minorname) {
1682 1682 len = strlen(mp->mp_minorname) + 1;
1683 1683 kmem_free(mp->mp_minorname, len);
1684 1684 }
1685 1685 kmem_free(mp, sizeof (mperm_t));
1686 1686 }
1687 1687
1688 1688 #define MP_NO_DRV_ERR \
1689 1689 "/etc/minor_perm: no driver for %s\n"
1690 1690
1691 1691 #define MP_EMPTY_MINOR \
1692 1692 "/etc/minor_perm: empty minor name for driver %s\n"
1693 1693
1694 1694 #define MP_NO_MINOR \
1695 1695 "/etc/minor_perm: no minor matching %s for driver %s\n"
1696 1696
1697 1697 /*
1698 1698 * Remove mperm entry with matching minorname
1699 1699 */
1700 1700 static void
1701 1701 rem_minorperm(major_t major, char *drvname, mperm_t *mp, int is_clone)
1702 1702 {
1703 1703 mperm_t **mp_head;
1704 1704 mperm_t *freemp = NULL;
1705 1705 struct devnames *dnp = &devnamesp[major];
1706 1706 mperm_t **wildmp;
1707 1707
1708 1708 ASSERT(mp->mp_minorname && strlen(mp->mp_minorname) > 0);
1709 1709
1710 1710 LOCK_DEV_OPS(&dnp->dn_lock);
1711 1711 if (strcmp(mp->mp_minorname, "*") == 0) {
1712 1712 wildmp = ((is_clone == 0) ?
1713 1713 &dnp->dn_mperm_wild : &dnp->dn_mperm_clone);
1714 1714 if (*wildmp)
1715 1715 freemp = *wildmp;
1716 1716 *wildmp = NULL;
1717 1717 } else {
1718 1718 mp_head = &dnp->dn_mperm;
1719 1719 while (*mp_head) {
1720 1720 if (strcmp((*mp_head)->mp_minorname,
1721 1721 mp->mp_minorname) != 0) {
1722 1722 mp_head = &(*mp_head)->mp_next;
1723 1723 continue;
1724 1724 }
1725 1725 /* remove the entry */
1726 1726 freemp = *mp_head;
1727 1727 *mp_head = freemp->mp_next;
1728 1728 break;
1729 1729 }
1730 1730 }
1731 1731 if (freemp) {
1732 1732 if (moddebug & MODDEBUG_MINORPERM) {
1733 1733 cmn_err(CE_CONT, "< %s %s 0%o %d %d\n",
1734 1734 drvname, freemp->mp_minorname,
1735 1735 freemp->mp_mode & 0777,
1736 1736 freemp->mp_uid, freemp->mp_gid);
1737 1737 }
1738 1738 free_mperm(freemp);
1739 1739 } else {
1740 1740 if (moddebug & MODDEBUG_MINORPERM) {
1741 1741 cmn_err(CE_CONT, MP_NO_MINOR,
1742 1742 drvname, mp->mp_minorname);
1743 1743 }
1744 1744 }
1745 1745
1746 1746 UNLOCK_DEV_OPS(&dnp->dn_lock);
1747 1747 }
1748 1748
1749 1749 /*
1750 1750 * Add minor perm entry
1751 1751 */
1752 1752 static void
1753 1753 add_minorperm(major_t major, char *drvname, mperm_t *mp, int is_clone)
1754 1754 {
1755 1755 mperm_t **mp_head;
1756 1756 mperm_t *freemp = NULL;
1757 1757 struct devnames *dnp = &devnamesp[major];
1758 1758 mperm_t **wildmp;
1759 1759
1760 1760 ASSERT(mp->mp_minorname && strlen(mp->mp_minorname) > 0);
1761 1761
1762 1762 /*
1763 1763 * Note that update_drv replace semantics require
1764 1764 * replacing matching entries with the new permissions.
1765 1765 */
1766 1766 LOCK_DEV_OPS(&dnp->dn_lock);
1767 1767 if (strcmp(mp->mp_minorname, "*") == 0) {
1768 1768 wildmp = ((is_clone == 0) ?
1769 1769 &dnp->dn_mperm_wild : &dnp->dn_mperm_clone);
1770 1770 if (*wildmp)
1771 1771 freemp = *wildmp;
1772 1772 *wildmp = mp;
1773 1773 } else {
1774 1774 mperm_t *p, *v = NULL;
1775 1775 for (p = dnp->dn_mperm; p; v = p, p = p->mp_next) {
1776 1776 if (strcmp(p->mp_minorname, mp->mp_minorname) == 0) {
1777 1777 if (v == NULL)
1778 1778 dnp->dn_mperm = mp;
1779 1779 else
1780 1780 v->mp_next = mp;
1781 1781 mp->mp_next = p->mp_next;
1782 1782 freemp = p;
1783 1783 goto replaced;
1784 1784 }
1785 1785 }
1786 1786 if (p == NULL) {
1787 1787 mp_head = &dnp->dn_mperm;
1788 1788 if (*mp_head == NULL) {
1789 1789 *mp_head = mp;
1790 1790 } else {
1791 1791 mp->mp_next = *mp_head;
1792 1792 *mp_head = mp;
1793 1793 }
1794 1794 }
1795 1795 }
1796 1796 replaced:
1797 1797 if (freemp) {
1798 1798 if (moddebug & MODDEBUG_MINORPERM) {
1799 1799 cmn_err(CE_CONT, "< %s %s 0%o %d %d\n",
1800 1800 drvname, freemp->mp_minorname,
1801 1801 freemp->mp_mode & 0777,
1802 1802 freemp->mp_uid, freemp->mp_gid);
1803 1803 }
1804 1804 free_mperm(freemp);
1805 1805 }
1806 1806 if (moddebug & MODDEBUG_MINORPERM) {
1807 1807 cmn_err(CE_CONT, "> %s %s 0%o %d %d\n",
1808 1808 drvname, mp->mp_minorname, mp->mp_mode & 0777,
1809 1809 mp->mp_uid, mp->mp_gid);
1810 1810 }
1811 1811 UNLOCK_DEV_OPS(&dnp->dn_lock);
1812 1812 }
1813 1813
1814 1814
1815 1815 static int
1816 1816 process_minorperm(int cmd, nvlist_t *nvl)
1817 1817 {
1818 1818 char *minor;
1819 1819 major_t major;
1820 1820 mperm_t *mp;
1821 1821 nvpair_t *nvp;
1822 1822 char *name;
1823 1823 int is_clone;
1824 1824 major_t minmaj;
1825 1825
1826 1826 ASSERT(cmd == MODLOADMINORPERM ||
1827 1827 cmd == MODADDMINORPERM || cmd == MODREMMINORPERM);
1828 1828
1829 1829 nvp = NULL;
1830 1830 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
1831 1831 name = nvpair_name(nvp);
1832 1832
1833 1833 is_clone = 0;
1834 1834 (void) nvpair_value_string(nvp, &minor);
1835 1835 major = ddi_name_to_major(name);
1836 1836 if (major != DDI_MAJOR_T_NONE) {
1837 1837 mp = kmem_zalloc(sizeof (*mp), KM_SLEEP);
1838 1838 if (minor == NULL || strlen(minor) == 0) {
1839 1839 if (moddebug & MODDEBUG_MINORPERM) {
1840 1840 cmn_err(CE_CONT, MP_EMPTY_MINOR, name);
1841 1841 }
1842 1842 minor = "*";
1843 1843 }
1844 1844
1845 1845 /*
1846 1846 * The minor name of a node using the clone
1847 1847 * driver must be the driver name. To avoid
1848 1848 * multiple searches, we map entries in the form
1849 1849 * clone:<driver> to <driver>:*. This also allows us
1850 1850 * to filter out some of the litter in /etc/minor_perm.
1851 1851 * Minor perm alias entries where the name is not
1852 1852 * the driver kept on the clone list itself.
1853 1853 * This all seems very fragile as a driver could
1854 1854 * be introduced with an existing alias name.
1855 1855 */
1856 1856 if (strcmp(name, "clone") == 0) {
1857 1857 minmaj = ddi_name_to_major(minor);
1858 1858 if (minmaj != DDI_MAJOR_T_NONE) {
1859 1859 if (moddebug & MODDEBUG_MINORPERM) {
1860 1860 cmn_err(CE_CONT,
1861 1861 "mapping %s:%s to %s:*\n",
1862 1862 name, minor, minor);
1863 1863 }
1864 1864 major = minmaj;
1865 1865 name = minor;
1866 1866 minor = "*";
1867 1867 is_clone = 1;
1868 1868 }
1869 1869 }
1870 1870
1871 1871 if (mp) {
1872 1872 mp->mp_minorname =
1873 1873 i_ddi_strdup(minor, KM_SLEEP);
1874 1874 }
1875 1875 } else {
1876 1876 mp = NULL;
1877 1877 if (moddebug & MODDEBUG_MINORPERM) {
1878 1878 cmn_err(CE_CONT, MP_NO_DRV_ERR, name);
1879 1879 }
1880 1880 }
1881 1881
1882 1882 /* mode */
1883 1883 nvp = nvlist_next_nvpair(nvl, nvp);
1884 1884 ASSERT(strcmp(nvpair_name(nvp), "mode") == 0);
1885 1885 if (mp)
1886 1886 (void) nvpair_value_int32(nvp, (int *)&mp->mp_mode);
1887 1887 /* uid */
1888 1888 nvp = nvlist_next_nvpair(nvl, nvp);
1889 1889 ASSERT(strcmp(nvpair_name(nvp), "uid") == 0);
1890 1890 if (mp)
1891 1891 (void) nvpair_value_uint32(nvp, &mp->mp_uid);
1892 1892 /* gid */
1893 1893 nvp = nvlist_next_nvpair(nvl, nvp);
1894 1894 ASSERT(strcmp(nvpair_name(nvp), "gid") == 0);
1895 1895 if (mp) {
1896 1896 (void) nvpair_value_uint32(nvp, &mp->mp_gid);
1897 1897
1898 1898 if (cmd == MODREMMINORPERM) {
1899 1899 rem_minorperm(major, name, mp, is_clone);
1900 1900 free_mperm(mp);
1901 1901 } else {
1902 1902 add_minorperm(major, name, mp, is_clone);
1903 1903 }
1904 1904 }
1905 1905 }
1906 1906
1907 1907 if (cmd == MODLOADMINORPERM)
1908 1908 minorperm_loaded = 1;
1909 1909
1910 1910 /*
1911 1911 * Reset permissions of cached dv_nodes
1912 1912 */
1913 1913 (void) devfs_reset_perm(DV_RESET_PERM);
1914 1914
1915 1915 return (0);
1916 1916 }
1917 1917
1918 1918 static int
1919 1919 modctl_minorperm(int cmd, char *usrbuf, size_t buflen)
1920 1920 {
1921 1921 int error;
1922 1922 nvlist_t *nvl;
1923 1923 char *buf = kmem_alloc(buflen, KM_SLEEP);
1924 1924
1925 1925 if ((error = ddi_copyin(usrbuf, buf, buflen, 0)) != 0) {
1926 1926 kmem_free(buf, buflen);
1927 1927 return (error);
1928 1928 }
1929 1929
1930 1930 error = nvlist_unpack(buf, buflen, &nvl, KM_SLEEP);
1931 1931 kmem_free(buf, buflen);
1932 1932 if (error)
1933 1933 return (error);
1934 1934
1935 1935 error = process_minorperm(cmd, nvl);
1936 1936 nvlist_free(nvl);
1937 1937 return (error);
1938 1938 }
1939 1939
1940 1940 struct walk_args {
1941 1941 char *wa_drvname;
1942 1942 list_t wa_pathlist;
1943 1943 };
1944 1944
1945 1945 struct path_elem {
1946 1946 char *pe_dir;
1947 1947 char *pe_nodename;
1948 1948 list_node_t pe_node;
1949 1949 int pe_dirlen;
1950 1950 };
1951 1951
1952 1952 /*ARGSUSED*/
1953 1953 static int
1954 1954 modctl_inst_walker(const char *path, in_node_t *np, in_drv_t *dp, void *arg)
1955 1955 {
1956 1956 struct walk_args *wargs = (struct walk_args *)arg;
1957 1957 struct path_elem *pe;
1958 1958 char *nodename;
1959 1959
1960 1960 /*
1961 1961 * Search may be restricted to a single driver in the case of rem_drv
1962 1962 */
1963 1963 if (wargs->wa_drvname &&
1964 1964 strcmp(dp->ind_driver_name, wargs->wa_drvname) != 0)
1965 1965 return (INST_WALK_CONTINUE);
1966 1966
1967 1967 pe = kmem_zalloc(sizeof (*pe), KM_SLEEP);
1968 1968 pe->pe_dir = i_ddi_strdup((char *)path, KM_SLEEP);
1969 1969 pe->pe_dirlen = strlen(pe->pe_dir) + 1;
1970 1970 ASSERT(strrchr(pe->pe_dir, '/') != NULL);
1971 1971 nodename = strrchr(pe->pe_dir, '/');
1972 1972 *nodename++ = 0;
1973 1973 pe->pe_nodename = nodename;
1974 1974 list_insert_tail(&wargs->wa_pathlist, pe);
1975 1975
1976 1976 return (INST_WALK_CONTINUE);
1977 1977 }
1978 1978
1979 1979 /*
1980 1980 * /devices attribute nodes clean-up optionally performed
1981 1981 * when removing a driver (rem_drv -C).
1982 1982 *
1983 1983 * Removing attribute nodes allows a machine to be reprovisioned
1984 1984 * without the side-effect of inadvertently picking up stale
1985 1985 * device node ownership or permissions.
1986 1986 *
1987 1987 * Preserving attributes (not performing cleanup) allows devices
1988 1988 * attribute changes to be preserved across upgrades, as
1989 1989 * upgrade rather heavy-handedly does a rem_drv/add_drv cycle.
1990 1990 */
1991 1991 static int
1992 1992 modctl_remdrv_cleanup(const char *u_drvname)
1993 1993 {
1994 1994 struct walk_args *wargs;
1995 1995 struct path_elem *pe;
1996 1996 char *drvname;
1997 1997 int err, rval = 0;
1998 1998
1999 1999 drvname = kmem_alloc(MAXMODCONFNAME, KM_SLEEP);
2000 2000 if ((err = copyinstr(u_drvname, drvname, MAXMODCONFNAME, 0))) {
2001 2001 kmem_free(drvname, MAXMODCONFNAME);
2002 2002 return (err);
2003 2003 }
2004 2004
2005 2005 /*
2006 2006 * First go through the instance database. For each
2007 2007 * instance of a device bound to the driver being
2008 2008 * removed, remove any underlying devfs attribute nodes.
2009 2009 *
2010 2010 * This is a two-step process. First we go through
2011 2011 * the instance data itself, constructing a list of
2012 2012 * the nodes discovered. The second step is then
2013 2013 * to find and remove any devfs attribute nodes
2014 2014 * for the instances discovered in the first step.
2015 2015 * The two-step process avoids any difficulties
2016 2016 * which could arise by holding the instance data
2017 2017 * lock with simultaneous devfs operations.
2018 2018 */
2019 2019 wargs = kmem_zalloc(sizeof (*wargs), KM_SLEEP);
2020 2020
2021 2021 wargs->wa_drvname = drvname;
2022 2022 list_create(&wargs->wa_pathlist,
2023 2023 sizeof (struct path_elem), offsetof(struct path_elem, pe_node));
2024 2024
2025 2025 (void) e_ddi_walk_instances(modctl_inst_walker, (void *)wargs);
2026 2026
2027 2027 for (pe = list_head(&wargs->wa_pathlist); pe != NULL;
2028 2028 pe = list_next(&wargs->wa_pathlist, pe)) {
2029 2029 err = devfs_remdrv_cleanup((const char *)pe->pe_dir,
2030 2030 (const char *)pe->pe_nodename);
2031 2031 if (rval == 0)
2032 2032 rval = err;
2033 2033 }
2034 2034
2035 2035 while ((pe = list_head(&wargs->wa_pathlist)) != NULL) {
2036 2036 list_remove(&wargs->wa_pathlist, pe);
2037 2037 kmem_free(pe->pe_dir, pe->pe_dirlen);
2038 2038 kmem_free(pe, sizeof (*pe));
2039 2039 }
2040 2040 kmem_free(wargs, sizeof (*wargs));
2041 2041
2042 2042 /*
2043 2043 * Pseudo nodes aren't recorded in the instance database
2044 2044 * so any such nodes need to be handled separately.
2045 2045 */
2046 2046 err = devfs_remdrv_cleanup("pseudo", (const char *)drvname);
2047 2047 if (rval == 0)
2048 2048 rval = err;
2049 2049
2050 2050 kmem_free(drvname, MAXMODCONFNAME);
2051 2051 return (rval);
2052 2052 }
2053 2053
2054 2054 /*
2055 2055 * Perform a cleanup of non-existent /devices attribute nodes,
2056 2056 * similar to rem_drv -C, but for all drivers/devices.
2057 2057 * This is also optional, performed as part of devfsadm -C.
2058 2058 */
2059 2059 void
2060 2060 dev_devices_cleanup()
2061 2061 {
2062 2062 struct walk_args *wargs;
2063 2063 struct path_elem *pe;
2064 2064 dev_info_t *devi;
2065 2065 char *path;
2066 2066 int err;
2067 2067
2068 2068 /*
2069 2069 * It's expected that all drivers have been loaded and
2070 2070 * module unloading disabled while performing cleanup.
2071 2071 */
2072 2072 ASSERT(modunload_disable_count > 0);
2073 2073
2074 2074 wargs = kmem_zalloc(sizeof (*wargs), KM_SLEEP);
2075 2075 wargs->wa_drvname = NULL;
2076 2076 list_create(&wargs->wa_pathlist,
2077 2077 sizeof (struct path_elem), offsetof(struct path_elem, pe_node));
2078 2078
2079 2079 (void) e_ddi_walk_instances(modctl_inst_walker, (void *)wargs);
2080 2080
2081 2081 path = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2082 2082
2083 2083 for (pe = list_head(&wargs->wa_pathlist); pe != NULL;
2084 2084 pe = list_next(&wargs->wa_pathlist, pe)) {
2085 2085 (void) snprintf(path, MAXPATHLEN, "%s/%s",
2086 2086 pe->pe_dir, pe->pe_nodename);
2087 2087 devi = e_ddi_hold_devi_by_path(path, 0);
2088 2088 if (devi != NULL) {
2089 2089 ddi_release_devi(devi);
2090 2090 } else {
2091 2091 err = devfs_remdrv_cleanup((const char *)pe->pe_dir,
2092 2092 (const char *)pe->pe_nodename);
2093 2093 if (err) {
2094 2094 cmn_err(CE_CONT,
2095 2095 "devfs: %s: clean-up error %d\n",
2096 2096 path, err);
2097 2097 }
2098 2098 }
2099 2099 }
2100 2100
2101 2101 while ((pe = list_head(&wargs->wa_pathlist)) != NULL) {
2102 2102 list_remove(&wargs->wa_pathlist, pe);
2103 2103 kmem_free(pe->pe_dir, pe->pe_dirlen);
2104 2104 kmem_free(pe, sizeof (*pe));
2105 2105 }
2106 2106 kmem_free(wargs, sizeof (*wargs));
2107 2107 kmem_free(path, MAXPATHLEN);
2108 2108 }
2109 2109
2110 2110 static int
2111 2111 modctl_allocpriv(const char *name)
2112 2112 {
2113 2113 char *pstr = kmem_alloc(PRIVNAME_MAX, KM_SLEEP);
2114 2114 int error;
2115 2115
2116 2116 if ((error = copyinstr(name, pstr, PRIVNAME_MAX, 0))) {
2117 2117 kmem_free(pstr, PRIVNAME_MAX);
2118 2118 return (error);
2119 2119 }
2120 2120 error = priv_getbyname(pstr, PRIV_ALLOC);
2121 2121 if (error < 0)
2122 2122 error = -error;
2123 2123 else
2124 2124 error = 0;
2125 2125 kmem_free(pstr, PRIVNAME_MAX);
2126 2126 return (error);
2127 2127 }
2128 2128
2129 2129 static int
2130 2130 modctl_devexists(const char *upath, int pathlen)
2131 2131 {
2132 2132 char *path;
2133 2133 int ret;
2134 2134
2135 2135 /*
2136 2136 * copy in the path, including the terminating null
2137 2137 */
2138 2138 pathlen++;
2139 2139 if (pathlen <= 1 || pathlen > MAXPATHLEN)
2140 2140 return (EINVAL);
2141 2141 path = kmem_zalloc(pathlen + 1, KM_SLEEP);
2142 2142 if ((ret = copyinstr(upath, path, pathlen, NULL)) == 0) {
2143 2143 ret = sdev_modctl_devexists(path);
2144 2144 }
2145 2145
2146 2146 kmem_free(path, pathlen + 1);
2147 2147 return (ret);
2148 2148 }
2149 2149
2150 2150 static int
2151 2151 modctl_devreaddir(const char *udir, int udirlen,
2152 2152 char *upaths, int64_t *ulensp)
2153 2153 {
2154 2154 char *paths = NULL;
2155 2155 char **dirlist = NULL;
2156 2156 char *dir;
2157 2157 int64_t ulens;
2158 2158 int64_t lens;
2159 2159 int i, n;
2160 2160 int ret = 0;
2161 2161 char *p;
2162 2162 int npaths;
2163 2163 int npaths_alloc;
2164 2164
2165 2165 /*
2166 2166 * If upaths is NULL then we are only computing the amount of space
2167 2167 * needed to return the paths, with the value returned in *ulensp. If we
2168 2168 * are copying out paths then we get the amount of space allocated by
2169 2169 * the caller. If the actual space needed for paths is larger, or
2170 2170 * things are changing out from under us, then we return EAGAIN.
2171 2171 */
2172 2172 if (upaths) {
2173 2173 if (ulensp == NULL)
2174 2174 return (EINVAL);
2175 2175 if (copyin(ulensp, &ulens, sizeof (ulens)) != 0)
2176 2176 return (EFAULT);
2177 2177 }
2178 2178
2179 2179 /*
2180 2180 * copyin the /dev path including terminating null
2181 2181 */
2182 2182 udirlen++;
2183 2183 if (udirlen <= 1 || udirlen > MAXPATHLEN)
2184 2184 return (EINVAL);
2185 2185 dir = kmem_zalloc(udirlen + 1, KM_SLEEP);
2186 2186 if ((ret = copyinstr(udir, dir, udirlen, NULL)) != 0)
2187 2187 goto err;
2188 2188
2189 2189 if ((ret = sdev_modctl_readdir(dir, &dirlist,
2190 2190 &npaths, &npaths_alloc, 0)) != 0) {
2191 2191 ASSERT(dirlist == NULL);
2192 2192 goto err;
2193 2193 }
2194 2194
2195 2195 lens = 0;
2196 2196 for (i = 0; i < npaths; i++) {
2197 2197 lens += strlen(dirlist[i]) + 1;
2198 2198 }
2199 2199 lens++; /* add one for double termination */
2200 2200
2201 2201 if (upaths) {
2202 2202 if (lens > ulens) {
2203 2203 ret = EAGAIN;
2204 2204 goto out;
2205 2205 }
2206 2206
2207 2207 paths = kmem_alloc(lens, KM_SLEEP);
2208 2208
2209 2209 p = paths;
2210 2210 for (i = 0; i < npaths; i++) {
2211 2211 n = strlen(dirlist[i]) + 1;
2212 2212 bcopy(dirlist[i], p, n);
2213 2213 p += n;
2214 2214 }
2215 2215 *p = 0;
2216 2216
2217 2217 if (copyout(paths, upaths, lens)) {
2218 2218 ret = EFAULT;
2219 2219 goto err;
2220 2220 }
2221 2221 }
2222 2222
2223 2223 out:
2224 2224 /* copy out the amount of space needed to hold the paths */
2225 2225 if (copyout(&lens, ulensp, sizeof (lens)))
2226 2226 ret = EFAULT;
2227 2227
2228 2228 err:
2229 2229 if (dirlist)
2230 2230 sdev_modctl_readdir_free(dirlist, npaths, npaths_alloc);
2231 2231 if (paths)
2232 2232 kmem_free(paths, lens);
2233 2233 kmem_free(dir, udirlen + 1);
2234 2234 return (ret);
2235 2235 }
2236 2236
2237 2237 static int
2238 2238 modctl_devemptydir(const char *udir, int udirlen, int *uempty)
2239 2239 {
2240 2240 char *dir;
2241 2241 int ret;
2242 2242 char **dirlist = NULL;
2243 2243 int npaths;
2244 2244 int npaths_alloc;
2245 2245 int empty;
2246 2246
2247 2247 /*
2248 2248 * copyin the /dev path including terminating null
2249 2249 */
2250 2250 udirlen++;
2251 2251 if (udirlen <= 1 || udirlen > MAXPATHLEN)
2252 2252 return (EINVAL);
2253 2253 dir = kmem_zalloc(udirlen + 1, KM_SLEEP);
2254 2254 if ((ret = copyinstr(udir, dir, udirlen, NULL)) != 0)
2255 2255 goto err;
2256 2256
2257 2257 if ((ret = sdev_modctl_readdir(dir, &dirlist,
2258 2258 &npaths, &npaths_alloc, 1)) != 0) {
2259 2259 goto err;
2260 2260 }
2261 2261
2262 2262 empty = npaths ? 0 : 1;
2263 2263 if (copyout(&empty, uempty, sizeof (empty)))
2264 2264 ret = EFAULT;
2265 2265
2266 2266 err:
2267 2267 if (dirlist)
2268 2268 sdev_modctl_readdir_free(dirlist, npaths, npaths_alloc);
2269 2269 kmem_free(dir, udirlen + 1);
2270 2270 return (ret);
2271 2271 }
2272 2272
2273 2273 static int
2274 2274 modctl_hp(int subcmd, const char *path, char *cn_name, uintptr_t arg,
2275 2275 uintptr_t rval)
2276 2276 {
2277 2277 int error = 0;
2278 2278 size_t pathsz, namesz;
2279 2279 char *devpath, *cn_name_str;
2280 2280
2281 2281 if (path == NULL)
2282 2282 return (EINVAL);
2283 2283
2284 2284 devpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2285 2285 error = copyinstr(path, devpath, MAXPATHLEN, &pathsz);
2286 2286 if (error != 0) {
2287 2287 kmem_free(devpath, MAXPATHLEN);
2288 2288 return (EFAULT);
2289 2289 }
2290 2290
2291 2291 cn_name_str = kmem_zalloc(MAXNAMELEN, KM_SLEEP);
2292 2292 error = copyinstr(cn_name, cn_name_str, MAXNAMELEN, &namesz);
2293 2293 if (error != 0) {
2294 2294 kmem_free(devpath, MAXPATHLEN);
2295 2295 kmem_free(cn_name_str, MAXNAMELEN);
2296 2296
2297 2297 return (EFAULT);
2298 2298 }
2299 2299
2300 2300 switch (subcmd) {
2301 2301 case MODHPOPS_CHANGE_STATE:
2302 2302 error = ddihp_modctl(DDI_HPOP_CN_CHANGE_STATE, devpath,
2303 2303 cn_name_str, arg, NULL);
2304 2304 break;
2305 2305 case MODHPOPS_CREATE_PORT:
2306 2306 /* Create an empty PORT */
2307 2307 error = ddihp_modctl(DDI_HPOP_CN_CREATE_PORT, devpath,
2308 2308 cn_name_str, NULL, NULL);
2309 2309 break;
2310 2310 case MODHPOPS_REMOVE_PORT:
2311 2311 /* Remove an empty PORT */
2312 2312 error = ddihp_modctl(DDI_HPOP_CN_REMOVE_PORT, devpath,
2313 2313 cn_name_str, NULL, NULL);
2314 2314 break;
2315 2315 case MODHPOPS_BUS_GET:
2316 2316 error = ddihp_modctl(DDI_HPOP_CN_GET_PROPERTY, devpath,
2317 2317 cn_name_str, arg, rval);
2318 2318 break;
2319 2319 case MODHPOPS_BUS_SET:
2320 2320 error = ddihp_modctl(DDI_HPOP_CN_SET_PROPERTY, devpath,
2321 2321 cn_name_str, arg, rval);
2322 2322 break;
2323 2323 default:
2324 2324 error = ENOTSUP;
2325 2325 break;
2326 2326 }
2327 2327
2328 2328 kmem_free(devpath, MAXPATHLEN);
2329 2329 kmem_free(cn_name_str, MAXNAMELEN);
2330 2330
2331 2331 return (error);
2332 2332 }
2333 2333
2334 2334 int
2335 2335 modctl_moddevname(int subcmd, uintptr_t a1, uintptr_t a2)
2336 2336 {
2337 2337 int error = 0;
2338 2338
2339 2339 switch (subcmd) {
2340 2340 case MODDEVNAME_LOOKUPDOOR:
2341 2341 error = devname_filename_register((char *)a1);
2342 2342 break;
2343 2343 case MODDEVNAME_PROFILE:
2344 2344 error = devname_profile_update((char *)a1, (size_t)a2);
2345 2345 break;
2346 2346 case MODDEVNAME_RECONFIG:
2347 2347 i_ddi_set_reconfig();
2348 2348 break;
2349 2349 case MODDEVNAME_SYSAVAIL:
2350 2350 i_ddi_set_sysavail();
2351 2351 break;
2352 2352 default:
2353 2353 error = EINVAL;
2354 2354 break;
2355 2355 }
2356 2356
2357 2357 return (error);
2358 2358 }
2359 2359
2360 2360 /*ARGSUSED5*/
2361 2361 int
2362 2362 modctl(int cmd, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4,
2363 2363 uintptr_t a5)
2364 2364 {
2365 2365 int error = EINVAL;
2366 2366 dev_t dev;
2367 2367
2368 2368 if (secpolicy_modctl(CRED(), cmd) != 0)
2369 2369 return (set_errno(EPERM));
2370 2370
2371 2371 switch (cmd) {
2372 2372 case MODLOAD: /* load a module */
2373 2373 error = modctl_modload((int)a1, (char *)a2, (int *)a3);
2374 2374 break;
2375 2375
2376 2376 case MODUNLOAD: /* unload a module */
2377 2377 error = modctl_modunload((modid_t)a1);
2378 2378 break;
2379 2379
2380 2380 case MODINFO: /* get module status */
2381 2381 error = modctl_modinfo((modid_t)a1, (struct modinfo *)a2);
2382 2382 break;
2383 2383
2384 2384 case MODRESERVED: /* get last major number in range */
2385 2385 error = modctl_modreserve((modid_t)a1, (int *)a2);
2386 2386 break;
2387 2387
2388 2388 case MODSETMINIROOT: /* we are running in miniroot */
2389 2389 isminiroot = 1;
2390 2390 error = 0;
2391 2391 break;
2392 2392
2393 2393 case MODADDMAJBIND: /* add major / driver alias bindings */
2394 2394 error = modctl_add_driver_aliases((int *)a2);
2395 2395 break;
2396 2396
2397 2397 case MODGETPATHLEN: /* get modpath length */
2398 2398 error = modctl_getmodpathlen((int *)a2);
2399 2399 break;
2400 2400
2401 2401 case MODGETPATH: /* get modpath */
2402 2402 error = modctl_getmodpath((char *)a2);
2403 2403 break;
2404 2404
2405 2405 case MODREADSYSBIND: /* read system call binding file */
2406 2406 error = modctl_read_sysbinding_file();
2407 2407 break;
2408 2408
2409 2409 case MODGETMAJBIND: /* get major number for named device */
2410 2410 error = modctl_getmaj((char *)a1, (uint_t)a2, (int *)a3);
2411 2411 break;
2412 2412
2413 2413 case MODGETNAME: /* get name of device given major number */
2414 2414 error = modctl_getname((char *)a1, (uint_t)a2, (int *)a3);
2415 2415 break;
2416 2416
2417 2417 case MODDEVT2INSTANCE:
2418 2418 if (get_udatamodel() == DATAMODEL_NATIVE) {
2419 2419 dev = (dev_t)a1;
2420 2420 }
2421 2421 #ifdef _SYSCALL32_IMPL
2422 2422 else {
2423 2423 dev = expldev(a1);
2424 2424 }
2425 2425 #endif
2426 2426 error = modctl_devt2instance(dev, (int *)a2);
2427 2427 break;
2428 2428
2429 2429 case MODSIZEOF_DEVID: /* sizeof device id of device given dev_t */
2430 2430 if (get_udatamodel() == DATAMODEL_NATIVE) {
2431 2431 dev = (dev_t)a1;
2432 2432 }
2433 2433 #ifdef _SYSCALL32_IMPL
2434 2434 else {
2435 2435 dev = expldev(a1);
2436 2436 }
2437 2437 #endif
2438 2438 error = modctl_sizeof_devid(dev, (uint_t *)a2);
2439 2439 break;
2440 2440
2441 2441 case MODGETDEVID: /* get device id of device given dev_t */
2442 2442 if (get_udatamodel() == DATAMODEL_NATIVE) {
2443 2443 dev = (dev_t)a1;
2444 2444 }
2445 2445 #ifdef _SYSCALL32_IMPL
2446 2446 else {
2447 2447 dev = expldev(a1);
2448 2448 }
2449 2449 #endif
2450 2450 error = modctl_get_devid(dev, (uint_t)a2, (ddi_devid_t)a3);
2451 2451 break;
2452 2452
2453 2453 case MODSIZEOF_MINORNAME: /* sizeof minor nm (dev_t,spectype) */
2454 2454 if (get_udatamodel() == DATAMODEL_NATIVE) {
2455 2455 error = modctl_sizeof_minorname((dev_t)a1, (int)a2,
2456 2456 (uint_t *)a3);
2457 2457 }
2458 2458 #ifdef _SYSCALL32_IMPL
2459 2459 else {
2460 2460 error = modctl_sizeof_minorname(expldev(a1), (int)a2,
2461 2461 (uint_t *)a3);
2462 2462 }
2463 2463
2464 2464 #endif
2465 2465 break;
2466 2466
2467 2467 case MODGETMINORNAME: /* get minor name of (dev_t,spectype) */
2468 2468 if (get_udatamodel() == DATAMODEL_NATIVE) {
2469 2469 error = modctl_get_minorname((dev_t)a1, (int)a2,
2470 2470 (uint_t)a3, (char *)a4);
2471 2471 }
2472 2472 #ifdef _SYSCALL32_IMPL
2473 2473 else {
2474 2474 error = modctl_get_minorname(expldev(a1), (int)a2,
2475 2475 (uint_t)a3, (char *)a4);
2476 2476 }
2477 2477 #endif
2478 2478 break;
2479 2479
2480 2480 case MODGETDEVFSPATH_LEN: /* sizeof path nm of (dev_t,spectype) */
2481 2481 if (get_udatamodel() == DATAMODEL_NATIVE) {
2482 2482 error = modctl_devfspath_len((dev_t)a1, (int)a2,
2483 2483 (uint_t *)a3);
2484 2484 }
2485 2485 #ifdef _SYSCALL32_IMPL
2486 2486 else {
2487 2487 error = modctl_devfspath_len(expldev(a1), (int)a2,
2488 2488 (uint_t *)a3);
2489 2489 }
2490 2490
2491 2491 #endif
2492 2492 break;
2493 2493
2494 2494 case MODGETDEVFSPATH: /* get path name of (dev_t,spec) type */
2495 2495 if (get_udatamodel() == DATAMODEL_NATIVE) {
2496 2496 error = modctl_devfspath((dev_t)a1, (int)a2,
2497 2497 (uint_t)a3, (char *)a4);
2498 2498 }
2499 2499 #ifdef _SYSCALL32_IMPL
2500 2500 else {
2501 2501 error = modctl_devfspath(expldev(a1), (int)a2,
2502 2502 (uint_t)a3, (char *)a4);
2503 2503 }
2504 2504 #endif
2505 2505 break;
2506 2506
2507 2507 case MODGETDEVFSPATH_MI_LEN: /* sizeof path nm of (major,instance) */
2508 2508 error = modctl_devfspath_mi_len((major_t)a1, (int)a2,
2509 2509 (uint_t *)a3);
2510 2510 break;
2511 2511
2512 2512 case MODGETDEVFSPATH_MI: /* get path name of (major,instance) */
2513 2513 error = modctl_devfspath_mi((major_t)a1, (int)a2,
2514 2514 (uint_t)a3, (char *)a4);
2515 2515 break;
2516 2516
2517 2517
2518 2518 case MODEVENTS:
2519 2519 error = modctl_modevents((int)a1, a2, a3, a4, (uint_t)a5);
2520 2520 break;
2521 2521
2522 2522 case MODGETFBNAME: /* get the framebuffer name */
2523 2523 error = modctl_get_fbname((char *)a1);
2524 2524 break;
2525 2525
2526 2526 case MODREREADDACF: /* reread dacf rule database from given file */
2527 2527 error = modctl_reread_dacf((char *)a1);
2528 2528 break;
2529 2529
2530 2530 case MODLOADDRVCONF: /* load driver.conf file for major */
2531 2531 error = modctl_load_drvconf((major_t)a1, (int)a2);
2532 2532 break;
2533 2533
2534 2534 case MODUNLOADDRVCONF: /* unload driver.conf file for major */
2535 2535 error = modctl_unload_drvconf((major_t)a1);
2536 2536 break;
2537 2537
2538 2538 case MODREMMAJBIND: /* remove a major binding */
2539 2539 error = modctl_rem_major((major_t)a1);
2540 2540 break;
2541 2541
2542 2542 case MODREMDRVALIAS: /* remove a major/alias binding */
2543 2543 error = modctl_remove_driver_aliases((int *)a2);
2544 2544 break;
2545 2545
2546 2546 case MODDEVID2PATHS: /* get paths given devid */
2547 2547 error = modctl_devid2paths((ddi_devid_t)a1, (char *)a2,
2548 2548 (uint_t)a3, (size_t *)a4, (char *)a5);
2549 2549 break;
2550 2550
2551 2551 case MODSETDEVPOLICY: /* establish device policy */
2552 2552 error = devpolicy_load((int)a1, (size_t)a2, (devplcysys_t *)a3);
2553 2553 break;
2554 2554
2555 2555 case MODGETDEVPOLICY: /* get device policy */
2556 2556 error = devpolicy_get((int *)a1, (size_t)a2,
2557 2557 (devplcysys_t *)a3);
2558 2558 break;
2559 2559
2560 2560 case MODALLOCPRIV:
2561 2561 error = modctl_allocpriv((const char *)a1);
2562 2562 break;
2563 2563
2564 2564 case MODGETDEVPOLICYBYNAME:
2565 2565 error = devpolicy_getbyname((size_t)a1,
2566 2566 (devplcysys_t *)a2, (char *)a3);
2567 2567 break;
2568 2568
2569 2569 case MODLOADMINORPERM:
2570 2570 case MODADDMINORPERM:
2571 2571 case MODREMMINORPERM:
2572 2572 error = modctl_minorperm(cmd, (char *)a1, (size_t)a2);
2573 2573 break;
2574 2574
2575 2575 case MODREMDRVCLEANUP:
2576 2576 error = modctl_remdrv_cleanup((const char *)a1);
2577 2577 break;
2578 2578
2579 2579 case MODDEVEXISTS: /* non-reconfiguring /dev lookup */
2580 2580 error = modctl_devexists((const char *)a1, (size_t)a2);
2581 2581 break;
2582 2582
2583 2583 case MODDEVREADDIR: /* non-reconfiguring /dev readdir */
2584 2584 error = modctl_devreaddir((const char *)a1, (size_t)a2,
2585 2585 (char *)a3, (int64_t *)a4);
2586 2586 break;
2587 2587
2588 2588 case MODDEVEMPTYDIR: /* non-reconfiguring /dev emptydir */
2589 2589 error = modctl_devemptydir((const char *)a1, (size_t)a2,
2590 2590 (int *)a3);
2591 2591 break;
2592 2592
2593 2593 case MODDEVNAME:
2594 2594 error = modctl_moddevname((int)a1, a2, a3);
2595 2595 break;
2596 2596
2597 2597 case MODRETIRE: /* retire device named by physpath a1 */
2598 2598 error = modctl_retire((char *)a1, (char *)a2, (size_t)a3);
2599 2599 break;
2600 2600
2601 2601 case MODISRETIRED: /* check if a device is retired. */
2602 2602 error = modctl_is_retired((char *)a1, (int *)a2);
2603 2603 break;
2604 2604
2605 2605 case MODUNRETIRE: /* unretire device named by physpath a1 */
2606 2606 error = modctl_unretire((char *)a1);
2607 2607 break;
2608 2608
2609 2609 case MODHPOPS: /* hotplug operations */
2610 2610 /* device named by physpath a2 and Connection name a3 */
2611 2611 error = modctl_hp((int)a1, (char *)a2, (char *)a3, a4, a5);
2612 2612 break;
2613 2613
2614 2614 default:
2615 2615 error = EINVAL;
2616 2616 break;
2617 2617 }
2618 2618
2619 2619 return (error ? set_errno(error) : 0);
2620 2620 }
2621 2621
2622 2622 /*
2623 2623 * Calls to kobj_load_module()() are handled off to this routine in a
2624 2624 * separate thread.
2625 2625 */
2626 2626 static void
2627 2627 modload_thread(struct loadmt *ltp)
2628 2628 {
2629 2629 /* load the module and signal the creator of this thread */
2630 2630 kmutex_t cpr_lk;
2631 2631 callb_cpr_t cpr_i;
2632 2632
2633 2633 mutex_init(&cpr_lk, NULL, MUTEX_DEFAULT, NULL);
2634 2634 CALLB_CPR_INIT(&cpr_i, &cpr_lk, callb_generic_cpr, "modload");
2635 2635 /* borrow the devi lock from thread which invoked us */
2636 2636 pm_borrow_lock(ltp->owner);
2637 2637 ltp->retval = kobj_load_module(ltp->mp, ltp->usepath);
2638 2638 pm_return_lock();
2639 2639 sema_v(<p->sema);
2640 2640 mutex_enter(&cpr_lk);
2641 2641 CALLB_CPR_EXIT(&cpr_i);
2642 2642 mutex_destroy(&cpr_lk);
2643 2643 thread_exit();
2644 2644 }
2645 2645
2646 2646 /*
2647 2647 * load a module, adding a reference if caller specifies rmodp. If rmodp
2648 2648 * is specified then an errno is returned, otherwise a module index is
2649 2649 * returned (-1 on error).
2650 2650 */
2651 2651 static int
2652 2652 modrload(const char *subdir, const char *filename, struct modctl **rmodp)
2653 2653 {
2654 2654 struct modctl *modp;
2655 2655 size_t size;
2656 2656 char *fullname;
2657 2657 int retval = EINVAL;
2658 2658 int id = -1;
2659 2659
2660 2660 if (rmodp)
2661 2661 *rmodp = NULL; /* avoid garbage */
2662 2662
2663 2663 if (subdir != NULL) {
2664 2664 /*
2665 2665 * refuse / in filename to prevent "../" escapes.
2666 2666 */
2667 2667 if (strchr(filename, '/') != NULL)
2668 2668 return (rmodp ? retval : id);
2669 2669
2670 2670 /*
2671 2671 * allocate enough space for <subdir>/<filename><NULL>
2672 2672 */
2673 2673 size = strlen(subdir) + strlen(filename) + 2;
2674 2674 fullname = kmem_zalloc(size, KM_SLEEP);
2675 2675 (void) sprintf(fullname, "%s/%s", subdir, filename);
2676 2676 } else {
2677 2677 fullname = (char *)filename;
2678 2678 }
2679 2679
2680 2680 modp = mod_hold_installed_mod(fullname, 1, 0, &retval);
2681 2681 if (modp != NULL) {
2682 2682 id = modp->mod_id;
2683 2683 if (rmodp) {
2684 2684 /* add mod_ref and return *rmodp */
2685 2685 mutex_enter(&mod_lock);
2686 2686 modp->mod_ref++;
2687 2687 mutex_exit(&mod_lock);
2688 2688 *rmodp = modp;
2689 2689 }
2690 2690 mod_release_mod(modp);
2691 2691 CPU_STATS_ADDQ(CPU, sys, modload, 1);
2692 2692 }
2693 2693
2694 2694 done: if (subdir != NULL)
2695 2695 kmem_free(fullname, size);
2696 2696 return (rmodp ? retval : id);
2697 2697 }
2698 2698
2699 2699 /*
2700 2700 * This is the primary kernel interface to load a module. It loads and
2701 2701 * installs the named module. It does not hold mod_ref of the module, so
2702 2702 * a module unload attempt can occur at any time - it is up to the
2703 2703 * _fini/mod_remove implementation to determine if unload will succeed.
2704 2704 */
2705 2705 int
2706 2706 modload(const char *subdir, const char *filename)
2707 2707 {
2708 2708 return (modrload(subdir, filename, NULL));
2709 2709 }
2710 2710
2711 2711 /*
2712 2712 * Load a module using a series of qualified names from most specific to least
2713 2713 * specific, e.g. for subdir "foo", p1 "bar", p2 "baz", we might try:
2714 2714 * Value returned in *chosen
2715 2715 * foo/bar.baz.1.2.3 3
2716 2716 * foo/bar.baz.1.2 2
2717 2717 * foo/bar.baz.1 1
2718 2718 * foo/bar.baz 0
2719 2719 *
2720 2720 * Return the module ID on success; -1 if no module was loaded. On success
2721 2721 * and if 'chosen' is not NULL we also return the number of suffices that
2722 2722 * were in the module we chose to load.
2723 2723 */
2724 2724 int
2725 2725 modload_qualified(const char *subdir, const char *p1,
2726 2726 const char *p2, const char *delim, uint_t suffv[], int suffc, int *chosen)
2727 2727 {
2728 2728 char path[MOD_MAXPATH];
2729 2729 size_t n, resid = sizeof (path);
2730 2730 char *p = path;
2731 2731
2732 2732 char **dotv;
2733 2733 int i, rc, id;
2734 2734 modctl_t *mp;
2735 2735
2736 2736 if (p2 != NULL)
2737 2737 n = snprintf(p, resid, "%s/%s%s%s", subdir, p1, delim, p2);
2738 2738 else
2739 2739 n = snprintf(p, resid, "%s/%s", subdir, p1);
2740 2740
2741 2741 if (n >= resid)
2742 2742 return (-1);
2743 2743
2744 2744 p += n;
2745 2745 resid -= n;
2746 2746 dotv = kmem_alloc(sizeof (char *) * (suffc + 1), KM_SLEEP);
2747 2747
2748 2748 for (i = 0; i < suffc; i++) {
2749 2749 dotv[i] = p;
2750 2750 n = snprintf(p, resid, "%s%u", delim, suffv[i]);
2751 2751
2752 2752 if (n >= resid) {
2753 2753 kmem_free(dotv, sizeof (char *) * (suffc + 1));
2754 2754 return (-1);
2755 2755 }
2756 2756
2757 2757 p += n;
2758 2758 resid -= n;
2759 2759 }
2760 2760
2761 2761 dotv[suffc] = p;
2762 2762
2763 2763 for (i = suffc; i >= 0; i--) {
2764 2764 dotv[i][0] = '\0';
2765 2765 mp = mod_hold_installed_mod(path, 1, 1, &rc);
2766 2766
2767 2767 if (mp != NULL) {
2768 2768 kmem_free(dotv, sizeof (char *) * (suffc + 1));
2769 2769 id = mp->mod_id;
2770 2770 mod_release_mod(mp);
2771 2771 if (chosen != NULL)
2772 2772 *chosen = i;
2773 2773 return (id);
2774 2774 }
2775 2775 }
2776 2776
2777 2777 kmem_free(dotv, sizeof (char *) * (suffc + 1));
2778 2778 return (-1);
2779 2779 }
2780 2780
2781 2781 /*
2782 2782 * Load a module.
2783 2783 */
2784 2784 int
2785 2785 modloadonly(const char *subdir, const char *filename)
2786 2786 {
2787 2787 struct modctl *modp;
2788 2788 char *fullname;
2789 2789 size_t size;
2790 2790 int id, retval;
2791 2791
2792 2792 if (subdir != NULL) {
2793 2793 /*
2794 2794 * allocate enough space for <subdir>/<filename><NULL>
2795 2795 */
2796 2796 size = strlen(subdir) + strlen(filename) + 2;
2797 2797 fullname = kmem_zalloc(size, KM_SLEEP);
2798 2798 (void) sprintf(fullname, "%s/%s", subdir, filename);
2799 2799 } else {
2800 2800 fullname = (char *)filename;
2801 2801 }
2802 2802
2803 2803 modp = mod_hold_loaded_mod(NULL, fullname, &retval);
2804 2804 if (modp) {
2805 2805 id = modp->mod_id;
2806 2806 mod_release_mod(modp);
2807 2807 }
2808 2808
2809 2809 if (subdir != NULL)
2810 2810 kmem_free(fullname, size);
2811 2811
2812 2812 if (retval == 0)
2813 2813 return (id);
2814 2814 return (-1);
2815 2815 }
2816 2816
2817 2817 /*
2818 2818 * Try to uninstall and unload a module, removing a reference if caller
2819 2819 * specifies rmodp.
2820 2820 */
2821 2821 static int
2822 2822 modunrload(modid_t id, struct modctl **rmodp, int unload)
2823 2823 {
2824 2824 struct modctl *modp;
2825 2825 int retval;
2826 2826
2827 2827 if (rmodp)
2828 2828 *rmodp = NULL; /* avoid garbage */
2829 2829
2830 2830 if ((modp = mod_hold_by_id((modid_t)id)) == NULL)
2831 2831 return (EINVAL);
2832 2832
2833 2833 if (rmodp) {
2834 2834 mutex_enter(&mod_lock);
2835 2835 modp->mod_ref--;
2836 2836 if (modp->mod_ref == 0)
2837 2837 mod_uninstall_ref_zero++;
2838 2838 mutex_exit(&mod_lock);
2839 2839 *rmodp = modp;
2840 2840 }
2841 2841
2842 2842 if (unload) {
2843 2843 retval = moduninstall(modp);
2844 2844 if (retval == 0) {
2845 2845 mod_unload(modp);
2846 2846 CPU_STATS_ADDQ(CPU, sys, modunload, 1);
2847 2847 } else if (retval == EALREADY)
2848 2848 retval = 0; /* already unloaded, not an error */
2849 2849 } else
2850 2850 retval = 0;
2851 2851
2852 2852 mod_release_mod(modp);
2853 2853 return (retval);
2854 2854 }
2855 2855
2856 2856 /*
2857 2857 * Uninstall and unload a module.
2858 2858 */
2859 2859 int
2860 2860 modunload(modid_t id)
2861 2861 {
2862 2862 int retval;
2863 2863
2864 2864 /* synchronize with any active modunload_disable() */
2865 2865 modunload_begin();
2866 2866 if (ddi_root_node())
2867 2867 (void) devfs_clean(ddi_root_node(), NULL, 0);
2868 2868 retval = modunrload(id, NULL, 1);
2869 2869 modunload_end();
2870 2870 return (retval);
2871 2871 }
2872 2872
2873 2873 /*
2874 2874 * Return status of a loaded module.
2875 2875 */
2876 2876 static int
2877 2877 modinfo(modid_t id, struct modinfo *modinfop)
2878 2878 {
2879 2879 struct modctl *modp;
2880 2880 modid_t mid;
2881 2881 int i;
2882 2882
2883 2883 mid = modinfop->mi_id;
2884 2884 if (modinfop->mi_info & MI_INFO_ALL) {
2885 2885 while ((modp = mod_hold_next_by_id(mid++)) != NULL) {
2886 2886 if ((modinfop->mi_info & MI_INFO_CNT) ||
2887 2887 modp->mod_installed)
2888 2888 break;
2889 2889 mod_release_mod(modp);
2890 2890 }
2891 2891 if (modp == NULL)
2892 2892 return (EINVAL);
2893 2893 } else {
2894 2894 modp = mod_hold_by_id(id);
2895 2895 if (modp == NULL)
2896 2896 return (EINVAL);
2897 2897 if (!(modinfop->mi_info & MI_INFO_CNT) &&
2898 2898 (modp->mod_installed == 0)) {
2899 2899 mod_release_mod(modp);
2900 2900 return (EINVAL);
2901 2901 }
2902 2902 }
2903 2903
2904 2904 modinfop->mi_rev = 0;
2905 2905 modinfop->mi_state = 0;
2906 2906 for (i = 0; i < MODMAXLINK; i++) {
2907 2907 modinfop->mi_msinfo[i].msi_p0 = -1;
2908 2908 modinfop->mi_msinfo[i].msi_linkinfo[0] = 0;
2909 2909 }
2910 2910 if (modp->mod_loaded) {
2911 2911 modinfop->mi_state = MI_LOADED;
2912 2912 kobj_getmodinfo(modp->mod_mp, modinfop);
2913 2913 }
2914 2914 if (modp->mod_installed) {
2915 2915 modinfop->mi_state |= MI_INSTALLED;
2916 2916
2917 2917 (void) mod_getinfo(modp, modinfop);
2918 2918 }
2919 2919
2920 2920 modinfop->mi_id = modp->mod_id;
2921 2921 modinfop->mi_loadcnt = modp->mod_loadcnt;
2922 2922 (void) strcpy(modinfop->mi_name, modp->mod_modname);
2923 2923
2924 2924 mod_release_mod(modp);
2925 2925 return (0);
2926 2926 }
2927 2927
2928 2928 static char mod_stub_err[] = "mod_hold_stub: Couldn't load stub module %s";
2929 2929 static char no_err[] = "No error function for weak stub %s";
2930 2930
2931 2931 /*
2932 2932 * used by the stubs themselves to load and hold a module.
2933 2933 * Returns 0 if the module is successfully held;
2934 2934 * the stub needs to call mod_release_stub().
2935 2935 * -1 if the stub should just call the err_fcn.
2936 2936 * Note that this code is stretched out so that we avoid subroutine calls
2937 2937 * and optimize for the most likely case. That is, the case where the
2938 2938 * module is loaded and installed and not held. In that case we just inc
2939 2939 * the mod_ref count and continue.
2940 2940 */
2941 2941 int
2942 2942 mod_hold_stub(struct mod_stub_info *stub)
2943 2943 {
2944 2944 struct modctl *mp;
2945 2945 struct mod_modinfo *mip;
2946 2946
2947 2947 mip = stub->mods_modinfo;
2948 2948
2949 2949 mutex_enter(&mod_lock);
2950 2950
2951 2951 /* we do mod_hold_by_modctl inline for speed */
2952 2952
2953 2953 mod_check_again:
2954 2954 if ((mp = mip->mp) != NULL) {
2955 2955 if (mp->mod_busy == 0) {
2956 2956 if (mp->mod_installed) {
2957 2957 /* increment the reference count */
2958 2958 mp->mod_ref++;
2959 2959 ASSERT(mp->mod_ref && mp->mod_installed);
2960 2960 mutex_exit(&mod_lock);
2961 2961 return (0);
2962 2962 } else {
2963 2963 mp->mod_busy = 1;
2964 2964 mp->mod_inprogress_thread =
2965 2965 (curthread == NULL ?
2966 2966 (kthread_id_t)-1 : curthread);
2967 2967 }
2968 2968 } else {
2969 2969 /*
2970 2970 * wait one time and then go see if someone
2971 2971 * else has resolved the stub (set mip->mp).
2972 2972 */
2973 2973 if (mod_hold_by_modctl(mp,
2974 2974 MOD_WAIT_ONCE | MOD_LOCK_HELD))
2975 2975 goto mod_check_again;
2976 2976
2977 2977 /*
2978 2978 * what we have now may have been unloaded!, in
2979 2979 * that case, mip->mp will be NULL, we'll hit this
2980 2980 * module and load again..
2981 2981 */
2982 2982 cmn_err(CE_PANIC, "mod_hold_stub should have blocked");
2983 2983 }
2984 2984 mutex_exit(&mod_lock);
2985 2985 } else {
2986 2986 /* first time we've hit this module */
2987 2987 mutex_exit(&mod_lock);
2988 2988 mp = mod_hold_by_name(mip->modm_module_name);
2989 2989 mip->mp = mp;
2990 2990 }
2991 2991
2992 2992 /*
2993 2993 * If we are here, it means that the following conditions
2994 2994 * are satisfied.
2995 2995 *
2996 2996 * mip->mp != NULL
2997 2997 * this thread has set the mp->mod_busy = 1
2998 2998 * mp->mod_installed = 0
2999 2999 *
3000 3000 */
3001 3001 ASSERT(mp != NULL);
3002 3002 ASSERT(mp->mod_busy == 1);
3003 3003
3004 3004 if (mp->mod_installed == 0) {
3005 3005 /* Module not loaded, if weak stub don't load it */
3006 3006 if (stub->mods_flag & MODS_WEAK) {
3007 3007 if (stub->mods_errfcn == NULL) {
3008 3008 mod_release_mod(mp);
3009 3009 cmn_err(CE_PANIC, no_err,
3010 3010 mip->modm_module_name);
3011 3011 }
3012 3012 } else {
3013 3013 /* Not a weak stub so load the module */
3014 3014
3015 3015 if (mod_load(mp, 1) != 0 || modinstall(mp) != 0) {
3016 3016 /*
3017 3017 * If mod_load() was successful
3018 3018 * and modinstall() failed, then
3019 3019 * unload the module.
3020 3020 */
3021 3021 if (mp->mod_loaded)
3022 3022 mod_unload(mp);
3023 3023
3024 3024 mod_release_mod(mp);
3025 3025 if (stub->mods_errfcn == NULL) {
3026 3026 cmn_err(CE_PANIC, mod_stub_err,
3027 3027 mip->modm_module_name);
3028 3028 } else {
3029 3029 return (-1);
3030 3030 }
3031 3031 }
3032 3032 }
3033 3033 }
3034 3034
3035 3035 /*
3036 3036 * At this point module is held and loaded. Release
3037 3037 * the mod_busy and mod_inprogress_thread before
3038 3038 * returning. We actually call mod_release() here so
3039 3039 * that if another stub wants to access this module,
3040 3040 * it can do so. mod_ref is incremented before mod_release()
3041 3041 * is called to prevent someone else from snatching the
3042 3042 * module from this thread.
3043 3043 */
3044 3044 mutex_enter(&mod_lock);
3045 3045 mp->mod_ref++;
3046 3046 ASSERT(mp->mod_ref &&
3047 3047 (mp->mod_loaded || (stub->mods_flag & MODS_WEAK)));
3048 3048 mod_release(mp);
3049 3049 mutex_exit(&mod_lock);
3050 3050 return (0);
3051 3051 }
3052 3052
3053 3053 void
3054 3054 mod_release_stub(struct mod_stub_info *stub)
3055 3055 {
3056 3056 struct modctl *mp = stub->mods_modinfo->mp;
3057 3057
3058 3058 /* inline mod_release_mod */
3059 3059 mutex_enter(&mod_lock);
3060 3060 ASSERT(mp->mod_ref &&
3061 3061 (mp->mod_loaded || (stub->mods_flag & MODS_WEAK)));
3062 3062 mp->mod_ref--;
3063 3063 if (mp->mod_ref == 0)
3064 3064 mod_uninstall_ref_zero++;
3065 3065 if (mp->mod_want) {
3066 3066 mp->mod_want = 0;
3067 3067 cv_broadcast(&mod_cv);
3068 3068 }
3069 3069 mutex_exit(&mod_lock);
3070 3070 }
3071 3071
3072 3072 static struct modctl *
3073 3073 mod_hold_loaded_mod(struct modctl *dep, char *filename, int *status)
3074 3074 {
3075 3075 struct modctl *modp;
3076 3076 int retval;
3077 3077
3078 3078 /*
3079 3079 * Hold the module.
3080 3080 */
3081 3081 modp = mod_hold_by_name_requisite(dep, filename);
3082 3082 if (modp) {
3083 3083 retval = mod_load(modp, 1);
3084 3084 if (retval != 0) {
3085 3085 mod_release_mod(modp);
3086 3086 modp = NULL;
3087 3087 }
3088 3088 *status = retval;
3089 3089 } else {
3090 3090 *status = ENOSPC;
3091 3091 }
3092 3092
3093 3093 /*
3094 3094 * if dep is not NULL, clear the module dependency information.
3095 3095 * This information is set in mod_hold_by_name_common().
3096 3096 */
3097 3097 if (dep != NULL && dep->mod_requisite_loading != NULL) {
3098 3098 ASSERT(dep->mod_busy);
3099 3099 dep->mod_requisite_loading = NULL;
3100 3100 }
3101 3101
3102 3102 return (modp);
3103 3103 }
3104 3104
3105 3105 /*
3106 3106 * hold, load, and install the named module
3107 3107 */
3108 3108 static struct modctl *
3109 3109 mod_hold_installed_mod(char *name, int usepath, int forcecheck, int *r)
3110 3110 {
3111 3111 struct modctl *modp;
3112 3112 int retval;
3113 3113
3114 3114 /*
3115 3115 * Verify that that module in question actually exists on disk
3116 3116 * before allocation of module structure by mod_hold_by_name.
3117 3117 */
3118 3118 if (modrootloaded && swaploaded || forcecheck) {
3119 3119 if (!kobj_path_exists(name, usepath)) {
3120 3120 *r = ENOENT;
3121 3121 return (NULL);
3122 3122 }
3123 3123 }
3124 3124
3125 3125 /*
3126 3126 * Hold the module.
3127 3127 */
3128 3128 modp = mod_hold_by_name(name);
3129 3129 if (modp) {
3130 3130 retval = mod_load(modp, usepath);
3131 3131 if (retval != 0) {
3132 3132 mod_release_mod(modp);
3133 3133 modp = NULL;
3134 3134 *r = retval;
3135 3135 } else {
3136 3136 if ((*r = modinstall(modp)) != 0) {
3137 3137 /*
3138 3138 * We loaded it, but failed to _init() it.
3139 3139 * Be kind to developers -- force it
3140 3140 * out of memory now so that the next
3141 3141 * attempt to use the module will cause
3142 3142 * a reload. See 1093793.
3143 3143 */
3144 3144 mod_unload(modp);
3145 3145 mod_release_mod(modp);
3146 3146 modp = NULL;
3147 3147 }
3148 3148 }
3149 3149 } else {
3150 3150 *r = ENOSPC;
3151 3151 }
3152 3152 return (modp);
3153 3153 }
3154 3154
3155 3155 static char mod_excl_msg[] =
3156 3156 "module %s(%s) is EXCLUDED and will not be loaded\n";
3157 3157 static char mod_init_msg[] = "loadmodule:%s(%s): _init() error %d\n";
3158 3158
3159 3159 /*
3160 3160 * This routine is needed for dependencies. Users specify dependencies
3161 3161 * by declaring a character array initialized to filenames of dependents.
3162 3162 * So the code that handles dependents deals with filenames (and not
3163 3163 * module names) because that's all it has. We load by filename and once
3164 3164 * we've loaded a file we can get the module name.
3165 3165 * Unfortunately there isn't a single unified filename/modulename namespace.
3166 3166 * C'est la vie.
3167 3167 *
3168 3168 * We allow the name being looked up to be prepended by an optional
3169 3169 * subdirectory e.g. we can lookup (NULL, "fs/ufs") or ("fs", "ufs")
3170 3170 */
3171 3171 struct modctl *
3172 3172 mod_find_by_filename(char *subdir, char *filename)
3173 3173 {
3174 3174 struct modctl *mp;
3175 3175 size_t sublen;
3176 3176
3177 3177 ASSERT(!MUTEX_HELD(&mod_lock));
3178 3178 if (subdir != NULL)
3179 3179 sublen = strlen(subdir);
3180 3180 else
3181 3181 sublen = 0;
3182 3182
3183 3183 mutex_enter(&mod_lock);
3184 3184 mp = &modules;
3185 3185 do {
3186 3186 if (sublen) {
3187 3187 char *mod_filename = mp->mod_filename;
3188 3188
3189 3189 if (strncmp(subdir, mod_filename, sublen) == 0 &&
3190 3190 mod_filename[sublen] == '/' &&
3191 3191 strcmp(filename, &mod_filename[sublen + 1]) == 0) {
3192 3192 mutex_exit(&mod_lock);
3193 3193 return (mp);
3194 3194 }
3195 3195 } else if (strcmp(filename, mp->mod_filename) == 0) {
3196 3196 mutex_exit(&mod_lock);
3197 3197 return (mp);
3198 3198 }
3199 3199 } while ((mp = mp->mod_next) != &modules);
3200 3200 mutex_exit(&mod_lock);
3201 3201 return (NULL);
3202 3202 }
3203 3203
3204 3204 /*
3205 3205 * Check for circular dependencies. This is called from do_dependents()
3206 3206 * in kobj.c. If we are the thread already loading this module, then
3207 3207 * we're trying to load a dependent that we're already loading which
3208 3208 * means the user specified circular dependencies.
3209 3209 */
3210 3210 static int
3211 3211 mod_circdep(struct modctl *modp)
3212 3212 {
3213 3213 struct modctl *rmod;
3214 3214
3215 3215 ASSERT(MUTEX_HELD(&mod_lock));
3216 3216
3217 3217 /*
3218 3218 * Check the mod_inprogress_thread first.
3219 3219 * mod_inprogress_thread is used in mod_hold_stub()
3220 3220 * directly to improve performance.
3221 3221 */
3222 3222 if (modp->mod_inprogress_thread == curthread)
3223 3223 return (1);
3224 3224
3225 3225 /*
3226 3226 * Check the module circular dependencies.
3227 3227 */
3228 3228 for (rmod = modp; rmod != NULL; rmod = rmod->mod_requisite_loading) {
3229 3229 /*
3230 3230 * Check if there is a module circular dependency.
3231 3231 */
3232 3232 if (rmod->mod_requisite_loading == modp)
3233 3233 return (1);
3234 3234 }
3235 3235 return (0);
3236 3236 }
3237 3237
3238 3238 static int
3239 3239 mod_getinfo(struct modctl *modp, struct modinfo *modinfop)
3240 3240 {
3241 3241 int (*func)(struct modinfo *);
3242 3242 int retval;
3243 3243
3244 3244 ASSERT(modp->mod_busy);
3245 3245
3246 3246 /* primary modules don't do getinfo */
3247 3247 if (modp->mod_prim)
3248 3248 return (0);
3249 3249
3250 3250 func = (int (*)(struct modinfo *))kobj_lookup(modp->mod_mp, "_info");
3251 3251
3252 3252 if (kobj_addrcheck(modp->mod_mp, (caddr_t)func)) {
3253 3253 cmn_err(CE_WARN, "_info() not defined properly in %s",
3254 3254 modp->mod_filename);
3255 3255 /*
3256 3256 * The semantics of mod_info(9F) are that 0 is failure
3257 3257 * and non-zero is success.
3258 3258 */
3259 3259 retval = 0;
3260 3260 } else
3261 3261 retval = (*func)(modinfop); /* call _info() function */
3262 3262
3263 3263 if (moddebug & MODDEBUG_USERDEBUG)
3264 3264 printf("Returned from _info, retval = %x\n", retval);
3265 3265
3266 3266 return (retval);
3267 3267 }
3268 3268
3269 3269 static void
3270 3270 modadd(struct modctl *mp)
3271 3271 {
3272 3272 ASSERT(MUTEX_HELD(&mod_lock));
3273 3273
3274 3274 mp->mod_id = last_module_id++;
3275 3275 mp->mod_next = &modules;
3276 3276 mp->mod_prev = modules.mod_prev;
3277 3277 modules.mod_prev->mod_next = mp;
3278 3278 modules.mod_prev = mp;
3279 3279 }
3280 3280
3281 3281 /*ARGSUSED*/
3282 3282 static struct modctl *
3283 3283 allocate_modp(const char *filename, const char *modname)
3284 3284 {
3285 3285 struct modctl *mp;
3286 3286
3287 3287 mp = kobj_zalloc(sizeof (*mp), KM_SLEEP);
3288 3288 mp->mod_modname = kobj_zalloc(strlen(modname) + 1, KM_SLEEP);
3289 3289 (void) strcpy(mp->mod_modname, modname);
3290 3290 return (mp);
3291 3291 }
3292 3292
3293 3293 /*
3294 3294 * Get the value of a symbol. This is a wrapper routine that
3295 3295 * calls kobj_getsymvalue(). kobj_getsymvalue() may go away but this
3296 3296 * wrapper will prevent callers from noticing.
3297 3297 */
3298 3298 uintptr_t
3299 3299 modgetsymvalue(char *name, int kernelonly)
3300 3300 {
3301 3301 return (kobj_getsymvalue(name, kernelonly));
3302 3302 }
3303 3303
3304 3304 /*
3305 3305 * Get the symbol nearest an address. This is a wrapper routine that
3306 3306 * calls kobj_getsymname(). kobj_getsymname() may go away but this
3307 3307 * wrapper will prevent callers from noticing.
3308 3308 */
3309 3309 char *
3310 3310 modgetsymname(uintptr_t value, ulong_t *offset)
3311 3311 {
3312 3312 return (kobj_getsymname(value, offset));
3313 3313 }
3314 3314
3315 3315 /*
3316 3316 * Lookup a symbol in a specified module. These are wrapper routines that
3317 3317 * call kobj_lookup(). kobj_lookup() may go away but these wrappers will
3318 3318 * prevent callers from noticing.
3319 3319 */
3320 3320 uintptr_t
3321 3321 modlookup(const char *modname, const char *symname)
3322 3322 {
3323 3323 struct modctl *modp;
3324 3324 uintptr_t val;
3325 3325
3326 3326 if ((modp = mod_hold_by_name(modname)) == NULL)
3327 3327 return (0);
3328 3328 val = kobj_lookup(modp->mod_mp, symname);
3329 3329 mod_release_mod(modp);
3330 3330 return (val);
3331 3331 }
3332 3332
3333 3333 uintptr_t
3334 3334 modlookup_by_modctl(modctl_t *modp, const char *symname)
3335 3335 {
3336 3336 ASSERT(modp->mod_ref > 0 || modp->mod_busy);
3337 3337
3338 3338 return (kobj_lookup(modp->mod_mp, symname));
3339 3339 }
3340 3340
3341 3341 /*
3342 3342 * Ask the user for the name of the system file and the default path
3343 3343 * for modules.
↓ open down ↓ |
2096 lines elided |
↑ open up ↑ |
3344 3344 */
3345 3345 void
3346 3346 mod_askparams()
3347 3347 {
3348 3348 static char s0[64];
3349 3349 intptr_t fd;
3350 3350
3351 3351 if ((fd = kobj_open(systemfile)) != -1L)
3352 3352 kobj_close(fd);
3353 3353 else
3354 - systemfile = NULL;
3354 + systemfile = self_assembly = NULL;
3355 3355
3356 3356 /*CONSTANTCONDITION*/
3357 3357 while (1) {
3358 3358 printf("Name of system file [%s]: ",
3359 3359 systemfile ? systemfile : "/dev/null");
3360 3360
3361 3361 console_gets(s0, sizeof (s0));
3362 3362
3363 3363 if (s0[0] == '\0')
3364 3364 break;
3365 3365 else if (strcmp(s0, "/dev/null") == 0) {
3366 - systemfile = NULL;
3366 + systemfile = self_assembly = NULL;
3367 3367 break;
3368 3368 } else {
3369 3369 if ((fd = kobj_open(s0)) != -1L) {
3370 3370 kobj_close(fd);
3371 3371 systemfile = s0;
3372 + self_assembly = NULL;
3372 3373 break;
3373 3374 }
3374 3375 }
3375 3376 printf("can't find file %s\n", s0);
3376 3377 }
3377 3378 }
3378 3379
3379 3380 static char loading_msg[] = "loading '%s' id %d\n";
3380 3381 static char load_msg[] = "load '%s' id %d loaded @ 0x%p/0x%p size %d/%d\n";
3381 3382
3382 3383 /*
3383 3384 * Common code for loading a module (but not installing it).
3384 3385 * Handoff the task of module loading to a separate thread
3385 3386 * with a large stack if possible, since this code may recurse a few times.
3386 3387 * Return zero if there are no errors or an errno value.
3387 3388 */
3388 3389 static int
3389 3390 mod_load(struct modctl *mp, int usepath)
3390 3391 {
3391 3392 int retval;
3392 3393 struct modinfo *modinfop = NULL;
3393 3394 struct loadmt lt;
3394 3395
3395 3396 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3396 3397 ASSERT(mp->mod_busy);
3397 3398
3398 3399 if (mp->mod_loaded)
3399 3400 return (0);
3400 3401
3401 3402 if (mod_sysctl(SYS_CHECK_EXCLUDE, mp->mod_modname) != 0 ||
3402 3403 mod_sysctl(SYS_CHECK_EXCLUDE, mp->mod_filename) != 0) {
3403 3404 if (moddebug & MODDEBUG_LOADMSG) {
3404 3405 printf(mod_excl_msg, mp->mod_filename,
3405 3406 mp->mod_modname);
3406 3407 }
3407 3408 return (ENXIO);
3408 3409 }
3409 3410 if (moddebug & MODDEBUG_LOADMSG2)
3410 3411 printf(loading_msg, mp->mod_filename, mp->mod_id);
3411 3412
3412 3413 if (curthread != &t0) {
3413 3414 lt.mp = mp;
3414 3415 lt.usepath = usepath;
3415 3416 lt.owner = curthread;
3416 3417 sema_init(<.sema, 0, NULL, SEMA_DEFAULT, NULL);
3417 3418
3418 3419 /* create thread to hand of call to */
3419 3420 (void) thread_create(NULL, DEFAULTSTKSZ * 2,
3420 3421 modload_thread, <, 0, &p0, TS_RUN, maxclsyspri);
3421 3422
3422 3423 /* wait for thread to complete kobj_load_module */
3423 3424 sema_p(<.sema);
3424 3425
3425 3426 sema_destroy(<.sema);
3426 3427 retval = lt.retval;
3427 3428 } else
3428 3429 retval = kobj_load_module(mp, usepath);
3429 3430
3430 3431 if (mp->mod_mp) {
3431 3432 ASSERT(retval == 0);
3432 3433 mp->mod_loaded = 1;
3433 3434 mp->mod_loadcnt++;
3434 3435 if (moddebug & MODDEBUG_LOADMSG) {
3435 3436 printf(load_msg, mp->mod_filename, mp->mod_id,
3436 3437 (void *)((struct module *)mp->mod_mp)->text,
3437 3438 (void *)((struct module *)mp->mod_mp)->data,
3438 3439 ((struct module *)mp->mod_mp)->text_size,
3439 3440 ((struct module *)mp->mod_mp)->data_size);
3440 3441 }
3441 3442
3442 3443 /*
3443 3444 * XXX - There should be a better way to get this.
3444 3445 */
3445 3446 modinfop = kmem_zalloc(sizeof (struct modinfo), KM_SLEEP);
3446 3447 modinfop->mi_info = MI_INFO_LINKAGE;
3447 3448 if (mod_getinfo(mp, modinfop) == 0)
3448 3449 mp->mod_linkage = NULL;
3449 3450 else {
3450 3451 mp->mod_linkage = (void *)modinfop->mi_base;
3451 3452 ASSERT(mp->mod_linkage->ml_rev == MODREV_1);
3452 3453 }
3453 3454
3454 3455 /*
3455 3456 * DCS: bootstrapping code. If the driver is loaded
3456 3457 * before root mount, it is assumed that the driver
3457 3458 * may be used before mounting root. In order to
3458 3459 * access mappings of global to local minor no.'s
3459 3460 * during installation/open of the driver, we load
3460 3461 * them into memory here while the BOP_interfaces
3461 3462 * are still up.
3462 3463 */
3463 3464 if ((cluster_bootflags & CLUSTER_BOOTED) && !modrootloaded) {
3464 3465 retval = clboot_modload(mp);
3465 3466 }
3466 3467
3467 3468 kmem_free(modinfop, sizeof (struct modinfo));
3468 3469 (void) mod_sysctl(SYS_SET_MVAR, (void *)mp);
3469 3470 retval = install_stubs_by_name(mp, mp->mod_modname);
3470 3471
3471 3472 /*
3472 3473 * Now that the module is loaded, we need to give DTrace
3473 3474 * a chance to notify its providers. This is done via
3474 3475 * the dtrace_modload function pointer.
3475 3476 */
3476 3477 if (strcmp(mp->mod_modname, "dtrace") != 0) {
3477 3478 struct modctl *dmp = mod_hold_by_name("dtrace");
3478 3479
3479 3480 if (dmp != NULL && dtrace_modload != NULL)
3480 3481 (*dtrace_modload)(mp);
3481 3482
3482 3483 mod_release_mod(dmp);
3483 3484 }
3484 3485
3485 3486 } else {
3486 3487 /*
3487 3488 * If load failed then we need to release any requisites
3488 3489 * that we had established.
3489 3490 */
3490 3491 ASSERT(retval);
3491 3492 mod_release_requisites(mp);
3492 3493
3493 3494 if (moddebug & MODDEBUG_ERRMSG)
3494 3495 printf("error loading '%s', error %d\n",
3495 3496 mp->mod_filename, retval);
3496 3497 }
3497 3498 return (retval);
3498 3499 }
3499 3500
3500 3501 static char unload_msg[] = "unloading %s, module id %d, loadcnt %d.\n";
3501 3502
3502 3503 static void
3503 3504 mod_unload(struct modctl *mp)
3504 3505 {
3505 3506 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3506 3507 ASSERT(mp->mod_busy);
3507 3508 ASSERT((mp->mod_loaded && (mp->mod_installed == 0)) &&
3508 3509 ((mp->mod_prim == 0) && (mp->mod_ref >= 0)));
3509 3510
3510 3511 if (moddebug & MODDEBUG_LOADMSG)
3511 3512 printf(unload_msg, mp->mod_modname,
3512 3513 mp->mod_id, mp->mod_loadcnt);
3513 3514
3514 3515 /*
3515 3516 * If mod_ref is not zero, it means some modules might still refer
3516 3517 * to this module. Then you can't unload this module right now.
3517 3518 * Instead, set 1 to mod_delay_unload to notify the system of
3518 3519 * unloading this module later when it's not required any more.
3519 3520 */
3520 3521 if (mp->mod_ref > 0) {
3521 3522 mp->mod_delay_unload = 1;
3522 3523 if (moddebug & MODDEBUG_LOADMSG2) {
3523 3524 printf("module %s not unloaded,"
3524 3525 " non-zero reference count (%d)",
3525 3526 mp->mod_modname, mp->mod_ref);
3526 3527 }
3527 3528 return;
3528 3529 }
3529 3530
3530 3531 if (((mp->mod_loaded == 0) || mp->mod_installed) ||
3531 3532 (mp->mod_ref || mp->mod_prim)) {
3532 3533 /*
3533 3534 * A DEBUG kernel would ASSERT panic above, the code is broken
3534 3535 * if we get this warning.
3535 3536 */
3536 3537 cmn_err(CE_WARN, "mod_unload: %s in incorrect state: %d %d %d",
3537 3538 mp->mod_filename, mp->mod_installed, mp->mod_loaded,
3538 3539 mp->mod_ref);
3539 3540 return;
3540 3541 }
3541 3542
3542 3543 /* reset stub functions to call the binder again */
3543 3544 reset_stubs(mp);
3544 3545
3545 3546 /*
3546 3547 * mark module as unloaded before the modctl structure is freed.
3547 3548 * This is required not to reuse the modctl structure before
3548 3549 * the module is marked as unloaded.
3549 3550 */
3550 3551 mp->mod_loaded = 0;
3551 3552 mp->mod_linkage = NULL;
3552 3553
3553 3554 /* free the memory */
3554 3555 kobj_unload_module(mp);
3555 3556
3556 3557 if (mp->mod_delay_unload) {
3557 3558 mp->mod_delay_unload = 0;
3558 3559 if (moddebug & MODDEBUG_LOADMSG2) {
3559 3560 printf("deferred unload of module %s"
3560 3561 " (id %d) successful",
3561 3562 mp->mod_modname, mp->mod_id);
3562 3563 }
3563 3564 }
3564 3565
3565 3566 /* release hold on requisites */
3566 3567 mod_release_requisites(mp);
3567 3568
3568 3569 /*
3569 3570 * Now that the module is gone, we need to give DTrace a chance to
3570 3571 * remove any probes that it may have had in the module. This is
3571 3572 * done via the dtrace_modunload function pointer.
3572 3573 */
3573 3574 if (strcmp(mp->mod_modname, "dtrace") != 0) {
3574 3575 struct modctl *dmp = mod_hold_by_name("dtrace");
3575 3576
3576 3577 if (dmp != NULL && dtrace_modunload != NULL)
3577 3578 (*dtrace_modunload)(mp);
3578 3579
3579 3580 mod_release_mod(dmp);
3580 3581 }
3581 3582 }
3582 3583
3583 3584 static int
3584 3585 modinstall(struct modctl *mp)
3585 3586 {
3586 3587 int val;
3587 3588 int (*func)(void);
3588 3589
3589 3590 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3590 3591 ASSERT(mp->mod_busy && mp->mod_loaded);
3591 3592
3592 3593 if (mp->mod_installed)
3593 3594 return (0);
3594 3595 /*
3595 3596 * If mod_delay_unload is on, it means the system chose the deferred
3596 3597 * unload for this module. Then you can't install this module until
3597 3598 * it's unloaded from the system.
3598 3599 */
3599 3600 if (mp->mod_delay_unload)
3600 3601 return (ENXIO);
3601 3602
3602 3603 if (moddebug & MODDEBUG_LOADMSG)
3603 3604 printf("installing %s, module id %d.\n",
3604 3605 mp->mod_modname, mp->mod_id);
3605 3606
3606 3607 ASSERT(mp->mod_mp != NULL);
3607 3608 if (mod_install_requisites(mp) != 0) {
3608 3609 /*
3609 3610 * Note that we can't call mod_unload(mp) here since
3610 3611 * if modinstall() was called by mod_install_requisites(),
3611 3612 * we won't be able to hold the dependent modules
3612 3613 * (otherwise there would be a deadlock).
3613 3614 */
3614 3615 return (ENXIO);
3615 3616 }
3616 3617
3617 3618 if (moddebug & MODDEBUG_ERRMSG) {
3618 3619 printf("init '%s' id %d loaded @ 0x%p/0x%p size %lu/%lu\n",
3619 3620 mp->mod_filename, mp->mod_id,
3620 3621 (void *)((struct module *)mp->mod_mp)->text,
3621 3622 (void *)((struct module *)mp->mod_mp)->data,
3622 3623 ((struct module *)mp->mod_mp)->text_size,
3623 3624 ((struct module *)mp->mod_mp)->data_size);
3624 3625 }
3625 3626
3626 3627 func = (int (*)())kobj_lookup(mp->mod_mp, "_init");
3627 3628
3628 3629 if (kobj_addrcheck(mp->mod_mp, (caddr_t)func)) {
3629 3630 cmn_err(CE_WARN, "_init() not defined properly in %s",
3630 3631 mp->mod_filename);
3631 3632 return (EFAULT);
3632 3633 }
3633 3634
3634 3635 if (moddebug & MODDEBUG_USERDEBUG) {
3635 3636 printf("breakpoint before calling %s:_init()\n",
3636 3637 mp->mod_modname);
3637 3638 if (DEBUGGER_PRESENT)
3638 3639 debug_enter("_init");
3639 3640 }
3640 3641
3641 3642 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3642 3643 ASSERT(mp->mod_busy && mp->mod_loaded);
3643 3644 val = (*func)(); /* call _init */
3644 3645
3645 3646 if (moddebug & MODDEBUG_USERDEBUG)
3646 3647 printf("Returned from _init, val = %x\n", val);
3647 3648
3648 3649 if (val == 0) {
3649 3650 /*
3650 3651 * Set the MODS_INSTALLED flag to enable this module
3651 3652 * being called now.
3652 3653 */
3653 3654 install_stubs(mp);
3654 3655 mp->mod_installed = 1;
3655 3656 } else if (moddebug & MODDEBUG_ERRMSG)
3656 3657 printf(mod_init_msg, mp->mod_filename, mp->mod_modname, val);
3657 3658
3658 3659 return (val);
3659 3660 }
3660 3661
3661 3662 int detach_driver_unconfig = 0;
3662 3663
3663 3664 static int
3664 3665 detach_driver(char *name)
3665 3666 {
3666 3667 major_t major;
3667 3668 int error;
3668 3669
3669 3670 /*
3670 3671 * If being called from mod_uninstall_all() then the appropriate
3671 3672 * driver detaches (leaf only) have already been done.
3672 3673 */
3673 3674 if (mod_in_autounload())
3674 3675 return (0);
3675 3676
3676 3677 major = ddi_name_to_major(name);
3677 3678 if (major == DDI_MAJOR_T_NONE)
3678 3679 return (0);
3679 3680
3680 3681 error = ndi_devi_unconfig_driver(ddi_root_node(),
3681 3682 NDI_DETACH_DRIVER | detach_driver_unconfig, major);
3682 3683 return (error == NDI_SUCCESS ? 0 : -1);
3683 3684 }
3684 3685
3685 3686 static char finiret_msg[] = "Returned from _fini for %s, status = %x\n";
3686 3687
3687 3688 static int
3688 3689 moduninstall(struct modctl *mp)
3689 3690 {
3690 3691 int status = 0;
3691 3692 int (*func)(void);
3692 3693
3693 3694 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3694 3695 ASSERT(mp->mod_busy);
3695 3696
3696 3697 /*
3697 3698 * Verify that we need to do something and can uninstall the module.
3698 3699 *
3699 3700 * If we should not uninstall the module or if the module is not in
3700 3701 * the correct state to start an uninstall we return EBUSY to prevent
3701 3702 * us from progressing to mod_unload. If the module has already been
3702 3703 * uninstalled and unloaded we return EALREADY.
3703 3704 */
3704 3705 if (mp->mod_prim || mp->mod_ref || mp->mod_nenabled != 0)
3705 3706 return (EBUSY);
3706 3707 if ((mp->mod_installed == 0) || (mp->mod_loaded == 0))
3707 3708 return (EALREADY);
3708 3709
3709 3710 /*
3710 3711 * To avoid devinfo / module deadlock we must release this module
3711 3712 * prior to initiating the detach_driver, otherwise the detach_driver
3712 3713 * might deadlock on a devinfo node held by another thread
3713 3714 * coming top down and involving the module we have locked.
3714 3715 *
3715 3716 * When we regrab the module we must reverify that it is OK
3716 3717 * to proceed with the uninstall operation.
3717 3718 */
3718 3719 mod_release_mod(mp);
3719 3720 status = detach_driver(mp->mod_modname);
3720 3721 (void) mod_hold_by_modctl(mp, MOD_WAIT_FOREVER | MOD_LOCK_NOT_HELD);
3721 3722
3722 3723 /* check detach status and reverify state with lock */
3723 3724 mutex_enter(&mod_lock);
3724 3725 if ((status != 0) || mp->mod_prim || mp->mod_ref) {
3725 3726 mutex_exit(&mod_lock);
3726 3727 return (EBUSY);
3727 3728 }
3728 3729 if ((mp->mod_installed == 0) || (mp->mod_loaded == 0)) {
3729 3730 mutex_exit(&mod_lock);
3730 3731 return (EALREADY);
3731 3732 }
3732 3733 mutex_exit(&mod_lock);
3733 3734
3734 3735 if (moddebug & MODDEBUG_LOADMSG2)
3735 3736 printf("uninstalling %s\n", mp->mod_modname);
3736 3737
3737 3738 /*
3738 3739 * lookup _fini, return EBUSY if not defined.
3739 3740 *
3740 3741 * The MODDEBUG_FINI_EBUSY is usefull in resolving leaks in
3741 3742 * detach(9E) - it allows bufctl addresses to be resolved.
3742 3743 */
3743 3744 func = (int (*)())kobj_lookup(mp->mod_mp, "_fini");
3744 3745 if ((func == NULL) || (mp->mod_loadflags & MOD_NOUNLOAD) ||
3745 3746 (moddebug & MODDEBUG_FINI_EBUSY))
3746 3747 return (EBUSY);
3747 3748
3748 3749 /* verify that _fini is in this module */
3749 3750 if (kobj_addrcheck(mp->mod_mp, (caddr_t)func)) {
3750 3751 cmn_err(CE_WARN, "_fini() not defined properly in %s",
3751 3752 mp->mod_filename);
3752 3753 return (EFAULT);
3753 3754 }
3754 3755
3755 3756 /* call _fini() */
3756 3757 ASSERT(MUTEX_NOT_HELD(&mod_lock));
3757 3758 ASSERT(mp->mod_busy && mp->mod_loaded && mp->mod_installed);
3758 3759
3759 3760 status = (*func)();
3760 3761
3761 3762 if (status == 0) {
3762 3763 /* _fini returned success, the module is no longer installed */
3763 3764 if (moddebug & MODDEBUG_LOADMSG)
3764 3765 printf("uninstalled %s\n", mp->mod_modname);
3765 3766
3766 3767 /*
3767 3768 * Even though we only set mod_installed to zero here, a zero
3768 3769 * return value means we are committed to a code path were
3769 3770 * mod_loaded will also end up as zero - we have no other
3770 3771 * way to get the module data and bss back to the pre _init
3771 3772 * state except a reload. To ensure this, after return,
3772 3773 * mod_busy must stay set until mod_loaded is cleared.
3773 3774 */
3774 3775 mp->mod_installed = 0;
3775 3776
3776 3777 /*
3777 3778 * Clear the MODS_INSTALLED flag not to call functions
3778 3779 * in the module directly from now on.
3779 3780 */
3780 3781 uninstall_stubs(mp);
3781 3782 } else {
3782 3783 if (moddebug & MODDEBUG_USERDEBUG)
3783 3784 printf(finiret_msg, mp->mod_filename, status);
3784 3785 /*
3785 3786 * By definition _fini is only allowed to return EBUSY or the
3786 3787 * result of mod_remove (EBUSY or EINVAL). In the off chance
3787 3788 * that a driver returns EALREADY we convert this to EINVAL
3788 3789 * since to our caller EALREADY means module was already
3789 3790 * removed.
3790 3791 */
3791 3792 if (status == EALREADY)
3792 3793 status = EINVAL;
3793 3794 }
3794 3795
3795 3796 return (status);
3796 3797 }
3797 3798
3798 3799 /*
3799 3800 * Uninstall all modules.
3800 3801 */
3801 3802 static void
3802 3803 mod_uninstall_all(void)
3803 3804 {
3804 3805 struct modctl *mp;
3805 3806 int pass;
3806 3807 modid_t modid;
3807 3808
3808 3809 /* synchronize with any active modunload_disable() */
3809 3810 modunload_begin();
3810 3811
3811 3812 /* mark this thread as doing autounloading */
3812 3813 (void) tsd_set(mod_autounload_key, (void *)1);
3813 3814
3814 3815 (void) devfs_clean(ddi_root_node(), NULL, 0);
3815 3816 (void) ndi_devi_unconfig(ddi_root_node(), NDI_AUTODETACH);
3816 3817
3817 3818 /*
3818 3819 * Loop up to max times if we keep producing unreferenced modules.
3819 3820 * A new unreferenced module is an opportunity to unload.
3820 3821 */
3821 3822 for (pass = 0; pass < mod_uninstall_pass_max; pass++) {
3822 3823
3823 3824 /* zero count of modules that go unreferenced during pass */
3824 3825 mod_uninstall_ref_zero = 0;
3825 3826
3826 3827 modid = 0;
3827 3828 while ((mp = mod_hold_next_by_id(modid)) != NULL) {
3828 3829 modid = mp->mod_id;
3829 3830
3830 3831 /*
3831 3832 * Skip modules with the MOD_NOAUTOUNLOAD flag set
3832 3833 */
3833 3834 if (mp->mod_loadflags & MOD_NOAUTOUNLOAD) {
3834 3835 mod_release_mod(mp);
3835 3836 continue;
3836 3837 }
3837 3838
3838 3839 if (moduninstall(mp) == 0) {
3839 3840 mod_unload(mp);
3840 3841 CPU_STATS_ADDQ(CPU, sys, modunload, 1);
3841 3842 }
3842 3843 mod_release_mod(mp);
3843 3844 }
3844 3845
3845 3846 /* break if no modules went unreferenced during pass */
3846 3847 if (mod_uninstall_ref_zero == 0)
3847 3848 break;
3848 3849 }
3849 3850 if (pass >= mod_uninstall_pass_max)
3850 3851 mod_uninstall_pass_exc++;
3851 3852
3852 3853 (void) tsd_set(mod_autounload_key, NULL);
3853 3854 modunload_end();
3854 3855 }
3855 3856
3856 3857 /* wait for unloads that have begun before registering disable */
3857 3858 void
3858 3859 modunload_disable(void)
3859 3860 {
3860 3861 mutex_enter(&modunload_wait_mutex);
3861 3862 while (modunload_active_count) {
3862 3863 modunload_wait++;
3863 3864 cv_wait(&modunload_wait_cv, &modunload_wait_mutex);
3864 3865 modunload_wait--;
3865 3866 }
3866 3867 modunload_disable_count++;
3867 3868 mutex_exit(&modunload_wait_mutex);
3868 3869 }
3869 3870
3870 3871 /* mark end of disable and signal waiters */
3871 3872 void
3872 3873 modunload_enable(void)
3873 3874 {
3874 3875 mutex_enter(&modunload_wait_mutex);
3875 3876 modunload_disable_count--;
3876 3877 if ((modunload_disable_count == 0) && modunload_wait)
3877 3878 cv_broadcast(&modunload_wait_cv);
3878 3879 mutex_exit(&modunload_wait_mutex);
3879 3880 }
3880 3881
3881 3882 /* wait for disables to complete before begining unload */
3882 3883 void
3883 3884 modunload_begin()
3884 3885 {
3885 3886 mutex_enter(&modunload_wait_mutex);
3886 3887 while (modunload_disable_count) {
3887 3888 modunload_wait++;
3888 3889 cv_wait(&modunload_wait_cv, &modunload_wait_mutex);
3889 3890 modunload_wait--;
3890 3891 }
3891 3892 modunload_active_count++;
3892 3893 mutex_exit(&modunload_wait_mutex);
3893 3894 }
3894 3895
3895 3896 /* mark end of unload and signal waiters */
3896 3897 void
3897 3898 modunload_end()
3898 3899 {
3899 3900 mutex_enter(&modunload_wait_mutex);
3900 3901 modunload_active_count--;
3901 3902 if ((modunload_active_count == 0) && modunload_wait)
3902 3903 cv_broadcast(&modunload_wait_cv);
3903 3904 mutex_exit(&modunload_wait_mutex);
3904 3905 }
3905 3906
3906 3907 void
3907 3908 mod_uninstall_daemon(void)
3908 3909 {
3909 3910 callb_cpr_t cprinfo;
3910 3911 clock_t ticks;
3911 3912
3912 3913 mod_aul_thread = curthread;
3913 3914
3914 3915 CALLB_CPR_INIT(&cprinfo, &mod_uninstall_lock, callb_generic_cpr, "mud");
3915 3916 for (;;) {
3916 3917 mutex_enter(&mod_uninstall_lock);
3917 3918 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3918 3919 /*
3919 3920 * In DEBUG kernels, unheld drivers are uninstalled periodically
3920 3921 * every mod_uninstall_interval seconds. Periodic uninstall can
3921 3922 * be disabled by setting mod_uninstall_interval to 0 which is
3922 3923 * the default for a non-DEBUG kernel.
3923 3924 */
3924 3925 if (mod_uninstall_interval) {
3925 3926 ticks = drv_usectohz(mod_uninstall_interval * 1000000);
3926 3927 (void) cv_reltimedwait(&mod_uninstall_cv,
3927 3928 &mod_uninstall_lock, ticks, TR_CLOCK_TICK);
3928 3929 } else {
3929 3930 cv_wait(&mod_uninstall_cv, &mod_uninstall_lock);
3930 3931 }
3931 3932 /*
3932 3933 * The whole daemon is safe for CPR except we don't want
3933 3934 * the daemon to run if FREEZE is issued and this daemon
3934 3935 * wakes up from the cv_wait above. In this case, it'll be
3935 3936 * blocked in CALLB_CPR_SAFE_END until THAW is issued.
3936 3937 *
3937 3938 * The reason of calling CALLB_CPR_SAFE_BEGIN twice is that
3938 3939 * mod_uninstall_lock is used to protect cprinfo and
3939 3940 * CALLB_CPR_SAFE_BEGIN assumes that this lock is held when
3940 3941 * called.
3941 3942 */
3942 3943 CALLB_CPR_SAFE_END(&cprinfo, &mod_uninstall_lock);
3943 3944 CALLB_CPR_SAFE_BEGIN(&cprinfo);
3944 3945 mutex_exit(&mod_uninstall_lock);
3945 3946 if ((modunload_disable_count == 0) &&
3946 3947 ((moddebug & MODDEBUG_NOAUTOUNLOAD) == 0)) {
3947 3948 mod_uninstall_all();
3948 3949 }
3949 3950 }
3950 3951 }
3951 3952
3952 3953 /*
3953 3954 * Unload all uninstalled modules.
3954 3955 */
3955 3956 void
3956 3957 modreap(void)
3957 3958 {
3958 3959 mutex_enter(&mod_uninstall_lock);
3959 3960 cv_broadcast(&mod_uninstall_cv);
3960 3961 mutex_exit(&mod_uninstall_lock);
3961 3962 }
3962 3963
3963 3964 /*
3964 3965 * Hold the specified module. This is the module holding primitive.
3965 3966 *
3966 3967 * If MOD_LOCK_HELD then the caller already holds the mod_lock.
3967 3968 *
3968 3969 * Return values:
3969 3970 * 0 ==> the module is held
3970 3971 * 1 ==> the module is not held and the MOD_WAIT_ONCE caller needs
3971 3972 * to determine how to retry.
3972 3973 */
3973 3974 int
3974 3975 mod_hold_by_modctl(struct modctl *mp, int f)
3975 3976 {
3976 3977 ASSERT((f & (MOD_WAIT_ONCE | MOD_WAIT_FOREVER)) &&
3977 3978 ((f & (MOD_WAIT_ONCE | MOD_WAIT_FOREVER)) !=
3978 3979 (MOD_WAIT_ONCE | MOD_WAIT_FOREVER)));
3979 3980 ASSERT((f & (MOD_LOCK_HELD | MOD_LOCK_NOT_HELD)) &&
3980 3981 ((f & (MOD_LOCK_HELD | MOD_LOCK_NOT_HELD)) !=
3981 3982 (MOD_LOCK_HELD | MOD_LOCK_NOT_HELD)));
3982 3983 ASSERT((f & MOD_LOCK_NOT_HELD) || MUTEX_HELD(&mod_lock));
3983 3984
3984 3985 if (f & MOD_LOCK_NOT_HELD)
3985 3986 mutex_enter(&mod_lock);
3986 3987
3987 3988 while (mp->mod_busy) {
3988 3989 mp->mod_want = 1;
3989 3990 cv_wait(&mod_cv, &mod_lock);
3990 3991 /*
3991 3992 * Module may be unloaded by daemon.
3992 3993 * Nevertheless, modctl structure is still in linked list
3993 3994 * (i.e., off &modules), not freed!
3994 3995 * Caller is not supposed to assume "mp" is valid, but there
3995 3996 * is no reasonable way to detect this but using
3996 3997 * mp->mod_modinfo->mp == NULL check (follow the back pointer)
3997 3998 * (or similar check depending on calling context)
3998 3999 * DON'T free modctl structure, it will be very very
3999 4000 * problematic.
4000 4001 */
4001 4002 if (f & MOD_WAIT_ONCE) {
4002 4003 if (f & MOD_LOCK_NOT_HELD)
4003 4004 mutex_exit(&mod_lock);
4004 4005 return (1); /* caller decides how to retry */
4005 4006 }
4006 4007 }
4007 4008
4008 4009 mp->mod_busy = 1;
4009 4010 mp->mod_inprogress_thread =
4010 4011 (curthread == NULL ? (kthread_id_t)-1 : curthread);
4011 4012
4012 4013 if (f & MOD_LOCK_NOT_HELD)
4013 4014 mutex_exit(&mod_lock);
4014 4015 return (0);
4015 4016 }
4016 4017
4017 4018 static struct modctl *
4018 4019 mod_hold_by_name_common(struct modctl *dep, const char *filename)
4019 4020 {
4020 4021 const char *modname;
4021 4022 struct modctl *mp;
4022 4023 char *curname, *newname;
4023 4024 int found = 0;
4024 4025
4025 4026 mutex_enter(&mod_lock);
4026 4027
4027 4028 if ((modname = strrchr(filename, '/')) == NULL)
4028 4029 modname = filename;
4029 4030 else
4030 4031 modname++;
4031 4032
4032 4033 mp = &modules;
4033 4034 do {
4034 4035 if (strcmp(modname, mp->mod_modname) == 0) {
4035 4036 found = 1;
4036 4037 break;
4037 4038 }
4038 4039 } while ((mp = mp->mod_next) != &modules);
4039 4040
4040 4041 if (found == 0) {
4041 4042 mp = allocate_modp(filename, modname);
4042 4043 modadd(mp);
4043 4044 }
4044 4045
4045 4046 /*
4046 4047 * if dep is not NULL, set the mp in mod_requisite_loading for
4047 4048 * the module circular dependency check. This field is used in
4048 4049 * mod_circdep(), but it's cleard in mod_hold_loaded_mod().
4049 4050 */
4050 4051 if (dep != NULL) {
4051 4052 ASSERT(dep->mod_busy && dep->mod_requisite_loading == NULL);
4052 4053 dep->mod_requisite_loading = mp;
4053 4054 }
4054 4055
4055 4056 /*
4056 4057 * If the module was held, then it must be us who has it held.
4057 4058 */
4058 4059 if (mod_circdep(mp))
4059 4060 mp = NULL;
4060 4061 else {
4061 4062 (void) mod_hold_by_modctl(mp, MOD_WAIT_FOREVER | MOD_LOCK_HELD);
4062 4063
4063 4064 /*
4064 4065 * If the name hadn't been set or has changed, allocate
4065 4066 * space and set it. Free space used by previous name.
4066 4067 *
4067 4068 * Do not change the name of primary modules, for primary
4068 4069 * modules the mod_filename was allocated in standalone mode:
4069 4070 * it is illegal to kobj_alloc in standalone mode and kobj_free
4070 4071 * in non-standalone mode.
4071 4072 */
4072 4073 curname = mp->mod_filename;
4073 4074 if (curname == NULL ||
4074 4075 ((mp->mod_prim == 0) &&
4075 4076 (curname != filename) &&
4076 4077 (modname != filename) &&
4077 4078 (strcmp(curname, filename) != 0))) {
4078 4079 newname = kobj_zalloc(strlen(filename) + 1, KM_SLEEP);
4079 4080 (void) strcpy(newname, filename);
4080 4081 mp->mod_filename = newname;
4081 4082 if (curname != NULL)
4082 4083 kobj_free(curname, strlen(curname) + 1);
4083 4084 }
4084 4085 }
4085 4086
4086 4087 mutex_exit(&mod_lock);
4087 4088 if (mp && moddebug & MODDEBUG_LOADMSG2)
4088 4089 printf("Holding %s\n", mp->mod_filename);
4089 4090 if (mp == NULL && moddebug & MODDEBUG_LOADMSG2)
4090 4091 printf("circular dependency loading %s\n", filename);
4091 4092 return (mp);
4092 4093 }
4093 4094
4094 4095 static struct modctl *
4095 4096 mod_hold_by_name_requisite(struct modctl *dep, char *filename)
4096 4097 {
4097 4098 return (mod_hold_by_name_common(dep, filename));
4098 4099 }
4099 4100
4100 4101 struct modctl *
4101 4102 mod_hold_by_name(const char *filename)
4102 4103 {
4103 4104 return (mod_hold_by_name_common(NULL, filename));
4104 4105 }
4105 4106
4106 4107 struct modctl *
4107 4108 mod_hold_by_id(modid_t modid)
4108 4109 {
4109 4110 struct modctl *mp;
4110 4111 int found = 0;
4111 4112
4112 4113 mutex_enter(&mod_lock);
4113 4114 mp = &modules;
4114 4115 do {
4115 4116 if (mp->mod_id == modid) {
4116 4117 found = 1;
4117 4118 break;
4118 4119 }
4119 4120 } while ((mp = mp->mod_next) != &modules);
4120 4121
4121 4122 if ((found == 0) || mod_circdep(mp))
4122 4123 mp = NULL;
4123 4124 else
4124 4125 (void) mod_hold_by_modctl(mp, MOD_WAIT_FOREVER | MOD_LOCK_HELD);
4125 4126
4126 4127 mutex_exit(&mod_lock);
4127 4128 return (mp);
4128 4129 }
4129 4130
4130 4131 static struct modctl *
4131 4132 mod_hold_next_by_id(modid_t modid)
4132 4133 {
4133 4134 struct modctl *mp;
4134 4135 int found = 0;
4135 4136
4136 4137 if (modid < -1)
4137 4138 return (NULL);
4138 4139
4139 4140 mutex_enter(&mod_lock);
4140 4141
4141 4142 mp = &modules;
4142 4143 do {
4143 4144 if (mp->mod_id > modid) {
4144 4145 found = 1;
4145 4146 break;
4146 4147 }
4147 4148 } while ((mp = mp->mod_next) != &modules);
4148 4149
4149 4150 if ((found == 0) || mod_circdep(mp))
4150 4151 mp = NULL;
4151 4152 else
4152 4153 (void) mod_hold_by_modctl(mp, MOD_WAIT_FOREVER | MOD_LOCK_HELD);
4153 4154
4154 4155 mutex_exit(&mod_lock);
4155 4156 return (mp);
4156 4157 }
4157 4158
4158 4159 static void
4159 4160 mod_release(struct modctl *mp)
4160 4161 {
4161 4162 ASSERT(MUTEX_HELD(&mod_lock));
4162 4163 ASSERT(mp->mod_busy);
4163 4164
4164 4165 mp->mod_busy = 0;
4165 4166 mp->mod_inprogress_thread = NULL;
4166 4167 if (mp->mod_want) {
4167 4168 mp->mod_want = 0;
4168 4169 cv_broadcast(&mod_cv);
4169 4170 }
4170 4171 }
4171 4172
4172 4173 void
4173 4174 mod_release_mod(struct modctl *mp)
4174 4175 {
4175 4176 if (moddebug & MODDEBUG_LOADMSG2)
4176 4177 printf("Releasing %s\n", mp->mod_filename);
4177 4178 mutex_enter(&mod_lock);
4178 4179 mod_release(mp);
4179 4180 mutex_exit(&mod_lock);
4180 4181 }
4181 4182
4182 4183 modid_t
4183 4184 mod_name_to_modid(char *filename)
4184 4185 {
4185 4186 char *modname;
4186 4187 struct modctl *mp;
4187 4188
4188 4189 mutex_enter(&mod_lock);
4189 4190
4190 4191 if ((modname = strrchr(filename, '/')) == NULL)
4191 4192 modname = filename;
4192 4193 else
4193 4194 modname++;
4194 4195
4195 4196 mp = &modules;
4196 4197 do {
4197 4198 if (strcmp(modname, mp->mod_modname) == 0) {
4198 4199 mutex_exit(&mod_lock);
4199 4200 return (mp->mod_id);
4200 4201 }
4201 4202 } while ((mp = mp->mod_next) != &modules);
4202 4203
4203 4204 mutex_exit(&mod_lock);
4204 4205 return (-1);
4205 4206 }
4206 4207
4207 4208
4208 4209 int
4209 4210 mod_remove_by_name(char *name)
4210 4211 {
4211 4212 struct modctl *mp;
4212 4213 int retval;
4213 4214
4214 4215 mp = mod_hold_by_name(name);
4215 4216
4216 4217 if (mp == NULL)
4217 4218 return (EINVAL);
4218 4219
4219 4220 if (mp->mod_loadflags & MOD_NOAUTOUNLOAD) {
4220 4221 /*
4221 4222 * Do not unload forceloaded modules
4222 4223 */
4223 4224 mod_release_mod(mp);
4224 4225 return (0);
4225 4226 }
4226 4227
4227 4228 if ((retval = moduninstall(mp)) == 0) {
4228 4229 mod_unload(mp);
4229 4230 CPU_STATS_ADDQ(CPU, sys, modunload, 1);
4230 4231 } else if (retval == EALREADY)
4231 4232 retval = 0; /* already unloaded, not an error */
4232 4233 mod_release_mod(mp);
4233 4234 return (retval);
4234 4235 }
4235 4236
4236 4237 /*
4237 4238 * Record that module "dep" is dependent on module "on_mod."
4238 4239 */
4239 4240 static void
4240 4241 mod_make_requisite(struct modctl *dependent, struct modctl *on_mod)
4241 4242 {
4242 4243 struct modctl_list **pmlnp; /* previous next pointer */
4243 4244 struct modctl_list *mlp;
4244 4245 struct modctl_list *new;
4245 4246
4246 4247 ASSERT(dependent->mod_busy && on_mod->mod_busy);
4247 4248 mutex_enter(&mod_lock);
4248 4249
4249 4250 /*
4250 4251 * Search dependent's requisite list to see if on_mod is recorded.
4251 4252 * List is ordered by id.
4252 4253 */
4253 4254 for (pmlnp = &dependent->mod_requisites, mlp = *pmlnp;
4254 4255 mlp; pmlnp = &mlp->modl_next, mlp = *pmlnp)
4255 4256 if (mlp->modl_modp->mod_id >= on_mod->mod_id)
4256 4257 break;
4257 4258
4258 4259 /* Create and insert if not already recorded */
4259 4260 if ((mlp == NULL) || (mlp->modl_modp->mod_id != on_mod->mod_id)) {
4260 4261 new = kobj_zalloc(sizeof (*new), KM_SLEEP);
4261 4262 new->modl_modp = on_mod;
4262 4263 new->modl_next = mlp;
4263 4264 *pmlnp = new;
4264 4265
4265 4266 /*
4266 4267 * Increment the mod_ref count in our new requisite module.
4267 4268 * This is what keeps a module that has other modules
4268 4269 * which are dependent on it from being uninstalled and
4269 4270 * unloaded. "on_mod"'s mod_ref count decremented in
4270 4271 * mod_release_requisites when the "dependent" module
4271 4272 * unload is complete. "on_mod" must be loaded, but may not
4272 4273 * yet be installed.
4273 4274 */
4274 4275 on_mod->mod_ref++;
4275 4276 ASSERT(on_mod->mod_ref && on_mod->mod_loaded);
4276 4277 }
4277 4278
4278 4279 mutex_exit(&mod_lock);
4279 4280 }
4280 4281
4281 4282 /*
4282 4283 * release the hold associated with mod_make_requisite mod_ref++
4283 4284 * as part of unload.
4284 4285 */
4285 4286 void
4286 4287 mod_release_requisites(struct modctl *modp)
4287 4288 {
4288 4289 struct modctl_list *modl;
4289 4290 struct modctl_list *next;
4290 4291 struct modctl *req;
4291 4292 struct modctl_list *start = NULL, *mod_garbage;
4292 4293
4293 4294 ASSERT(!quiesce_active);
4294 4295 ASSERT(modp->mod_busy);
4295 4296 ASSERT(MUTEX_NOT_HELD(&mod_lock));
4296 4297
4297 4298 mutex_enter(&mod_lock); /* needed for manipulation of req */
4298 4299 for (modl = modp->mod_requisites; modl; modl = next) {
4299 4300 next = modl->modl_next;
4300 4301 req = modl->modl_modp;
4301 4302 ASSERT(req->mod_ref >= 1 && req->mod_loaded);
4302 4303 req->mod_ref--;
4303 4304 if (req->mod_ref == 0)
4304 4305 mod_uninstall_ref_zero++;
4305 4306
4306 4307 /*
4307 4308 * Check if the module has to be unloaded or not.
4308 4309 */
4309 4310 if (req->mod_ref == 0 && req->mod_delay_unload) {
4310 4311 struct modctl_list *new;
4311 4312 /*
4312 4313 * Allocate the modclt_list holding the garbage
4313 4314 * module which should be unloaded later.
4314 4315 */
4315 4316 new = kobj_zalloc(sizeof (struct modctl_list),
4316 4317 KM_SLEEP);
4317 4318 new->modl_modp = req;
4318 4319
4319 4320 if (start == NULL)
4320 4321 mod_garbage = start = new;
4321 4322 else {
4322 4323 mod_garbage->modl_next = new;
4323 4324 mod_garbage = new;
4324 4325 }
4325 4326 }
4326 4327
4327 4328 /* free the list as we go */
4328 4329 kobj_free(modl, sizeof (*modl));
4329 4330 }
4330 4331 modp->mod_requisites = NULL;
4331 4332 mutex_exit(&mod_lock);
4332 4333
4333 4334 /*
4334 4335 * Unload the garbage modules.
4335 4336 */
4336 4337 for (mod_garbage = start; mod_garbage != NULL; /* nothing */) {
4337 4338 struct modctl_list *old = mod_garbage;
4338 4339 struct modctl *mp = mod_garbage->modl_modp;
4339 4340 ASSERT(mp != NULL);
4340 4341
4341 4342 /*
4342 4343 * Hold this module until it's unloaded completely.
4343 4344 */
4344 4345 (void) mod_hold_by_modctl(mp,
4345 4346 MOD_WAIT_FOREVER | MOD_LOCK_NOT_HELD);
4346 4347 /*
4347 4348 * Check if the module is not unloaded yet and nobody requires
4348 4349 * the module. If it's unloaded already or somebody still
4349 4350 * requires the module, don't unload it now.
4350 4351 */
4351 4352 if (mp->mod_loaded && mp->mod_ref == 0)
4352 4353 mod_unload(mp);
4353 4354 ASSERT((mp->mod_loaded == 0 && mp->mod_delay_unload == 0) ||
4354 4355 (mp->mod_ref > 0));
4355 4356 mod_release_mod(mp);
4356 4357
4357 4358 mod_garbage = mod_garbage->modl_next;
4358 4359 kobj_free(old, sizeof (struct modctl_list));
4359 4360 }
4360 4361 }
4361 4362
4362 4363 /*
4363 4364 * Process dependency of the module represented by "dep" on the
4364 4365 * module named by "on."
4365 4366 *
4366 4367 * Called from kobj_do_dependents() to load a module "on" on which
4367 4368 * "dep" depends.
4368 4369 */
4369 4370 struct modctl *
4370 4371 mod_load_requisite(struct modctl *dep, char *on)
4371 4372 {
4372 4373 struct modctl *on_mod;
4373 4374 int retval;
4374 4375
4375 4376 if ((on_mod = mod_hold_loaded_mod(dep, on, &retval)) != NULL) {
4376 4377 mod_make_requisite(dep, on_mod);
4377 4378 } else if (moddebug & MODDEBUG_ERRMSG) {
4378 4379 printf("error processing %s on which module %s depends\n",
4379 4380 on, dep->mod_modname);
4380 4381 }
4381 4382 return (on_mod);
4382 4383 }
4383 4384
4384 4385 static int
4385 4386 mod_install_requisites(struct modctl *modp)
4386 4387 {
4387 4388 struct modctl_list *modl;
4388 4389 struct modctl *req;
4389 4390 int status = 0;
4390 4391
4391 4392 ASSERT(MUTEX_NOT_HELD(&mod_lock));
4392 4393 ASSERT(modp->mod_busy);
4393 4394
4394 4395 for (modl = modp->mod_requisites; modl; modl = modl->modl_next) {
4395 4396 req = modl->modl_modp;
4396 4397 (void) mod_hold_by_modctl(req,
4397 4398 MOD_WAIT_FOREVER | MOD_LOCK_NOT_HELD);
4398 4399 status = modinstall(req);
4399 4400 mod_release_mod(req);
4400 4401
4401 4402 if (status != 0)
4402 4403 break;
4403 4404 }
4404 4405 return (status);
4405 4406 }
4406 4407
4407 4408 /*
4408 4409 * returns 1 if this thread is doing autounload, 0 otherwise.
4409 4410 * see mod_uninstall_all.
4410 4411 */
4411 4412 int
4412 4413 mod_in_autounload()
4413 4414 {
4414 4415 return ((int)(uintptr_t)tsd_get(mod_autounload_key));
4415 4416 }
4416 4417
4417 4418 /*
4418 4419 * gmatch adapted from libc, stripping the wchar stuff
4419 4420 */
4420 4421 #define popchar(p, c) { \
4421 4422 c = *p++; \
4422 4423 if (c == 0) { \
4423 4424 return (0); \
4424 4425 } \
4425 4426 }
4426 4427
4427 4428 int
4428 4429 gmatch(const char *s, const char *p)
4429 4430 {
4430 4431 int c, sc;
4431 4432 int ok, lc, notflag;
4432 4433
4433 4434 sc = *s++;
4434 4435 c = *p++;
4435 4436 if (c == 0)
4436 4437 return (sc == c); /* nothing matches nothing */
4437 4438
4438 4439 switch (c) {
4439 4440 case '\\':
4440 4441 /* skip to quoted character */
4441 4442 popchar(p, c);
4442 4443 /*FALLTHRU*/
4443 4444
4444 4445 default:
4445 4446 /* straight comparison */
4446 4447 if (c != sc)
4447 4448 return (0);
4448 4449 /*FALLTHRU*/
4449 4450
4450 4451 case '?':
4451 4452 /* first char matches, move to remainder */
4452 4453 return (sc != '\0' ? gmatch(s, p) : 0);
4453 4454
4454 4455
4455 4456 case '*':
4456 4457 while (*p == '*')
4457 4458 p++;
4458 4459
4459 4460 /* * matches everything */
4460 4461 if (*p == 0)
4461 4462 return (1);
4462 4463
4463 4464 /* undo skip at the beginning & iterate over substrings */
4464 4465 --s;
4465 4466 while (*s) {
4466 4467 if (gmatch(s, p))
4467 4468 return (1);
4468 4469 s++;
4469 4470 }
4470 4471 return (0);
4471 4472
4472 4473 case '[':
4473 4474 /* match any char within [] */
4474 4475 if (sc == 0)
4475 4476 return (0);
4476 4477
4477 4478 ok = lc = notflag = 0;
4478 4479
4479 4480 if (*p == '!') {
4480 4481 notflag = 1;
4481 4482 p++;
4482 4483 }
4483 4484 popchar(p, c);
4484 4485
4485 4486 do {
4486 4487 if (c == '-' && lc && *p != ']') {
4487 4488 /* test sc against range [c1-c2] */
4488 4489 popchar(p, c);
4489 4490 if (c == '\\') {
4490 4491 popchar(p, c);
4491 4492 }
4492 4493
4493 4494 if (notflag) {
4494 4495 /* return 0 on mismatch */
4495 4496 if (lc <= sc && sc <= c)
4496 4497 return (0);
4497 4498 ok++;
4498 4499 } else if (lc <= sc && sc <= c) {
4499 4500 ok++;
4500 4501 }
4501 4502 /* keep going, may get a match next */
4502 4503 } else if (c == '\\') {
4503 4504 /* skip to quoted character */
4504 4505 popchar(p, c);
4505 4506 }
4506 4507 lc = c;
4507 4508 if (notflag) {
4508 4509 if (sc == lc)
4509 4510 return (0);
4510 4511 ok++;
4511 4512 } else if (sc == lc) {
4512 4513 ok++;
4513 4514 }
4514 4515 popchar(p, c);
4515 4516 } while (c != ']');
4516 4517
4517 4518 /* recurse on remainder of string */
4518 4519 return (ok ? gmatch(s, p) : 0);
4519 4520 }
4520 4521 /*NOTREACHED*/
4521 4522 }
4522 4523
4523 4524
4524 4525 /*
4525 4526 * Get default perm for device from /etc/minor_perm. Return 0 if match found.
4526 4527 *
4527 4528 * Pure wild-carded patterns are handled separately so the ordering of
4528 4529 * these patterns doesn't matter. We're still dependent on ordering
4529 4530 * however as the first matching entry is the one returned.
4530 4531 * Not ideal but all existing examples and usage do imply this
4531 4532 * ordering implicitly.
4532 4533 *
4533 4534 * Drivers using the clone driver are always good for some entertainment.
4534 4535 * Clone nodes under pseudo have the form clone@0:<driver>. Some minor
4535 4536 * perm entries have the form clone:<driver>, others use <driver>:*
4536 4537 * Examples are clone:llc1 vs. llc2:*, for example.
4537 4538 *
4538 4539 * Minor perms in the clone:<driver> form are mapped to the drivers's
4539 4540 * mperm list, not the clone driver, as wildcard entries for clone
4540 4541 * reference only. In other words, a clone wildcard will match
4541 4542 * references for clone@0:<driver> but never <driver>@<minor>.
4542 4543 *
4543 4544 * Additional minor perms in the standard form are also supported,
4544 4545 * for mixed usage, ie a node with an entry clone:<driver> could
4545 4546 * provide further entries <driver>:<minor>.
4546 4547 *
4547 4548 * Finally, some uses of clone use an alias as the minor name rather
4548 4549 * than the driver name, with the alias as the minor perm entry.
4549 4550 * This case is handled by attaching the driver to bring its
4550 4551 * minor list into existence, then discover the alias via DDI_ALIAS.
4551 4552 * The clone device's minor perm list can then be searched for
4552 4553 * that alias.
4553 4554 */
4554 4555
4555 4556 static int
4556 4557 dev_alias_minorperm(dev_info_t *dip, char *minor_name, mperm_t *rmp)
4557 4558 {
4558 4559 major_t major;
4559 4560 struct devnames *dnp;
4560 4561 mperm_t *mp;
4561 4562 char *alias = NULL;
4562 4563 dev_info_t *cdevi;
4563 4564 int circ;
4564 4565 struct ddi_minor_data *dmd;
4565 4566
4566 4567 major = ddi_name_to_major(minor_name);
4567 4568
4568 4569 ASSERT(dip == clone_dip);
4569 4570 ASSERT(major != DDI_MAJOR_T_NONE);
4570 4571
4571 4572 /*
4572 4573 * Attach the driver named by the minor node, then
4573 4574 * search its first instance's minor list for an
4574 4575 * alias node.
4575 4576 */
4576 4577 if (ddi_hold_installed_driver(major) == NULL)
4577 4578 return (1);
4578 4579
4579 4580 dnp = &devnamesp[major];
4580 4581 LOCK_DEV_OPS(&dnp->dn_lock);
4581 4582
4582 4583 if ((cdevi = dnp->dn_head) != NULL) {
4583 4584 ndi_devi_enter(cdevi, &circ);
4584 4585 for (dmd = DEVI(cdevi)->devi_minor; dmd; dmd = dmd->next) {
4585 4586 if (dmd->type == DDM_ALIAS) {
4586 4587 alias = i_ddi_strdup(dmd->ddm_name, KM_SLEEP);
4587 4588 break;
4588 4589 }
4589 4590 }
4590 4591 ndi_devi_exit(cdevi, circ);
4591 4592 }
4592 4593
4593 4594 UNLOCK_DEV_OPS(&dnp->dn_lock);
4594 4595 ddi_rele_driver(major);
4595 4596
4596 4597 if (alias == NULL) {
4597 4598 if (moddebug & MODDEBUG_MINORPERM)
4598 4599 cmn_err(CE_CONT, "dev_minorperm: "
4599 4600 "no alias for %s\n", minor_name);
4600 4601 return (1);
4601 4602 }
4602 4603
4603 4604 major = ddi_driver_major(clone_dip);
4604 4605 dnp = &devnamesp[major];
4605 4606 LOCK_DEV_OPS(&dnp->dn_lock);
4606 4607
4607 4608 /*
4608 4609 * Go through the clone driver's mperm list looking
4609 4610 * for a match for the specified alias.
4610 4611 */
4611 4612 for (mp = dnp->dn_mperm; mp; mp = mp->mp_next) {
4612 4613 if (strcmp(alias, mp->mp_minorname) == 0) {
4613 4614 break;
4614 4615 }
4615 4616 }
4616 4617
4617 4618 if (mp) {
4618 4619 if (moddebug & MODDEBUG_MP_MATCH) {
4619 4620 cmn_err(CE_CONT,
4620 4621 "minor perm defaults: %s %s 0%o %d %d (aliased)\n",
4621 4622 minor_name, alias, mp->mp_mode,
4622 4623 mp->mp_uid, mp->mp_gid);
4623 4624 }
4624 4625 rmp->mp_uid = mp->mp_uid;
4625 4626 rmp->mp_gid = mp->mp_gid;
4626 4627 rmp->mp_mode = mp->mp_mode;
4627 4628 }
4628 4629 UNLOCK_DEV_OPS(&dnp->dn_lock);
4629 4630
4630 4631 kmem_free(alias, strlen(alias)+1);
4631 4632
4632 4633 return (mp == NULL);
4633 4634 }
4634 4635
4635 4636 int
4636 4637 dev_minorperm(dev_info_t *dip, char *name, mperm_t *rmp)
4637 4638 {
4638 4639 major_t major;
4639 4640 char *minor_name;
4640 4641 struct devnames *dnp;
4641 4642 mperm_t *mp;
4642 4643 int is_clone = 0;
4643 4644
4644 4645 if (!minorperm_loaded) {
4645 4646 if (moddebug & MODDEBUG_MINORPERM)
4646 4647 cmn_err(CE_CONT,
4647 4648 "%s: minor perm not yet loaded\n", name);
4648 4649 return (1);
4649 4650 }
4650 4651
4651 4652 minor_name = strchr(name, ':');
4652 4653 if (minor_name == NULL)
4653 4654 return (1);
4654 4655 minor_name++;
4655 4656
4656 4657 /*
4657 4658 * If it's the clone driver, search the driver as named
4658 4659 * by the minor. All clone minor perm entries other than
4659 4660 * alias nodes are actually installed on the real driver's list.
4660 4661 */
4661 4662 if (dip == clone_dip) {
4662 4663 major = ddi_name_to_major(minor_name);
4663 4664 if (major == DDI_MAJOR_T_NONE) {
4664 4665 if (moddebug & MODDEBUG_MINORPERM)
4665 4666 cmn_err(CE_CONT, "dev_minorperm: "
4666 4667 "%s: no such driver\n", minor_name);
4667 4668 return (1);
4668 4669 }
4669 4670 is_clone = 1;
4670 4671 } else {
4671 4672 major = ddi_driver_major(dip);
4672 4673 ASSERT(major != DDI_MAJOR_T_NONE);
4673 4674 }
4674 4675
4675 4676 dnp = &devnamesp[major];
4676 4677 LOCK_DEV_OPS(&dnp->dn_lock);
4677 4678
4678 4679 /*
4679 4680 * Go through the driver's mperm list looking for
4680 4681 * a match for the specified minor. If there's
4681 4682 * no matching pattern, use the wild card.
4682 4683 * Defer to the clone wild for clone if specified,
4683 4684 * otherwise fall back to the normal form.
4684 4685 */
4685 4686 for (mp = dnp->dn_mperm; mp; mp = mp->mp_next) {
4686 4687 if (gmatch(minor_name, mp->mp_minorname) != 0) {
4687 4688 break;
4688 4689 }
4689 4690 }
4690 4691 if (mp == NULL) {
4691 4692 if (is_clone)
4692 4693 mp = dnp->dn_mperm_clone;
4693 4694 if (mp == NULL)
4694 4695 mp = dnp->dn_mperm_wild;
4695 4696 }
4696 4697
4697 4698 if (mp) {
4698 4699 if (moddebug & MODDEBUG_MP_MATCH) {
4699 4700 cmn_err(CE_CONT,
4700 4701 "minor perm defaults: %s %s 0%o %d %d\n",
4701 4702 name, mp->mp_minorname, mp->mp_mode,
4702 4703 mp->mp_uid, mp->mp_gid);
4703 4704 }
4704 4705 rmp->mp_uid = mp->mp_uid;
4705 4706 rmp->mp_gid = mp->mp_gid;
4706 4707 rmp->mp_mode = mp->mp_mode;
4707 4708 }
4708 4709 UNLOCK_DEV_OPS(&dnp->dn_lock);
4709 4710
4710 4711 /*
4711 4712 * If no match can be found for a clone node,
4712 4713 * search for a possible match for an alias.
4713 4714 * One such example is /dev/ptmx -> /devices/pseudo/clone@0:ptm,
4714 4715 * with minor perm entry clone:ptmx.
4715 4716 */
4716 4717 if (mp == NULL && is_clone) {
4717 4718 return (dev_alias_minorperm(dip, minor_name, rmp));
4718 4719 }
4719 4720
4720 4721 return (mp == NULL);
4721 4722 }
4722 4723
4723 4724 /*
4724 4725 * dynamicaly reference load a dl module/library, returning handle
4725 4726 */
4726 4727 /*ARGSUSED*/
4727 4728 ddi_modhandle_t
4728 4729 ddi_modopen(const char *modname, int mode, int *errnop)
4729 4730 {
4730 4731 char *subdir;
4731 4732 char *mod;
4732 4733 int subdirlen;
4733 4734 struct modctl *hmodp = NULL;
4734 4735 int retval = EINVAL;
4735 4736
4736 4737 ASSERT(modname && (mode == KRTLD_MODE_FIRST));
4737 4738 if ((modname == NULL) || (mode != KRTLD_MODE_FIRST))
4738 4739 goto out;
4739 4740
4740 4741 /* find last '/' in modname */
4741 4742 mod = strrchr(modname, '/');
4742 4743
4743 4744 if (mod) {
4744 4745 /* for subdir string without modification to argument */
4745 4746 mod++;
4746 4747 subdirlen = mod - modname;
4747 4748 subdir = kmem_alloc(subdirlen, KM_SLEEP);
4748 4749 (void) strlcpy(subdir, modname, subdirlen);
4749 4750 } else {
4750 4751 subdirlen = 0;
4751 4752 subdir = "misc";
4752 4753 mod = (char *)modname;
4753 4754 }
4754 4755
4755 4756 /* reference load with errno return value */
4756 4757 retval = modrload(subdir, mod, &hmodp);
4757 4758
4758 4759 if (subdirlen)
4759 4760 kmem_free(subdir, subdirlen);
4760 4761
4761 4762 out: if (errnop)
4762 4763 *errnop = retval;
4763 4764
4764 4765 if (moddebug & MODDEBUG_DDI_MOD)
4765 4766 printf("ddi_modopen %s mode %x: %s %p %d\n",
4766 4767 modname ? modname : "<unknown>", mode,
4767 4768 hmodp ? hmodp->mod_filename : "<unknown>",
4768 4769 (void *)hmodp, retval);
4769 4770
4770 4771 return ((ddi_modhandle_t)hmodp);
4771 4772 }
4772 4773
4773 4774 /* lookup "name" in open dl module/library */
4774 4775 void *
4775 4776 ddi_modsym(ddi_modhandle_t h, const char *name, int *errnop)
4776 4777 {
4777 4778 struct modctl *hmodp = (struct modctl *)h;
4778 4779 void *f;
4779 4780 int retval;
4780 4781
4781 4782 ASSERT(hmodp && name && hmodp->mod_installed && (hmodp->mod_ref >= 1));
4782 4783 if ((hmodp == NULL) || (name == NULL) ||
4783 4784 (hmodp->mod_installed == 0) || (hmodp->mod_ref < 1)) {
4784 4785 f = NULL;
4785 4786 retval = EINVAL;
4786 4787 } else {
4787 4788 f = (void *)kobj_lookup(hmodp->mod_mp, (char *)name);
4788 4789 if (f)
4789 4790 retval = 0;
4790 4791 else
4791 4792 retval = ENOTSUP;
4792 4793 }
4793 4794
4794 4795 if (moddebug & MODDEBUG_DDI_MOD)
4795 4796 printf("ddi_modsym in %s of %s: %d %p\n",
4796 4797 hmodp ? hmodp->mod_modname : "<unknown>",
4797 4798 name ? name : "<unknown>", retval, f);
4798 4799
4799 4800 if (errnop)
4800 4801 *errnop = retval;
4801 4802 return (f);
4802 4803 }
4803 4804
4804 4805 /* dynamic (un)reference unload of an open dl module/library */
4805 4806 int
4806 4807 ddi_modclose(ddi_modhandle_t h)
4807 4808 {
4808 4809 struct modctl *hmodp = (struct modctl *)h;
4809 4810 struct modctl *modp = NULL;
4810 4811 int retval;
4811 4812
4812 4813 ASSERT(hmodp && hmodp->mod_installed && (hmodp->mod_ref >= 1));
4813 4814 if ((hmodp == NULL) ||
4814 4815 (hmodp->mod_installed == 0) || (hmodp->mod_ref < 1)) {
4815 4816 retval = EINVAL;
4816 4817 goto out;
4817 4818 }
4818 4819
4819 4820 retval = modunrload(hmodp->mod_id, &modp, ddi_modclose_unload);
4820 4821 if (retval == EBUSY)
4821 4822 retval = 0; /* EBUSY is not an error */
4822 4823
4823 4824 if (retval == 0) {
4824 4825 ASSERT(hmodp == modp);
4825 4826 if (hmodp != modp)
4826 4827 retval = EINVAL;
4827 4828 }
4828 4829
4829 4830 out: if (moddebug & MODDEBUG_DDI_MOD)
4830 4831 printf("ddi_modclose %s: %d\n",
4831 4832 hmodp ? hmodp->mod_modname : "<unknown>", retval);
4832 4833
4833 4834 return (retval);
4834 4835 }
↓ open down ↓ |
1453 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX