SDR: Adding fru records as part of Get SDR command

Currently Get SDR only responds with physical/virtual sensor
records,it doesn't support for FRU records,This commit adds
the support for FRU records.

Resolves openbmc/openbmc#2776

Change-Id: I34edfa892b32f4e866cf0c084d97c2f3482d40f4
Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
diff --git a/sensorhandler.h b/sensorhandler.h
index 1cf43ca..e32405d 100644
--- a/sensorhandler.h
+++ b/sensorhandler.h
@@ -16,6 +16,16 @@
     IPMI_CMD_GET_SENSOR_THRESHOLDS = 0x27,
 };
 
+/**
+ * @enum device_type
+ * IPMI FRU device types
+ */
+enum device_type
+{
+    IPMI_PHYSICAL_FRU = 0x00,
+    IPMI_LOGICAL_FRU = 0x80,
+};
+
 // Discrete sensor types.
 enum ipmi_sensor_types
 {
@@ -40,6 +50,11 @@
 int set_sensor_dbus_state_y(uint8_t , const char *, const uint8_t);
 int find_openbmc_path(uint8_t , dbus_interface_t *);
 
+static const uint16_t FRU_RECORD_ID_START = 256;
+static const uint8_t SDR_VERSION = 0x51;
+static const uint16_t END_OF_RECORD = 0xFFFF;
+static const uint8_t LENGTH_MASK = 0x1F;
+
 /**
  * Get SDR Info
  */
@@ -109,7 +124,7 @@
     return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
 };
 
-inline uint8_t get_record_id(GetSdrReq* req)
+inline uint16_t get_record_id(GetSdrReq* req)
 {
     return (req->record_id_lsb + (req->record_id_msb << 8));
 };
@@ -127,7 +142,7 @@
 namespace response
 {
 
-inline void set_next_record_id(int next, GetSdrResp* resp)
+inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
 {
     resp->next_record_id_lsb = next & 0xff;
     resp->next_record_id_msb = (next >> 8) & 0xff;
@@ -158,7 +173,8 @@
 
 enum SensorDataRecordType
 {
-    SENSOR_DATA_FULL_RECORD = 1,
+    SENSOR_DATA_FULL_RECORD = 0x1,
+    SENSOR_DATA_FRU_RECORD = 0x11,
 };
 
 // Record key
@@ -169,6 +185,18 @@
     uint8_t sensor_number;
 } __attribute__((packed));
 
+/** @struct SensorDataFruRecordKey
+ *
+ *  FRU Device Locator Record(key) - SDR Type 11
+ */
+struct SensorDataFruRecordKey
+{
+    uint8_t deviceAddress;
+    uint8_t fruID;
+    uint8_t accessLun;
+    uint8_t channelNumber;
+} __attribute__((packed));
+
 namespace key
 {
 
@@ -219,6 +247,9 @@
 
 // Body - full record
 #define FULL_RECORD_ID_STR_MAX_LENGTH 16
+
+static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
+
 struct SensorDataFullRecordBody
 {
     uint8_t entity_id;
@@ -260,6 +291,22 @@
     char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
 } __attribute__((packed));
 
+/** @struct SensorDataFruRecordBody
+ *
+ *  FRU Device Locator Record(body) - SDR Type 11
+ */
+struct SensorDataFruRecordBody
+{
+    uint8_t reserved;
+    uint8_t deviceType;
+    uint8_t deviceTypeModifier;
+    uint8_t entityID;
+    uint8_t entityInstance;
+    uint8_t oem;
+    uint8_t deviceIDLen;
+    char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
+} __attribute__((packed));
+
 namespace body
 {
 
@@ -464,6 +511,17 @@
     body->id_string_info |= (type & 0x3)<<6;
 };
 
+inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
+{
+    body->deviceIDLen &= ~(LENGTH_MASK);
+    body->deviceIDLen |= len & LENGTH_MASK;
+};
+
+inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
+{
+    return body->deviceIDLen & LENGTH_MASK;
+};
+
 } // namespace body
 
 // More types contained in section 43.17 Sensor Unit Type Codes,
@@ -486,6 +544,17 @@
     SensorDataFullRecordBody body;
 } __attribute__((packed));
 
+/** @struct SensorDataFruRecord
+ *
+ *  FRU Device Locator Record - SDR Type 11
+ */
+struct SensorDataFruRecord
+{
+    SensorDataRecordHeader header;
+    SensorDataFruRecordKey key;
+    SensorDataFruRecordBody body;
+} __attribute__((packed));
+
 } // get_sdr
 
 namespace ipmi