blob: 9cc7ef302416b9912115c82e8d3db7fcbc45c3d8 [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
John Edward Broadbentefd41542022-12-13 16:39:18 -080029#ifdef DIMM_ONLY_LOCATOR
30bool onlyDimmLocationCode = true;
31#else
32bool onlyDimmLocationCode = false;
33#endif
34
Cheng C Yang8c3fab62019-12-19 00:51:06 +080035using DeviceType =
36 sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType;
37
kasunath2eca4fe2022-08-17 17:30:07 -070038using EccType =
39 sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::Ecc;
40
Cheng C Yang8c3fab62019-12-19 00:51:06 +080041static constexpr uint16_t maxOldDimmSize = 0x7fff;
42void Dimm::memoryInfoUpdate(void)
43{
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080044 uint8_t* dataIn = storage;
Cheng C Yang8c3fab62019-12-19 00:51:06 +080045
46 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
47
48 if (dataIn == nullptr)
49 {
50 return;
51 }
52 for (uint8_t index = 0; index < dimmNum; index++)
53 {
54 dataIn = smbiosNextPtr(dataIn);
55 if (dataIn == nullptr)
56 {
57 return;
58 }
59 dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
60 if (dataIn == nullptr)
61 {
62 return;
63 }
64 }
65
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +080066 auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080067
68 memoryDataWidth(memoryInfo->dataWidth);
69
70 if (memoryInfo->size == maxOldDimmSize)
71 {
72 dimmSizeExt(memoryInfo->extendedSize);
73 }
74 else
75 {
76 dimmSize(memoryInfo->size);
77 }
78
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +000079 dimmDeviceLocator(memoryInfo->bankLocator, memoryInfo->deviceLocator,
80 memoryInfo->length, dataIn);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080081 dimmType(memoryInfo->memoryType);
82 dimmTypeDetail(memoryInfo->typeDetail);
83 maxMemorySpeedInMhz(memoryInfo->speed);
84 dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
85 dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
86 dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
87 memoryAttributes(memoryInfo->attributes);
88 memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
89
kasunath2eca4fe2022-08-17 17:30:07 -070090 updateEccType(memoryInfo->phyArrayHandle);
91
Jie Yange7cf3192021-08-20 11:21:43 -070092 if (!motherboardPath.empty())
93 {
94 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
95 assocs.emplace_back("chassis", "memories", motherboardPath);
96 association::associations(assocs);
97 }
98
Cheng C Yang8c3fab62019-12-19 00:51:06 +080099 return;
100}
101
kasunath2eca4fe2022-08-17 17:30:07 -0700102void Dimm::updateEccType(uint16_t exPhyArrayHandle)
103{
104 uint8_t* dataIn = storage;
105
106 while (dataIn != nullptr)
107 {
108 dataIn = getSMBIOSTypePtr(dataIn, physicalMemoryArrayType);
109 if (dataIn == nullptr)
110 {
111 phosphor::logging::log<phosphor::logging::level::ERR>(
112 "Failed to get SMBIOS table type-16 data.");
113 return;
114 }
115
116 auto info = reinterpret_cast<struct PhysicalMemoryArrayInfo*>(dataIn);
117 if (info->handle == exPhyArrayHandle)
118 {
119 std::map<uint8_t, EccType>::const_iterator it =
120 dimmEccTypeMap.find(info->memoryErrorCorrection);
121 if (it == dimmEccTypeMap.end())
122 {
123 ecc(EccType::NoECC);
124 }
125 else
126 {
127 ecc(it->second);
128 }
129 return;
130 }
131
132 dataIn = smbiosNextPtr(dataIn);
133 }
134 phosphor::logging::log<phosphor::logging::level::ERR>(
135 "Failed find the corresponding SMBIOS table type-16 data for dimm:",
136 phosphor::logging::entry("DIMM:%d", dimmNum));
137}
138
139EccType Dimm::ecc(EccType value)
140{
141 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::ecc(
142 value);
143}
144
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800145uint16_t Dimm::memoryDataWidth(uint16_t value)
146{
147 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
148 memoryDataWidth(value);
149}
150
151static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
152static constexpr uint16_t dimmSizeUnit = 1024;
153void Dimm::dimmSize(const uint16_t size)
154{
Jason M. Billse7770992021-05-14 13:24:33 -0700155 size_t result = size & maxOldDimmSize;
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800156 if (0 == (size & baseNewVersionDimmSize))
157 {
158 result = result * dimmSizeUnit;
159 }
160 memorySizeInKB(result);
161}
162
Jason M. Billse7770992021-05-14 13:24:33 -0700163void Dimm::dimmSizeExt(size_t size)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800164{
165 size = size * dimmSizeUnit;
166 memorySizeInKB(size);
167}
168
Jason M. Billse7770992021-05-14 13:24:33 -0700169size_t Dimm::memorySizeInKB(size_t value)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800170{
171 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
172 memorySizeInKB(value);
173}
174
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000175void Dimm::dimmDeviceLocator(const uint8_t bankLocatorPositionNum,
176 const uint8_t deviceLocatorPositionNum,
177 const uint8_t structLen, uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800178{
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000179 std::string deviceLocator =
180 positionToString(deviceLocatorPositionNum, structLen, dataIn);
181 std::string bankLocator =
182 positionToString(bankLocatorPositionNum, structLen, dataIn);
183
184 std::string result;
John Edward Broadbentefd41542022-12-13 16:39:18 -0800185 if (bankLocator.empty() || onlyDimmLocationCode)
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000186 {
John Edward Broadbentefd41542022-12-13 16:39:18 -0800187 result = deviceLocator;
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000188 }
189 else
190 {
John Edward Broadbentefd41542022-12-13 16:39:18 -0800191 result = bankLocator + " " + deviceLocator;
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000192 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800193
194 memoryDeviceLocator(result);
Jie Yang31720392021-07-22 21:45:45 -0700195
196 locationCode(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800197}
198
199std::string Dimm::memoryDeviceLocator(std::string value)
200{
201 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
202 memoryDeviceLocator(value);
203}
204
205void Dimm::dimmType(const uint8_t type)
206{
207 std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
208 if (it == dimmTypeTable.end())
209 {
210 memoryType(DeviceType::Unknown);
211 }
212 else
213 {
214 memoryType(it->second);
215 }
216}
217
218DeviceType Dimm::memoryType(DeviceType value)
219{
220 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
221 memoryType(value);
222}
223
224void Dimm::dimmTypeDetail(uint16_t detail)
225{
226 std::string result;
227 for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
228 {
229 if (detail & 0x01)
230 {
231 result += detailTable[index];
232 }
233 detail >>= 1;
234 }
235 memoryTypeDetail(result);
236}
237
238std::string Dimm::memoryTypeDetail(std::string value)
239{
240 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
241 memoryTypeDetail(value);
242}
243
244uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
245{
246 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
247 maxMemorySpeedInMhz(value);
248}
249
250void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800251 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800252{
253 std::string result = positionToString(positionNum, structLen, dataIn);
254
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530255 bool val = true;
256 if (result == "NO DIMM")
257 {
258 val = false;
259
260 // No dimm presence so making manufacturer value as "" (instead of
261 // NO DIMM - as there won't be any manufacturer for DIMM which is not
262 // present).
263 result = "";
264 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800265 manufacturer(result);
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530266 present(val);
Tim Leedc469c72021-07-20 10:55:58 +0800267 functional(val);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800268}
269
270std::string Dimm::manufacturer(std::string value)
271{
272 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
273 Asset::manufacturer(value);
274}
275
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530276bool Dimm::present(bool value)
277{
278 return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present(
279 value);
280}
281
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800282void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800283 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800284{
285 std::string result = positionToString(positionNum, structLen, dataIn);
286
287 serialNumber(result);
288}
289
290std::string Dimm::serialNumber(std::string value)
291{
292 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
293 Asset::serialNumber(value);
294}
295
296void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800297 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800298{
299 std::string result = positionToString(positionNum, structLen, dataIn);
300
kasunath634ec6a2022-07-25 15:34:17 -0700301 // Part number could contain spaces at the end. Eg: "abcd123 ". Since its
302 // unnecessary, we should remove them.
303 boost::algorithm::trim_right(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800304 partNumber(result);
305}
306
307std::string Dimm::partNumber(std::string value)
308{
309 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
310 Asset::partNumber(value);
311}
312
Jie Yang31720392021-07-22 21:45:45 -0700313std::string Dimm::locationCode(std::string value)
314{
315 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
316 LocationCode::locationCode(value);
317}
318
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800319uint8_t Dimm::memoryAttributes(uint8_t value)
320{
321 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
322 memoryAttributes(value);
323}
324
325uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
326{
327 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
328 memoryConfiguredSpeedInMhz(value);
329}
330
Tim Leedc469c72021-07-20 10:55:58 +0800331bool Dimm::functional(bool value)
332{
333 return sdbusplus::xyz::openbmc_project::State::Decorator::server::
334 OperationalStatus::functional(value);
335}
336
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800337} // namespace smbios
338} // namespace phosphor