xref: /illumos-gate/usr/src/cmd/modload/add_drv.c (revision 4df55fde49134f9735f84011f23a767c75e393c7)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <libelf.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/buf.h>
32 #include <wait.h>
33 #include <unistd.h>
34 #include <libintl.h>
35 #include <sys/modctl.h>
36 #include <sys/systeminfo.h>
37 #include <string.h>
38 #include <limits.h>
39 #include <locale.h>
40 #include <ftw.h>
41 #include <sys/sunddi.h>
42 #include <libdevinfo.h>
43 #include <sys/sysmacros.h>
44 #include <fcntl.h>
45 #include <zone.h>
46 #include "addrem.h"
47 #include "errmsg.h"
48 #include "plcysubr.h"
49 
50 /*
51  * globals needed for libdevinfo - there is no way to pass
52  * private data to the find routine.
53  */
54 struct dev_list {
55 	int clone;
56 	char *dev_name;
57 	char *driver_name;
58 	struct dev_list *next;
59 };
60 
61 static char *kelf_desc = NULL;
62 static int kelf_type = ELFCLASSNONE;
63 
64 static char *new_drv;
65 static struct dev_list *conflict_lst = NULL;
66 
67 static int module_not_found(char *, char *, int, char **, int *);
68 static void usage();
69 static int update_minor_perm(char *, char *);
70 static int devfs_update_minor_perm(char *, char *);
71 static int update_driver_classes(char *, char *);
72 static int drv_name_conflict(di_node_t);
73 static int devfs_node(di_node_t node, void *arg);
74 static int drv_name_match(char *, int, char *, char *);
75 static void print_drv_conflict_info(int);
76 static void check_dev_dir(int);
77 static int dev_node(const char *, const struct stat *, int, struct FTW *);
78 static void free_conflict_list(struct dev_list *);
79 static int clone(di_node_t node);
80 static int elf_type(char *, char **, int *);
81 static int correct_location(char *, char **, int *);
82 static int isaspec_drvmod_discovery();
83 static void remove_slashes(char *);
84 static int update_extra_privs(char *, char *privlist);
85 static int ignore_root_basedir();
86 
87 int
88 main(int argc, char *argv[])
89 {
90 	int opt;
91 	major_t major_num;
92 	char driver_name[FILENAME_MAX + 1];
93 	int driver_name_size = sizeof (driver_name);
94 	char path_driver_name[MAXPATHLEN];
95 	int path_driver_name_size = sizeof (path_driver_name);
96 	char *perms = NULL;
97 	char *aliases = NULL;
98 	char *classes = NULL;
99 	char *policy = NULL;
100 	char *priv = NULL;
101 	int noload_flag = 0;
102 	int verbose_flag = 0;
103 	int force_flag = 0;
104 	int update_only = 0;
105 	int i_flag = 0;
106 	int c_flag = 0;
107 	int m_flag = 0;
108 	int cleanup_flag = 0;
109 	int server = 0;
110 	char *basedir = NULL;
111 	int is_unique;
112 	char *slash;
113 	int conflict;
114 	di_node_t root_node;	/* for device tree snapshot */
115 	char *drvelf_desc = NULL;
116 	int drvelf_type = ELFCLASSNONE;
117 	int config_flags;
118 
119 	moddir = NULL;
120 
121 	(void) setlocale(LC_ALL, "");
122 #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
123 #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
124 #endif
125 	(void) textdomain(TEXT_DOMAIN);
126 
127 	/*  must be run by root */
128 
129 	if (geteuid() != 0) {
130 		(void) fprintf(stderr, gettext(ERR_NOT_ROOT));
131 		exit(1);
132 	}
133 
134 	while ((opt = getopt(argc, argv, "vfm:ni:b:c:p:P:u")) != EOF) {
135 		switch (opt) {
136 		case 'm' :
137 			m_flag = 1;
138 			perms = optarg;
139 			break;
140 		case 'f':
141 			force_flag++;
142 			break;
143 		case 'v':
144 			verbose_flag++;
145 			break;
146 		case 'n':
147 			noload_flag++;
148 			break;
149 		case 'i' :
150 			i_flag = 1;
151 			aliases = optarg;
152 			if (check_space_within_quote(aliases) == ERROR) {
153 				(void) fprintf(stderr, gettext(ERR_NO_SPACE),
154 				    aliases);
155 				exit(1);
156 			}
157 			break;
158 		case 'b' :
159 			server = 1;
160 			basedir = optarg;
161 			if (strcmp(basedir, "/") == 0 &&
162 			    ignore_root_basedir()) {
163 				server = 0;
164 				basedir = NULL;
165 			}
166 			break;
167 		case 'c':
168 			c_flag = 1;
169 			classes = optarg;
170 			break;
171 		case 'p':
172 			policy = optarg;
173 			break;
174 		case 'P':
175 			priv = optarg;
176 			break;
177 		case 'u':
178 			/*
179 			 * Update binding files and kernel but
180 			 * do not load or configure devices.
181 			 */
182 			update_only = 1;
183 			break;
184 		case '?' :
185 		default:
186 			usage();
187 			exit(1);
188 		}
189 	}
190 
191 
192 	if (argv[optind] != NULL) {
193 		if (strlcpy(driver_name, argv[optind], driver_name_size) >=
194 		    driver_name_size) {
195 			(void) fprintf(stderr, gettext(ERR_DRVNAME_TOO_LONG),
196 			    driver_name_size, argv[optind]);
197 			exit(1);
198 		}
199 
200 		/*
201 		 * check for extra args
202 		 */
203 		if ((optind + 1) != argc) {
204 			usage();
205 			exit(1);
206 		}
207 
208 	} else {
209 		usage();
210 		exit(1);
211 	}
212 
213 	if (getzoneid() != GLOBAL_ZONEID) {
214 		(void) fprintf(stderr, gettext(ERR_NOT_GLOBAL_ZONE));
215 		exit(1);
216 	}
217 
218 	/*
219 	 * Fail if add_drv was invoked with a pathname prepended to the
220 	 * driver_name argument.
221 	 *
222 	 * Check driver_name for any '/'s. If found, we assume that caller
223 	 * is trying to specify a pathname.
224 	 */
225 
226 	slash = strchr(driver_name, '/');
227 	if (slash) {
228 		remove_slashes(driver_name);
229 
230 		/* extract module name out of path */
231 		slash = strrchr(driver_name, '/');
232 
233 		if (slash != NULL) {
234 			(void) fprintf(stderr, gettext(ERR_PATH_SPEC),
235 			    driver_name);
236 			(void) fprintf(stderr, gettext(ERR_INSTALL_FAIL),
237 			    ++slash);
238 			exit(1);
239 		}
240 	}
241 	new_drv = driver_name;
242 
243 	/* set up add_drv filenames */
244 	if ((build_filenames(basedir)) == ERROR) {
245 		exit(1);
246 	}
247 
248 	/* must be only running version of add_drv/rem_drv */
249 	enter_lock();
250 
251 	if ((check_perms_aliases(m_flag, i_flag)) == ERROR)
252 		err_exit();
253 
254 	if ((check_name_to_major(R_OK | W_OK)) == ERROR)
255 		err_exit();
256 
257 	/*
258 	 * check validity of options
259 	 */
260 	if (m_flag) {
261 		if ((check_perm_opts(perms)) == ERROR) {
262 			usage();
263 			err_exit();
264 		}
265 	}
266 
267 	if (i_flag) {
268 		if (aliases != NULL)
269 			if ((aliases_unique(aliases)) == ERROR)
270 				err_exit();
271 	}
272 
273 	/* -u and -n/-b are mutually exclusive */
274 	if (update_only && (noload_flag || server)) {
275 		usage();
276 		err_exit();
277 	}
278 
279 	/* update kernel unless -b or -n */
280 	if (noload_flag == 0 && server == 0 &&
281 	    priv != NULL && check_priv_entry(priv, 1) != 0)
282 		err_exit();
283 
284 	if (policy != NULL &&
285 	    (policy = check_plcy_entry(policy, driver_name, B_FALSE)) == NULL) {
286 		err_exit();
287 	}
288 
289 	if ((unique_driver_name(driver_name, name_to_major,
290 	    &is_unique)) == ERROR)
291 		err_exit();
292 
293 	if (is_unique == NOT_UNIQUE) {
294 		(void) fprintf(stderr, gettext(ERR_NOT_UNIQUE), driver_name);
295 		err_exit();
296 	}
297 
298 	if (noload_flag == 0 && server == 0) {
299 		if (elf_type("/dev/ksyms", &kelf_desc, &kelf_type) == ERROR) {
300 			(void) fprintf(stderr, gettext(ERR_KERNEL_ISA));
301 			err_exit();
302 		}
303 
304 		if (module_not_found(driver_name, path_driver_name,
305 		    path_driver_name_size, &drvelf_desc, &drvelf_type) ==
306 		    ERROR) {
307 			(void) fprintf(stderr, gettext(ERR_NOMOD), driver_name);
308 			err_exit();
309 		}
310 
311 		/*
312 		 * If the driver location is incorrect but the kernel and driver
313 		 * are of the same ISA, suggest a fix.  If the driver location
314 		 * is incorrect and the ISA's mismatch, notify the user that
315 		 * this driver can not be loaded on this kernel.  In both cases,
316 		 * do not attempt to load the driver module.
317 		 */
318 
319 		if (correct_location(path_driver_name, &drvelf_desc,
320 		    (&drvelf_type)) == ERROR) {
321 			noload_flag = 1;
322 			if (kelf_type == drvelf_type) {
323 				(void) fprintf(stderr,
324 				    gettext(ERR_SOL_LOCATION), driver_name,
325 				    driver_name);
326 			} else {
327 				(void) fprintf(stderr,
328 				    gettext(ERR_NOT_LOADABLE),
329 				    drvelf_desc, driver_name, kelf_desc);
330 			}
331 
332 		/*
333 		 * The driver location is correct.  Verify that the kernel ISA
334 		 * and driver ISA match.  If they do not match, produce an error
335 		 * message and do not attempt to load the module.
336 		 */
337 
338 		} else if (kelf_type != drvelf_type) {
339 			noload_flag = 1;
340 			(void) fprintf(stderr, gettext(ERR_ISA_MISMATCH),
341 			    kelf_desc, driver_name, drvelf_desc);
342 			(void) fprintf(stderr, gettext(ERR_NOT_LOADABLE),
343 			    drvelf_desc, driver_name, kelf_desc);
344 		}
345 
346 
347 		/*
348 		 * Check for a more specific driver conflict - see
349 		 * PSARC/1995/239
350 		 * Note that drv_name_conflict() can return -1 for error
351 		 * or 1 for a conflict.  Since the default is to fail unless
352 		 * the -f flag is specified, we don't bother to differentiate.
353 		 */
354 		if ((root_node = di_init("/", DINFOSUBTREE | DINFOMINOR))
355 		    == DI_NODE_NIL) {
356 			(void) fprintf(stderr, gettext(ERR_DEVTREE));
357 			conflict = -1;
358 		} else {
359 			conflict = drv_name_conflict(root_node);
360 			di_fini(root_node);
361 		}
362 
363 		if (conflict) {
364 			/*
365 			 * if the force flag is not set, we fail here
366 			 */
367 			if (!force_flag) {
368 				(void) fprintf(stderr,
369 				    gettext(ERR_INSTALL_FAIL), driver_name);
370 				(void) fprintf(stderr, "Device managed by "
371 				    "another driver.\n");
372 				if (verbose_flag)
373 					print_drv_conflict_info(force_flag);
374 				err_exit();
375 			}
376 			/*
377 			 * The force flag was specified so we print warnings
378 			 * and install the driver anyways
379 			 */
380 			if (verbose_flag)
381 				print_drv_conflict_info(force_flag);
382 			free_conflict_list(conflict_lst);
383 		}
384 	}
385 
386 	if ((update_name_to_major(driver_name, &major_num, server)) == ERROR) {
387 		err_exit();
388 	}
389 
390 	cleanup_flag |= CLEAN_NAM_MAJ;
391 
392 
393 	if (m_flag) {
394 		cleanup_flag |= CLEAN_MINOR_PERM;
395 		if (update_minor_perm(driver_name, perms) == ERROR) {
396 			remove_entry(cleanup_flag, driver_name);
397 			err_exit();
398 		}
399 	}
400 
401 	if (i_flag) {
402 		cleanup_flag |= CLEAN_DRV_ALIAS;
403 		if (update_driver_aliases(driver_name, aliases) == ERROR) {
404 			remove_entry(cleanup_flag, driver_name);
405 			err_exit();
406 
407 		}
408 	}
409 
410 	if (c_flag) {
411 		cleanup_flag |= CLEAN_DRV_CLASSES;
412 		if (update_driver_classes(driver_name, classes) == ERROR) {
413 			remove_entry(cleanup_flag, driver_name);
414 			err_exit();
415 
416 		}
417 	}
418 
419 	if (priv != NULL) {
420 		cleanup_flag |= CLEAN_DRV_PRIV;
421 		if (update_extra_privs(driver_name, priv) == ERROR) {
422 			remove_entry(cleanup_flag, driver_name);
423 			err_exit();
424 		}
425 	}
426 
427 	if (policy != NULL) {
428 		cleanup_flag |= CLEAN_DEV_POLICY;
429 		if (update_device_policy(device_policy, policy, B_FALSE)
430 		    == ERROR) {
431 			remove_entry(cleanup_flag, driver_name);
432 			err_exit();
433 		}
434 	}
435 
436 	if (noload_flag || server) {
437 		(void) fprintf(stderr, gettext(BOOT_CLIENT));
438 	} else {
439 		/*
440 		 * paranoia - if we crash whilst configuring the driver
441 		 * this might avert possible file corruption.
442 		 */
443 		sync();
444 
445 		config_flags = 0;
446 		if (verbose_flag)
447 			config_flags |= CONFIG_DRV_VERBOSE;
448 		if (update_only)
449 			config_flags |= CONFIG_DRV_UPDATE_ONLY;
450 
451 		if (config_driver(driver_name, major_num, aliases, classes,
452 		    cleanup_flag, config_flags) == ERROR) {
453 			err_exit();
454 		}
455 		if (m_flag) {
456 			if (devfs_update_minor_perm(basedir,
457 			    driver_name) == ERROR) {
458 				err_exit();
459 			}
460 		}
461 		if (update_only) {
462 			(void) fprintf(stderr, gettext(INFO_UPDATE_ONLY),
463 			    driver_name);
464 		} else if (noload_flag) {
465 			(void) fprintf(stderr, gettext(ERR_CONFIG_NOLOAD),
466 			    driver_name);
467 		} else {
468 			load_driver(driver_name, verbose_flag);
469 		}
470 	}
471 
472 	if (create_reconfig(basedir) == ERROR)
473 		(void) fprintf(stderr, gettext(ERR_CREATE_RECONFIG));
474 
475 	cleanup_moddir();
476 	exit_unlock();
477 
478 	if (verbose_flag) {
479 		(void) fprintf(stderr, gettext(DRIVER_INSTALLED), driver_name);
480 	}
481 
482 	return (NOERR);
483 }
484 
485 /*
486  *	Searches for the driver module along the module path (returned
487  *	from modctl) and returns a string (in drv_path) representing the path
488  *	where drv_name was found.  ERROR is returned if function is unable
489  *	to locate drv_name.
490  */
491 int
492 module_not_found(char *drv_name, char *drv_path, int drv_path_size,
493     char **drvelf_desc, int *drvelf_type_ptr)
494 {
495 	struct stat buf;
496 	char data [MAXMODPATHS];
497 	char pathsave [MAXMODPATHS];
498 	char *next = data;
499 	struct drvmod_dir *curdir = NULL;
500 	char foundpath[MAXPATHLEN];
501 
502 	if (modctl(MODGETPATH, NULL, data) != 0) {
503 		(void) fprintf(stderr, gettext(ERR_MODPATH));
504 		return (ERROR);
505 	}
506 	(void) strcpy(pathsave, data);
507 	next = strtok(data, MOD_SEP);
508 
509 	if (isaspec_drvmod_discovery() == ERROR)
510 		err_exit();
511 
512 	curdir = moddir;
513 	while (curdir != NULL) {
514 		while (next != NULL) {
515 			(void) snprintf(foundpath, sizeof (foundpath),
516 			    "%s/drv/%s/%s", next, curdir->direc, drv_name);
517 			if ((stat(foundpath, &buf) == 0) &&
518 			    ((buf.st_mode & S_IFMT) == S_IFREG)) {
519 				if (elf_type(foundpath, drvelf_desc,
520 				    drvelf_type_ptr) == ERROR) {
521 					(void) fprintf(stderr,
522 					    gettext(ERR_INSTALL_FAIL),
523 					    drv_name);
524 					err_exit();
525 				}
526 				remove_slashes(foundpath);
527 
528 				if (strlcpy(drv_path, foundpath, drv_path_size)
529 				    >= drv_path_size) {
530 					return (ERROR);
531 				}
532 
533 				return (NOERR);
534 			}
535 			next = strtok((char *)NULL, MOD_SEP);
536 		}
537 		(void) strcpy(data, pathsave);
538 		next = strtok(data, MOD_SEP);
539 		curdir = curdir->next;
540 	}
541 
542 	return (ERROR);
543 }
544 
545 static void
546 usage()
547 {
548 	(void) fprintf(stderr, gettext(USAGE));
549 }
550 
551 static int
552 update_driver_classes(
553 	char *driver_name,
554 	char *classes)
555 {
556 	/* make call to update the classes file */
557 	return (append_to_file(driver_name, classes, driver_classes,
558 	    ' ', "\t", 0));
559 }
560 
561 static int
562 update_minor_perm(
563 	char *driver_name,
564 	char *perm_list)
565 {
566 	return (append_to_minor_perm(driver_name, perm_list, minor_perm));
567 }
568 
569 
570 /*
571  * Complete the minor perm update by communicating the minor perm
572  * data to the kernel.  This information is used by devfs to ensure
573  * that devices always have the correct permissions when attached.
574  * The minor perm file must be updated and the driver configured
575  * in the system for this step to complete correctly.
576  */
577 static int
578 devfs_update_minor_perm(
579 	char *basedir,
580 	char *driver_name)
581 {
582 	int rval = 0;
583 
584 	if (basedir == NULL || (strcmp(basedir, "/") == 0)) {
585 		if (devfs_add_minor_perm(driver_name,
586 		    log_minorperm_error) != 0) {
587 			(void) fprintf(stderr,
588 			    gettext(ERR_UPDATE_PERM), driver_name);
589 		}
590 	}
591 	return (rval);
592 }
593 
594 static int
595 update_extra_privs(
596 	char *driver_name,
597 	char *privlist)
598 {
599 	return (append_to_file(driver_name, privlist, extra_privs,
600 	    ',', ":", 0));
601 }
602 
603 /*
604  * Check to see if the driver we are adding is a more specific
605  * driver for a device already attached to a less specific driver.
606  * In other words, see if this driver comes earlier on the compatible
607  * list of a device already attached to another driver.
608  * If so, the new node will not be created (since the device is
609  * already attached) but when the system reboots, it will attach to
610  * the new driver but not have a node - we need to warn the user
611  * if this is the case.
612  */
613 static int
614 drv_name_conflict(di_node_t root_node)
615 {
616 	/*
617 	 * walk the device tree checking each node
618 	 */
619 	if (di_walk_node(root_node, DI_WALK_SIBFIRST, NULL, devfs_node) == -1) {
620 		free_conflict_list(conflict_lst);
621 		conflict_lst = (struct dev_list *)NULL;
622 		(void) fprintf(stderr, gettext(ERR_DEVTREE));
623 		return (-1);
624 	}
625 
626 	if (conflict_lst == NULL)
627 		/* no conflicts found */
628 		return (0);
629 	else
630 		/* conflicts! */
631 		return (1);
632 }
633 
634 /*
635  * called via di_walk_node().
636  * called for each node in the device tree.  We skip nodes that:
637  *	1. are not hw nodes (since they cannot have generic names)
638  *	2. that do not have a compatible property
639  *	3. whose node name = binding name.
640  *	4. nexus nodes - the name of a generic nexus node would
641  *	not be affected by a driver change.
642  * Otherwise, we parse the compatible property, if we find a
643  * match with the new driver before we find a match with the
644  * current driver, then we have a conflict and we save the
645  * node away.
646  */
647 /*ARGSUSED*/
648 static int
649 devfs_node(di_node_t node, void *arg)
650 {
651 	char *binding_name, *node_name, *compat_names, *devfsnm;
652 	struct dev_list *new_entry;
653 	char strbuf[MAXPATHLEN];
654 	int n_names;
655 
656 	/*
657 	 * if there is no compatible property, we don't
658 	 * have to worry about any conflicts.
659 	 */
660 	if ((n_names = di_compatible_names(node, &compat_names)) <= 0)
661 		return (DI_WALK_CONTINUE);
662 
663 	/*
664 	 * if the binding name and the node name match, then
665 	 * either no driver existed that could be bound to this node,
666 	 * or the driver name is the same as the node name.
667 	 */
668 	binding_name = di_binding_name(node);
669 	node_name = di_node_name(node);
670 	if ((binding_name == NULL) || (strcmp(node_name, binding_name) == 0))
671 		return (DI_WALK_CONTINUE);
672 
673 	/*
674 	 * we can skip nexus drivers since they do not
675 	 * have major/minor number info encoded in their
676 	 * /devices name and therefore won't change.
677 	 */
678 	if (di_driver_ops(node) & DI_BUS_OPS)
679 		return (DI_WALK_CONTINUE);
680 
681 	/*
682 	 * check for conflicts
683 	 * If we do find that the new driver is a more specific driver
684 	 * than the driver already attached to the device, we'll save
685 	 * away the node name for processing later.
686 	 */
687 	if (drv_name_match(compat_names, n_names, binding_name, new_drv)) {
688 		devfsnm = di_devfs_path(node);
689 		(void) snprintf(strbuf, sizeof (strbuf),
690 		    "%s%s", DEVFS_ROOT, devfsnm);
691 		di_devfs_path_free(devfsnm);
692 		new_entry = (struct dev_list *)calloc(1,
693 		    sizeof (struct dev_list));
694 		if (new_entry == (struct dev_list *)NULL) {
695 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
696 			err_exit();
697 		}
698 		/* save the /devices name */
699 		if ((new_entry->dev_name = strdup(strbuf)) == NULL) {
700 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
701 			free(new_entry);
702 			err_exit();
703 		}
704 		/* save the driver name */
705 		if ((new_entry->driver_name = strdup(di_driver_name(node)))
706 		    == NULL) {
707 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
708 			free(new_entry->dev_name);
709 			free(new_entry);
710 			err_exit();
711 		}
712 		/* check to see if this is a clone device */
713 		if (clone(node))
714 			new_entry->clone = 1;
715 
716 		/* add it to the list */
717 		new_entry->next = conflict_lst;
718 		conflict_lst = new_entry;
719 	}
720 
721 	return (DI_WALK_CONTINUE);
722 }
723 
724 static int
725 clone(di_node_t node)
726 {
727 	di_minor_t minor = DI_MINOR_NIL;
728 
729 	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
730 		if (di_minor_type(minor) == DDM_ALIAS)
731 			return (1);
732 	}
733 	return (0);
734 }
735 /*
736  * check to see if the new_name shows up on the compat list before
737  * the cur_name (driver currently attached to the device).
738  */
739 static int
740 drv_name_match(char *compat_names, int n_names, char *cur_name, char *new_name)
741 {
742 	int i, ret = 0;
743 
744 	if (strcmp(cur_name, new_name) == 0)
745 		return (0);
746 
747 	/* parse the coompatible list */
748 	for (i = 0; i < n_names; i++) {
749 		if (strcmp(compat_names, new_name) == 0) {
750 			ret = 1;
751 			break;
752 		}
753 		if (strcmp(compat_names, cur_name) == 0) {
754 			break;
755 		}
756 		compat_names += strlen(compat_names) + 1;
757 	}
758 	return (ret);
759 }
760 
761 /*
762  * A more specific driver is being added for a device already attached
763  * to a less specific driver.  Print out a general warning and if
764  * the force flag was passed in, give the user a hint as to what
765  * nodes may be affected in /devices and /dev
766  */
767 static void
768 print_drv_conflict_info(int force)
769 {
770 	struct dev_list *ptr;
771 
772 	if (conflict_lst == NULL)
773 		return;
774 	if (force) {
775 		(void) fprintf(stderr,
776 		    "\nA reconfiguration boot must be performed to "
777 		    "complete the\n");
778 		(void) fprintf(stderr, "installation of this driver.\n");
779 	}
780 
781 	if (force) {
782 		(void) fprintf(stderr,
783 		    "\nThe following entries in /devices will be "
784 		    "affected:\n\n");
785 	} else {
786 		(void) fprintf(stderr,
787 		    "\nDriver installation failed because the following\n");
788 		(void) fprintf(stderr,
789 		    "entries in /devices would be affected:\n\n");
790 	}
791 
792 	ptr = conflict_lst;
793 	while (ptr != NULL) {
794 		(void) fprintf(stderr, "\t%s", ptr->dev_name);
795 		if (ptr->clone)
796 			(void) fprintf(stderr, " (clone device)\n");
797 		else
798 			(void) fprintf(stderr, "[:*]\n");
799 		(void) fprintf(stderr, "\t(Device currently managed by driver "
800 		    "\"%s\")\n\n", ptr->driver_name);
801 		ptr = ptr->next;
802 	}
803 	check_dev_dir(force);
804 }
805 
806 /*
807  * use nftw to walk through /dev looking for links that match
808  * an entry in the conflict list.
809  */
810 static void
811 check_dev_dir(int force)
812 {
813 	int  walk_flags = FTW_PHYS | FTW_MOUNT;
814 	int ft_depth = 15;
815 
816 	if (force) {
817 		(void) fprintf(stderr, "\nThe following entries in /dev will "
818 		    "be affected:\n\n");
819 	} else {
820 		(void) fprintf(stderr, "\nThe following entries in /dev would "
821 		    "be affected:\n\n");
822 	}
823 
824 	(void) nftw("/dev", dev_node, ft_depth, walk_flags);
825 
826 	(void) fprintf(stderr, "\n");
827 }
828 
829 /*
830  * checks a /dev link to see if it matches any of the conlficting
831  * /devices nodes in conflict_lst.
832  */
833 /*ARGSUSED1*/
834 static int
835 dev_node(const char *node, const struct stat *node_stat, int flags,
836 	struct FTW *ftw_info)
837 {
838 	char linkbuf[MAXPATHLEN];
839 	struct dev_list *ptr;
840 
841 	if (readlink(node, linkbuf, MAXPATHLEN) == -1)
842 		return (0);
843 
844 	ptr = conflict_lst;
845 
846 	while (ptr != NULL) {
847 		if (strstr(linkbuf, ptr->dev_name) != NULL)
848 			(void) fprintf(stderr, "\t%s\n", node);
849 		ptr = ptr->next;
850 	}
851 	return (0);
852 }
853 
854 
855 static void
856 free_conflict_list(struct dev_list *list)
857 {
858 	struct dev_list *save;
859 
860 	/* free up any dev_list structs we allocated. */
861 	while (list != NULL) {
862 		save = list;
863 		list = list->next;
864 		free(save->dev_name);
865 		free(save);
866 	}
867 }
868 
869 int
870 elf_type(char *file, char **elfdesc, int *elf_type_ptr)
871 {
872 	int fd;
873 	Elf *elf;
874 	char *ident;
875 
876 	if ((fd = open(file, O_RDONLY)) < 0) {
877 		(void) fprintf(stderr, gettext(ERR_CANNOT_OPEN), file,
878 		    strerror(errno));
879 		return (ERROR);
880 	}
881 	if (elf_version(EV_CURRENT) == EV_NONE) {
882 		(void) fprintf(stderr, gettext(ERR_ELF_VERSION),
883 		    elf_errmsg(-1));
884 		(void) close(fd);
885 		return (ERROR);
886 	}
887 	elf = elf_begin(fd, ELF_C_READ, NULL);
888 	if (elf_kind(elf) != ELF_K_ELF) {
889 		(void) fprintf(stderr, gettext(ERR_ELF_KIND), file);
890 		(void) elf_end(elf);
891 		(void) close(fd);
892 		return (ERROR);
893 	}
894 	ident = elf_getident(elf, 0);
895 	if (ident[EI_CLASS] == ELFCLASS32) {
896 		*elfdesc = "32";
897 		*elf_type_ptr = ELFCLASS32;
898 	} else if (ident[EI_CLASS] == ELFCLASS64) {
899 		*elfdesc = "64";
900 		*elf_type_ptr = ELFCLASS64;
901 	} else {
902 		*elfdesc = "none";
903 		*elf_type_ptr = ELFCLASSNONE;
904 	}
905 	(void) elf_end(elf);
906 	(void) close(fd);
907 	return (NOERR);
908 }
909 
910 int
911 correct_location(char *drv_path, char **drvelf_desc, int *drvelf_type_ptr)
912 {
913 
914 	char copy_drv_path[MAXPATHLEN];
915 	char *token = copy_drv_path;
916 
917 	(void) strcpy(copy_drv_path, drv_path);
918 
919 	if (elf_type(drv_path, drvelf_desc, drvelf_type_ptr) == ERROR) {
920 		err_exit();
921 	}
922 	token = strtok(copy_drv_path, DIR_SEP);
923 	while (token != NULL) {
924 		if (strcmp("drv", token) == 0) {
925 			token = strtok((char *)NULL, DIR_SEP);
926 			if (strcmp(DRVDIR64, token) == 0) {
927 				if (*drvelf_type_ptr == ELFCLASS64)
928 					return (NOERR);
929 				(void) fprintf(stderr, gettext(ERR_LOCATION),
930 				    *drvelf_desc, drv_path);
931 				return (ERROR);
932 			} else {
933 				if (*drvelf_type_ptr == ELFCLASS32)
934 					return (NOERR);
935 				(void) fprintf(stderr, gettext(ERR_LOCATION),
936 				    *drvelf_desc, drv_path);
937 				return (ERROR);
938 			}
939 		} else {
940 			token = strtok((char *)NULL, DIR_SEP);
941 		}
942 	}
943 	return (ERROR);
944 }
945 
946 /*
947  * Creates a two-element linked list of isa-specific subdirectories to
948  * search for each driver, which is is used by the function
949  * module_not_found() to convert the isa-independent modpath into an
950  * isa-specific path .  The list is ordered depending on the machine
951  * architecture and instruction set architecture, corresponding to the
952  * order in which module_not_found() will search for the driver.  This
953  * routine relies on an architecture not having more than two
954  * sub-architectures (e.g., sparc/sparcv9 or i386/amd64).
955  */
956 int
957 isaspec_drvmod_discovery()
958 {
959 	char arch[SYS_NMLN];
960 
961 	moddir = (struct drvmod_dir *)calloc(1, sizeof (struct drvmod_dir));
962 	if (moddir == NULL) {
963 		(void) fprintf(stderr, gettext(ERR_NO_MEM));
964 		return (ERROR);
965 	}
966 
967 	if (sysinfo(SI_ARCHITECTURE, arch, sizeof (arch)) == -1) {
968 		(void) fprintf(stderr, gettext(ERR_SYSINFO_ARCH));
969 		return (ERROR);
970 	}
971 
972 	if (strcmp(arch, "sparc") == 0 || strcmp(arch, "i386") == 0) {
973 		moddir->next = (struct drvmod_dir *)
974 		    calloc(1, sizeof (struct drvmod_dir));
975 		if (moddir->next == NULL) {
976 			(void) fprintf(stderr, gettext(ERR_NO_MEM));
977 			return (ERROR);
978 		}
979 		if (kelf_type == ELFCLASS64) {
980 			(void) strcpy(moddir->direc, DRVDIR64);
981 			(void) strcpy(moddir->next->direc, "");
982 		} else {
983 			(void) strcpy(moddir->direc, "");
984 			(void) strcpy(moddir->next->direc, DRVDIR64);
985 		}
986 		moddir->next->next = NULL;
987 		return (NOERR);
988 	} else {
989 		(void) fprintf(stderr, gettext(ERR_ARCH_NOT_SUPPORTED), arch);
990 		return (ERROR);
991 	}
992 }
993 
994 void
995 remove_slashes(char *path)
996 {
997 	char *slash = path;
998 	char *remain_str;
999 	int pathlen;
1000 
1001 	while ((slash = strchr(slash, '/')) != NULL) {
1002 		remain_str = ++slash;
1003 		while (*remain_str == '/')
1004 			++remain_str;
1005 		if (slash != remain_str)
1006 			(void) strcpy(slash, remain_str);
1007 	}
1008 
1009 	pathlen = strlen(path);
1010 	if ((pathlen > 1) && path[pathlen - 1] == '/')
1011 		path[pathlen - 1] = '\0';
1012 }
1013 
1014 /*
1015  * This is for ITU floppies to add packages to the miniroot
1016  */
1017 static int
1018 ignore_root_basedir(void)
1019 {
1020 	struct stat statbuf;
1021 
1022 	return (stat("/ADD_DRV_IGNORE_ROOT_BASEDIR", &statbuf) == 0);
1023 }
1024