Add type 12h sdr records

This adds support for BMC and ME type 12 records.

Tested:

ipmitool sdr list mcloc

Device ID              : �Basbrd Mgmt Ctl
Entity ID              : 0.46 (Unspecified)
Device Slave Address   : 20h
Channel Number         : 0h
ACPI System P/S Notif  : Not Required
ACPI Device P/S Notif  : Not Required
Controller Presence    : Dynamic
Logs Init Agent Errors : No
Event Message Gen      : Enable
Device Capabilities
 Chassis Device        : Yes
 Bridge                : No
 IPMB Event Generator  : Yes
 IPMB Event Receiver   : Yes
 FRU Inventory Device  : Yes
 SEL Device            : Yes
 SDR Repository        : Yes
 Sensor Device         : Yes

Device ID              : �Mgmt Engin
Entity ID              : 0.46 (Unspecified)
Device Slave Address   : 2Ch
Channel Number         : 6h
ACPI System P/S Notif  : Not Required
ACPI Device P/S Notif  : Not Required
Controller Presence    : Static
Logs Init Agent Errors : No
Event Message Gen      : Enable
Device Capabilities
 Chassis Device        : No
 Bridge                : No
 IPMB Event Generator  : Yes
 IPMB Event Receiver   : No
 FRU Inventory Device  : No
 SEL Device            : No
 SDR Repository        : No
 Sensor Device         : Yes

Change-Id: I3d015ca2f61ab07be18ba46239c3d6a919f0298b
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/src/sensorcommands.cpp b/src/sensorcommands.cpp
index b24ac7e..28d68f4 100644
--- a/src/sensorcommands.cpp
+++ b/src/sensorcommands.cpp
@@ -1053,52 +1053,41 @@
 
 /* storage commands */
 
