xref: /openbmc/smbios-mdr/src/dimm.cpp (revision a30229e1)
1 /*
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 
21 namespace phosphor
22 {
23 namespace smbios
24 {
25 
26 using DeviceType =
27     sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType;
28 
29 static constexpr uint16_t maxOldDimmSize = 0x7fff;
30 void Dimm::memoryInfoUpdate(void)
31 {
32     uint8_t* dataIn = storage;
33 
34     dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
35 
36     if (dataIn == nullptr)
37     {
38         return;
39     }
40     for (uint8_t index = 0; index < dimmNum; index++)
41     {
42         dataIn = smbiosNextPtr(dataIn);
43         if (dataIn == nullptr)
44         {
45             return;
46         }
47         dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
48         if (dataIn == nullptr)
49         {
50             return;
51         }
52     }
53 
54     auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);
55 
56     memoryDataWidth(memoryInfo->dataWidth);
57 
58     if (memoryInfo->size == maxOldDimmSize)
59     {
60         dimmSizeExt(memoryInfo->extendedSize);
61     }
62     else
63     {
64         dimmSize(memoryInfo->size);
65     }
66 
67     dimmDeviceLocator(memoryInfo->deviceLocator, memoryInfo->length, dataIn);
68     dimmType(memoryInfo->memoryType);
69     dimmTypeDetail(memoryInfo->typeDetail);
70     maxMemorySpeedInMhz(memoryInfo->speed);
71     dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn);
72     dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn);
73     dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn);
74     memoryAttributes(memoryInfo->attributes);
75     memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
76 
77     if (!motherboardPath.empty())
78     {
79         std::vector<std::tuple<std::string, std::string, std::string>> assocs;
80         assocs.emplace_back("chassis", "memories", motherboardPath);
81         association::associations(assocs);
82     }
83 
84     return;
85 }
86 
87 uint16_t Dimm::memoryDataWidth(uint16_t value)
88 {
89     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
90         memoryDataWidth(value);
91 }
92 
93 static constexpr uint16_t baseNewVersionDimmSize = 0x8000;
94 static constexpr uint16_t dimmSizeUnit = 1024;
95 void Dimm::dimmSize(const uint16_t size)
96 {
97     size_t result = size & maxOldDimmSize;
98     if (0 == (size & baseNewVersionDimmSize))
99     {
100         result = result * dimmSizeUnit;
101     }
102     memorySizeInKB(result);
103 }
104 
105 void Dimm::dimmSizeExt(size_t size)
106 {
107     size = size * dimmSizeUnit;
108     memorySizeInKB(size);
109 }
110 
111 size_t Dimm::memorySizeInKB(size_t value)
112 {
113     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
114         memorySizeInKB(value);
115 }
116 
117 void Dimm::dimmDeviceLocator(const uint8_t positionNum, const uint8_t structLen,
118                              uint8_t* dataIn)
119 {
120     std::string result = positionToString(positionNum, structLen, dataIn);
121 
122     memoryDeviceLocator(result);
123 
124     locationCode(result);
125 }
126 
127 std::string Dimm::memoryDeviceLocator(std::string value)
128 {
129     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
130         memoryDeviceLocator(value);
131 }
132 
133 void Dimm::dimmType(const uint8_t type)
134 {
135     std::map<uint8_t, DeviceType>::const_iterator it = dimmTypeTable.find(type);
136     if (it == dimmTypeTable.end())
137     {
138         memoryType(DeviceType::Unknown);
139     }
140     else
141     {
142         memoryType(it->second);
143     }
144 }
145 
146 DeviceType Dimm::memoryType(DeviceType value)
147 {
148     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
149         memoryType(value);
150 }
151 
152 void Dimm::dimmTypeDetail(uint16_t detail)
153 {
154     std::string result;
155     for (uint8_t index = 0; index < (8 * sizeof(detail)); index++)
156     {
157         if (detail & 0x01)
158         {
159             result += detailTable[index];
160         }
161         detail >>= 1;
162     }
163     memoryTypeDetail(result);
164 }
165 
166 std::string Dimm::memoryTypeDetail(std::string value)
167 {
168     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
169         memoryTypeDetail(value);
170 }
171 
172 uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value)
173 {
174     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
175         maxMemorySpeedInMhz(value);
176 }
177 
178 void Dimm::dimmManufacturer(const uint8_t positionNum, const uint8_t structLen,
179                             uint8_t* dataIn)
180 {
181     std::string result = positionToString(positionNum, structLen, dataIn);
182 
183     bool val = true;
184     if (result == "NO DIMM")
185     {
186         val = false;
187 
188         // No dimm presence so making manufacturer value as "" (instead of
189         // NO DIMM - as there won't be any manufacturer for DIMM which is not
190         // present).
191         result = "";
192     }
193     manufacturer(result);
194     present(val);
195     functional(val);
196 }
197 
198 std::string Dimm::manufacturer(std::string value)
199 {
200     return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
201         Asset::manufacturer(value);
202 }
203 
204 bool Dimm::present(bool value)
205 {
206     return sdbusplus::xyz::openbmc_project::Inventory::server::Item::present(
207         value);
208 }
209 
210 void Dimm::dimmSerialNum(const uint8_t positionNum, const uint8_t structLen,
211                          uint8_t* dataIn)
212 {
213     std::string result = positionToString(positionNum, structLen, dataIn);
214 
215     serialNumber(result);
216 }
217 
218 std::string Dimm::serialNumber(std::string value)
219 {
220     return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
221         Asset::serialNumber(value);
222 }
223 
224 void Dimm::dimmPartNum(const uint8_t positionNum, const uint8_t structLen,
225                        uint8_t* dataIn)
226 {
227     std::string result = positionToString(positionNum, structLen, dataIn);
228 
229     partNumber(result);
230 }
231 
232 std::string Dimm::partNumber(std::string value)
233 {
234     return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
235         Asset::partNumber(value);
236 }
237 
238 std::string Dimm::locationCode(std::string value)
239 {
240     return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
241         LocationCode::locationCode(value);
242 }
243 
244 uint8_t Dimm::memoryAttributes(uint8_t value)
245 {
246     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
247         memoryAttributes(value);
248 }
249 
250 uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value)
251 {
252     return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::
253         memoryConfiguredSpeedInMhz(value);
254 }
255 
256 bool Dimm::functional(bool value)
257 {
258     return sdbusplus::xyz::openbmc_project::State::Decorator::server::
259         OperationalStatus::functional(value);
260 }
261 
262 } // namespace smbios
263 } // namespace phosphor
264