blob: 6928c8b3dc7ee7da8ede56ea3d8155b9b7ebb48e [file] [log] [blame]
Cheng C Yang8c3fab62019-12-19 00:51:06 +08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#include "dimm.hpp"
18
19#include "mdrv2.hpp"
20
kasunath634ec6a2022-07-25 15:34:17 -070021#include <boost/algorithm/string.hpp>
kasunath2eca4fe2022-08-17 17:30:07 -070022#include <phosphor-logging/elog-errors.hpp>
kasunath634ec6a2022-07-25 15:34:17 -070023
Cheng C Yang8c3fab62019-12-19 00:51:06 +080024namespace phosphor
25{
26namespace smbios
27{
28
29using DeviceType =
30 sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType;
31
kasunath2eca4fe2022-08-17 17:30:07 -070032using EccType =
33 sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::Ecc;
34
Cheng C Yang8c3fab62019-12-19 00:51:06 +080035static constexpr uint16_t maxOldDimmSize = 0x7fff;
36void Dimm::memoryInfoUpdate(void)
37{
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080038 uint8_t* dataIn = storage;
Cheng C Yang8c3fab62019-12-19 00:51:06 +080039
40 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
41
42 if (dataIn == nullptr)
43 {
44 return;
45 }
46 for (uint8_t index = 0; index < dimmNum; index++)
47 {
48 dataIn = smbiosNextPtr(dataIn);
49 if (dataIn == nullptr)
50 {
51 return;
52 }
53 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
54 if (dataIn == nullptr)
55 {
56 return;
57 }
58 }
59
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080060 auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080061
62 memoryDataWidth(memoryInfo->dataWidth);
63
64 if (memoryInfo->size == maxOldDimmSize)
65 {
66 dimmSizeExt(memoryInfo->extendedSize);
67 }
68 else
69 {
70 dimmSize(memoryInfo->size);
71 }
72
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +000073 dimmDeviceLocator(memoryInfo->bankLocator, memoryInfo->deviceLocator,
74 memoryInfo->length, dataIn);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080075 dimmType(memoryInfo->memoryType);
76 dimmTypeDetail(memoryInfo->typeDetail);
77 maxMemorySpeedInMhz(memoryInfo->speed);
78 dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
79 dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
80 dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
81 memoryAttributes(memoryInfo->attributes);
82 memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
83
kasunath2eca4fe2022-08-17 17:30:07 -070084 updateEccType(memoryInfo->phyArrayHandle);
85
Jie Yange7cf3192021-08-20 11:21:43 -070086 if (!motherboardPath.empty())
87 {
88 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
89 assocs.emplace_back("chassis", "memories", motherboardPath);
90 association::associations(assocs);
91 }
92
Cheng C Yang8c3fab62019-12-19 00:51:06 +080093 return;
94}
95
kasunath2eca4fe2022-08-17 17:30:07 -070096void Dimm::updateEccType(uint16_t exPhyArrayHandle)
97{
98 uint8_t* dataIn = storage;
99
100 while (dataIn != nullptr)
101 {
102 dataIn = getSMBIOSTypePtr(dataIn, physicalMemoryArrayType);
103 if (dataIn == nullptr)
104 {
105 phosphor::logging::log<phosphor::logging::level::ERR>(
106 "Failed to get SMBIOS table type-16 data.");
107 return;
108 }
109
110 auto info = reinterpret_cast<struct PhysicalMemoryArrayInfo*>(dataIn);
111 if (info->handle == exPhyArrayHandle)
112 {
113 std::map<uint8_t, EccType>::const_iterator it =
114 dimmEccTypeMap.find(info->memoryErrorCorrection);
115 if (it == dimmEccTypeMap.end())
116 {
117 ecc(EccType::NoECC);
118 }
119 else
120 {
121 ecc(it->second);
122 }
123 return;
124 }
125
126 dataIn = smbiosNextPtr(dataIn);
127 }
128 phosphor::logging::log<phosphor::logging::level::ERR>(
129 "Failed find the corresponding SMBIOS table type-16 data for dimm:",
130 phosphor::logging::entry("DIMM:%d", dimmNum));
131}
132
133EccType Dimm::ecc(EccType value)
134{
135 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::ecc(
136 value);
137}
138
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800139uint16_t Dimm::memoryDataWidth(uint16_t value)
140{
141 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
142 memoryDataWidth(value);
143}
144
145static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
146static constexpr uint16_t dimmSizeUnit = 1024;
147void Dimm::dimmSize(const uint16_t size)
148{
Jason M. Billse7770992021-05-14 13:24:33 -0700149 size_t result = size & maxOldDimmSize;
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800150 if (0 == (size & baseNewVersionDimmSize))
151 {
152 result = result * dimmSizeUnit;
153 }
154 memorySizeInKB(result);
155}
156
Jason M. Billse7770992021-05-14 13:24:33 -0700157void Dimm::dimmSizeExt(size_t size)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800158{
159 size = size * dimmSizeUnit;
160 memorySizeInKB(size);
161}
162
Jason M. Billse7770992021-05-14 13:24:33 -0700163size_t Dimm::memorySizeInKB(size_t value)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800164{
165 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
166 memorySizeInKB(value);
167}
168
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000169void Dimm::dimmDeviceLocator(const uint8_t bankLocatorPositionNum,
170 const uint8_t deviceLocatorPositionNum,
171 const uint8_t structLen, uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800172{
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000173 std::string deviceLocator =
174 positionToString(deviceLocatorPositionNum, structLen, dataIn);
175 std::string bankLocator =
176 positionToString(bankLocatorPositionNum, structLen, dataIn);
177
178 std::string result;
179 if (!bankLocator.empty())
180 {
181 result = bankLocator + " " + deviceLocator;
182 }
183 else
184 {
185 result = deviceLocator;
186 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800187
188 memoryDeviceLocator(result);
Jie Yang31720392021-07-22 21:45:45 -0700189
190 locationCode(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800191}
192
193std::string Dimm::memoryDeviceLocator(std::string value)
194{
195 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
196 memoryDeviceLocator(value);
197}
198
199void Dimm::dimmType(const uint8_t type)
200{
201 std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
202 if (it == dimmTypeTable.end())
203 {
204 memoryType(DeviceType::Unknown);
205 }
206 else
207 {
208 memoryType(it->second);
209 }
210}
211
212DeviceType Dimm::memoryType(DeviceType value)
213{
214 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
215 memoryType(value);
216}
217
218void Dimm::dimmTypeDetail(uint16_t detail)
219{
220 std::string result;
221 for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
222 {
223 if (detail & 0x01)
224 {
225 result += detailTable[index];
226 }
227 detail >>= 1;
228 }
229 memoryTypeDetail(result);
230}
231
232std::string Dimm::memoryTypeDetail(std::string value)
233{
234 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
235 memoryTypeDetail(value);
236}
237
238uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
239{
240 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
241 maxMemorySpeedInMhz(value);
242}
243
244void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800245 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800246{
247 std::string result = positionToString(positionNum, structLen, dataIn);
248
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530249 bool val = true;
250 if (result == "NO DIMM")
251 {
252 val = false;
253
254 // No dimm presence so making manufacturer value as "" (instead of
255 // NO DIMM - as there won't be any manufacturer for DIMM which is not
256 // present).
257 result = "";
258 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800259 manufacturer(result);
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530260 present(val);
Tim Leedc469c72021-07-20 10:55:58 +0800261 functional(val);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800262}
263
264std::string Dimm::manufacturer(std::string value)
265{
266 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
267 Asset::manufacturer(value);
268}
269
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530270bool Dimm::present(bool value)
271{
272 return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present(
273 value);
274}
275
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800276void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800277 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800278{
279 std::string result = positionToString(positionNum, structLen, dataIn);
280
281 serialNumber(result);
282}
283
284std::string Dimm::serialNumber(std::string value)
285{
286 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
287 Asset::serialNumber(value);
288}
289
290void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800291 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800292{
293 std::string result = positionToString(positionNum, structLen, dataIn);
294
kasunath634ec6a2022-07-25 15:34:17 -0700295 // Part number could contain spaces at the end. Eg: "abcd123 ". Since its
296 // unnecessary, we should remove them.
297 boost::algorithm::trim_right(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800298 partNumber(result);
299}
300
301std::string Dimm::partNumber(std::string value)
302{
303 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
304 Asset::partNumber(value);
305}
306
Jie Yang31720392021-07-22 21:45:45 -0700307std::string Dimm::locationCode(std::string value)
308{
309 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
310 LocationCode::locationCode(value);
311}
312
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800313uint8_t Dimm::memoryAttributes(uint8_t value)
314{
315 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
316 memoryAttributes(value);
317}
318
319uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
320{
321 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
322 memoryConfiguredSpeedInMhz(value);
323}
324
Tim Leedc469c72021-07-20 10:55:58 +0800325bool Dimm::functional(bool value)
326{
327 return sdbusplus::xyz::openbmc_project::State::Decorator::server::
328 OperationalStatus::functional(value);
329}
330
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800331} // namespace smbios
332} // namespace phosphor