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 *
ipmi_sdr_get_unit_string(uint8_t pct,uint8_t type,uint8_t base,uint8_t modifier)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
sdr_sensor_has_analog_reading(struct ipmi_intf * intf,struct sensor_reading * sr)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
sdr_convert_sensor_reading(struct sdr_record_full_sensor * sensor,uint8_t val)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
sdr_convert_sensor_hysterisis(struct sdr_record_full_sensor * sensor,uint8_t val)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
sdr_convert_sensor_tolerance(struct sdr_record_full_sensor * sensor,uint8_t val)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
sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor * sensor,double val)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 *
ipmi_sdr_get_sensor_thresholds(struct ipmi_intf * intf,uint8_t sensor,uint8_t target,uint8_t lun,uint8_t channel)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 *
ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf * intf,uint8_t sensor,uint8_t target,uint8_t lun,uint8_t channel)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 *
ipmi_sdr_get_sensor_reading(struct ipmi_intf * intf,uint8_t sensor)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 *
ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf * intf,uint8_t sensor,uint8_t target,uint8_t lun,uint8_t channel)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 *
ipmi_sdr_get_sensor_event_status(struct ipmi_intf * intf,uint8_t sensor,uint8_t target,uint8_t lun,uint8_t channel)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 *
ipmi_sdr_get_sensor_event_enable(struct ipmi_intf * intf,uint8_t sensor,uint8_t target,uint8_t lun,uint8_t channel)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 *
ipmi_sdr_get_sensor_type_desc(const uint8_t type)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 *
ipmi_sdr_get_thresh_status(struct sensor_reading * sr,const char * invalidstr)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 *
ipmi_sdr_get_header(struct ipmi_intf * intf,struct ipmi_sdr_iterator * itr)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 *
ipmi_sdr_get_next_header(struct ipmi_intf * intf,struct ipmi_sdr_iterator * itr)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
ipmi_sdr_print_sensor_event_status(struct ipmi_intf * intf,uint8_t sensor_num,uint8_t sensor_type,uint8_t event_type,int numeric_fmt,uint8_t target,uint8_t lun,uint8_t channel)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
ipmi_sdr_print_sensor_mask(struct sdr_record_mask * mask,uint8_t sensor_type,uint8_t event_type,int numeric_fmt)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
ipmi_sdr_print_sensor_event_enable(struct ipmi_intf * intf,uint8_t sensor_num,uint8_t sensor_type,uint8_t event_type,int numeric_fmt,uint8_t target,uint8_t lun,uint8_t channel)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
ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor * sensor,struct sdr_record_full_sensor * full,uint8_t hysteresis_value,const char * hvstr)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
print_sensor_min_max(struct sdr_record_full_sensor * full)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
print_csv_discrete(struct sdr_record_common_sensor * sensor,const struct sensor_reading * sr)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 *
ipmi_sdr_read_sensor_value(struct ipmi_intf * intf,struct sdr_record_common_sensor * sensor,uint8_t sdr_record_type,int precision)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
ipmi_sdr_print_sensor_fc(struct ipmi_intf * intf,struct sdr_record_common_sensor * sensor,uint8_t sdr_record_type)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
get_offset(uint8_t x)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
ipmi_sdr_print_discrete_state_mini(const char * header,const char * separator,uint8_t sensor_type,uint8_t event_type,uint8_t state1,uint8_t state2)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
ipmi_sdr_print_discrete_state(const char * desc,uint8_t sensor_type,uint8_t event_type,uint8_t state1,uint8_t state2)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
ipmi_sdr_print_sensor_eventonly(struct ipmi_intf * intf,struct sdr_record_eventonly_sensor * sensor)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
ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf * intf,struct sdr_record_mc_locator * mc)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
ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf * intf,struct sdr_record_generic_locator * dev)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
ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf * intf,struct sdr_record_fru_locator * fru)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
ipmi_sdr_print_sensor_entity_assoc(struct ipmi_intf * intf,struct sdr_record_entity_assoc * assoc)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
ipmi_sdr_print_sensor_oem_intel(struct ipmi_intf * intf,struct sdr_record_oem * oem)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
ipmi_sdr_print_sensor_oem(struct ipmi_intf * intf,struct sdr_record_oem * oem)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
ipmi_sdr_print_name_from_rawentry(struct ipmi_intf * intf,uint16_t id,uint8_t type,uint8_t * raw)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
ipmi_sdr_print_rawentry(struct ipmi_intf * intf,uint8_t type,uint8_t * raw,int len)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
ipmi_sdr_print_listentry(struct ipmi_intf * intf,struct sdr_record_list * entry)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
ipmi_sdr_print_sdr(struct ipmi_intf * intf,uint8_t type)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
ipmi_sdr_get_reservation(struct ipmi_intf * intf,int use_builtin,uint16_t * reserve_id)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 *
ipmi_sdr_start(struct ipmi_intf * intf,int use_builtin)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 *
ipmi_sdr_get_record(struct ipmi_intf * intf,struct sdr_get_rs * header,struct ipmi_sdr_iterator * itr)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
ipmi_sdr_end(struct ipmi_intf * intf,struct ipmi_sdr_iterator * itr)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
__sdr_list_add(struct sdr_record_list * head,struct sdr_record_list * entry)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
__sdr_list_empty(struct sdr_record_list * head)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
ipmi_sdr_list_empty(struct ipmi_intf * intf)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 *
ipmi_sdr_find_sdr_bynumtype(struct ipmi_intf * intf,uint16_t gen_id,uint8_t num,uint8_t type)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 *
ipmi_sdr_find_sdr_bysensortype(struct ipmi_intf * intf,uint8_t type)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 *
ipmi_sdr_find_sdr_byentity(struct ipmi_intf * intf,struct entity_id * entity)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 *
ipmi_sdr_find_sdr_bytype(struct ipmi_intf * intf,uint8_t type)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 *
ipmi_sdr_find_sdr_byid(struct ipmi_intf * intf,char * id)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
ipmi_sdr_list_cache_fromfile(struct ipmi_intf * intf,const char * ifile)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
ipmi_sdr_list_cache(struct ipmi_intf * intf)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
ipmi_sdr_get_info(struct ipmi_intf * intf,struct get_sdr_repository_info_rsp * sdr_repository_info)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 *
ipmi_sdr_timestamp(uint32_t stamp)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
ipmi_sdr_print_info(struct ipmi_intf * intf)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
ipmi_sdr_dump_bin(struct ipmi_intf * intf,const char * ofile)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
ipmi_sdr_print_type(struct ipmi_intf * intf,char * type)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
ipmi_sdr_print_entity(struct ipmi_intf * intf,char * entitystr)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
ipmi_sdr_print_entry_byid(struct ipmi_intf * intf,int argc,char ** argv)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
ipmi_sdr_main(struct ipmi_intf * intf,int argc,char ** argv)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
printf_sdr_usage()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