1 /* 2 * Copyright (c) 2012 Hewlett-Packard Development Company, L.P. 3 * 4 * Based on code from 5 * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * Redistribution of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * Redistribution in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name of Sun Microsystems, Inc. or the names of 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * This software is provided "AS IS," without a warranty of any kind. 23 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, 24 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A 25 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. 26 * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE 27 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING 28 * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL 29 * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, 30 * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR 31 * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF 32 * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 33 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 34 */ 35 36 #include <string.h> 37 38 #include <math.h> 39 #include <stdio.h> 40 #include <unistd.h> 41 #include <sys/types.h> 42 #include <time.h> 43 44 #include <ipmitool/ipmi.h> 45 #include <ipmitool/log.h> 46 #include <ipmitool/ipmi_mc.h> 47 #include <ipmitool/ipmi_sdr.h> 48 #include <ipmitool/ipmi_sdradd.h> 49 #include <ipmitool/ipmi_sensor.h> 50 #include <ipmitool/ipmi_intf.h> 51 #include <ipmitool/ipmi_sel.h> 52 #include <ipmitool/ipmi_entity.h> 53 #include <ipmitool/ipmi_constants.h> 54 #include <ipmitool/ipmi_strings.h> 55 56 #if HAVE_CONFIG_H 57 # include <config.h> 58 #endif 59 60 extern int verbose; 61 static int use_built_in; /* Uses DeviceSDRs instead of SDRR */ 62 static int sdr_max_read_len = 0; 63 static int sdr_extended = 0; 64 static long sdriana = 0; 65 66 static struct sdr_record_list *sdr_list_head = NULL; 67 static struct sdr_record_list *sdr_list_tail = NULL; 68 static struct ipmi_sdr_iterator *sdr_list_itr = NULL; 69 70 void printf_sdr_usage(); 71 72 /* ipmi_sdr_get_unit_string - return units for base/modifier 73 * 74 * @pct: units are a percentage 75 * @type: unit type 76 * @base: base 77 * @modifier: modifier 78 * 79 * returns pointer to static string 80 */ 81 const char * 82 ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type, uint8_t base, uint8_t modifier) 83 { 84 static char unitstr[16]; 85 /* 86 * By default, if units are supposed to be percent, we will pre-pend 87 * the percent string to the textual representation of the units. 88 */ 89 char *pctstr = pct ? "% " : ""; 90 memset(unitstr, 0, sizeof (unitstr)); 91 switch (type) { 92 case 2: 93 snprintf(unitstr, sizeof (unitstr), "%s%s * %s", 94 pctstr, unit_desc[base], unit_desc[modifier]); 95 break; 96 case 1: 97 snprintf(unitstr, sizeof (unitstr), "%s%s/%s", 98 pctstr, unit_desc[base], unit_desc[modifier]); 99 break; 100 case 0: 101 default: 102 /* 103 * Display the text "percent" only when the Base unit is 104 * "unspecified" and the caller specified to print percent. 105 */ 106 if (base == 0 && pct) { 107 snprintf(unitstr, sizeof(unitstr), "percent"); 108 } else { 109 snprintf(unitstr, sizeof (unitstr), "%s%s", 110 pctstr, unit_desc[base]); 111 } 112 break; 113 } 114 return unitstr; 115 } 116 117 /* sdr_sensor_has_analog_reading - Determine if sensor has an analog reading 118 * 119 */ 120 static int 121 sdr_sensor_has_analog_reading(struct ipmi_intf *intf, 122 struct sensor_reading *sr) 123 { 124 /* Compact sensors can't return analog values so we false */ 125 if (!sr->full) { 126 return 0; 127 } 128 /* 129 * Per the IPMI Specification: 130 * Only Full Threshold sensors are identified as providing 131 * analog readings. 132 * 133 * But... HP didn't interpret this as meaning that "Only Threshold 134 * Sensors" can provide analog readings. So, HP packed analog 135 * readings into some of their non-Threshold Sensor. There is 136 * nothing that explictly prohibits this in the spec, so if 137 * an Analog reading is available in a Non-Threshod sensor and 138 * there are units specified for identifying the reading then 139 * we do an analog conversion even though the sensor is 140 * non-Threshold. To be safe, we provide this extension for 141 * HP. 142 * 143 */ 144 if ( UNITS_ARE_DISCRETE(&sr->full->cmn) ) { 145 return 0;/* Sensor specified as not having Analog Units */ 146 } 147 if ( !IS_THRESHOLD_SENSOR(&sr->full->cmn) ) { 148 /* Non-Threshold Sensors are not defined as having analog */ 149 /* But.. We have one with defined with Analog Units */ 150 if ( (sr->full->cmn.unit.pct | sr->full->cmn.unit.modifier | 151 sr->full->cmn.unit.type.base | 152 sr->full->cmn.unit.type.modifier)) { 153 /* And it does have the necessary units specs */ 154 if ( !(intf->manufacturer_id == IPMI_OEM_HP) ) { 155 /* But to be safe we only do this for HP */ 156 return 0; 157 } 158 } else { 159 return 0; 160 } 161 } 162 /* 163 * If sensor has linearization, then we should be able to update the 164 * reading factors and if we cannot fail the conversion. 165 */ 166 if (sr->full->linearization >= SDR_SENSOR_L_NONLINEAR && 167 sr->full->linearization <= 0x7F) { 168 if (ipmi_sensor_get_sensor_reading_factors(intf, sr->full, sr->s_reading) < 0){ 169 sr->s_reading_valid = 0; 170 return 0; 171 } 172 } 173 174 return 1; 175 } 176 177 /* sdr_convert_sensor_reading - convert raw sensor reading 178 * 179 * @sensor: sensor record 180 * @val: raw sensor reading 181 * 182 * returns floating-point sensor reading 183 */ 184 double 185 sdr_convert_sensor_reading(struct sdr_record_full_sensor *sensor, uint8_t val) 186 { 187 int m, b, k1, k2; 188 double result; 189 190 m = __TO_M(sensor->mtol); 191 b = __TO_B(sensor->bacc); 192 k1 = __TO_B_EXP(sensor->bacc); 193 k2 = __TO_R_EXP(sensor->bacc); 194 195 switch (sensor->cmn.unit.analog) { 196 case 0: 197 result = (double) (((m * val) + 198 (b * pow(10, k1))) * pow(10, k2)); 199 break; 200 case 1: 201 if (val & 0x80) 202 val++; 203 /* Deliberately fall through to case 2. */ 204 case 2: 205 result = (double) (((m * (int8_t) val) + 206 (b * pow(10, k1))) * pow(10, k2)); 207 break; 208 default: 209 /* Oops! This isn't an analog sensor. */ 210 return 0.0; 211 } 212 213 switch (sensor->linearization & 0x7f) { 214 case SDR_SENSOR_L_LN: 215 result = log(result); 216 break; 217 case SDR_SENSOR_L_LOG10: 218 result = log10(result); 219 break; 220 case SDR_SENSOR_L_LOG2: 221 result = (double) (log(result) / log(2.0)); 222 break; 223 case SDR_SENSOR_L_E: 224 result = exp(result); 225 break; 226 case SDR_SENSOR_L_EXP10: 227 result = pow(10.0, result); 228 break; 229 case SDR_SENSOR_L_EXP2: 230 result = pow(2.0, result); 231 break; 232 case SDR_SENSOR_L_1_X: 233 result = pow(result, -1.0); /*1/x w/o exception */ 234 break; 235 case SDR_SENSOR_L_SQR: 236 result = pow(result, 2.0); 237 break; 238 case SDR_SENSOR_L_CUBE: 239 result = pow(result, 3.0); 240 break; 241 case SDR_SENSOR_L_SQRT: 242 result = sqrt(result); 243 break; 244 case SDR_SENSOR_L_CUBERT: 245 result = cbrt(result); 246 break; 247 case SDR_SENSOR_L_LINEAR: 248 default: 249 break; 250 } 251 return result; 252 } 253 /* sdr_convert_sensor_hysterisis - convert raw sensor hysterisis 254 * 255 * Even though spec says histerisis should be computed using Mx+B 256 * formula, B is irrelevant when doing raw comparison 257 * 258 * threshold rearm point is computed using threshold +/- hysterisis 259 * with the full formula however B can't be applied in raw comparisons 260 * 261 * @sensor: sensor record 262 * @val: raw sensor reading 263 * 264 * returns floating-point sensor reading 265 */ 266 double 267 sdr_convert_sensor_hysterisis(struct sdr_record_full_sensor *sensor, uint8_t val) 268 { 269 int m, k2; 270 double result; 271 272 m = __TO_M(sensor->mtol); 273 274 k2 = __TO_R_EXP(sensor->bacc); 275 276 switch (sensor->cmn.unit.analog) { 277 case 0: 278 result = (double) (((m * val)) * pow(10, k2)); 279 break; 280 case 1: 281 if (val & 0x80) 282 val++; 283 /* Deliberately fall through to case 2. */ 284 case 2: 285 result = (double) (((m * (int8_t) val) ) * pow(10, k2)); 286 break; 287 default: 288 /* Oops! This isn't an analog sensor. */ 289 return 0.0; 290 } 291 292 switch (sensor->linearization & 0x7f) { 293 case SDR_SENSOR_L_LN: 294 result = log(result); 295 break; 296 case SDR_SENSOR_L_LOG10: 297 result = log10(result); 298 break; 299 case SDR_SENSOR_L_LOG2: 300 result = (double) (log(result) / log(2.0)); 301 break; 302 case SDR_SENSOR_L_E: 303 result = exp(result); 304 break; 305 case SDR_SENSOR_L_EXP10: 306 result = pow(10.0, result); 307 break; 308 case SDR_SENSOR_L_EXP2: 309 result = pow(2.0, result); 310 break; 311 case SDR_SENSOR_L_1_X: 312 result = pow(result, -1.0); /*1/x w/o exception */ 313 break; 314 case SDR_SENSOR_L_SQR: 315 result = pow(result, 2.0); 316 break; 317 case SDR_SENSOR_L_CUBE: 318 result = pow(result, 3.0); 319 break; 320 case SDR_SENSOR_L_SQRT: 321 result = sqrt(result); 322 break; 323 case SDR_SENSOR_L_CUBERT: 324 result = cbrt(result); 325 break; 326 case SDR_SENSOR_L_LINEAR: 327 default: 328 break; 329 } 330 return result; 331 } 332 333 334 /* sdr_convert_sensor_tolerance - convert raw sensor reading 335 * 336 * @sensor: sensor record 337 * @val: raw sensor reading 338 * 339 * returns floating-point sensor tolerance(interpreted) 340 */ 341 double 342 sdr_convert_sensor_tolerance(struct sdr_record_full_sensor *sensor, uint8_t val) 343 { 344 int m, k2; 345 double result; 346 347 m = __TO_M(sensor->mtol); 348 k2 = __TO_R_EXP(sensor->bacc); 349 350 switch (sensor->cmn.unit.analog) { 351 case 0: 352 /* as suggested in section 30.4.1 of IPMI 1.5 spec */ 353 result = (double) ((((m * (double)val/2)) ) * pow(10, k2)); 354 break; 355 case 1: 356 if (val & 0x80) 357 val++; 358 /* Deliberately fall through to case 2. */ 359 case 2: 360 result = (double) (((m * ((double)((int8_t) val)/2))) * pow(10, k2)); 361 break; 362 default: 363 /* Oops! This isn't an analog sensor. */ 364 return 0.0; 365 } 366 367 switch (sensor->linearization & 0x7f) { 368 case SDR_SENSOR_L_LN: 369 result = log(result); 370 break; 371 case SDR_SENSOR_L_LOG10: 372 result = log10(result); 373 break; 374 case SDR_SENSOR_L_LOG2: 375 result = (double) (log(result) / log(2.0)); 376 break; 377 case SDR_SENSOR_L_E: 378 result = exp(result); 379 break; 380 case SDR_SENSOR_L_EXP10: 381 result = pow(10.0, result); 382 break; 383 case SDR_SENSOR_L_EXP2: 384 result = pow(2.0, result); 385 break; 386 case SDR_SENSOR_L_1_X: 387 result = pow(result, -1.0); /*1/x w/o exception */ 388 break; 389 case SDR_SENSOR_L_SQR: 390 result = pow(result, 2.0); 391 break; 392 case SDR_SENSOR_L_CUBE: 393 result = pow(result, 3.0); 394 break; 395 case SDR_SENSOR_L_SQRT: 396 result = sqrt(result); 397 break; 398 case SDR_SENSOR_L_CUBERT: 399 result = cbrt(result); 400 break; 401 case SDR_SENSOR_L_LINEAR: 402 default: 403 break; 404 } 405 return result; 406 } 407 408 /* sdr_convert_sensor_value_to_raw - convert sensor reading back to raw 409 * 410 * @sensor: sensor record 411 * @val: converted sensor reading 412 * 413 * returns raw sensor reading 414 */ 415 uint8_t 416 sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor * sensor, 417 double val) 418 { 419 int m, b, k1, k2; 420 double result; 421 422 /* only works for analog sensors */ 423 if (UNITS_ARE_DISCRETE((&sensor->cmn))) 424 return 0; 425 426 m = __TO_M(sensor->mtol); 427 b = __TO_B(sensor->bacc); 428 k1 = __TO_B_EXP(sensor->bacc); 429 k2 = __TO_R_EXP(sensor->bacc); 430 431 /* don't divide by zero */ 432 if (m == 0) 433 return 0; 434 435 result = (((val / pow(10, k2)) - (b * pow(10, k1))) / m); 436 437 if ((result - (int) result) >= .5) 438 return (uint8_t) ceil(result); 439 else 440 return (uint8_t) result; 441 } 442 443 /* ipmi_sdr_get_sensor_thresholds - return thresholds for sensor 444 * 445 * @intf: ipmi interface 446 * @sensor: sensor number 447 * @target: sensor owner ID 448 * @lun: sensor lun 449 * @channel: channel number 450 * 451 * returns pointer to ipmi response 452 */ 453 struct ipmi_rs * 454 ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf, uint8_t sensor, 455 uint8_t target, uint8_t lun, uint8_t channel) 456 { 457 struct ipmi_rq req; 458 struct ipmi_rs *rsp; 459 uint8_t bridged_request = 0; 460 uint32_t save_addr; 461 uint32_t save_channel; 462 463 if ( BRIDGE_TO_SENSOR(intf, target, channel) ) { 464 bridged_request = 1; 465 save_addr = intf->target_addr; 466 intf->target_addr = target; 467 save_channel = intf->target_channel; 468 intf->target_channel = channel; 469 } 470 471 memset(&req, 0, sizeof (req)); 472 req.msg.netfn = IPMI_NETFN_SE; 473 req.msg.lun = lun; 474 req.msg.cmd = GET_SENSOR_THRESHOLDS; 475 req.msg.data = &sensor; 476 req.msg.data_len = sizeof (sensor); 477 478 rsp = intf->sendrecv(intf, &req); 479 if (bridged_request) { 480 intf->target_addr = save_addr; 481 intf->target_channel = save_channel; 482 } 483 return rsp; 484 } 485 486 /* ipmi_sdr_get_sensor_hysteresis - return hysteresis for sensor 487 * 488 * @intf: ipmi interface 489 * @sensor: sensor number 490 * @target: sensor owner ID 491 * @lun: sensor lun 492 * @channel: channel number 493 * 494 * returns pointer to ipmi response 495 */ 496 struct ipmi_rs * 497 ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf, uint8_t sensor, 498 uint8_t target, uint8_t lun, uint8_t channel) 499 { 500 struct ipmi_rq req; 501 uint8_t rqdata[2]; 502 struct ipmi_rs *rsp; 503 uint8_t bridged_request = 0; 504 uint32_t save_addr; 505 uint32_t save_channel; 506 507 if ( BRIDGE_TO_SENSOR(intf, target, channel) ) { 508 bridged_request = 1; 509 save_addr = intf->target_addr; 510 intf->target_addr = target; 511 save_channel = intf->target_channel; 512 intf->target_channel = channel; 513 } 514 515 rqdata[0] = sensor; 516 rqdata[1] = 0xff; /* reserved */ 517 518 memset(&req, 0, sizeof (req)); 519 req.msg.netfn = IPMI_NETFN_SE; 520 req.msg.lun = lun; 521 req.msg.cmd = GET_SENSOR_HYSTERESIS; 522 req.msg.data = rqdata; 523 req.msg.data_len = 2; 524 525 rsp = intf->sendrecv(intf, &req); 526 if (bridged_request) { 527 intf->target_addr = save_addr; 528 intf->target_channel = save_channel; 529 } 530 return rsp; 531 } 532 533 /* ipmi_sdr_get_sensor_reading - retrieve a raw sensor reading 534 * 535 * @intf: ipmi interface 536 * @sensor: sensor id 537 * 538 * returns ipmi response structure 539 */ 540 struct ipmi_rs * 541 ipmi_sdr_get_sensor_reading(struct ipmi_intf *intf, uint8_t sensor) 542 { 543 struct ipmi_rq req; 544 545 memset(&req, 0, sizeof (req)); 546 req.msg.netfn = IPMI_NETFN_SE; 547 req.msg.cmd = GET_SENSOR_READING; 548 req.msg.data = &sensor; 549 req.msg.data_len = 1; 550 551 return intf->sendrecv(intf, &req); 552 } 553 554 555 /* ipmi_sdr_get_sensor_reading_ipmb - retrieve a raw sensor reading from ipmb 556 * 557 * @intf: ipmi interface 558 * @sensor: sensor id 559 * @target: IPMB target address 560 * @lun: sensor lun 561 * @channel: channel number 562 * 563 * returns ipmi response structure 564 */ 565 struct ipmi_rs * 566 ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf, uint8_t sensor, 567 uint8_t target, uint8_t lun, uint8_t channel) 568 { 569 struct ipmi_rq req; 570 struct ipmi_rs *rsp; 571 uint8_t bridged_request = 0; 572 uint32_t save_addr; 573 uint32_t save_channel; 574 575 if ( BRIDGE_TO_SENSOR(intf, target, channel) ) { 576 lprintf(LOG_DEBUG, 577 "Bridge to Sensor " 578 "Intf my/%#x tgt/%#x:%#x Sdr tgt/%#x:%#x\n", 579 intf->my_addr, intf->target_addr, intf->target_channel, 580 target, channel); 581 bridged_request = 1; 582 save_addr = intf->target_addr; 583 intf->target_addr = target; 584 save_channel = intf->target_channel; 585 intf->target_channel = channel; 586 } 587 memset(&req, 0, sizeof (req)); 588 req.msg.netfn = IPMI_NETFN_SE; 589 req.msg.lun = lun; 590 req.msg.cmd = GET_SENSOR_READING; 591 req.msg.data = &sensor; 592 req.msg.data_len = 1; 593 594 rsp = intf->sendrecv(intf, &req); 595 if (bridged_request) { 596 intf->target_addr = save_addr; 597 intf->target_channel = save_channel; 598 } 599 return rsp; 600 } 601 602 /* ipmi_sdr_get_sensor_event_status - retrieve sensor event status 603 * 604 * @intf: ipmi interface 605 * @sensor: sensor id 606 * @target: sensor owner ID 607 * @lun: sensor lun 608 * @channel: channel number 609 * 610 * returns ipmi response structure 611 */ 612 struct ipmi_rs * 613 ipmi_sdr_get_sensor_event_status(struct ipmi_intf *intf, uint8_t sensor, 614 uint8_t target, uint8_t lun, uint8_t channel) 615 { 616 struct ipmi_rq req; 617 struct ipmi_rs *rsp; 618 uint8_t bridged_request = 0; 619 uint32_t save_addr; 620 uint32_t save_channel; 621 622 if ( BRIDGE_TO_SENSOR(intf, target, channel) ) { 623 bridged_request = 1; 624 save_addr = intf->target_addr; 625 intf->target_addr = target; 626 save_channel = intf->target_channel; 627 intf->target_channel = channel; 628 } 629 memset(&req, 0, sizeof (req)); 630 req.msg.netfn = IPMI_NETFN_SE; 631 req.msg.lun = lun; 632 req.msg.cmd = GET_SENSOR_EVENT_STATUS; 633 req.msg.data = &sensor; 634 req.msg.data_len = 1; 635 636 rsp = intf->sendrecv(intf, &req); 637 if (bridged_request) { 638 intf->target_addr = save_addr; 639 intf->target_channel = save_channel; 640 } 641 return rsp; 642 } 643 644 /* ipmi_sdr_get_sensor_event_enable - retrieve sensor event enables 645 * 646 * @intf: ipmi interface 647 * @sensor: sensor id 648 * @target: sensor owner ID 649 * @lun: sensor lun 650 * @channel: channel number 651 * 652 * returns ipmi response structure 653 */ 654 struct ipmi_rs * 655 ipmi_sdr_get_sensor_event_enable(struct ipmi_intf *intf, uint8_t sensor, 656 uint8_t target, uint8_t lun, uint8_t channel) 657 { 658 struct ipmi_rq req; 659 struct ipmi_rs *rsp; 660 uint8_t bridged_request = 0; 661 uint32_t save_addr; 662 uint32_t save_channel; 663 664 if ( BRIDGE_TO_SENSOR(intf, target, channel) ) { 665 bridged_request = 1; 666 save_addr = intf->target_addr; 667 intf->target_addr = target; 668 save_channel = intf->target_channel; 669 intf->target_channel = channel; 670 } 671 672 memset(&req, 0, sizeof (req)); 673 req.msg.netfn = IPMI_NETFN_SE; 674 req.msg.lun = lun; 675 req.msg.cmd = GET_SENSOR_EVENT_ENABLE; 676 req.msg.data = &sensor; 677 req.msg.data_len = 1; 678 679 rsp = intf->sendrecv(intf, &req); 680 if (bridged_request) { 681 intf->target_addr = save_addr; 682 intf->target_channel = save_channel; 683 } 684 return rsp; 685 } 686 687 /* ipmi_sdr_get_sensor_type_desc - Get sensor type descriptor 688 * 689 * @type: ipmi sensor type 690 * 691 * returns 692 * string from sensor_type_desc 693 * or "reserved" 694 * or "OEM reserved" 695 */ 696 const char * 697 ipmi_sdr_get_sensor_type_desc(const uint8_t type) 698 { 699 static char desc[32]; 700 memset(desc, 0, 32); 701 if (type <= SENSOR_TYPE_MAX) 702 return sensor_type_desc[type]; 703 if (type < 0xc0) 704 snprintf(desc, 32, "reserved #%02x", type); 705 else 706 { 707 snprintf(desc, 32, oemval2str(sdriana,type,ipmi_oem_sdr_type_vals), 708 type); 709 } 710 return desc; 711 } 712 713 /* ipmi_sdr_get_thresh_status - threshold status indicator 714 * 715 * @rsp: response from Get Sensor Reading comand 716 * @validread: validity of the status field argument 717 * @invalidstr: string to return if status field is not valid 718 * 719 * returns 720 * cr = critical 721 * nc = non-critical 722 * nr = non-recoverable 723 * ok = ok 724 * ns = not specified 725 */ 726 const char * 727 ipmi_sdr_get_thresh_status(struct sensor_reading *sr, const char *invalidstr) 728 { 729 uint8_t stat; 730 if (!sr->s_reading_valid) { 731 return invalidstr; 732 } 733 stat = sr->s_data2; 734 if (stat & SDR_SENSOR_STAT_LO_NR) { 735 if (verbose) 736 return "Lower Non-Recoverable"; 737 else if (sdr_extended) 738 return "lnr"; 739 else 740 return "nr"; 741 } else if (stat & SDR_SENSOR_STAT_HI_NR) { 742 if (verbose) 743 return "Upper Non-Recoverable"; 744 else if (sdr_extended) 745 return "unr"; 746 else 747 return "nr"; 748 } else if (stat & SDR_SENSOR_STAT_LO_CR) { 749 if (verbose) 750 return "Lower Critical"; 751 else if (sdr_extended) 752 return "lcr"; 753 else 754 return "cr"; 755 } else if (stat & SDR_SENSOR_STAT_HI_CR) { 756 if (verbose) 757 return "Upper Critical"; 758 else if (sdr_extended) 759 return "ucr"; 760 else 761 return "cr"; 762 } else if (stat & SDR_SENSOR_STAT_LO_NC) { 763 if (verbose) 764 return "Lower Non-Critical"; 765 else if (sdr_extended) 766 return "lnc"; 767 else 768 return "nc"; 769 } else if (stat & SDR_SENSOR_STAT_HI_NC) { 770 if (verbose) 771 return "Upper Non-Critical"; 772 else if (sdr_extended) 773 return "unc"; 774 else 775 return "nc"; 776 } 777 return "ok"; 778 } 779 780 /* ipmi_sdr_get_header - retreive SDR record header 781 * 782 * @intf: ipmi interface 783 * @itr: sdr iterator 784 * 785 * returns pointer to static sensor retrieval struct 786 * returns NULL on error 787 */ 788 static struct sdr_get_rs * 789 ipmi_sdr_get_header(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr) 790 { 791 struct ipmi_rq req; 792 struct ipmi_rs *rsp; 793 struct sdr_get_rq sdr_rq; 794 static struct sdr_get_rs sdr_rs; 795 int try = 0; 796 797 memset(&sdr_rq, 0, sizeof (sdr_rq)); 798 sdr_rq.reserve_id = itr->reservation; 799 sdr_rq.id = itr->next; 800 sdr_rq.offset = 0; 801 sdr_rq.length = 5; /* only get the header */ 802 803 memset(&req, 0, sizeof (req)); 804 if (itr->use_built_in == 0) { 805 req.msg.netfn = IPMI_NETFN_STORAGE; 806 req.msg.cmd = GET_SDR; 807 } else { 808 req.msg.netfn = IPMI_NETFN_SE; 809 req.msg.cmd = GET_DEVICE_SDR; 810 } 811 req.msg.data = (uint8_t *) & sdr_rq; 812 req.msg.data_len = sizeof (sdr_rq); 813 814 for (try = 0; try < 5; try++) { 815 sdr_rq.reserve_id = itr->reservation; 816 rsp = intf->sendrecv(intf, &req); 817 if (rsp == NULL) { 818 lprintf(LOG_ERR, "Get SDR %04x command failed", 819 itr->next); 820 continue; 821 } else if (rsp->ccode == 0xc5) { 822 /* lost reservation */ 823 lprintf(LOG_DEBUG, "SDR reservation %04x cancelled. " 824 "Sleeping a bit and retrying...", 825 itr->reservation); 826 827 sleep(rand() & 3); 828 829 if (ipmi_sdr_get_reservation(intf, itr->use_built_in, 830 &(itr->reservation)) < 0) { 831 lprintf(LOG_ERR, 832 "Unable to renew SDR reservation"); 833 return NULL; 834 } 835 } else if (rsp->ccode > 0) { 836 lprintf(LOG_ERR, "Get SDR %04x command failed: %s", 837 itr->next, val2str(rsp->ccode, 838 completion_code_vals)); 839 continue; 840 } else { 841 break; 842 } 843 } 844 845 if (try == 5) 846 return NULL; 847 848 if (!rsp) 849 return NULL; 850 851 lprintf(LOG_DEBUG, "SDR record ID : 0x%04x", itr->next); 852 853 memcpy(&sdr_rs, rsp->data, sizeof (sdr_rs)); 854 855 if (sdr_rs.length == 0) { 856 lprintf(LOG_ERR, "SDR record id 0x%04x: invalid length %d", 857 itr->next, sdr_rs.length); 858 return NULL; 859 } 860 861 /* achu (chu11 at llnl dot gov): - Some boards are stupid and 862 * return a record id from the Get SDR Record command 863 * different than the record id passed in. If we find this 864 * situation, we cheat and put the original record id back in. 865 * Otherwise, a later Get SDR Record command will fail with 866 * completion code CBh = "Requested Sensor, data, or record 867 * not present" 868 */ 869 if (sdr_rs.id != itr->next) { 870 lprintf(LOG_DEBUG, "SDR record id mismatch: 0x%04x", sdr_rs.id); 871 sdr_rs.id = itr->next; 872 } 873 874 lprintf(LOG_DEBUG, "SDR record type : 0x%02x", sdr_rs.type); 875 lprintf(LOG_DEBUG, "SDR record next : 0x%04x", sdr_rs.next); 876 lprintf(LOG_DEBUG, "SDR record bytes: %d", sdr_rs.length); 877 878 return &sdr_rs; 879 } 880 881 /* ipmi_sdr_get_next_header - retreive next SDR header 882 * 883 * @intf: ipmi interface 884 * @itr: sdr iterator 885 * 886 * returns pointer to sensor retrieval struct 887 * returns NULL on error 888 */ 889 struct sdr_get_rs * 890 ipmi_sdr_get_next_header(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr) 891 { 892 struct sdr_get_rs *header; 893 894 if (itr->next == 0xffff) 895 return NULL; 896 897 header = ipmi_sdr_get_header(intf, itr); 898 if (header == NULL) 899 return NULL; 900 901 itr->next = header->next; 902 903 return header; 904 } 905 906 /* 907 * This macro is used to print nominal, normal and threshold settings, 908 * but it is not compatible with PRINT_NORMAL/PRINT_THRESH since it does 909 * not have the sensor.init.thresholds setting qualifier as is done in 910 * PRINT_THRESH. This means CSV output can be different than non CSV 911 * output if sensor.init.thresholds is ever zero 912 */ 913 /* helper macro for printing CSV output for Full SDR Threshold reading */ 914 #define SENSOR_PRINT_CSV(FULLSENS, FLAG, READ) \ 915 if ((FLAG)) { \ 916 if (UNITS_ARE_DISCRETE((&FULLSENS->cmn))) \ 917 printf("0x%02X,", READ); \ 918 else \ 919 printf("%.3f,", sdr_convert_sensor_reading( \ 920 (FULLSENS), READ)); \ 921 } else { \ 922 printf(","); \ 923 } 924 925 /* helper macro for printing analog values for Full SDR Threshold readings */ 926 #define SENSOR_PRINT_NORMAL(FULLSENS, NAME, READ) \ 927 if ((FULLSENS)->analog_flag.READ != 0) { \ 928 printf(" %-21s : ", NAME); \ 929 if (UNITS_ARE_DISCRETE((&FULLSENS->cmn))) \ 930 printf("0x%02X\n", \ 931 (FULLSENS)->READ); \ 932 else \ 933 printf("%.3f\n", sdr_convert_sensor_reading( \ 934 (FULLSENS), (FULLSENS)->READ));\ 935 } 936 937 /* helper macro for printing Full SDR sensor Thresholds */ 938 #define SENSOR_PRINT_THRESH(FULLSENS, NAME, READ, FLAG) \ 939 if ((FULLSENS)->cmn.sensor.init.thresholds && \ 940 (FULLSENS)->cmn.mask.type.threshold.read.FLAG != 0) { \ 941 printf(" %-21s : ", NAME); \ 942 if (UNITS_ARE_DISCRETE((&FULLSENS->cmn))) \ 943 printf("0x%02X\n", \ 944 (FULLSENS)->threshold.READ); \ 945 else \ 946 printf("%.3f\n", sdr_convert_sensor_reading( \ 947 (FULLSENS), (FULLSENS)->threshold.READ)); \ 948 } 949 950 int 951 ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf, 952 uint8_t sensor_num, 953 uint8_t sensor_type, 954 uint8_t event_type, int numeric_fmt, 955 uint8_t target, uint8_t lun, uint8_t channel) 956 { 957 struct ipmi_rs *rsp; 958 int i; 959 const struct valstr assert_cond_1[] = { 960 {0x80, "unc+"}, 961 {0x40, "unc-"}, 962 {0x20, "lnr+"}, 963 {0x10, "lnr-"}, 964 {0x08, "lcr+"}, 965 {0x04, "lcr-"}, 966 {0x02, "lnc+"}, 967 {0x01, "lnc-"}, 968 {0x00, NULL}, 969 }; 970 const struct valstr assert_cond_2[] = { 971 {0x08, "unr+"}, 972 {0x04, "unr-"}, 973 {0x02, "ucr+"}, 974 {0x01, "ucr-"}, 975 {0x00, NULL}, 976 }; 977 978 rsp = ipmi_sdr_get_sensor_event_status(intf, sensor_num, 979 target, lun, channel); 980 981 if (rsp == NULL) { 982 lprintf(LOG_DEBUG, 983 "Error reading event status for sensor #%02x", 984 sensor_num); 985 return -1; 986 } 987 if (rsp->ccode > 0) { 988 lprintf(LOG_DEBUG, 989 "Error reading event status for sensor #%02x: %s", 990 sensor_num, val2str(rsp->ccode, completion_code_vals)); 991 return -1; 992 } 993 /* There is an assumption here that data_len >= 1 */ 994 if (IS_READING_UNAVAILABLE(rsp->data[0])) { 995 printf(" Event Status : Unavailable\n"); 996 return 0; 997 } 998 if (IS_SCANNING_DISABLED(rsp->data[0])) { 999 //printf(" Event Status : Scanning Disabled\n"); 1000 //return 0; 1001 } 1002 if (IS_EVENT_MSG_DISABLED(rsp->data[0])) { 1003 printf(" Event Status : Event Messages Disabled\n"); 1004 //return 0; 1005 } 1006 1007 switch (numeric_fmt) { 1008 case DISCRETE_SENSOR: 1009 if (rsp->data_len == 2) { 1010 ipmi_sdr_print_discrete_state("Assertion Events", 1011 sensor_type, event_type, 1012 rsp->data[1], 0); 1013 } else if (rsp->data_len > 2) { 1014 ipmi_sdr_print_discrete_state("Assertion Events", 1015 sensor_type, event_type, 1016 rsp->data[1], 1017 rsp->data[2]); 1018 } 1019 if (rsp->data_len == 4) { 1020 ipmi_sdr_print_discrete_state("Deassertion Events", 1021 sensor_type, event_type, 1022 rsp->data[3], 0); 1023 } else if (rsp->data_len > 4) { 1024 ipmi_sdr_print_discrete_state("Deassertion Events", 1025 sensor_type, event_type, 1026 rsp->data[3], 1027 rsp->data[4]); 1028 } 1029 break; 1030 1031 case ANALOG_SENSOR: 1032 printf(" Assertion Events : "); 1033 for (i = 0; i < 8; i++) { 1034 if (rsp->data[1] & (1 << i)) 1035 printf("%s ", val2str(1 << i, assert_cond_1)); 1036 } 1037 if (rsp->data_len > 2) { 1038 for (i = 0; i < 4; i++) { 1039 if (rsp->data[2] & (1 << i)) 1040 printf("%s ", 1041 val2str(1 << i, assert_cond_2)); 1042 } 1043 printf("\n"); 1044 if ((rsp->data_len == 4 && rsp->data[3] != 0) || 1045 (rsp->data_len > 4 1046 && (rsp->data[3] != 0 && rsp->data[4] != 0))) { 1047 printf(" Deassertion Events : "); 1048 for (i = 0; i < 8; i++) { 1049 if (rsp->data[3] & (1 << i)) 1050 printf("%s ", 1051 val2str(1 << i, 1052 assert_cond_1)); 1053 } 1054 if (rsp->data_len > 4) { 1055 for (i = 0; i < 4; i++) { 1056 if (rsp->data[4] & (1 << i)) 1057 printf("%s ", 1058 val2str(1 << i, 1059 assert_cond_2)); 1060 } 1061 } 1062 printf("\n"); 1063 } 1064 } else { 1065 printf("\n"); 1066 } 1067 break; 1068 1069 default: 1070 break; 1071 } 1072 1073 return 0; 1074 } 1075 1076 static int 1077 ipmi_sdr_print_sensor_mask(struct sdr_record_mask *mask, 1078 uint8_t sensor_type, 1079 uint8_t event_type, int numeric_fmt) 1080 { 1081 /* iceblink - don't print some event status fields - CVS rev1.53 */ 1082 return 0; 1083 1084 switch (numeric_fmt) { 1085 case DISCRETE_SENSOR: 1086 ipmi_sdr_print_discrete_state("Assert Event Mask", sensor_type, 1087 event_type, 1088 mask->type.discrete. 1089 assert_event & 0xff, 1090 (mask->type.discrete. 1091 assert_event & 0xff00) >> 8); 1092 ipmi_sdr_print_discrete_state("Deassert Event Mask", 1093 sensor_type, event_type, 1094 mask->type.discrete. 1095 deassert_event & 0xff, 1096 (mask->type.discrete. 1097 deassert_event & 0xff00) >> 8); 1098 break; 1099 1100 case ANALOG_SENSOR: 1101 printf(" Assert Event Mask : "); 1102 if (mask->type.threshold.assert_lnr_high) 1103 printf("lnr+ "); 1104 if (mask->type.threshold.assert_lnr_low) 1105 printf("lnr- "); 1106 if (mask->type.threshold.assert_lcr_high) 1107 printf("lcr+ "); 1108 if (mask->type.threshold.assert_lcr_low) 1109 printf("lcr- "); 1110 if (mask->type.threshold.assert_lnc_high) 1111 printf("lnc+ "); 1112 if (mask->type.threshold.assert_lnc_low) 1113 printf("lnc- "); 1114 if (mask->type.threshold.assert_unc_high) 1115 printf("unc+ "); 1116 if (mask->type.threshold.assert_unc_low) 1117 printf("unc- "); 1118 if (mask->type.threshold.assert_ucr_high) 1119 printf("ucr+ "); 1120 if (mask->type.threshold.assert_ucr_low) 1121 printf("ucr- "); 1122 if (mask->type.threshold.assert_unr_high) 1123 printf("unr+ "); 1124 if (mask->type.threshold.assert_unr_low) 1125 printf("unr- "); 1126 printf("\n"); 1127 1128 printf(" Deassert Event Mask : "); 1129 if (mask->type.threshold.deassert_lnr_high) 1130 printf("lnr+ "); 1131 if (mask->type.threshold.deassert_lnr_low) 1132 printf("lnr- "); 1133 if (mask->type.threshold.deassert_lcr_high) 1134 printf("lcr+ "); 1135 if (mask->type.threshold.deassert_lcr_low) 1136 printf("lcr- "); 1137 if (mask->type.threshold.deassert_lnc_high) 1138 printf("lnc+ "); 1139 if (mask->type.threshold.deassert_lnc_low) 1140 printf("lnc- "); 1141 if (mask->type.threshold.deassert_unc_high) 1142 printf("unc+ "); 1143 if (mask->type.threshold.deassert_unc_low) 1144 printf("unc- "); 1145 if (mask->type.threshold.deassert_ucr_high) 1146 printf("ucr+ "); 1147 if (mask->type.threshold.deassert_ucr_low) 1148 printf("ucr- "); 1149 if (mask->type.threshold.deassert_unr_high) 1150 printf("unr+ "); 1151 if (mask->type.threshold.deassert_unr_low) 1152 printf("unr- "); 1153 printf("\n"); 1154 break; 1155 1156 default: 1157 break; 1158 } 1159 1160 return 0; 1161 } 1162 1163 int 1164 ipmi_sdr_print_sensor_event_enable(struct ipmi_intf *intf, 1165 uint8_t sensor_num, 1166 uint8_t sensor_type, 1167 uint8_t event_type, int numeric_fmt, 1168 uint8_t target, uint8_t lun, uint8_t channel) 1169 { 1170 struct ipmi_rs *rsp; 1171 int i; 1172 const struct valstr assert_cond_1[] = { 1173 {0x80, "unc+"}, 1174 {0x40, "unc-"}, 1175 {0x20, "lnr+"}, 1176 {0x10, "lnr-"}, 1177 {0x08, "lcr+"}, 1178 {0x04, "lcr-"}, 1179 {0x02, "lnc+"}, 1180 {0x01, "lnc-"}, 1181 {0x00, NULL}, 1182 }; 1183 const struct valstr assert_cond_2[] = { 1184 {0x08, "unr+"}, 1185 {0x04, "unr-"}, 1186 {0x02, "ucr+"}, 1187 {0x01, "ucr-"}, 1188 {0x00, NULL}, 1189 }; 1190 1191 rsp = ipmi_sdr_get_sensor_event_enable(intf, sensor_num, 1192 target, lun, channel); 1193 1194 if (rsp == NULL) { 1195 lprintf(LOG_DEBUG, 1196 "Error reading event enable for sensor #%02x", 1197 sensor_num); 1198 return -1; 1199 } 1200 if (rsp->ccode > 0) { 1201 lprintf(LOG_DEBUG, 1202 "Error reading event enable for sensor #%02x: %s", 1203 sensor_num, val2str(rsp->ccode, completion_code_vals)); 1204 return -1; 1205 } 1206 1207 if (IS_SCANNING_DISABLED(rsp->data[0])) { 1208 //printf(" Event Enable : Scanning Disabled\n"); 1209 //return 0; 1210 } 1211 if (IS_EVENT_MSG_DISABLED(rsp->data[0])) { 1212 printf(" Event Enable : Event Messages Disabled\n"); 1213 //return 0; 1214 } 1215 1216 switch (numeric_fmt) { 1217 case DISCRETE_SENSOR: 1218 /* discrete */ 1219 if (rsp->data_len == 2) { 1220 ipmi_sdr_print_discrete_state("Assertions Enabled", 1221 sensor_type, event_type, 1222 rsp->data[1], 0); 1223 } else if (rsp->data_len > 2) { 1224 ipmi_sdr_print_discrete_state("Assertions Enabled", 1225 sensor_type, event_type, 1226 rsp->data[1], 1227 rsp->data[2]); 1228 } 1229 if (rsp->data_len == 4) { 1230 ipmi_sdr_print_discrete_state("Deassertions Enabled", 1231 sensor_type, event_type, 1232 rsp->data[3], 0); 1233 } else if (rsp->data_len > 4) { 1234 ipmi_sdr_print_discrete_state("Deassertions Enabled", 1235 sensor_type, event_type, 1236 rsp->data[3], 1237 rsp->data[4]); 1238 } 1239 break; 1240 1241 case ANALOG_SENSOR: 1242 /* analog */ 1243 printf(" Assertions Enabled : "); 1244 for (i = 0; i < 8; i++) { 1245 if (rsp->data[1] & (1 << i)) 1246 printf("%s ", val2str(1 << i, assert_cond_1)); 1247 } 1248 if (rsp->data_len > 2) { 1249 for (i = 0; i < 4; i++) { 1250 if (rsp->data[2] & (1 << i)) 1251 printf("%s ", 1252 val2str(1 << i, assert_cond_2)); 1253 } 1254 printf("\n"); 1255 if ((rsp->data_len == 4 && rsp->data[3] != 0) || 1256 (rsp->data_len > 4 1257 && (rsp->data[3] != 0 || rsp->data[4] != 0))) { 1258 printf(" Deassertions Enabled : "); 1259 for (i = 0; i < 8; i++) { 1260 if (rsp->data[3] & (1 << i)) 1261 printf("%s ", 1262 val2str(1 << i, 1263 assert_cond_1)); 1264 } 1265 if (rsp->data_len > 4) { 1266 for (i = 0; i < 4; i++) { 1267 if (rsp->data[4] & (1 << i)) 1268 printf("%s ", 1269 val2str(1 << i, 1270 assert_cond_2)); 1271 } 1272 } 1273 printf("\n"); 1274 } 1275 } else { 1276 printf("\n"); 1277 } 1278 break; 1279 1280 default: 1281 break; 1282 } 1283 1284 return 0; 1285 } 1286 1287 /* ipmi_sdr_print_sensor_hysteresis - print hysteresis for Discrete & Analog 1288 * 1289 * @sensor: Common Sensor Record SDR pointer 1290 * @full: Full Sensor Record SDR pointer (if applicable) 1291 * @hysteresis_value: Actual hysteresis value 1292 * @hvstr: hysteresis value Identifier String 1293 * 1294 * returns void 1295 */ 1296 void 1297 ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor *sensor, 1298 struct sdr_record_full_sensor *full, 1299 uint8_t hysteresis_value, 1300 const char *hvstr) 1301 { 1302 /* 1303 * compact can have pos/neg hysteresis, but they cannot be analog! 1304 * We use not full in addition to our discrete units check just in 1305 * case a compact sensor is incorrectly identified as analog. 1306 */ 1307 if (!full || UNITS_ARE_DISCRETE(sensor)) { 1308 if ( hysteresis_value == 0x00 || hysteresis_value == 0xff ) { 1309 printf(" %s : Unspecified\n", hvstr); 1310 } else { 1311 printf(" %s : 0x%02X\n", hvstr, hysteresis_value); 1312 } 1313 return; 1314 } 1315 /* A Full analog sensor */ 1316 double creading = sdr_convert_sensor_hysterisis(full, hysteresis_value); 1317 if ( hysteresis_value == 0x00 || hysteresis_value == 0xff || 1318 creading == 0.0 ) { 1319 printf(" %s : Unspecified\n", hvstr); 1320 } else { 1321 printf(" %s : %.3f\n", hvstr, creading); 1322 } 1323 } 1324 1325 /* print_sensor_min_max - print Discrete & Analog Minimum/Maximum Sensor Range 1326 * 1327 * @full: Full Sensor Record SDR pointer 1328 * 1329 * returns void 1330 */ 1331 static void 1332 print_sensor_min_max(struct sdr_record_full_sensor *full) 1333 { 1334 if (!full) { /* No min/max for compact SDR record */ 1335 return; 1336 } 1337 1338 double creading = 0.0; 1339 uint8_t is_analog = !UNITS_ARE_DISCRETE(&full->cmn); 1340 if (is_analog) 1341 creading = sdr_convert_sensor_reading(full, full->sensor_min); 1342 if ((full->cmn.unit.analog == 0 && full->sensor_min == 0x00) || 1343 (full->cmn.unit.analog == 1 && full->sensor_min == 0xff) || 1344 (full->cmn.unit.analog == 2 && full->sensor_min == 0x80) || 1345 (is_analog && (creading == 0.0))) 1346 printf(" Minimum sensor range : Unspecified\n"); 1347 else { 1348 if (is_analog) 1349 printf(" Minimum sensor range : %.3f\n", creading); 1350 else 1351 printf(" Minimum sensor range : 0x%02X\n", full->sensor_min); 1352 1353 } 1354 if (is_analog) 1355 creading = sdr_convert_sensor_reading(full, full->sensor_max); 1356 if ((full->cmn.unit.analog == 0 && full->sensor_max == 0xff) || 1357 (full->cmn.unit.analog == 1 && full->sensor_max == 0x00) || 1358 (full->cmn.unit.analog == 2 && full->sensor_max == 0x7f) || 1359 (is_analog && (creading == 0.0))) 1360 printf(" Maximum sensor range : Unspecified\n"); 1361 else { 1362 if (is_analog) 1363 printf(" Maximum sensor range : %.3f\n", creading); 1364 else 1365 printf(" Maximum sensor range : 0x%02X\n", full->sensor_max); 1366 } 1367 } 1368 1369 /* print_csv_discrete - print csv formatted discrete sensor 1370 * 1371 * @sensor: common sensor structure 1372 * @sr: sensor reading 1373 * 1374 * returns void 1375 */ 1376 static void 1377 print_csv_discrete(struct sdr_record_common_sensor *sensor, 1378 const struct sensor_reading *sr) 1379 { 1380 if (!sr->s_reading_valid || sr->s_reading_unavailable) { 1381 printf("%02Xh,ns,%d.%d,No Reading", 1382 sensor->keys.sensor_num, 1383 sensor->entity.id, 1384 sensor->entity.instance); 1385 return; 1386 } 1387 1388 if (sr->s_has_analog_value) { /* Sensor has an analog value */ 1389 printf("%s,%s,", sr->s_a_str, sr->s_a_units); 1390 } else { /* Sensor has a discrete value */ 1391 printf("%02Xh,", sensor->keys.sensor_num); 1392 } 1393 printf("ok,%d.%d,", 1394 sensor->entity.id, 1395 sensor->entity.instance); 1396 ipmi_sdr_print_discrete_state_mini(NULL, ", ", 1397 sensor->sensor.type, 1398 sensor->event_type, 1399 sr->s_data2, 1400 sr->s_data3); 1401 } 1402 1403 /* ipmi_sdr_read_sensor_value - read sensor value 1404 * 1405 * @intf Interface pointer 1406 * @sensor Common sensor component pointer 1407 * @sdr_record_type Type of sdr sensor record 1408 * @precision decimal precision for analog format conversion 1409 * 1410 * returns a pointer to sensor value reading data structure 1411 */ 1412 struct sensor_reading * 1413 ipmi_sdr_read_sensor_value(struct ipmi_intf *intf, 1414 struct sdr_record_common_sensor *sensor, 1415 uint8_t sdr_record_type, int precision) 1416 { 1417 static struct sensor_reading sr; 1418 1419 if (sensor == NULL) 1420 return NULL; 1421 1422 /* Initialize to reading valid value of zero */ 1423 memset(&sr, 0, sizeof(sr)); 1424 1425 switch (sdr_record_type) { 1426 int idlen; 1427 case (SDR_RECORD_TYPE_FULL_SENSOR): 1428 sr.full = (struct sdr_record_full_sensor *)sensor; 1429 idlen = sr.full->id_code & 0x1f; 1430 idlen = idlen < sizeof(sr.s_id) ? 1431 idlen : sizeof(sr.s_id) - 1; 1432 memcpy(sr.s_id, sr.full->id_string, idlen); 1433 break; 1434 case SDR_RECORD_TYPE_COMPACT_SENSOR: 1435 sr.compact = (struct sdr_record_compact_sensor *)sensor; 1436 idlen = sr.compact->id_code & 0x1f; 1437 idlen = idlen < sizeof(sr.s_id) ? 1438 idlen : sizeof(sr.s_id) - 1; 1439 memcpy(sr.s_id, sr.compact->id_string, idlen); 1440 break; 1441 default: 1442 return NULL; 1443 } 1444 1445 /* 1446 * Get current reading via IPMI interface 1447 */ 1448 struct ipmi_rs *rsp; 1449 rsp = ipmi_sdr_get_sensor_reading_ipmb(intf, 1450 sensor->keys.sensor_num, 1451 sensor->keys.owner_id, 1452 sensor->keys.lun, 1453 sensor->keys.channel); 1454 sr.s_a_val = 0.0; /* init analog value to a floating point 0 */ 1455 sr.s_a_str[0] = '\0'; /* no converted analog value string */ 1456 sr.s_a_units = ""; /* no converted analog units units */ 1457 1458 1459 if (rsp == NULL) { 1460 lprintf(LOG_DEBUG, "Error reading sensor %s (#%02x)", 1461 sr.s_id, sensor->keys.sensor_num); 1462 return &sr; 1463 } 1464 1465 if (rsp->ccode) { 1466 if ( !((sr.full && rsp->ccode == 0xcb) || 1467 (sr.compact && rsp->ccode == 0xcd)) ) { 1468 lprintf(LOG_DEBUG, 1469 "Error reading sensor %s (#%02x): %s", sr.s_id, 1470 sensor->keys.sensor_num, 1471 val2str(rsp->ccode, completion_code_vals)); 1472 } 1473 return &sr; 1474 } 1475 1476 if (rsp->data_len < 2) { 1477 /* 1478 * We must be returned both a value (data[0]), and the validity 1479 * of the value (data[1]), in order to correctly interpret 1480 * the reading. If we don't have both of these we can't have 1481 * a valid sensor reading. 1482 */ 1483 lprintf(LOG_DEBUG, "Error reading sensor %s invalid len %d", 1484 sr.s_id, rsp->data_len); 1485 return &sr; 1486 } 1487 1488 1489 if (IS_READING_UNAVAILABLE(rsp->data[1])) 1490 sr.s_reading_unavailable = 1; 1491 1492 if (IS_SCANNING_DISABLED(rsp->data[1])) { 1493 sr.s_scanning_disabled = 1; 1494 lprintf(LOG_DEBUG, "Sensor %s (#%02x) scanning disabled", 1495 sr.s_id, sensor->keys.sensor_num); 1496 return &sr; 1497 } 1498 if ( !sr.s_reading_unavailable ) { 1499 sr.s_reading_valid = 1; 1500 sr.s_reading = rsp->data[0]; 1501 } 1502 if (rsp->data_len > 2) 1503 sr.s_data2 = rsp->data[2]; 1504 if (rsp->data_len > 3) 1505 sr.s_data3 = rsp->data[3]; 1506 if (sdr_sensor_has_analog_reading(intf, &sr)) { 1507 sr.s_has_analog_value = 1; 1508 if (sr.s_reading_valid) { 1509 sr.s_a_val = sdr_convert_sensor_reading(sr.full, sr.s_reading); 1510 } 1511 /* determine units string with possible modifiers */ 1512 sr.s_a_units = ipmi_sdr_get_unit_string(sr.full->cmn.unit.pct, 1513 sr.full->cmn.unit.modifier, 1514 sr.full->cmn.unit.type.base, 1515 sr.full->cmn.unit.type.modifier); 1516 snprintf(sr.s_a_str, sizeof(sr.s_a_str), "%.*f", 1517 (sr.s_a_val == (int) sr.s_a_val) ? 0 : 1518 precision, sr.s_a_val); 1519 } 1520 return &sr; 1521 } 1522 1523 /* ipmi_sdr_print_sensor_fc - print full & compact SDR records 1524 * 1525 * @intf: ipmi interface 1526 * @sensor: common sensor structure 1527 * @sdr_record_type: type of sdr record, either full or compact 1528 * 1529 * returns 0 on success 1530 * returns -1 on error 1531 */ 1532 int 1533 ipmi_sdr_print_sensor_fc(struct ipmi_intf *intf, 1534 struct sdr_record_common_sensor *sensor, 1535 uint8_t sdr_record_type) 1536 { 1537 char sval[16]; 1538 int i = 0; 1539 uint8_t target, lun, channel; 1540 struct sensor_reading *sr; 1541 1542 1543 sr = ipmi_sdr_read_sensor_value(intf, sensor, sdr_record_type, 2); 1544 1545 if (sr == NULL) 1546 return -1; 1547 1548 target = sensor->keys.owner_id; 1549 lun = sensor->keys.lun; 1550 channel = sensor->keys.channel; 1551 1552 /* 1553 * CSV OUTPUT 1554 */ 1555 1556 if (csv_output) { 1557 /* 1558 * print sensor name, reading, unit, state 1559 */ 1560 printf("%s,", sr->s_id); 1561 if (!IS_THRESHOLD_SENSOR(sensor)) { 1562 /* Discrete/Non-Threshold */ 1563 print_csv_discrete(sensor, sr); 1564 printf("\n"); 1565 } 1566 else { 1567 /* Threshold Analog & Discrete*/ 1568 if (sr->s_reading_valid) { 1569 if (sr->s_has_analog_value) { 1570 /* Analog/Threshold */ 1571 printf("%.*f,", (sr->s_a_val == 1572 (int) sr->s_a_val) ? 0 : 3, 1573 sr->s_a_val); 1574 printf("%s,%s", sr->s_a_units, 1575 ipmi_sdr_get_thresh_status(sr, "ns")); 1576 } else { /* Discrete/Threshold */ 1577 print_csv_discrete(sensor, sr); 1578 } 1579 } else { 1580 printf(",,ns"); 1581 } 1582 1583 if (verbose) { 1584 printf(",%d.%d,%s,%s,", 1585 sensor->entity.id, sensor->entity.instance, 1586 val2str(sensor->entity.id, entity_id_vals), 1587 ipmi_sdr_get_sensor_type_desc(sensor->sensor. 1588 type)); 1589 1590 if (sr->full) { 1591 SENSOR_PRINT_CSV(sr->full, sr->full->analog_flag.nominal_read, 1592 sr->full->nominal_read); 1593 SENSOR_PRINT_CSV(sr->full, sr->full->analog_flag.normal_min, 1594 sr->full->normal_min); 1595 SENSOR_PRINT_CSV(sr->full, sr->full->analog_flag.normal_max, 1596 sr->full->normal_max); 1597 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.unr, 1598 sr->full->threshold.upper.non_recover); 1599 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.ucr, 1600 sr->full->threshold.upper.critical); 1601 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.unc, 1602 sr->full->threshold.upper.non_critical); 1603 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.lnr, 1604 sr->full->threshold.lower.non_recover); 1605 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.lcr, 1606 sr->full->threshold.lower.critical); 1607 SENSOR_PRINT_CSV(sr->full, sensor->mask.type.threshold.read.lnc, 1608 sr->full->threshold.lower.non_critical); 1609 1610 if (UNITS_ARE_DISCRETE(sensor)) { 1611 printf("0x%02X,0x%02X", sr->full->sensor_min, sr->full->sensor_max); 1612 } 1613 else { 1614 printf("%.3f,%.3f", 1615 sdr_convert_sensor_reading(sr->full, 1616 sr->full->sensor_min), 1617 sdr_convert_sensor_reading(sr->full, 1618 sr->full->sensor_max)); 1619 } 1620 } else { 1621 printf(",,,,,,,,,,"); 1622 } 1623 } 1624 printf("\n"); 1625 } 1626 1627 return 0; /* done */ 1628 } 1629 1630 /* 1631 * NORMAL OUTPUT 1632 */ 1633 1634 if (verbose == 0 && sdr_extended == 0) { 1635 /* 1636 * print sensor name, reading, state 1637 */ 1638 printf("%-16s | ", sr->s_id); 1639 1640 memset(sval, 0, sizeof (sval)); 1641 1642 if (sr->s_reading_valid) { 1643 if( sr->s_has_analog_value ) { 1644 snprintf(sval, sizeof (sval), "%s %s", 1645 sr->s_a_str, 1646 sr->s_a_units); 1647 } else /* Discrete */ 1648 snprintf(sval, sizeof(sval), 1649 "0x%02x", sr->s_reading); 1650 } 1651 else if (sr->s_scanning_disabled) 1652 snprintf(sval, sizeof (sval), sr->full ? "disabled" : "Not Readable"); 1653 else 1654 snprintf(sval, sizeof (sval), sr->full ? "no reading" : "Not Readable"); 1655 1656 printf("%s", sval); 1657 1658 for (i = strlen(sval); i <= sizeof (sval); i++) 1659 printf(" "); 1660 printf(" | "); 1661 1662 if (IS_THRESHOLD_SENSOR(sensor)) { 1663 printf("%s", ipmi_sdr_get_thresh_status(sr, "ns")); 1664 } 1665 else { 1666 printf("%s", sr->s_reading_valid ? "ok" : "ns"); 1667 } 1668 1669 printf("\n"); 1670 1671 return 0; /* done */ 1672 } else if (verbose == 0 && sdr_extended == 1) { 1673 /* 1674 * print sensor name, number, state, entity, reading 1675 */ 1676 printf("%-16s | %02Xh | ", 1677 sr->s_id, sensor->keys.sensor_num); 1678 1679 if (IS_THRESHOLD_SENSOR(sensor)) { 1680 /* Threshold Analog & Discrete */ 1681 printf("%-3s | %2d.%1d | ", 1682 ipmi_sdr_get_thresh_status(sr, "ns"), 1683 sensor->entity.id, sensor->entity.instance); 1684 } 1685 else { 1686 /* Non Threshold Analog & Discrete */ 1687 printf("%-3s | %2d.%1d | ", 1688 (sr->s_reading_valid ? "ok" : "ns"), 1689 sensor->entity.id, sensor->entity.instance); 1690 } 1691 1692 memset(sval, 0, sizeof (sval)); 1693 1694 if (sr->s_reading_valid) { 1695 if (IS_THRESHOLD_SENSOR(sensor) && 1696 sr->s_has_analog_value ) { 1697 /* Threshold Analog */ 1698 snprintf(sval, sizeof (sval), "%s %s", 1699 sr->s_a_str, 1700 sr->s_a_units); 1701 } else { 1702 /* Analog & Discrete & Threshold/Discrete */ 1703 char *header = NULL; 1704 if (sr->s_has_analog_value) { /* Sensor has an analog value */ 1705 printf("%s %s", sr->s_a_str, sr->s_a_units); 1706 header = ", "; 1707 } 1708 ipmi_sdr_print_discrete_state_mini(header, ", ", 1709 sensor->sensor.type, 1710 sensor->event_type, 1711 sr->s_data2, 1712 sr->s_data3); 1713 } 1714 } 1715 else if (sr->s_scanning_disabled) 1716 snprintf(sval, sizeof (sval), "Disabled"); 1717 else 1718 snprintf(sval, sizeof (sval), "No Reading"); 1719 1720 printf("%s\n", sval); 1721 return 0; /* done */ 1722 } 1723 /* 1724 * VERBOSE OUTPUT 1725 */ 1726 1727 printf("Sensor ID : %s (0x%x)\n", 1728 sr->s_id, sensor->keys.sensor_num); 1729 printf(" Entity ID : %d.%d (%s)\n", 1730 sensor->entity.id, sensor->entity.instance, 1731 val2str(sensor->entity.id, entity_id_vals)); 1732 1733 if (!IS_THRESHOLD_SENSOR(sensor)) { 1734 /* Discrete */ 1735 printf(" Sensor Type (Discrete): %s (0x%02x)\n", 1736 ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), 1737 sensor->sensor.type); 1738 lprintf(LOG_DEBUG, " Event Type Code : 0x%02x", 1739 sensor->event_type); 1740 1741 printf(" Sensor Reading : "); 1742 if (sr->s_reading_valid) { 1743 if (sr->s_has_analog_value) { /* Sensor has an analog value */ 1744 printf("%s %s\n", sr->s_a_str, sr->s_a_units); 1745 } else { 1746 printf("%xh\n", sr->s_reading); 1747 } 1748 } 1749 else if (sr->s_scanning_disabled) 1750 printf("Disabled\n"); 1751 else { 1752 /* Used to be 'Not Reading' */ 1753 printf("No Reading\n"); 1754 } 1755 1756 printf(" Event Message Control : "); 1757 switch (sensor->sensor.capabilities.event_msg) { 1758 case 0: 1759 printf("Per-threshold\n"); 1760 break; 1761 case 1: 1762 printf("Entire Sensor Only\n"); 1763 break; 1764 case 2: 1765 printf("Global Disable Only\n"); 1766 break; 1767 case 3: 1768 printf("No Events From Sensor\n"); 1769 break; 1770 } 1771 1772 ipmi_sdr_print_discrete_state("States Asserted", 1773 sensor->sensor.type, 1774 sensor->event_type, 1775 sr->s_data2, 1776 sr->s_data3); 1777 ipmi_sdr_print_sensor_mask(&sensor->mask, sensor->sensor.type, 1778 sensor->event_type, DISCRETE_SENSOR); 1779 ipmi_sdr_print_sensor_event_status(intf, 1780 sensor->keys.sensor_num, 1781 sensor->sensor.type, 1782 sensor->event_type, 1783 DISCRETE_SENSOR, 1784 target, 1785 lun, channel); 1786 ipmi_sdr_print_sensor_event_enable(intf, 1787 sensor->keys.sensor_num, 1788 sensor->sensor.type, 1789 sensor->event_type, 1790 DISCRETE_SENSOR, 1791 target, 1792 lun, channel); 1793 printf(" OEM : %X\n", 1794 sr->full ? sr->full->oem : sr->compact->oem); 1795 printf("\n"); 1796 1797 return 0; /* done */ 1798 } 1799 printf(" Sensor Type (Threshold) : %s (0x%02x)\n", 1800 ipmi_sdr_get_sensor_type_desc(sensor->sensor.type), 1801 sensor->sensor.type); 1802 1803 printf(" Sensor Reading : "); 1804 if (sr->s_reading_valid) { 1805 if (sr->full) { 1806 uint16_t raw_tol = __TO_TOL(sr->full->mtol); 1807 if (UNITS_ARE_DISCRETE(sensor)) { 1808 printf("0x%02X (+/- 0x%02X) %s\n", 1809 sr->s_reading, raw_tol, sr->s_a_units); 1810 } 1811 else { 1812 double tol = sdr_convert_sensor_tolerance(sr->full, raw_tol); 1813 printf("%.*f (+/- %.*f) %s\n", 1814 (sr->s_a_val == (int) sr->s_a_val) ? 0 : 3, 1815 sr->s_a_val, (tol == (int) tol) ? 0 : 1816 3, tol, sr->s_a_units); 1817 } 1818 } else { 1819 printf("0x%02X %s\n", sr->s_reading, sr->s_a_units); 1820 } 1821 } else if (sr->s_scanning_disabled) 1822 printf("Disabled\n"); 1823 else 1824 printf("No Reading\n"); 1825 1826 printf(" Status : %s\n", 1827 ipmi_sdr_get_thresh_status(sr, "Not Available")); 1828 1829 if(sr->full) { 1830 SENSOR_PRINT_NORMAL(sr->full, "Nominal Reading", nominal_read); 1831 SENSOR_PRINT_NORMAL(sr->full, "Normal Minimum", normal_min); 1832 SENSOR_PRINT_NORMAL(sr->full, "Normal Maximum", normal_max); 1833 1834 SENSOR_PRINT_THRESH(sr->full, "Upper non-recoverable", upper.non_recover, unr); 1835 SENSOR_PRINT_THRESH(sr->full, "Upper critical", upper.critical, ucr); 1836 SENSOR_PRINT_THRESH(sr->full, "Upper non-critical", upper.non_critical, unc); 1837 SENSOR_PRINT_THRESH(sr->full, "Lower non-recoverable", lower.non_recover, lnr); 1838 SENSOR_PRINT_THRESH(sr->full, "Lower critical", lower.critical, lcr); 1839 SENSOR_PRINT_THRESH(sr->full, "Lower non-critical", lower.non_critical, lnc); 1840 } 1841 ipmi_sdr_print_sensor_hysteresis(sensor, sr->full, 1842 sr->full ? sr->full->threshold.hysteresis.positive : 1843 sr->compact->threshold.hysteresis.positive, "Positive Hysteresis"); 1844 1845 ipmi_sdr_print_sensor_hysteresis(sensor, sr->full, 1846 sr->full ? sr->full->threshold.hysteresis.negative : 1847 sr->compact->threshold.hysteresis.negative, "Negative Hysteresis"); 1848 1849 print_sensor_min_max(sr->full); 1850 1851 printf(" Event Message Control : "); 1852 switch (sensor->sensor.capabilities.event_msg) { 1853 case 0: 1854 printf("Per-threshold\n"); 1855 break; 1856 case 1: 1857 printf("Entire Sensor Only\n"); 1858 break; 1859 case 2: 1860 printf("Global Disable Only\n"); 1861 break; 1862 case 3: 1863 printf("No Events From Sensor\n"); 1864 break; 1865 } 1866 1867 printf(" Readable Thresholds : "); 1868 switch (sensor->sensor.capabilities.threshold) { 1869 case 0: 1870 printf("No Thresholds\n"); 1871 break; 1872 case 1: /* readable according to mask */ 1873 case 2: /* readable and settable according to mask */ 1874 if (sensor->mask.type.threshold.read.lnr) 1875 printf("lnr "); 1876 if (sensor->mask.type.threshold.read.lcr) 1877 printf("lcr "); 1878 if (sensor->mask.type.threshold.read.lnc) 1879 printf("lnc "); 1880 if (sensor->mask.type.threshold.read.unc) 1881 printf("unc "); 1882 if (sensor->mask.type.threshold.read.ucr) 1883 printf("ucr "); 1884 if (sensor->mask.type.threshold.read.unr) 1885 printf("unr "); 1886 printf("\n"); 1887 break; 1888 case 3: 1889 printf("Thresholds Fixed\n"); 1890 break; 1891 } 1892 1893 printf(" Settable Thresholds : "); 1894 switch (sensor->sensor.capabilities.threshold) { 1895 case 0: 1896 printf("No Thresholds\n"); 1897 break; 1898 case 1: /* readable according to mask */ 1899 case 2: /* readable and settable according to mask */ 1900 if (sensor->mask.type.threshold.set.lnr) 1901 printf("lnr "); 1902 if (sensor->mask.type.threshold.set.lcr) 1903 printf("lcr "); 1904 if (sensor->mask.type.threshold.set.lnc) 1905 printf("lnc "); 1906 if (sensor->mask.type.threshold.set.unc) 1907 printf("unc "); 1908 if (sensor->mask.type.threshold.set.ucr) 1909 printf("ucr "); 1910 if (sensor->mask.type.threshold.set.unr) 1911 printf("unr "); 1912 printf("\n"); 1913 break; 1914 case 3: 1915 printf("Thresholds Fixed\n"); 1916 break; 1917 } 1918 1919 if (sensor->mask.type.threshold.status_lnr || 1920 sensor->mask.type.threshold.status_lcr || 1921 sensor->mask.type.threshold.status_lnc || 1922 sensor->mask.type.threshold.status_unc || 1923 sensor->mask.type.threshold.status_ucr || 1924 sensor->mask.type.threshold.status_unr) { 1925 printf(" Threshold Read Mask : "); 1926 if (sensor->mask.type.threshold.status_lnr) 1927 printf("lnr "); 1928 if (sensor->mask.type.threshold.status_lcr) 1929 printf("lcr "); 1930 if (sensor->mask.type.threshold.status_lnc) 1931 printf("lnc "); 1932 if (sensor->mask.type.threshold.status_unc) 1933 printf("unc "); 1934 if (sensor->mask.type.threshold.status_ucr) 1935 printf("ucr "); 1936 if (sensor->mask.type.threshold.status_unr) 1937 printf("unr "); 1938 printf("\n"); 1939 } 1940 1941 ipmi_sdr_print_sensor_mask(&sensor->mask, 1942 sensor->sensor.type, 1943 sensor->event_type, ANALOG_SENSOR); 1944 ipmi_sdr_print_sensor_event_status(intf, 1945 sensor->keys.sensor_num, 1946 sensor->sensor.type, 1947 sensor->event_type, ANALOG_SENSOR, 1948 target, 1949 lun, channel); 1950 1951 ipmi_sdr_print_sensor_event_enable(intf, 1952 sensor->keys.sensor_num, 1953 sensor->sensor.type, 1954 sensor->event_type, ANALOG_SENSOR, 1955 target, 1956 lun, channel); 1957 1958 printf("\n"); 1959 return 0; 1960 } 1961 1962 static inline int 1963 get_offset(uint8_t x) 1964 { 1965 int i; 1966 for (i = 0; i < 8; i++) 1967 if (x >> i == 1) 1968 return i; 1969 return 0; 1970 } 1971 1972 /* ipmi_sdr_print_discrete_state_mini - print list of asserted states 1973 * for a discrete sensor 1974 * 1975 * @header : header string if necessary 1976 * @separator : field separator string 1977 * @sensor_type : sensor type code 1978 * @event_type : event type code 1979 * @state : mask of asserted states 1980 * 1981 * no meaningful return value 1982 */ 1983 void 1984 ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator, 1985 uint8_t sensor_type, uint8_t event_type, 1986 uint8_t state1, uint8_t state2) 1987 { 1988 uint8_t typ; 1989 struct ipmi_event_sensor_types *evt; 1990 int pre = 0, c = 0; 1991 1992 if (state1 == 0 && (state2 & 0x7f) == 0) 1993 return; 1994 1995 if (event_type == 0x6f) { 1996 evt = sensor_specific_types; 1997 typ = sensor_type; 1998 } else { 1999 evt = generic_event_types; 2000 typ = event_type; 2001 } 2002 2003 if (header) 2004 printf("%s", header); 2005 2006 for (; evt->type != NULL; evt++) { 2007 if ((evt->code != typ) || 2008 (evt->data != 0xFF)) 2009 continue; 2010 2011 if (evt->offset > 7) { 2012 if ((1 << (evt->offset - 8)) & (state2 & 0x7f)) { 2013 if (pre++ != 0) 2014 printf("%s", separator); 2015 if (evt->desc) 2016 printf("%s", evt->desc); 2017 } 2018 } else { 2019 if ((1 << evt->offset) & state1) { 2020 if (pre++ != 0) 2021 printf("%s", separator); 2022 if (evt->desc) 2023 printf("%s", evt->desc); 2024 } 2025 } 2026 c++; 2027 } 2028 } 2029 2030 /* ipmi_sdr_print_discrete_state - print list of asserted states 2031 * for a discrete sensor 2032 * 2033 * @desc : description for this line 2034 * @sensor_type : sensor type code 2035 * @event_type : event type code 2036 * @state : mask of asserted states 2037 * 2038 * no meaningful return value 2039 */ 2040 void 2041 ipmi_sdr_print_discrete_state(const char *desc, 2042 uint8_t sensor_type, uint8_t event_type, 2043 uint8_t state1, uint8_t state2) 2044 { 2045 uint8_t typ; 2046 struct ipmi_event_sensor_types *evt; 2047 int pre = 0, c = 0; 2048 2049 if (state1 == 0 && (state2 & 0x7f) == 0) 2050 return; 2051 2052 if (event_type == 0x6f) { 2053 evt = sensor_specific_types; 2054 typ = sensor_type; 2055 } else { 2056 evt = generic_event_types; 2057 typ = event_type; 2058 } 2059 2060 for (; evt->type != NULL; evt++) { 2061 if ((evt->code != typ) || 2062 (evt->data != 0xFF)) 2063 continue; 2064 2065 if (pre == 0) { 2066 printf(" %-21s : %s\n", desc, evt->type); 2067 pre = 1; 2068 } 2069 2070 if (evt->offset > 7) { 2071 if ((1 << (evt->offset - 8)) & (state2 & 0x7f)) { 2072 if (evt->desc) { 2073 printf(" " 2074 "[%s]\n", 2075 evt->desc); 2076 } else { 2077 printf(" " 2078 "[no description]\n"); 2079 } 2080 } 2081 } else { 2082 if ((1 << evt->offset) & state1) { 2083 if (evt->desc) { 2084 printf(" " 2085 "[%s]\n", 2086 evt->desc); 2087 } else { 2088 printf(" " 2089 "[no description]\n"); 2090 } 2091 } 2092 } 2093 c++; 2094 } 2095 } 2096 2097 2098 /* ipmi_sdr_print_sensor_eventonly - print SDR event only record 2099 * 2100 * @intf: ipmi interface 2101 * @sensor: event only sdr record 2102 * 2103 * returns 0 on success 2104 * returns -1 on error 2105 */ 2106 int 2107 ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf, 2108 struct sdr_record_eventonly_sensor *sensor) 2109 { 2110 char desc[17]; 2111 2112 if (sensor == NULL) 2113 return -1; 2114 2115 memset(desc, 0, sizeof (desc)); 2116 snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string); 2117 2118 if (verbose) { 2119 printf("Sensor ID : %s (0x%x)\n", 2120 sensor->id_code ? desc : "", sensor->keys.sensor_num); 2121 printf("Entity ID : %d.%d (%s)\n", 2122 sensor->entity.id, sensor->entity.instance, 2123 val2str(sensor->entity.id, entity_id_vals)); 2124 printf("Sensor Type : %s (0x%02x)\n", 2125 ipmi_sdr_get_sensor_type_desc(sensor->sensor_type), 2126 sensor->sensor_type); 2127 lprintf(LOG_DEBUG, "Event Type Code : 0x%02x", 2128 sensor->event_type); 2129 printf("\n"); 2130 } else { 2131 if (csv_output) 2132 printf("%s,%02Xh,ns,%d.%d,Event-Only\n", 2133 sensor->id_code ? desc : "", 2134 sensor->keys.sensor_num, 2135 sensor->entity.id, sensor->entity.instance); 2136 else if (sdr_extended) 2137 printf("%-16s | %02Xh | ns | %2d.%1d | Event-Only\n", 2138 sensor->id_code ? desc : "", 2139 sensor->keys.sensor_num, 2140 sensor->entity.id, sensor->entity.instance); 2141 else 2142 printf("%-16s | Event-Only | ns\n", 2143 sensor->id_code ? desc : ""); 2144 } 2145 2146 return 0; 2147 } 2148 2149 /* ipmi_sdr_print_sensor_mc_locator - print SDR MC locator record 2150 * 2151 * @intf: ipmi interface 2152 * @mc: mc locator sdr record 2153 * 2154 * returns 0 on success 2155 * returns -1 on error 2156 */ 2157 int 2158 ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf, 2159 struct sdr_record_mc_locator *mc) 2160 { 2161 char desc[17]; 2162 2163 if (mc == NULL) 2164 return -1; 2165 2166 memset(desc, 0, sizeof (desc)); 2167 snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string); 2168 2169 if (verbose == 0) { 2170 if (csv_output) 2171 printf("%s,00h,ok,%d.%d\n", 2172 mc->id_code ? desc : "", 2173 mc->entity.id, mc->entity.instance); 2174 else if (sdr_extended) { 2175 printf("%-16s | 00h | ok | %2d.%1d | ", 2176 mc->id_code ? desc : "", 2177 mc->entity.id, mc->entity.instance); 2178 2179 printf("%s MC @ %02Xh\n", 2180 (mc-> 2181 pwr_state_notif & 0x1) ? "Static" : "Dynamic", 2182 mc->dev_slave_addr); 2183 } else { 2184 printf("%-16s | %s MC @ %02Xh %s | ok\n", 2185 mc->id_code ? desc : "", 2186 (mc-> 2187 pwr_state_notif & 0x1) ? "Static" : "Dynamic", 2188 mc->dev_slave_addr, 2189 (mc->pwr_state_notif & 0x1) ? " " : ""); 2190 } 2191 2192 return 0; /* done */ 2193 } 2194 2195 printf("Device ID : %s\n", mc->id_string); 2196 printf("Entity ID : %d.%d (%s)\n", 2197 mc->entity.id, mc->entity.instance, 2198 val2str(mc->entity.id, entity_id_vals)); 2199 2200 printf("Device Slave Address : %02Xh\n", mc->dev_slave_addr); 2201 printf("Channel Number : %01Xh\n", mc->channel_num); 2202 2203 printf("ACPI System P/S Notif : %sRequired\n", 2204 (mc->pwr_state_notif & 0x4) ? "" : "Not "); 2205 printf("ACPI Device P/S Notif : %sRequired\n", 2206 (mc->pwr_state_notif & 0x2) ? "" : "Not "); 2207 printf("Controller Presence : %s\n", 2208 (mc->pwr_state_notif & 0x1) ? "Static" : "Dynamic"); 2209 printf("Logs Init Agent Errors : %s\n", 2210 (mc->global_init & 0x8) ? "Yes" : "No"); 2211 2212 printf("Event Message Gen : "); 2213 if (!(mc->global_init & 0x3)) 2214 printf("Enable\n"); 2215 else if ((mc->global_init & 0x3) == 0x1) 2216 printf("Disable\n"); 2217 else if ((mc->global_init & 0x3) == 0x2) 2218 printf("Do Not Init Controller\n"); 2219 else 2220 printf("Reserved\n"); 2221 2222 printf("Device Capabilities\n"); 2223 printf(" Chassis Device : %s\n", 2224 (mc->dev_support & 0x80) ? "Yes" : "No"); 2225 printf(" Bridge : %s\n", 2226 (mc->dev_support & 0x40) ? "Yes" : "No"); 2227 printf(" IPMB Event Generator : %s\n", 2228 (mc->dev_support & 0x20) ? "Yes" : "No"); 2229 printf(" IPMB Event Receiver : %s\n", 2230 (mc->dev_support & 0x10) ? "Yes" : "No"); 2231 printf(" FRU Inventory Device : %s\n", 2232 (mc->dev_support & 0x08) ? "Yes" : "No"); 2233 printf(" SEL Device : %s\n", 2234 (mc->dev_support & 0x04) ? "Yes" : "No"); 2235 printf(" SDR Repository : %s\n", 2236 (mc->dev_support & 0x02) ? "Yes" : "No"); 2237 printf(" Sensor Device : %s\n", 2238 (mc->dev_support & 0x01) ? "Yes" : "No"); 2239 2240 printf("\n"); 2241 2242 return 0; 2243 } 2244 2245 /* ipmi_sdr_print_sensor_generic_locator - print generic device locator record 2246 * 2247 * @intf: ipmi interface 2248 * @gen: generic device locator sdr record 2249 * 2250 * returns 0 on success 2251 * returns -1 on error 2252 */ 2253 int 2254 ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf, 2255 struct sdr_record_generic_locator *dev) 2256 { 2257 char desc[17]; 2258 2259 memset(desc, 0, sizeof (desc)); 2260 snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string); 2261 2262 if (!verbose) { 2263 if (csv_output) 2264 printf("%s,00h,ns,%d.%d\n", 2265 dev->id_code ? desc : "", 2266 dev->entity.id, dev->entity.instance); 2267 else if (sdr_extended) 2268 printf 2269 ("%-16s | 00h | ns | %2d.%1d | Generic Device @%02Xh:%02Xh.%1d\n", 2270 dev->id_code ? desc : "", dev->entity.id, 2271 dev->entity.instance, dev->dev_access_addr, 2272 dev->dev_slave_addr, dev->oem); 2273 else 2274 printf("%-16s | Generic @%02X:%02X.%-2d | ok\n", 2275 dev->id_code ? desc : "", 2276 dev->dev_access_addr, 2277 dev->dev_slave_addr, dev->oem); 2278 2279 return 0; 2280 } 2281 2282 printf("Device ID : %s\n", dev->id_string); 2283 printf("Entity ID : %d.%d (%s)\n", 2284 dev->entity.id, dev->entity.instance, 2285 val2str(dev->entity.id, entity_id_vals)); 2286 2287 printf("Device Access Address : %02Xh\n", dev->dev_access_addr); 2288 printf("Device Slave Address : %02Xh\n", dev->dev_slave_addr); 2289 printf("Address Span : %02Xh\n", dev->addr_span); 2290 printf("Channel Number : %01Xh\n", dev->channel_num); 2291 printf("LUN.Bus : %01Xh.%01Xh\n", dev->lun, dev->bus); 2292 printf("Device Type.Modifier : %01Xh.%01Xh (%s)\n", 2293 dev->dev_type, dev->dev_type_modifier, 2294 val2str(dev->dev_type << 8 | dev->dev_type_modifier, 2295 entity_device_type_vals)); 2296 printf("OEM : %02Xh\n", dev->oem); 2297 printf("\n"); 2298 2299 return 0; 2300 } 2301 2302 /* ipmi_sdr_print_sensor_fru_locator - print FRU locator record 2303 * 2304 * @intf: ipmi interface 2305 * @fru: fru locator sdr record 2306 * 2307 * returns 0 on success 2308 * returns -1 on error 2309 */ 2310 int 2311 ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf, 2312 struct sdr_record_fru_locator *fru) 2313 { 2314 char desc[17]; 2315 2316 memset(desc, 0, sizeof (desc)); 2317 snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string); 2318 2319 if (!verbose) { 2320 if (csv_output) 2321 printf("%s,00h,ns,%d.%d\n", 2322 fru->id_code ? desc : "", 2323 fru->entity.id, fru->entity.instance); 2324 else if (sdr_extended) 2325 printf("%-16s | 00h | ns | %2d.%1d | %s FRU @%02Xh\n", 2326 fru->id_code ? desc : "", 2327 fru->entity.id, fru->entity.instance, 2328 (fru->logical) ? "Logical" : "Physical", 2329 fru->device_id); 2330 else 2331 printf("%-16s | %s FRU @%02Xh %02x.%x | ok\n", 2332 fru->id_code ? desc : "", 2333 (fru->logical) ? "Log" : "Phy", 2334 fru->device_id, 2335 fru->entity.id, fru->entity.instance); 2336 2337 return 0; 2338 } 2339 2340 printf("Device ID : %s\n", fru->id_string); 2341 printf("Entity ID : %d.%d (%s)\n", 2342 fru->entity.id, fru->entity.instance, 2343 val2str(fru->entity.id, entity_id_vals)); 2344 2345 printf("Device Access Address : %02Xh\n", fru->dev_slave_addr); 2346 printf("%s: %02Xh\n", 2347 fru->logical ? "Logical FRU Device " : 2348 "Slave Address ", fru->device_id); 2349 printf("Channel Number : %01Xh\n", fru->channel_num); 2350 printf("LUN.Bus : %01Xh.%01Xh\n", fru->lun, fru->bus); 2351 printf("Device Type.Modifier : %01Xh.%01Xh (%s)\n", 2352 fru->dev_type, fru->dev_type_modifier, 2353 val2str(fru->dev_type << 8 | fru->dev_type_modifier, 2354 entity_device_type_vals)); 2355 printf("OEM : %02Xh\n", fru->oem); 2356 printf("\n"); 2357 2358 return 0; 2359 } 2360 2361 /* ipmi_sdr_print_sensor_entity_assoc - print SDR entity association record 2362 * 2363 * @intf: ipmi interface 2364 * @mc: entity association sdr record 2365 * 2366 * returns 0 on success 2367 * returns -1 on error 2368 */ 2369 int 2370 ipmi_sdr_print_sensor_entity_assoc(struct ipmi_intf *intf, 2371 struct sdr_record_entity_assoc *assoc) 2372 { 2373 return 0; 2374 } 2375 2376 /* ipmi_sdr_print_sensor_oem_intel - print Intel OEM sensors 2377 * 2378 * @intf: ipmi interface 2379 * @oem: oem sdr record 2380 * 2381 * returns 0 on success 2382 * returns -1 on error 2383 */ 2384 static int 2385 ipmi_sdr_print_sensor_oem_intel(struct ipmi_intf *intf, 2386 struct sdr_record_oem *oem) 2387 { 2388 switch (oem->data[3]) { /* record sub-type */ 2389 case 0x02: /* Power Unit Map */ 2390 if (verbose) { 2391 printf 2392 ("Sensor ID : Power Unit Redundancy (0x%x)\n", 2393 oem->data[4]); 2394 printf 2395 ("Sensor Type : Intel OEM - Power Unit Map\n"); 2396 printf("Redundant Supplies : %d", oem->data[6]); 2397 if (oem->data[5]) 2398 printf(" (flags %xh)", oem->data[5]); 2399 printf("\n"); 2400 } 2401 2402 switch (oem->data_len) { 2403 case 7: /* SR1300, non-redundant */ 2404 if (verbose) 2405 printf("Power Redundancy : No\n"); 2406 else if (csv_output) 2407 printf("Power Redundancy,Not Available,nr\n"); 2408 else 2409 printf 2410 ("Power Redundancy | Not Available | nr\n"); 2411 break; 2412 case 8: /* SR2300, redundant, PS1 & PS2 present */ 2413 if (verbose) { 2414 printf("Power Redundancy : No\n"); 2415 printf("Power Supply 2 Sensor : %x\n", 2416 oem->data[8]); 2417 } else if (csv_output) { 2418 printf("Power Redundancy,PS@%02xh,nr\n", 2419 oem->data[8]); 2420 } else { 2421 printf 2422 ("Power Redundancy | PS@%02xh | nr\n", 2423 oem->data[8]); 2424 } 2425 break; 2426 case 9: /* SR2300, non-redundant, PSx present */ 2427 if (verbose) { 2428 printf("Power Redundancy : Yes\n"); 2429 printf("Power Supply Sensor : %x\n", 2430 oem->data[7]); 2431 printf("Power Supply Sensor : %x\n", 2432 oem->data[8]); 2433 } else if (csv_output) { 2434 printf 2435 ("Power Redundancy,PS@%02xh + PS@%02xh,ok\n", 2436 oem->data[7], oem->data[8]); 2437 } else { 2438 printf 2439 ("Power Redundancy | PS@%02xh + PS@%02xh | ok\n", 2440 oem->data[7], oem->data[8]); 2441 } 2442 break; 2443 } 2444 if (verbose) 2445 printf("\n"); 2446 break; 2447 case 0x03: /* Fan Speed Control */ 2448 break; 2449 case 0x06: /* System Information */ 2450 break; 2451 case 0x07: /* Ambient Temperature Fan Speed Control */ 2452 break; 2453 default: 2454 lprintf(LOG_DEBUG, "Unknown Intel OEM SDR Record type %02x", 2455 oem->data[3]); 2456 } 2457 2458 return 0; 2459 } 2460 2461 /* ipmi_sdr_print_sensor_oem - print OEM sensors 2462 * 2463 * This function is generally only filled out by decoding what 2464 * a particular BMC might stuff into its OEM records. The 2465 * records are keyed off manufacturer ID and record subtypes. 2466 * 2467 * @intf: ipmi interface 2468 * @oem: oem sdr record 2469 * 2470 * returns 0 on success 2471 * returns -1 on error 2472 */ 2473 static int 2474 ipmi_sdr_print_sensor_oem(struct ipmi_intf *intf, struct sdr_record_oem *oem) 2475 { 2476 int rc = 0; 2477 2478 if (oem == NULL) 2479 return -1; 2480 if (oem->data_len == 0 || oem->data == NULL) 2481 return -1; 2482 2483 if (verbose > 2) 2484 printbuf(oem->data, oem->data_len, "OEM Record"); 2485 2486 /* intel manufacturer id */ 2487 if (oem->data[0] == 0x57 && 2488 oem->data[1] == 0x01 && oem->data[2] == 0x00) { 2489 rc = ipmi_sdr_print_sensor_oem_intel(intf, oem); 2490 } 2491 2492 return rc; 2493 } 2494 2495 /* ipmi_sdr_print_name_from_rawentry - Print SDR name from raw data 2496 * 2497 * @intf: ipmi interface 2498 * @type: sensor type 2499 * @raw: raw sensor data 2500 * 2501 * returns 0 on success 2502 * returns -1 on error 2503 */ 2504 int 2505 ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf,uint16_t id, 2506 uint8_t type,uint8_t * raw) 2507 { 2508 union { 2509 struct sdr_record_full_sensor *full; 2510 struct sdr_record_compact_sensor *compact; 2511 struct sdr_record_eventonly_sensor *eventonly; 2512 struct sdr_record_generic_locator *genloc; 2513 struct sdr_record_fru_locator *fruloc; 2514 struct sdr_record_mc_locator *mcloc; 2515 struct sdr_record_entity_assoc *entassoc; 2516 struct sdr_record_oem *oem; 2517 } record; 2518 2519 int rc =0; 2520 char desc[17]; 2521 memset(desc, ' ', sizeof (desc)); 2522 2523 switch ( type) { 2524 case SDR_RECORD_TYPE_FULL_SENSOR: 2525 record.full = (struct sdr_record_full_sensor *) raw; 2526 snprintf(desc, (record.full->id_code & 0x1f) +1, "%s", 2527 (const char *)record.full->id_string); 2528 break; 2529 case SDR_RECORD_TYPE_COMPACT_SENSOR: 2530 record.compact = (struct sdr_record_compact_sensor *) raw ; 2531 snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s", 2532 (const char *)record.compact->id_string); 2533 break; 2534 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 2535 record.eventonly = (struct sdr_record_eventonly_sensor *) raw ; 2536 snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s", 2537 (const char *)record.eventonly->id_string); 2538 break; 2539 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 2540 record.mcloc = (struct sdr_record_mc_locator *) raw ; 2541 snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s", 2542 (const char *)record.mcloc->id_string); 2543 break; 2544 default: 2545 rc = -1; 2546 break; 2547 } 2548 2549 lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc); 2550 return rc; 2551 } 2552 2553 /* ipmi_sdr_print_rawentry - Print SDR entry from raw data 2554 * 2555 * @intf: ipmi interface 2556 * @type: sensor type 2557 * @raw: raw sensor data 2558 * @len: length of raw sensor data 2559 * 2560 * returns 0 on success 2561 * returns -1 on error 2562 */ 2563 int 2564 ipmi_sdr_print_rawentry(struct ipmi_intf *intf, uint8_t type, 2565 uint8_t * raw, int len) 2566 { 2567 int rc = 0; 2568 2569 switch (type) { 2570 case SDR_RECORD_TYPE_FULL_SENSOR: 2571 case SDR_RECORD_TYPE_COMPACT_SENSOR: 2572 rc = ipmi_sdr_print_sensor_fc(intf, 2573 (struct sdr_record_common_sensor *) raw, 2574 type); 2575 break; 2576 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 2577 rc = ipmi_sdr_print_sensor_eventonly(intf, 2578 (struct 2579 sdr_record_eventonly_sensor 2580 *) raw); 2581 break; 2582 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 2583 rc = ipmi_sdr_print_sensor_generic_locator(intf, 2584 (struct 2585 sdr_record_generic_locator 2586 *) raw); 2587 break; 2588 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 2589 rc = ipmi_sdr_print_sensor_fru_locator(intf, 2590 (struct 2591 sdr_record_fru_locator 2592 *) raw); 2593 break; 2594 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 2595 rc = ipmi_sdr_print_sensor_mc_locator(intf, 2596 (struct 2597 sdr_record_mc_locator *) 2598 raw); 2599 break; 2600 case SDR_RECORD_TYPE_ENTITY_ASSOC: 2601 rc = ipmi_sdr_print_sensor_entity_assoc(intf, 2602 (struct 2603 sdr_record_entity_assoc 2604 *) raw); 2605 break; 2606 case SDR_RECORD_TYPE_OEM:{ 2607 struct sdr_record_oem oem; 2608 oem.data = raw; 2609 oem.data_len = len; 2610 rc = ipmi_sdr_print_sensor_oem(intf, 2611 (struct sdr_record_oem *) 2612 &oem); 2613 break; 2614 } 2615 case SDR_RECORD_TYPE_DEVICE_ENTITY_ASSOC: 2616 case SDR_RECORD_TYPE_MC_CONFIRMATION: 2617 case SDR_RECORD_TYPE_BMC_MSG_CHANNEL_INFO: 2618 /* not implemented */ 2619 break; 2620 } 2621 2622 return rc; 2623 } 2624 2625 /* ipmi_sdr_print_listentry - Print SDR entry from list 2626 * 2627 * @intf: ipmi interface 2628 * @entry: sdr record list entry 2629 * 2630 * returns 0 on success 2631 * returns -1 on error 2632 */ 2633 int 2634 ipmi_sdr_print_listentry(struct ipmi_intf *intf, struct sdr_record_list *entry) 2635 { 2636 int rc = 0; 2637 2638 switch (entry->type) { 2639 case SDR_RECORD_TYPE_FULL_SENSOR: 2640 case SDR_RECORD_TYPE_COMPACT_SENSOR: 2641 rc = ipmi_sdr_print_sensor_fc(intf, entry->record.common, entry->type); 2642 break; 2643 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 2644 rc = ipmi_sdr_print_sensor_eventonly(intf, 2645 entry->record.eventonly); 2646 break; 2647 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 2648 rc = ipmi_sdr_print_sensor_generic_locator(intf, 2649 entry->record. 2650 genloc); 2651 break; 2652 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 2653 rc = ipmi_sdr_print_sensor_fru_locator(intf, 2654 entry->record.fruloc); 2655 break; 2656 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 2657 rc = ipmi_sdr_print_sensor_mc_locator(intf, 2658 entry->record.mcloc); 2659 break; 2660 case SDR_RECORD_TYPE_ENTITY_ASSOC: 2661 rc = ipmi_sdr_print_sensor_entity_assoc(intf, 2662 entry->record.entassoc); 2663 break; 2664 case SDR_RECORD_TYPE_OEM: 2665 rc = ipmi_sdr_print_sensor_oem(intf, entry->record.oem); 2666 break; 2667 case SDR_RECORD_TYPE_DEVICE_ENTITY_ASSOC: 2668 case SDR_RECORD_TYPE_MC_CONFIRMATION: 2669 case SDR_RECORD_TYPE_BMC_MSG_CHANNEL_INFO: 2670 /* not implemented yet */ 2671 break; 2672 } 2673 2674 return rc; 2675 } 2676 2677 /* ipmi_sdr_print_sdr - iterate through SDR printing records 2678 * 2679 * intf: ipmi interface 2680 * type: record type to print 2681 * 2682 * returns 0 on success 2683 * returns -1 on error 2684 */ 2685 int 2686 ipmi_sdr_print_sdr(struct ipmi_intf *intf, uint8_t type) 2687 { 2688 struct sdr_get_rs *header; 2689 struct sdr_record_list *e; 2690 int rc = 0; 2691 2692 lprintf(LOG_DEBUG, "Querying SDR for sensor list"); 2693 2694 if (sdr_list_itr == NULL) { 2695 sdr_list_itr = ipmi_sdr_start(intf, 0); 2696 if (sdr_list_itr == NULL) { 2697 lprintf(LOG_ERR, "Unable to open SDR for reading"); 2698 return -1; 2699 } 2700 } 2701 2702 for (e = sdr_list_head; e != NULL; e = e->next) { 2703 if (type != e->type && type != 0xff && type != 0xfe) 2704 continue; 2705 if (type == 0xfe && 2706 e->type != SDR_RECORD_TYPE_FULL_SENSOR && 2707 e->type != SDR_RECORD_TYPE_COMPACT_SENSOR) 2708 continue; 2709 if (ipmi_sdr_print_listentry(intf, e) < 0) 2710 rc = -1; 2711 } 2712 2713 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 2714 uint8_t *rec; 2715 struct sdr_record_list *sdrr; 2716 2717 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 2718 if (rec == NULL) { 2719 lprintf(LOG_ERR, "ipmitool: ipmi_sdr_get_record() failed"); 2720 rc = -1; 2721 continue; 2722 } 2723 2724 sdrr = malloc(sizeof (struct sdr_record_list)); 2725 if (sdrr == NULL) { 2726 lprintf(LOG_ERR, "ipmitool: malloc failure"); 2727 if (rec != NULL) { 2728 free(rec); 2729 rec = NULL; 2730 } 2731 break; 2732 } 2733 memset(sdrr, 0, sizeof (struct sdr_record_list)); 2734 sdrr->id = header->id; 2735 sdrr->type = header->type; 2736 2737 switch (header->type) { 2738 case SDR_RECORD_TYPE_FULL_SENSOR: 2739 case SDR_RECORD_TYPE_COMPACT_SENSOR: 2740 sdrr->record.common = 2741 (struct sdr_record_common_sensor *) rec; 2742 break; 2743 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 2744 sdrr->record.eventonly = 2745 (struct sdr_record_eventonly_sensor *) rec; 2746 break; 2747 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 2748 sdrr->record.genloc = 2749 (struct sdr_record_generic_locator *) rec; 2750 break; 2751 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 2752 sdrr->record.fruloc = 2753 (struct sdr_record_fru_locator *) rec; 2754 break; 2755 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 2756 sdrr->record.mcloc = 2757 (struct sdr_record_mc_locator *) rec; 2758 break; 2759 case SDR_RECORD_TYPE_ENTITY_ASSOC: 2760 sdrr->record.entassoc = 2761 (struct sdr_record_entity_assoc *) rec; 2762 break; 2763 default: 2764 free(rec); 2765 rec = NULL; 2766 if (sdrr != NULL) { 2767 free(sdrr); 2768 sdrr = NULL; 2769 } 2770 continue; 2771 } 2772 2773 lprintf(LOG_DEBUG, "SDR record ID : 0x%04x", sdrr->id); 2774 2775 if (type == header->type || type == 0xff || 2776 (type == 0xfe && 2777 (header->type == SDR_RECORD_TYPE_FULL_SENSOR || 2778 header->type == SDR_RECORD_TYPE_COMPACT_SENSOR))) { 2779 if (ipmi_sdr_print_rawentry(intf, header->type, 2780 rec, header->length) < 0) 2781 rc = -1; 2782 } 2783 2784 /* add to global record liset */ 2785 if (sdr_list_head == NULL) 2786 sdr_list_head = sdrr; 2787 else 2788 sdr_list_tail->next = sdrr; 2789 2790 sdr_list_tail = sdrr; 2791 } 2792 2793 return rc; 2794 } 2795 2796 /* ipmi_sdr_get_reservation - Obtain SDR reservation ID 2797 * 2798 * @intf: ipmi interface 2799 * @reserve_id: pointer to short int for storing the id 2800 * 2801 * returns 0 on success 2802 * returns -1 on error 2803 */ 2804 int 2805 ipmi_sdr_get_reservation(struct ipmi_intf *intf, int use_builtin, 2806 uint16_t * reserve_id) 2807 { 2808 struct ipmi_rs *rsp; 2809 struct ipmi_rq req; 2810 2811 /* obtain reservation ID */ 2812 memset(&req, 0, sizeof (req)); 2813 2814 if (use_builtin == 0) { 2815 req.msg.netfn = IPMI_NETFN_STORAGE; 2816 } else { 2817 req.msg.netfn = IPMI_NETFN_SE; 2818 } 2819 2820 req.msg.cmd = GET_SDR_RESERVE_REPO; 2821 rsp = intf->sendrecv(intf, &req); 2822 2823 /* be slient for errors, they are handled by calling function */ 2824 if (rsp == NULL) 2825 return -1; 2826 if (rsp->ccode > 0) 2827 return -1; 2828 2829 *reserve_id = ((struct sdr_reserve_repo_rs *) &(rsp->data))->reserve_id; 2830 lprintf(LOG_DEBUG, "SDR reservation ID %04x", *reserve_id); 2831 2832 return 0; 2833 } 2834 2835 /* ipmi_sdr_start - setup sdr iterator 2836 * 2837 * @intf: ipmi interface 2838 * 2839 * returns sdr iterator structure pointer 2840 * returns NULL on error 2841 */ 2842 struct ipmi_sdr_iterator * 2843 ipmi_sdr_start(struct ipmi_intf *intf, int use_builtin) 2844 { 2845 struct ipmi_sdr_iterator *itr; 2846 struct ipmi_rs *rsp; 2847 struct ipmi_rq req; 2848 2849 struct ipm_devid_rsp *devid; 2850 2851 itr = malloc(sizeof (struct ipmi_sdr_iterator)); 2852 if (itr == NULL) { 2853 lprintf(LOG_ERR, "ipmitool: malloc failure"); 2854 return NULL; 2855 } 2856 2857 /* check SDRR capability */ 2858 memset(&req, 0, sizeof (req)); 2859 req.msg.netfn = IPMI_NETFN_APP; 2860 req.msg.cmd = BMC_GET_DEVICE_ID; 2861 req.msg.data_len = 0; 2862 2863 rsp = intf->sendrecv(intf, &req); 2864 2865 if (rsp == NULL) { 2866 lprintf(LOG_ERR, "Get Device ID command failed"); 2867 free(itr); 2868 itr = NULL; 2869 return NULL; 2870 } 2871 if (rsp->ccode > 0) { 2872 lprintf(LOG_ERR, "Get Device ID command failed: %#x %s", 2873 rsp->ccode, val2str(rsp->ccode, completion_code_vals)); 2874 free(itr); 2875 itr = NULL; 2876 return NULL; 2877 } 2878 devid = (struct ipm_devid_rsp *) rsp->data; 2879 2880 sdriana = (long)IPM_DEV_MANUFACTURER_ID(devid->manufacturer_id); 2881 2882 if (!use_builtin && (devid->device_revision & IPM_DEV_DEVICE_ID_SDR_MASK)) { 2883 if ((devid->adtl_device_support & 0x02) == 0) { 2884 if ((devid->adtl_device_support & 0x01)) { 2885 lprintf(LOG_DEBUG, "Using Device SDRs\n"); 2886 use_built_in = 1; 2887 } else { 2888 lprintf(LOG_ERR, "Error obtaining SDR info"); 2889 free(itr); 2890 itr = NULL; 2891 return NULL; 2892 } 2893 } else { 2894 lprintf(LOG_DEBUG, "Using SDR from Repository \n"); 2895 } 2896 } 2897 itr->use_built_in = use_builtin ? 1 : use_built_in; 2898 /***********************/ 2899 if (itr->use_built_in == 0) { 2900 struct sdr_repo_info_rs sdr_info; 2901 /* get sdr repository info */ 2902 memset(&req, 0, sizeof (req)); 2903 req.msg.netfn = IPMI_NETFN_STORAGE; 2904 req.msg.cmd = GET_SDR_REPO_INFO; 2905 2906 rsp = intf->sendrecv(intf, &req); 2907 if (rsp == NULL) { 2908 lprintf(LOG_ERR, "Error obtaining SDR info"); 2909 free(itr); 2910 itr = NULL; 2911 return NULL; 2912 } 2913 if (rsp->ccode > 0) { 2914 lprintf(LOG_ERR, "Error obtaining SDR info: %s", 2915 val2str(rsp->ccode, completion_code_vals)); 2916 free(itr); 2917 itr = NULL; 2918 return NULL; 2919 } 2920 2921 memcpy(&sdr_info, rsp->data, sizeof (sdr_info)); 2922 /* IPMIv1.0 == 0x01 2923 * IPMIv1.5 == 0x51 2924 * IPMIv2.0 == 0x02 2925 */ 2926 if ((sdr_info.version != 0x51) && 2927 (sdr_info.version != 0x01) && 2928 (sdr_info.version != 0x02)) { 2929 lprintf(LOG_WARN, "WARNING: Unknown SDR repository " 2930 "version 0x%02x", sdr_info.version); 2931 } 2932 2933 itr->total = sdr_info.count; 2934 itr->next = 0; 2935 2936 lprintf(LOG_DEBUG, "SDR free space: %d", sdr_info.free); 2937 lprintf(LOG_DEBUG, "SDR records : %d", sdr_info.count); 2938 2939 /* Build SDRR if there is no record in repository */ 2940 if( sdr_info.count == 0 ) { 2941 lprintf(LOG_DEBUG, "Rebuilding SDRR..."); 2942 2943 if( ipmi_sdr_add_from_sensors( intf, 0 ) != 0 ) { 2944 lprintf(LOG_ERR, "Could not build SDRR!"); 2945 free(itr); 2946 itr = NULL; 2947 return NULL; 2948 } 2949 } 2950 } else { 2951 struct sdr_device_info_rs sdr_info; 2952 /* get device sdr info */ 2953 memset(&req, 0, sizeof (req)); 2954 req.msg.netfn = IPMI_NETFN_SE; 2955 req.msg.cmd = GET_DEVICE_SDR_INFO; 2956 2957 rsp = intf->sendrecv(intf, &req); 2958 if (!rsp || !rsp->data_len || rsp->ccode) { 2959 printf("Err in cmd get sensor sdr info\n"); 2960 free(itr); 2961 itr = NULL; 2962 return NULL; 2963 } 2964 memcpy(&sdr_info, rsp->data, sizeof (sdr_info)); 2965 2966 itr->total = sdr_info.count; 2967 itr->next = 0; 2968 lprintf(LOG_DEBUG, "SDR records : %d", sdr_info.count); 2969 } 2970 2971 if (ipmi_sdr_get_reservation(intf, itr->use_built_in, 2972 &(itr->reservation)) < 0) { 2973 lprintf(LOG_ERR, "Unable to obtain SDR reservation"); 2974 free(itr); 2975 itr = NULL; 2976 return NULL; 2977 } 2978 2979 return itr; 2980 } 2981 2982 /* ipmi_sdr_get_record - return RAW SDR record 2983 * 2984 * @intf: ipmi interface 2985 * @header: SDR header 2986 * @itr: SDR iterator 2987 * 2988 * returns raw SDR data 2989 * returns NULL on error 2990 */ 2991 uint8_t * 2992 ipmi_sdr_get_record(struct ipmi_intf * intf, struct sdr_get_rs * header, 2993 struct ipmi_sdr_iterator * itr) 2994 { 2995 struct ipmi_rq req; 2996 struct ipmi_rs *rsp; 2997 struct sdr_get_rq sdr_rq; 2998 uint8_t *data; 2999 int i = 0, len = header->length; 3000 3001 if (len < 1) 3002 return NULL; 3003 3004 data = malloc(len + 1); 3005 if (data == NULL) { 3006 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3007 return NULL; 3008 } 3009 memset(data, 0, len + 1); 3010 3011 memset(&sdr_rq, 0, sizeof (sdr_rq)); 3012 sdr_rq.reserve_id = itr->reservation; 3013 sdr_rq.id = header->id; 3014 sdr_rq.offset = 0; 3015 3016 memset(&req, 0, sizeof (req)); 3017 if (itr->use_built_in == 0) { 3018 req.msg.netfn = IPMI_NETFN_STORAGE; 3019 req.msg.cmd = GET_SDR; 3020 } else { 3021 req.msg.netfn = IPMI_NETFN_SE; 3022 req.msg.cmd = GET_DEVICE_SDR; 3023 } 3024 req.msg.data = (uint8_t *) & sdr_rq; 3025 req.msg.data_len = sizeof (sdr_rq); 3026 3027 /* check if max length is null */ 3028 if ( sdr_max_read_len == 0 ) { 3029 /* get maximum response size */ 3030 sdr_max_read_len = ipmi_intf_get_max_response_data_size(intf) - 2; 3031 3032 /* cap the number of bytes to read */ 3033 if (sdr_max_read_len > 0xFE) { 3034 sdr_max_read_len = 0xFE; 3035 } 3036 } 3037 3038 /* read SDR record with partial reads 3039 * because a full read usually exceeds the maximum 3040 * transport buffer size. (completion code 0xca) 3041 */ 3042 while (i < len) { 3043 sdr_rq.length = (len - i < sdr_max_read_len) ? 3044 len - i : sdr_max_read_len; 3045 sdr_rq.offset = i + 5; /* 5 header bytes */ 3046 3047 lprintf(LOG_DEBUG, "Getting %d bytes from SDR at offset %d", 3048 sdr_rq.length, sdr_rq.offset); 3049 3050 rsp = intf->sendrecv(intf, &req); 3051 if (rsp == NULL) { 3052 sdr_max_read_len = sdr_rq.length - 1; 3053 if (sdr_max_read_len > 0) { 3054 /* no response may happen if requests are bridged 3055 and too many bytes are requested */ 3056 continue; 3057 } else { 3058 free(data); 3059 data = NULL; 3060 return NULL; 3061 } 3062 } 3063 3064 switch (rsp->ccode) { 3065 case 0xca: 3066 /* read too many bytes at once */ 3067 sdr_max_read_len = sdr_rq.length - 1; 3068 continue; 3069 case 0xc5: 3070 /* lost reservation */ 3071 lprintf(LOG_DEBUG, "SDR reservation cancelled. " 3072 "Sleeping a bit and retrying..."); 3073 3074 sleep(rand() & 3); 3075 3076 if (ipmi_sdr_get_reservation(intf, itr->use_built_in, 3077 &(itr->reservation)) < 0) { 3078 free(data); 3079 data = NULL; 3080 return NULL; 3081 } 3082 sdr_rq.reserve_id = itr->reservation; 3083 continue; 3084 } 3085 3086 /* special completion codes handled above */ 3087 if (rsp->ccode > 0 || rsp->data_len == 0) { 3088 free(data); 3089 data = NULL; 3090 return NULL; 3091 } 3092 3093 memcpy(data + i, rsp->data + 2, sdr_rq.length); 3094 i += sdr_max_read_len; 3095 } 3096 3097 return data; 3098 } 3099 3100 /* ipmi_sdr_end - cleanup SDR iterator 3101 * 3102 * @intf: ipmi interface 3103 * @itr: SDR iterator 3104 * 3105 * no meaningful return code 3106 */ 3107 void 3108 ipmi_sdr_end(struct ipmi_intf *intf, struct ipmi_sdr_iterator *itr) 3109 { 3110 if (itr) { 3111 free(itr); 3112 itr = NULL; 3113 } 3114 } 3115 3116 /* __sdr_list_add - helper function to add SDR record to list 3117 * 3118 * @head: list head 3119 * @entry: new entry to add to end of list 3120 * 3121 * returns 0 on success 3122 * returns -1 on error 3123 */ 3124 static int 3125 __sdr_list_add(struct sdr_record_list *head, struct sdr_record_list *entry) 3126 { 3127 struct sdr_record_list *e; 3128 struct sdr_record_list *new; 3129 3130 if (head == NULL) 3131 return -1; 3132 3133 new = malloc(sizeof (struct sdr_record_list)); 3134 if (new == NULL) { 3135 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3136 return -1; 3137 } 3138 memcpy(new, entry, sizeof (struct sdr_record_list)); 3139 3140 e = head; 3141 while (e->next) 3142 e = e->next; 3143 e->next = new; 3144 new->next = NULL; 3145 3146 return 0; 3147 } 3148 3149 /* __sdr_list_empty - low-level handler to clean up record list 3150 * 3151 * @head: list head to clean 3152 * 3153 * no meaningful return code 3154 */ 3155 static void 3156 __sdr_list_empty(struct sdr_record_list *head) 3157 { 3158 struct sdr_record_list *e, *f; 3159 for (e = head; e != NULL; e = f) { 3160 f = e->next; 3161 free(e); 3162 e = NULL; 3163 } 3164 head = NULL; 3165 } 3166 3167 /* ipmi_sdr_list_empty - clean global SDR list 3168 * 3169 * @intf: ipmi interface 3170 * 3171 * no meaningful return code 3172 */ 3173 void 3174 ipmi_sdr_list_empty(struct ipmi_intf *intf) 3175 { 3176 struct sdr_record_list *list, *next; 3177 3178 ipmi_sdr_end(intf, sdr_list_itr); 3179 3180 for (list = sdr_list_head; list != NULL; list = next) { 3181 switch (list->type) { 3182 case SDR_RECORD_TYPE_FULL_SENSOR: 3183 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3184 if (list->record.common) { 3185 free(list->record.common); 3186 list->record.common = NULL; 3187 } 3188 break; 3189 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3190 if (list->record.eventonly) { 3191 free(list->record.eventonly); 3192 list->record.eventonly = NULL; 3193 } 3194 break; 3195 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3196 if (list->record.genloc) { 3197 free(list->record.genloc); 3198 list->record.genloc = NULL; 3199 } 3200 break; 3201 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3202 if (list->record.fruloc) { 3203 free(list->record.fruloc); 3204 list->record.fruloc = NULL; 3205 } 3206 break; 3207 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3208 if (list->record.mcloc) { 3209 free(list->record.mcloc); 3210 list->record.mcloc = NULL; 3211 } 3212 break; 3213 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3214 if (list->record.entassoc) { 3215 free(list->record.entassoc); 3216 list->record.entassoc = NULL; 3217 } 3218 break; 3219 } 3220 next = list->next; 3221 free(list); 3222 list = NULL; 3223 } 3224 3225 sdr_list_head = NULL; 3226 sdr_list_tail = NULL; 3227 sdr_list_itr = NULL; 3228 } 3229 3230 /* ipmi_sdr_find_sdr_bynumtype - lookup SDR entry by number/type 3231 * 3232 * @intf: ipmi interface 3233 * @gen_id: sensor owner ID/LUN - SEL generator ID 3234 * @num: sensor number to search for 3235 * @type: sensor type to search for 3236 * 3237 * returns pointer to SDR list 3238 * returns NULL on error 3239 */ 3240 struct sdr_record_list * 3241 ipmi_sdr_find_sdr_bynumtype(struct ipmi_intf *intf, uint16_t gen_id, uint8_t num, uint8_t type) 3242 { 3243 struct sdr_get_rs *header; 3244 struct sdr_record_list *e; 3245 int found = 0; 3246 3247 if (sdr_list_itr == NULL) { 3248 sdr_list_itr = ipmi_sdr_start(intf, 0); 3249 if (sdr_list_itr == NULL) { 3250 lprintf(LOG_ERR, "Unable to open SDR for reading"); 3251 return NULL; 3252 } 3253 } 3254 3255 /* check what we've already read */ 3256 for (e = sdr_list_head; e != NULL; e = e->next) { 3257 switch (e->type) { 3258 case SDR_RECORD_TYPE_FULL_SENSOR: 3259 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3260 if (e->record.common->keys.sensor_num == num && 3261 e->record.common->keys.owner_id == (gen_id & 0x00ff) && 3262 e->record.common->sensor.type == type) 3263 return e; 3264 break; 3265 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3266 if (e->record.eventonly->keys.sensor_num == num && 3267 e->record.eventonly->keys.owner_id == (gen_id & 0x00ff) && 3268 e->record.eventonly->sensor_type == type) 3269 return e; 3270 break; 3271 } 3272 } 3273 3274 /* now keep looking */ 3275 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 3276 uint8_t *rec; 3277 struct sdr_record_list *sdrr; 3278 3279 sdrr = malloc(sizeof (struct sdr_record_list)); 3280 if (sdrr == NULL) { 3281 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3282 break; 3283 } 3284 memset(sdrr, 0, sizeof (struct sdr_record_list)); 3285 sdrr->id = header->id; 3286 sdrr->type = header->type; 3287 3288 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 3289 if (rec == NULL) { 3290 if (sdrr != NULL) { 3291 free(sdrr); 3292 sdrr = NULL; 3293 } 3294 continue; 3295 } 3296 3297 switch (header->type) { 3298 case SDR_RECORD_TYPE_FULL_SENSOR: 3299 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3300 sdrr->record.common = 3301 (struct sdr_record_common_sensor *) rec; 3302 if (sdrr->record.common->keys.sensor_num == num 3303 && sdrr->record.common->keys.owner_id == (gen_id & 0x00ff) 3304 && sdrr->record.common->sensor.type == type) 3305 found = 1; 3306 break; 3307 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3308 sdrr->record.eventonly = 3309 (struct sdr_record_eventonly_sensor *) rec; 3310 if (sdrr->record.eventonly->keys.sensor_num == num 3311 && sdrr->record.eventonly->keys.owner_id == (gen_id & 0x00ff) 3312 && sdrr->record.eventonly->sensor_type == type) 3313 found = 1; 3314 break; 3315 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3316 sdrr->record.genloc = 3317 (struct sdr_record_generic_locator *) rec; 3318 break; 3319 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3320 sdrr->record.fruloc = 3321 (struct sdr_record_fru_locator *) rec; 3322 break; 3323 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3324 sdrr->record.mcloc = 3325 (struct sdr_record_mc_locator *) rec; 3326 break; 3327 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3328 sdrr->record.entassoc = 3329 (struct sdr_record_entity_assoc *) rec; 3330 break; 3331 default: 3332 free(rec); 3333 rec = NULL; 3334 if (sdrr != NULL) { 3335 free(sdrr); 3336 sdrr = NULL; 3337 } 3338 continue; 3339 } 3340 3341 /* put in the global record list */ 3342 if (sdr_list_head == NULL) 3343 sdr_list_head = sdrr; 3344 else 3345 sdr_list_tail->next = sdrr; 3346 3347 sdr_list_tail = sdrr; 3348 3349 if (found) 3350 return sdrr; 3351 } 3352 3353 return NULL; 3354 } 3355 3356 /* ipmi_sdr_find_sdr_bysensortype - lookup SDR entry by sensor type 3357 * 3358 * @intf: ipmi interface 3359 * @type: sensor type to search for 3360 * 3361 * returns pointer to SDR list 3362 * returns NULL on error 3363 */ 3364 struct sdr_record_list * 3365 ipmi_sdr_find_sdr_bysensortype(struct ipmi_intf *intf, uint8_t type) 3366 { 3367 struct sdr_record_list *head; 3368 struct sdr_get_rs *header; 3369 struct sdr_record_list *e; 3370 3371 if (sdr_list_itr == NULL) { 3372 sdr_list_itr = ipmi_sdr_start(intf, 0); 3373 if (sdr_list_itr == NULL) { 3374 lprintf(LOG_ERR, "Unable to open SDR for reading"); 3375 return NULL; 3376 } 3377 } 3378 3379 /* check what we've already read */ 3380 head = malloc(sizeof (struct sdr_record_list)); 3381 if (head == NULL) { 3382 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3383 return NULL; 3384 } 3385 memset(head, 0, sizeof (struct sdr_record_list)); 3386 3387 for (e = sdr_list_head; e != NULL; e = e->next) { 3388 switch (e->type) { 3389 case SDR_RECORD_TYPE_FULL_SENSOR: 3390 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3391 if (e->record.common->sensor.type == type) 3392 __sdr_list_add(head, e); 3393 break; 3394 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3395 if (e->record.eventonly->sensor_type == type) 3396 __sdr_list_add(head, e); 3397 break; 3398 } 3399 } 3400 3401 /* now keep looking */ 3402 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 3403 uint8_t *rec; 3404 struct sdr_record_list *sdrr; 3405 3406 sdrr = malloc(sizeof (struct sdr_record_list)); 3407 if (sdrr == NULL) { 3408 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3409 break; 3410 } 3411 memset(sdrr, 0, sizeof (struct sdr_record_list)); 3412 sdrr->id = header->id; 3413 sdrr->type = header->type; 3414 3415 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 3416 if (rec == NULL) { 3417 if (sdrr != NULL) { 3418 free(sdrr); 3419 sdrr = NULL; 3420 } 3421 continue; 3422 } 3423 3424 switch (header->type) { 3425 case SDR_RECORD_TYPE_FULL_SENSOR: 3426 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3427 sdrr->record.common = 3428 (struct sdr_record_common_sensor *) rec; 3429 if (sdrr->record.common->sensor.type == type) 3430 __sdr_list_add(head, sdrr); 3431 break; 3432 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3433 sdrr->record.eventonly = 3434 (struct sdr_record_eventonly_sensor *) rec; 3435 if (sdrr->record.eventonly->sensor_type == type) 3436 __sdr_list_add(head, sdrr); 3437 break; 3438 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3439 sdrr->record.genloc = 3440 (struct sdr_record_generic_locator *) rec; 3441 break; 3442 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3443 sdrr->record.fruloc = 3444 (struct sdr_record_fru_locator *) rec; 3445 break; 3446 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3447 sdrr->record.mcloc = 3448 (struct sdr_record_mc_locator *) rec; 3449 break; 3450 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3451 sdrr->record.entassoc = 3452 (struct sdr_record_entity_assoc *) rec; 3453 break; 3454 default: 3455 free(rec); 3456 rec = NULL; 3457 if (sdrr != NULL) { 3458 free(sdrr); 3459 sdrr = NULL; 3460 } 3461 continue; 3462 } 3463 3464 /* put in the global record list */ 3465 if (sdr_list_head == NULL) 3466 sdr_list_head = sdrr; 3467 else 3468 sdr_list_tail->next = sdrr; 3469 3470 sdr_list_tail = sdrr; 3471 } 3472 3473 return head; 3474 } 3475 3476 /* ipmi_sdr_find_sdr_byentity - lookup SDR entry by entity association 3477 * 3478 * @intf: ipmi interface 3479 * @entity: entity id/instance to search for 3480 * 3481 * returns pointer to SDR list 3482 * returns NULL on error 3483 */ 3484 struct sdr_record_list * 3485 ipmi_sdr_find_sdr_byentity(struct ipmi_intf *intf, struct entity_id *entity) 3486 { 3487 struct sdr_get_rs *header; 3488 struct sdr_record_list *e; 3489 struct sdr_record_list *head; 3490 3491 if (sdr_list_itr == NULL) { 3492 sdr_list_itr = ipmi_sdr_start(intf, 0); 3493 if (sdr_list_itr == NULL) { 3494 lprintf(LOG_ERR, "Unable to open SDR for reading"); 3495 return NULL; 3496 } 3497 } 3498 3499 head = malloc(sizeof (struct sdr_record_list)); 3500 if (head == NULL) { 3501 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3502 return NULL; 3503 } 3504 memset(head, 0, sizeof (struct sdr_record_list)); 3505 3506 /* check what we've already read */ 3507 for (e = sdr_list_head; e != NULL; e = e->next) { 3508 switch (e->type) { 3509 case SDR_RECORD_TYPE_FULL_SENSOR: 3510 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3511 if (e->record.common->entity.id == entity->id && 3512 (entity->instance == 0x7f || 3513 e->record.common->entity.instance == 3514 entity->instance)) 3515 __sdr_list_add(head, e); 3516 break; 3517 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3518 if (e->record.eventonly->entity.id == entity->id && 3519 (entity->instance == 0x7f || 3520 e->record.eventonly->entity.instance == 3521 entity->instance)) 3522 __sdr_list_add(head, e); 3523 break; 3524 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3525 if (e->record.genloc->entity.id == entity->id && 3526 (entity->instance == 0x7f || 3527 e->record.genloc->entity.instance == 3528 entity->instance)) 3529 __sdr_list_add(head, e); 3530 break; 3531 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3532 if (e->record.fruloc->entity.id == entity->id && 3533 (entity->instance == 0x7f || 3534 e->record.fruloc->entity.instance == 3535 entity->instance)) 3536 __sdr_list_add(head, e); 3537 break; 3538 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3539 if (e->record.mcloc->entity.id == entity->id && 3540 (entity->instance == 0x7f || 3541 e->record.mcloc->entity.instance == 3542 entity->instance)) 3543 __sdr_list_add(head, e); 3544 break; 3545 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3546 if (e->record.entassoc->entity.id == entity->id && 3547 (entity->instance == 0x7f || 3548 e->record.entassoc->entity.instance == 3549 entity->instance)) 3550 __sdr_list_add(head, e); 3551 break; 3552 } 3553 } 3554 3555 /* now keep looking */ 3556 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 3557 uint8_t *rec; 3558 struct sdr_record_list *sdrr; 3559 3560 sdrr = malloc(sizeof (struct sdr_record_list)); 3561 if (sdrr == NULL) { 3562 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3563 break; 3564 } 3565 memset(sdrr, 0, sizeof (struct sdr_record_list)); 3566 sdrr->id = header->id; 3567 sdrr->type = header->type; 3568 3569 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 3570 if (rec == NULL) { 3571 if (sdrr != NULL) { 3572 free(sdrr); 3573 sdrr = NULL; 3574 } 3575 continue; 3576 } 3577 3578 switch (header->type) { 3579 case SDR_RECORD_TYPE_FULL_SENSOR: 3580 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3581 sdrr->record.common = 3582 (struct sdr_record_common_sensor *) rec; 3583 if (sdrr->record.common->entity.id == entity->id 3584 && (entity->instance == 0x7f 3585 || sdrr->record.common->entity.instance == 3586 entity->instance)) 3587 __sdr_list_add(head, sdrr); 3588 break; 3589 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3590 sdrr->record.eventonly = 3591 (struct sdr_record_eventonly_sensor *) rec; 3592 if (sdrr->record.eventonly->entity.id == entity->id 3593 && (entity->instance == 0x7f 3594 || sdrr->record.eventonly->entity.instance == 3595 entity->instance)) 3596 __sdr_list_add(head, sdrr); 3597 break; 3598 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3599 sdrr->record.genloc = 3600 (struct sdr_record_generic_locator *) rec; 3601 if (sdrr->record.genloc->entity.id == entity->id 3602 && (entity->instance == 0x7f 3603 || sdrr->record.genloc->entity.instance == 3604 entity->instance)) 3605 __sdr_list_add(head, sdrr); 3606 break; 3607 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3608 sdrr->record.fruloc = 3609 (struct sdr_record_fru_locator *) rec; 3610 if (sdrr->record.fruloc->entity.id == entity->id 3611 && (entity->instance == 0x7f 3612 || sdrr->record.fruloc->entity.instance == 3613 entity->instance)) 3614 __sdr_list_add(head, sdrr); 3615 break; 3616 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3617 sdrr->record.mcloc = 3618 (struct sdr_record_mc_locator *) rec; 3619 if (sdrr->record.mcloc->entity.id == entity->id 3620 && (entity->instance == 0x7f 3621 || sdrr->record.mcloc->entity.instance == 3622 entity->instance)) 3623 __sdr_list_add(head, sdrr); 3624 break; 3625 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3626 sdrr->record.entassoc = 3627 (struct sdr_record_entity_assoc *) rec; 3628 if (sdrr->record.entassoc->entity.id == entity->id 3629 && (entity->instance == 0x7f 3630 || sdrr->record.entassoc->entity.instance == 3631 entity->instance)) 3632 __sdr_list_add(head, sdrr); 3633 break; 3634 default: 3635 free(rec); 3636 rec = NULL; 3637 if (sdrr != NULL) { 3638 free(sdrr); 3639 sdrr = NULL; 3640 } 3641 continue; 3642 } 3643 3644 /* add to global record list */ 3645 if (sdr_list_head == NULL) 3646 sdr_list_head = sdrr; 3647 else 3648 sdr_list_tail->next = sdrr; 3649 3650 sdr_list_tail = sdrr; 3651 } 3652 3653 return head; 3654 } 3655 3656 /* ipmi_sdr_find_sdr_bytype - lookup SDR entries by type 3657 * 3658 * @intf: ipmi interface 3659 * @type: type of sensor record to search for 3660 * 3661 * returns pointer to SDR list with all matching entities 3662 * returns NULL on error 3663 */ 3664 struct sdr_record_list * 3665 ipmi_sdr_find_sdr_bytype(struct ipmi_intf *intf, uint8_t type) 3666 { 3667 struct sdr_get_rs *header; 3668 struct sdr_record_list *e; 3669 struct sdr_record_list *head; 3670 3671 if (sdr_list_itr == NULL) { 3672 sdr_list_itr = ipmi_sdr_start(intf, 0); 3673 if (sdr_list_itr == NULL) { 3674 lprintf(LOG_ERR, "Unable to open SDR for reading"); 3675 return NULL; 3676 } 3677 } 3678 3679 head = malloc(sizeof (struct sdr_record_list)); 3680 if (head == NULL) { 3681 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3682 return NULL; 3683 } 3684 memset(head, 0, sizeof (struct sdr_record_list)); 3685 3686 /* check what we've already read */ 3687 for (e = sdr_list_head; e != NULL; e = e->next) 3688 if (e->type == type) 3689 __sdr_list_add(head, e); 3690 3691 /* now keep looking */ 3692 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 3693 uint8_t *rec; 3694 struct sdr_record_list *sdrr; 3695 3696 sdrr = malloc(sizeof (struct sdr_record_list)); 3697 if (sdrr == NULL) { 3698 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3699 break; 3700 } 3701 memset(sdrr, 0, sizeof (struct sdr_record_list)); 3702 sdrr->id = header->id; 3703 sdrr->type = header->type; 3704 3705 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 3706 if (rec == NULL) { 3707 if (sdrr != NULL) { 3708 free(sdrr); 3709 sdrr = NULL; 3710 } 3711 continue; 3712 } 3713 3714 switch (header->type) { 3715 case SDR_RECORD_TYPE_FULL_SENSOR: 3716 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3717 sdrr->record.common = 3718 (struct sdr_record_common_sensor *) rec; 3719 break; 3720 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3721 sdrr->record.eventonly = 3722 (struct sdr_record_eventonly_sensor *) rec; 3723 break; 3724 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3725 sdrr->record.genloc = 3726 (struct sdr_record_generic_locator *) rec; 3727 break; 3728 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3729 sdrr->record.fruloc = 3730 (struct sdr_record_fru_locator *) rec; 3731 break; 3732 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3733 sdrr->record.mcloc = 3734 (struct sdr_record_mc_locator *) rec; 3735 break; 3736 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3737 sdrr->record.entassoc = 3738 (struct sdr_record_entity_assoc *) rec; 3739 break; 3740 default: 3741 free(rec); 3742 rec = NULL; 3743 if (sdrr != NULL) { 3744 free(sdrr); 3745 sdrr = NULL; 3746 } 3747 continue; 3748 } 3749 3750 if (header->type == type) 3751 __sdr_list_add(head, sdrr); 3752 3753 /* add to global record list */ 3754 if (sdr_list_head == NULL) 3755 sdr_list_head = sdrr; 3756 else 3757 sdr_list_tail->next = sdrr; 3758 3759 sdr_list_tail = sdrr; 3760 } 3761 3762 return head; 3763 } 3764 3765 /* ipmi_sdr_find_sdr_byid - lookup SDR entry by ID string 3766 * 3767 * @intf: ipmi interface 3768 * @id: string to match for sensor name 3769 * 3770 * returns pointer to SDR list 3771 * returns NULL on error 3772 */ 3773 struct sdr_record_list * 3774 ipmi_sdr_find_sdr_byid(struct ipmi_intf *intf, char *id) 3775 { 3776 struct sdr_get_rs *header; 3777 struct sdr_record_list *e; 3778 int found = 0; 3779 int idlen; 3780 3781 if (id == NULL) 3782 return NULL; 3783 3784 idlen = strlen(id); 3785 3786 if (sdr_list_itr == NULL) { 3787 sdr_list_itr = ipmi_sdr_start(intf, 0); 3788 if (sdr_list_itr == NULL) { 3789 lprintf(LOG_ERR, "Unable to open SDR for reading"); 3790 return NULL; 3791 } 3792 } 3793 3794 /* check what we've already read */ 3795 for (e = sdr_list_head; e != NULL; e = e->next) { 3796 switch (e->type) { 3797 case SDR_RECORD_TYPE_FULL_SENSOR: 3798 if (!strncmp((const char *)e->record.full->id_string, 3799 (const char *)id, 3800 __max(e->record.full->id_code & 0x1f, idlen))) 3801 return e; 3802 break; 3803 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3804 if (!strncmp((const char *)e->record.compact->id_string, 3805 (const char *)id, 3806 __max(e->record.compact->id_code & 0x1f, idlen))) 3807 return e; 3808 break; 3809 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3810 if (!strncmp((const char *)e->record.eventonly->id_string, 3811 (const char *)id, 3812 __max(e->record.eventonly->id_code & 0x1f, idlen))) 3813 return e; 3814 break; 3815 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3816 if (!strncmp((const char *)e->record.genloc->id_string, 3817 (const char *)id, 3818 __max(e->record.genloc->id_code & 0x1f, idlen))) 3819 return e; 3820 break; 3821 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3822 if (!strncmp((const char *)e->record.fruloc->id_string, 3823 (const char *)id, 3824 __max(e->record.fruloc->id_code & 0x1f, idlen))) 3825 return e; 3826 break; 3827 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3828 if (!strncmp((const char *)e->record.mcloc->id_string, 3829 (const char *)id, 3830 __max(e->record.mcloc->id_code & 0x1f, idlen))) 3831 return e; 3832 break; 3833 } 3834 } 3835 3836 /* now keep looking */ 3837 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 3838 uint8_t *rec; 3839 struct sdr_record_list *sdrr; 3840 3841 sdrr = malloc(sizeof (struct sdr_record_list)); 3842 if (sdrr == NULL) { 3843 lprintf(LOG_ERR, "ipmitool: malloc failure"); 3844 break; 3845 } 3846 memset(sdrr, 0, sizeof (struct sdr_record_list)); 3847 sdrr->id = header->id; 3848 sdrr->type = header->type; 3849 3850 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 3851 if (rec == NULL) { 3852 if (sdrr != NULL) { 3853 free(sdrr); 3854 sdrr = NULL; 3855 } 3856 continue; 3857 } 3858 3859 switch (header->type) { 3860 case SDR_RECORD_TYPE_FULL_SENSOR: 3861 sdrr->record.full = 3862 (struct sdr_record_full_sensor *) rec; 3863 if (!strncmp( 3864 (const char *)sdrr->record.full->id_string, 3865 (const char *)id, 3866 __max(sdrr->record.full->id_code & 0x1f, idlen))) 3867 found = 1; 3868 break; 3869 case SDR_RECORD_TYPE_COMPACT_SENSOR: 3870 sdrr->record.compact = 3871 (struct sdr_record_compact_sensor *) rec; 3872 if (!strncmp( 3873 (const char *)sdrr->record.compact->id_string, 3874 (const char *)id, 3875 __max(sdrr->record.compact->id_code & 0x1f, 3876 idlen))) 3877 found = 1; 3878 break; 3879 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 3880 sdrr->record.eventonly = 3881 (struct sdr_record_eventonly_sensor *) rec; 3882 if (!strncmp( 3883 (const char *)sdrr->record.eventonly->id_string, 3884 (const char *)id, 3885 __max(sdrr->record.eventonly->id_code & 0x1f, 3886 idlen))) 3887 found = 1; 3888 break; 3889 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 3890 sdrr->record.genloc = 3891 (struct sdr_record_generic_locator *) rec; 3892 if (!strncmp( 3893 (const char *)sdrr->record.genloc->id_string, 3894 (const char *)id, 3895 __max(sdrr->record.genloc->id_code & 0x1f, idlen))) 3896 found = 1; 3897 break; 3898 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 3899 sdrr->record.fruloc = 3900 (struct sdr_record_fru_locator *) rec; 3901 if (!strncmp( 3902 (const char *)sdrr->record.fruloc->id_string, 3903 (const char *)id, 3904 __max(sdrr->record.fruloc->id_code & 0x1f, idlen))) 3905 found = 1; 3906 break; 3907 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 3908 sdrr->record.mcloc = 3909 (struct sdr_record_mc_locator *) rec; 3910 if (!strncmp( 3911 (const char *)sdrr->record.mcloc->id_string, 3912 (const char *)id, 3913 __max(sdrr->record.mcloc->id_code & 0x1f, idlen))) 3914 found = 1; 3915 break; 3916 case SDR_RECORD_TYPE_ENTITY_ASSOC: 3917 sdrr->record.entassoc = 3918 (struct sdr_record_entity_assoc *) rec; 3919 break; 3920 default: 3921 free(rec); 3922 rec = NULL; 3923 if (sdrr != NULL) { 3924 free(sdrr); 3925 sdrr = NULL; 3926 } 3927 continue; 3928 } 3929 3930 /* add to global record liset */ 3931 if (sdr_list_head == NULL) 3932 sdr_list_head = sdrr; 3933 else 3934 sdr_list_tail->next = sdrr; 3935 3936 sdr_list_tail = sdrr; 3937 3938 if (found) 3939 return sdrr; 3940 } 3941 3942 return NULL; 3943 } 3944 3945 /* ipmi_sdr_list_cache_fromfile - generate SDR cache for fast lookup from local file 3946 * 3947 * @intf: ipmi interface 3948 * @ifile: input filename 3949 * 3950 * returns pointer to SDR list 3951 * returns NULL on error 3952 */ 3953 int 3954 ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile) 3955 { 3956 FILE *fp; 3957 struct __sdr_header { 3958 uint16_t id; 3959 uint8_t version; 3960 uint8_t type; 3961 uint8_t length; 3962 } header; 3963 struct sdr_record_list *sdrr; 3964 uint8_t *rec; 3965 int ret = 0, count = 0, bc = 0; 3966 3967 if (ifile == NULL) { 3968 lprintf(LOG_ERR, "No SDR cache filename given"); 3969 return -1; 3970 } 3971 3972 fp = ipmi_open_file_read(ifile); 3973 if (fp == NULL) { 3974 lprintf(LOG_ERR, "Unable to open SDR cache %s for reading", 3975 ifile); 3976 return -1; 3977 } 3978 3979 while (feof(fp) == 0) { 3980 memset(&header, 0, sizeof(header)); 3981 bc = fread(&header, 1, 5, fp); 3982 if (bc <= 0) 3983 break; 3984 3985 if (bc != 5) { 3986 lprintf(LOG_ERR, "header read %d bytes, expected 5", 3987 bc); 3988 ret = -1; 3989 break; 3990 } 3991 3992 if (header.length == 0) 3993 continue; 3994 3995 if (header.version != 0x51 && 3996 header.version != 0x01 && 3997 header.version != 0x02) { 3998 lprintf(LOG_WARN, "invalid sdr header version %02x", 3999 header.version); 4000 ret = -1; 4001 break; 4002 } 4003 4004 sdrr = malloc(sizeof (struct sdr_record_list)); 4005 if (sdrr == NULL) { 4006 lprintf(LOG_ERR, "ipmitool: malloc failure"); 4007 ret = -1; 4008 break; 4009 } 4010 memset(sdrr, 0, sizeof (struct sdr_record_list)); 4011 4012 sdrr->id = header.id; 4013 sdrr->type = header.type; 4014 4015 rec = malloc(header.length + 1); 4016 if (rec == NULL) { 4017 lprintf(LOG_ERR, "ipmitool: malloc failure"); 4018 ret = -1; 4019 if (sdrr != NULL) { 4020 free(sdrr); 4021 sdrr = NULL; 4022 } 4023 break; 4024 } 4025 memset(rec, 0, header.length + 1); 4026 4027 bc = fread(rec, 1, header.length, fp); 4028 if (bc != header.length) { 4029 lprintf(LOG_ERR, 4030 "record %04x read %d bytes, expected %d", 4031 header.id, bc, header.length); 4032 ret = -1; 4033 if (sdrr != NULL) { 4034 free(sdrr); 4035 sdrr = NULL; 4036 } 4037 if (rec != NULL) { 4038 free(rec); 4039 rec = NULL; 4040 } 4041 break; 4042 } 4043 4044 switch (header.type) { 4045 case SDR_RECORD_TYPE_FULL_SENSOR: 4046 case SDR_RECORD_TYPE_COMPACT_SENSOR: 4047 sdrr->record.common = 4048 (struct sdr_record_common_sensor *) rec; 4049 break; 4050 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 4051 sdrr->record.eventonly = 4052 (struct sdr_record_eventonly_sensor *) rec; 4053 break; 4054 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 4055 sdrr->record.genloc = 4056 (struct sdr_record_generic_locator *) rec; 4057 break; 4058 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 4059 sdrr->record.fruloc = 4060 (struct sdr_record_fru_locator *) rec; 4061 break; 4062 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 4063 sdrr->record.mcloc = 4064 (struct sdr_record_mc_locator *) rec; 4065 break; 4066 case SDR_RECORD_TYPE_ENTITY_ASSOC: 4067 sdrr->record.entassoc = 4068 (struct sdr_record_entity_assoc *) rec; 4069 break; 4070 default: 4071 free(rec); 4072 rec = NULL; 4073 if (sdrr != NULL) { 4074 free(sdrr); 4075 sdrr = NULL; 4076 } 4077 continue; 4078 } 4079 4080 /* add to global record liset */ 4081 if (sdr_list_head == NULL) 4082 sdr_list_head = sdrr; 4083 else 4084 sdr_list_tail->next = sdrr; 4085 4086 sdr_list_tail = sdrr; 4087 4088 count++; 4089 4090 lprintf(LOG_DEBUG, "Read record %04x from file into cache", 4091 sdrr->id); 4092 } 4093 4094 if (sdr_list_itr == NULL) { 4095 sdr_list_itr = malloc(sizeof (struct ipmi_sdr_iterator)); 4096 if (sdr_list_itr != NULL) { 4097 sdr_list_itr->reservation = 0; 4098 sdr_list_itr->total = count; 4099 sdr_list_itr->next = 0xffff; 4100 } 4101 } 4102 4103 fclose(fp); 4104 return ret; 4105 } 4106 4107 /* ipmi_sdr_list_cache - generate SDR cache for fast lookup 4108 * 4109 * @intf: ipmi interface 4110 * 4111 * returns pointer to SDR list 4112 * returns NULL on error 4113 */ 4114 int 4115 ipmi_sdr_list_cache(struct ipmi_intf *intf) 4116 { 4117 struct sdr_get_rs *header; 4118 4119 if (sdr_list_itr == NULL) { 4120 sdr_list_itr = ipmi_sdr_start(intf, 0); 4121 if (sdr_list_itr == NULL) { 4122 lprintf(LOG_ERR, "Unable to open SDR for reading"); 4123 return -1; 4124 } 4125 } 4126 4127 while ((header = ipmi_sdr_get_next_header(intf, sdr_list_itr)) != NULL) { 4128 uint8_t *rec; 4129 struct sdr_record_list *sdrr; 4130 4131 sdrr = malloc(sizeof (struct sdr_record_list)); 4132 if (sdrr == NULL) { 4133 lprintf(LOG_ERR, "ipmitool: malloc failure"); 4134 break; 4135 } 4136 memset(sdrr, 0, sizeof (struct sdr_record_list)); 4137 sdrr->id = header->id; 4138 sdrr->type = header->type; 4139 4140 rec = ipmi_sdr_get_record(intf, header, sdr_list_itr); 4141 if (rec == NULL) { 4142 if (sdrr != NULL) { 4143 free(sdrr); 4144 sdrr = NULL; 4145 } 4146 continue; 4147 } 4148 4149 switch (header->type) { 4150 case SDR_RECORD_TYPE_FULL_SENSOR: 4151 case SDR_RECORD_TYPE_COMPACT_SENSOR: 4152 sdrr->record.common = 4153 (struct sdr_record_common_sensor *) rec; 4154 break; 4155 case SDR_RECORD_TYPE_EVENTONLY_SENSOR: 4156 sdrr->record.eventonly = 4157 (struct sdr_record_eventonly_sensor *) rec; 4158 break; 4159 case SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR: 4160 sdrr->record.genloc = 4161 (struct sdr_record_generic_locator *) rec; 4162 break; 4163 case SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR: 4164 sdrr->record.fruloc = 4165 (struct sdr_record_fru_locator *) rec; 4166 break; 4167 case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR: 4168 sdrr->record.mcloc = 4169 (struct sdr_record_mc_locator *) rec; 4170 break; 4171 case SDR_RECORD_TYPE_ENTITY_ASSOC: 4172 sdrr->record.entassoc = 4173 (struct sdr_record_entity_assoc *) rec; 4174 break; 4175 default: 4176 free(rec); 4177 rec = NULL; 4178 if (sdrr != NULL) { 4179 free(sdrr); 4180 sdrr = NULL; 4181 } 4182 continue; 4183 } 4184 4185 /* add to global record liset */ 4186 if (sdr_list_head == NULL) 4187 sdr_list_head = sdrr; 4188 else 4189 sdr_list_tail->next = sdrr; 4190 4191 sdr_list_tail = sdrr; 4192 } 4193 4194 return 0; 4195 } 4196 4197 /* 4198 * ipmi_sdr_get_info 4199 * 4200 * Execute the GET SDR REPOSITORY INFO command, and populate the sdr_info 4201 * structure. 4202 * See section 33.9 of the IPMI v2 specification for details 4203 * 4204 * returns 0 on success 4205 * -1 on transport error 4206 * > 0 for other errors 4207 */ 4208 int 4209 ipmi_sdr_get_info(struct ipmi_intf *intf, 4210 struct get_sdr_repository_info_rsp *sdr_repository_info) 4211 { 4212 struct ipmi_rs *rsp; 4213 struct ipmi_rq req; 4214 4215 memset(&req, 0, sizeof (req)); 4216 4217 req.msg.netfn = IPMI_NETFN_STORAGE; // 0x0A 4218 req.msg.cmd = IPMI_GET_SDR_REPOSITORY_INFO; // 0x20 4219 req.msg.data = 0; 4220 req.msg.data_len = 0; 4221 4222 rsp = intf->sendrecv(intf, &req); 4223 4224 if (rsp == NULL) { 4225 lprintf(LOG_ERR, "Get SDR Repository Info command failed"); 4226 return -1; 4227 } 4228 if (rsp->ccode > 0) { 4229 lprintf(LOG_ERR, "Get SDR Repository Info command failed: %s", 4230 val2str(rsp->ccode, completion_code_vals)); 4231 return -1; 4232 } 4233 4234 memcpy(sdr_repository_info, 4235 rsp->data, 4236 __min(sizeof (struct get_sdr_repository_info_rsp), 4237 rsp->data_len)); 4238 4239 return 0; 4240 } 4241 4242 /* ipmi_sdr_timestamp - return string from timestamp value 4243 * 4244 * @stamp: 32bit timestamp 4245 * 4246 * returns pointer to static buffer 4247 */ 4248 static char * 4249 ipmi_sdr_timestamp(uint32_t stamp) 4250 { 4251 static char tbuf[40]; 4252 time_t s = (time_t) stamp; 4253 memset(tbuf, 0, 40); 4254 if (stamp) 4255 strftime(tbuf, sizeof (tbuf), "%m/%d/%Y %H:%M:%S", 4256 gmtime(&s)); 4257 return tbuf; 4258 } 4259 4260 /* 4261 * ipmi_sdr_print_info 4262 * 4263 * Display the return data of the GET SDR REPOSITORY INFO command 4264 * See section 33.9 of the IPMI v2 specification for details 4265 * 4266 * returns 0 on success 4267 * -1 on error 4268 */ 4269 int 4270 ipmi_sdr_print_info(struct ipmi_intf *intf) 4271 { 4272 uint32_t timestamp; 4273 uint16_t free_space; 4274 4275 struct get_sdr_repository_info_rsp sdr_repository_info; 4276 4277 if (ipmi_sdr_get_info(intf, &sdr_repository_info) != 0) 4278 return -1; 4279 4280 printf("SDR Version : 0x%x\n", 4281 sdr_repository_info.sdr_version); 4282 printf("Record Count : %d\n", 4283 (sdr_repository_info.record_count_msb << 8) | 4284 sdr_repository_info.record_count_lsb); 4285 4286 free_space = 4287 (sdr_repository_info.free_space[1] << 8) | 4288 sdr_repository_info.free_space[0]; 4289 4290 printf("Free Space : "); 4291 switch (free_space) { 4292 case 0x0000: 4293 printf("none (full)\n"); 4294 break; 4295 case 0xFFFF: 4296 printf("unspecified\n"); 4297 break; 4298 case 0xFFFE: 4299 printf("> 64Kb - 2 bytes\n"); 4300 break; 4301 default: 4302 printf("%d bytes\n", free_space); 4303 break; 4304 } 4305 4306 timestamp = 4307 (sdr_repository_info.most_recent_addition_timestamp[3] << 24) | 4308 (sdr_repository_info.most_recent_addition_timestamp[2] << 16) | 4309 (sdr_repository_info.most_recent_addition_timestamp[1] << 8) | 4310 sdr_repository_info.most_recent_addition_timestamp[0]; 4311 printf("Most recent Addition : %s\n", 4312 ipmi_sdr_timestamp(timestamp)); 4313 4314 timestamp = 4315 (sdr_repository_info.most_recent_erase_timestamp[3] << 24) | 4316 (sdr_repository_info.most_recent_erase_timestamp[2] << 16) | 4317 (sdr_repository_info.most_recent_erase_timestamp[1] << 8) | 4318 sdr_repository_info.most_recent_erase_timestamp[0]; 4319 printf("Most recent Erase : %s\n", 4320 ipmi_sdr_timestamp(timestamp)); 4321 4322 printf("SDR overflow : %s\n", 4323 (sdr_repository_info.overflow_flag ? "yes" : "no")); 4324 4325 printf("SDR Repository Update Support : "); 4326 switch (sdr_repository_info.modal_update_support) { 4327 case 0: 4328 printf("unspecified\n"); 4329 break; 4330 case 1: 4331 printf("non-modal\n"); 4332 break; 4333 case 2: 4334 printf("modal\n"); 4335 break; 4336 case 3: 4337 printf("modal and non-modal\n"); 4338 break; 4339 default: 4340 printf("error in response\n"); 4341 break; 4342 } 4343 4344 printf("Delete SDR supported : %s\n", 4345 sdr_repository_info.delete_sdr_supported ? "yes" : "no"); 4346 printf("Partial Add SDR supported : %s\n", 4347 sdr_repository_info.partial_add_sdr_supported ? "yes" : "no"); 4348 printf("Reserve SDR repository supported : %s\n", 4349 sdr_repository_info. 4350 reserve_sdr_repository_supported ? "yes" : "no"); 4351 printf("SDR Repository Alloc info supported : %s\n", 4352 sdr_repository_info. 4353 get_sdr_repository_allo_info_supported ? "yes" : "no"); 4354 4355 return 0; 4356 } 4357 4358 /* ipmi_sdr_dump_bin - Write raw SDR to binary file 4359 * 4360 * used for post-processing by other utilities 4361 * 4362 * @intf: ipmi interface 4363 * @ofile: output filename 4364 * 4365 * returns 0 on success 4366 * returns -1 on error 4367 */ 4368 static int 4369 ipmi_sdr_dump_bin(struct ipmi_intf *intf, const char *ofile) 4370 { 4371 struct sdr_get_rs *header; 4372 struct ipmi_sdr_iterator *itr; 4373 struct sdr_record_list *sdrr; 4374 FILE *fp; 4375 int rc = 0; 4376 4377 /* open connection to SDR */ 4378 itr = ipmi_sdr_start(intf, 0); 4379 if (itr == NULL) { 4380 lprintf(LOG_ERR, "Unable to open SDR for reading"); 4381 return -1; 4382 } 4383 4384 printf("Dumping Sensor Data Repository to '%s'\n", ofile); 4385 4386 /* generate list of records */ 4387 while ((header = ipmi_sdr_get_next_header(intf, itr)) != NULL) { 4388 sdrr = malloc(sizeof(struct sdr_record_list)); 4389 if (sdrr == NULL) { 4390 lprintf(LOG_ERR, "ipmitool: malloc failure"); 4391 return -1; 4392 } 4393 memset(sdrr, 0, sizeof(struct sdr_record_list)); 4394 4395 lprintf(LOG_INFO, "Record ID %04x (%d bytes)", 4396 header->id, header->length); 4397 4398 sdrr->id = header->id; 4399 sdrr->version = header->version; 4400 sdrr->type = header->type; 4401 sdrr->length = header->length; 4402 sdrr->raw = ipmi_sdr_get_record(intf, header, itr); 4403 4404 if (sdrr->raw == NULL) { 4405 lprintf(LOG_ERR, "ipmitool: cannot obtain SDR record %04x", header->id); 4406 if (sdrr != NULL) { 4407 free(sdrr); 4408 sdrr = NULL; 4409 } 4410 return -1; 4411 } 4412 4413 if (sdr_list_head == NULL) 4414 sdr_list_head = sdrr; 4415 else 4416 sdr_list_tail->next = sdrr; 4417 4418 sdr_list_tail = sdrr; 4419 } 4420 4421 ipmi_sdr_end(intf, itr); 4422 4423 /* now write to file */ 4424 fp = ipmi_open_file_write(ofile); 4425 if (fp == NULL) 4426 return -1; 4427 4428 for (sdrr = sdr_list_head; sdrr != NULL; sdrr = sdrr->next) { 4429 int r; 4430 uint8_t h[5]; 4431 4432 /* build and write sdr header */ 4433 h[0] = sdrr->id & 0xff; // LS Byte first 4434 h[1] = (sdrr->id >> 8) & 0xff; 4435 h[2] = sdrr->version; 4436 h[3] = sdrr->type; 4437 h[4] = sdrr->length; 4438 4439 r = fwrite(h, 1, 5, fp); 4440 if (r != 5) { 4441 lprintf(LOG_ERR, "Error writing header " 4442 "to output file %s", ofile); 4443 rc = -1; 4444 break; 4445 } 4446 4447 /* write sdr entry */ 4448 if (!sdrr->raw) { 4449 lprintf(LOG_ERR, "Error: raw data is null (length=%d)", 4450 sdrr->length); 4451 rc = -1; 4452 break; 4453 } 4454 r = fwrite(sdrr->raw, 1, sdrr->length, fp); 4455 if (r != sdrr->length) { 4456 lprintf(LOG_ERR, "Error writing %d record bytes " 4457 "to output file %s", sdrr->length, ofile); 4458 rc = -1; 4459 break; 4460 } 4461 } 4462 fclose(fp); 4463 4464 return rc; 4465 } 4466 4467 /* ipmi_sdr_print_type - print all sensors of specified type 4468 * 4469 * @intf: ipmi interface 4470 * @type: sensor type 4471 * 4472 * returns 0 on success 4473 * returns -1 on error 4474 */ 4475 int 4476 ipmi_sdr_print_type(struct ipmi_intf *intf, char *type) 4477 { 4478 struct sdr_record_list *list, *entry; 4479 int rc = 0; 4480 int x; 4481 uint8_t sensor_type = 0; 4482 4483 if (type == NULL || 4484 strncasecmp(type, "help", 4) == 0 || 4485 strncasecmp(type, "list", 4) == 0) { 4486 printf("Sensor Types:\n"); 4487 for (x = 1; x < SENSOR_TYPE_MAX; x += 2) { 4488 printf("\t%-25s (0x%02x) %-25s (0x%02x)\n", 4489 sensor_type_desc[x], x, 4490 sensor_type_desc[x + 1], x + 1); 4491 } 4492 return 0; 4493 } 4494 4495 if (strncmp(type, "0x", 2) == 0) { 4496 /* begins with 0x so let it be entered as raw hex value */ 4497 if (str2uchar(type, &sensor_type) != 0) { 4498 lprintf(LOG_ERR, 4499 "Given type of sensor \"%s\" is either invalid or out of range.", 4500 type); 4501 return (-1); 4502 } 4503 } else { 4504 for (x = 1; x < SENSOR_TYPE_MAX; x++) { 4505 if (strncasecmp(sensor_type_desc[x], type, 4506 __maxlen(type, 4507 sensor_type_desc[x])) == 0) { 4508 sensor_type = x; 4509 break; 4510 } 4511 } 4512 if (sensor_type != x) { 4513 lprintf(LOG_ERR, "Sensor Type \"%s\" not found.", 4514 type); 4515 printf("Sensor Types:\n"); 4516 for (x = 1; x < SENSOR_TYPE_MAX; x += 2) { 4517 printf("\t%-25s (0x%02x) %-25s (0x%02x)\n", 4518 sensor_type_desc[x], x, 4519 sensor_type_desc[x + 1], x + 1); 4520 } 4521 return 0; 4522 } 4523 } 4524 4525 list = ipmi_sdr_find_sdr_bysensortype(intf, sensor_type); 4526 4527 for (entry = list; entry != NULL; entry = entry->next) { 4528 rc = ipmi_sdr_print_listentry(intf, entry); 4529 } 4530 4531 __sdr_list_empty(list); 4532 4533 return rc; 4534 } 4535 4536 /* ipmi_sdr_print_entity - print entity's for an id/instance 4537 * 4538 * @intf: ipmi interface 4539 * @entitystr: entity id/instance string, i.e. "1.1" 4540 * 4541 * returns 0 on success 4542 * returns -1 on error 4543 */ 4544 int 4545 ipmi_sdr_print_entity(struct ipmi_intf *intf, char *entitystr) 4546 { 4547 struct sdr_record_list *list, *entry; 4548 struct entity_id entity; 4549 unsigned id = 0; 4550 unsigned instance = 0; 4551 int rc = 0; 4552 4553 if (entitystr == NULL || 4554 strncasecmp(entitystr, "help", 4) == 0 || 4555 strncasecmp(entitystr, "list", 4) == 0) { 4556 print_valstr_2col(entity_id_vals, "Entity IDs", -1); 4557 return 0; 4558 } 4559 4560 if (sscanf(entitystr, "%u.%u", &id, &instance) != 2) { 4561 /* perhaps no instance was passed 4562 * in which case we want all instances for this entity 4563 * so set entity.instance = 0x7f to indicate this 4564 */ 4565 if (sscanf(entitystr, "%u", &id) != 1) { 4566 int i, j=0; 4567 4568 /* now try string input */ 4569 for (i = 0; entity_id_vals[i].str != NULL; i++) { 4570 if (strncasecmp(entitystr, entity_id_vals[i].str, 4571 __maxlen(entitystr, entity_id_vals[i].str)) == 0) { 4572 entity.id = entity_id_vals[i].val; 4573 entity.instance = 0x7f; 4574 j=1; 4575 } 4576 } 4577 if (j == 0) { 4578 lprintf(LOG_ERR, "Invalid entity: %s", entitystr); 4579 return -1; 4580 } 4581 } else { 4582 entity.id = id; 4583 entity.instance = 0x7f; 4584 } 4585 } else { 4586 entity.id = id; 4587 entity.instance = instance; 4588 } 4589 4590 list = ipmi_sdr_find_sdr_byentity(intf, &entity); 4591 4592 for (entry = list; entry != NULL; entry = entry->next) { 4593 rc = ipmi_sdr_print_listentry(intf, entry); 4594 } 4595 4596 __sdr_list_empty(list); 4597 4598 return rc; 4599 } 4600 4601 /* ipmi_sdr_print_entry_byid - print sdr entries identified by sensor id 4602 * 4603 * @intf: ipmi interface 4604 * @argc: number of entries to print 4605 * @argv: list of sensor ids 4606 * 4607 * returns 0 on success 4608 * returns -1 on error 4609 */ 4610 static int 4611 ipmi_sdr_print_entry_byid(struct ipmi_intf *intf, int argc, char **argv) 4612 { 4613 struct sdr_record_list *sdr; 4614 int rc = 0; 4615 int v, i; 4616 4617 if (argc < 1) { 4618 lprintf(LOG_ERR, "No Sensor ID supplied"); 4619 return -1; 4620 } 4621 4622 v = verbose; 4623 verbose = 1; 4624 4625 for (i = 0; i < argc; i++) { 4626 sdr = ipmi_sdr_find_sdr_byid(intf, argv[i]); 4627 if (sdr == NULL) { 4628 lprintf(LOG_ERR, "Unable to find sensor id '%s'", 4629 argv[i]); 4630 } else { 4631 if (ipmi_sdr_print_listentry(intf, sdr) < 0) 4632 rc = -1; 4633 } 4634 } 4635 4636 verbose = v; 4637 4638 return rc; 4639 } 4640 4641 /* ipmi_sdr_main - top-level handler for SDR subsystem 4642 * 4643 * @intf: ipmi interface 4644 * @argc: number of arguments 4645 * @argv: argument list 4646 * 4647 * returns 0 on success 4648 * returns -1 on error 4649 */ 4650 int 4651 ipmi_sdr_main(struct ipmi_intf *intf, int argc, char **argv) 4652 { 4653 int rc = 0; 4654 4655 /* initialize random numbers used later */ 4656 srand(time(NULL)); 4657 4658 if (argc == 0) 4659 return ipmi_sdr_print_sdr(intf, 0xfe); 4660 else if (strncmp(argv[0], "help", 4) == 0) { 4661 printf_sdr_usage(); 4662 } else if (strncmp(argv[0], "list", 4) == 0 4663 || strncmp(argv[0], "elist", 5) == 0) { 4664 4665 if (strncmp(argv[0], "elist", 5) == 0) 4666 sdr_extended = 1; 4667 else 4668 sdr_extended = 0; 4669 4670 if (argc <= 1) 4671 rc = ipmi_sdr_print_sdr(intf, 0xfe); 4672 else if (strncmp(argv[1], "all", 3) == 0) 4673 rc = ipmi_sdr_print_sdr(intf, 0xff); 4674 else if (strncmp(argv[1], "full", 4) == 0) 4675 rc = ipmi_sdr_print_sdr(intf, 4676 SDR_RECORD_TYPE_FULL_SENSOR); 4677 else if (strncmp(argv[1], "compact", 7) == 0) 4678 rc = ipmi_sdr_print_sdr(intf, 4679 SDR_RECORD_TYPE_COMPACT_SENSOR); 4680 else if (strncmp(argv[1], "event", 5) == 0) 4681 rc = ipmi_sdr_print_sdr(intf, 4682 SDR_RECORD_TYPE_EVENTONLY_SENSOR); 4683 else if (strncmp(argv[1], "mcloc", 5) == 0) 4684 rc = ipmi_sdr_print_sdr(intf, 4685 SDR_RECORD_TYPE_MC_DEVICE_LOCATOR); 4686 else if (strncmp(argv[1], "fru", 3) == 0) 4687 rc = ipmi_sdr_print_sdr(intf, 4688 SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR); 4689 else if (strncmp(argv[1], "generic", 7) == 0) 4690 rc = ipmi_sdr_print_sdr(intf, 4691 SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR); 4692 else if (strcmp(argv[1], "help") == 0) { 4693 lprintf(LOG_NOTICE, 4694 "usage: sdr %s [all|full|compact|event|mcloc|fru|generic]", 4695 argv[0]); 4696 return 0; 4697 } 4698 else { 4699 lprintf(LOG_ERR, 4700 "Invalid SDR %s command: %s", 4701 argv[0], argv[1]); 4702 lprintf(LOG_NOTICE, 4703 "usage: sdr %s [all|full|compact|event|mcloc|fru|generic]", 4704 argv[0]); 4705 return (-1); 4706 } 4707 } else if (strncmp(argv[0], "type", 4) == 0) { 4708 sdr_extended = 1; 4709 rc = ipmi_sdr_print_type(intf, argv[1]); 4710 } else if (strncmp(argv[0], "entity", 6) == 0) { 4711 sdr_extended = 1; 4712 rc = ipmi_sdr_print_entity(intf, argv[1]); 4713 } else if (strncmp(argv[0], "info", 4) == 0) { 4714 rc = ipmi_sdr_print_info(intf); 4715 } else if (strncmp(argv[0], "get", 3) == 0) { 4716 rc = ipmi_sdr_print_entry_byid(intf, argc - 1, &argv[1]); 4717 } else if (strncmp(argv[0], "dump", 4) == 0) { 4718 if (argc < 2) { 4719 lprintf(LOG_ERR, "Not enough parameters given."); 4720 lprintf(LOG_NOTICE, "usage: sdr dump <file>"); 4721 return (-1); 4722 } 4723 rc = ipmi_sdr_dump_bin(intf, argv[1]); 4724 } else if (strncmp(argv[0], "fill", 4) == 0) { 4725 if (argc <= 1) { 4726 lprintf(LOG_ERR, "Not enough parameters given."); 4727 lprintf(LOG_NOTICE, "usage: sdr fill sensors"); 4728 lprintf(LOG_NOTICE, "usage: sdr fill file <file>"); 4729 lprintf(LOG_NOTICE, "usage: sdr fill range <range>"); 4730 return (-1); 4731 } else if (strncmp(argv[1], "sensors", 7) == 0) { 4732 rc = ipmi_sdr_add_from_sensors(intf, 21); 4733 } else if (strncmp(argv[1], "nosat", 5) == 0) { 4734 rc = ipmi_sdr_add_from_sensors(intf, 0); 4735 } else if (strncmp(argv[1], "file", 4) == 0) { 4736 if (argc < 3) { 4737 lprintf(LOG_ERR, 4738 "Not enough parameters given."); 4739 lprintf(LOG_NOTICE, 4740 "usage: sdr fill file <file>"); 4741 return (-1); 4742 } 4743 rc = ipmi_sdr_add_from_file(intf, argv[2]); 4744 } else if (strncmp(argv[1], "range", 4) == 0) { 4745 if (argc < 3) { 4746 lprintf(LOG_ERR, 4747 "Not enough parameters given."); 4748 lprintf(LOG_NOTICE, 4749 "usage: sdr fill range <range>"); 4750 return (-1); 4751 } 4752 rc = ipmi_sdr_add_from_list(intf, argv[2]); 4753 } else { 4754 lprintf(LOG_ERR, 4755 "Invalid SDR %s command: %s", 4756 argv[0], argv[1]); 4757 lprintf(LOG_NOTICE, 4758 "usage: sdr %s <sensors|nosat|file|range> [options]", 4759 argv[0]); 4760 return (-1); 4761 } 4762 } else { 4763 lprintf(LOG_ERR, "Invalid SDR command: %s", argv[0]); 4764 rc = -1; 4765 } 4766 4767 return rc; 4768 } 4769 4770 void 4771 printf_sdr_usage() 4772 { 4773 lprintf(LOG_NOTICE, 4774 "usage: sdr <command> [options]"); 4775 lprintf(LOG_NOTICE, 4776 " list | elist [option]"); 4777 lprintf(LOG_NOTICE, 4778 " all All SDR Records"); 4779 lprintf(LOG_NOTICE, 4780 " full Full Sensor Record"); 4781 lprintf(LOG_NOTICE, 4782 " compact Compact Sensor Record"); 4783 lprintf(LOG_NOTICE, 4784 " event Event-Only Sensor Record"); 4785 lprintf(LOG_NOTICE, 4786 " mcloc Management Controller Locator Record"); 4787 lprintf(LOG_NOTICE, 4788 " fru FRU Locator Record"); 4789 lprintf(LOG_NOTICE, 4790 " generic Generic Device Locator Record\n"); 4791 lprintf(LOG_NOTICE, 4792 " type [option]"); 4793 lprintf(LOG_NOTICE, 4794 " <Sensor_Type> Retrieve the state of specified sensor."); 4795 lprintf(LOG_NOTICE, 4796 " Sensor_Type can be specified either as"); 4797 lprintf(LOG_NOTICE, 4798 " a string or a hex value."); 4799 lprintf(LOG_NOTICE, 4800 " list Get a list of available sensor types\n"); 4801 lprintf(LOG_NOTICE, 4802 " get <Sensor_ID>"); 4803 lprintf(LOG_NOTICE, 4804 " Retrieve state of the first sensor matched by Sensor_ID\n"); 4805 lprintf(LOG_NOTICE, 4806 " info"); 4807 lprintf(LOG_NOTICE, 4808 " Display information about the repository itself\n"); 4809 lprintf(LOG_NOTICE, 4810 " entity <Entity_ID>[.<Instance_ID>]"); 4811 lprintf(LOG_NOTICE, 4812 " Display all sensors associated with an entity\n"); 4813 lprintf(LOG_NOTICE, 4814 " dump <file>"); 4815 lprintf(LOG_NOTICE, 4816 " Dump raw SDR data to a file\n"); 4817 lprintf(LOG_NOTICE, 4818 " fill <option>"); 4819 lprintf(LOG_NOTICE, 4820 " sensors Creates the SDR repository for the current"); 4821 lprintf(LOG_NOTICE, 4822 " configuration"); 4823 lprintf(LOG_NOTICE, 4824 " nosat Creates the SDR repository for the current"); 4825 lprintf(LOG_NOTICE, 4826 " configuration, without satellite scan"); 4827 lprintf(LOG_NOTICE, 4828 " file <file> Load SDR repository from a file"); 4829 lprintf(LOG_NOTICE, 4830 " range <range> Load SDR repository from a provided list"); 4831 lprintf(LOG_NOTICE, 4832 " or range. Use ',' for list or '-' for"); 4833 lprintf(LOG_NOTICE, 4834 " range, eg. 0x28,0x32,0x40-0x44"); 4835 } 4836