xref: /openbmc/smbios-mdr/src/dimm.cpp (revision 5a122a6e1b620e79c5c6807e83f1cd75fe872fb6)
18c3fab63SCheng C Yang /*
28c3fab63SCheng C Yang // Copyright (c) 2018 Intel Corporation
38c3fab63SCheng C Yang //
48c3fab63SCheng C Yang // Licensed under the Apache License, Version 2.0 (the "License");
58c3fab63SCheng C Yang // you may not use this file except in compliance with the License.
68c3fab63SCheng C Yang // You may obtain a copy of the License at
78c3fab63SCheng C Yang //
88c3fab63SCheng C Yang //      http://www.apache.org/licenses/LICENSE-2.0
98c3fab63SCheng C Yang //
108c3fab63SCheng C Yang // Unless required by applicable law or agreed to in writing, software
118c3fab63SCheng C Yang // distributed under the License is distributed on an "AS IS" BASIS,
128c3fab63SCheng C Yang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138c3fab63SCheng C Yang // See the License for the specific language governing permissions and
148c3fab63SCheng C Yang // limitations under the License.
158c3fab63SCheng C Yang */
168c3fab63SCheng C Yang 
178c3fab63SCheng C Yang #include "dimm.hpp"
188c3fab63SCheng C Yang 
198c3fab63SCheng C Yang #include "mdrv2.hpp"
208c3fab63SCheng C Yang 
21634ec6aeSkasunath #include <boost/algorithm/string.hpp>
222eca4fe5Skasunath #include <phosphor-logging/elog-errors.hpp>
23634ec6aeSkasunath 
248c3fab63SCheng C Yang namespace phosphor
258c3fab63SCheng C Yang {
268c3fab63SCheng C Yang namespace smbios
278c3fab63SCheng C Yang {
288c3fab63SCheng C Yang 
29efd41540SJohn Edward Broadbent #ifdef DIMM_ONLY_LOCATOR
30efd41540SJohn Edward Broadbent bool onlyDimmLocationCode = true;
31efd41540SJohn Edward Broadbent #else
32efd41540SJohn Edward Broadbent bool onlyDimmLocationCode = false;
33efd41540SJohn Edward Broadbent #endif
34efd41540SJohn Edward Broadbent 
358c3fab63SCheng C Yang using DeviceType =
3633ae81feSJason M. Bills     sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::DeviceType;
378c3fab63SCheng C Yang 
382eca4fe5Skasunath using EccType =
3933ae81feSJason M. Bills     sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::Ecc;
402eca4fe5Skasunath 
418c3fab63SCheng C Yang static constexpr uint16_t maxOldDimmSize = 0x7fff;
42*5a122a6eSBrandon Kim void Dimm::memoryInfoUpdate(uint8_t* smbiosTableStorage,
43*5a122a6eSBrandon Kim                             const std::string& motherboard)
448c3fab63SCheng C Yang {
45*5a122a6eSBrandon Kim     storage = smbiosTableStorage;
46*5a122a6eSBrandon Kim     motherboardPath = motherboard;
47*5a122a6eSBrandon Kim 
488c3fab63SCheng C Yang     uint8_t* dataIn = storage;
498c3fab63SCheng C Yang 
508c3fab63SCheng C Yang     dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
518c3fab63SCheng C Yang 
528c3fab63SCheng C Yang     if (dataIn == nullptr)
538c3fab63SCheng C Yang     {
548c3fab63SCheng C Yang         return;
558c3fab63SCheng C Yang     }
568c3fab63SCheng C Yang     for (uint8_t index = 0; index < dimmNum; index++)
578c3fab63SCheng C Yang     {
588c3fab63SCheng C Yang         dataIn = smbiosNextPtr(dataIn);
598c3fab63SCheng C Yang         if (dataIn == nullptr)
608c3fab63SCheng C Yang         {
618c3fab63SCheng C Yang             return;
628c3fab63SCheng C Yang         }
638c3fab63SCheng C Yang         dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
648c3fab63SCheng C Yang         if (dataIn == nullptr)
658c3fab63SCheng C Yang         {
668c3fab63SCheng C Yang             return;
678c3fab63SCheng C Yang         }
688c3fab63SCheng C Yang     }
698c3fab63SCheng C Yang 
708c3fab63SCheng C Yang     auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);
718c3fab63SCheng C Yang 
728c3fab63SCheng C Yang     memoryDataWidth(memoryInfo->dataWidth);
738c3fab63SCheng C Yang 
748c3fab63SCheng C Yang     if (memoryInfo->size == maxOldDimmSize)
758c3fab63SCheng C Yang     {
768c3fab63SCheng C Yang         dimmSizeExt(memoryInfo->extendedSize);
778c3fab63SCheng C Yang     }
788c3fab63SCheng C Yang     else
798c3fab63SCheng C Yang     {
808c3fab63SCheng C Yang         dimmSize(memoryInfo->size);
818c3fab63SCheng C Yang     }
8239cc3683STom Tung     // If the size is 0, no memory device is installed in the socket.
8339cc3683STom Tung     const auto isDimmPresent = memoryInfo->size > 0;
8439cc3683STom Tung     present(isDimmPresent);
8539cc3683STom Tung     functional(isDimmPresent);
868c3fab63SCheng C Yang 
87744b35aaSKonstantin Aladyshev     dimmDeviceLocator(memoryInfo->bankLocator, memoryInfo->deviceLocator,
88744b35aaSKonstantin Aladyshev                       memoryInfo->length, dataIn);
898c3fab63SCheng C Yang     dimmType(memoryInfo->memoryType);
908c3fab63SCheng C Yang     dimmTypeDetail(memoryInfo->typeDetail);
918c3fab63SCheng C Yang     maxMemorySpeedInMhz(memoryInfo->speed);
928c3fab63SCheng C Yang     dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
938c3fab63SCheng C Yang     dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
948c3fab63SCheng C Yang     dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
958c3fab63SCheng C Yang     memoryAttributes(memoryInfo->attributes);
968c3fab63SCheng C Yang     memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
978c3fab63SCheng C Yang 
982eca4fe5Skasunath     updateEccType(memoryInfo->phyArrayHandle);
992eca4fe5Skasunath 
100e7cf3195SJie Yang     if (!motherboardPath.empty())
101e7cf3195SJie Yang     {
102e7cf3195SJie Yang         std::vector<std::tuple<std::string, std::string, std::string>> assocs;
103e7cf3195SJie Yang         assocs.emplace_back("chassis", "memories", motherboardPath);
104e7cf3195SJie Yang         association::associations(assocs);
105e7cf3195SJie Yang     }
106e7cf3195SJie Yang 
1078c3fab63SCheng C Yang     return;
1088c3fab63SCheng C Yang }
1098c3fab63SCheng C Yang 
1102eca4fe5Skasunath void Dimm::updateEccType(uint16_t exPhyArrayHandle)
1112eca4fe5Skasunath {
1122eca4fe5Skasunath     uint8_t* dataIn = storage;
1132eca4fe5Skasunath 
1142eca4fe5Skasunath     while (dataIn != nullptr)
1152eca4fe5Skasunath     {
1162eca4fe5Skasunath         dataIn = getSMBIOSTypePtr(dataIn, physicalMemoryArrayType);
1172eca4fe5Skasunath         if (dataIn == nullptr)
1182eca4fe5Skasunath         {
1192eca4fe5Skasunath             phosphor::logging::log<phosphor::logging::level::ERR>(
1202eca4fe5Skasunath                 "Failed to get SMBIOS table type-16 data.");
1212eca4fe5Skasunath             return;
1222eca4fe5Skasunath         }
1232eca4fe5Skasunath 
1242eca4fe5Skasunath         auto info = reinterpret_cast<struct PhysicalMemoryArrayInfo*>(dataIn);
1252eca4fe5Skasunath         if (info->handle == exPhyArrayHandle)
1262eca4fe5Skasunath         {
1272eca4fe5Skasunath             std::map<uint8_t, EccType>::const_iterator it =
1282eca4fe5Skasunath                 dimmEccTypeMap.find(info->memoryErrorCorrection);
1292eca4fe5Skasunath             if (it == dimmEccTypeMap.end())
1302eca4fe5Skasunath             {
1312eca4fe5Skasunath                 ecc(EccType::NoECC);
1322eca4fe5Skasunath             }
1332eca4fe5Skasunath             else
1342eca4fe5Skasunath             {
1352eca4fe5Skasunath                 ecc(it->second);
1362eca4fe5Skasunath             }
1372eca4fe5Skasunath             return;
1382eca4fe5Skasunath         }
1392eca4fe5Skasunath 
1402eca4fe5Skasunath         dataIn = smbiosNextPtr(dataIn);
1412eca4fe5Skasunath     }
1422eca4fe5Skasunath     phosphor::logging::log<phosphor::logging::level::ERR>(
1432eca4fe5Skasunath         "Failed find the corresponding SMBIOS table type-16 data for dimm:",
1442eca4fe5Skasunath         phosphor::logging::entry("DIMM:%d", dimmNum));
1452eca4fe5Skasunath }
1462eca4fe5Skasunath 
1472eca4fe5Skasunath EccType Dimm::ecc(EccType value)
1482eca4fe5Skasunath {
14933ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::ecc(
1502eca4fe5Skasunath         value);
1512eca4fe5Skasunath }
1522eca4fe5Skasunath 
1538c3fab63SCheng C Yang uint16_t Dimm::memoryDataWidth(uint16_t value)
1548c3fab63SCheng C Yang {
15533ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
1568c3fab63SCheng C Yang         memoryDataWidth(value);
1578c3fab63SCheng C Yang }
1588c3fab63SCheng C Yang 
1598c3fab63SCheng C Yang static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
1608c3fab63SCheng C Yang static constexpr uint16_t dimmSizeUnit = 1024;
1618c3fab63SCheng C Yang void Dimm::dimmSize(const uint16_t size)
1628c3fab63SCheng C Yang {
1630b1d942dSJoseph Fu     uint32_t result = size & maxOldDimmSize;
1648c3fab63SCheng C Yang     if (0 == (size & baseNewVersionDimmSize))
1658c3fab63SCheng C Yang     {
1668c3fab63SCheng C Yang         result = result * dimmSizeUnit;
1678c3fab63SCheng C Yang     }
1688c3fab63SCheng C Yang     memorySizeInKB(result);
1698c3fab63SCheng C Yang }
1708c3fab63SCheng C Yang 
1710b1d942dSJoseph Fu void Dimm::dimmSizeExt(uint32_t size)
1728c3fab63SCheng C Yang {
1738c3fab63SCheng C Yang     size = size * dimmSizeUnit;
1748c3fab63SCheng C Yang     memorySizeInKB(size);
1758c3fab63SCheng C Yang }
1768c3fab63SCheng C Yang 
177e7770991SJason M. Bills size_t Dimm::memorySizeInKB(size_t value)
1788c3fab63SCheng C Yang {
17933ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
1808c3fab63SCheng C Yang         memorySizeInKB(value);
1818c3fab63SCheng C Yang }
1828c3fab63SCheng C Yang 
183744b35aaSKonstantin Aladyshev void Dimm::dimmDeviceLocator(const uint8_t bankLocatorPositionNum,
184744b35aaSKonstantin Aladyshev                              const uint8_t deviceLocatorPositionNum,
185744b35aaSKonstantin Aladyshev                              const uint8_t structLen, uint8_t* dataIn)
1868c3fab63SCheng C Yang {
187c39d3dfcSPatrick Williams     std::string deviceLocator = positionToString(deviceLocatorPositionNum,
188c39d3dfcSPatrick Williams                                                  structLen, dataIn);
189c39d3dfcSPatrick Williams     std::string bankLocator = positionToString(bankLocatorPositionNum,
190c39d3dfcSPatrick Williams                                                structLen, dataIn);
191744b35aaSKonstantin Aladyshev 
192744b35aaSKonstantin Aladyshev     std::string result;
193efd41540SJohn Edward Broadbent     if (bankLocator.empty() || onlyDimmLocationCode)
194744b35aaSKonstantin Aladyshev     {
195efd41540SJohn Edward Broadbent         result = deviceLocator;
196744b35aaSKonstantin Aladyshev     }
197744b35aaSKonstantin Aladyshev     else
198744b35aaSKonstantin Aladyshev     {
199efd41540SJohn Edward Broadbent         result = bankLocator + " " + deviceLocator;
200744b35aaSKonstantin Aladyshev     }
2018c3fab63SCheng C Yang 
2028c3fab63SCheng C Yang     memoryDeviceLocator(result);
20331720397SJie Yang 
20431720397SJie Yang     locationCode(result);
2058c3fab63SCheng C Yang }
2068c3fab63SCheng C Yang 
2078c3fab63SCheng C Yang std::string Dimm::memoryDeviceLocator(std::string value)
2088c3fab63SCheng C Yang {
20933ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
2108c3fab63SCheng C Yang         memoryDeviceLocator(value);
2118c3fab63SCheng C Yang }
2128c3fab63SCheng C Yang 
2138c3fab63SCheng C Yang void Dimm::dimmType(const uint8_t type)
2148c3fab63SCheng C Yang {
2158c3fab63SCheng C Yang     std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
2168c3fab63SCheng C Yang     if (it == dimmTypeTable.end())
2178c3fab63SCheng C Yang     {
2188c3fab63SCheng C Yang         memoryType(DeviceType::Unknown);
2198c3fab63SCheng C Yang     }
2208c3fab63SCheng C Yang     else
2218c3fab63SCheng C Yang     {
2228c3fab63SCheng C Yang         memoryType(it->second);
2238c3fab63SCheng C Yang     }
2248c3fab63SCheng C Yang }
2258c3fab63SCheng C Yang 
2268c3fab63SCheng C Yang DeviceType Dimm::memoryType(DeviceType value)
2278c3fab63SCheng C Yang {
22833ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
2298c3fab63SCheng C Yang         memoryType(value);
2308c3fab63SCheng C Yang }
2318c3fab63SCheng C Yang 
2328c3fab63SCheng C Yang void Dimm::dimmTypeDetail(uint16_t detail)
2338c3fab63SCheng C Yang {
2348c3fab63SCheng C Yang     std::string result;
2358c3fab63SCheng C Yang     for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
2368c3fab63SCheng C Yang     {
2378c3fab63SCheng C Yang         if (detail & 0x01)
2388c3fab63SCheng C Yang         {
2398c3fab63SCheng C Yang             result += detailTable[index];
2408c3fab63SCheng C Yang         }
2418c3fab63SCheng C Yang         detail >>= 1;
2428c3fab63SCheng C Yang     }
2438c3fab63SCheng C Yang     memoryTypeDetail(result);
2448c3fab63SCheng C Yang }
2458c3fab63SCheng C Yang 
2468c3fab63SCheng C Yang std::string Dimm::memoryTypeDetail(std::string value)
2478c3fab63SCheng C Yang {
24833ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
2498c3fab63SCheng C Yang         memoryTypeDetail(value);
2508c3fab63SCheng C Yang }
2518c3fab63SCheng C Yang 
2528c3fab63SCheng C Yang uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
2538c3fab63SCheng C Yang {
25433ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
2558c3fab63SCheng C Yang         maxMemorySpeedInMhz(value);
2568c3fab63SCheng C Yang }
2578c3fab63SCheng C Yang 
2588c3fab63SCheng C Yang void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
2598c3fab63SCheng C Yang                             uint8_t* dataIn)
2608c3fab63SCheng C Yang {
2618c3fab63SCheng C Yang     std::string result = positionToString(positionNum, structLen, dataIn);
2628c3fab63SCheng C Yang 
26333c948a4SJoshi-Mansi     if (result == "NO DIMM")
26433c948a4SJoshi-Mansi     {
26533c948a4SJoshi-Mansi         // No dimm presence so making manufacturer value as "" (instead of
26633c948a4SJoshi-Mansi         // NO DIMM - as there won't be any manufacturer for DIMM which is not
26733c948a4SJoshi-Mansi         // present).
26833c948a4SJoshi-Mansi         result = "";
26933c948a4SJoshi-Mansi     }
2708c3fab63SCheng C Yang     manufacturer(result);
2718c3fab63SCheng C Yang }
2728c3fab63SCheng C Yang 
2738c3fab63SCheng C Yang std::string Dimm::manufacturer(std::string value)
2748c3fab63SCheng C Yang {
27533ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
2768c3fab63SCheng C Yang         Asset::manufacturer(value);
2778c3fab63SCheng C Yang }
2788c3fab63SCheng C Yang 
27933c948a4SJoshi-Mansi bool Dimm::present(bool value)
28033c948a4SJoshi-Mansi {
28133ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::Item::present(
28233c948a4SJoshi-Mansi         value);
28333c948a4SJoshi-Mansi }
28433c948a4SJoshi-Mansi 
2858c3fab63SCheng C Yang void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
2868c3fab63SCheng C Yang                          uint8_t* dataIn)
2878c3fab63SCheng C Yang {
2888c3fab63SCheng C Yang     std::string result = positionToString(positionNum, structLen, dataIn);
2898c3fab63SCheng C Yang 
2908c3fab63SCheng C Yang     serialNumber(result);
2918c3fab63SCheng C Yang }
2928c3fab63SCheng C Yang 
2938c3fab63SCheng C Yang std::string Dimm::serialNumber(std::string value)
2948c3fab63SCheng C Yang {
29533ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
2968c3fab63SCheng C Yang         Asset::serialNumber(value);
2978c3fab63SCheng C Yang }
2988c3fab63SCheng C Yang 
2998c3fab63SCheng C Yang void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
3008c3fab63SCheng C Yang                        uint8_t* dataIn)
3018c3fab63SCheng C Yang {
3028c3fab63SCheng C Yang     std::string result = positionToString(positionNum, structLen, dataIn);
3038c3fab63SCheng C Yang 
304634ec6aeSkasunath     // Part number could contain spaces at the end. Eg: "abcd123  ". Since its
305634ec6aeSkasunath     // unnecessary, we should remove them.
306634ec6aeSkasunath     boost::algorithm::trim_right(result);
3078c3fab63SCheng C Yang     partNumber(result);
3088c3fab63SCheng C Yang }
3098c3fab63SCheng C Yang 
3108c3fab63SCheng C Yang std::string Dimm::partNumber(std::string value)
3118c3fab63SCheng C Yang {
31233ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
3138c3fab63SCheng C Yang         Asset::partNumber(value);
3148c3fab63SCheng C Yang }
3158c3fab63SCheng C Yang 
31631720397SJie Yang std::string Dimm::locationCode(std::string value)
31731720397SJie Yang {
31833ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::decorator::
31931720397SJie Yang         LocationCode::locationCode(value);
32031720397SJie Yang }
32131720397SJie Yang 
3228c3fab63SCheng C Yang uint8_t Dimm::memoryAttributes(uint8_t value)
3238c3fab63SCheng C Yang {
32433ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
3258c3fab63SCheng C Yang         memoryAttributes(value);
3268c3fab63SCheng C Yang }
3278c3fab63SCheng C Yang 
3288c3fab63SCheng C Yang uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
3298c3fab63SCheng C Yang {
33033ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::inventory::item::Dimm::
3318c3fab63SCheng C Yang         memoryConfiguredSpeedInMhz(value);
3328c3fab63SCheng C Yang }
3338c3fab63SCheng C Yang 
334dc469c74STim Lee bool Dimm::functional(bool value)
335dc469c74STim Lee {
33633ae81feSJason M. Bills     return sdbusplus::server::xyz::openbmc_project::state::decorator::
337dc469c74STim Lee         OperationalStatus::functional(value);
338dc469c74STim Lee }
339dc469c74STim Lee 
3408c3fab63SCheng C Yang } // namespace smbios
3418c3fab63SCheng C Yang } // namespace phosphor
342