Dimm memory size support
This commit will calculate the memory size for Dimm and
populate the value with property MemorySizeinKB on dbus.
Test- Tested on simics 2s2u
Set the property with dummy value-
root@rain71bmc:/tmp# busctl introspect xyz.openbmc_project.Inventory.Manager /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm0| grep -e MemorySizeInKB -e Present -e PrettyName -e Model -e PartNumber -e SerialNumber
.Model property s "327A" emits-change writable
.PartNumber property s "78P6574" emits-change writable
.SerialNumber property s "YH301T01P00G" emits-change writable
.SparePartNumber property s "" emits-change writable
.SubModel property s "" emits-change writable
.Present property b true emits-change writable
.PrettyName property s "Memory DIMM" emits-change writable
.MemorySizeInKB property u 33554432 emits-change writable
root@rain71bmc:/tmp#
Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
Change-Id: I70e5bc3f538379f9891ae0ede6cdf09a585520a4
diff --git a/vpd-parser/memory_vpd_parser.cpp b/vpd-parser/memory_vpd_parser.cpp
index 3793ae0..9551e33 100644
--- a/vpd-parser/memory_vpd_parser.cpp
+++ b/vpd-parser/memory_vpd_parser.cpp
@@ -17,10 +17,107 @@
using namespace std;
using namespace openpower::vpd::parser;
+static constexpr auto MEM_BYTE_4 = 4;
+static constexpr auto MEM_BYTE_6 = 6;
+static constexpr auto MEM_BYTE_12 = 12;
+static constexpr auto MEM_BYTE_13 = 13;
+static constexpr auto JEDEC_SDRAM_CAP_MASK = 0x0F;
+static constexpr auto JEDEC_PRI_BUS_WIDTH_MASK = 0x07;
+static constexpr auto JEDEC_SDRAM_WIDTH_MASK = 0x07;
+static constexpr auto JEDEC_NUM_RANKS_MASK = 0x38;
+static constexpr auto JEDEC_DIE_COUNT_MASK = 0x70;
+static constexpr auto JEDEC_SINGLE_LOAD_STACK = 0x02;
+static constexpr auto JEDEC_SIGNAL_LOADING_MASK = 0x03;
+
+static constexpr auto JEDEC_SDRAMCAP_MULTIPLIER = 256;
+static constexpr auto JEDEC_PRI_BUS_WIDTH_MULTIPLIER = 8;
+static constexpr auto JEDEC_SDRAM_WIDTH_MULTIPLIER = 4;
+static constexpr auto JEDEC_SDRAMCAP_RESERVED = 6;
+static constexpr auto JEDEC_RESERVED_BITS = 3;
+static constexpr auto JEDEC_DIE_COUNT_RIGHT_SHIFT = 4;
+
+auto memoryVpdParser::getDimmSize(Binary::const_iterator iterator)
+{
+ size_t tmp = 0, dimmSize = 0;
+
+ size_t sdramCap = 1, priBusWid = 1, sdramWid = 1, logicalRanksPerDimm = 1;
+ Byte dieCount = 1;
+
+ // NOTE: This calculation is Only for DDR4
+
+ // Calculate SDRAM capacity
+ tmp = iterator[MEM_BYTE_4] & JEDEC_SDRAM_CAP_MASK;
+ /* Make sure the bits are not Reserved */
+ if (tmp > JEDEC_SDRAMCAP_RESERVED)
+ {
+ cerr << "Bad data in vpd byte 4. Can't calculate SDRAM capacity and so "
+ "dimm size.\n ";
+ return dimmSize;
+ }
+
+ sdramCap = (sdramCap << tmp) * JEDEC_SDRAMCAP_MULTIPLIER;
+
+ /* Calculate Primary bus width */
+ tmp = iterator[MEM_BYTE_13] & JEDEC_PRI_BUS_WIDTH_MASK;
+ if (tmp > JEDEC_RESERVED_BITS)
+ {
+ cerr << "Bad data in vpd byte 13. Can't calculate primary bus width "
+ "and so dimm size.\n ";
+ return dimmSize;
+ }
+ priBusWid = (priBusWid << tmp) * JEDEC_PRI_BUS_WIDTH_MULTIPLIER;
+
+ /* Calculate SDRAM width */
+ tmp = iterator[MEM_BYTE_12] & JEDEC_SDRAM_WIDTH_MASK;
+ if (tmp > JEDEC_RESERVED_BITS)
+ {
+ cerr << "Bad data in vpd byte 12. Can't calculate SDRAM width and so "
+ "dimm size.\n ";
+ return dimmSize;
+ }
+ sdramWid = (sdramWid << tmp) * JEDEC_SDRAM_WIDTH_MULTIPLIER;
+
+ tmp = iterator[MEM_BYTE_6] & JEDEC_SIGNAL_LOADING_MASK;
+
+ if (tmp == JEDEC_SINGLE_LOAD_STACK)
+ {
+ // Fetch die count
+ tmp = iterator[MEM_BYTE_6] & JEDEC_DIE_COUNT_MASK;
+ tmp >>= JEDEC_DIE_COUNT_RIGHT_SHIFT;
+ dieCount = tmp + 1;
+ }
+
+ /* Calculate Number of ranks */
+ tmp = iterator[MEM_BYTE_12] & JEDEC_NUM_RANKS_MASK;
+ tmp >>= JEDEC_RESERVED_BITS;
+
+ if (tmp > JEDEC_RESERVED_BITS)
+ {
+ cerr << "Can't calculate number of ranks. Invalid data found.\n ";
+ return dimmSize;
+ }
+ logicalRanksPerDimm = (tmp + 1) * dieCount;
+
+ dimmSize = (sdramCap / JEDEC_PRI_BUS_WIDTH_MULTIPLIER) *
+ (priBusWid / sdramWid) * logicalRanksPerDimm;
+
+ return dimmSize;
+}
+
kwdVpdMap memoryVpdParser::readKeywords(Binary::const_iterator iterator)
{
KeywordVpdMap map{};
+ // collect Dimm size value
+ auto dimmSize = getDimmSize(iterator);
+ if (!dimmSize)
+ {
+ cerr << "Error: Calculated dimm size is 0.";
+ }
+
+ map.emplace("MemorySizeInKB", dimmSize);
+ // point the iterator to DIMM data and skip "11S"
+ advance(iterator, MEMORY_VPD_DATA_START + 3);
Binary partNumber(iterator, iterator + PART_NUM_LEN);
advance(iterator, PART_NUM_LEN);
@@ -40,9 +137,6 @@
{
// Read the data and return the map
auto iterator = memVpd.cbegin();
- // point the iterator to DIMM data and skip "11S"
- advance(iterator, MEMORY_VPD_DATA_START + 3);
-
auto vpdDataMap = readKeywords(iterator);
return vpdDataMap;
diff --git a/vpd-parser/memory_vpd_parser.hpp b/vpd-parser/memory_vpd_parser.hpp
index 27efafe..cbd44bb 100644
--- a/vpd-parser/memory_vpd_parser.hpp
+++ b/vpd-parser/memory_vpd_parser.hpp
@@ -58,6 +58,14 @@
*/
kwdVpdMap readKeywords(Binary::const_iterator iterator);
+ /**
+ * @brief This function calculates dimm size from DIMM VPD
+ *
+ * @param[in] iterator - iterator to buffer containing VPD
+ * @return calculated data or 0 in case of any error.
+ */
+ auto getDimmSize(Binary::const_iterator iterator);
+
// vdp file to be parsed
const Binary& memVpd;
};