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/const.hpp b/const.hpp
index e173e89..5cab687 100644
--- a/const.hpp
+++ b/const.hpp
@@ -68,6 +68,7 @@
static constexpr auto PART_NUM_LEN = 7;
static constexpr auto SERIAL_NUM_LEN = 12;
static constexpr auto CCIN_LEN = 4;
+static constexpr auto CONVERT_MB_TO_KB = 1024;
using namespace std::string_literals;
constexpr auto pimPath = "/xyz/openbmc_project/inventory";
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 684b7a7..bb0088f 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -159,8 +159,6 @@
for (const auto& kwVal : map)
{
- vector<uint8_t> vec(kwVal.second.begin(), kwVal.second.end());
-
auto kw = kwVal.first;
if (kw[0] == '#')
@@ -171,7 +169,41 @@
{
kw = string("N_") + kw;
}
- prop.emplace(move(kw), move(vec));
+ if constexpr (is_same<T, KeywordVpdMap>::value)
+ {
+ if (get_if<Binary>(&kwVal.second))
+ {
+ Binary vec(get_if<Binary>(&kwVal.second)->begin(),
+ get_if<Binary>(&kwVal.second)->end());
+
+ prop.emplace(move(kw), move(vec));
+ }
+ else
+ {
+ if (kw == "MemorySizeInKB")
+ {
+ inventory::PropertyMap memProp;
+ auto memVal = get_if<size_t>(&kwVal.second);
+ if (memVal)
+ {
+ memProp.emplace(move(kw),
+ ((*memVal) * CONVERT_MB_TO_KB));
+ interfaces.emplace(
+ "xyz.openbmc_project.Inventory.Item.Dimm",
+ move(memProp));
+ }
+ else
+ {
+ cerr << "MemorySizeInKB value not found in vpd map\n";
+ }
+ }
+ }
+ }
+ else
+ {
+ Binary vec(kwVal.second.begin(), kwVal.second.end());
+ prop.emplace(move(kw), move(vec));
+ }
}
interfaces.emplace(preIntrStr, move(prop));
@@ -259,10 +291,22 @@
{
if (!kw.empty() && vpdMap.count(kw))
{
- auto prop =
- string(vpdMap.at(kw).begin(), vpdMap.at(kw).end());
- auto encoded = encodeKeyword(prop, encoding);
- props.emplace(busProp, encoded);
+ auto kwValue = get_if<Binary>(&vpdMap.at(kw));
+ auto uintValue = get_if<size_t>(&vpdMap.at(kw));
+
+ if (kwValue)
+ {
+ auto prop =
+ string((*kwValue).begin(), (*kwValue).end());
+
+ auto encoded = encodeKeyword(prop, encoding);
+
+ props.emplace(busProp, encoded);
+ }
+ else if (uintValue)
+ {
+ props.emplace(busProp, *uintValue);
+ }
}
}
}
@@ -1069,4 +1113,4 @@
}
return rc;
-}
+}
\ No newline at end of file
diff --git a/test/keyword_vpd_parser_test/kw_vpd_test.cpp b/test/keyword_vpd_parser_test/kw_vpd_test.cpp
index 48c3961..413e31b 100644
--- a/test/keyword_vpd_parser_test/kw_vpd_test.cpp
+++ b/test/keyword_vpd_parser_test/kw_vpd_test.cpp
@@ -38,50 +38,59 @@
TEST_F(KeywordVpdParserTest, GoodTestCase)
{
KeywordVpdParser parserObj1(std::move(keywordVpdVector));
- KeywordVpdMap map1 = {
- {"WI", {0x00}},
- {"FL", {0x50, 0x32, 0x20, 0x20, 0x20}},
- {"SM",
- {0x82, 0x50, 0x32, 0x2d, 0x44, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x32, 0x53, 0x53, 0x43, 0x81, 0x50, 0x32, 0x2d, 0x44, 0x35,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x53, 0x53, 0x43, 0x80,
- 0x50, 0x32, 0x2d, 0x44, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
- 0x32, 0x53, 0x53, 0x43, 0x83, 0x50, 0x32, 0x2d, 0x44, 0x38, 0x20,
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x53, 0x53, 0x43}},
- {"B2",
- {0x50, 0x05, 0x07, 0x60, 0x73, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00}},
- {"MF", {0x00, 0x10}},
- {"VZ", {0x30, 0x33}},
- {"PN", {0x30, 0x31, 0x4b, 0x55, 0x37, 0x32, 0x34}},
- {"FN", {0x20, 0x30, 0x31, 0x4b, 0x55, 0x37, 0x32, 0x34}},
- {"CE", {0x31}},
- {"SN",
- {0x59, 0x48, 0x33, 0x30, 0x42, 0x47, 0x37, 0x38, 0x42, 0x30, 0x31,
- 0x34}},
- {"CC", {0x32, 0x44, 0x33, 0x37}}};
+ KeywordVpdMap map1{
+ pair<std::string, Binary>{"WI", {0x00}},
+ pair<std::string, Binary>{"FL", {0x50, 0x32, 0x20, 0x20, 0x20}},
+ pair<std::string, Binary>{
+ "SM",
+ {0x82, 0x50, 0x32, 0x2d, 0x44, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x32, 0x53, 0x53, 0x43, 0x81, 0x50, 0x32, 0x2d, 0x44, 0x35,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x53, 0x53, 0x43, 0x80,
+ 0x50, 0x32, 0x2d, 0x44, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x32, 0x53, 0x53, 0x43, 0x83, 0x50, 0x32, 0x2d, 0x44, 0x38, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x53, 0x53, 0x43}},
+ pair<std::string, Binary>{"B2",
+ {0x50, 0x05, 0x07, 0x60, 0x73, 0x00, 0x72,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00}},
+ pair<std::string, Binary>{"MF", {0x00, 0x10}},
+ pair<std::string, Binary>{"VZ", {0x30, 0x33}},
+ pair<std::string, Binary>{"PN",
+ {0x30, 0x31, 0x4b, 0x55, 0x37, 0x32, 0x34}},
+ pair<std::string, Binary>{
+ "FN", {0x20, 0x30, 0x31, 0x4b, 0x55, 0x37, 0x32, 0x34}},
+ pair<std::string, Binary>{"CE", {0x31}},
+ pair<std::string, Binary>{"SN",
+ {0x59, 0x48, 0x33, 0x30, 0x42, 0x47, 0x37,
+ 0x38, 0x42, 0x30, 0x31, 0x34}},
+ pair<std::string, Binary>{"CC", {0x32, 0x44, 0x33, 0x37}}};
auto map2 = std::move(get<KeywordVpdMap>(parserObj1.parse()));
ASSERT_EQ(1, map1 == map2);
// BONO TYPE VPD
KeywordVpdParser parserObj2(std::move(bonoKwVpdVector));
- map1 = {{"B2",
- {0x50, 0x0, 0xb3, 0xe0, 0x90, 0x0, 0x2, 0x50, 0x0, 0x0, 0x0, 0x0,
- 0x0, 0x0, 0x0, 0x0}},
- {"CC", {0x35, 0x39, 0x33, 0x42}},
- {"CT", {0x50, 0x37, 0x32, 0x0}},
- {"EC", {0x50, 0x34, 0x35, 0x35, 0x33, 0x37}},
- {"FN", {0x30, 0x32, 0x44, 0x45, 0x33, 0x36, 0x35}},
- {"PN", {0x30, 0x32, 0x44, 0x45, 0x33, 0x36, 0x36}},
- {"RV", {0xa1}},
- {"SI", {0x31, 0x30, 0x31, 0x34, 0x30, 0x36, 0x37, 0x34}},
- {"SN",
- {0x59, 0x4c, 0x35, 0x30, 0x48, 0x54, 0x39, 0x36, 0x4a, 0x30, 0x30,
- 0x38}},
- {"Z4", {0x30}},
- {"Z5", {0x30}},
- {"Z6", {0x41, 0x31, 0x38, 0x30, 0x30, 0x32, 0x30, 0x30}}};
+ map1 = {
+ pair<std::string, Binary>{"B2",
+ {0x50, 0x0, 0xb3, 0xe0, 0x90, 0x0, 0x2, 0x50,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
+ pair<std::string, Binary>{"CC", {0x35, 0x39, 0x33, 0x42}},
+ pair<std::string, Binary>{"CT", {0x50, 0x37, 0x32, 0x0}},
+ pair<std::string, Binary>{"EC", {0x50, 0x34, 0x35, 0x35, 0x33, 0x37}},
+ pair<std::string, Binary>{"FN",
+ {0x30, 0x32, 0x44, 0x45, 0x33, 0x36, 0x35}},
+ pair<std::string, Binary>{"PN",
+ {0x30, 0x32, 0x44, 0x45, 0x33, 0x36, 0x36}},
+ pair<std::string, Binary>{"RV", {0xa1}},
+ pair<std::string, Binary>{
+ "SI", {0x31, 0x30, 0x31, 0x34, 0x30, 0x36, 0x37, 0x34}},
+ pair<std::string, Binary>{"SN",
+ {0x59, 0x4c, 0x35, 0x30, 0x48, 0x54, 0x39,
+ 0x36, 0x4a, 0x30, 0x30, 0x38}},
+ pair<std::string, Binary>{"Z4", {0x30}},
+ pair<std::string, Binary>{"Z5", {0x30}},
+ pair<std::string, Binary>{
+ "Z6", {0x41, 0x31, 0x38, 0x30, 0x30, 0x32, 0x30, 0x30}}};
map2 = std::move(get<KeywordVpdMap>(parserObj2.parse()));
ASSERT_EQ(1, map1 == map2);
@@ -201,4 +210,4 @@
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
-}
+}
\ No newline at end of file
diff --git a/types.hpp b/types.hpp
index 8c5c6e1..080a976 100644
--- a/types.hpp
+++ b/types.hpp
@@ -23,8 +23,9 @@
using Path = std::string;
using Property = std::string;
-using Value = std::variant<bool, int64_t, std::string, Binary>;
+using Value = std::variant<bool, size_t, int64_t, std::string, Binary>;
using PropertyMap = std::map<Property, Value>;
+using kwdVpdValueTypes = std::variant<size_t, Binary>;
using Interface = std::string;
using InterfaceMap = std::map<Interface, PropertyMap>;
@@ -40,7 +41,7 @@
using ListOfPaths = std::vector<sdbusplus::message::object_path>;
using NodeNumber = uint16_t;
using namespace std::string_literals;
-using KeywordVpdMap = std::unordered_map<std::string, Binary>;
+using KeywordVpdMap = std::unordered_map<std::string, kwdVpdValueTypes>;
using systemType = std::string;
using deviceTree = std::string;
@@ -58,4 +59,4 @@
} // namespace inventory
} // namespace vpd
-} // namespace openpower
+} // namespace openpower
\ No newline at end of file
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;
};