1 /*
2  * Copyright (c) 2003 Sun Microsystems, Inc.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * Redistribution of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * Redistribution in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * Neither the name of Sun Microsystems, Inc. or the names of
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * This software is provided "AS IS," without a warranty of any kind.
20  * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
21  * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
22  * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
23  * SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE
24  * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
25  * OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.  IN NO EVENT WILL
26  * SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA,
27  * OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR
28  * PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF
29  * LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  */
32 
33 #ifndef IPMI_SDR_H
34 #define IPMI_SDR_H
35 
36 #if HAVE_CONFIG_H
37 # include <config.h>
38 #endif
39 
40 #include <inttypes.h>
41 #include <math.h>
42 #include <ipmitool/bswap.h>
43 #include <ipmitool/ipmi.h>
44 #include <ipmitool/ipmi_entity.h>
45 
46 int ipmi_sdr_main(struct ipmi_intf *, int, char **);
47 
48 #define tos32(val, bits)    ((val & ((1<<((bits)-1)))) ? (-((val) & (1<<((bits)-1))) | (val)) : (val))
49 
50 #if WORDS_BIGENDIAN
51 # define __TO_TOL(mtol)     (uint16_t)(mtol & 0x3f)
52 # define __TO_M(mtol)       (int16_t)(tos32((((mtol & 0xff00) >> 8) | ((mtol & 0xc0) << 2)), 10))
53 # define __TO_B(bacc)       (int32_t)(tos32((((bacc & 0xff000000) >> 24) | ((bacc & 0xc00000) >> 14)), 10))
54 # define __TO_ACC(bacc)     (uint32_t)(((bacc & 0x3f0000) >> 16) | ((bacc & 0xf000) >> 6))
55 # define __TO_ACC_EXP(bacc) (uint32_t)((bacc & 0xc00) >> 10)
56 # define __TO_R_EXP(bacc)   (int32_t)(tos32(((bacc & 0xf0) >> 4), 4))
57 # define __TO_B_EXP(bacc)   (int32_t)(tos32((bacc & 0xf), 4))
58 #else
59 # define __TO_TOL(mtol)     (uint16_t)(BSWAP_16(mtol) & 0x3f)
60 # define __TO_M(mtol)       (int16_t)(tos32((((BSWAP_16(mtol) & 0xff00) >> 8) | ((BSWAP_16(mtol) & 0xc0) << 2)), 10))
61 # define __TO_B(bacc)       (int32_t)(tos32((((BSWAP_32(bacc) & 0xff000000) >> 24) | \
62                             ((BSWAP_32(bacc) & 0xc00000) >> 14)), 10))
63 # define __TO_ACC(bacc)     (uint32_t)(((BSWAP_32(bacc) & 0x3f0000) >> 16) | ((BSWAP_32(bacc) & 0xf000) >> 6))
64 # define __TO_ACC_EXP(bacc) (uint32_t)((BSWAP_32(bacc) & 0xc00) >> 10)
65 # define __TO_R_EXP(bacc)   (int32_t)(tos32(((BSWAP_32(bacc) & 0xf0) >> 4), 4))
66 # define __TO_B_EXP(bacc)   (int32_t)(tos32((BSWAP_32(bacc) & 0xf), 4))
67 #endif
68 
69 enum {
70 	ANALOG_SENSOR,
71 	DISCRETE_SENSOR,
72 };
73 
74 #define READING_UNAVAILABLE	0x20
75 #define SCANNING_DISABLED	0x40
76 #define EVENT_MSG_DISABLED	0x80
77 
78 #define IS_READING_UNAVAILABLE(val)	((val) & READING_UNAVAILABLE)
79 #define IS_SCANNING_DISABLED(val)	(!((val) & SCANNING_DISABLED))
80 #define IS_EVENT_MSG_DISABLED(val)	(!((val) & EVENT_MSG_DISABLED))
81 
82 #define GET_SDR_REPO_INFO	0x20
83 #define GET_SDR_ALLOC_INFO	0x21
84 
85 #define SDR_SENSOR_STAT_LO_NC	(1<<0)
86 #define SDR_SENSOR_STAT_LO_CR	(1<<1)
87 #define SDR_SENSOR_STAT_LO_NR	(1<<2)
88 #define SDR_SENSOR_STAT_HI_NC	(1<<3)
89 #define SDR_SENSOR_STAT_HI_CR	(1<<4)
90 #define SDR_SENSOR_STAT_HI_NR	(1<<5)
91 
92 #define GET_DEVICE_SDR_INFO      0x20
93 #define GET_DEVICE_SDR           0x21
94 #define GET_SENSOR_FACTORS      0x23
95 #define GET_SENSOR_FACTORS      0x23
96 #define SET_SENSOR_HYSTERESIS	0x24
97 #define GET_SENSOR_HYSTERESIS	0x25
98 #define SET_SENSOR_THRESHOLDS   0x26
99 #define GET_SENSOR_THRESHOLDS   0x27
100 #define SET_SENSOR_EVENT_ENABLE	0x28
101 #define GET_SENSOR_EVENT_ENABLE 0x29
102 #define GET_SENSOR_EVENT_STATUS	0x2b
103 #define GET_SENSOR_READING	0x2d
104 #define GET_SENSOR_TYPE		0x2f
105 
106 #ifdef HAVE_PRAGMA_PACK
107 #pragma pack(1)
108 #endif
109 struct sdr_repo_info_rs {
110 	uint8_t version;	/* SDR version (51h) */
111 	uint16_t count;		/* number of records */
112 	uint16_t free;		/* free space in SDR */
113 	uint32_t add_stamp;	/* last add timestamp */
114 	uint32_t erase_stamp;	/* last del timestamp */
115 	uint8_t op_support;	/* supported operations */
116 } ATTRIBUTE_PACKING;
117 #ifdef HAVE_PRAGMA_PACK
118 #pragma pack(0)
119 #endif
120 
121 #ifdef HAVE_PRAGMA_PACK
122 #pragma pack(1)
123 #endif
124 /* builtin (device) sdrs support */
125 struct sdr_device_info_rs {
126 	unsigned char count;	/* number of records */
127 	unsigned char flags;	/* flags */
128 	unsigned char popChangeInd[3];	/* free space in SDR */
129 } ATTRIBUTE_PACKING;
130 #ifdef HAVE_PRAGMA_PACK
131 #pragma pack(0)
132 #endif
133 
134 #ifdef HAVE_PRAGMA_PACK
135 #pragma pack(1)
136 #endif
137 #define GET_SDR_RESERVE_REPO	0x22
138 struct sdr_reserve_repo_rs {
139 	uint16_t reserve_id;	/* reservation ID */
140 } ATTRIBUTE_PACKING;
141 #ifdef HAVE_PRAGMA_PACK
142 #pragma pack(0)
143 #endif
144 
145 
146 #ifdef HAVE_PRAGMA_PACK
147 #pragma pack(1)
148 #endif
149 #define GET_SDR		0x23
150 struct sdr_get_rq {
151 	uint16_t reserve_id;	/* reservation ID */
152 	uint16_t id;		/* record ID */
153 	uint8_t offset;		/* offset into SDR */
154 #define GET_SDR_ENTIRE_RECORD	0xff
155 	uint8_t length;		/* length to read */
156 } ATTRIBUTE_PACKING;
157 #ifdef HAVE_PRAGMA_PACK
158 #pragma pack(0)
159 #endif
160 
161 #ifdef HAVE_PRAGMA_PACK
162 #pragma pack(1)
163 #endif
164 struct sdr_get_rs {
165 	uint16_t next;		/* next record id */
166 	uint16_t id;		/* record ID */
167 	uint8_t version;	/* SDR version (51h) */
168 #define SDR_RECORD_TYPE_FULL_SENSOR		0x01
169 #define SDR_RECORD_TYPE_COMPACT_SENSOR		0x02
170 #define SDR_RECORD_TYPE_EVENTONLY_SENSOR	0x03
171 #define SDR_RECORD_TYPE_ENTITY_ASSOC		0x08
172 #define SDR_RECORD_TYPE_DEVICE_ENTITY_ASSOC	0x09
173 #define SDR_RECORD_TYPE_GENERIC_DEVICE_LOCATOR	0x10
174 #define SDR_RECORD_TYPE_FRU_DEVICE_LOCATOR	0x11
175 #define SDR_RECORD_TYPE_MC_DEVICE_LOCATOR	0x12
176 #define SDR_RECORD_TYPE_MC_CONFIRMATION		0x13
177 #define SDR_RECORD_TYPE_BMC_MSG_CHANNEL_INFO	0x14
178 #define SDR_RECORD_TYPE_OEM			0xc0
179 	uint8_t type;		/* record type */
180 	uint8_t length;		/* remaining record bytes */
181 } ATTRIBUTE_PACKING;
182 #ifdef HAVE_PRAGMA_PACK
183 #pragma pack(0)
184 #endif
185 
186 #ifdef HAVE_PRAGMA_PACK
187 #pragma pack(1)
188 #endif
189 struct sdr_record_mask {
190 	union {
191 		struct {
192 			uint16_t assert_event;	/* assertion event mask */
193 			uint16_t deassert_event;	/* de-assertion event mask */
194 			uint16_t read;	/* discrete reading mask */
195 		} ATTRIBUTE_PACKING discrete;
196 		struct {
197 #if WORDS_BIGENDIAN
198 			uint16_t reserved:1;
199 			uint16_t status_lnr:1;
200 			uint16_t status_lcr:1;
201 			uint16_t status_lnc:1;
202 			uint16_t assert_unr_high:1;
203 			uint16_t assert_unr_low:1;
204 			uint16_t assert_ucr_high:1;
205 			uint16_t assert_ucr_low:1;
206 			uint16_t assert_unc_high:1;
207 			uint16_t assert_unc_low:1;
208 			uint16_t assert_lnr_high:1;
209 			uint16_t assert_lnr_low:1;
210 			uint16_t assert_lcr_high:1;
211 			uint16_t assert_lcr_low:1;
212 			uint16_t assert_lnc_high:1;
213 			uint16_t assert_lnc_low:1;
214 #else
215 			uint16_t assert_lnc_low:1;
216 			uint16_t assert_lnc_high:1;
217 			uint16_t assert_lcr_low:1;
218 			uint16_t assert_lcr_high:1;
219 			uint16_t assert_lnr_low:1;
220 			uint16_t assert_lnr_high:1;
221 			uint16_t assert_unc_low:1;
222 			uint16_t assert_unc_high:1;
223 			uint16_t assert_ucr_low:1;
224 			uint16_t assert_ucr_high:1;
225 			uint16_t assert_unr_low:1;
226 			uint16_t assert_unr_high:1;
227 			uint16_t status_lnc:1;
228 			uint16_t status_lcr:1;
229 			uint16_t status_lnr:1;
230 			uint16_t reserved:1;
231 #endif
232 #if WORDS_BIGENDIAN
233 			uint16_t reserved_2:1;
234 			uint16_t status_unr:1;
235 			uint16_t status_ucr:1;
236 			uint16_t status_unc:1;
237 			uint16_t deassert_unr_high:1;
238 			uint16_t deassert_unr_low:1;
239 			uint16_t deassert_ucr_high:1;
240 			uint16_t deassert_ucr_low:1;
241 			uint16_t deassert_unc_high:1;
242 			uint16_t deassert_unc_low:1;
243 			uint16_t deassert_lnr_high:1;
244 			uint16_t deassert_lnr_low:1;
245 			uint16_t deassert_lcr_high:1;
246 			uint16_t deassert_lcr_low:1;
247 			uint16_t deassert_lnc_high:1;
248 			uint16_t deassert_lnc_low:1;
249 #else
250 			uint16_t deassert_lnc_low:1;
251 			uint16_t deassert_lnc_high:1;
252 			uint16_t deassert_lcr_low:1;
253 			uint16_t deassert_lcr_high:1;
254 			uint16_t deassert_lnr_low:1;
255 			uint16_t deassert_lnr_high:1;
256 			uint16_t deassert_unc_low:1;
257 			uint16_t deassert_unc_high:1;
258 			uint16_t deassert_ucr_low:1;
259 			uint16_t deassert_ucr_high:1;
260 			uint16_t deassert_unr_low:1;
261 			uint16_t deassert_unr_high:1;
262 			uint16_t status_unc:1;
263 			uint16_t status_ucr:1;
264 			uint16_t status_unr:1;
265 			uint16_t reserved_2:1;
266 #endif
267 			union {
268 				struct {
269 #if WORDS_BIGENDIAN			/* settable threshold mask */
270 					uint16_t reserved:2;
271 					uint16_t unr:1;
272 					uint16_t ucr:1;
273 					uint16_t unc:1;
274 					uint16_t lnr:1;
275 					uint16_t lcr:1;
276 					uint16_t lnc:1;
277 					/* padding lower 8 bits */
278 					uint16_t readable:8;
279 #else
280 					uint16_t readable:8;
281 					uint16_t lnc:1;
282 					uint16_t lcr:1;
283 					uint16_t lnr:1;
284 					uint16_t unc:1;
285 					uint16_t ucr:1;
286 					uint16_t unr:1;
287 					uint16_t reserved:2;
288 #endif
289 				} ATTRIBUTE_PACKING set;
290 				struct {
291 #if WORDS_BIGENDIAN			/* readable threshold mask */
292 					/* padding upper 8 bits */
293 					uint16_t settable:8;
294 					uint16_t reserved:2;
295 					uint16_t unr:1;
296 					uint16_t ucr:1;
297 					uint16_t unc:1;
298 					uint16_t lnr:1;
299 					uint16_t lcr:1;
300 					uint16_t lnc:1;
301 #else
302 					uint16_t lnc:1;
303 					uint16_t lcr:1;
304 					uint16_t lnr:1;
305 					uint16_t unc:1;
306 					uint16_t ucr:1;
307 					uint16_t unr:1;
308 					uint16_t reserved:2;
309 					uint16_t settable:8;
310 #endif
311 				} ATTRIBUTE_PACKING read;
312 			} ATTRIBUTE_PACKING;
313 		} ATTRIBUTE_PACKING threshold;
314 	} ATTRIBUTE_PACKING type;
315 } ATTRIBUTE_PACKING;
316 #ifdef HAVE_PRAGMA_PACK
317 #pragma pack(0)
318 #endif
319 
320 #ifdef HAVE_PRAGMA_PACK
321 #pragma pack(1)
322 #endif
323 struct sdr_record_common_sensor {
324 	struct {
325 		uint8_t owner_id;
326 #if WORDS_BIGENDIAN
327 		uint8_t channel:4;	/* channel number */
328 		uint8_t __reserved:2;
329 		uint8_t lun:2;	/* sensor owner lun */
330 #else
331 		uint8_t lun:2;	/* sensor owner lun */
332 		uint8_t __reserved:2;
333 		uint8_t channel:4;	/* channel number */
334 #endif
335 		uint8_t sensor_num;	/* unique sensor number */
336 	} ATTRIBUTE_PACKING keys;
337 
338 	struct entity_id entity;
339 
340 	struct {
341 		struct {
342 #if WORDS_BIGENDIAN
343 			uint8_t __reserved:1;
344 			uint8_t scanning:1;
345 			uint8_t events:1;
346 			uint8_t thresholds:1;
347 			uint8_t hysteresis:1;
348 			uint8_t type:1;
349 			uint8_t event_gen:1;
350 			uint8_t sensor_scan:1;
351 #else
352 			uint8_t sensor_scan:1;
353 			uint8_t event_gen:1;
354 			uint8_t type:1;
355 			uint8_t hysteresis:1;
356 			uint8_t thresholds:1;
357 			uint8_t events:1;
358 			uint8_t scanning:1;
359 			uint8_t __reserved:1;
360 #endif
361 		} ATTRIBUTE_PACKING init;
362 		struct {
363 #if WORDS_BIGENDIAN
364 			uint8_t ignore:1;
365 			uint8_t rearm:1;
366 			uint8_t hysteresis:2;
367 			uint8_t threshold:2;
368 			uint8_t event_msg:2;
369 #else
370 			uint8_t event_msg:2;
371 			uint8_t threshold:2;
372 			uint8_t hysteresis:2;
373 			uint8_t rearm:1;
374 			uint8_t ignore:1;
375 #endif
376 		} ATTRIBUTE_PACKING capabilities;
377 		uint8_t type;
378 	} ATTRIBUTE_PACKING sensor;
379 
380 	uint8_t event_type;	/* event/reading type code */
381 
382 	struct sdr_record_mask mask;
383 
384 	struct {
385 #if WORDS_BIGENDIAN
386 		uint8_t analog:2;
387 		uint8_t rate:3;
388 		uint8_t modifier:2;
389 		uint8_t pct:1;
390 #else
391 		uint8_t pct:1;
392 		uint8_t modifier:2;
393 		uint8_t rate:3;
394 		uint8_t analog:2;
395 #endif
396 		struct {
397 			uint8_t base;
398 			uint8_t modifier;
399 		} ATTRIBUTE_PACKING type;
400 	} ATTRIBUTE_PACKING unit;
401 } ATTRIBUTE_PACKING;
402 
403 /* SDR Record Common Sensor header macros */
404 #define IS_THRESHOLD_SENSOR(s)	((s)->event_type == 1)
405 #define UNITS_ARE_DISCRETE(s)	((s)->unit.analog == 3)
406 
407 #ifdef HAVE_PRAGMA_PACK
408 #pragma pack(0)
409 #endif
410 
411 #ifdef HAVE_PRAGMA_PACK
412 #pragma pack(1)
413 #endif
414 struct sdr_record_compact_sensor {
415 	struct sdr_record_common_sensor cmn;
416 	struct {
417 #if WORDS_BIGENDIAN
418 		uint8_t __reserved:2;
419 		uint8_t mod_type:2;
420 		uint8_t count:4;
421 #else
422 		uint8_t count:4;
423 		uint8_t mod_type:2;
424 		uint8_t __reserved:2;
425 #endif
426 #if WORDS_BIGENDIAN
427 		uint8_t entity_inst:1;
428 		uint8_t mod_offset:7;
429 #else
430 		uint8_t mod_offset:7;
431 		uint8_t entity_inst:1;
432 #endif
433 	} ATTRIBUTE_PACKING share;
434 
435 	struct {
436 		struct {
437 			uint8_t positive;
438 			uint8_t negative;
439 		} ATTRIBUTE_PACKING hysteresis;
440 	} ATTRIBUTE_PACKING threshold;
441 
442 	uint8_t __reserved[3];
443 	uint8_t oem;		/* reserved for OEM use */
444 	uint8_t id_code;	/* sensor ID string type/length code */
445 	uint8_t id_string[16];	/* sensor ID string bytes, only if id_code != 0 */
446 } ATTRIBUTE_PACKING;
447 #ifdef HAVE_PRAGMA_PACK
448 #pragma pack(0)
449 #endif
450 
451 #ifdef HAVE_PRAGMA_PACK
452 #pragma pack(1)
453 #endif
454 struct sdr_record_eventonly_sensor {
455 	struct {
456 		uint8_t owner_id;
457 #if WORDS_BIGENDIAN
458 		uint8_t channel:4;	/* channel number */
459 		uint8_t fru_owner:2;	/* fru device owner lun */
460 		uint8_t lun:2;	/* sensor owner lun */
461 #else
462 		uint8_t lun:2;	/* sensor owner lun */
463 		uint8_t fru_owner:2;	/* fru device owner lun */
464 		uint8_t channel:4;	/* channel number */
465 #endif
466 		uint8_t sensor_num;	/* unique sensor number */
467 	} ATTRIBUTE_PACKING keys;
468 
469 	struct entity_id entity;
470 
471 	uint8_t sensor_type;	/* sensor type */
472 	uint8_t event_type;	/* event/reading type code */
473 
474 	struct {
475 #if WORDS_BIGENDIAN
476 		uint8_t __reserved:2;
477 		uint8_t mod_type:2;
478 		uint8_t count:4;
479 #else
480 		uint8_t count:4;
481 		uint8_t mod_type:2;
482 		uint8_t __reserved:2;
483 #endif
484 #if WORDS_BIGENDIAN
485 		uint8_t entity_inst:1;
486 		uint8_t mod_offset:7;
487 #else
488 		uint8_t mod_offset:7;
489 		uint8_t entity_inst:1;
490 #endif
491 	} ATTRIBUTE_PACKING share;
492 
493 	uint8_t __reserved;
494 	uint8_t oem;		/* reserved for OEM use */
495 	uint8_t id_code;	/* sensor ID string type/length code */
496 	uint8_t id_string[16];	/* sensor ID string bytes, only if id_code != 0 */
497 
498 } ATTRIBUTE_PACKING;
499 #ifdef HAVE_PRAGMA_PACK
500 #pragma pack(0)
501 #endif
502 
503 #ifdef HAVE_PRAGMA_PACK
504 #pragma pack(1)
505 #endif
506 struct sdr_record_full_sensor {
507 	struct sdr_record_common_sensor cmn;
508 
509 #define SDR_SENSOR_L_LINEAR     0x00
510 #define SDR_SENSOR_L_LN         0x01
511 #define SDR_SENSOR_L_LOG10      0x02
512 #define SDR_SENSOR_L_LOG2       0x03
513 #define SDR_SENSOR_L_E          0x04
514 #define SDR_SENSOR_L_EXP10      0x05
515 #define SDR_SENSOR_L_EXP2       0x06
516 #define SDR_SENSOR_L_1_X        0x07
517 #define SDR_SENSOR_L_SQR        0x08
518 #define SDR_SENSOR_L_CUBE       0x09
519 #define SDR_SENSOR_L_SQRT       0x0a
520 #define SDR_SENSOR_L_CUBERT     0x0b
521 #define SDR_SENSOR_L_NONLINEAR  0x70
522 
523 	uint8_t linearization;	/* 70h=non linear, 71h-7Fh=non linear, OEM */
524 	uint16_t mtol;		/* M, tolerance */
525 	uint32_t bacc;		/* accuracy, B, Bexp, Rexp */
526 
527 	struct {
528 #if WORDS_BIGENDIAN
529 		uint8_t __reserved:5;
530 		uint8_t normal_min:1;	/* normal min field specified */
531 		uint8_t normal_max:1;	/* normal max field specified */
532 		uint8_t nominal_read:1;	/* nominal reading field specified */
533 #else
534 		uint8_t nominal_read:1;	/* nominal reading field specified */
535 		uint8_t normal_max:1;	/* normal max field specified */
536 		uint8_t normal_min:1;	/* normal min field specified */
537 		uint8_t __reserved:5;
538 #endif
539 	} ATTRIBUTE_PACKING analog_flag;
540 
541 	uint8_t nominal_read;	/* nominal reading, raw value */
542 	uint8_t normal_max;	/* normal maximum, raw value */
543 	uint8_t normal_min;	/* normal minimum, raw value */
544 	uint8_t sensor_max;	/* sensor maximum, raw value */
545 	uint8_t sensor_min;	/* sensor minimum, raw value */
546 
547 	struct {
548 		struct {
549 			uint8_t non_recover;
550 			uint8_t critical;
551 			uint8_t non_critical;
552 		} ATTRIBUTE_PACKING upper;
553 		struct {
554 			uint8_t non_recover;
555 			uint8_t critical;
556 			uint8_t non_critical;
557 		} ATTRIBUTE_PACKING lower;
558 		struct {
559 			uint8_t positive;
560 			uint8_t negative;
561 		} ATTRIBUTE_PACKING hysteresis;
562 	} ATTRIBUTE_PACKING threshold;
563 	uint8_t __reserved[2];
564 	uint8_t oem;		/* reserved for OEM use */
565 	uint8_t id_code;	/* sensor ID string type/length code */
566 	uint8_t id_string[16];	/* sensor ID string bytes, only if id_code != 0 */
567 } ATTRIBUTE_PACKING;
568 #ifdef HAVE_PRAGMA_PACK
569 #pragma pack(0)
570 #endif
571 
572 #ifdef HAVE_PRAGMA_PACK
573 #pragma pack(1)
574 #endif
575 struct sdr_record_mc_locator {
576 	uint8_t dev_slave_addr;
577 #if WORDS_BIGENDIAN
578 	uint8_t __reserved2:4;
579 	uint8_t channel_num:4;
580 #else
581 	uint8_t channel_num:4;
582 	uint8_t __reserved2:4;
583 #endif
584 #if WORDS_BIGENDIAN
585 	uint8_t pwr_state_notif:3;
586 	uint8_t __reserved3:1;
587 	uint8_t global_init:4;
588 #else
589 	uint8_t global_init:4;
590 	uint8_t __reserved3:1;
591 	uint8_t pwr_state_notif:3;
592 #endif
593 	uint8_t dev_support;
594 	uint8_t __reserved4[3];
595 	struct entity_id entity;
596 	uint8_t oem;
597 	uint8_t id_code;
598 	uint8_t id_string[16];
599 } ATTRIBUTE_PACKING;
600 #ifdef HAVE_PRAGMA_PACK
601 #pragma pack(0)
602 #endif
603 
604 struct sdr_record_fru_locator {
605 	uint8_t dev_slave_addr;
606 	uint8_t device_id;
607 #if WORDS_BIGENDIAN
608 	uint8_t logical:1;
609 	uint8_t __reserved2:2;
610 	uint8_t lun:2;
611 	uint8_t bus:3;
612 #else
613 	uint8_t bus:3;
614 	uint8_t lun:2;
615 	uint8_t __reserved2:2;
616 	uint8_t logical:1;
617 #endif
618 #if WORDS_BIGENDIAN
619 	uint8_t channel_num:4;
620 	uint8_t __reserved3:4;
621 #else
622 	uint8_t __reserved3:4;
623 	uint8_t channel_num:4;
624 #endif
625 	uint8_t __reserved4;
626 	uint8_t dev_type;
627 	uint8_t dev_type_modifier;
628 	struct entity_id entity;
629 	uint8_t oem;
630 	uint8_t id_code;
631 	uint8_t id_string[16];
632 } ATTRIBUTE_PACKING;
633 #ifdef HAVE_PRAGMA_PACK
634 #pragma pack(0)
635 #endif
636 
637 #ifdef HAVE_PRAGMA_PACK
638 #pragma pack(1)
639 #endif
640 struct sdr_record_generic_locator {
641 	uint8_t dev_access_addr;
642 	uint8_t dev_slave_addr;
643 #if WORDS_BIGENDIAN
644 	uint8_t channel_num:3;
645 	uint8_t lun:2;
646 	uint8_t bus:3;
647 #else
648 	uint8_t bus:3;
649 	uint8_t lun:2;
650 	uint8_t channel_num:3;
651 #endif
652 #if WORDS_BIGENDIAN
653 	uint8_t addr_span:3;
654 	uint8_t __reserved1:5;
655 #else
656 	uint8_t __reserved1:5;
657 	uint8_t addr_span:3;
658 #endif
659 	uint8_t __reserved2;
660 	uint8_t dev_type;
661 	uint8_t dev_type_modifier;
662 	struct entity_id entity;
663 	uint8_t oem;
664 	uint8_t id_code;
665 	uint8_t id_string[16];
666 } ATTRIBUTE_PACKING;
667 #ifdef HAVE_PRAGMA_PACK
668 #pragma pack(0)
669 #endif
670 
671 #ifdef HAVE_PRAGMA_PACK
672 #pragma pack(1)
673 #endif
674 struct sdr_record_entity_assoc {
675 	struct entity_id entity;	/* container entity ID and instance */
676 	struct {
677 #if WORDS_BIGENDIAN
678 		uint8_t isrange:1;
679 		uint8_t islinked:1;
680 		uint8_t isaccessable:1;
681 		uint8_t __reserved:5;
682 #else
683 		uint8_t __reserved:5;
684 		uint8_t isaccessable:1;
685 		uint8_t islinked:1;
686 		uint8_t isrange:1;
687 #endif
688 	} flags;
689 	uint8_t entity_id_1;	/* entity ID 1    |  range 1 entity */
690 	uint8_t entity_inst_1;	/* entity inst 1  |  range 1 first instance */
691 	uint8_t entity_id_2;	/* entity ID 2    |  range 1 entity */
692 	uint8_t entity_inst_2;	/* entity inst 2  |  range 1 last instance */
693 	uint8_t entity_id_3;	/* entity ID 3    |  range 2 entity */
694 	uint8_t entity_inst_3;	/* entity inst 3  |  range 2 first instance */
695 	uint8_t entity_id_4;	/* entity ID 4    |  range 2 entity */
696 	uint8_t entity_inst_4;	/* entity inst 4  |  range 2 last instance */
697 } ATTRIBUTE_PACKING;
698 #ifdef HAVE_PRAGMA_PACK
699 #pragma pack(0)
700 #endif
701 
702 struct sdr_record_oem {
703 	uint8_t *data;
704 	int data_len;
705 };
706 
707 /*
708  * The Get SDR Repository Info response structure
709  * From table 33-3 of the IPMI v2.0 spec
710  */
711 #ifdef HAVE_PRAGMA_PACK
712 #pragma pack(1)
713 #endif
714 struct get_sdr_repository_info_rsp {
715 	uint8_t sdr_version;
716 	uint8_t record_count_lsb;
717 	uint8_t record_count_msb;
718 	uint8_t free_space[2];
719 	uint8_t most_recent_addition_timestamp[4];
720 	uint8_t most_recent_erase_timestamp[4];
721 #if WORDS_BIGENDIAN
722 	uint8_t overflow_flag:1;
723 	uint8_t modal_update_support:2;
724 	uint8_t __reserved1:1;
725 	uint8_t delete_sdr_supported:1;
726 	uint8_t partial_add_sdr_supported:1;
727 	uint8_t reserve_sdr_repository_supported:1;
728 	uint8_t get_sdr_repository_allo_info_supported:1;
729 #else
730 	uint8_t get_sdr_repository_allo_info_supported:1;
731 	uint8_t reserve_sdr_repository_supported:1;
732 	uint8_t partial_add_sdr_supported:1;
733 	uint8_t delete_sdr_supported:1;
734 	uint8_t __reserved1:1;
735 	uint8_t modal_update_support:2;
736 	uint8_t overflow_flag:1;
737 #endif
738 } ATTRIBUTE_PACKING;
739 #ifdef HAVE_PRAGMA_PACK
740 #pragma pack(0)
741 #endif
742 
743 struct ipmi_sdr_iterator {
744 	uint16_t reservation;
745 	int total;
746 	int next;
747 	int use_built_in;
748 };
749 
750 #ifdef HAVE_PRAGMA_PACK
751 #pragma pack(1)
752 #endif
753 struct sdr_record_list {
754 	uint16_t id;
755 	uint8_t version;
756 	uint8_t type;
757 	uint8_t length;
758 	uint8_t *raw;
759 	struct sdr_record_list *next;
760 	union {
761 		struct sdr_record_common_sensor *common;
762 		struct sdr_record_full_sensor *full;
763 		struct sdr_record_compact_sensor *compact;
764 		struct sdr_record_eventonly_sensor *eventonly;
765 		struct sdr_record_generic_locator *genloc;
766 		struct sdr_record_fru_locator *fruloc;
767 		struct sdr_record_mc_locator *mcloc;
768 		struct sdr_record_entity_assoc *entassoc;
769 		struct sdr_record_oem *oem;
770 	} ATTRIBUTE_PACKING  record;
771 } ATTRIBUTE_PACKING;
772 #ifdef HAVE_PRAGMA_PACK
773 #pragma pack(0)
774 #endif
775 
776 
777 /* unit description codes (IPMI v1.5 section 37.16) */
778 #define UNIT_MAX	0x90
779 static const char *unit_desc[] __attribute__ ((unused)) = {
780 "unspecified",
781 	    "degrees C", "degrees F", "degrees K",
782 	    "Volts", "Amps", "Watts", "Joules",
783 	    "Coulombs", "VA", "Nits",
784 	    "lumen", "lux", "Candela",
785 	    "kPa", "PSI", "Newton",
786 	    "CFM", "RPM", "Hz",
787 	    "microsecond", "millisecond", "second", "minute", "hour",
788 	    "day", "week", "mil", "inches", "feet", "cu in", "cu feet",
789 	    "mm", "cm", "m", "cu cm", "cu m", "liters", "fluid ounce",
790 	    "radians", "steradians", "revolutions", "cycles",
791 	    "gravities", "ounce", "pound", "ft-lb", "oz-in", "gauss",
792 	    "gilberts", "henry", "millihenry", "farad", "microfarad",
793 	    "ohms", "siemens", "mole", "becquerel", "PPM", "reserved",
794 	    "Decibels", "DbA", "DbC", "gray", "sievert",
795 	    "color temp deg K", "bit", "kilobit", "megabit", "gigabit",
796 	    "byte", "kilobyte", "megabyte", "gigabyte", "word", "dword",
797 	    "qword", "line", "hit", "miss", "retry", "reset",
798 	    "overflow", "underrun", "collision", "packets", "messages",
799 	    "characters", "error", "correctable error", "uncorrectable error",};
800 
801 /* sensor type codes (IPMI v1.5 table 36.3)
802   / Updated to v2.0 Table 42-3, Sensor Type Codes */
803 #define SENSOR_TYPE_MAX 0x2C
804 static const char *sensor_type_desc[] __attribute__ ((unused)) = {
805 "reserved",
806 	    "Temperature", "Voltage", "Current", "Fan",
807 	    "Physical Security", "Platform Security", "Processor",
808 	    "Power Supply", "Power Unit", "Cooling Device", "Other",
809 	    "Memory", "Drive Slot / Bay", "POST Memory Resize",
810 	    "System Firmwares", "Event Logging Disabled", "Watchdog1",
811 	    "System Event", "Critical Interrupt", "Button",
812 	    "Module / Board", "Microcontroller", "Add-in Card",
813 	    "Chassis", "Chip Set", "Other FRU", "Cable / Interconnect",
814 	    "Terminator", "System Boot Initiated", "Boot Error",
815 	    "OS Boot", "OS Critical Stop", "Slot / Connector",
816 	    "System ACPI Power State", "Watchdog2", "Platform Alert",
817 	    "Entity Presence", "Monitor ASIC", "LAN",
818 	    "Management Subsys Health", "Battery", "Session Audit",
819 	    "Version Change", "FRU State" };
820 
821 struct sensor_reading {
822 	char		s_id[17];		/* name of the sensor */
823 	struct sdr_record_full_sensor    *full;
824 	struct sdr_record_compact_sensor *compact;
825 	uint8_t		s_reading_valid;	/* read value valididity */
826 	uint8_t		s_scanning_disabled;	/* read of value disabled */
827 	uint8_t		s_reading_unavailable;	/* read value unavailable */
828 	uint8_t		s_reading;		/* value which was read */
829 	uint8_t		s_data2;		/* data2 value read */
830 	uint8_t		s_data3;		/* data3 value read */
831 	uint8_t		s_has_analog_value;	/* sensor has analog value */
832 	double		s_a_val;		/* read value converted to analog */
833 	char		s_a_str[16];		/* analog value as a string */
834 	const char	*s_a_units;		/* analog value units string */
835 };
836 
837 /*
838  * Determine if bridging is necessary to address a sensor at the given
839  * address (_addr) and (_chan) via the interface (_intf).
840  *
841  * If the sensor is being addressed on channel zero, it resides on
842  * IPMB-0.  If the interface target IPMB-0 address is exactly the same as
843  * the sensor address then the sensor resides on the target IPMB-0
844  * so we don't need extra levels of bridging to address  the sensor.
845  *	Or
846  * If the sensor target address and channel match the interface target address
847  * and channel then there is no extra levels of bridging required.
848  *
849  * Note:
850  *	The target IPMB-0 address is the address of the SDR repository that was
851  *	accessed using the user specified bridging command line arguments.
852  *	Access to any sensor on the target IPMB-0 can be addressed using the
853  *	target address and transit address in the interface.
854  */
855 #define BRIDGE_TO_SENSOR(_intf, _addr, _chan)			\
856  ( !((_chan == 0 && _intf->target_ipmb_addr &&			\
857 			     _intf->target_ipmb_addr == _addr)  ||	\
858     (_addr == _intf->target_addr && _chan == _intf->target_channel)) )
859 
860 
861 struct ipmi_sdr_iterator *ipmi_sdr_start(struct ipmi_intf *intf,
862                                          int use_builtin);
863 struct sdr_get_rs *ipmi_sdr_get_next_header(struct ipmi_intf *intf,
864 					    struct ipmi_sdr_iterator *i);
865 uint8_t *ipmi_sdr_get_record(struct ipmi_intf *intf, struct sdr_get_rs *header,
866 			     struct ipmi_sdr_iterator *i);
867 void ipmi_sdr_end(struct ipmi_intf *intf, struct ipmi_sdr_iterator *i);
868 int ipmi_sdr_print_sdr(struct ipmi_intf *intf, uint8_t type);
869 
870 int ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf,uint16_t id,
871                                       uint8_t type,uint8_t * raw);
872 int ipmi_sdr_print_rawentry(struct ipmi_intf *intf, uint8_t type, uint8_t * raw,
873 			    int len);
874 int ipmi_sdr_print_listentry(struct ipmi_intf *intf,
875 			     struct sdr_record_list *entry);
876 void ipmi_sdr_print_sensor_hysteresis(struct sdr_record_common_sensor *sensor,
877 		 struct sdr_record_full_sensor   *full,
878 		 uint8_t hysteresis_value,
879 		 const char *hdrstr);
880 const char *ipmi_sdr_get_unit_string(uint8_t pct, uint8_t type,
881 				      uint8_t base, uint8_t modifier);
882 struct sensor_reading *
883 ipmi_sdr_read_sensor_value(struct ipmi_intf *intf,
884 		struct sdr_record_common_sensor *sensor,
885 		uint8_t sdr_record_type, int precision);
886 const char *ipmi_sdr_get_thresh_status(struct sensor_reading *sr,
887 					const char *invalidstr);
888 const char *ipmi_sdr_get_status(int, const char *, uint8_t stat);
889 double sdr_convert_sensor_tolerance(struct sdr_record_full_sensor *sensor,
890 				  uint8_t val);
891 double sdr_convert_sensor_reading(struct sdr_record_full_sensor *sensor,
892 				  uint8_t val);
893 double sdr_convert_sensor_hysterisis(struct sdr_record_full_sensor *sensor,
894 				  uint8_t val);
895 uint8_t sdr_convert_sensor_value_to_raw(struct sdr_record_full_sensor *sensor,
896 					double val);
897 struct ipmi_rs *ipmi_sdr_get_sensor_reading(struct ipmi_intf *intf,
898 					    uint8_t sensor);
899 struct ipmi_rs *ipmi_sdr_get_sensor_reading_ipmb(struct ipmi_intf *intf,
900 						 uint8_t sensor,
901 						 uint8_t target,
902 						 uint8_t lun,
903 						 uint8_t channel);
904 struct ipmi_rs *ipmi_sdr_get_sensor_thresholds(struct ipmi_intf *intf,
905 					       uint8_t sensor,
906 					       uint8_t target, uint8_t lun, uint8_t channel);
907 struct ipmi_rs *ipmi_sdr_get_sensor_hysteresis(struct ipmi_intf *intf,
908 					       uint8_t sensor,
909 					       uint8_t target, uint8_t lun, uint8_t channel);
910 const char *ipmi_sdr_get_sensor_type_desc(const uint8_t type);
911 int ipmi_sdr_get_reservation(struct ipmi_intf *intf, int use_builtin,
912                              uint16_t * reserve_id);
913 
914 int ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
915 				    struct sdr_record_eventonly_sensor *sensor);
916 int ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
917 					  struct sdr_record_generic_locator
918 					  *fru);
919 int ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
920 				      struct sdr_record_fru_locator *fru);
921 int ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
922 				     struct sdr_record_mc_locator *mc);
923 int ipmi_sdr_print_sensor_entity_assoc(struct ipmi_intf *intf,
924 				       struct sdr_record_entity_assoc *assoc);
925 
926 struct sdr_record_list *ipmi_sdr_find_sdr_byentity(struct ipmi_intf *intf,
927 						   struct entity_id *entity);
928 struct sdr_record_list *ipmi_sdr_find_sdr_bynumtype(struct ipmi_intf *intf,
929 					uint16_t gen_id, uint8_t num, uint8_t type);
930 struct sdr_record_list *ipmi_sdr_find_sdr_bysensortype(struct ipmi_intf *intf,
931 						       uint8_t type);
932 struct sdr_record_list *ipmi_sdr_find_sdr_byid(struct ipmi_intf *intf,
933 					       char *id);
934 struct sdr_record_list *ipmi_sdr_find_sdr_bytype(struct ipmi_intf *intf,
935 						 uint8_t type);
936 int ipmi_sdr_list_cache(struct ipmi_intf *intf);
937 int ipmi_sdr_list_cache_fromfile(struct ipmi_intf *intf, const char *ifile);
938 void ipmi_sdr_list_empty(struct ipmi_intf *intf);
939 int ipmi_sdr_print_info(struct ipmi_intf *intf);
940 void ipmi_sdr_print_discrete_state(const char *desc, uint8_t sensor_type,
941 				   uint8_t event_type, uint8_t state1,
942 				   uint8_t state2);
943 void ipmi_sdr_print_discrete_state_mini(const char *header, const char *separator,
944 					uint8_t sensor_type, uint8_t event_type,
945 					uint8_t state1, uint8_t state2);
946 int ipmi_sdr_print_sensor_event_status(struct ipmi_intf *intf,
947 				       uint8_t sensor_num, uint8_t sensor_type,
948 				       uint8_t event_type, int numeric_fmt,
949 				       uint8_t target, uint8_t lun, uint8_t channel);
950 int ipmi_sdr_print_sensor_event_enable(struct ipmi_intf *intf,
951 				       uint8_t sensor_num, uint8_t sensor_type,
952 				       uint8_t event_type, int numeric_fmt,
953 				       uint8_t target, uint8_t lun, uint8_t channel);
954 
955 #endif				/* IPMI_SDR_H */
956