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