-ipmi_ret_t ipmiStorageGetSDRRepositoryInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                                           ipmi_request_t request,
-                                           ipmi_response_t response,
-                                           ipmi_data_len_t dataLen,
-                                           ipmi_context_t context)
+ipmi::RspType<uint8_t,  // sdr version
+              uint16_t, // record count
+              uint16_t, // free space
+              uint32_t, // most recent addition
+              uint32_t, // most recent erase
+              uint8_t   // operationSupport
+              >
+    ipmiStorageGetSDRRepositoryInfo(void)
 {
-    printCommand(+netfn, +cmd);
-
-    if (*dataLen)
-    {
-        *dataLen = 0;
-        return IPMI_CC_REQ_DATA_LEN_INVALID;
-    }
-    *dataLen = 0; // default to 0 in case of an error
-
+    constexpr const uint16_t unspecifiedFreeSpace = 0xFFFF;
     if (sensorTree.empty() && !getSensorSubtree(sensorTree))
     {
-        return IPMI_CC_RESPONSE_ERROR;
+        return ipmi::responseResponseError();
     }
 
-    // zero out response buff
-    auto responseClear = static_cast<uint8_t *>(response);
-    std::fill(responseClear, responseClear + sizeof(GetSDRInfoResp), 0);
+    size_t fruCount = 0;
+    ipmi::Cc ret = ipmi::storage::getFruSdrCount(fruCount);
+    if (ret != ipmi::ccSuccess)
+    {
+        return ipmi::response(ret);
+    }
 
-    auto resp = static_cast<GetSDRInfoResp *>(response);
-    resp->sdrVersion = ipmiSdrVersion;
-    uint16_t recordCount = sensorTree.size();
+    uint16_t recordCount =
+        sensorTree.size() + fruCount + ipmi::storage::type12Count;
 
-    // todo: for now, sdr count is number of sensors
-    resp->recordCountLS = recordCount & 0xFF;
-    resp->recordCountMS = recordCount >> 8;
-
-    // free space unspcified
-    resp->freeSpace[0] = 0xFF;
-    resp->freeSpace[1] = 0xFF;
-
-    resp->mostRecentAddition = sdrLastAdd;
-    resp->mostRecentErase = sdrLastRemove;
-    resp->operationSupport = static_cast<uint8_t>(
+    uint8_t operationSupport = static_cast<uint8_t>(
         SdrRepositoryInfoOps::overflow); // write not supported
-    resp->operationSupport |=
+
+    operationSupport |=
         static_cast<uint8_t>(SdrRepositoryInfoOps::allocCommandSupported);
-    resp->operationSupport |= static_cast<uint8_t>(
+    operationSupport |= static_cast<uint8_t>(
         SdrRepositoryInfoOps::reserveSDRRepositoryCommandSupported);
-    *dataLen = sizeof(GetSDRInfoResp);
-    return IPMI_CC_OK;
+    return ipmi::responseSuccess(ipmiSdrVersion, recordCount,
+                                 unspecifiedFreeSpace, sdrLastAdd,
+                                 sdrLastRemove, operationSupport);
 }
 
 /** @brief implements the get SDR allocation info command
@@ -1166,13 +1155,14 @@
     }
 
     size_t fruCount = 0;
-    ipmi_ret_t ret = ipmi::storage::getFruSdrCount(fruCount);
-    if (ret != IPMI_CC_OK)
+    ipmi::Cc ret = ipmi::storage::getFruSdrCount(fruCount);
+    if (ret != ipmi::ccSuccess)
     {
         return ipmi::response(ret);
     }
 
-    size_t lastRecord = sensorTree.size() + fruCount - 1;
+    size_t lastRecord =
+        sensorTree.size() + fruCount + ipmi::storage::type12Count - 1;
     if (recordID == lastRecordIndex)
     {
         recordID = lastRecord;
@@ -1186,30 +1176,51 @@
 
     if (recordID >= sensorTree.size())
     {
+        std::vector<uint8_t> recordData;
         size_t fruIndex = recordID - sensorTree.size();
         if (fruIndex >= fruCount)
         {
-            return ipmi::responseInvalidFieldRequest();
-        }
-        get_sdr::SensorDataFruRecord data;
-        if (offset > sizeof(data))
-        {
-            return ipmi::responseInvalidFieldRequest();
-        }
-        ret = ipmi::storage::getFruSdrs(fruIndex, data);
-        if (ret != IPMI_CC_OK)
-        {
-            return ipmi::response(ret);
-        }
-        data.header.record_id_msb = recordID << 8;
-        data.header.record_id_lsb = recordID & 0xFF;
-        if (sizeof(data) < (offset + bytesToRead))
-        {
-            bytesToRead = sizeof(data) - offset;
-        }
+            // handle type 12 hardcoded records
+            size_t type12Index = fruIndex - fruCount;
+            if (type12Index >= ipmi::storage::type12Count ||
+                offset > sizeof(Type12Record))
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            std::vector<uint8_t> record =
+                ipmi::storage::getType12SDRs(type12Index, recordID);
+            if (record.size() < (offset + bytesToRead))
+            {
+                bytesToRead = record.size() - offset;
+            }
 
-        uint8_t *respStart = reinterpret_cast<uint8_t *>(&data) + offset;
-        std::vector<uint8_t> recordData(respStart, respStart + bytesToRead);
+            recordData.insert(recordData.end(), record.begin() + offset,
+                              record.begin() + offset + bytesToRead);
+        }
+        else
+        {
+            // handle fru records
+            get_sdr::SensorDataFruRecord data;
+            if (offset > sizeof(data))
+            {
+                return ipmi::responseInvalidFieldRequest();
+            }
+            ret = ipmi::storage::getFruSdrs(fruIndex, data);
+            if (ret != IPMI_CC_OK)
+            {
+                return ipmi::response(ret);
+            }
+            data.header.record_id_msb = recordID << 8;
+            data.header.record_id_lsb = recordID & 0xFF;
+            if (sizeof(data) < (offset + bytesToRead))
+            {
+                bytesToRead = sizeof(data) - offset;
+            }
+
+            uint8_t *respStart = reinterpret_cast<uint8_t *>(&data) + offset;
+            recordData.insert(recordData.end(), respStart,
+                              respStart + bytesToRead);
+        }
 
         return ipmi::responseSuccess(nextRecordId, recordData);
     }
@@ -1491,10 +1502,10 @@
     // versions
 
     // <Get SDR Repository Info>
-    ipmiPrintAndRegister(
-        NETFUN_STORAGE,
-        static_cast<ipmi_cmd_t>(IPMINetfnStorageCmds::ipmiCmdGetRepositoryInfo),
-        nullptr, ipmiStorageGetSDRRepositoryInfo, PRIVILEGE_USER);
+    ipmi::registerHandler(
+        ipmi::prioOemBase, NETFUN_STORAGE,
+        static_cast<ipmi::Cmd>(IPMINetfnStorageCmds::ipmiCmdGetRepositoryInfo),
+        ipmi::Privilege::User, ipmiStorageGetSDRRepositoryInfo);
 
     // <Get SDR Allocation Info>
     ipmi::registerHandler(