blob: 869096956a738615e0e70a96fc2d6c2f206a4164 [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 }
Tom Tung39cc3682023-03-15 04:44:04 +080078 // If the size is 0, no memory device is installed in the socket.
79 const auto isDimmPresent = memoryInfo->size > 0;
80 present(isDimmPresent);
81 functional(isDimmPresent);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080082
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +000083 dimmDeviceLocator(memoryInfo->bankLocator, memoryInfo->deviceLocator,
84 memoryInfo->length, dataIn);
Cheng C Yang8c3fab62019-12-19 00:51:06 +080085 dimmType(memoryInfo->memoryType);
86 dimmTypeDetail(memoryInfo->typeDetail);
87 maxMemorySpeedInMhz(memoryInfo->speed);
88 dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
89 dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
90 dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
91 memoryAttributes(memoryInfo->attributes);
92 memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
93
kasunath2eca4fe2022-08-17 17:30:07 -070094 updateEccType(memoryInfo->phyArrayHandle);
95
Jie Yange7cf3192021-08-20 11:21:43 -070096 if (!motherboardPath.empty())
97 {
98 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
99 assocs.emplace_back("chassis", "memories", motherboardPath);
100 association::associations(assocs);
101 }
102
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800103 return;
104}
105
kasunath2eca4fe2022-08-17 17:30:07 -0700106void Dimm::updateEccType(uint16_t exPhyArrayHandle)
107{
108 uint8_t* dataIn = storage;
109
110 while (dataIn != nullptr)
111 {
112 dataIn = getSMBIOSTypePtr(dataIn, physicalMemoryArrayType);
113 if (dataIn == nullptr)
114 {
115 phosphor::logging::log<phosphor::logging::level::ERR>(
116 "Failed to get SMBIOS table type-16 data.");
117 return;
118 }
119
120 auto info = reinterpret_cast<struct PhysicalMemoryArrayInfo*>(dataIn);
121 if (info->handle == exPhyArrayHandle)
122 {
123 std::map<uint8_t, EccType>::const_iterator it =
124 dimmEccTypeMap.find(info->memoryErrorCorrection);
125 if (it == dimmEccTypeMap.end())
126 {
127 ecc(EccType::NoECC);
128 }
129 else
130 {
131 ecc(it->second);
132 }
133 return;
134 }
135
136 dataIn = smbiosNextPtr(dataIn);
137 }
138 phosphor::logging::log<phosphor::logging::level::ERR>(
139 "Failed find the corresponding SMBIOS table type-16 data for dimm:",
140 phosphor::logging::entry("DIMM:%d", dimmNum));
141}
142
143EccType Dimm::ecc(EccType value)
144{
145 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::ecc(
146 value);
147}
148
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800149uint16_t Dimm::memoryDataWidth(uint16_t value)
150{
151 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
152 memoryDataWidth(value);
153}
154
155static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
156static constexpr uint16_t dimmSizeUnit = 1024;
157void Dimm::dimmSize(const uint16_t size)
158{
Jason M. Billse7770992021-05-14 13:24:33 -0700159 size_t result = size & maxOldDimmSize;
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800160 if (0 == (size & baseNewVersionDimmSize))
161 {
162 result = result * dimmSizeUnit;
163 }
164 memorySizeInKB(result);
165}
166
Jason M. Billse7770992021-05-14 13:24:33 -0700167void Dimm::dimmSizeExt(size_t size)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800168{
169 size = size * dimmSizeUnit;
170 memorySizeInKB(size);
171}
172
Jason M. Billse7770992021-05-14 13:24:33 -0700173size_t Dimm::memorySizeInKB(size_t value)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800174{
175 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
176 memorySizeInKB(value);
177}
178
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000179void Dimm::dimmDeviceLocator(const uint8_t bankLocatorPositionNum,
180 const uint8_t deviceLocatorPositionNum,
181 const uint8_t structLen, uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800182{
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000183 std::string deviceLocator =
184 positionToString(deviceLocatorPositionNum, structLen, dataIn);
185 std::string bankLocator =
186 positionToString(bankLocatorPositionNum, structLen, dataIn);
187
188 std::string result;
John Edward Broadbentefd41542022-12-13 16:39:18 -0800189 if (bankLocator.empty() || onlyDimmLocationCode)
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000190 {
John Edward Broadbentefd41542022-12-13 16:39:18 -0800191 result = deviceLocator;
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000192 }
193 else
194 {
John Edward Broadbentefd41542022-12-13 16:39:18 -0800195 result = bankLocator + " " + deviceLocator;
Konstantin Aladyshev744b35a2022-11-02 08:34:27 +0000196 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800197
198 memoryDeviceLocator(result);
Jie Yang31720392021-07-22 21:45:45 -0700199
200 locationCode(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800201}
202
203std::string Dimm::memoryDeviceLocator(std::string value)
204{
205 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
206 memoryDeviceLocator(value);
207}
208
209void Dimm::dimmType(const uint8_t type)
210{
211 std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
212 if (it == dimmTypeTable.end())
213 {
214 memoryType(DeviceType::Unknown);
215 }
216 else
217 {
218 memoryType(it->second);
219 }
220}
221
222DeviceType Dimm::memoryType(DeviceType value)
223{
224 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
225 memoryType(value);
226}
227
228void Dimm::dimmTypeDetail(uint16_t detail)
229{
230 std::string result;
231 for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
232 {
233 if (detail & 0x01)
234 {
235 result += detailTable[index];
236 }
237 detail >>= 1;
238 }
239 memoryTypeDetail(result);
240}
241
242std::string Dimm::memoryTypeDetail(std::string value)
243{
244 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
245 memoryTypeDetail(value);
246}
247
248uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
249{
250 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
251 maxMemorySpeedInMhz(value);
252}
253
254void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800255 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800256{
257 std::string result = positionToString(positionNum, structLen, dataIn);
258
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530259 if (result == "NO DIMM")
260 {
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530261 // No dimm presence so making manufacturer value as "" (instead of
262 // NO DIMM - as there won't be any manufacturer for DIMM which is not
263 // present).
264 result = "";
265 }
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800266 manufacturer(result);
267}
268
269std::string Dimm::manufacturer(std::string value)
270{
271 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
272 Asset::manufacturer(value);
273}
274
Joshi-Mansi33c948a2021-03-20 00:58:50 +0530275bool Dimm::present(bool value)
276{
277 return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present(
278 value);
279}
280
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800281void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800282 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800283{
284 std::string result = positionToString(positionNum, structLen, dataIn);
285
286 serialNumber(result);
287}
288
289std::string Dimm::serialNumber(std::string value)
290{
291 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
292 Asset::serialNumber(value);
293}
294
295void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
Cheng C Yang2ca7a0f2019-12-19 10:46:42 +0800296 uint8_t* dataIn)
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800297{
298 std::string result = positionToString(positionNum, structLen, dataIn);
299
kasunath634ec6a2022-07-25 15:34:17 -0700300 // Part number could contain spaces at the end. Eg: "abcd123 ". Since its
301 // unnecessary, we should remove them.
302 boost::algorithm::trim_right(result);
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800303 partNumber(result);
304}
305
306std::string Dimm::partNumber(std::string value)
307{
308 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
309 Asset::partNumber(value);
310}
311
Jie Yang31720392021-07-22 21:45:45 -0700312std::string Dimm::locationCode(std::string value)
313{
314 return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
315 LocationCode::locationCode(value);
316}
317
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800318uint8_t Dimm::memoryAttributes(uint8_t value)
319{
320 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
321 memoryAttributes(value);
322}
323
324uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
325{
326 return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
327 memoryConfiguredSpeedInMhz(value);
328}
329
Tim Leedc469c72021-07-20 10:55:58 +0800330bool Dimm::functional(bool value)
331{
332 return sdbusplus::xyz::openbmc_project::State::Decorator::server::
333 OperationalStatus::functional(value);
334}
335
Cheng C Yang8c3fab62019-12-19 00:51:06 +0800336} // namespace smbios
337} // namespace phosphor