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