1 #pragma once
2
3 #include <stdint.h>
4
5 #include <ipmid/api.hpp>
6 #include <ipmid/types.hpp>
7
8 #include <exception>
9
10 /**
11 * @enum device_type
12 * IPMI FRU device types
13 */
14 enum device_type
15 {
16 IPMI_PHYSICAL_FRU = 0x00,
17 IPMI_LOGICAL_FRU = 0x80,
18 };
19
20 // Discrete sensor types.
21 enum ipmi_sensor_types
22 {
23 IPMI_SENSOR_TEMP = 0x01,
24 IPMI_SENSOR_VOLTAGE = 0x02,
25 IPMI_SENSOR_CURRENT = 0x03,
26 IPMI_SENSOR_FAN = 0x04,
27 IPMI_SENSOR_TPM = 0xCC,
28 };
29
30 /** @brief Custom exception for reading sensors that are not funcitonal.
31 */
32 struct SensorFunctionalError : public std::exception
33 {
whatSensorFunctionalError34 const char* what() const noexcept
35 {
36 return "Sensor not functional";
37 }
38 };
39
40 #define MAX_DBUS_PATH 128
41 struct dbus_interface_t
42 {
43 uint8_t sensornumber;
44 uint8_t sensortype;
45
46 char bus[MAX_DBUS_PATH];
47 char path[MAX_DBUS_PATH];
48 char interface[MAX_DBUS_PATH];
49 };
50
51 struct PlatformEventRequest
52 {
53 uint8_t eventMessageRevision;
54 uint8_t sensorType;
55 uint8_t sensorNumber;
56 uint8_t eventDirectionType;
57 uint8_t data[3];
58 };
59
60 static constexpr const char* ipmiSELPath = "/xyz/openbmc_project/Logging/IPMI";
61 static constexpr const char* ipmiSELAddInterface =
62 "xyz.openbmc_project.Logging.IPMI";
63 static const std::string ipmiSELAddMessage = "IPMI generated SEL Entry";
64
65 static constexpr int selSystemEventSizeWith3Bytes = 8;
66 static constexpr int selSystemEventSizeWith2Bytes = 7;
67 static constexpr int selSystemEventSizeWith1Bytes = 6;
68 static constexpr int selIPMBEventSize = 7;
69 static constexpr uint8_t directionMask = 0x80;
70 static constexpr uint8_t byte3EnableMask = 0x30;
71 static constexpr uint8_t byte2EnableMask = 0xC0;
72
73 int set_sensor_dbus_state_s(uint8_t, const char*, const char*);
74 int set_sensor_dbus_state_y(uint8_t, const char*, const uint8_t);
75 int find_openbmc_path(uint8_t, dbus_interface_t*);
76
77 ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
78 ipmi_request_t request, ipmi_response_t response,
79 ipmi_data_len_t data_len, ipmi_context_t context);
80
81 ipmi::RspType<uint16_t> ipmiSensorReserveSdr();
82
83 static const uint16_t FRU_RECORD_ID_START = 256;
84 static const uint16_t ENTITY_RECORD_ID_START = 512;
85 static const uint8_t SDR_VERSION = 0x51;
86 static const uint16_t END_OF_RECORD = 0xFFFF;
87 static const uint8_t LENGTH_MASK = 0x1F;
88
89 /**
90 * Get SDR Info
91 */
92
93 namespace get_sdr_info
94 {
95 namespace request
96 {
97 // Note: for some reason the ipmi_request_t appears to be the
98 // raw value for this call.
get_count(void * req)99 inline bool get_count(void* req)
100 {
101 return (bool)((uint64_t)(req) & 1);
102 }
103 } // namespace request
104 } // namespace get_sdr_info
105
106 /**
107 * Get SDR
108 */
109 namespace get_sdr
110 {
111
112 struct GetSdrReq
113 {
114 uint8_t reservation_id_lsb;
115 uint8_t reservation_id_msb;
116 uint8_t record_id_lsb;
117 uint8_t record_id_msb;
118 uint8_t offset;
119 uint8_t bytes_to_read;
120 } __attribute__((packed));
121
122 namespace request
123 {
124
get_reservation_id(GetSdrReq * req)125 inline uint16_t get_reservation_id(GetSdrReq* req)
126 {
127 return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
128 };
129
get_record_id(GetSdrReq * req)130 inline uint16_t get_record_id(GetSdrReq* req)
131 {
132 return (req->record_id_lsb + (req->record_id_msb << 8));
133 };
134
135 } // namespace request
136
137 // Response
138 struct GetSdrResp
139 {
140 uint8_t next_record_id_lsb;
141 uint8_t next_record_id_msb;
142 uint8_t record_data[64];
143 } __attribute__((packed));
144
145 namespace response
146 {
147
set_next_record_id(uint16_t next,GetSdrResp * resp)148 inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
149 {
150 resp->next_record_id_lsb = next & 0xff;
151 resp->next_record_id_msb = (next >> 8) & 0xff;
152 };
153
154 } // namespace response
155
156 // Record header
157 struct SensorDataRecordHeader
158 {
159 uint8_t record_id_lsb;
160 uint8_t record_id_msb;
161 uint8_t sdr_version;
162 uint8_t record_type;
163 uint8_t record_length; // Length not counting the header
164 } __attribute__((packed));
165
166 namespace header
167 {
168
set_record_id(int id,SensorDataRecordHeader * hdr)169 inline void set_record_id(int id, SensorDataRecordHeader* hdr)
170 {
171 hdr->record_id_lsb = (id & 0xFF);
172 hdr->record_id_msb = (id >> 8) & 0xFF;
173 };
174
175 } // namespace header
176
177 enum SensorDataRecordType
178 {
179 SENSOR_DATA_FULL_RECORD = 0x1,
180 SENSOR_DATA_COMPACT_RECORD = 0x2,
181 SENSOR_DATA_EVENT_RECORD = 0x3,
182 SENSOR_DATA_ENTITY_RECORD = 0x8,
183 SENSOR_DATA_FRU_RECORD = 0x11,
184 SENSOR_DATA_MGMT_CTRL_LOCATOR = 0x12,
185 };
186
187 // Record key
188 struct SensorDataRecordKey
189 {
190 uint8_t owner_id;
191 uint8_t owner_lun;
192 uint8_t sensor_number;
193 } __attribute__((packed));
194
195 /** @struct SensorDataFruRecordKey
196 *
197 * FRU Device Locator Record(key) - SDR Type 11
198 */
199 struct SensorDataFruRecordKey
200 {
201 uint8_t deviceAddress;
202 uint8_t fruID;
203 uint8_t accessLun;
204 uint8_t channelNumber;
205 } __attribute__((packed));
206
207 /** @struct SensorDataEntityRecordKey
208 *
209 * Entity Association Record(key) - SDR Type 8
210 */
211 struct SensorDataEntityRecordKey
212 {
213 uint8_t containerEntityId;
214 uint8_t containerEntityInstance;
215 uint8_t flags;
216 uint8_t entityId1;
217 uint8_t entityInstance1;
218 } __attribute__((packed));
219
220 namespace key
221 {
222
223 static constexpr uint8_t listOrRangeBit = 7;
224 static constexpr uint8_t linkedBit = 6;
225
set_owner_id_ipmb(SensorDataRecordKey * key)226 inline void set_owner_id_ipmb(SensorDataRecordKey* key)
227 {
228 key->owner_id &= ~0x01;
229 };
230
set_owner_id_system_sw(SensorDataRecordKey * key)231 inline void set_owner_id_system_sw(SensorDataRecordKey* key)
232 {
233 key->owner_id |= 0x01;
234 };
235
set_owner_id_bmc(SensorDataRecordKey * key)236 inline void set_owner_id_bmc(SensorDataRecordKey* key)
237 {
238 key->owner_id |= 0x20;
239 };
240
set_owner_id_address(uint8_t addr,SensorDataRecordKey * key)241 inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
242 {
243 key->owner_id &= 0x01;
244 key->owner_id |= addr << 1;
245 };
246
set_owner_lun(uint8_t lun,SensorDataRecordKey * key)247 inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
248 {
249 key->owner_lun &= ~0x03;
250 key->owner_lun |= (lun & 0x03);
251 };
252
set_owner_lun_channel(uint8_t channel,SensorDataRecordKey * key)253 inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
254 {
255 key->owner_lun &= 0x0f;
256 key->owner_lun |= ((channel & 0xf) << 4);
257 };
258
set_flags(bool isList,bool isLinked,SensorDataEntityRecordKey * key)259 inline void set_flags(bool isList, bool isLinked,
260 SensorDataEntityRecordKey* key)
261 {
262 key->flags = 0x00;
263 if (!isList)
264 key->flags |= 1 << listOrRangeBit;
265
266 if (isLinked)
267 key->flags |= 1 << linkedBit;
268 };
269
270 } // namespace key
271
272 /** @struct GetSensorThresholdsResponse
273 *
274 * Response structure for Get Sensor Thresholds command
275 */
276 struct GetSensorThresholdsResponse
277 {
278 uint8_t validMask; //!< valid mask
279 uint8_t lowerNonCritical; //!< lower non-critical threshold
280 uint8_t lowerCritical; //!< lower critical threshold
281 uint8_t lowerNonRecoverable; //!< lower non-recoverable threshold
282 uint8_t upperNonCritical; //!< upper non-critical threshold
283 uint8_t upperCritical; //!< upper critical threshold
284 uint8_t upperNonRecoverable; //!< upper non-recoverable threshold
285 } __attribute__((packed));
286
287 // Body - full record
288 #define FULL_RECORD_ID_STR_MAX_LENGTH 16
289
290 static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
291
292 struct SensorDataFullRecordBody
293 {
294 uint8_t entity_id;
295 uint8_t entity_instance;
296 uint8_t sensor_initialization;
297 uint8_t sensor_capabilities; // no macro support
298 uint8_t sensor_type;
299 uint8_t event_reading_type;
300 uint8_t supported_assertions[2]; // no macro support
301 uint8_t supported_deassertions[2]; // no macro support
302 uint8_t discrete_reading_setting_mask[2]; // no macro support
303 uint8_t sensor_units_1;
304 uint8_t sensor_units_2_base;
305 uint8_t sensor_units_3_modifier;
306 uint8_t linearization;
307 uint8_t m_lsb;
308 uint8_t m_msb_and_tolerance;
309 uint8_t b_lsb;
310 uint8_t b_msb_and_accuracy_lsb;
311 uint8_t accuracy_and_sensor_direction;
312 uint8_t r_b_exponents;
313 uint8_t analog_characteristic_flags; // no macro support
314 uint8_t nominal_reading;
315 uint8_t normal_max;
316 uint8_t normal_min;
317 uint8_t sensor_max;
318 uint8_t sensor_min;
319 uint8_t upper_nonrecoverable_threshold;
320 uint8_t upper_critical_threshold;
321 uint8_t upper_noncritical_threshold;
322 uint8_t lower_nonrecoverable_threshold;
323 uint8_t lower_critical_threshold;
324 uint8_t lower_noncritical_threshold;
325 uint8_t positive_threshold_hysteresis;
326 uint8_t negative_threshold_hysteresis;
327 uint16_t reserved;
328 uint8_t oem_reserved;
329 uint8_t id_string_info;
330 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
331 } __attribute__((packed));
332
333 /** @struct SensorDataCompactRecord
334 *
335 * Compact Sensor Record(body) - SDR Type 2
336 */
337 struct SensorDataCompactRecordBody
338 {
339 uint8_t entity_id;
340 uint8_t entity_instance;
341 uint8_t sensor_initialization;
342 uint8_t sensor_capabilities; // no macro support
343 uint8_t sensor_type;
344 uint8_t event_reading_type;
345 uint8_t supported_assertions[2]; // no macro support
346 uint8_t supported_deassertions[2]; // no macro support
347 uint8_t discrete_reading_setting_mask[2]; // no macro support
348 uint8_t sensor_units_1;
349 uint8_t sensor_units_2_base;
350 uint8_t sensor_units_3_modifier;
351 uint8_t record_sharing[2];
352 uint8_t positive_threshold_hysteresis;
353 uint8_t negative_threshold_hysteresis;
354 uint8_t reserved[3];
355 uint8_t oem_reserved;
356 uint8_t id_string_info;
357 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
358 } __attribute__((packed));
359
360 /** @struct SensorDataEventRecord
361 *
362 * Event Only Sensor Record(body) - SDR Type 3
363 */
364 struct SensorDataEventRecordBody
365 {
366 uint8_t entity_id;
367 uint8_t entity_instance;
368 uint8_t sensor_type;
369 uint8_t event_reading_type;
370 uint8_t sensor_record_sharing_1;
371 uint8_t sensor_record_sharing_2;
372 uint8_t reserved;
373 uint8_t oem_reserved;
374 uint8_t id_string_info;
375 char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
376 } __attribute__((packed));
377
378 /** @struct SensorDataFruRecordBody
379 *
380 * FRU Device Locator Record(body) - SDR Type 11
381 */
382 struct SensorDataFruRecordBody
383 {
384 uint8_t reserved;
385 uint8_t deviceType;
386 uint8_t deviceTypeModifier;
387 uint8_t entityID;
388 uint8_t entityInstance;
389 uint8_t oem;
390 uint8_t deviceIDLen;
391 char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
392 } __attribute__((packed));
393
394 /** @struct SensorDataEntityRecordBody
395 *
396 * Entity Association Record(body) - SDR Type 8
397 */
398 struct SensorDataEntityRecordBody
399 {
400 uint8_t entityId2;
401 uint8_t entityInstance2;
402 uint8_t entityId3;
403 uint8_t entityInstance3;
404 uint8_t entityId4;
405 uint8_t entityInstance4;
406 } __attribute__((packed));
407
408 namespace body
409 {
410
set_entity_instance_number(uint8_t n,SensorDataFullRecordBody * body)411 inline void set_entity_instance_number(uint8_t n,
412 SensorDataFullRecordBody* body)
413 {
414 body->entity_instance &= 1 << 7;
415 body->entity_instance |= (n & ~(1 << 7));
416 };
set_entity_physical_entity(SensorDataFullRecordBody * body)417 inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
418 {
419 body->entity_instance &= ~(1 << 7);
420 };
set_entity_logical_container(SensorDataFullRecordBody * body)421 inline void set_entity_logical_container(SensorDataFullRecordBody* body)
422 {
423 body->entity_instance |= 1 << 7;
424 };
425
sensor_scanning_state(bool enabled,SensorDataFullRecordBody * body)426 inline void sensor_scanning_state(bool enabled, SensorDataFullRecordBody* body)
427 {
428 if (enabled)
429 {
430 body->sensor_initialization |= 1 << 0;
431 }
432 else
433 {
434 body->sensor_initialization &= ~(1 << 0);
435 };
436 };
event_generation_state(bool enabled,SensorDataFullRecordBody * body)437 inline void event_generation_state(bool enabled, SensorDataFullRecordBody* body)
438 {
439 if (enabled)
440 {
441 body->sensor_initialization |= 1 << 1;
442 }
443 else
444 {
445 body->sensor_initialization &= ~(1 << 1);
446 }
447 };
init_types_state(bool enabled,SensorDataFullRecordBody * body)448 inline void init_types_state(bool enabled, SensorDataFullRecordBody* body)
449 {
450 if (enabled)
451 {
452 body->sensor_initialization |= 1 << 2;
453 }
454 else
455 {
456 body->sensor_initialization &= ~(1 << 2);
457 }
458 };
init_hyst_state(bool enabled,SensorDataFullRecordBody * body)459 inline void init_hyst_state(bool enabled, SensorDataFullRecordBody* body)
460 {
461 if (enabled)
462 {
463 body->sensor_initialization |= 1 << 3;
464 }
465 else
466 {
467 body->sensor_initialization &= ~(1 << 3);
468 }
469 };
init_thresh_state(bool enabled,SensorDataFullRecordBody * body)470 inline void init_thresh_state(bool enabled, SensorDataFullRecordBody* body)
471 {
472 if (enabled)
473 {
474 body->sensor_initialization |= 1 << 4;
475 }
476 else
477 {
478 body->sensor_initialization &= ~(1 << 4);
479 }
480 };
init_events_state(bool enabled,SensorDataFullRecordBody * body)481 inline void init_events_state(bool enabled, SensorDataFullRecordBody* body)
482 {
483 if (enabled)
484 {
485 body->sensor_initialization |= 1 << 5;
486 }
487 else
488 {
489 body->sensor_initialization &= ~(1 << 5);
490 }
491 };
init_scanning_state(bool enabled,SensorDataFullRecordBody * body)492 inline void init_scanning_state(bool enabled, SensorDataFullRecordBody* body)
493 {
494 if (enabled)
495 {
496 body->sensor_initialization |= 1 << 6;
497 }
498 else
499 {
500 body->sensor_initialization &= ~(1 << 6);
501 }
502 };
init_settable_state(bool enabled,SensorDataFullRecordBody * body)503 inline void init_settable_state(bool enabled, SensorDataFullRecordBody* body)
504 {
505 if (enabled)
506 {
507 body->sensor_initialization |= 1 << 7;
508 }
509 else
510 {
511 body->sensor_initialization &= ~(1 << 7);
512 }
513 };
514
set_percentage(SensorDataFullRecordBody * body)515 inline void set_percentage(SensorDataFullRecordBody* body)
516 {
517 body->sensor_units_1 |= 1 << 0;
518 };
unset_percentage(SensorDataFullRecordBody * body)519 inline void unset_percentage(SensorDataFullRecordBody* body)
520 {
521 body->sensor_units_1 &= ~(1 << 0);
522 };
set_modifier_operation(uint8_t op,SensorDataFullRecordBody * body)523 inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
524 {
525 body->sensor_units_1 &= ~(3 << 1);
526 body->sensor_units_1 |= (op & 0x3) << 1;
527 };
set_rate_unit(uint8_t unit,SensorDataFullRecordBody * body)528 inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
529 {
530 body->sensor_units_1 &= ~(7 << 3);
531 body->sensor_units_1 |= (unit & 0x7) << 3;
532 };
set_analog_data_format(uint8_t format,SensorDataFullRecordBody * body)533 inline void set_analog_data_format(uint8_t format,
534 SensorDataFullRecordBody* body)
535 {
536 body->sensor_units_1 &= ~(3 << 6);
537 body->sensor_units_1 |= (format & 0x3) << 6;
538 };
539
set_m(uint16_t m,SensorDataFullRecordBody * body)540 inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
541 {
542 body->m_lsb = m & 0xff;
543 body->m_msb_and_tolerance &= ~(3 << 6);
544 body->m_msb_and_tolerance |= ((m & (3 << 8)) >> 2);
545 };
set_tolerance(uint8_t tol,SensorDataFullRecordBody * body)546 inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
547 {
548 body->m_msb_and_tolerance &= ~0x3f;
549 body->m_msb_and_tolerance |= tol & 0x3f;
550 };
551
set_b(uint16_t b,SensorDataFullRecordBody * body)552 inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
553 {
554 body->b_lsb = b & 0xff;
555 body->b_msb_and_accuracy_lsb &= ~(3 << 6);
556 body->b_msb_and_accuracy_lsb |= ((b & (3 << 8)) >> 2);
557 };
set_accuracy(uint16_t acc,SensorDataFullRecordBody * body)558 inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
559 {
560 // bottom 6 bits
561 body->b_msb_and_accuracy_lsb &= ~0x3f;
562 body->b_msb_and_accuracy_lsb |= acc & 0x3f;
563 // top 4 bits
564 body->accuracy_and_sensor_direction &= 0x0f;
565 body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
566 };
set_accuracy_exp(uint8_t exp,SensorDataFullRecordBody * body)567 inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
568 {
569 body->accuracy_and_sensor_direction &= ~(3 << 2);
570 body->accuracy_and_sensor_direction |= (exp & 3) << 2;
571 };
set_sensor_dir(uint8_t dir,SensorDataFullRecordBody * body)572 inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
573 {
574 body->accuracy_and_sensor_direction &= ~(3 << 0);
575 body->accuracy_and_sensor_direction |= (dir & 3);
576 };
577
set_b_exp(uint8_t exp,SensorDataFullRecordBody * body)578 inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
579 {
580 body->r_b_exponents &= 0xf0;
581 body->r_b_exponents |= exp & 0x0f;
582 };
set_r_exp(uint8_t exp,SensorDataFullRecordBody * body)583 inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
584 {
585 body->r_b_exponents &= 0x0f;
586 body->r_b_exponents |= (exp & 0x0f) << 4;
587 };
588
set_id_strlen(uint8_t len,SensorDataFullRecordBody * body)589 inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
590 {
591 body->id_string_info &= ~(0x1f);
592 body->id_string_info |= len & 0x1f;
593 };
set_id_strlen(uint8_t len,SensorDataEventRecordBody * body)594 inline void set_id_strlen(uint8_t len, SensorDataEventRecordBody* body)
595 {
596 body->id_string_info &= ~(0x1f);
597 body->id_string_info |= len & 0x1f;
598 };
get_id_strlen(SensorDataFullRecordBody * body)599 inline uint8_t get_id_strlen(SensorDataFullRecordBody* body)
600 {
601 return body->id_string_info & 0x1f;
602 };
set_id_type(uint8_t type,SensorDataFullRecordBody * body)603 inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
604 {
605 body->id_string_info &= ~(3 << 6);
606 body->id_string_info |= (type & 0x3) << 6;
607 };
set_id_type(uint8_t type,SensorDataEventRecordBody * body)608 inline void set_id_type(uint8_t type, SensorDataEventRecordBody* body)
609 {
610 body->id_string_info &= ~(3 << 6);
611 body->id_string_info |= (type & 0x3) << 6;
612 };
613
set_device_id_strlen(uint8_t len,SensorDataFruRecordBody * body)614 inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
615 {
616 body->deviceIDLen &= ~(LENGTH_MASK);
617 body->deviceIDLen |= len & LENGTH_MASK;
618 };
619
get_device_id_strlen(SensorDataFruRecordBody * body)620 inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
621 {
622 return body->deviceIDLen & LENGTH_MASK;
623 };
624
set_readable_mask(uint8_t mask,SensorDataFullRecordBody * body)625 inline void set_readable_mask(uint8_t mask, SensorDataFullRecordBody* body)
626 {
627 body->discrete_reading_setting_mask[1] = mask & 0x3F;
628 }
629
630 } // namespace body
631
632 // More types contained in section 43.17 Sensor Unit Type Codes,
633 // IPMI spec v2 rev 1.1
634 enum SensorUnitTypeCodes
635 {
636 SENSOR_UNIT_UNSPECIFIED = 0,
637 SENSOR_UNIT_DEGREES_C = 1,
638 SENSOR_UNIT_VOLTS = 4,
639 SENSOR_UNIT_AMPERES = 5,
640 SENSOR_UNIT_WATTS = 6,
641 SENSOR_UNIT_JOULES = 7,
642 SENSOR_UNIT_RPM = 18,
643 SENSOR_UNIT_METERS = 34,
644 SENSOR_UNIT_REVOLUTIONS = 41,
645 };
646
647 struct SensorDataFullRecord
648 {
649 SensorDataRecordHeader header;
650 SensorDataRecordKey key;
651 SensorDataFullRecordBody body;
652 } __attribute__((packed));
653
654 /** @struct SensorDataComapactRecord
655 *
656 * Compact Sensor Record - SDR Type 2
657 */
658 struct SensorDataCompactRecord
659 {
660 SensorDataRecordHeader header;
661 SensorDataRecordKey key;
662 SensorDataCompactRecordBody body;
663 } __attribute__((packed));
664
665 /** @struct SensorDataEventRecord
666 *
667 * Event Only Sensor Record - SDR Type 3
668 */
669 struct SensorDataEventRecord
670 {
671 SensorDataRecordHeader header;
672 SensorDataRecordKey key;
673 SensorDataEventRecordBody body;
674 } __attribute__((packed));
675
676 /** @struct SensorDataFruRecord
677 *
678 * FRU Device Locator Record - SDR Type 11
679 */
680 struct SensorDataFruRecord
681 {
682 SensorDataRecordHeader header;
683 SensorDataFruRecordKey key;
684 SensorDataFruRecordBody body;
685 } __attribute__((packed));
686
687 /** @struct SensorDataEntityRecord
688 *
689 * Entity Association Record - SDR Type 8
690 */
691 struct SensorDataEntityRecord
692 {
693 SensorDataRecordHeader header;
694 SensorDataEntityRecordKey key;
695 SensorDataEntityRecordBody body;
696 } __attribute__((packed));
697
698 } // namespace get_sdr
699
700 namespace ipmi
701 {
702
703 namespace sensor
704 {
705
706 /**
707 * @brief Map offset to the corresponding bit in the assertion byte.
708 *
709 * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
710 * byte and offsets 8-14 in the second byte.
711 *
712 * @param[in] offset - offset number.
713 * @param[in/out] resp - get sensor reading response.
714 */
setOffset(uint8_t offset,ipmi::sensor::GetSensorResponse * resp)715 inline void setOffset(uint8_t offset, ipmi::sensor::GetSensorResponse* resp)
716 {
717 if (offset > 7)
718 {
719 resp->discreteReadingSensorStates |= 1 << (offset - 8);
720 }
721 else
722 {
723 resp->thresholdLevelsStates |= 1 << offset;
724 }
725 }
726
727 /**
728 * @brief Set the reading field in the response.
729 *
730 * @param[in] offset - offset number.
731 * @param[in/out] resp - get sensor reading response.
732 */
setReading(uint8_t value,ipmi::sensor::GetSensorResponse * resp)733 inline void setReading(uint8_t value, ipmi::sensor::GetSensorResponse* resp)
734 {
735 resp->reading = value;
736 }
737
738 /**
739 * @brief Map the value to the assertion bytes. The assertion states are stored
740 * in 2 bytes.
741 *
742 * @param[in] value - value to mapped to the assertion byte.
743 * @param[in/out] resp - get sensor reading response.
744 */
setAssertionBytes(uint16_t value,ipmi::sensor::GetSensorResponse * resp)745 inline void setAssertionBytes(uint16_t value,
746 ipmi::sensor::GetSensorResponse* resp)
747 {
748 resp->thresholdLevelsStates = static_cast<uint8_t>(value & 0x00FF);
749 resp->discreteReadingSensorStates = static_cast<uint8_t>(value >> 8);
750 }
751
752 /**
753 * @brief Set the scanning enabled bit in the response.
754 *
755 * @param[in/out] resp - get sensor reading response.
756 */
enableScanning(ipmi::sensor::GetSensorResponse * resp)757 inline void enableScanning(ipmi::sensor::GetSensorResponse* resp)
758 {
759 resp->readingOrStateUnavailable = false;
760 resp->scanningEnabled = true;
761 resp->allEventMessagesEnabled = false;
762 }
763
764 } // namespace sensor
765
766 } // namespace ipmi
767