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