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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/fm/protocol.h> 30 #include <fm/libtopo.h> 31 #include <ctype.h> 32 #include <fnmatch.h> 33 #include <limits.h> 34 #include <strings.h> 35 #include <stdio.h> 36 #include <errno.h> 37 #include <umem.h> 38 #include <sys/param.h> 39 40 #define FMTOPO_EXIT_SUCCESS 0 41 #define FMTOPO_EXIT_ERROR 1 42 #define FMTOPO_EXIT_USAGE 2 43 44 #define STDERR "stderr" 45 #define DOTS "..." 46 #define ALL "all" 47 48 static const char *g_pname; 49 static const char *g_fmri = NULL; 50 51 static const char *opt_R = "/"; 52 static const char *opt_s = FM_FMRI_SCHEME_HC; 53 static const char optstr[] = "bCdeEP:pR:s:StVx"; 54 55 static int opt_b = 0; 56 static int opt_d = 0; 57 static int opt_e = 0; 58 static int opt_E = 0; 59 static int opt_p = 0; 60 static int opt_S = 0; 61 static int opt_t = 0; 62 static int opt_V = 0; 63 static int opt_x = 0; 64 static int opt_all = 0; 65 66 struct prop_args { 67 const char *group; 68 const char *prop; 69 const char *type; 70 const char *value; 71 }; 72 73 static struct prop_args **pargs = NULL; 74 static int pcnt = 0; 75 76 static int 77 usage(FILE *fp) 78 { 79 (void) fprintf(fp, 80 "Usage: %s [-bCeEdpSVx] [-P group.property[=type:value]] " 81 "[-R root] [-s scheme] [fmri]\n", g_pname); 82 83 (void) fprintf(fp, 84 "\t-b walk in sibling-first order (default is child-first)\n" 85 "\t-C dump core after completing execution\n" 86 "\t-d set debug mode for libtopo modules\n" 87 "\t-e display FMRIs as paths using esc/eft notation\n" 88 "\t-E enumerate sensor nodes\n" 89 "\t-P get/set specified properties\n" 90 "\t-p display of FMRI protocol properties\n" 91 "\t-R set root directory for libtopo plug-ins and other files\n" 92 "\t-s display topology for the specified FMRI scheme\n" 93 "\t-S display FMRI status (present/usable)\n" 94 "\t-V set verbose mode\n" 95 "\t-x display a xml formatted topology\n"); 96 97 return (FMTOPO_EXIT_USAGE); 98 } 99 100 static topo_type_t 101 str2type(const char *tstr) 102 { 103 topo_type_t type; 104 105 if (tstr == NULL) 106 return (TOPO_TYPE_INVALID); 107 108 if (strcmp(tstr, "int32") == 0) 109 type = TOPO_TYPE_INT32; 110 else if (strcmp(tstr, "uint32") == 0) 111 type = TOPO_TYPE_UINT32; 112 else if (strcmp(tstr, "int64") == 0) 113 type = TOPO_TYPE_INT64; 114 else if (strcmp(tstr, "uint64") == 0) 115 type = TOPO_TYPE_UINT64; 116 else if (strcmp(tstr, "string") == 0) 117 type = TOPO_TYPE_STRING; 118 else if (strcmp(tstr, "fmri") == 0) 119 type = TOPO_TYPE_FMRI; 120 else { 121 type = TOPO_TYPE_INVALID; 122 } 123 124 return (type); 125 } 126 127 static void 128 print_node(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl, const char *fmri) 129 { 130 int err, ret; 131 132 (void) printf("%s\n", (char *)fmri); 133 134 if (opt_p && !(pcnt > 0 || opt_V || opt_all)) { 135 char *aname = NULL, *fname = NULL, *lname = NULL; 136 nvlist_t *asru = NULL; 137 nvlist_t *fru = NULL; 138 139 if (topo_node_asru(node, &asru, NULL, &err) == 0) 140 (void) topo_fmri_nvl2str(thp, asru, &aname, &err); 141 if (topo_node_fru(node, &fru, NULL, &err) == 0) 142 (void) topo_fmri_nvl2str(thp, fru, &fname, &err); 143 (void) topo_node_label(node, &lname, &err); 144 if (aname != NULL) { 145 nvlist_free(asru); 146 (void) printf("\tASRU: %s\n", aname); 147 topo_hdl_strfree(thp, aname); 148 } else { 149 (void) printf("\tASRU: -\n"); 150 } 151 if (fname != NULL) { 152 nvlist_free(fru); 153 (void) printf("\tFRU: %s\n", fname); 154 topo_hdl_strfree(thp, fname); 155 } else { 156 (void) printf("\tFRU: -\n"); 157 } 158 if (lname != NULL) { 159 (void) printf("\tLabel: %s\n", lname); 160 topo_hdl_strfree(thp, lname); 161 } else { 162 (void) printf("\tLabel: -\n"); 163 } 164 } 165 166 if (opt_S) { 167 if ((ret = topo_fmri_present(thp, nvl, &err)) < 0) 168 (void) printf("\tPresent: -\n"); 169 else 170 (void) printf("\tPresent: %s\n", 171 ret ? "true" : "false"); 172 173 if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0) 174 (void) printf("\tUnusable: -\n"); 175 else 176 (void) printf("\tUnusable: %s\n", 177 ret ? "true" : "false"); 178 } 179 } 180 181 static void 182 print_everstyle(tnode_t *node) 183 { 184 char buf[PATH_MAX], numbuf[64]; 185 nvlist_t *fmri, **hcl; 186 int i, err; 187 uint_t n; 188 189 if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, 190 TOPO_PROP_RESOURCE, &fmri, &err) < 0) { 191 (void) fprintf(stderr, "%s: failed to get fmri for %s=%d: %s\n", 192 g_pname, topo_node_name(node), 193 topo_node_instance(node), topo_strerror(err)); 194 return; 195 } 196 197 if (nvlist_lookup_nvlist_array(fmri, FM_FMRI_HC_LIST, &hcl, &n) != 0) { 198 (void) fprintf(stderr, "%s: failed to find %s for %s=%d\n", 199 g_pname, FM_FMRI_HC_LIST, topo_node_name(node), 200 topo_node_instance(node)); 201 nvlist_free(fmri); 202 return; 203 } 204 205 buf[0] = '\0'; 206 207 for (i = 0; i < n; i++) { 208 char *name, *inst, *estr; 209 ulong_t ul; 210 211 if (nvlist_lookup_string(hcl[i], FM_FMRI_HC_NAME, &name) != 0 || 212 nvlist_lookup_string(hcl[i], FM_FMRI_HC_ID, &inst) != 0) { 213 (void) fprintf(stderr, "%s: failed to get " 214 "name-instance for %s=%d\n", g_pname, 215 topo_node_name(node), topo_node_instance(node)); 216 nvlist_free(fmri); 217 return; 218 } 219 220 errno = 0; 221 ul = strtoul(inst, &estr, 10); 222 223 if (errno != 0 || estr == inst) { 224 (void) fprintf(stderr, "%s: instance %s does not " 225 "convert to an unsigned integer\n", g_pname, inst); 226 } 227 228 (void) strlcat(buf, "/", sizeof (buf)); 229 (void) strlcat(buf, name, sizeof (buf)); 230 (void) snprintf(numbuf, sizeof (numbuf), "%u", ul); 231 (void) strlcat(buf, numbuf, sizeof (buf)); 232 } 233 nvlist_free(fmri); 234 235 (void) printf("%s\n", buf); 236 } 237 238 static void 239 print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl) 240 { 241 int err; 242 topo_type_t type; 243 char *tstr, *propn, buf[48], *factype; 244 nvpair_t *pv_nvp; 245 int i; 246 uint_t nelem; 247 248 if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL) 249 return; 250 251 /* Print property name */ 252 if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL || 253 nvpair_name(pv_nvp) == NULL || 254 strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) { 255 (void) fprintf(stderr, "%s: malformed property name\n", 256 g_pname); 257 return; 258 } else { 259 (void) nvpair_value_string(pv_nvp, &propn); 260 } 261 262 if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL || 263 nvpair_name(pv_nvp) == NULL || 264 strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 || 265 nvpair_type(pv_nvp) != DATA_TYPE_UINT32) { 266 (void) fprintf(stderr, "%s: malformed property type for %s\n", 267 g_pname, propn); 268 return; 269 } else { 270 (void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type); 271 } 272 273 switch (type) { 274 case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break; 275 case TOPO_TYPE_INT32: tstr = "int32"; break; 276 case TOPO_TYPE_UINT32: tstr = "uint32"; break; 277 case TOPO_TYPE_INT64: tstr = "int64"; break; 278 case TOPO_TYPE_UINT64: tstr = "uint64"; break; 279 case TOPO_TYPE_DOUBLE: tstr = "double"; break; 280 case TOPO_TYPE_STRING: tstr = "string"; break; 281 case TOPO_TYPE_FMRI: tstr = "fmri"; break; 282 case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break; 283 case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break; 284 case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break; 285 case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break; 286 case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break; 287 case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break; 288 default: tstr = "unknown type"; 289 } 290 291 printf(" %-17s %-8s ", propn, tstr); 292 293 /* 294 * Get property value 295 */ 296 if (nvpair_name(pv_nvp) == NULL || 297 (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) { 298 (void) fprintf(stderr, "%s: malformed property value\n", 299 g_pname); 300 return; 301 } 302 303 switch (nvpair_type(pv_nvp)) { 304 case DATA_TYPE_INT32: { 305 int32_t val; 306 (void) nvpair_value_int32(pv_nvp, &val); 307 (void) printf(" %d", val); 308 break; 309 } 310 case DATA_TYPE_UINT32: { 311 uint32_t val, type; 312 char val_str[49]; 313 nvlist_t *fac, *rsrc = NULL; 314 315 (void) nvpair_value_uint32(pv_nvp, &val); 316 if (node == NULL || topo_node_flags(node) != 317 TOPO_NODE_FACILITY) 318 goto uint32_def; 319 320 if (topo_node_resource(node, &rsrc, &err) != 0) 321 goto uint32_def; 322 323 if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0) 324 goto uint32_def; 325 326 if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE, 327 &factype) != 0) 328 goto uint32_def; 329 330 nvlist_free(rsrc); 331 rsrc = NULL; 332 333 /* 334 * Special case code to do friendlier printing of 335 * facility node properties 336 */ 337 if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && 338 (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { 339 topo_sensor_type_name(val, val_str, 48); 340 (void) printf(" 0x%x (%s)", val, val_str); 341 break; 342 } else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && 343 (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) { 344 topo_led_type_name(val, val_str, 48); 345 (void) printf(" 0x%x (%s)", val, val_str); 346 break; 347 } else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) { 348 topo_sensor_units_name(val, val_str, 48); 349 (void) printf(" 0x%x (%s)", val, val_str); 350 break; 351 } else if (strcmp(propn, TOPO_LED_MODE) == 0) { 352 topo_led_state_name(val, val_str, 48); 353 (void) printf(" 0x%x (%s)", val, val_str); 354 break; 355 } else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) && 356 (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { 357 if (topo_prop_get_uint32(node, 358 TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, 359 &type, &err) != 0) { 360 goto uint32_def; 361 } 362 topo_sensor_state_name(type, val, val_str, 48); 363 (void) printf(" 0x%x (%s)", val, val_str); 364 break; 365 } 366 uint32_def: 367 (void) printf(" 0x%x", val); 368 if (rsrc != NULL) 369 nvlist_free(rsrc); 370 break; 371 } 372 case DATA_TYPE_INT64: { 373 int64_t val; 374 (void) nvpair_value_int64(pv_nvp, &val); 375 (void) printf(" %lld", (longlong_t)val); 376 break; 377 } 378 case DATA_TYPE_UINT64: { 379 uint64_t val; 380 (void) nvpair_value_uint64(pv_nvp, &val); 381 (void) printf(" 0x%llx", (u_longlong_t)val); 382 break; 383 } 384 case DATA_TYPE_DOUBLE: { 385 double val; 386 (void) nvpair_value_double(pv_nvp, &val); 387 (void) printf(" %lf", (double)val); 388 break; 389 } 390 case DATA_TYPE_STRING: { 391 char *val; 392 (void) nvpair_value_string(pv_nvp, &val); 393 if (!opt_V && strlen(val) > 48) { 394 (void) snprintf(buf, 48, "%s...", val); 395 (void) printf(" %s", buf); 396 } else { 397 (void) printf(" %s", val); 398 } 399 break; 400 } 401 case DATA_TYPE_NVLIST: { 402 nvlist_t *val; 403 char *fmri; 404 (void) nvpair_value_nvlist(pv_nvp, &val); 405 if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) { 406 if (opt_V) 407 nvlist_print(stdout, nvl); 408 break; 409 } 410 411 if (!opt_V && strlen(fmri) > 48) { 412 (void) snprintf(buf, 48, "%s", fmri); 413 (void) snprintf(&buf[45], 4, "%s", DOTS); 414 (void) printf(" %s", buf); 415 } else { 416 (void) printf(" %s", fmri); 417 } 418 419 topo_hdl_strfree(thp, fmri); 420 break; 421 } 422 case DATA_TYPE_UINT32_ARRAY: { 423 uint32_t *val; 424 425 (void) nvpair_value_uint32_array(pv_nvp, &val, &nelem); 426 (void) printf(" [ "); 427 for (i = 0; i < nelem; i++) 428 (void) printf("%u ", val[i]); 429 (void) printf("]"); 430 break; 431 } 432 case DATA_TYPE_INT64_ARRAY: { 433 int64_t *val; 434 435 (void) nvpair_value_int64_array(pv_nvp, &val, &nelem); 436 (void) printf(" [ "); 437 for (i = 0; i < nelem; i++) 438 (void) printf("%lld ", val[i]); 439 (void) printf("]"); 440 break; 441 } 442 case DATA_TYPE_STRING_ARRAY: { 443 char **val; 444 445 (void) nvpair_value_string_array(pv_nvp, &val, &nelem); 446 (void) printf(" [ "); 447 for (i = 0; i < nelem; i++) 448 (void) printf("%s ", val[i]); 449 (void) printf("]"); 450 break; 451 } 452 default: 453 (void) fprintf(stderr, " unknown data type (%d)", 454 nvpair_type(pv_nvp)); 455 break; 456 } 457 (void) printf("\n"); 458 } 459 460 static void 461 print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab, 462 char *nstab, int32_t version) 463 { 464 int err; 465 char buf[30]; 466 topo_pgroup_info_t *pgi = NULL; 467 468 if (pgn == NULL) 469 return; 470 471 if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) { 472 if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) { 473 dstab = (char *)topo_stability2name(pgi->tpi_datastab); 474 nstab = (char *)topo_stability2name(pgi->tpi_namestab); 475 version = pgi->tpi_version; 476 } 477 } 478 479 if (dstab == NULL || nstab == NULL || version == -1) { 480 printf(" group: %-30s version: - stability: -/-\n", pgn); 481 } else if (!opt_V && strlen(pgn) > 30) { 482 (void) snprintf(buf, 26, "%s", pgn); 483 (void) snprintf(&buf[27], 4, "%s", DOTS); 484 printf(" group: %-30s version: %-3d stability: %s/%s\n", 485 buf, version, nstab, dstab); 486 } else { 487 printf(" group: %-30s version: %-3d stability: %s/%s\n", 488 pgn, version, nstab, dstab); 489 } 490 491 if (pgi != NULL) { 492 topo_hdl_strfree(thp, (char *)pgi->tpi_name); 493 topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t)); 494 } 495 } 496 497 static void 498 print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv, 499 const char *group) 500 { 501 char *pgn = NULL, *dstab = NULL, *nstab = NULL; 502 int32_t version; 503 nvlist_t *pg_nv, *pv_nv; 504 nvpair_t *nvp, *pg_nvp; 505 int pg_done, match, all = strcmp(group, ALL) == 0; 506 507 for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL; 508 nvp = nvlist_next_nvpair(p_nv, nvp)) { 509 if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 || 510 nvpair_type(nvp) != DATA_TYPE_NVLIST) 511 continue; 512 513 nstab = NULL; 514 dstab = NULL; 515 version = -1; 516 pg_done = match = 0; 517 (void) nvpair_value_nvlist(nvp, &pg_nv); 518 for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL; 519 pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) { 520 /* 521 * Print property group name and stability levels 522 */ 523 if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp)) 524 == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 525 (void) nvpair_value_string(pg_nvp, &pgn); 526 match = strcmp(group, pgn) == 0; 527 continue; 528 } 529 530 if (strcmp(TOPO_PROP_GROUP_NSTAB, 531 nvpair_name(pg_nvp)) == 0 && 532 nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 533 (void) nvpair_value_string(pg_nvp, &nstab); 534 continue; 535 } 536 537 if (strcmp(TOPO_PROP_GROUP_DSTAB, 538 nvpair_name(pg_nvp)) == 0 && 539 nvpair_type(pg_nvp) == DATA_TYPE_STRING) { 540 (void) nvpair_value_string(pg_nvp, &dstab); 541 continue; 542 } 543 544 if (strcmp(TOPO_PROP_GROUP_VERSION, 545 nvpair_name(pg_nvp)) == 0 && 546 nvpair_type(pg_nvp) == DATA_TYPE_INT32) { 547 (void) nvpair_value_int32(pg_nvp, &version); 548 continue; 549 } 550 551 if ((match || all) && !pg_done) { 552 print_pgroup(thp, node, pgn, dstab, nstab, 553 version); 554 pg_done++; 555 } 556 557 /* 558 * Print property group and property name-value pair 559 */ 560 if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) 561 == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) { 562 (void) nvpair_value_nvlist(pg_nvp, &pv_nv); 563 if ((match || all) && pg_done) { 564 print_prop_nameval(thp, node, pv_nv); 565 } 566 567 } 568 569 } 570 if (match && !all) 571 return; 572 } 573 } 574 575 static void 576 set_prop(topo_hdl_t *thp, tnode_t *node, nvlist_t *fmri, struct prop_args *pp) 577 { 578 int ret, err = 0; 579 topo_type_t type; 580 nvlist_t *nvl, *f = NULL; 581 char *end; 582 583 if (pp->prop == NULL || pp->type == NULL || pp->value == NULL) 584 return; 585 586 if ((type = str2type(pp->type)) == TOPO_TYPE_INVALID) { 587 (void) fprintf(stderr, "%s: invalid property type %s for %s\n", 588 g_pname, pp->type, pp->prop); 589 return; 590 } 591 592 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { 593 (void) fprintf(stderr, "%s: nvlist allocation failed for " 594 "%s=%s:%s\n", g_pname, pp->prop, pp->type, pp->value); 595 return; 596 } 597 ret = nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, pp->prop); 598 ret |= nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, type); 599 if (ret != 0) { 600 (void) fprintf(stderr, "%s: invalid property type %s for %s\n", 601 g_pname, pp->type, pp->prop); 602 nvlist_free(nvl); 603 return; 604 } 605 606 errno = 0; 607 switch (type) { 608 case TOPO_TYPE_INT32: 609 { 610 int32_t val; 611 612 val = strtol(pp->value, &end, 0); 613 if (errno == ERANGE) { 614 ret = -1; 615 break; 616 } 617 ret = nvlist_add_int32(nvl, TOPO_PROP_VAL_VAL, val); 618 break; 619 } 620 case TOPO_TYPE_UINT32: 621 { 622 uint32_t val; 623 624 val = strtoul(pp->value, &end, 0); 625 if (errno == ERANGE) { 626 ret = -1; 627 break; 628 } 629 ret = nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, val); 630 break; 631 } 632 case TOPO_TYPE_INT64: 633 { 634 int64_t val; 635 636 val = strtoll(pp->value, &end, 0); 637 if (errno == ERANGE) { 638 ret = -1; 639 break; 640 } 641 ret = nvlist_add_int64(nvl, TOPO_PROP_VAL_VAL, val); 642 break; 643 } 644 case TOPO_TYPE_UINT64: 645 { 646 uint64_t val; 647 648 val = strtoull(pp->value, &end, 0); 649 if (errno == ERANGE) { 650 ret = -1; 651 break; 652 } 653 ret = nvlist_add_uint64(nvl, TOPO_PROP_VAL_VAL, val); 654 break; 655 } 656 case TOPO_TYPE_STRING: 657 { 658 ret = nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, 659 pp->value); 660 break; 661 } 662 case TOPO_TYPE_FMRI: 663 { 664 if ((ret = topo_fmri_str2nvl(thp, pp->value, &f, &err)) 665 < 0) 666 break; 667 668 if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL_VAL, 669 f)) != 0) 670 err = ETOPO_PROP_NVL; 671 break; 672 } 673 default: 674 ret = -1; 675 } 676 677 if (ret != 0) { 678 (void) fprintf(stderr, "%s: unable to set property value for " 679 "%s: %s\n", g_pname, pp->prop, topo_strerror(err)); 680 nvlist_free(nvl); 681 return; 682 } 683 684 if (node != NULL) { 685 if (topo_prop_setprop(node, pp->group, nvl, TOPO_PROP_MUTABLE, 686 f, &ret) < 0) { 687 (void) fprintf(stderr, "%s: unable to set property " 688 "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, 689 pp->type, pp->value, topo_strerror(ret)); 690 nvlist_free(nvl); 691 nvlist_free(f); 692 return; 693 } 694 } else { 695 if (topo_fmri_setprop(thp, fmri, pp->group, nvl, 696 TOPO_PROP_MUTABLE, f, &ret) < 0) { 697 (void) fprintf(stderr, "%s: unable to set property " 698 "value for " "%s=%s:%s: %s\n", g_pname, pp->prop, 699 pp->type, pp->value, topo_strerror(ret)); 700 nvlist_free(nvl); 701 nvlist_free(f); 702 return; 703 } 704 } 705 706 nvlist_free(nvl); 707 708 /* 709 * Now, get the property back for printing 710 */ 711 if (node != NULL) { 712 if (topo_prop_getprop(node, pp->group, pp->prop, f, &nvl, 713 &err) < 0) { 714 (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", 715 g_pname, pp->group, pp->prop, topo_strerror(err)); 716 nvlist_free(f); 717 return; 718 } 719 } else { 720 if (topo_fmri_getprop(thp, fmri, pp->group, pp->prop, 721 f, &nvl, &err) < 0) { 722 (void) fprintf(stderr, "%s: failed to get %s.%s: %s\n", 723 g_pname, pp->group, pp->prop, topo_strerror(err)); 724 nvlist_free(f); 725 return; 726 } 727 } 728 729 print_pgroup(thp, node, pp->group, NULL, NULL, 0); 730 print_prop_nameval(thp, node, nvl); 731 nvlist_free(nvl); 732 733 nvlist_free(f); 734 } 735 736 static void 737 print_props(topo_hdl_t *thp, tnode_t *node) 738 { 739 int i, err; 740 nvlist_t *nvl; 741 struct prop_args *pp; 742 743 if (pcnt == 0) 744 return; 745 746 for (i = 0; i < pcnt; ++i) { 747 pp = pargs[i]; 748 749 if (pp->group == NULL) 750 continue; 751 752 /* 753 * If we have a valid value, this is a request to 754 * set a property. Otherwise, just print the property 755 * group and any specified properties. 756 */ 757 if (pp->value == NULL) { 758 if (pp->prop == NULL) { 759 760 /* 761 * Print all properties in this group 762 */ 763 if ((nvl = topo_prop_getprops(node, &err)) 764 == NULL) { 765 (void) fprintf(stderr, "%s: failed to " 766 "get %s: %s\n", g_pname, 767 pp->group, 768 topo_strerror(err)); 769 continue; 770 } else { 771 print_all_props(thp, node, nvl, 772 pp->group); 773 nvlist_free(nvl); 774 continue; 775 } 776 } 777 if (topo_prop_getprop(node, pp->group, pp->prop, 778 NULL, &nvl, &err) < 0) { 779 (void) fprintf(stderr, "%s: failed to get " 780 "%s.%s: %s\n", g_pname, 781 pp->group, pp->prop, 782 topo_strerror(err)); 783 continue; 784 } else { 785 print_pgroup(thp, node, pp->group, NULL, 786 NULL, 0); 787 print_prop_nameval(thp, node, nvl); 788 nvlist_free(nvl); 789 } 790 } else { 791 set_prop(thp, node, NULL, pp); 792 } 793 } 794 } 795 796 /*ARGSUSED*/ 797 static int 798 walk_node(topo_hdl_t *thp, tnode_t *node, void *arg) 799 { 800 int err; 801 nvlist_t *nvl; 802 nvlist_t *rsrc, *out; 803 char *s; 804 805 if (opt_e && strcmp(opt_s, FM_FMRI_SCHEME_HC) == 0) { 806 print_everstyle(node); 807 return (TOPO_WALK_NEXT); 808 } 809 810 if (topo_node_resource(node, &rsrc, &err) < 0) { 811 (void) fprintf(stderr, "%s: failed to get resource: " 812 "%s", g_pname, topo_strerror(err)); 813 return (TOPO_WALK_NEXT); 814 } 815 if (topo_fmri_nvl2str(thp, rsrc, &s, &err) < 0) { 816 (void) fprintf(stderr, "%s: failed to convert " 817 "resource to FMRI string: %s", g_pname, 818 topo_strerror(err)); 819 nvlist_free(rsrc); 820 return (TOPO_WALK_NEXT); 821 } 822 823 if (g_fmri != NULL && fnmatch(g_fmri, s, 0) != 0) { 824 nvlist_free(rsrc); 825 topo_hdl_strfree(thp, s); 826 return (TOPO_WALK_NEXT); 827 } 828 829 print_node(thp, node, rsrc, s); 830 topo_hdl_strfree(thp, s); 831 nvlist_free(rsrc); 832 833 /* 834 * If the "-E" option was specified, we want to also enumerate any 835 * available facility nodes. To do that we check if the node supports 836 * a facility enumerator method. If it exists, then we invoke it to 837 * enumerate the sensors for this node. 838 */ 839 if (opt_E) { 840 if (topo_method_supported(node, TOPO_METH_FAC_ENUM, 0)) 841 if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0, 842 NULL, &out, &err) != 0) { 843 (void) fprintf(stderr, 844 "topo_method_invoke failed (%s) on node " 845 "%s=%d\n", topo_strerror(err), 846 topo_node_name(node), 847 topo_node_instance(node)); 848 } 849 } 850 851 if (opt_V || opt_all) { 852 if ((nvl = topo_prop_getprops(node, &err)) == NULL) { 853 (void) fprintf(stderr, "%s: failed to get " 854 "properties for %s=%d: %s\n", g_pname, 855 topo_node_name(node), topo_node_instance(node), 856 topo_strerror(err)); 857 } else { 858 print_all_props(thp, node, nvl, ALL); 859 nvlist_free(nvl); 860 } 861 } else if (pcnt > 0) 862 print_props(thp, node); 863 864 printf("\n"); 865 866 return (TOPO_WALK_NEXT); 867 } 868 869 static void 870 get_pargs(int argc, char *argv[]) 871 { 872 struct prop_args *pp; 873 char c, *s, *p; 874 int i = 0; 875 876 if ((pargs = malloc(sizeof (struct prop_args *) * pcnt)) == NULL) { 877 (void) fprintf(stderr, "%s: failed to allocate property " 878 "arguments\n", g_pname); 879 return; 880 } 881 882 for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) { 883 if (c == 'P') { 884 885 if (strcmp(optarg, ALL) == 0) { 886 opt_all++; 887 break; 888 } 889 890 if ((pp = pargs[i] = malloc(sizeof (struct prop_args))) 891 == NULL) { 892 (void) fprintf(stderr, "%s: failed to " 893 "allocate propertyarguments\n", g_pname); 894 return; 895 } 896 ++i; 897 pp->group = NULL; 898 pp->prop = NULL; 899 pp->type = NULL; 900 pp->value = NULL; 901 902 p = optarg; 903 if ((s = strchr(p, '.')) != NULL) { 904 *s++ = '\0'; /* strike out delimiter */ 905 pp->group = p; 906 p = s; 907 if ((s = strchr(p, '=')) != NULL) { 908 *s++ = '\0'; /* strike out delimiter */ 909 pp->prop = p; 910 p = s; 911 if ((s = strchr(p, ':')) != NULL) { 912 *s++ = '\0'; 913 pp->type = p; 914 pp->value = s; 915 } else { 916 (void) fprintf(stderr, "%s: " 917 "property type not " 918 "specified for assignment " 919 " of %s.%s\n", g_pname, 920 pp->group, pp->prop); 921 break; 922 } 923 } else { 924 pp->prop = p; 925 } 926 } else { 927 pp->group = p; 928 } 929 if (i >= pcnt) 930 break; 931 } 932 } 933 934 if (opt_all > 0) { 935 int j; 936 937 for (j = 0; j < i; ++j) 938 free(pargs[i]); 939 free(pargs); 940 pargs = NULL; 941 } 942 } 943 944 static int 945 walk_topo(topo_hdl_t *thp, char *uuid) 946 { 947 int err; 948 topo_walk_t *twp; 949 int flag; 950 951 if ((twp = topo_walk_init(thp, opt_s, walk_node, NULL, &err)) 952 == NULL) { 953 (void) fprintf(stderr, "%s: failed to walk %s topology:" 954 " %s\n", g_pname, opt_s, topo_strerror(err)); 955 956 return (-1); 957 } 958 959 /* 960 * Print standard header 961 */ 962 if (!opt_e) { 963 char buf[32]; 964 time_t tod = time(NULL); 965 966 printf("TIME UUID\n"); 967 (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod)); 968 (void) printf("%-15s %-32s\n", buf, uuid); 969 (void) printf("\n"); 970 } 971 972 flag = opt_b != 0 ? TOPO_WALK_SIBLING : TOPO_WALK_CHILD; 973 974 if (topo_walk_step(twp, flag) == TOPO_WALK_ERR) { 975 (void) fprintf(stderr, "%s: failed to walk topology\n", 976 g_pname); 977 topo_walk_fini(twp); 978 return (-1); 979 } 980 981 topo_walk_fini(twp); 982 983 return (0); 984 } 985 986 static void 987 print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl) 988 { 989 char *dstab = NULL, *nstab = NULL; 990 int32_t version = -1; 991 nvlist_t *pnvl; 992 nvpair_t *pnvp; 993 994 (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab); 995 (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab); 996 (void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version); 997 998 print_pgroup(thp, NULL, pgn, dstab, nstab, version); 999 1000 for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL; 1001 pnvp = nvlist_next_nvpair(nvl, pnvp)) { 1002 1003 /* 1004 * Print property group and property name-value pair 1005 */ 1006 if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp)) 1007 == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) { 1008 (void) nvpair_value_nvlist(pnvp, &pnvl); 1009 print_prop_nameval(thp, NULL, pnvl); 1010 1011 } 1012 1013 } 1014 } 1015 1016 static void 1017 print_fmri_props(topo_hdl_t *thp, nvlist_t *nvl) 1018 { 1019 int i, err; 1020 struct prop_args *pp; 1021 nvlist_t *pnvl; 1022 1023 for (i = 0; i < pcnt; ++i) { 1024 pp = pargs[i]; 1025 1026 if (pp->group == NULL) 1027 continue; 1028 1029 pnvl = NULL; 1030 1031 /* 1032 * If we have a valid value, this is a request to 1033 * set a property. Otherwise, just print the property 1034 * group and any specified properties. 1035 */ 1036 if (pp->value == NULL) { 1037 if (pp->prop == NULL) { 1038 1039 /* 1040 * Print all properties in this group 1041 */ 1042 if (topo_fmri_getpgrp(thp, nvl, pp->group, 1043 &pnvl, &err) < 0) { 1044 (void) fprintf(stderr, "%s: failed to " 1045 "get group %s: %s\n", g_pname, 1046 pp->group, topo_strerror(err)); 1047 continue; 1048 } else { 1049 print_fmri_pgroup(thp, pp->group, 1050 pnvl); 1051 nvlist_free(pnvl); 1052 continue; 1053 } 1054 } 1055 if (topo_fmri_getprop(thp, nvl, pp->group, pp->prop, 1056 NULL, &pnvl, &err) < 0) { 1057 (void) fprintf(stderr, "%s: failed to get " 1058 "%s.%s: %s\n", g_pname, 1059 pp->group, pp->prop, 1060 topo_strerror(err)); 1061 continue; 1062 } else { 1063 print_fmri_pgroup(thp, pp->group, pnvl); 1064 print_prop_nameval(thp, NULL, pnvl); 1065 nvlist_free(nvl); 1066 } 1067 } else { 1068 set_prop(thp, NULL, nvl, pp); 1069 } 1070 } 1071 } 1072 1073 void 1074 print_fmri(topo_hdl_t *thp, char *uuid) 1075 { 1076 int ret, err; 1077 nvlist_t *nvl; 1078 char buf[32]; 1079 time_t tod = time(NULL); 1080 1081 if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { 1082 (void) fprintf(stderr, "%s: failed to convert %s to nvlist: " 1083 "%s\n", g_pname, g_fmri, topo_strerror(err)); 1084 return; 1085 } 1086 1087 printf("TIME UUID\n"); 1088 (void) strftime(buf, sizeof (buf), "%b %d %T", localtime(&tod)); 1089 (void) printf("%-15s %-32s\n", buf, uuid); 1090 (void) printf("\n"); 1091 1092 (void) printf("%s\n", (char *)g_fmri); 1093 1094 if (opt_p && !(pcnt > 0 || opt_V || opt_all)) { 1095 char *aname = NULL, *fname = NULL, *lname = NULL; 1096 nvlist_t *asru = NULL; 1097 nvlist_t *fru = NULL; 1098 1099 if (topo_fmri_asru(thp, nvl, &asru, &err) == 0) 1100 (void) topo_fmri_nvl2str(thp, asru, &aname, &err); 1101 if (topo_fmri_fru(thp, nvl, &fru, &err) == 0) 1102 (void) topo_fmri_nvl2str(thp, fru, &fname, &err); 1103 (void) topo_fmri_label(thp, nvl, &lname, &err); 1104 1105 nvlist_free(fru); 1106 nvlist_free(asru); 1107 1108 if (aname != NULL) { 1109 (void) printf("\tASRU: %s\n", aname); 1110 topo_hdl_strfree(thp, aname); 1111 } else { 1112 (void) printf("\tASRU: -\n"); 1113 } 1114 if (fname != NULL) { 1115 (void) printf("\tFRU: %s\n", fname); 1116 topo_hdl_strfree(thp, fname); 1117 } else { 1118 (void) printf("\tFRU: -\n"); 1119 } 1120 if (lname != NULL) { 1121 (void) printf("\tLabel: %s\n", lname); 1122 topo_hdl_strfree(thp, lname); 1123 } else { 1124 (void) printf("\tLabel: -\n"); 1125 } 1126 } 1127 1128 if (opt_S) { 1129 if (topo_fmri_str2nvl(thp, g_fmri, &nvl, &err) < 0) { 1130 (void) printf("\tPresent: -\n"); 1131 (void) printf("\tUnusable: -\n"); 1132 return; 1133 } 1134 1135 if ((ret = topo_fmri_present(thp, nvl, &err)) < 0) 1136 (void) printf("\tPresent: -\n"); 1137 else 1138 (void) printf("\tPresent: %s\n", 1139 ret ? "true" : "false"); 1140 1141 if ((ret = topo_fmri_unusable(thp, nvl, &err)) < 0) 1142 (void) printf("\tUnusable: -\n"); 1143 else 1144 (void) printf("\tUnusable: %s\n", 1145 ret ? "true" : "false"); 1146 1147 nvlist_free(nvl); 1148 } 1149 1150 if (pargs && pcnt > 0) 1151 print_fmri_props(thp, nvl); 1152 } 1153 1154 int 1155 fmtopo_exit(topo_hdl_t *thp, char *uuid, int err) 1156 { 1157 if (uuid != NULL) 1158 topo_hdl_strfree(thp, uuid); 1159 1160 if (thp != NULL) { 1161 topo_snap_release(thp); 1162 topo_close(thp); 1163 } 1164 1165 if (pargs) { 1166 int i; 1167 for (i = 0; i < pcnt; ++i) 1168 free(pargs[i]); 1169 free(pargs); 1170 } 1171 1172 return (err); 1173 } 1174 1175 int 1176 main(int argc, char *argv[]) 1177 { 1178 topo_hdl_t *thp = NULL; 1179 char *uuid = NULL; 1180 int c, err = 0; 1181 1182 g_pname = argv[0]; 1183 1184 while (optind < argc) { 1185 while ((c = getopt(argc, argv, optstr)) != -1) { 1186 switch (c) { 1187 case 'b': 1188 opt_b++; 1189 break; 1190 case 'C': 1191 atexit(abort); 1192 break; 1193 case 'd': 1194 opt_d++; 1195 break; 1196 case 'e': 1197 opt_e++; 1198 break; 1199 case 'E': 1200 opt_E++; 1201 break; 1202 case 'P': 1203 pcnt++; 1204 break; 1205 case 'p': 1206 opt_p++; 1207 break; 1208 case 'V': 1209 opt_V++; 1210 break; 1211 case 'R': 1212 opt_R = optarg; 1213 break; 1214 case 's': 1215 opt_s = optarg; 1216 break; 1217 case 'S': 1218 opt_S++; 1219 break; 1220 case 't': 1221 opt_t++; 1222 break; 1223 case 'x': 1224 opt_x++; 1225 break; 1226 default: 1227 return (usage(stderr)); 1228 } 1229 } 1230 1231 if (optind < argc) { 1232 if (g_fmri != NULL) { 1233 (void) fprintf(stderr, "%s: illegal argument " 1234 "-- %s\n", g_pname, argv[optind]); 1235 return (FMTOPO_EXIT_USAGE); 1236 } else { 1237 g_fmri = argv[optind++]; 1238 } 1239 } 1240 } 1241 1242 if (pcnt > 0) 1243 get_pargs(argc, argv); 1244 1245 if ((thp = topo_open(TOPO_VERSION, opt_R, &err)) == NULL) { 1246 (void) fprintf(stderr, "%s: failed to open topology tree: %s\n", 1247 g_pname, topo_strerror(err)); 1248 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1249 } 1250 1251 if (opt_d) 1252 topo_debug_set(thp, "module", "stderr"); 1253 1254 if ((uuid = topo_snap_hold(thp, NULL, &err)) == NULL) { 1255 (void) fprintf(stderr, "%s: failed to snapshot topology: %s\n", 1256 g_pname, topo_strerror(err)); 1257 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1258 } else if (err != 0) { 1259 (void) fprintf(stderr, "%s: topology snapshot incomplete\n", 1260 g_pname); 1261 } 1262 1263 if (opt_x) { 1264 if (opt_b) { 1265 (void) fprintf(stderr, 1266 "%s: -b and -x cannot be specified together\n", 1267 g_pname); 1268 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_USAGE)); 1269 } 1270 1271 err = 0; 1272 if (topo_xml_print(thp, stdout, opt_s, &err) < 0) 1273 (void) fprintf(stderr, "%s: failed to print xml " 1274 "formatted topology:%s", g_pname, 1275 topo_strerror(err)); 1276 1277 return (fmtopo_exit(thp, uuid, err ? FMTOPO_EXIT_ERROR : 1278 FMTOPO_EXIT_SUCCESS)); 1279 } 1280 1281 if (opt_t || walk_topo(thp, uuid) < 0) { 1282 if (g_fmri != NULL) 1283 /* 1284 * Try getting some useful information 1285 */ 1286 print_fmri(thp, uuid); 1287 1288 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_ERROR)); 1289 } 1290 1291 return (fmtopo_exit(thp, uuid, FMTOPO_EXIT_SUCCESS)); 1292 } 1293