dbus-sdr: Add VR to ipmiStorageGetSDR().

ipmiStorageGetSDR() now can handle new sensor type of VR control. The
function will generate a SDR type 3 record for the new type of
sensors.

tested = ipmitool sdr list event
```
$ ipmitool sdr list event -v
Running Get PICMG Properties my_addr 0x20, transit 0, target 0
Error response 0xc1 from Get PICMG Properities
Running Get VSO Capabilities my_addr 0x20, transit 0, target 0
Invalid completion code received: Invalid command
Discovered IPMB address 0x0
Sensor ID              : vr_sensor_0_fprof (0xb4)
Entity ID              : 11.5 (Add-in Card)
Sensor Type            : Module / Board (0x15)

Sensor ID              : vr_sensor_1_fprof (0xb5)
Entity ID              : 11.6 (Add-in Card)
Sensor Type            : Module / Board (0x15)

...
```

Signed-off-by: Hao Jiang <jianghao@google.com>
Change-Id: I7c6bd2481c0f0a9fdc7db8629cfba9e43e842e37
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/dbus-sdr/sensorcommands.cpp b/dbus-sdr/sensorcommands.cpp
index e06148c..f15b80b 100644
--- a/dbus-sdr/sensorcommands.cpp
+++ b/dbus-sdr/sensorcommands.cpp
@@ -1417,6 +1417,55 @@
     return true;
 }
 
+// Construct a type 3 SDR for VR typed sensor(daemon).
+void constructVrSdr(uint16_t sensorNum, uint16_t recordID,
+                    const std::string& path, const DbusInterfaceMap& sensorMap,
+                    get_sdr::SensorDataEventRecord& record)
+{
+    uint8_t sensornumber = static_cast<uint8_t>(sensorNum);
+    uint8_t lun = static_cast<uint8_t>(sensorNum >> 8);
+
+    get_sdr::header::set_record_id(
+        recordID, reinterpret_cast<get_sdr::SensorDataRecordHeader*>(&record));
+
+    record.header.sdr_version = ipmiSdrVersion;
+    record.header.record_type = get_sdr::SENSOR_DATA_EVENT_RECORD;
+    record.header.record_length = sizeof(get_sdr::SensorDataEventRecord) -
+                                  sizeof(get_sdr::SensorDataRecordHeader);
+    record.key.owner_id = bmcI2CAddr;
+    record.key.owner_lun = lun;
+    record.key.sensor_number = sensornumber;
+
+    record.body.entity_id = 0x00;
+    record.body.entity_instance = 0x01;
+
+    // follow the association chain to get the parent board's entityid and
+    // entityInstance
+    updateIpmiFromAssociation(path, sensorMap, record.body.entity_id,
+                              record.body.entity_instance);
+
+    // Sensor type is hardcoded as a module/board type instead of parsing from
+    // sensor path. This is because VR control is allocated in an independent
+    // path(/xyz/openbmc_project/vr/profile/...) which is not categorized by
+    // types.
+    static constexpr const uint8_t module_board_type = 0x15;
+    record.body.sensor_type = module_board_type;
+    record.body.event_reading_type = 0x00;
+
+    record.body.sensor_record_sharing_1 = 0x00;
+    record.body.sensor_record_sharing_2 = 0x00;
+
+    // populate sensor name from path
+    auto name = sensor::parseSdrIdFromPath(path);
+    int nameSize = std::min(name.size(), sizeof(record.body.id_string));
+    record.body.id_string_info = nameSize;
+    std::memset(record.body.id_string, 0x00, sizeof(record.body.id_string));
+    std::memcpy(record.body.id_string, name.c_str(), nameSize);
+
+    // Remember the sensor name, as determined for this sensor number
+    details::sdrStatsTable.updateName(sensornumber, name);
+}
+
 static int getSensorDataRecord(ipmi::Context::ptr ctx,
                                std::vector<uint8_t>& recordData,
                                uint16_t recordID)
@@ -1514,7 +1563,21 @@
         }
         recordData.insert(recordData.end(), (uint8_t*)&record,
                           ((uint8_t*)&record) + sizeof(record));
+
+        return 0;
     }
+
+    // Contruct SDR type 3 record for VR sensor (daemon)
+    sensorObject = sensorMap.find(sensor::vrInterface);
+    if (sensorObject != sensorMap.end())
+    {
+        get_sdr::SensorDataEventRecord record = {0};
+
+        constructVrSdr(sensorNum, recordID, path, sensorMap, record);
+        recordData.insert(recordData.end(), (uint8_t*)&record,
+                          ((uint8_t*)&record) + sizeof(record));
+    }
+
     return 0;
 }