Home | History | Annotate | Download | only in common
      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 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <alloca.h>
     28 #include <ctype.h>
     29 #include <limits.h>
     30 #include <syslog.h>
     31 #include <strings.h>
     32 #include <unistd.h>
     33 
     34 #include <topo_error.h>
     35 #include <topo_subr.h>
     36 
     37 struct _rwlock;
     38 struct _lwp_mutex;
     39 
     40 int
     41 topo_rw_read_held(pthread_rwlock_t *lock)
     42 {
     43 	extern int _rw_read_held(struct _rwlock *);
     44 	return (_rw_read_held((struct _rwlock *)lock));
     45 }
     46 
     47 int
     48 topo_rw_write_held(pthread_rwlock_t *lock)
     49 {
     50 	extern int _rw_write_held(struct _rwlock *);
     51 	return (_rw_write_held((struct _rwlock *)lock));
     52 }
     53 
     54 int
     55 topo_mutex_held(pthread_mutex_t *lock)
     56 {
     57 	extern int _mutex_held(struct _lwp_mutex *);
     58 	return (_mutex_held((struct _lwp_mutex *)lock));
     59 }
     60 
     61 void
     62 topo_hdl_lock(topo_hdl_t *thp)
     63 {
     64 	(void) pthread_mutex_lock(&thp->th_lock);
     65 }
     66 
     67 void
     68 topo_hdl_unlock(topo_hdl_t *thp)
     69 {
     70 	(void) pthread_mutex_unlock(&thp->th_lock);
     71 }
     72 
     73 const char *
     74 topo_stability2name(topo_stability_t s)
     75 {
     76 	switch (s) {
     77 	case TOPO_STABILITY_INTERNAL:	return (TOPO_STABSTR_INTERNAL);
     78 	case TOPO_STABILITY_PRIVATE:	return (TOPO_STABSTR_PRIVATE);
     79 	case TOPO_STABILITY_OBSOLETE:	return (TOPO_STABSTR_OBSOLETE);
     80 	case TOPO_STABILITY_EXTERNAL:	return (TOPO_STABSTR_EXTERNAL);
     81 	case TOPO_STABILITY_UNSTABLE:	return (TOPO_STABSTR_UNSTABLE);
     82 	case TOPO_STABILITY_EVOLVING:	return (TOPO_STABSTR_EVOLVING);
     83 	case TOPO_STABILITY_STABLE:	return (TOPO_STABSTR_STABLE);
     84 	case TOPO_STABILITY_STANDARD:	return (TOPO_STABSTR_STANDARD);
     85 	default:			return (TOPO_STABSTR_UNKNOWN);
     86 	}
     87 }
     88 
     89 topo_stability_t
     90 topo_name2stability(const char *name)
     91 {
     92 	if (strcmp(name, TOPO_STABSTR_INTERNAL) == 0)
     93 		return (TOPO_STABILITY_INTERNAL);
     94 	else if (strcmp(name, TOPO_STABSTR_PRIVATE) == 0)
     95 		return (TOPO_STABILITY_PRIVATE);
     96 	else if (strcmp(name, TOPO_STABSTR_OBSOLETE) == 0)
     97 		return (TOPO_STABILITY_OBSOLETE);
     98 	else if (strcmp(name, TOPO_STABSTR_EXTERNAL) == 0)
     99 		return (TOPO_STABILITY_EXTERNAL);
    100 	else if (strcmp(name, TOPO_STABSTR_UNSTABLE) == 0)
    101 		return (TOPO_STABILITY_UNSTABLE);
    102 	else if (strcmp(name, TOPO_STABSTR_EVOLVING) == 0)
    103 		return (TOPO_STABILITY_EVOLVING);
    104 	else if (strcmp(name, TOPO_STABSTR_STABLE) == 0)
    105 		return (TOPO_STABILITY_STABLE);
    106 	else if (strcmp(name, TOPO_STABSTR_STANDARD) == 0)
    107 		return (TOPO_STABILITY_STANDARD);
    108 
    109 	return (TOPO_STABILITY_UNKNOWN);
    110 }
    111 
    112 static const topo_debug_mode_t _topo_dbout_modes[] = {
    113 	{ "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR },
    114 	{ "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG },
    115 	{ NULL, NULL, 0 }
    116 };
    117 
    118 static const topo_debug_mode_t _topo_dbflag_modes[] = {
    119 	{ "error", "error handling debug messages enabled", TOPO_DBG_ERR },
    120 	{ "module", "module debug messages enabled", TOPO_DBG_MOD },
    121 	{ "modulesvc", "module services debug messages enabled",
    122 	    TOPO_DBG_MODSVC },
    123 	{ "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK },
    124 	{ "xml", "xml file parsing messages enabled", TOPO_DBG_XML },
    125 	{ "all", "all debug modes enabled", TOPO_DBG_ALL},
    126 	{ NULL, NULL, 0 }
    127 };
    128 
    129 void
    130 env_process_value(topo_hdl_t *thp, const char *begin, const char *end)
    131 {
    132 	char buf[MAXNAMELEN];
    133 	size_t count;
    134 	topo_debug_mode_t *dbp;
    135 
    136 	while (begin < end && isspace(*begin))
    137 		begin++;
    138 
    139 	while (begin < end && isspace(*(end - 1)))
    140 		end--;
    141 
    142 	if (begin >= end)
    143 		return;
    144 
    145 	count = end - begin;
    146 	count += 1;
    147 
    148 	if (count > sizeof (buf))
    149 		return;
    150 
    151 	(void) snprintf(buf, count, "%s", begin);
    152 
    153 	for (dbp = (topo_debug_mode_t *)_topo_dbflag_modes;
    154 	    dbp->tdm_name != NULL; ++dbp) {
    155 		if (strcmp(buf, dbp->tdm_name) == 0)
    156 			thp->th_debug |= dbp->tdm_mode;
    157 	}
    158 }
    159 
    160 void
    161 topo_debug_set(topo_hdl_t *thp, const char *dbmode, const char *dout)
    162 {
    163 	char *end, *value, *next;
    164 	topo_debug_mode_t *dbp;
    165 
    166 	topo_hdl_lock(thp);
    167 	value = (char *)dbmode;
    168 
    169 	for (end = (char *)dbmode; *end != '\0'; value = next) {
    170 		end = strchr(value, ',');
    171 		if (end != NULL)
    172 			next = end + 1;	/* skip the comma */
    173 		else
    174 			next = end = value + strlen(value);
    175 
    176 		env_process_value(thp, value, end);
    177 	}
    178 
    179 	if (dout == NULL) {
    180 		topo_hdl_unlock(thp);
    181 		return;
    182 	}
    183 
    184 	for (dbp = (topo_debug_mode_t *)_topo_dbout_modes;
    185 	    dbp->tdm_name != NULL; ++dbp) {
    186 		if (strcmp(dout, dbp->tdm_name) == 0)
    187 		thp->th_dbout = dbp->tdm_mode;
    188 	}
    189 	topo_hdl_unlock(thp);
    190 }
    191 
    192 void
    193 topo_vdprintf(topo_hdl_t *thp, int mask, const char *mod, const char *format,
    194     va_list ap)
    195 {
    196 	char *msg;
    197 	size_t len;
    198 	char c;
    199 
    200 	if (!(thp->th_debug & mask))
    201 		return;
    202 
    203 	len = vsnprintf(&c, 1, format, ap);
    204 	msg = alloca(len + 2);
    205 	(void) vsnprintf(msg, len + 1, format, ap);
    206 
    207 	if (msg[len - 1] != '\n')
    208 		(void) strcpy(&msg[len], "\n");
    209 
    210 	if (thp->th_dbout == TOPO_DBOUT_SYSLOG) {
    211 		if (mod == NULL) {
    212 			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg);
    213 		} else {
    214 			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s: %s",
    215 			    mod, msg);
    216 		}
    217 	} else {
    218 		if (mod == NULL) {
    219 			(void) fprintf(stderr, "libtopo DEBUG: %s", msg);
    220 		} else {
    221 			(void) fprintf(stderr, "libtopo DEBUG: %s: %s", mod,
    222 			    msg);
    223 		}
    224 	}
    225 }
    226 
    227 /*PRINTFLIKE3*/
    228 void
    229 topo_dprintf(topo_hdl_t *thp, int mask, const char *format, ...)
    230 {
    231 	va_list ap;
    232 
    233 	va_start(ap, format);
    234 	topo_vdprintf(thp, mask, NULL, format, ap);
    235 	va_end(ap);
    236 }
    237 
    238 tnode_t *
    239 topo_hdl_root(topo_hdl_t *thp, const char *scheme)
    240 {
    241 	ttree_t *tp;
    242 
    243 	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
    244 	    tp = topo_list_next(tp)) {
    245 		if (strcmp(scheme, tp->tt_scheme) == 0)
    246 			return (tp->tt_root);
    247 	}
    248 
    249 	return (NULL);
    250 }
    251 
    252 /*
    253  * buf_append -- Append str to buf (if it's non-NULL).  Place prepend
    254  * in buf in front of str and append behind it (if they're non-NULL).
    255  * Continue to update size even if we run out of space to actually
    256  * stuff characters in the buffer.
    257  */
    258 void
    259 topo_fmristr_build(ssize_t *sz, char *buf, size_t buflen, char *str,
    260     char *prepend, char *append)
    261 {
    262 	ssize_t left;
    263 
    264 	if (str == NULL)
    265 		return;
    266 
    267 	if (buflen == 0 || (left = buflen - *sz) < 0)
    268 		left = 0;
    269 
    270 	if (buf != NULL && left != 0)
    271 		buf += *sz;
    272 
    273 	if (prepend == NULL && append == NULL)
    274 		*sz += snprintf(buf, left, "%s", str);
    275 	else if (append == NULL)
    276 		*sz += snprintf(buf, left, "%s%s", prepend, str);
    277 	else if (prepend == NULL)
    278 		*sz += snprintf(buf, left, "%s%s", str, append);
    279 	else
    280 		*sz += snprintf(buf, left, "%s%s%s", prepend, str, append);
    281 }
    282 
    283 #define	TOPO_PLATFORM_PATH	"%s/usr/platform/%s/lib/fm/topo/%s"
    284 #define	TOPO_COMMON_PATH	"%s/usr/lib/fm/topo/%s"
    285 
    286 char *
    287 topo_search_path(topo_mod_t *mod, const char *rootdir, const char *file)
    288 {
    289 	char *pp, sp[PATH_MAX];
    290 	topo_hdl_t *thp = mod->tm_hdl;
    291 
    292 	/*
    293 	 * Search for file name in order of platform, machine and common
    294 	 * topo directories
    295 	 */
    296 	(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH, rootdir,
    297 	    thp->th_platform, file);
    298 	if (access(sp, F_OK) != 0) {
    299 		(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH,
    300 		    thp->th_rootdir, thp->th_machine, file);
    301 		if (access(sp, F_OK) != 0) {
    302 			(void) snprintf(sp, PATH_MAX, TOPO_COMMON_PATH,
    303 			    thp->th_rootdir, file);
    304 			if (access(sp, F_OK) != 0) {
    305 				return (NULL);
    306 			}
    307 		}
    308 	}
    309 
    310 	pp = topo_mod_strdup(mod, sp);
    311 
    312 	return (pp);
    313 }
    314 
    315 /*
    316  * SMBIOS serial numbers can contain characters (particularly ':' and ' ')
    317  * that are invalid for the authority and can break FMRI parsing.  We translate
    318  * any invalid characters to a safe '-', as well as trimming any leading or
    319  * trailing whitespace.  Similarly, '/' can be found in some product names
    320  * so we translate that to '-'.
    321  */
    322 char *
    323 topo_cleanup_auth_str(topo_hdl_t *thp, const char *begin)
    324 {
    325 	char buf[MAXNAMELEN];
    326 	const char *end, *cp;
    327 	char *pp;
    328 	char c;
    329 	int i;
    330 
    331 	end = begin + strlen(begin);
    332 
    333 	while (begin < end && isspace(*begin))
    334 		begin++;
    335 	while (begin < end && isspace(*(end - 1)))
    336 		end--;
    337 
    338 	if (begin >= end)
    339 		return (NULL);
    340 
    341 	cp = begin;
    342 	for (i = 0; i < MAXNAMELEN - 1; i++) {
    343 		if (cp >= end)
    344 			break;
    345 		c = *cp;
    346 		if (c == ':' || c == '=' || c == '/' || isspace(c) ||
    347 		    !isprint(c))
    348 			buf[i] = '-';
    349 		else
    350 			buf[i] = c;
    351 		cp++;
    352 	}
    353 	buf[i] = 0;
    354 
    355 	pp = topo_hdl_strdup(thp, buf);
    356 	return (pp);
    357 }
    358 
    359 void
    360 topo_sensor_type_name(uint32_t type, char *buf, size_t len)
    361 {
    362 	topo_name_trans_t *ntp;
    363 
    364 	for (ntp = &topo_sensor_type_table[0]; ntp->int_name != NULL; ntp++) {
    365 		if (ntp->int_value == type) {
    366 			(void) strlcpy(buf, ntp->int_name, len);
    367 			return;
    368 		}
    369 	}
    370 
    371 	(void) snprintf(buf, len, "0x%02x", type);
    372 }
    373 
    374 void
    375 topo_sensor_units_name(uint8_t type, char *buf, size_t len)
    376 {
    377 	topo_name_trans_t *ntp;
    378 
    379 	for (ntp = &topo_units_type_table[0]; ntp->int_name != NULL; ntp++) {
    380 		if (ntp->int_value == type) {
    381 			(void) strlcpy(buf, ntp->int_name, len);
    382 			return;
    383 		}
    384 	}
    385 
    386 	(void) snprintf(buf, len, "0x%02x", type);
    387 }
    388 
    389 void
    390 topo_led_type_name(uint8_t type, char *buf, size_t len)
    391 {
    392 	topo_name_trans_t *ntp;
    393 
    394 	for (ntp = &topo_led_type_table[0]; ntp->int_name != NULL; ntp++) {
    395 		if (ntp->int_value == type) {
    396 			(void) strlcpy(buf, ntp->int_name, len);
    397 			return;
    398 		}
    399 	}
    400 
    401 	(void) snprintf(buf, len, "0x%02x", type);
    402 }
    403 
    404 void
    405 topo_led_state_name(uint8_t type, char *buf, size_t len)
    406 {
    407 	topo_name_trans_t *ntp;
    408 
    409 	for (ntp = &topo_led_states_table[0]; ntp->int_name != NULL; ntp++) {
    410 		if (ntp->int_value == type) {
    411 			(void) strlcpy(buf, ntp->int_name, len);
    412 			return;
    413 		}
    414 	}
    415 
    416 	(void) snprintf(buf, len, "0x%02x", type);
    417 }
    418 
    419 void
    420 topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf,
    421 size_t len)
    422 {
    423 	topo_name_trans_t *ntp;
    424 
    425 	switch (sensor_type) {
    426 		case TOPO_SENSOR_TYPE_PHYSICAL:
    427 			ntp = &topo_sensor_states_physical_table[0];
    428 			break;
    429 		case TOPO_SENSOR_TYPE_PLATFORM:
    430 			ntp = &topo_sensor_states_platform_table[0];
    431 			break;
    432 		case TOPO_SENSOR_TYPE_PROCESSOR:
    433 			ntp = &topo_sensor_states_processor_table[0];
    434 			break;
    435 		case TOPO_SENSOR_TYPE_POWER_SUPPLY:
    436 			ntp = &topo_sensor_states_power_supply_table[0];
    437 			break;
    438 		case TOPO_SENSOR_TYPE_POWER_UNIT:
    439 			ntp = &topo_sensor_states_power_unit_table[0];
    440 			break;
    441 		case TOPO_SENSOR_TYPE_MEMORY:
    442 			ntp = &topo_sensor_states_memory_table[0];
    443 			break;
    444 		case TOPO_SENSOR_TYPE_BAY:
    445 			ntp = &topo_sensor_states_bay_table[0];
    446 			break;
    447 		case TOPO_SENSOR_TYPE_FIRMWARE:
    448 			ntp = &topo_sensor_states_firmware_table[0];
    449 			break;
    450 		case TOPO_SENSOR_TYPE_EVENT_LOG:
    451 			ntp = &topo_sensor_states_event_log_table[0];
    452 			break;
    453 		case TOPO_SENSOR_TYPE_WATCHDOG1:
    454 			ntp = &topo_sensor_states_watchdog1_table[0];
    455 			break;
    456 		case TOPO_SENSOR_TYPE_SYSTEM:
    457 			ntp = &topo_sensor_states_system_table[0];
    458 			break;
    459 		case TOPO_SENSOR_TYPE_CRITICAL:
    460 			ntp = &topo_sensor_states_critical_table[0];
    461 			break;
    462 		case TOPO_SENSOR_TYPE_BUTTON:
    463 			ntp = &topo_sensor_states_button_table[0];
    464 			break;
    465 		case TOPO_SENSOR_TYPE_CABLE:
    466 			ntp = &topo_sensor_states_cable_table[0];
    467 			break;
    468 		case TOPO_SENSOR_TYPE_BOOT_STATE:
    469 			ntp = &topo_sensor_states_boot_state_table[0];
    470 			break;
    471 		case TOPO_SENSOR_TYPE_BOOT_ERROR:
    472 			ntp = &topo_sensor_states_boot_error_table[0];
    473 			break;
    474 		case TOPO_SENSOR_TYPE_BOOT_OS:
    475 			ntp = &topo_sensor_states_boot_os_table[0];
    476 			break;
    477 		case TOPO_SENSOR_TYPE_OS_SHUTDOWN:
    478 			ntp = &topo_sensor_states_os_table[0];
    479 			break;
    480 		case TOPO_SENSOR_TYPE_SLOT:
    481 			ntp = &topo_sensor_states_slot_table[0];
    482 			break;
    483 		case TOPO_SENSOR_TYPE_ACPI:
    484 			ntp = &topo_sensor_states_acpi_table[0];
    485 			break;
    486 		case TOPO_SENSOR_TYPE_WATCHDOG2:
    487 			ntp = &topo_sensor_states_watchdog2_table[0];
    488 			break;
    489 		case TOPO_SENSOR_TYPE_ALERT:
    490 			ntp = &topo_sensor_states_alert_table[0];
    491 			break;
    492 		case TOPO_SENSOR_TYPE_PRESENCE:
    493 			ntp = &topo_sensor_states_presence_table[0];
    494 			break;
    495 		case TOPO_SENSOR_TYPE_LAN:
    496 			ntp = &topo_sensor_states_lan_table[0];
    497 			break;
    498 		case TOPO_SENSOR_TYPE_HEALTH:
    499 			ntp = &topo_sensor_states_health_table[0];
    500 			break;
    501 		case TOPO_SENSOR_TYPE_BATTERY:
    502 			ntp = &topo_sensor_states_battery_table[0];
    503 			break;
    504 		case TOPO_SENSOR_TYPE_AUDIT:
    505 			ntp = &topo_sensor_states_audit_table[0];
    506 			break;
    507 		case TOPO_SENSOR_TYPE_VERSION:
    508 			ntp = &topo_sensor_states_version_table[0];
    509 			break;
    510 		case TOPO_SENSOR_TYPE_FRU_STATE:
    511 			ntp = &topo_sensor_states_fru_state_table[0];
    512 			break;
    513 		case TOPO_SENSOR_TYPE_THRESHOLD_STATE:
    514 			ntp = &topo_sensor_states_thresh_table[0];
    515 			break;
    516 		case TOPO_SENSOR_TYPE_GENERIC_USAGE:
    517 			ntp = &topo_sensor_states_generic_usage_table[0];
    518 			break;
    519 		case TOPO_SENSOR_TYPE_GENERIC_STATE:
    520 			ntp = &topo_sensor_states_generic_state_table[0];
    521 			break;
    522 		case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL:
    523 			ntp = &topo_sensor_states_generic_predfail_table[0];
    524 			break;
    525 		case TOPO_SENSOR_TYPE_GENERIC_LIMIT:
    526 			ntp = &topo_sensor_states_generic_limit_table[0];
    527 			break;
    528 		case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE:
    529 			ntp = &topo_sensor_states_generic_perf_table[0];
    530 			break;
    531 		case TOPO_SENSOR_TYPE_SEVERITY:
    532 			ntp = &topo_sensor_states_severity_table[0];
    533 			break;
    534 		case TOPO_SENSOR_TYPE_GENERIC_PRESENCE:
    535 			ntp = &topo_sensor_states_generic_presence_table[0];
    536 			break;
    537 		case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY:
    538 			ntp = &topo_sensor_states_generic_avail_table[0];
    539 			break;
    540 		case TOPO_SENSOR_TYPE_GENERIC_STATUS:
    541 			ntp = &topo_sensor_states_generic_status_table[0];
    542 			break;
    543 		case TOPO_SENSOR_TYPE_GENERIC_ACPI:
    544 			ntp = &topo_sensor_states_generic_acpi_pwr_table[0];
    545 			break;
    546 		case TOPO_SENSOR_TYPE_GENERIC_FAILURE:
    547 			ntp = &topo_sensor_states_generic_failure_table[0];
    548 			break;
    549 		case TOPO_SENSOR_TYPE_GENERIC_OK:
    550 			ntp = &topo_sensor_states_generic_ok_table[0];
    551 			break;
    552 		default:
    553 			(void) snprintf(buf, len, "0x%02x", state);
    554 			return;
    555 	}
    556 	for (; ntp->int_name != NULL; ntp++) {
    557 		if (ntp->int_value == state) {
    558 			(void) strlcpy(buf, ntp->int_name, len);
    559 			return;
    560 		}
    561 	}
    562 
    563 	(void) snprintf(buf, len, "0x%02x", state);
    564 }
    565