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