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