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.
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.
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]
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
33 #include <topo_error.h>
34 #include <topo_subr.h>
37 topo_hdl_lock(topo_hdl_t
*thp
)
39 (void) pthread_mutex_lock(&thp
->th_lock
);
43 topo_hdl_unlock(topo_hdl_t
*thp
)
45 (void) pthread_mutex_unlock(&thp
->th_lock
);
49 topo_stability2name(topo_stability_t s
)
52 case TOPO_STABILITY_INTERNAL
: return (TOPO_STABSTR_INTERNAL
);
53 case TOPO_STABILITY_PRIVATE
: return (TOPO_STABSTR_PRIVATE
);
54 case TOPO_STABILITY_OBSOLETE
: return (TOPO_STABSTR_OBSOLETE
);
55 case TOPO_STABILITY_EXTERNAL
: return (TOPO_STABSTR_EXTERNAL
);
56 case TOPO_STABILITY_UNSTABLE
: return (TOPO_STABSTR_UNSTABLE
);
57 case TOPO_STABILITY_EVOLVING
: return (TOPO_STABSTR_EVOLVING
);
58 case TOPO_STABILITY_STABLE
: return (TOPO_STABSTR_STABLE
);
59 case TOPO_STABILITY_STANDARD
: return (TOPO_STABSTR_STANDARD
);
60 default: return (TOPO_STABSTR_UNKNOWN
);
65 topo_name2stability(const char *name
)
67 if (strcmp(name
, TOPO_STABSTR_INTERNAL
) == 0)
68 return (TOPO_STABILITY_INTERNAL
);
69 else if (strcmp(name
, TOPO_STABSTR_PRIVATE
) == 0)
70 return (TOPO_STABILITY_PRIVATE
);
71 else if (strcmp(name
, TOPO_STABSTR_OBSOLETE
) == 0)
72 return (TOPO_STABILITY_OBSOLETE
);
73 else if (strcmp(name
, TOPO_STABSTR_EXTERNAL
) == 0)
74 return (TOPO_STABILITY_EXTERNAL
);
75 else if (strcmp(name
, TOPO_STABSTR_UNSTABLE
) == 0)
76 return (TOPO_STABILITY_UNSTABLE
);
77 else if (strcmp(name
, TOPO_STABSTR_EVOLVING
) == 0)
78 return (TOPO_STABILITY_EVOLVING
);
79 else if (strcmp(name
, TOPO_STABSTR_STABLE
) == 0)
80 return (TOPO_STABILITY_STABLE
);
81 else if (strcmp(name
, TOPO_STABSTR_STANDARD
) == 0)
82 return (TOPO_STABILITY_STANDARD
);
84 return (TOPO_STABILITY_UNKNOWN
);
87 static const topo_debug_mode_t _topo_dbout_modes
[] = {
88 { "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR
},
89 { "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG
},
93 static const topo_debug_mode_t _topo_dbflag_modes
[] = {
94 { "error", "error handling debug messages enabled", TOPO_DBG_ERR
},
95 { "module", "module debug messages enabled", TOPO_DBG_MOD
},
96 { "modulesvc", "module services debug messages enabled",
98 { "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK
},
99 { "xml", "xml file parsing messages enabled", TOPO_DBG_XML
},
100 { "devinfoforce", "devinfo DINFOFORCE snapshot used", TOPO_DBG_FORCE
},
101 { "all", "all debug modes enabled", TOPO_DBG_ALL
},
106 env_process_value(topo_hdl_t
*thp
, const char *begin
, const char *end
)
108 char buf
[MAXNAMELEN
];
110 topo_debug_mode_t
*dbp
;
112 while (begin
< end
&& isspace(*begin
))
115 while (begin
< end
&& isspace(*(end
- 1)))
124 if (count
> sizeof (buf
))
127 (void) snprintf(buf
, count
, "%s", begin
);
129 for (dbp
= (topo_debug_mode_t
*)_topo_dbflag_modes
;
130 dbp
->tdm_name
!= NULL
; ++dbp
) {
131 if (strcmp(buf
, dbp
->tdm_name
) == 0)
132 thp
->th_debug
|= dbp
->tdm_mode
;
137 topo_debug_set(topo_hdl_t
*thp
, const char *dbmode
, const char *dout
)
139 char *end
, *value
, *next
;
140 topo_debug_mode_t
*dbp
;
143 value
= (char *)dbmode
;
145 for (end
= (char *)dbmode
; *end
!= '\0'; value
= next
) {
146 end
= strchr(value
, ',');
148 next
= end
+ 1; /* skip the comma */
150 next
= end
= value
+ strlen(value
);
152 env_process_value(thp
, value
, end
);
156 topo_hdl_unlock(thp
);
160 for (dbp
= (topo_debug_mode_t
*)_topo_dbout_modes
;
161 dbp
->tdm_name
!= NULL
; ++dbp
) {
162 if (strcmp(dout
, dbp
->tdm_name
) == 0)
163 thp
->th_dbout
= dbp
->tdm_mode
;
165 topo_hdl_unlock(thp
);
169 topo_vdprintf(topo_hdl_t
*thp
, int mask
, const char *mod
, const char *format
,
176 if (!(thp
->th_debug
& mask
))
179 len
= vsnprintf(&c
, 1, format
, ap
);
180 msg
= alloca(len
+ 2);
181 (void) vsnprintf(msg
, len
+ 1, format
, ap
);
183 if (msg
[len
- 1] != '\n')
184 (void) strcpy(&msg
[len
], "\n");
186 if (thp
->th_dbout
== TOPO_DBOUT_SYSLOG
) {
188 syslog(LOG_DEBUG
| LOG_USER
, "libtopo DEBUG: %s", msg
);
190 syslog(LOG_DEBUG
| LOG_USER
, "libtopo DEBUG: %s: %s",
195 (void) fprintf(stderr
, "libtopo DEBUG: %s", msg
);
197 (void) fprintf(stderr
, "libtopo DEBUG: %s: %s", mod
,
205 topo_dprintf(topo_hdl_t
*thp
, int mask
, const char *format
, ...)
209 va_start(ap
, format
);
210 topo_vdprintf(thp
, mask
, NULL
, format
, ap
);
215 topo_hdl_root(topo_hdl_t
*thp
, const char *scheme
)
219 for (tp
= topo_list_next(&thp
->th_trees
); tp
!= NULL
;
220 tp
= topo_list_next(tp
)) {
221 if (strcmp(scheme
, tp
->tt_scheme
) == 0)
222 return (tp
->tt_root
);
229 * buf_append -- Append str to buf (if it's non-NULL). Place prepend
230 * in buf in front of str and append behind it (if they're non-NULL).
231 * Continue to update size even if we run out of space to actually
232 * stuff characters in the buffer.
235 topo_fmristr_build(ssize_t
*sz
, char *buf
, size_t buflen
, char *str
,
236 char *prepend
, char *append
)
243 if (buflen
== 0 || (left
= buflen
- *sz
) < 0)
246 if (buf
!= NULL
&& left
!= 0)
249 if (prepend
== NULL
&& append
== NULL
)
250 *sz
+= snprintf(buf
, left
, "%s", str
);
251 else if (append
== NULL
)
252 *sz
+= snprintf(buf
, left
, "%s%s", prepend
, str
);
253 else if (prepend
== NULL
)
254 *sz
+= snprintf(buf
, left
, "%s%s", str
, append
);
256 *sz
+= snprintf(buf
, left
, "%s%s%s", prepend
, str
, append
);
259 #define TOPO_PLATFORM_PATH "%s/usr/platform/%s/lib/fm/topo/%s"
260 #define TOPO_COMMON_PATH "%s/usr/lib/fm/topo/%s"
263 topo_search_path(topo_mod_t
*mod
, const char *rootdir
, const char *file
)
265 char *pp
, sp
[PATH_MAX
];
266 topo_hdl_t
*thp
= mod
->tm_hdl
;
269 * Search for file name in order of platform, machine and common
272 (void) snprintf(sp
, PATH_MAX
, TOPO_PLATFORM_PATH
, rootdir
,
273 thp
->th_platform
, file
);
274 if (access(sp
, F_OK
) != 0) {
275 (void) snprintf(sp
, PATH_MAX
, TOPO_PLATFORM_PATH
,
276 thp
->th_rootdir
, thp
->th_machine
, file
);
277 if (access(sp
, F_OK
) != 0) {
278 (void) snprintf(sp
, PATH_MAX
, TOPO_COMMON_PATH
,
279 thp
->th_rootdir
, file
);
280 if (access(sp
, F_OK
) != 0) {
286 pp
= topo_mod_strdup(mod
, sp
);
292 * SMBIOS serial numbers can contain characters (particularly ':' and ' ')
293 * that are invalid for the authority and can break FMRI parsing. We translate
294 * any invalid characters to a safe '-', as well as trimming any leading or
295 * trailing whitespace. Similarly, '/' can be found in some product names
296 * so we translate that to '-'.
299 topo_cleanup_auth_str(topo_hdl_t
*thp
, const char *begin
)
301 char buf
[MAXNAMELEN
];
302 const char *end
, *cp
;
307 end
= begin
+ strlen(begin
);
309 while (begin
< end
&& isspace(*begin
))
311 while (begin
< end
&& isspace(*(end
- 1)))
318 for (i
= 0; i
< MAXNAMELEN
- 1; i
++) {
322 if (c
== ':' || c
== '=' || c
== '/' || isspace(c
) ||
331 pp
= topo_hdl_strdup(thp
, buf
);
336 topo_sensor_type_name(uint32_t type
, char *buf
, size_t len
)
338 topo_name_trans_t
*ntp
;
340 for (ntp
= &topo_sensor_type_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
341 if (ntp
->int_value
== type
) {
342 (void) strlcpy(buf
, ntp
->int_name
, len
);
347 (void) snprintf(buf
, len
, "0x%02x", type
);
351 topo_sensor_units_name(uint8_t type
, char *buf
, size_t len
)
353 topo_name_trans_t
*ntp
;
355 for (ntp
= &topo_units_type_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
356 if (ntp
->int_value
== type
) {
357 (void) strlcpy(buf
, ntp
->int_name
, len
);
362 (void) snprintf(buf
, len
, "0x%02x", type
);
366 topo_led_type_name(uint8_t type
, char *buf
, size_t len
)
368 topo_name_trans_t
*ntp
;
370 for (ntp
= &topo_led_type_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
371 if (ntp
->int_value
== type
) {
372 (void) strlcpy(buf
, ntp
->int_name
, len
);
377 (void) snprintf(buf
, len
, "0x%02x", type
);
381 topo_led_state_name(uint8_t type
, char *buf
, size_t len
)
383 topo_name_trans_t
*ntp
;
385 for (ntp
= &topo_led_states_table
[0]; ntp
->int_name
!= NULL
; ntp
++) {
386 if (ntp
->int_value
== type
) {
387 (void) strlcpy(buf
, ntp
->int_name
, len
);
392 (void) snprintf(buf
, len
, "0x%02x", type
);
396 topo_sensor_state_name(uint32_t sensor_type
, uint8_t state
, char *buf
,
399 topo_name_trans_t
*ntp
;
401 switch (sensor_type
) {
402 case TOPO_SENSOR_TYPE_PHYSICAL
:
403 ntp
= &topo_sensor_states_physical_table
[0];
405 case TOPO_SENSOR_TYPE_PLATFORM
:
406 ntp
= &topo_sensor_states_platform_table
[0];
408 case TOPO_SENSOR_TYPE_PROCESSOR
:
409 ntp
= &topo_sensor_states_processor_table
[0];
411 case TOPO_SENSOR_TYPE_POWER_SUPPLY
:
412 ntp
= &topo_sensor_states_power_supply_table
[0];
414 case TOPO_SENSOR_TYPE_POWER_UNIT
:
415 ntp
= &topo_sensor_states_power_unit_table
[0];
417 case TOPO_SENSOR_TYPE_MEMORY
:
418 ntp
= &topo_sensor_states_memory_table
[0];
420 case TOPO_SENSOR_TYPE_BAY
:
421 ntp
= &topo_sensor_states_bay_table
[0];
423 case TOPO_SENSOR_TYPE_FIRMWARE
:
424 ntp
= &topo_sensor_states_firmware_table
[0];
426 case TOPO_SENSOR_TYPE_EVENT_LOG
:
427 ntp
= &topo_sensor_states_event_log_table
[0];
429 case TOPO_SENSOR_TYPE_WATCHDOG1
:
430 ntp
= &topo_sensor_states_watchdog1_table
[0];
432 case TOPO_SENSOR_TYPE_SYSTEM
:
433 ntp
= &topo_sensor_states_system_table
[0];
435 case TOPO_SENSOR_TYPE_CRITICAL
:
436 ntp
= &topo_sensor_states_critical_table
[0];
438 case TOPO_SENSOR_TYPE_BUTTON
:
439 ntp
= &topo_sensor_states_button_table
[0];
441 case TOPO_SENSOR_TYPE_CABLE
:
442 ntp
= &topo_sensor_states_cable_table
[0];
444 case TOPO_SENSOR_TYPE_BOOT_STATE
:
445 ntp
= &topo_sensor_states_boot_state_table
[0];
447 case TOPO_SENSOR_TYPE_BOOT_ERROR
:
448 ntp
= &topo_sensor_states_boot_error_table
[0];
450 case TOPO_SENSOR_TYPE_BOOT_OS
:
451 ntp
= &topo_sensor_states_boot_os_table
[0];
453 case TOPO_SENSOR_TYPE_OS_SHUTDOWN
:
454 ntp
= &topo_sensor_states_os_table
[0];
456 case TOPO_SENSOR_TYPE_SLOT
:
457 ntp
= &topo_sensor_states_slot_table
[0];
459 case TOPO_SENSOR_TYPE_ACPI
:
460 ntp
= &topo_sensor_states_acpi_table
[0];
462 case TOPO_SENSOR_TYPE_WATCHDOG2
:
463 ntp
= &topo_sensor_states_watchdog2_table
[0];
465 case TOPO_SENSOR_TYPE_ALERT
:
466 ntp
= &topo_sensor_states_alert_table
[0];
468 case TOPO_SENSOR_TYPE_PRESENCE
:
469 ntp
= &topo_sensor_states_presence_table
[0];
471 case TOPO_SENSOR_TYPE_LAN
:
472 ntp
= &topo_sensor_states_lan_table
[0];
474 case TOPO_SENSOR_TYPE_HEALTH
:
475 ntp
= &topo_sensor_states_health_table
[0];
477 case TOPO_SENSOR_TYPE_BATTERY
:
478 ntp
= &topo_sensor_states_battery_table
[0];
480 case TOPO_SENSOR_TYPE_AUDIT
:
481 ntp
= &topo_sensor_states_audit_table
[0];
483 case TOPO_SENSOR_TYPE_VERSION
:
484 ntp
= &topo_sensor_states_version_table
[0];
486 case TOPO_SENSOR_TYPE_FRU_STATE
:
487 ntp
= &topo_sensor_states_fru_state_table
[0];
489 case TOPO_SENSOR_TYPE_THRESHOLD_STATE
:
490 ntp
= &topo_sensor_states_thresh_table
[0];
492 case TOPO_SENSOR_TYPE_GENERIC_USAGE
:
493 ntp
= &topo_sensor_states_generic_usage_table
[0];
495 case TOPO_SENSOR_TYPE_GENERIC_STATE
:
496 ntp
= &topo_sensor_states_generic_state_table
[0];
498 case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL
:
499 ntp
= &topo_sensor_states_generic_predfail_table
[0];
501 case TOPO_SENSOR_TYPE_GENERIC_LIMIT
:
502 ntp
= &topo_sensor_states_generic_limit_table
[0];
504 case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE
:
505 ntp
= &topo_sensor_states_generic_perf_table
[0];
507 case TOPO_SENSOR_TYPE_SEVERITY
:
508 ntp
= &topo_sensor_states_severity_table
[0];
510 case TOPO_SENSOR_TYPE_GENERIC_PRESENCE
:
511 ntp
= &topo_sensor_states_generic_presence_table
[0];
513 case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY
:
514 ntp
= &topo_sensor_states_generic_avail_table
[0];
516 case TOPO_SENSOR_TYPE_GENERIC_STATUS
:
517 ntp
= &topo_sensor_states_generic_status_table
[0];
519 case TOPO_SENSOR_TYPE_GENERIC_ACPI
:
520 ntp
= &topo_sensor_states_generic_acpi_pwr_table
[0];
522 case TOPO_SENSOR_TYPE_GENERIC_FAILURE
:
523 ntp
= &topo_sensor_states_generic_failure_table
[0];
525 case TOPO_SENSOR_TYPE_GENERIC_OK
:
526 ntp
= &topo_sensor_states_generic_ok_table
[0];
529 (void) snprintf(buf
, len
, "0x%02x", state
);
532 for (; ntp
->int_name
!= NULL
; ntp
++) {
533 if (ntp
->int_value
== state
) {
534 (void) strlcpy(buf
, ntp
->int_name
, len
);
539 (void) snprintf(buf
, len
, "0x%02x", state
);