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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <alloca.h> 28 #include <ctype.h> 29 #include <limits.h> 30 #include <syslog.h> 31 #include <strings.h> 32 #include <unistd.h> 33 34 #include <topo_error.h> 35 #include <topo_subr.h> 36 37 void 38 topo_hdl_lock(topo_hdl_t *thp) 39 { 40 (void) pthread_mutex_lock(&thp->th_lock); 41 } 42 43 void 44 topo_hdl_unlock(topo_hdl_t *thp) 45 { 46 (void) pthread_mutex_unlock(&thp->th_lock); 47 } 48 49 const char * 50 topo_stability2name(topo_stability_t s) 51 { 52 switch (s) { 53 case TOPO_STABILITY_INTERNAL: return (TOPO_STABSTR_INTERNAL); 54 case TOPO_STABILITY_PRIVATE: return (TOPO_STABSTR_PRIVATE); 55 case TOPO_STABILITY_OBSOLETE: return (TOPO_STABSTR_OBSOLETE); 56 case TOPO_STABILITY_EXTERNAL: return (TOPO_STABSTR_EXTERNAL); 57 case TOPO_STABILITY_UNSTABLE: return (TOPO_STABSTR_UNSTABLE); 58 case TOPO_STABILITY_EVOLVING: return (TOPO_STABSTR_EVOLVING); 59 case TOPO_STABILITY_STABLE: return (TOPO_STABSTR_STABLE); 60 case TOPO_STABILITY_STANDARD: return (TOPO_STABSTR_STANDARD); 61 default: return (TOPO_STABSTR_UNKNOWN); 62 } 63 } 64 65 topo_stability_t 66 topo_name2stability(const char *name) 67 { 68 if (strcmp(name, TOPO_STABSTR_INTERNAL) == 0) 69 return (TOPO_STABILITY_INTERNAL); 70 else if (strcmp(name, TOPO_STABSTR_PRIVATE) == 0) 71 return (TOPO_STABILITY_PRIVATE); 72 else if (strcmp(name, TOPO_STABSTR_OBSOLETE) == 0) 73 return (TOPO_STABILITY_OBSOLETE); 74 else if (strcmp(name, TOPO_STABSTR_EXTERNAL) == 0) 75 return (TOPO_STABILITY_EXTERNAL); 76 else if (strcmp(name, TOPO_STABSTR_UNSTABLE) == 0) 77 return (TOPO_STABILITY_UNSTABLE); 78 else if (strcmp(name, TOPO_STABSTR_EVOLVING) == 0) 79 return (TOPO_STABILITY_EVOLVING); 80 else if (strcmp(name, TOPO_STABSTR_STABLE) == 0) 81 return (TOPO_STABILITY_STABLE); 82 else if (strcmp(name, TOPO_STABSTR_STANDARD) == 0) 83 return (TOPO_STABILITY_STANDARD); 84 85 return (TOPO_STABILITY_UNKNOWN); 86 } 87 88 static const topo_debug_mode_t _topo_dbout_modes[] = { 89 { "stderr", "send debug messages to stderr", TOPO_DBOUT_STDERR }, 90 { "syslog", "send debug messages to syslog", TOPO_DBOUT_SYSLOG }, 91 { NULL, NULL, 0 } 92 }; 93 94 static const topo_debug_mode_t _topo_dbflag_modes[] = { 95 { "error", "error handling debug messages enabled", TOPO_DBG_ERR }, 96 { "module", "module debug messages enabled", TOPO_DBG_MOD }, 97 { "modulesvc", "module services debug messages enabled", 98 TOPO_DBG_MODSVC }, 99 { "walk", "walker subsystem debug messages enabled", TOPO_DBG_WALK }, 100 { "xml", "xml file parsing messages enabled", TOPO_DBG_XML }, 101 { "all", "all debug modes enabled", TOPO_DBG_ALL}, 102 { NULL, NULL, 0 } 103 }; 104 105 void 106 env_process_value(topo_hdl_t *thp, const char *begin, const char *end) 107 { 108 char buf[MAXNAMELEN]; 109 size_t count; 110 topo_debug_mode_t *dbp; 111 112 while (begin < end && isspace(*begin)) 113 begin++; 114 115 while (begin < end && isspace(*(end - 1))) 116 end--; 117 118 if (begin >= end) 119 return; 120 121 count = end - begin; 122 count += 1; 123 124 if (count > sizeof (buf)) 125 return; 126 127 (void) snprintf(buf, count, "%s", begin); 128 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; 133 } 134 } 135 136 void 137 topo_debug_set(topo_hdl_t *thp, const char *dbmode, const char *dout) 138 { 139 char *end, *value, *next; 140 topo_debug_mode_t *dbp; 141 142 topo_hdl_lock(thp); 143 value = (char *)dbmode; 144 145 for (end = (char *)dbmode; *end != '\0'; value = next) { 146 end = strchr(value, ','); 147 if (end != NULL) 148 next = end + 1; /* skip the comma */ 149 else 150 next = end = value + strlen(value); 151 152 env_process_value(thp, value, end); 153 } 154 155 if (dout == NULL) { 156 topo_hdl_unlock(thp); 157 return; 158 } 159 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; 164 } 165 topo_hdl_unlock(thp); 166 } 167 168 void 169 topo_vdprintf(topo_hdl_t *thp, int mask, const char *mod, const char *format, 170 va_list ap) 171 { 172 char *msg; 173 size_t len; 174 char c; 175 176 if (!(thp->th_debug & mask)) 177 return; 178 179 len = vsnprintf(&c, 1, format, ap); 180 msg = alloca(len + 2); 181 (void) vsnprintf(msg, len + 1, format, ap); 182 183 if (msg[len - 1] != '\n') 184 (void) strcpy(&msg[len], "\n"); 185 186 if (thp->th_dbout == TOPO_DBOUT_SYSLOG) { 187 if (mod == NULL) { 188 syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s", msg); 189 } else { 190 syslog(LOG_DEBUG | LOG_USER, "libtopo DEBUG: %s: %s", 191 mod, msg); 192 } 193 } else { 194 if (mod == NULL) { 195 (void) fprintf(stderr, "libtopo DEBUG: %s", msg); 196 } else { 197 (void) fprintf(stderr, "libtopo DEBUG: %s: %s", mod, 198 msg); 199 } 200 } 201 } 202 203 /*PRINTFLIKE3*/ 204 void 205 topo_dprintf(topo_hdl_t *thp, int mask, const char *format, ...) 206 { 207 va_list ap; 208 209 va_start(ap, format); 210 topo_vdprintf(thp, mask, NULL, format, ap); 211 va_end(ap); 212 } 213 214 tnode_t * 215 topo_hdl_root(topo_hdl_t *thp, const char *scheme) 216 { 217 ttree_t *tp; 218 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); 223 } 224 225 return (NULL); 226 } 227 228 /* 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. 233 */ 234 void 235 topo_fmristr_build(ssize_t *sz, char *buf, size_t buflen, char *str, 236 char *prepend, char *append) 237 { 238 ssize_t left; 239 240 if (str == NULL) 241 return; 242 243 if (buflen == 0 || (left = buflen - *sz) < 0) 244 left = 0; 245 246 if (buf != NULL && left != 0) 247 buf += *sz; 248 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); 255 else 256 *sz += snprintf(buf, left, "%s%s%s", prepend, str, append); 257 } 258 259 #define TOPO_PLATFORM_PATH "%s/usr/platform/%s/lib/fm/topo/%s" 260 #define TOPO_COMMON_PATH "%s/usr/lib/fm/topo/%s" 261 262 char * 263 topo_search_path(topo_mod_t *mod, const char *rootdir, const char *file) 264 { 265 char *pp, sp[PATH_MAX]; 266 topo_hdl_t *thp = mod->tm_hdl; 267 268 /* 269 * Search for file name in order of platform, machine and common 270 * topo directories 271 */ 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) { 281 return (NULL); 282 } 283 } 284 } 285 286 pp = topo_mod_strdup(mod, sp); 287 288 return (pp); 289 } 290 291 /* 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 '-'. 297 */ 298 char * 299 topo_cleanup_auth_str(topo_hdl_t *thp, const char *begin) 300 { 301 char buf[MAXNAMELEN]; 302 const char *end, *cp; 303 char *pp; 304 char c; 305 int i; 306 307 end = begin + strlen(begin); 308 309 while (begin < end && isspace(*begin)) 310 begin++; 311 while (begin < end && isspace(*(end - 1))) 312 end--; 313 314 if (begin >= end) 315 return (NULL); 316 317 cp = begin; 318 for (i = 0; i < MAXNAMELEN - 1; i++) { 319 if (cp >= end) 320 break; 321 c = *cp; 322 if (c == ':' || c == '=' || c == '/' || isspace(c) || 323 !isprint(c)) 324 buf[i] = '-'; 325 else 326 buf[i] = c; 327 cp++; 328 } 329 buf[i] = 0; 330 331 pp = topo_hdl_strdup(thp, buf); 332 return (pp); 333 } 334 335 void 336 topo_sensor_type_name(uint32_t type, char *buf, size_t len) 337 { 338 topo_name_trans_t *ntp; 339 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); 343 return; 344 } 345 } 346 347 (void) snprintf(buf, len, "0x%02x", type); 348 } 349 350 void 351 topo_sensor_units_name(uint8_t type, char *buf, size_t len) 352 { 353 topo_name_trans_t *ntp; 354 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); 358 return; 359 } 360 } 361 362 (void) snprintf(buf, len, "0x%02x", type); 363 } 364 365 void 366 topo_led_type_name(uint8_t type, char *buf, size_t len) 367 { 368 topo_name_trans_t *ntp; 369 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); 373 return; 374 } 375 } 376 377 (void) snprintf(buf, len, "0x%02x", type); 378 } 379 380 void 381 topo_led_state_name(uint8_t type, char *buf, size_t len) 382 { 383 topo_name_trans_t *ntp; 384 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); 388 return; 389 } 390 } 391 392 (void) snprintf(buf, len, "0x%02x", type); 393 } 394 395 void 396 topo_sensor_state_name(uint32_t sensor_type, uint8_t state, char *buf, 397 size_t len) 398 { 399 topo_name_trans_t *ntp; 400 401 switch (sensor_type) { 402 case TOPO_SENSOR_TYPE_PHYSICAL: 403 ntp = &topo_sensor_states_physical_table[0]; 404 break; 405 case TOPO_SENSOR_TYPE_PLATFORM: 406 ntp = &topo_sensor_states_platform_table[0]; 407 break; 408 case TOPO_SENSOR_TYPE_PROCESSOR: 409 ntp = &topo_sensor_states_processor_table[0]; 410 break; 411 case TOPO_SENSOR_TYPE_POWER_SUPPLY: 412 ntp = &topo_sensor_states_power_supply_table[0]; 413 break; 414 case TOPO_SENSOR_TYPE_POWER_UNIT: 415 ntp = &topo_sensor_states_power_unit_table[0]; 416 break; 417 case TOPO_SENSOR_TYPE_MEMORY: 418 ntp = &topo_sensor_states_memory_table[0]; 419 break; 420 case TOPO_SENSOR_TYPE_BAY: 421 ntp = &topo_sensor_states_bay_table[0]; 422 break; 423 case TOPO_SENSOR_TYPE_FIRMWARE: 424 ntp = &topo_sensor_states_firmware_table[0]; 425 break; 426 case TOPO_SENSOR_TYPE_EVENT_LOG: 427 ntp = &topo_sensor_states_event_log_table[0]; 428 break; 429 case TOPO_SENSOR_TYPE_WATCHDOG1: 430 ntp = &topo_sensor_states_watchdog1_table[0]; 431 break; 432 case TOPO_SENSOR_TYPE_SYSTEM: 433 ntp = &topo_sensor_states_system_table[0]; 434 break; 435 case TOPO_SENSOR_TYPE_CRITICAL: 436 ntp = &topo_sensor_states_critical_table[0]; 437 break; 438 case TOPO_SENSOR_TYPE_BUTTON: 439 ntp = &topo_sensor_states_button_table[0]; 440 break; 441 case TOPO_SENSOR_TYPE_CABLE: 442 ntp = &topo_sensor_states_cable_table[0]; 443 break; 444 case TOPO_SENSOR_TYPE_BOOT_STATE: 445 ntp = &topo_sensor_states_boot_state_table[0]; 446 break; 447 case TOPO_SENSOR_TYPE_BOOT_ERROR: 448 ntp = &topo_sensor_states_boot_error_table[0]; 449 break; 450 case TOPO_SENSOR_TYPE_BOOT_OS: 451 ntp = &topo_sensor_states_boot_os_table[0]; 452 break; 453 case TOPO_SENSOR_TYPE_OS_SHUTDOWN: 454 ntp = &topo_sensor_states_os_table[0]; 455 break; 456 case TOPO_SENSOR_TYPE_SLOT: 457 ntp = &topo_sensor_states_slot_table[0]; 458 break; 459 case TOPO_SENSOR_TYPE_ACPI: 460 ntp = &topo_sensor_states_acpi_table[0]; 461 break; 462 case TOPO_SENSOR_TYPE_WATCHDOG2: 463 ntp = &topo_sensor_states_watchdog2_table[0]; 464 break; 465 case TOPO_SENSOR_TYPE_ALERT: 466 ntp = &topo_sensor_states_alert_table[0]; 467 break; 468 case TOPO_SENSOR_TYPE_PRESENCE: 469 ntp = &topo_sensor_states_presence_table[0]; 470 break; 471 case TOPO_SENSOR_TYPE_LAN: 472 ntp = &topo_sensor_states_lan_table[0]; 473 break; 474 case TOPO_SENSOR_TYPE_HEALTH: 475 ntp = &topo_sensor_states_health_table[0]; 476 break; 477 case TOPO_SENSOR_TYPE_BATTERY: 478 ntp = &topo_sensor_states_battery_table[0]; 479 break; 480 case TOPO_SENSOR_TYPE_AUDIT: 481 ntp = &topo_sensor_states_audit_table[0]; 482 break; 483 case TOPO_SENSOR_TYPE_VERSION: 484 ntp = &topo_sensor_states_version_table[0]; 485 break; 486 case TOPO_SENSOR_TYPE_FRU_STATE: 487 ntp = &topo_sensor_states_fru_state_table[0]; 488 break; 489 case TOPO_SENSOR_TYPE_THRESHOLD_STATE: 490 ntp = &topo_sensor_states_thresh_table[0]; 491 break; 492 case TOPO_SENSOR_TYPE_GENERIC_USAGE: 493 ntp = &topo_sensor_states_generic_usage_table[0]; 494 break; 495 case TOPO_SENSOR_TYPE_GENERIC_STATE: 496 ntp = &topo_sensor_states_generic_state_table[0]; 497 break; 498 case TOPO_SENSOR_TYPE_GENERIC_PREDFAIL: 499 ntp = &topo_sensor_states_generic_predfail_table[0]; 500 break; 501 case TOPO_SENSOR_TYPE_GENERIC_LIMIT: 502 ntp = &topo_sensor_states_generic_limit_table[0]; 503 break; 504 case TOPO_SENSOR_TYPE_GENERIC_PERFORMANCE: 505 ntp = &topo_sensor_states_generic_perf_table[0]; 506 break; 507 case TOPO_SENSOR_TYPE_SEVERITY: 508 ntp = &topo_sensor_states_severity_table[0]; 509 break; 510 case TOPO_SENSOR_TYPE_GENERIC_PRESENCE: 511 ntp = &topo_sensor_states_generic_presence_table[0]; 512 break; 513 case TOPO_SENSOR_TYPE_GENERIC_AVAILABILITY: 514 ntp = &topo_sensor_states_generic_avail_table[0]; 515 break; 516 case TOPO_SENSOR_TYPE_GENERIC_STATUS: 517 ntp = &topo_sensor_states_generic_status_table[0]; 518 break; 519 case TOPO_SENSOR_TYPE_GENERIC_ACPI: 520 ntp = &topo_sensor_states_generic_acpi_pwr_table[0]; 521 break; 522 case TOPO_SENSOR_TYPE_GENERIC_FAILURE: 523 ntp = &topo_sensor_states_generic_failure_table[0]; 524 break; 525 case TOPO_SENSOR_TYPE_GENERIC_OK: 526 ntp = &topo_sensor_states_generic_ok_table[0]; 527 break; 528 default: 529 (void) snprintf(buf, len, "0x%02x", state); 530 return; 531 } 532 for (; ntp->int_name != NULL; ntp++) { 533 if (ntp->int_value == state) { 534 (void) strlcpy(buf, ntp->int_name, len); 535 return; 536 } 537 } 538 539 (void) snprintf(buf, len, "0x%02x", state); 540 } 541