Home | History | Annotate | Download | only in modload
      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