17aec1d6eScindi /*
27aec1d6eScindi  * CDDL HEADER START
37aec1d6eScindi  *
47aec1d6eScindi  * The contents of this file are subject to the terms of the
574a31ce6Stimh  * Common Development and Distribution License (the "License").
674a31ce6Stimh  * You may not use this file except in compliance with the License.
77aec1d6eScindi  *
87aec1d6eScindi  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97aec1d6eScindi  * or http://www.opensolaris.org/os/licensing.
107aec1d6eScindi  * See the License for the specific language governing permissions
117aec1d6eScindi  * and limitations under the License.
127aec1d6eScindi  *
137aec1d6eScindi  * When distributing Covered Code, include this CDDL HEADER in each
147aec1d6eScindi  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157aec1d6eScindi  * If applicable, add the following below this CDDL HEADER, with the
167aec1d6eScindi  * fields enclosed by brackets "[]" replaced with your own identifying
177aec1d6eScindi  * information: Portions Copyright [yyyy] [name of copyright owner]
187aec1d6eScindi  *
197aec1d6eScindi  * CDDL HEADER END
207aec1d6eScindi  */
217aec1d6eScindi 
227aec1d6eScindi /*
238393544eSHyon Kim  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
247aec1d6eScindi  */
258522c52aSRob Johnston /*
26c5591576SRob Johnston  * Copyright 2020 Joyent, Inc.
27*9c994d58SRobert Mustacchi  * Copyright 2023 Oxide Computer Company
288522c52aSRob Johnston  */
297aec1d6eScindi 
307aec1d6eScindi #include <alloca.h>
310eb822a1Scindi #include <ctype.h>
320eb822a1Scindi #include <limits.h>
337aec1d6eScindi #include <syslog.h>
347aec1d6eScindi #include <strings.h>
350eb822a1Scindi #include <unistd.h>
368522c52aSRob Johnston #include <sys/fm/protocol.h>
378522c52aSRob Johnston #include <sys/systeminfo.h>
388522c52aSRob Johnston #include <sys/utsname.h>
397aec1d6eScindi 
407aec1d6eScindi #include <topo_error.h>
41c5591576SRob Johnston #include <topo_digraph.h>
427aec1d6eScindi #include <topo_subr.h>
437aec1d6eScindi 
447aec1d6eScindi void
topo_hdl_lock(topo_hdl_t * thp)457aec1d6eScindi topo_hdl_lock(topo_hdl_t *thp)
467aec1d6eScindi {
477aec1d6eScindi 	(void) pthread_mutex_lock(&thp->th_lock);
487aec1d6eScindi }
497aec1d6eScindi 
507aec1d6eScindi void
topo_hdl_unlock(topo_hdl_t * thp)517aec1d6eScindi topo_hdl_unlock(topo_hdl_t *thp)
527aec1d6eScindi {
537aec1d6eScindi 	(void) pthread_mutex_unlock(&thp->th_lock);
547aec1d6eScindi }
557aec1d6eScindi 
567aec1d6eScindi const char *
topo_stability2name(topo_stability_t s)570eb822a1Scindi topo_stability2name(topo_stability_t s)
587aec1d6eScindi {
597aec1d6eScindi 	switch (s) {
600eb822a1Scindi 	case TOPO_STABILITY_INTERNAL:	return (TOPO_STABSTR_INTERNAL);
610eb822a1Scindi 	case TOPO_STABILITY_PRIVATE:	return (TOPO_STABSTR_PRIVATE);
620eb822a1Scindi 	case TOPO_STABILITY_OBSOLETE:	return (TOPO_STABSTR_OBSOLETE);
630eb822a1Scindi 	case TOPO_STABILITY_EXTERNAL:	return (TOPO_STABSTR_EXTERNAL);
640eb822a1Scindi 	case TOPO_STABILITY_UNSTABLE:	return (TOPO_STABSTR_UNSTABLE);
650eb822a1Scindi 	case TOPO_STABILITY_EVOLVING:	return (TOPO_STABSTR_EVOLVING);
660eb822a1Scindi 	case TOPO_STABILITY_STABLE:	return (TOPO_STABSTR_STABLE);
670eb822a1Scindi 	case TOPO_STABILITY_STANDARD:	return (TOPO_STABSTR_STANDARD);
680eb822a1Scindi 	default:			return (TOPO_STABSTR_UNKNOWN);
697aec1d6eScindi 	}
707aec1d6eScindi }
717aec1d6eScindi 
720eb822a1Scindi topo_stability_t
topo_name2stability(const char * name)730eb822a1Scindi topo_name2stability(const char *name)
740eb822a1Scindi {
750eb822a1Scindi 	if (strcmp(name, TOPO_STABSTR_INTERNAL) == 0)
760eb822a1Scindi 		return (TOPO_STABILITY_INTERNAL);
770eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_PRIVATE) == 0)
780eb822a1Scindi 		return (TOPO_STABILITY_PRIVATE);
790eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_OBSOLETE) == 0)
800eb822a1Scindi 		return (TOPO_STABILITY_OBSOLETE);
810eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_EXTERNAL) == 0)
820eb822a1Scindi 		return (TOPO_STABILITY_EXTERNAL);
830eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_UNSTABLE) == 0)
840eb822a1Scindi 		return (TOPO_STABILITY_UNSTABLE);
850eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_EVOLVING) == 0)
860eb822a1Scindi 		return (TOPO_STABILITY_EVOLVING);
870eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_STABLE) == 0)
880eb822a1Scindi 		return (TOPO_STABILITY_STABLE);
890eb822a1Scindi 	else if (strcmp(name, TOPO_STABSTR_STANDARD) == 0)
900eb822a1Scindi 		return (TOPO_STABILITY_STANDARD);
910eb822a1Scindi 
920eb822a1Scindi 	return (TOPO_STABILITY_UNKNOWN);
930eb822a1Scindi }
940eb822a1Scindi 
957aec1d6eScindi static const topo_debug_mode_t _topo_dbout_modes[] = {
967aec1d6eScindi 	{ "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR },
977aec1d6eScindi 	{ "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG },
987aec1d6eScindi 	{ NULL, NULL, 0 }
997aec1d6eScindi };
1007aec1d6eScindi 
1010eb822a1Scindi static const topo_debug_mode_t _topo_dbflag_modes[] = {
1020eb822a1Scindi 	{ "error", "error handling debug messages enabled", TOPO_DBG_ERR },
1030eb822a1Scindi 	{ "module", "module debug messages enabled", TOPO_DBG_MOD },
1040eb822a1Scindi 	{ "modulesvc", "module services debug messages enabled",
1050eb822a1Scindi 	    TOPO_DBG_MODSVC },
1060eb822a1Scindi 	{ "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK },
1070eb822a1Scindi 	{ "xml", "xml file parsing messages enabled", TOPO_DBG_XML },
1088393544eSHyon Kim 	{ "devinfoforce", "devinfo DINFOFORCE snapshot used", TOPO_DBG_FORCE },
1090eb822a1Scindi 	{ "all", "all debug modes enabled", TOPO_DBG_ALL},
1100eb822a1Scindi 	{ NULL, NULL, 0 }
1110eb822a1Scindi };
1120eb822a1Scindi 
1137aec1d6eScindi void
env_process_value(topo_hdl_t * thp,const char * begin,const char * end)1140eb822a1Scindi env_process_value(topo_hdl_t *thp, const char *begin, const char *end)
1157aec1d6eScindi {
1160eb822a1Scindi 	char buf[MAXNAMELEN];
1170eb822a1Scindi 	size_t count;
1180eb822a1Scindi 	topo_debug_mode_t *dbp;
1190eb822a1Scindi 
1200eb822a1Scindi 	while (begin < end && isspace(*begin))
1210eb822a1Scindi 		begin++;
1220eb822a1Scindi 
1230eb822a1Scindi 	while (begin < end && isspace(*(end - 1)))
1240eb822a1Scindi 		end--;
1250eb822a1Scindi 
1260eb822a1Scindi 	if (begin >= end)
1270eb822a1Scindi 		return;
1280eb822a1Scindi 
1290eb822a1Scindi 	count = end - begin;
1300eb822a1Scindi 	count += 1;
1310eb822a1Scindi 
1320eb822a1Scindi 	if (count > sizeof (buf))
1330eb822a1Scindi 		return;
1340eb822a1Scindi 
1350eb822a1Scindi 	(void) snprintf(buf, count, "%s", begin);
1360eb822a1Scindi 
1370eb822a1Scindi 	for (dbp = (topo_debug_mode_t *)_topo_dbflag_modes;
1380eb822a1Scindi 	    dbp->tdm_name != NULL; ++dbp) {
1390eb822a1Scindi 		if (strcmp(buf, dbp->tdm_name) == 0)
1400eb822a1Scindi 			thp->th_debug |= dbp->tdm_mode;
1410eb822a1Scindi 	}
1420eb822a1Scindi }
1430eb822a1Scindi 
1440eb822a1Scindi void
topo_debug_set(topo_hdl_t * thp,const char * dbmode,const char * dout)1450eb822a1Scindi topo_debug_set(topo_hdl_t *thp, const char *dbmode, const char *dout)
1460eb822a1Scindi {
1470eb822a1Scindi 	char *end, *value, *next;
1480eb822a1Scindi 	topo_debug_mode_t *dbp;
1490eb822a1Scindi 
1500eb822a1Scindi 	topo_hdl_lock(thp);
1510eb822a1Scindi 	value = (char *)dbmode;
1520eb822a1Scindi 
1530eb822a1Scindi 	for (end = (char *)dbmode; *end != '\0'; value = next) {
1540eb822a1Scindi 		end = strchr(value, ',');
1550eb822a1Scindi 		if (end != NULL)
1560eb822a1Scindi 			next = end + 1;	/* skip the comma */
1570eb822a1Scindi 		else
1580eb822a1Scindi 			next = end = value + strlen(value);
1590eb822a1Scindi 
1600eb822a1Scindi 		env_process_value(thp, value, end);
1610eb822a1Scindi 	}
1620eb822a1Scindi 
1630eb822a1Scindi 	if (dout == NULL) {
1640eb822a1Scindi 		topo_hdl_unlock(thp);
1650eb822a1Scindi 		return;
1667aec1d6eScindi 	}
1670eb822a1Scindi 
1680eb822a1Scindi 	for (dbp = (topo_debug_mode_t *)_topo_dbout_modes;
1690eb822a1Scindi 	    dbp->tdm_name != NULL; ++dbp) {
1700eb822a1Scindi 		if (strcmp(dout, dbp->tdm_name) == 0)
1711e95bfe1SRob Johnston 			thp->th_dbout = dbp->tdm_mode;
1720eb822a1Scindi 	}
1730eb822a1Scindi 	topo_hdl_unlock(thp);
1747aec1d6eScindi }
1757aec1d6eScindi 
1767aec1d6eScindi void
topo_vdprintf(topo_hdl_t * thp,const char * mod,const char * format,va_list ap)1771de1e652SRob Johnston topo_vdprintf(topo_hdl_t *thp, const char *mod, const char *format, va_list ap)
1787aec1d6eScindi {
1797aec1d6eScindi 	char *msg;
1807aec1d6eScindi 	size_t len;
1817aec1d6eScindi 	char c;
1827aec1d6eScindi 
1837aec1d6eScindi 	len = vsnprintf(&c, 1, format, ap);
1847aec1d6eScindi 	msg = alloca(len + 2);
1857aec1d6eScindi 	(void) vsnprintf(msg, len + 1, format, ap);
1867aec1d6eScindi 
1877aec1d6eScindi 	if (msg[len - 1] != '\n')
1887aec1d6eScindi 		(void) strcpy(&msg[len], "\n");
1897aec1d6eScindi 
1900eb822a1Scindi 	if (thp->th_dbout == TOPO_DBOUT_SYSLOG) {
1910eb822a1Scindi 		if (mod == NULL) {
1920eb822a1Scindi 			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg);
1930eb822a1Scindi 		} else {
1940eb822a1Scindi 			syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s: %s",
1950eb822a1Scindi 			    mod, msg);
1960eb822a1Scindi 		}
1970eb822a1Scindi 	} else {
1980eb822a1Scindi 		if (mod == NULL) {
1990eb822a1Scindi 			(void) fprintf(stderr, "libtopo DEBUG: %s", msg);
2000eb822a1Scindi 		} else {
2010eb822a1Scindi 			(void) fprintf(stderr, "libtopo DEBUG: %s: %s", mod,
2020eb822a1Scindi 			    msg);
2030eb822a1Scindi 		}
2040eb822a1Scindi 	}
2057aec1d6eScindi }
2067aec1d6eScindi 
2070eb822a1Scindi /*PRINTFLIKE3*/
2087aec1d6eScindi void
topo_dprintf(topo_hdl_t * thp,int mask,const char * format,...)2090eb822a1Scindi topo_dprintf(topo_hdl_t *thp, int mask, const char *format, ...)
2107aec1d6eScindi {
2117aec1d6eScindi 	va_list ap;
2127aec1d6eScindi 
2131de1e652SRob Johnston 	if (!(thp->th_debug & mask))
2141de1e652SRob Johnston 		return;
2151de1e652SRob Johnston 
2167aec1d6eScindi 	va_start(ap, format);
2171de1e652SRob Johnston 	topo_vdprintf(thp, NULL, format, ap);
2187aec1d6eScindi 	va_end(ap);
2197aec1d6eScindi }
2207aec1d6eScindi 
2217aec1d6eScindi tnode_t *
topo_hdl_root(topo_hdl_t * thp,const char * scheme)2227aec1d6eScindi topo_hdl_root(topo_hdl_t *thp, const char *scheme)
2237aec1d6eScindi {
2247aec1d6eScindi 	ttree_t *tp;
225c5591576SRob Johnston 	topo_digraph_t *tdg;
2267aec1d6eScindi 
2277aec1d6eScindi 	for (tp = topo_list_next(&thp->th_trees); tp != NULL;
2287aec1d6eScindi 	    tp = topo_list_next(tp)) {
2297aec1d6eScindi 		if (strcmp(scheme, tp->tt_scheme) == 0)
2307aec1d6eScindi 			return (tp->tt_root);
2317aec1d6eScindi 	}
232c5591576SRob Johnston 	for (tdg = topo_list_next(&thp->th_digraphs); tdg != NULL;
233c5591576SRob Johnston 	    tdg = topo_list_next(tdg)) {
234c5591576SRob Johnston 		if (strcmp(scheme, tdg->tdg_scheme) == 0)
235c5591576SRob Johnston 			return (tdg->tdg_rootnode);
236c5591576SRob Johnston 	}
2377aec1d6eScindi 
2387aec1d6eScindi 	return (NULL);
2397aec1d6eScindi }
24074a31ce6Stimh 
24174a31ce6Stimh /*
24274a31ce6Stimh  * buf_append -- Append str to buf (if it's non-NULL).  Place prepend
24374a31ce6Stimh  * in buf in front of str and append behind it (if they're non-NULL).
24474a31ce6Stimh  * Continue to update size even if we run out of space to actually
24574a31ce6Stimh  * stuff characters in the buffer.
24674a31ce6Stimh  */
24774a31ce6Stimh void
topo_fmristr_build(ssize_t * sz,char * buf,size_t buflen,char * str,char * prepend,char * append)24874a31ce6Stimh topo_fmristr_build(ssize_t *sz, char *buf, size_t buflen, char *str,
24974a31ce6Stimh     char *prepend, char *append)
25074a31ce6Stimh {
25174a31ce6Stimh 	ssize_t left;
25274a31ce6Stimh 
25374a31ce6Stimh 	if (str == NULL)
25474a31ce6Stimh 		return;
25574a31ce6Stimh 
25674a31ce6Stimh 	if (buflen == 0 || (left = buflen - *sz) < 0)
25774a31ce6Stimh 		left = 0;
25874a31ce6Stimh 
25974a31ce6Stimh 	if (buf != NULL && left != 0)
26074a31ce6Stimh 		buf += *sz;
26174a31ce6Stimh 
26274a31ce6Stimh 	if (prepend == NULL && append == NULL)
26374a31ce6Stimh 		*sz += snprintf(buf, left, "%s", str);
26474a31ce6Stimh 	else if (append == NULL)
26574a31ce6Stimh 		*sz += snprintf(buf, left, "%s%s", prepend, str);
26674a31ce6Stimh 	else if (prepend == NULL)
26774a31ce6Stimh 		*sz += snprintf(buf, left, "%s%s", str, append);
26874a31ce6Stimh 	else
26974a31ce6Stimh 		*sz += snprintf(buf, left, "%s%s%s", prepend, str, append);
27074a31ce6Stimh }
2710eb822a1Scindi 
2720eb822a1Scindi #define	TOPO_PLATFORM_PATH	"%s/usr/platform/%s/lib/fm/topo/%s"
2730eb822a1Scindi #define	TOPO_COMMON_PATH	"%s/usr/lib/fm/topo/%s"
2740eb822a1Scindi 
2750eb822a1Scindi char *
topo_search_path(topo_mod_t * mod,const char * rootdir,const char * file)2760eb822a1Scindi topo_search_path(topo_mod_t *mod, const char *rootdir, const char *file)
2770eb822a1Scindi {
2780eb822a1Scindi 	char *pp, sp[PATH_MAX];
2790eb822a1Scindi 	topo_hdl_t *thp = mod->tm_hdl;
2800eb822a1Scindi 
2810eb822a1Scindi 	/*
2820eb822a1Scindi 	 * Search for file name in order of platform, machine and common
2830eb822a1Scindi 	 * topo directories
2840eb822a1Scindi 	 */
2850eb822a1Scindi 	(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH, rootdir,
2860eb822a1Scindi 	    thp->th_platform, file);
2870eb822a1Scindi 	if (access(sp, F_OK) != 0) {
2880eb822a1Scindi 		(void) snprintf(sp, PATH_MAX, TOPO_PLATFORM_PATH,
2890eb822a1Scindi 		    thp->th_rootdir, thp->th_machine, file);
2900eb822a1Scindi 		if (access(sp, F_OK) != 0) {
2910eb822a1Scindi 			(void) snprintf(sp, PATH_MAX, TOPO_COMMON_PATH,
2920eb822a1Scindi 			    thp->th_rootdir, file);
2930eb822a1Scindi 			if (access(sp, F_OK) != 0) {
2940eb822a1Scindi 				return (NULL);
2950eb822a1Scindi 			}
2960eb822a1Scindi 		}
2970eb822a1Scindi 	}
2980eb822a1Scindi 
2990eb822a1Scindi 	pp = topo_mod_strdup(mod, sp);
3000eb822a1Scindi 
3010eb822a1Scindi 	return (pp);
3020eb822a1Scindi }
30324db4641Seschrock 
30424db4641Seschrock /*
305*9c994d58SRobert Mustacchi  * SMBIOS serial numbers (and many other strings from devices) can contain
306*9c994d58SRobert Mustacchi  * characters (particularly ':' and ' ') that are invalid for the authority and
307*9c994d58SRobert Mustacchi  * can break FMRI parsing.  We translate any invalid characters to a safe '-',
308*9c994d58SRobert Mustacchi  * as well as trimming any leading or trailing whitespace.  Similarly, '/' can
309*9c994d58SRobert Mustacchi  * be found in some product names so we translate that to '-'.
31024db4641Seschrock  */
31124db4641Seschrock char *
topo_cleanup_strn(topo_hdl_t * thp,const char * begin,size_t max)312*9c994d58SRobert Mustacchi topo_cleanup_strn(topo_hdl_t *thp, const char *begin, size_t max)
31324db4641Seschrock {
31424db4641Seschrock 	char buf[MAXNAMELEN];
315e3d60c9bSAdrian Frost 	const char *end, *cp;
316e3d60c9bSAdrian Frost 	char *pp;
317e3d60c9bSAdrian Frost 	char c;
318*9c994d58SRobert Mustacchi 	size_t i;
31924db4641Seschrock 
320*9c994d58SRobert Mustacchi 	end = begin + max;
32124db4641Seschrock 
32224db4641Seschrock 	while (begin < end && isspace(*begin))
32324db4641Seschrock 		begin++;
324*9c994d58SRobert Mustacchi 	while (begin < end && (isspace(*(end - 1)) || *(end - 1) == '\0'))
32524db4641Seschrock 		end--;
32624db4641Seschrock 
32724db4641Seschrock 	if (begin >= end)
32824db4641Seschrock 		return (NULL);
32924db4641Seschrock 
330e3d60c9bSAdrian Frost 	cp = begin;
331e3d60c9bSAdrian Frost 	for (i = 0; i < MAXNAMELEN - 1; i++) {
332e3d60c9bSAdrian Frost 		if (cp >= end)
333e3d60c9bSAdrian Frost 			break;
334e3d60c9bSAdrian Frost 		c = *cp;
335e3d60c9bSAdrian Frost 		if (c == ':' || c == '=' || c == '/' || isspace(c) ||
336e3d60c9bSAdrian Frost 		    !isprint(c))
337e3d60c9bSAdrian Frost 			buf[i] = '-';
338e3d60c9bSAdrian Frost 		else
339e3d60c9bSAdrian Frost 			buf[i] = c;
340e3d60c9bSAdrian Frost 		cp++;
341e3d60c9bSAdrian Frost 	}
342e3d60c9bSAdrian Frost 	buf[i] = 0;
34324db4641Seschrock 
34424db4641Seschrock 	pp = topo_hdl_strdup(thp, buf);
34524db4641Seschrock 	return (pp);
34624db4641Seschrock }
347825ba0f2Srobj 
348*9c994d58SRobert Mustacchi char *
topo_cleanup_auth_str(topo_hdl_t * thp,const char * begin)349*9c994d58SRobert Mustacchi topo_cleanup_auth_str(topo_hdl_t *thp, const char *begin)
350*9c994d58SRobert Mustacchi {
351*9c994d58SRobert Mustacchi 	return (topo_cleanup_strn(thp, begin, strlen(begin)));
352*9c994d58SRobert Mustacchi }
353*9c994d58SRobert Mustacchi 
354825ba0f2Srobj void
topo_sensor_type_name(uint32_t type,char * buf,size_t len)355825ba0f2Srobj topo_sensor_type_name(uint32_t type, char *buf, size_t len)
356825ba0f2Srobj {
357825ba0f2Srobj 	topo_name_trans_t *ntp;
358825ba0f2Srobj 
359825ba0f2Srobj 	for (ntp = &topo_sensor_type_table[0]; ntp->int_name != NULL; ntp++) {
360825ba0f2Srobj 		if (ntp->int_value == type) {
361825ba0f2Srobj 			(void) strlcpy(buf, ntp->int_name, len);
362825ba0f2Srobj 			return;
363825ba0f2Srobj 		}
364825ba0f2Srobj 	}
365825ba0f2Srobj 
366825ba0f2Srobj 	(void) snprintf(buf, len, "0x%02x", type);
367825ba0f2Srobj }
368825ba0f2Srobj 
369825ba0f2Srobj void
topo_sensor_units_name(uint8_t type,char * buf,size_t len)370825ba0f2Srobj topo_sensor_units_name(uint8_t type, char *buf, size_t len)
371825ba0f2Srobj {
372825ba0f2Srobj 	topo_name_trans_t *ntp;
373825ba0f2Srobj 
374825ba0f2Srobj 	for (ntp = &topo_units_type_table[0]; ntp->int_name != NULL; ntp++) {
375825ba0f2Srobj 		if (ntp->int_value == type) {
376825ba0f2Srobj 			(void) strlcpy(buf, ntp->int_name, len);
377825ba0f2Srobj 			return;
378825ba0f2Srobj 		}
379825ba0f2Srobj 	}
380825ba0f2Srobj 
381825ba0f2Srobj 	(void) snprintf(buf, len, "0x%02x", type);
382825ba0f2Srobj }
383825ba0f2Srobj 
384825ba0f2Srobj void
topo_led_type_name(uint8_t type,char * buf,size_t len)385825ba0f2Srobj topo_led_type_name(uint8_t type, char *buf, size_t len)
386825ba0f2Srobj {
387825ba0f2Srobj 	topo_name_trans_t *ntp;
388825ba0f2Srobj 
389825ba0f2Srobj 	for (ntp = &topo_led_type_table[0]; ntp->int_name != NULL; ntp++) {
390825ba0f2Srobj 		if (ntp->int_value == type) {
391825ba0f2Srobj 			(void) strlcpy(buf, ntp->int_name, len);
392825ba0f2Srobj 			return;
393825ba0f2Srobj 		}
394825ba0f2Srobj 	}
395825ba0f2Srobj 
396825ba0f2Srobj 	(void) snprintf(buf, len, "0x%02x", type);
397825ba0f2Srobj }
398825ba0f2Srobj 
399825ba0f2Srobj void
topo_led_state_name(uint8_t type,char * buf,size_t len)400825ba0f2Srobj topo_led_state_name(uint8_t type, char *buf, size_t len)
401825ba0f2Srobj {
402825ba0f2Srobj 	topo_name_trans_t *ntp;
403825ba0f2Srobj 
404825ba0f2Srobj 	for (ntp = &topo_led_states_table[0]; ntp->int_name != NULL; ntp++) {
405825ba0f2Srobj 		if (ntp->int_value == type) {
406825ba0f2Srobj 			(void) strlcpy(buf, ntp->int_name, len);
407825ba0f2Srobj 			return;
408825ba0f2Srobj 		}
409825ba0f2Srobj 	}
410825ba0f2Srobj 
411825ba0f2Srobj 	(void) snprintf(buf, len, "0x%02x", type);
412825ba0f2Srobj }
413825ba0f2Srobj 
414825ba0f2Srobj void
topo_sensor_state_name(uint32_t sensor_type,uint8_t state,char * buf,size_t len)415825ba0f2Srobj topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf,
4168522c52aSRob Johnston     size_t len)
417825ba0f2Srobj {
418825ba0f2Srobj 	topo_name_trans_t *ntp;
419825ba0f2Srobj 
420825ba0f2Srobj 	switch (sensor_type) {
421825ba0f2Srobj 		case TOPO_SENSOR_TYPE_PHYSICAL:
422825ba0f2Srobj 			ntp = &topo_sensor_states_physical_table[0];
423825ba0f2Srobj 			break;
424825ba0f2Srobj 		case TOPO_SENSOR_TYPE_PLATFORM:
425825ba0f2Srobj 			ntp = &topo_sensor_states_platform_table[0];
426825ba0f2Srobj 			break;
427825ba0f2Srobj 		case TOPO_SENSOR_TYPE_PROCESSOR:
428825ba0f2Srobj 			ntp = &topo_sensor_states_processor_table[0];
429825ba0f2Srobj 			break;
430825ba0f2Srobj 		case TOPO_SENSOR_TYPE_POWER_SUPPLY:
431825ba0f2Srobj 			ntp = &topo_sensor_states_power_supply_table[0];
432825ba0f2Srobj 			break;
433825ba0f2Srobj 		case TOPO_SENSOR_TYPE_POWER_UNIT:
434825ba0f2Srobj 			ntp = &topo_sensor_states_power_unit_table[0];
435825ba0f2Srobj 			break;
436825ba0f2Srobj 		case TOPO_SENSOR_TYPE_MEMORY:
437825ba0f2Srobj 			ntp = &topo_sensor_states_memory_table[0];
438825ba0f2Srobj 			break;
439825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BAY:
440825ba0f2Srobj 			ntp = &topo_sensor_states_bay_table[0];
441825ba0f2Srobj 			break;
442825ba0f2Srobj 		case TOPO_SENSOR_TYPE_FIRMWARE:
443825ba0f2Srobj 			ntp = &topo_sensor_states_firmware_table[0];
444825ba0f2Srobj 			break;
445825ba0f2Srobj 		case TOPO_SENSOR_TYPE_EVENT_LOG:
446825ba0f2Srobj 			ntp = &topo_sensor_states_event_log_table[0];
447825ba0f2Srobj 			break;
448825ba0f2Srobj 		case TOPO_SENSOR_TYPE_WATCHDOG1:
449825ba0f2Srobj 			ntp = &topo_sensor_states_watchdog1_table[0];
450825ba0f2Srobj 			break;
451825ba0f2Srobj 		case TOPO_SENSOR_TYPE_SYSTEM:
452825ba0f2Srobj 			ntp = &topo_sensor_states_system_table[0];
453825ba0f2Srobj 			break;
454825ba0f2Srobj 		case TOPO_SENSOR_TYPE_CRITICAL:
455825ba0f2Srobj 			ntp = &topo_sensor_states_critical_table[0];
456825ba0f2Srobj 			break;
457825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BUTTON:
458825ba0f2Srobj 			ntp = &topo_sensor_states_button_table[0];
459825ba0f2Srobj 			break;
460825ba0f2Srobj 		case TOPO_SENSOR_TYPE_CABLE:
461825ba0f2Srobj 			ntp = &topo_sensor_states_cable_table[0];
462825ba0f2Srobj 			break;
463825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BOOT_STATE:
464825ba0f2Srobj 			ntp = &topo_sensor_states_boot_state_table[0];
465825ba0f2Srobj 			break;
466825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BOOT_ERROR:
467825ba0f2Srobj 			ntp = &topo_sensor_states_boot_error_table[0];
468825ba0f2Srobj 			break;
469825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BOOT_OS:
470825ba0f2Srobj 			ntp = &topo_sensor_states_boot_os_table[0];
471825ba0f2Srobj 			break;
472825ba0f2Srobj 		case TOPO_SENSOR_TYPE_OS_SHUTDOWN:
473825ba0f2Srobj 			ntp = &topo_sensor_states_os_table[0];
474825ba0f2Srobj 			break;
475825ba0f2Srobj 		case TOPO_SENSOR_TYPE_SLOT:
476825ba0f2Srobj 			ntp = &topo_sensor_states_slot_table[0];
477825ba0f2Srobj 			break;
478825ba0f2Srobj 		case TOPO_SENSOR_TYPE_ACPI:
479825ba0f2Srobj 			ntp = &topo_sensor_states_acpi_table[0];
480825ba0f2Srobj 			break;
481825ba0f2Srobj 		case TOPO_SENSOR_TYPE_WATCHDOG2:
482825ba0f2Srobj 			ntp = &topo_sensor_states_watchdog2_table[0];
483825ba0f2Srobj 			break;
484825ba0f2Srobj 		case TOPO_SENSOR_TYPE_ALERT:
485825ba0f2Srobj 			ntp = &topo_sensor_states_alert_table[0];
486825ba0f2Srobj 			break;
487825ba0f2Srobj 		case TOPO_SENSOR_TYPE_PRESENCE:
488825ba0f2Srobj 			ntp = &topo_sensor_states_presence_table[0];
489825ba0f2Srobj 			break;
490825ba0f2Srobj 		case TOPO_SENSOR_TYPE_LAN:
491825ba0f2Srobj 			ntp = &topo_sensor_states_lan_table[0];
492825ba0f2Srobj 			break;
493825ba0f2Srobj 		case TOPO_SENSOR_TYPE_HEALTH:
494825ba0f2Srobj 			ntp = &topo_sensor_states_health_table[0];
495825ba0f2Srobj 			break;
496825ba0f2Srobj 		case TOPO_SENSOR_TYPE_BATTERY:
497825ba0f2Srobj 			ntp = &topo_sensor_states_battery_table[0];
498825ba0f2Srobj 			break;
499825ba0f2Srobj 		case TOPO_SENSOR_TYPE_AUDIT:
500825ba0f2Srobj 			ntp = &topo_sensor_states_audit_table[0];
501825ba0f2Srobj 			break;
502825ba0f2Srobj 		case TOPO_SENSOR_TYPE_VERSION:
503825ba0f2Srobj 			ntp = &topo_sensor_states_version_table[0];
504825ba0f2Srobj 			break;
505825ba0f2Srobj 		case TOPO_SENSOR_TYPE_FRU_STATE:
506825ba0f2Srobj 			ntp = &topo_sensor_states_fru_state_table[0];
507825ba0f2Srobj 			break;
508825ba0f2Srobj 		case TOPO_SENSOR_TYPE_THRESHOLD_STATE:
509825ba0f2Srobj 			ntp = &topo_sensor_states_thresh_table[0];
510825ba0f2Srobj 			break;
511825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_USAGE:
512825ba0f2Srobj 			ntp = &topo_sensor_states_generic_usage_table[0];
513825ba0f2Srobj 			break;
514825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_STATE:
515825ba0f2Srobj 			ntp = &topo_sensor_states_generic_state_table[0];
516825ba0f2Srobj 			break;
517825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL:
518825ba0f2Srobj 			ntp = &topo_sensor_states_generic_predfail_table[0];
519825ba0f2Srobj 			break;
520825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_LIMIT:
521825ba0f2Srobj 			ntp = &topo_sensor_states_generic_limit_table[0];
522825ba0f2Srobj 			break;
523825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE:
524825ba0f2Srobj 			ntp = &topo_sensor_states_generic_perf_table[0];
525825ba0f2Srobj 			break;
526825ba0f2Srobj 		case TOPO_SENSOR_TYPE_SEVERITY:
527825ba0f2Srobj 			ntp = &topo_sensor_states_severity_table[0];
528825ba0f2Srobj 			break;
529825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_PRESENCE:
530825ba0f2Srobj 			ntp = &topo_sensor_states_generic_presence_table[0];
531825ba0f2Srobj 			break;
532825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY:
533825ba0f2Srobj 			ntp = &topo_sensor_states_generic_avail_table[0];
534825ba0f2Srobj 			break;
535825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_STATUS:
536825ba0f2Srobj 			ntp = &topo_sensor_states_generic_status_table[0];
537825ba0f2Srobj 			break;
538825ba0f2Srobj 		case TOPO_SENSOR_TYPE_GENERIC_ACPI:
539825ba0f2Srobj 			ntp = &topo_sensor_states_generic_acpi_pwr_table[0];
540825ba0f2Srobj 			break;
541e5dcf7beSRobert Johnston 		case TOPO_SENSOR_TYPE_GENERIC_FAILURE:
542e5dcf7beSRobert Johnston 			ntp = &topo_sensor_states_generic_failure_table[0];
543e5dcf7beSRobert Johnston 			break;
544e5dcf7beSRobert Johnston 		case TOPO_SENSOR_TYPE_GENERIC_OK:
545e5dcf7beSRobert Johnston 			ntp = &topo_sensor_states_generic_ok_table[0];
546e5dcf7beSRobert Johnston 			break;
547825ba0f2Srobj 		default:
548825ba0f2Srobj 			(void) snprintf(buf, len, "0x%02x", state);
549825ba0f2Srobj 			return;
550825ba0f2Srobj 	}
551881aaecdSRob Johnston 	if (state == 0) {
552881aaecdSRob Johnston 		(void) snprintf(buf, len, "NO_STATES_ASSERTED");
553881aaecdSRob Johnston 		return;
554881aaecdSRob Johnston 	}
555881aaecdSRob Johnston 	buf[0] = '\0';
556825ba0f2Srobj 	for (; ntp->int_name != NULL; ntp++) {
557881aaecdSRob Johnston 		if (state & ntp->int_value) {
558881aaecdSRob Johnston 			if (buf[0] != '\0')
559881aaecdSRob Johnston 				(void) strlcat(buf, "|", len);
560881aaecdSRob Johnston 			(void) strlcat(buf, ntp->int_name, len);
561825ba0f2Srobj 		}
562825ba0f2Srobj 	}
563825ba0f2Srobj 
564881aaecdSRob Johnston 	if (buf[0] == '\0')
565881aaecdSRob Johnston 		(void) snprintf(buf, len, "0x%02x", state);
566825ba0f2Srobj }
5678522c52aSRob Johnston 
5688522c52aSRob Johnston static const topo_pgroup_info_t sys_pgroup = {
5698522c52aSRob Johnston 	TOPO_PGROUP_SYSTEM,
5708522c52aSRob Johnston 	TOPO_STABILITY_PRIVATE,
5718522c52aSRob Johnston 	TOPO_STABILITY_PRIVATE,
5728522c52aSRob Johnston 	1
5738522c52aSRob Johnston };
5748522c52aSRob Johnston static const topo_pgroup_info_t auth_pgroup = {
5758522c52aSRob Johnston 	FM_FMRI_AUTHORITY,
5768522c52aSRob Johnston 	TOPO_STABILITY_PRIVATE,
5778522c52aSRob Johnston 	TOPO_STABILITY_PRIVATE,
5788522c52aSRob Johnston 	1
5798522c52aSRob Johnston };
5808522c52aSRob Johnston 
5818522c52aSRob Johnston void
topo_pgroup_hcset(tnode_t * node,nvlist_t * auth)5828522c52aSRob Johnston topo_pgroup_hcset(tnode_t *node, nvlist_t *auth)
5838522c52aSRob Johnston {
5848522c52aSRob Johnston 	int err;
5858522c52aSRob Johnston 	char isa[MAXNAMELEN];
5868522c52aSRob Johnston 	struct utsname uts;
5878522c52aSRob Johnston 	char *prod, *psn, *csn, *server;
5888522c52aSRob Johnston 
5898522c52aSRob Johnston 	if (auth == NULL)
5908522c52aSRob Johnston 		return;
5918522c52aSRob Johnston 
5928522c52aSRob Johnston 	if (topo_pgroup_create(node, &auth_pgroup, &err) != 0) {
5938522c52aSRob Johnston 		if (err != ETOPO_PROP_DEFD)
5948522c52aSRob Johnston 			return;
5958522c52aSRob Johnston 	}
5968522c52aSRob Johnston 
5978522c52aSRob Johnston 	/*
5988522c52aSRob Johnston 	 * Inherit if we can, it saves memory
5998522c52aSRob Johnston 	 */
6008522c52aSRob Johnston 	if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT,
6018522c52aSRob Johnston 	    &err) != 0) && (err != ETOPO_PROP_DEFD)) {
6028522c52aSRob Johnston 		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT, &prod) ==
6038522c52aSRob Johnston 		    0)
6048522c52aSRob Johnston 			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
6058522c52aSRob Johnston 			    FM_FMRI_AUTH_PRODUCT, TOPO_PROP_IMMUTABLE, prod,
6068522c52aSRob Johnston 			    &err);
6078522c52aSRob Johnston 	}
6088522c52aSRob Johnston 	if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_PRODUCT_SN,
6098522c52aSRob Johnston 	    &err) != 0) && (err != ETOPO_PROP_DEFD)) {
6108522c52aSRob Johnston 		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN, &psn) ==
6118522c52aSRob Johnston 		    0)
6128522c52aSRob Johnston 			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
6138522c52aSRob Johnston 			    FM_FMRI_AUTH_PRODUCT_SN, TOPO_PROP_IMMUTABLE, psn,
6148522c52aSRob Johnston 			    &err);
6158522c52aSRob Johnston 	}
6168522c52aSRob Johnston 	if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_CHASSIS,
6178522c52aSRob Johnston 	    &err) != 0) && (err != ETOPO_PROP_DEFD)) {
6188522c52aSRob Johnston 		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS, &csn) == 0)
6198522c52aSRob Johnston 			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
6208522c52aSRob Johnston 			    FM_FMRI_AUTH_CHASSIS, TOPO_PROP_IMMUTABLE, csn,
6218522c52aSRob Johnston 			    &err);
6228522c52aSRob Johnston 	}
6238522c52aSRob Johnston 	if ((topo_prop_inherit(node, FM_FMRI_AUTHORITY, FM_FMRI_AUTH_SERVER,
6248522c52aSRob Johnston 	    &err) != 0) && (err != ETOPO_PROP_DEFD)) {
6258522c52aSRob Johnston 		if (nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server) ==
6268522c52aSRob Johnston 		    0)
6278522c52aSRob Johnston 			(void) topo_prop_set_string(node, FM_FMRI_AUTHORITY,
6288522c52aSRob Johnston 			    FM_FMRI_AUTH_SERVER, TOPO_PROP_IMMUTABLE, server,
6298522c52aSRob Johnston 			    &err);
6308522c52aSRob Johnston 	}
6318522c52aSRob Johnston 
6328522c52aSRob Johnston 	if (topo_pgroup_create(node, &sys_pgroup, &err) != 0)
6338522c52aSRob Johnston 		return;
6348522c52aSRob Johnston 
6358522c52aSRob Johnston 	if (sysinfo(SI_ARCHITECTURE, isa, sizeof (isa)) != -1)
6368522c52aSRob Johnston 		(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM,
6378522c52aSRob Johnston 		    TOPO_PROP_ISA, TOPO_PROP_IMMUTABLE, isa, &err);
6388522c52aSRob Johnston 
6398522c52aSRob Johnston 	if (uname(&uts) != -1)
6408522c52aSRob Johnston 		(void) topo_prop_set_string(node, TOPO_PGROUP_SYSTEM,
6418522c52aSRob Johnston 		    TOPO_PROP_MACHINE, TOPO_PROP_IMMUTABLE, uts.machine, &err);
6428522c52aSRob Johnston }
643