Expose memory error correction type

Memory error correction types are provided by smbios table type-16.
This change use that table to populate 'ECC' field in
xyz.openbmc_project.Inventory.Item.Dimm interface.

Tested:
Tested this on a real machine.

Signed-off-by: Kasun Athukorala <kasunath@google.com>
Change-Id: Iaeb27f81d9b97be1858d1c4564318f5dc69cfa4f
diff --git a/include/dimm.hpp b/include/dimm.hpp
index 1d1fc18..709bfdf 100644
--- a/include/dimm.hpp
+++ b/include/dimm.hpp
@@ -34,6 +34,9 @@
 using DeviceType =
     sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType;
 
+using EccType =
+    sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::Ecc;
+
 class Dimm :
     sdbusplus::server::object_t<
         sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm>,
@@ -105,6 +108,7 @@
     uint8_t memoryAttributes(uint8_t value) override;
     uint16_t memoryConfiguredSpeedInMhz(uint16_t value) override;
     bool functional(bool value) override;
+    EccType ecc(EccType value) override;
 
   private:
     uint8_t dimmNum;
@@ -125,6 +129,7 @@
                        uint8_t* dataIn);
     void dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
                      uint8_t* dataIn);
+    void updateEccType(uint16_t exPhyArrayHandle);
 };
 
 struct MemoryInfo
@@ -167,6 +172,25 @@
     uint64_t logicalSize;
 } __attribute__((packed));
 
+/**
+ * @brief Struct to represent SMBIOS 3.2 type-16 (Physical Memory Array) data.
+ */
+struct PhysicalMemoryArrayInfo
+{
+    uint8_t type;
+    uint8_t length;
+    uint16_t handle;
+    uint8_t location;
+    uint8_t use;
+    uint8_t memoryErrorCorrection;
+    uint32_t maximumCapacity;
+    uint16_t memoryErrorInformationHandle;
+    uint16_t numberOfMemoryDevices;
+    uint64_t extendedMaximumCapacity;
+} __attribute__((packed));
+static_assert(sizeof(PhysicalMemoryArrayInfo) == 23,
+              "Size of PhysicalMemoryArrayInfo struct is incorrect.");
+
 const std::map<uint8_t, DeviceType> dimmTypeTable = {
     {0x1, DeviceType::Other},         {0x2, DeviceType::Unknown},
     {0x3, DeviceType::DRAM},          {0x4, DeviceType::EDRAM},
@@ -191,6 +215,20 @@
     "CMOS",          "EDO",           "Window DRAM", "Cache DRAM",
     "Non-volatile",  "Registered",    "Unbuffered",  "LRDIMM"};
 
+/**
+ * @brief Map SMBIOS 3.2 Memory Array Error Correction Types to
+ * xyz.openbmc_project.Inventory.Item.Dimm.Ecc types.
+ *
+ * SMBIOS 3.2 Memory Array Error Correction Types 'Unknown', 'None', 'CRC' are
+ * mapped to EccType::NoECC since the DBUs interface does not support those
+ * representations.
+ */
+const std::map<uint8_t, EccType> dimmEccTypeMap = {
+    {0x1, EccType::NoECC},        {0x2, EccType::NoECC},
+    {0x3, EccType::NoECC},        {0x4, EccType::AddressParity},
+    {0x5, EccType::SingleBitECC}, {0x6, EccType::MultiBitECC},
+    {0x7, EccType::NoECC}};
+
 } // namespace smbios
 
 } // namespace phosphor